Amaldi / Mbed 2 deprecated Amaldi_16_Exercise_Game_rev3

Dependencies:   mbed

Game.cpp

Committer:
pinofal
Date:
2018-12-04
Revision:
2:1bdcc88f5501
Child:
3:58b0cfe9cc3a

File content as of revision 2:1bdcc88f5501:

#include "mbed.h"
#include "stdlib.h"
#include "SampledSoundBadScore.h"
#include "SampledSoundGoodScore.h"

// numero di Step in cui è suddiviso il gioco
#define GAMESTEPNUMBER 4

// tempo di base tra due step di gioco in [msec]
#define TIMEBETWEEN 5000

// genera un oggetto serial collegato al PC
Serial pc(USBTX, USBRX);

DigitalOut myLed(LED2);
DigitalIn myButton(USER_BUTTON);

// moltiplicatore del tempo in millisecondi
double nMultiplier = 50.0;  
Timer myTimer;

// Tempo a disposizione del giocatore per colpire il piezo dopo l'accensiond del LED
int32_t nDelay = 500; // tempo in [msec]
float fDelay = 500.0; // tempo in [msec]

// tempi  misurati con il timer
int32_t nStartTimeGame, nElapsedTimeGame, nCurrentTimeGame;

// seme per la generazione di numeri casuali
unsigned int nSeed;

// numero di fade del gioco
int nStepIndex;

// tempo in [msec] di ciascuna fase. Per la fase numero nStepIndex, il LED viene acceso per il tempo naStepDuration[nStepIndex] e entro tale tempo fovrà arrivare la risposta del giocatore
const int naStepDuration[GAMESTEPNUMBER]={1500, 1000, 500, 250}; // tempi in [msec]

// array contenente i punteggi di ciascuno step
int naStepScore[GAMESTEPNUMBER];

// calcola lo score su ogni singolo Step
double fScore;


// indice per la generazione del messaggio di Good Score
int nGoodScoreMsgIndex;

// amplificazione, frequenza e periodo del segnale di Good Score
double fAmpGoodScoreSound;
double fFreqGoodScoreSound;
double fDeltaTGoodScoreSound;
// indice per la generazione del messaggio di Bad Score
int nBadScoreMsgIndex;

// amplificazione, frequenza e periodo del segnale di Bad Score
double fAmpBadScoreSound;
double fFreqBadScoreSound;
double fDeltaTBadScoreSound;


// pulsante su cui bisogna colpire
DigitalIn InPiezo(PA_0);
// output analogico per i messaggi audio
AnalogOut OutWave(PA_4);

/****************************************/
/* Gnerazione AudioMesaggio Good Result */
/****************************************/
void GoodScoreMessage(void)
{
    //++++++++++++ INIZIO generazione messaggio di GoodScore +++++++++++++++++ 
    fAmpGoodScoreSound = 1.0;  // fissa l'amplificazione per il messaggio di GoodScore. Valori da 0[min] a 1[max] 
    fFreqGoodScoreSound=nSamplePerSecGoodScore/nUnderSampleFactorGoodScore;// campioni per secondo del GoodScore message da generare = nSamplePerSec/nUnderSampleFactor
    fDeltaTGoodScoreSound = (1.0/fFreqGoodScoreSound);  // fFreq dipende dal periodo di campionamento e dal fattore di sottocampionamento
   
    
    for(nGoodScoreMsgIndex=0; nGoodScoreMsgIndex < nSampleNumGoodScore; nGoodScoreMsgIndex++)
    {
        // mette in output un campione della forma d'onda del GoodScore message  moltiplicato per l'amplificazione fAmp
        OutWave.write_u16(naInputSoundWaveGoodScore[nGoodScoreMsgIndex]*fAmpGoodScoreSound);
        
        // tra un campione e l'altro attendi un periodo pari al periodo di campionamento
        //wait(fDeltaTGoodScoreSound);
        wait_us(30);
    }
    //++++++++++++ FINE generazione messaggio di GoodScore +++++++++++++++++
}

/****************************************/
/* Gnerazione AudioMesaggio Good Result */
/****************************************/
void BadScoreMessage(void)
{
    //++++++++++++ INIZIO generazione messaggio di BadScore +++++++++++++++++ 
    fAmpBadScoreSound = 1.0;  // fissa l'amplificazione per il messaggio di BadScore. Valori da 0[min] a 1[max] 
    fFreqBadScoreSound=nSamplePerSecBadScore/nUnderSampleFactorBadScore;// campioni per secondo del BadScore message da generare = nSamplePerSec/nUnderSampleFactor
    fDeltaTBadScoreSound = (1.0/fFreqBadScoreSound);  // fFreq dipende dal periodo di campionamento e dal fattore di sottocampionamento
   
    
    for(nBadScoreMsgIndex=0; nBadScoreMsgIndex < nSampleNumBadScore; nBadScoreMsgIndex++)
    {
        // mette in output un campione della forma d'onda del BadScore message  moltiplicato per l'amplificazione fAmp
        OutWave.write_u16(naInputSoundWaveBadScore[nBadScoreMsgIndex]*fAmpBadScoreSound);
        
        // tra un campione e l'altro attendi un periodo pari al periodo di campionamento
        //wait(fDeltaTBadScoreSound);
        wait_us(30);
    }
    //++++++++++++ FINE generazione messaggio di BadScore +++++++++++++++++
}

/********/
/* MAIN */
/********/
int main() 
{
    // velocità di comunicazione sulla seriale con PC
    pc.baud(921600);
    
    // messaggio di benvenuto
    pc.printf("\r\nHallo Amaldi Students - Exercise 16 \r\n");
    pc.printf("\r\n*** Let's Play ***\r\n");
    
    
    // inizialmente spegne LED
    myLed=0;
    
    // pc.printf("RANDMAX= %d\r\n", RAND_MAX); // scopi diagnostici
        
    while(true) 
    {
        //++++++  INIZIO Attendi pressione USER_BUTTON per Start Game +++++++
        pc.printf("\r\n*** PRESS Blue Button to START ***\r\n");
        while(myButton ==1)
        {
            //myLed = 1;
        }
        if(myButton ==0)
        {
            while(myButton ==0){};
            //myLed = 0;
            //BadScoreMessage();
            //GoodScoreMessage();
        }
        //++++++  FINE Attendi pressione USER_BUTTON per Start Game +++++++
        
        //++++++ INIZIO degli step del gioco +++++++++++++++++++++
        myTimer.start(); // avvia il timer
        for(nStepIndex =0; nStepIndex < GAMESTEPNUMBER; nStepIndex++)
        {
            pc.printf("\r\nINIZIO FASE %d\r\n",nStepIndex); // scopi diagnostici
            
            //rand() fissa sempre la stessa sequenza di numeri patendo da 1, 
            //srand(seed) fissa il numero di partenza, seed, ma la sequenza è sempre la stessa
            // per generare una sequenza diversa partendo da un numero diverso il seed lo imposto leggendo l'orologio di sistema (p.e. timer)
            // RAND_MAX = 2147483647
            nSeed = unsigned(myTimer.read_ms()% RAND_MAX); // resto della divisione timer_read_us() / RAND_MAX
            srand(nSeed);
            // calcola il tempo da aggiungere come parte variabile al tempo tra uno step e l'altro
            fDelay = (nMultiplier * (float(rand()) / RAND_MAX));
            // pc.printf("\r\ndelay float = %f\r\n", fDelay); // scopi diagnostici
            nDelay = int(fDelay);
            pc.printf("delay [msec] = %d\r\n", nDelay); // scopi diagnostici
            
            // se il ritardo è maggiore di 500, dividilo per 3 fino a quando non diventa inferiore a 5000
            while(nDelay > 500)
            {
                nDelay /= 3;
            }
            
            // se il ritardo è minore di 100, moltiplicalo per 2 fino a quando non diventa maggiore di 100    
            while(nDelay < 50)
            {
                nDelay *= 2;    
            }
            // tra uno step e l'altro attendi (TIMEBETWEEN + nDelay) [msec]. In questo modo il giocatore non può memorizzare i tempi di risposta
            wait_ms(TIMEBETWEEN+nDelay);
            pc.printf("Tempo tra due step [ms] = %d\r\n", (TIMEBETWEEN+nDelay)); // scopi diagnostici
            
            // Accendi il LED per un tempo pari a una parte fissa in naStepDuration[nStepIndex] e una parte random pari a nDelay
            myLed=1; // Accendi LED
            nStartTimeGame = myTimer.read_ms();
            nElapsedTimeGame=0; // inizializza tempo trascorso
            // attendi fino alla pressione del pulsante/piezo oppure al timeout. Il timeout è fissato nell'array naStepDuration[]. mYButton diventa '0' alla pressione
            while( (nElapsedTimeGame < naStepDuration[nStepIndex]) && (myButton == 1))
            {
                // misura il tempo trascorso da StartTimeGame
                nCurrentTimeGame = myTimer.read_ms();
                nElapsedTimeGame= nCurrentTimeGame-nStartTimeGame;
            }
            myLed=0; // Spegni LED
            // memorizza lo score guadagnato nello Step
            naStepScore[nStepIndex] = nElapsedTimeGame;
            
            pc.printf("StepDuration= %d; Elapsed= %d\r\n", naStepDuration[nStepIndex], nElapsedTimeGame); //scopi diagnostici
            
            // calcola lo score in percentuale della durata step. fScore = (durata dello step-tempo trascorso)/ durata dello step.
            fScore = ((float)(naStepDuration[nStepIndex] - naStepScore[nStepIndex])/(float)naStepDuration[nStepIndex])*100.0;
            pc.printf("Score [%%] %.2f \r\n",fScore); //scopi diagnostici
              
            if(fScore <=0) // il tempo di risposta è stato superiore alla durata
            {
                // accendi LED RED relativo alla fase in cui ci si trova
                pc.printf("BAD :(  :(  :( \r\n"); // il giocatore ha risposto dopo la scadenza del timer
                BadScoreMessage();
            }
            if((fScore > 0) && (fScore <= 50))
            {
                // accendi LED YELLOW relativo alla fase in cui ci si trova
                pc.printf("SO-SO !!! \r\n"); // il giocatore ha risposto in un tempo intermedio
                BadScoreMessage();
            }
            if(fScore > 50)
            {
                // accendi LED VERDE relativo alla fase in cui ci si trova
                pc.printf("GOOD :)  :)  :) \r\n"); // il giocatore ha risposto prima della scadenza del timer
                GoodScoreMessage();
            }
            
        }
       
    }            
}