Add Serial UART communication to display action messages (Play notes X, release notes, change gamme X to gamme Y)

Dependencies:   TextLCD

Fork of Nucleo_piano_final_clean by karine aknin

main.cpp

Committer:
Aliened
Date:
2018-07-04
Revision:
9:653ee515b0ad
Parent:
8:781b03221397

File content as of revision 9:653ee515b0ad:

#include "mbed.h"
#include "TextLCD.h"
#include <string.h>
#include <math.h>
 
// Define screen
TextLCD lcd(PA_8, PA_9, PC_7, PB_6, PA_7, PA_6, PA_5); // RS, RW, E, D4-D7
 
// 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 Serial
Serial pc(PA_2, PA_3);
   
//Define variables for sound
struct  NoteReference {
    char    name[4];
    int     mask;
    double  frequency;
    double  add[4];
    };
    
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}},
                                        {"Fa", 0x8, 349.0, {0.0, 0.5, -1.0, 2.0}},
                                        {"Sol", 0x10, 392.0, {0.0, 0.0, 0.0, 0.0}},
                                        {"La", 0x20, 440.0, {0.0, 0.0, 0.0, 0.0}},
                                        {"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;

//Define variable for display
char     bufferOutput[30] = "";

//Define variables for synchronization
Mutex   lockBufferOutput;
Mutex   lockGamme;
 
void    refresh_state_button()
{
   stateButtons = Bus_In & Bus_In.mask(); // read the bus and mask out bits not being used
}
 
void        play_music(int notes, double frequency)
{
   speaker.period(1.0 / frequency);
   while (stateButtons == notes) {
     refresh_state_button();
   }
}

double      generate_frequency(double frequency, int actualGamme)
{
    frequency = 0.0;
    lockBufferOutput.lock();
    strcpy(bufferOutput, "");
    for (int i = 0; i < 8; i++) {
        if (!(stateButtons & noteReference[i].mask))
        {
            frequency += noteReference[i].frequency * pow(2.0, (double)actualGamme) + noteReference[i].add[actualGamme];
            strcat(bufferOutput, noteReference[i].name);
            strcat(bufferOutput, " ");
        }
    }
    lockBufferOutput.unlock();
    return (frequency);
}
 
void        check_buttons(double frequency, int actualGamme)
{
    if (stateButtons == 0xFF)
    {
        speaker = 0;
        lockBufferOutput.lock();
        strcpy(bufferOutput, "");
        lockBufferOutput.unlock();
    }
    else {
        lockGamme.lock();
        actualGamme = gamme;
        lockGamme.unlock();
        frequency = generate_frequency(frequency, actualGamme);
        speaker = 0.5;
        play_music(stateButtons, frequency);
    }
}

void    run_music()
{
    double  frequency = 0.0;
    int     actualGamme = 0;
    
    while (true)
    {
        refresh_state_button();
        check_buttons(frequency, actualGamme);
        Thread::wait(100);
    }
}

void    run_display()
{
    char    old_buffer[30] = "";
    int     old_gamme = 0;
    
    lockBufferOutput.lock();
    lockGamme.lock();
    lcd.printf("Gamme = %d", gamme);
    lockGamme.unlock();
    lockBufferOutput.unlock();
    while(true)
    {
        lockBufferOutput.lock();
        if (strcmp(old_buffer, bufferOutput))
        {
            lcd.cls();
            lockGamme.lock();
            if (strcmp(bufferOutput, ""))
            {
                lcd.printf("%s- g[%d]", bufferOutput, gamme);
                pc.printf("Play notes: %s with gamme %d\n", bufferOutput, gamme); 
            }
            else {
                lcd.printf("Gamme = %d", gamme);
                pc.printf("Release notes\n"); 
            }
            lockGamme.unlock();
            strcpy(old_buffer, bufferOutput);
        }
        else {
            lockGamme.lock();
            if (old_gamme != gamme)
            {
                lcd.cls();
                lcd.printf("Gamme = %d", gamme);
                pc.printf("Change gamme %d to gamme %d\n", old_gamme, gamme); 
                old_gamme = gamme;
            }
            lockGamme.unlock();
        }
        lockBufferOutput.unlock();
        Thread::wait(100);
    }
}

void     check_state_button_gamme()
{
    stateButtonGamme = Bus_In_Gamme & Bus_In_Gamme.mask();
}

void    run_gamme()
{
    while(true)
    {
        check_state_button_gamme();
        if (stateButtonGamme == 0x0)
        {
            lockGamme.lock();
            gamme = (gamme == 3) ? 0 : gamme + 1;
            lockGamme.unlock();
            while (stateButtonGamme == 0x0)
                check_state_button_gamme();
        }
        Thread::wait(100);
    }
}

int main()
{
    Thread  music_thread;
    Thread  display_thread;
    Thread  gamme_thread;
    
    lcd.printf("CS435 : Piano Project\n");
    wait(3);
    lcd.cls();
 
    music_thread.start(run_music);
    display_thread.start(run_display);
    gamme_thread.start(run_gamme);
    while(1);
}