Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of Nucleo_piano_final_clean by
Revision 9:9a36b66869fa, committed 2018-07-05
- Comitter:
- aknin001
- Date:
- Thu Jul 05 01:08:36 2018 +0000
- Parent:
- 8:781b03221397
- Commit message:
- final project finish tested and commented
Changed in this revision
main.cpp | Show annotated file Show diff for this revision Revisions of this file |
diff -r 781b03221397 -r 9a36b66869fa main.cpp --- a/main.cpp Wed Jul 04 21:47:32 2018 +0000 +++ b/main.cpp Thu Jul 05 01:08:36 2018 +0000 @@ -8,21 +8,25 @@ // Define Bus In for Buttons (Do, Re, Mi, Fa, Sol, La, Si, Do) BusIn Bus_In(PA_0, PA_1, PA_4, PB_0, PA_10, PB_3, PB_5, PB_4); - + // Define the PWM speaker PwmOut speaker(PB_10); - -//Define Bus In for Gamme Button -BusIn Bus_In_Gamme(PB_9); + +// Define Bus In for Octave Button +BusIn Bus_In_Octave(PB_9); + +// Define Serial +Serial pc(PA_2, PA_3); //Define variables for sound -struct NoteReference { - char name[4]; - int mask; - double frequency; - double add[4]; +struct NoteReference { // struct note reference + char name[4]; // note name + int mask; // note mask for pressed of not + double frequency; // note base frequency (octave 0) + double add[4]; // add value for octave balancing (from octave 0 to 3) }; - + +// NoteReference tab for 8 notes (1 octave) NoteReference noteReference[8] = { {"Do", 0x1, 262.0, {0.0, -1.0, -1.5, -3.0}}, {"Re", 0x2, 294.0, {0.0, -1.0, -1.0, -3.0 }}, {"Mi", 0x4, 330.0, {0.0, -1.0, -1.5, -3.0}}, @@ -32,152 +36,218 @@ {"Si", 0x40, 494.0, {0.0, 0.0, -1.0, -1.0}}, {"Do", 0x80, 523.0, {0.0, 0.0, 0.0, 0.0}} }; -volatile int stateButtons = 0; -volatile int stateButtonGamme = 0; -volatile int gamme = 0; - +volatile int stateButtons = 0; // State of notes buttons +volatile int stateButtonOctave = 0; // State of octave button +volatile int octave = 0; // octave value + //Define variable for display -char bufferOutput[30] = ""; - +char bufferOutput[30] = ""; // buffer for notes and octave + //Define variables for synchronization -Mutex lockBufferOutput; -Mutex lockGamme; - -void refresh_state_button() +Mutex lockBufferOutput; // Mutex for BufferOutput variable +Mutex lockOctave; // Mutex for octave variable + +/** + Function that refresh the value of + stateButtons depending on data input from + Bus_In. +**/ +void refresh_state_buttons() { stateButtons = Bus_In & Bus_In.mask(); // read the bus and mask out bits not being used } - + +/** + Function that output notes on the buzzer. +**/ void play_music(int notes, double frequency) { - speaker.period(1.0 / frequency); - while (stateButtons == notes) { - refresh_state_button(); + speaker.period(1.0 / frequency); // set the period to 1 / frequency of notes + while (stateButtons == notes) { // while button is pressed + refresh_state_buttons(); // refresh stateButtons } } -double generate_frequency(double frequency, int actualGamme) +/** + Function that generate a frequency depending on pressed notes + and actual octave. +**/ +double generate_frequency(double frequency, int actualOctave) { - frequency = 0.0; - lockBufferOutput.lock(); - strcpy(bufferOutput, ""); - for (int i = 0; i < 8; i++) { - if (!(stateButtons & noteReference[i].mask)) + frequency = 0.0; // init frequency to 0 + lockBufferOutput.lock(); // lock lockBufferOutput Mutex for writing new notes on bufferOutput variable + strcpy(bufferOutput, ""); // init bufferOuput to empty string + for (int i = 0; i < 8; i++) { // iterate on all element of noteReference tab + if (!(stateButtons & noteReference[i].mask)) // if note is pressed { - frequency += noteReference[i].frequency * pow(2.0, (double)actualGamme) + noteReference[i].add[actualGamme]; - strcat(bufferOutput, noteReference[i].name); - strcat(bufferOutput, " "); + // add note frequency to frequency (base frequency * 2^octave + add) + frequency += noteReference[i].frequency * pow(2.0, (double)actualOctave) + noteReference[i].add[actualOctave]; + strcat(bufferOutput, noteReference[i].name); // concatenate bufferOutput and new note name + strcat(bufferOutput, " "); // concatenate with space separator } } - lockBufferOutput.unlock(); - return (frequency); + lockBufferOutput.unlock(); // unlock bufferOutput at the end of the loop, end of writing + return (frequency); // return the frequency to play on buzzer } - -void check_buttons(double frequency, int actualGamme) + +/** + Check if buttons if pressed and play notes + otherwise set duty cycle to 0. +**/ +void check_buttons(double frequency, int actualOctave) { - if (stateButtons == 0xFF) + if (stateButtons == 0xFF) // if nothing pressed { - speaker = 0; - lockBufferOutput.lock(); - strcpy(bufferOutput, ""); - lockBufferOutput.unlock(); + speaker = 0; // duty cycle equal to 0 + lockBufferOutput.lock(); // lock BufferOutput Mutex for writing on bufferOutput variable + strcpy(bufferOutput, ""); // set bufferOutput to empty string + lockBufferOutput.unlock(); // unlock BufferOutput Mutex } - else { - lockGamme.lock(); - actualGamme = gamme; - lockGamme.unlock(); - frequency = generate_frequency(frequency, actualGamme); - speaker = 0.5; - play_music(stateButtons, frequency); + else { // if buttons pressed + lockOctave.lock(); // lock lockOctave Mutex for reading octave value + actualOctave = octave; // read octave value + lockOctave.unlock(); // unlock lockOctave Mutex + frequency = generate_frequency(frequency, actualOctave); // generate frequency depending on notes and octave + speaker = 0.5; // set duty cycle to 0.5 for volume + play_music(stateButtons, frequency); // play notes on buzzer } } +/** + Thread for playing notes. + check states of buttons notes and play music. +**/ void run_music() { - double frequency = 0.0; - int actualGamme = 0; + double frequency = 0.0; // double for total frequency + int actualOctave = 0; // int for actual octave - while (true) + while (true) // Infinte loop to catch buttons notes events { - refresh_state_button(); - check_buttons(frequency, actualGamme); - Thread::wait(100); + refresh_state_buttons(); // refresh state_buttons + check_buttons(frequency, actualOctave); // check if buttons are pressed and play music + Thread::wait(100); // Thread wait 100 for scheduling } } +/** + Function that will display notes and gammes on LCD screen and + PC device. + Only called when a change on BufferOutput occurs. +**/ +void refresh_display_notes(char *old_buffer) +{ + lcd.cls(); // clear LCD screen + lockOctave.lock(); // lock lockOctave Mutex for reading octave variable + if (strcmp(bufferOutput, "")) // if buffer not empty + { + lcd.printf("%s- O[%d]", bufferOutput, octave); // display notes and actual octave on LCD screen + pc.printf("Play notes: %s with octave %d\n", bufferOutput, octave); // display notes and actual octave on PC device + } + else + { + lcd.printf("Octave = %d", octave); // only display octave on screen if no button pressed + pc.printf("Release notes\n"); // display release message on PC device + } + lockOctave.unlock(); // unlock lockOctave + strcpy(old_buffer, bufferOutput); // save value bufferOutput in old_buffer +} + +/** + Function that will display the octave on screen + if a change in octave occurs. +**/ +int refresh_display_octave(int old_octave) +{ + lockOctave.lock(); // lock lockOctave for reading octave variable + if (old_octave != octave) // if change occurs + { + lcd.cls(); // clear screen + lcd.printf("Octave = %d", octave); // display new octave on LCD screen + pc.printf("[INFO] - Change octave %d to octave %d\n", old_octave, octave); // display new octave on PC device + old_octave = octave; // save the new value to old_octave + } + lockOctave.unlock(); // Unlock lockOctave + return old_octave; // return old_octave +} + +/** + Thread display function that output + notes and octaves on the LCD screen + and the PC device by Serial. +**/ void run_display() { - char old_buffer[30] = ""; - int old_gamme = 0; + char old_buffer[30] = ""; // buffer of old value BufferOutput variable, init to empty string by default + int old_octave = 0; // value for old octave variable, init to zero by default - lockBufferOutput.lock(); - lockGamme.lock(); - lcd.printf("Gamme = %d", gamme); - lockGamme.unlock(); - lockBufferOutput.unlock(); - while(true) + lockOctave.lock(); // Lock lockOctave Mutex for reading octave variable + lcd.printf("Octave = %d", octave); // Display default octave on screen until event occurs + lockOctave.unlock(); // Unlock lockOctave Mutex + while(true) // Infinite loop to run display { - lockBufferOutput.lock(); - if (strcmp(old_buffer, bufferOutput)) - { - lcd.cls(); - lockGamme.lock(); - if (strcmp(bufferOutput, "")) - lcd.printf("%s- g[%d]", bufferOutput, gamme); - else - lcd.printf("Gamme = %d", gamme); - lockGamme.unlock(); - strcpy(old_buffer, bufferOutput); - } - else { - lockGamme.lock(); - if (old_gamme != gamme) - { - lcd.cls(); - lcd.printf("Gamme = %d", gamme); - old_gamme = gamme; - } - lockGamme.unlock(); - } - lockBufferOutput.unlock(); - Thread::wait(100); + lockBufferOutput.lock(); // Lock lockBufferOutput Mutex for reading BufferOutput + if (strcmp(old_buffer, bufferOutput)) // if bufferOutput has change + refresh_display_notes(old_buffer); // output notes + else + old_octave = refresh_display_octave(old_octave); // else output gamme if change + lockBufferOutput.unlock(); // Unlock lockBufferOutput Mutex + Thread::wait(100); // Thread wait 100 for synchronization } } - -void check_state_button_gamme() + +/** + Function that refresh the value of + stateButtonOctave variable based on the + input data from Bus_In_Octave. +**/ +void check_state_button_octave() { - stateButtonGamme = Bus_In_Gamme & Bus_In_Gamme.mask(); + stateButtonOctave = Bus_In_Octave & Bus_In_Octave.mask(); } -void run_gamme() +/** + Thread for Octave. + + Catch octave button state and increment + the octave value if button has been pressed. +**/ +void run_octave() { - while(true) + while(true) // Infinite loop for octave Thread { - check_state_button_gamme(); - if (stateButtonGamme == 0x0) + check_state_button_octave(); // refresh state_button_octave + if (stateButtonOctave == 0x0) // if button is pressed { - lockGamme.lock(); - gamme = (gamme == 3) ? 0 : gamme + 1; - lockGamme.unlock(); - while (stateButtonGamme == 0x0) - check_state_button_gamme(); + lockOctave.lock(); // lock lockOctave Mutex, enter in critical section + octave = (octave == 3) ? 0 : octave + 1; // increment octave or set to 0 + lockOctave.unlock(); // unlock lockOctave Mutex, end of critical section + while (stateButtonOctave == 0x0) // continue check button state until it is unpressed + check_state_button_octave(); // refresh state_button_octave } - Thread::wait(100); + Thread::wait(100); // Thread wait 100 for scheduling } } - + +/** + Main function Piano Project. + + Launch 3 threads for playing music, display notes + and octaves. +**/ int main() { - Thread music_thread; - Thread display_thread; - Thread gamme_thread; + Thread music_thread; // Thread for playing music + Thread display_thread; // Thread for display notes and octave + Thread octave_thread; // Thread for octave - lcd.printf("CS435 : Piano Project\n"); + lcd.printf("CS435\nPiano Project"); // Print welcome string on LCD screen wait(3); - lcd.cls(); + lcd.cls(); // Clear the screen - music_thread.start(run_music); - display_thread.start(run_display); - gamme_thread.start(run_gamme); - while(1); + music_thread.start(run_music); // Start music thread + display_thread.start(run_display); // Start display thread + octave_thread.start(run_octave); // Start octave thread + + while(1); // Infinite loop for main thread } \ No newline at end of file