#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <IRremote.hpp>
#define IR_RECEIVE_PIN 11
//int receiver = 11; // Signal Pin of IR receiver to Arduino Digital Pin 11
// Imposta l'indirizzo I2C del display LCD (solitamente 0x27 o 0x3F)
LiquidCrystal_I2C lcd(0x27, 16, 2); // LCD I2C con 16 colonne e 2 righe
int button = 10;
int board = 3;
char timeobj;
enum StatusType { INPUTCODE, INPUTTEMPO, GUESSCODE, SOLVED, HACKED, FAILED, WAIT };
StatusType status;
unsigned long codiceSegreto = 0;
String inputString;
int tempoTimer = 0;
int countDown = 0;
bool codiceInserito = false;
unsigned long startTime;
unsigned long countDownTime;
char key;
/*-----( Declare objects )-----*/
//IRrecv irrecv(receiver); // create instance of 'irrecv'
//vairable uses to store the last decodedRawData
uint32_t last_decodedRawData = 0;
/*-----( Function )-----*/
void translateIR() // takes action based on IR code received
{
// Check if it is a repeat IR code
if (IrReceiver.decodedIRData.flags)
{
//set the current decodedRawData to the last decodedRawData
IrReceiver.decodedIRData.decodedRawData = last_decodedRawData;
Serial.println("REPEAT!");
} else
{
//output the IR code on the serial monitor
Serial.print("IR code:0x");
Serial.println(IrReceiver.decodedIRData.decodedRawData, HEX);
}
//map the IR code to the remote key
switch (IrReceiver.decodedIRData.decodedRawData)
{
case 0xBA45FF00: Serial.println("POWER"); key = 'P'; break;
case 0xB847FF00: Serial.println("FUNC/STOP"); key = 'F'; break;
case 0xB946FF00: Serial.println("VOL+"); key = '+'; break;
case 0xBB44FF00: Serial.println("FAST BACK"); key = 'B'; break;
case 0xBF40FF00: Serial.println("PAUSE"); key = 'S'; break;
case 0xBC43FF00: Serial.println("FAST FORWARD"); key = 'V'; break;
case 0xF807FF00: Serial.println("DOWN"); key = 'D'; break;
case 0xEA15FF00: Serial.println("VOL-"); key = '-'; break;
case 0xF609FF00: Serial.println("UP"); key = 'U'; break;
case 0xE619FF00: Serial.println("EQ"); key = 'E'; break;
case 0xF20DFF00: Serial.println("ST/REPT"); key = 'R'; break;
case 0xE916FF00: Serial.println("0"); key = '0'; break;
case 0xF30CFF00: Serial.println("1"); key = '1'; break;
case 0xE718FF00: Serial.println("2"); key = '2'; break;
case 0xA15EFF00: Serial.println("3"); key = '3'; break;
case 0xF708FF00: Serial.println("4"); key = '4'; break;
case 0xE31CFF00: Serial.println("5"); key = '5'; break;
case 0xA55AFF00: Serial.println("6"); key = '6'; break;
case 0xBD42FF00: Serial.println("7"); key = '7'; break;
case 0xAD52FF00: Serial.println("8"); key = '8'; break;
case 0xB54AFF00: Serial.println("9"); key = '9'; break;
default:
Serial.println(" other button ");
}// End Case
//store the last decodedRawData
last_decodedRawData = IrReceiver.decodedIRData.decodedRawData;
delay(500); // Do not get immediate repeat
} //END translateIR
void setup() {
// Inizializza il display I2C
lcd.init();
lcd.backlight(); // Attiva la retroilluminazione dell'LCD
Serial.begin(9600);
setNewStatus(INPUTCODE);
digitalWrite(button, HIGH);
IrReceiver.begin(IR_RECEIVE_PIN, ENABLE_LED_FEEDBACK); // Start the receiver
}
void loop() {
handleTimer();
handleHacking();
StateMachine();
}
void StateMachine() {
switch (status) {
case INPUTCODE:
handleCodeInput();
break;
case INPUTTEMPO:
handleTempoInput();
break;
case GUESSCODE:
guessCode();
break;
case SOLVED:
solved();
break;
case HACKED:
handleHacked();
break;
case FAILED:
failed();
break;
case WAIT:
handleWait();
break;
}
}
void handleWait() {
if (IrReceiver.decode()) { // Verifica se abbiamo ricevuto un segnale IR
Serial.println("Segnale IR ricevuto");
translateIR();
Serial.print("Tasto ricevuto: ");
Serial.println(key); // Verifica il valore di key
if (key == 'B') {
Serial.println("Passaggio a GUESSCODE");
setNewStatus(GUESSCODE);
}
if (key == 'V') {
Serial.println("Passaggio a INPUTCODE");
setNewStatus(INPUTCODE);
}
IrReceiver.resume(); // Prepara per ricevere il prossimo segnale
}
}
void setNewStatus(StatusType newStatus) {
inputString = "";
switch (newStatus) {
case INPUTCODE:
clearLCD("Inserisci codice:");
Serial.println("Inserisci codice:");
break;
case SOLVED:
codiceInserito = false;
break;
case FAILED:
codiceInserito = false;
startTime = millis();
break;
case GUESSCODE:
lcd.clear();
codiceInserito = true; // Timer inizia solo qui, flag per gestire il conto alla rovescia
countDownTime = millis();
countDown = tempoTimer + 1;
break;
case WAIT:
clearLCD("Again with 'FF'", "New with 'FB'");
Serial.println("Again with 'FF' New with 'FB'");
break;
}
status = newStatus;
}
void clearLCD(String line) {
lcd.clear();
lcd.print(line);
}
void clearLCD(String line0, String line1) {
clearLCD(line0);
lcd.setCursor(0, 1);
lcd.print(line1);
}
boolean keyIsNumber() {
return (key >= '0' && key <= '9');
}
void addNumberToInputString(int maxLen) {
boolean deleted = false;
boolean refresh = false;
if (IrReceiver.decode()) // have we received an IR signal?
{
translateIR();
if (keyIsNumber() && inputString.length() < maxLen) {
inputString += key;
refresh = true;
}
if (key == 'P') {
inputString = "";
refresh = true;
}
if (key == '-') {
int len = inputString.length();
inputString = inputString.substring(0, len - 1);
refresh = true;
}
if (refresh) {
lcd.setCursor(0, 1);
lcd.print(" ");
lcd.setCursor(0, 1);
lcd.print(inputString);
Serial.println(inputString);
}
IrReceiver.resume(); // receive the next value
}
}
void handleCodeInput() {
addNumberToInputString(3);
if (key == 'S' && inputString.length() >= 3) { // Usa almeno tre numeri
codiceSegreto = inputString.toInt();
clearLCD("Inserisci tempo:");
Serial.println("Inserisci tempo:");
setNewStatus(INPUTTEMPO);
}
}
void handleTempoInput() {
addNumberToInputString(4);
if (key == 'S' && inputString.toInt() >= 5) { // Imposta un minimo di cinque secondi
tempoTimer = inputString.toInt();
clearLCD("Codice e tempo", "inseriti!");
Serial.println("Codice e tempo inseriti!");
Serial.println(tempoTimer);
delay(2000);
setNewStatus(GUESSCODE);
}
}
void guessCode() {
//Serial.println("Guessing");
// Azzera la stringa di input per permettere un nuovo inserimento
if (inputString == "") {
lcd.setCursor(0, 1);
lcd.print(" ");
lcd.setCursor(0, 1);
lcd.print("Insert code:");
Serial.println("Insert code:");
}
// Aggiungi numeri alla stringa di input
addNumberToInputString(8);
// Controlla solo se il tasto 'S' (invio) è stato premuto
if (key == 'S' && inputString.length() >= 3) { // Assicurati che ci siano almeno 3 numeri
unsigned long guess = inputString.toInt();
// Resetta il flag codiceInserito per gestire correttamente il prossimo input
codiceInserito = false;
// Confronta il codice inserito con il codice segreto
if (guess == codiceSegreto) {
setNewStatus(SOLVED); // Codice corretto, passa allo stato risolto
} else {
setNewStatus(FAILED); // Codice errato, passa allo stato fallito
}
}
}
void failed() {
lcd.clear();
lcd.print("Ordigno detonato");
Serial.println("Ordigno detonato");
if (millis() - startTime > 3000) {
clearLCD("Out of business ...");
Serial.println("Out of business ...");
delay(10000);
setNewStatus(WAIT);
}
}
void solved() {
clearLCD("ordigno", "disinnescato");
Serial.println("ordigno disinnescato");
delay(3000);
setNewStatus(WAIT);
}
void handleHacked() {
clearLCD("Hacking ....");
Serial.println("Hacking ....");
delay(1000);
setNewStatus(SOLVED);
}
void handleTimer() {
static unsigned long lastCountDown = 0;
// Esegui solo se è stato inserito il codice e il timer è in corso
if (codiceInserito && countDown > 0) {
if (lastCountDown == 0) {
lastCountDown = millis(); // Inizia il conto alla rovescia
}
if (millis() - lastCountDown > 1000) {
lastCountDown = millis(); // Aggiorna ogni secondo
countDown--;
lcd.setCursor(0, 0);
lcd.print("Count Down: ");
Serial.println("Count Down: ");
lcd.setCursor(12, 0);
lcd.print(countDown);
}
// Se il timer è scaduto
if (countDown == 0) {
setNewStatus(FAILED); // Se il tempo è scaduto, fallisce
}
} else {
lastCountDown = 0; // Resetta il timer se non è attivo
}
}
void handleHacking() {
if (!codiceInserito) {
return;
}
if (digitalRead(button) == LOW) {
setNewStatus(HACKED);
}
}