
//Definimos el valor y sonido de la nota. 
#define NOTE_D3  147
#define NOTE_DS3 156
#define NOTE_E3  165
#define NOTE_F3  175

#define NOTE_G3  196
#define NOTE_GS3 208
#define NOTE_A3  220
#define NOTE_AS3 233
#define NOTE_B3  247
#define NOTE_C4  262
#define NOTE_CS4 277
#define NOTE_D4  294
#define NOTE_DS4 311

#define NOTE_F4  349
#define NOTE_FS4 370
#define NOTE_G4  392
#define NOTE_GS4 415
#define NOTE_A4  440
#define NOTE_AS4 466
#define NOTE_B4  494

#define NOTE_C5  523
#define NOTE_CS5 554
#define NOTE_D5  587
#define NOTE_DS5 622
#define NOTE_E5  659
#define NOTE_F5  698
#define NOTE_G5  784
#define NOTE_AS5 932

#define NOTE_E6  1319
#define NOTE_G6  1568
#define NOTE_A6  1760
#define NOTE_AS6 1865
#define NOTE_B6  1976
#define NOTE_C7  2093
#define NOTE_D7  2349
#define NOTE_E7  2637
#define NOTE_F7  2794
#define NOTE_G7  3136
#define NOTE_A7  3520

#define REST 0


//Incluimos libreria de la lcd
#include <LiquidCrystal.h>
LiquidCrystal lcd(12,11,2,3,4,5);

//Definimos pines de cada componente.
int led = 7;
int buz = 8;
const int b1 = 9;
const int b2 = 10;

//Inicializamos variables para guardar estados de los botones.
int e1 = 0;  
int e2 = 0;

int c_anterior = 0;
int anterior = 0;
///////////////////////////////////////////////////////////

//Melodia de las canciones usando notas definidas. 
//------------------Cancion Supero Mario------------------//
int melodys[] = {
  NOTE_E7, NOTE_E7, 0, NOTE_E7,
  0, NOTE_C7, NOTE_E7, 0,
  NOTE_G7, 0, 0,  0,
  NOTE_G6, 0, 0, 0,
 
  NOTE_C7, 0, 0, NOTE_G6,
  0, 0, NOTE_E6, 0,
  0, NOTE_A6, 0, NOTE_B6,
  0, NOTE_AS6, NOTE_A6, 0,
 
  NOTE_G6, NOTE_E7, NOTE_G7,
  NOTE_A7, 0, NOTE_F7, NOTE_G7,
  0, NOTE_E7, 0, NOTE_C7,
  NOTE_D7, NOTE_B6, 0, 0,
 
  NOTE_C7, 0, 0, NOTE_G6,
  0, 0, NOTE_E6, 0,
  0, NOTE_A6, 0, NOTE_B6,
  0, NOTE_AS6, NOTE_A6, 0,
 
  NOTE_G6, NOTE_E7, NOTE_G7,
  NOTE_A7, 0, NOTE_F7, NOTE_G7,
  0, NOTE_E7, 0, NOTE_C7,
  NOTE_D7, NOTE_B6, 0, 0
};
//Mario main them tempo
int tempos[] = {
  12, 12, 12, 12,
  12, 12, 12, 12,
  12, 12, 12, 12,
  12, 12, 12, 12,
 
  12, 12, 12, 12,
  12, 12, 12, 12,
  12, 12, 12, 12,
  12, 12, 12, 12,
 
  9, 9, 9,
  12, 12, 12, 12,
  12, 12, 12, 12,
  12, 12, 12, 12,
 
  12, 12, 12, 12,
  12, 12, 12, 12,
  12, 12, 12, 12,
  12, 12, 12, 12,
 
  9, 9, 9,
  12, 12, 12, 12,
  12, 12, 12, 12,
  12, 12, 12, 12,
  
  
};
//Underworld melody
int underworld_melodys[] = {
  NOTE_C4, NOTE_C5, NOTE_A3, NOTE_A4,
  NOTE_AS3, NOTE_AS4, 0,
  0,
  NOTE_C4, NOTE_C5, NOTE_A3, NOTE_A4,
  NOTE_AS3, NOTE_AS4, 0,
  0,
  NOTE_F3, NOTE_F4, NOTE_D3, NOTE_D4,
  NOTE_DS3, NOTE_DS4, 0,
  0,
  NOTE_F3, NOTE_F4, NOTE_D3, NOTE_D4,
  NOTE_DS3, NOTE_DS4, 0,
  0, NOTE_DS4, NOTE_CS4, NOTE_D4,
  NOTE_CS4, NOTE_DS4,
  NOTE_DS4, NOTE_GS3,
  NOTE_G3, NOTE_CS4,
  NOTE_C4, NOTE_FS4, NOTE_F4, NOTE_E3, NOTE_AS4, NOTE_A4,
  NOTE_GS4, NOTE_DS4, NOTE_B3,
  NOTE_AS3, NOTE_A3, NOTE_GS3,
  0, 0, 0
};
//Underwolrd tempo
int underworld_tempos[] = {
  12, 12, 12, 12,
  12, 12, 6,
  3,
  12, 12, 12, 12,
  12, 12, 6,
  3,
  12, 12, 12, 12,
  12, 12, 6,
  3,
  12, 12, 12, 12,
  12, 12, 6,
  6, 18, 18, 18,
  6, 6,
  6, 6,
  6, 6,
  18, 18, 18, 18, 18, 18,
  10, 10, 10,
  10, 10, 10,
  3, 3, 3
};

  int song = 0;


//--------------------------------------------------------//
// Melody 1: Star Wars Imperial March

int melody1[] = {NOTE_A4, REST,  NOTE_A4, REST,  NOTE_A4,REST, NOTE_F4, REST, NOTE_C5, REST, NOTE_A4, REST,  NOTE_F4, REST, NOTE_C5, 
REST, NOTE_A4, REST, NOTE_E5, REST, NOTE_E5,REST,  NOTE_E5,REST, NOTE_F5, REST, NOTE_C5, REST,  NOTE_G5,REST,  NOTE_F5, REST, NOTE_C5, REST, NOTE_A4, REST};

int beats1[]  = {50, 20, 50, 20, 50, 20, 40, 5, 20, 5,  60, 10, 40, 5,
20, 5, 60, 80, 50, 20, 50, 20, 50, 20, 40, 5, 20, 5,  60, 10, 40, 5,  20, 
5, 60, 40};

// Melody 2: Star Wars Theme
int melody2[] = {NOTE_F4,  NOTE_F4, NOTE_F4,  NOTE_AS4,   NOTE_F5,  NOTE_DS5, NOTE_D5,  NOTE_C5, NOTE_AS5, NOTE_F5, NOTE_DS5, 
NOTE_D5,  NOTE_C5,NOTE_AS5, NOTE_F5,NOTE_DS5, NOTE_D5, NOTE_DS5,   NOTE_C5};
int beats2[]  = {21,  21, 21,  128,  128,   21,  21, 21, 128, 64,  21, 
21,  21, 128, 64, 21, 21,  21, 128 };

int MAX_COUNT = sizeof(melody1) / 2;
long tempo = 10000;
int pause = 1000;

int toneM = 0;
int beat = 0;
long duration  = 0;
int potVal = 0;


void setup()
{
  //Serial.begin(9600);
  lcd.begin(16,2); //Inicializamos la lcd para
             //poder mostrar los mensajes. 
  
  //Definimos las salidas y entradas
  pinMode(buz,OUTPUT);
  pinMode(b1,INPUT_PULLUP);
  pinMode(b2,INPUT_PULLUP);
  pinMode(led, OUTPUT);

}

void loop()
{ 
  e1 = digitalRead(b1); //guardamos valores de botones en estado diferentes 
  e2 = digitalRead(b2); 
  
  //Cada que pulsemos el boton mostrara el mensaje
  //en la parte de arriba de la lcd. Lee el estado 
  //del boton. 
  if(e1 != anterior){
    if(e1 == LOW){  
        lcd.clear(); //Limpia la pantalla de la lcd.
        lcd.setCursor(1,0); //Mostrara el mensaje en la 
                  //parte superior de la lcd.       
      lcd.print("Super Mario");                   
    } 
    
    
    

  }  
 
  anterior = e1; //Guarda el estado final del boton 1. 
  
  if(e1 != c_anterior ){
    if(e1 == LOW){
        sing(1);
      //sing(1);
      sing(2);
    }  
    

  }
  
  c_anterior = e1;
  
  

  //Lee el estado del boton y cuando se apache 
  //se encienda mostrando el mensaje.
  if(e2 != anterior ){
    if(e2 == LOW){
      
        lcd.clear(); //Limpia la pantalla de la lcd. 
        lcd.setCursor(0,1); //Mostrara el mensaje en la 
                  //parte inferior de la lcd.
      lcd.print("Star Wars");         
    }
    

    
  }
  anterior = e2; //Guarda el estado final del boton 2. 
  
        
  if(e2 != c_anterior ){
    if(e2  == LOW){
      
        // Melody1, leera los valores del arreglo de la melodia para poder imprimirlo. 
        for (int i=0; i<MAX_COUNT; i++) {
        toneM = melody1[i];
        beat = beats1[i];
        duration = beat * tempo;
        playTone(); //Funcion echa para encender el led conforme a la musica. 
        delayMicroseconds(pause);
      }
      
        // Melody2
        MAX_COUNT = sizeof(melody2) / 2;
        for (int i = 0; i < MAX_COUNT; i++) {
        toneM = melody2[i];
        beat = beats2[i];
        duration = beat * tempo;
        playTone();
        delayMicroseconds(pause);
        }
      
    }
    
 }
    c_anterior = e2;
  
}
  
//Codigo para la canción de mario. 
void sing(int s) {
  // iterate over the notes of the melody:
  song = s;
  if (song == 2) {
    Serial.println(" 'Underworld Theme'");
    int size = sizeof(underworld_melodys) / sizeof(int);
    for (int thisNotes = 0; thisNotes < size; thisNotes++) {
 
    // calcula la duracion de la nota
      int noteDurations = 1000 / underworld_tempos[thisNotes];
 
      tone(buz, underworld_melodys[thisNotes], noteDurations);
 
      // Se define la duracion dependiendo la nota que suena 
      int pauseBetweenNotess = noteDurations * 1.30;
      delay(pauseBetweenNotess);
 
      // Determina el final de la nota o melodia 
      tone(buz, 0, noteDurations);
 
    }
 
  } else {
 
    Serial.println(" 'Mario Theme'");
    int size = sizeof(melodys) / sizeof(int);
    for (int thisNotes = 0; thisNotes < size; thisNotes++) {
 
      // calcula la duracion de la nota
      int noteDurations = 1000 / tempos[thisNotes];
 
      tone(buz, melodys[thisNotes], noteDurations);
 
      // Se define la duracion dependiendo la nota que suena 
      int pauseBetweenNotess = noteDurations * 1.30;
      delay(pauseBetweenNotess);
 
      // Determina el final de la nota o melodia 
      //tone(buz, 0, noteDurations);
 
    }
  }
}


int rest_count = 50;
int rest_count1 = 56;
int rest_count2 = 56;

//Creamos funcion para encender el led 
void playTone(){
      long elapsed_time = 0;
      
      if (toneM > 0) {
      //El led se enciende  
      digitalWrite(led,HIGH);
      
          //El le se va encender solo si el buzzer genera sonido. 
          while (elapsed_time < duration){
          digitalWrite(buz,HIGH);
          delayMicroseconds(toneM / 2);
          digitalWrite(buz, LOW);
          delayMicroseconds(toneM / 2);
          elapsed_time += (toneM);
          }
      digitalWrite(led,LOW);
      }
      
      else {
          for (int g = 0; g < rest_count; g++) {
          delayMicroseconds(duration);
          }
     }

}
