#include <LiquidCrystal_I2C.h>
#include <RotaryEncoder.h>
#define MELODIES 2
#define BUZZER_PIN 8
#define LCD_ADDRESS 0x27
LiquidCrystal_I2C lcd(LCD_ADDRESS, 16, 2);
RotaryEncoder encoder(2, 3);
int currentMelody = 0;
int playbackSpeed = 100;
void setup() {
// Inicializar el visualizador LCD
lcd.init();
lcd.backlight();
// Inicializar el codificador rotativo
encoder.begin();
// Configurar el pin del zumbador
pinMode(BUZZER_PIN, OUTPUT);
// Configurar el botón del codificador rotativo
pinMode(4, INPUT_PULLUP);
}
// Función para mostrar el nombre de la melodía y el número de notas en el visualizador LCD
void showMelodyInfo(const melody& m, int speed) {
lcd.setCursor(0, 0);
lcd.print(m.name);
lcd.setCursor(0, 1);
lcd.print(m.notes[MELODY_NOTES - 2].duration == 0 ? MELODY_NOTES - 2 : MELODY_NOTES - 1);
lcd.print(" notas, ");
lcd.print(speed);
lcd.print("% ");
}
// Función para reproducir una melodía
void playMelody(const melody& m, int speed) {
for (int i = 0; i < MELODY_NOTES && m.notes[i].frequency >= 0; i++) {
int duration = m.notes[i].duration * (100 / speed);
tone(BUZZER_PIN, m.notes[i].frequency, duration);
delay(duration + 25);
}
noTone(BUZZER_PIN);
}
// Función para cambiar la melodía actual y actualizar la información del visualizador LCD
void changeMelody(int delta) {
currentMelody = (currentMelody + delta + MELODIES) % MELODIES;
showMelodyInfo(melodies[currentMelody], playbackSpeed);
}
// Variables globales
int currentMelodyIndex = 0; // índice de la melodía seleccionada
int currentSpeed = 100; // velocidad de reproducción actual (por defecto 100%)
int melodyLength = 0; // número de notas de la melodía actual
void displayMelodyInfo() {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(melodies[currentMelodyIndex].name);
lcd.setCursor(0, 1);
lcd.print(melodyLength);
lcd.print(" notas, ");
lcd.print(currentSpeed);
lcd.print("%");
}
void startPlayback() {
// Mostrar información de la melodía
displayMelodyInfo();
// Reproducir la melodía seleccionada
playMelody(melodies[currentMelodyIndex], currentSpeed);
// Volver al modo de selección de melodía
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(currentMelodyIndex + 1);
lcd.print(". ");
lcd.print(melodies[currentMelodyIndex].name);
lcd.setCursor(0, 1);
lcd.print("Selecione con ");
lcd.print("<>");
lcd.print(", OK ");
lcd.write(byte(2));
}
void adjustSpeed(int increment) {
currentSpeed += increment;
if (currentSpeed < 50) {
currentSpeed = 50;
} else if (currentSpeed > 150) {
currentSpeed = 150;
}
displayMelodyInfo();
}
// Función principal del modo de reproducción de la melodía
void playMelodyMode() {
// Configurar el zumbador como salida
pinMode(BUZZER_PIN, OUTPUT);
// Mostrar información de la melodía seleccionada
melodyLength = 0;
while (melodies[currentMelodyIndex].notes[melodyLength].frequency >= 0 && melodyLength < MELODY_NOTES) {
melodyLength++;
}
displayMelodyInfo();
// Reproducir la melodía
startPlayback();
// Esperar hasta que se pulse el botón del codificador rotativo
while (digitalRead(ROTARY_ENCODER_BUTTON_PIN) == HIGH) {
// Ajustar la velocidad de reproducción si se gira el codificador rotativo
int encoderValue = readRotaryEncoder();
if (encoderValue != 0) {
adjustSpeed(encoderValue);
}
}
// Detener la reproducción de la melodía
noTone(BUZZER_PIN);
// Volver al modo de selección de melodía
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(currentMelodyIndex + 1);
lcd.print(". ");
lcd.print(melodies[currentMelodyIndex].name);
lcd.setCursor(0, 1);
lcd.print("Selecione con ");
lcd.print("<>");
lcd.print(", OK ");
lcd.write(byte(2));
}