#include <Keypad.h>
#include <Adafruit_GFX.h>
#include <Adafruit_ILI9341.h>
#include <SPI.h>
// TFT
#define TFT_CS 15
#define TFT_DC 2
#define TFT_RST 4
Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC);
// Encoder
#define CLK 5
#define DT 22
#define SW 21
int intentosFallidos = 0;
const int MAX_INTENTOS = 3;
// Keypad
const byte ROWS = 4, COLS = 4;
char keys[ROWS][COLS] = {
{'1','2','3','A'},
{'4','5','6','B'},
{'7','8','9','C'},
{'*','0','#','D'}
};
// Pines seguros
byte rowPins[ROWS] = {13, 12, 14, 27};
byte colPins[COLS] = {25, 26, 32, 33};
Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS);
// Variables
String password = "1234";
String input = "";
bool authenticated = false;
int menuIndex = 0;
int lastCLK = HIGH;
String menuItems[] = {"Configurar", "Historial", "Salir"};
const int numItems = sizeof(menuItems) / sizeof(menuItems[0]);
void setup() {
Serial.begin(115200);
// TFT
tft.begin();
tft.setRotation(1);
tft.fillScreen(ILI9341_BLACK);
tft.setTextColor(ILI9341_WHITE);
tft.setTextSize(2);
// Encoder
pinMode(CLK, INPUT);
pinMode(DT, INPUT);
pinMode(SW, INPUT_PULLUP);
input = "";
showLoginScreen();
}
void loop() {
if (!authenticated) {
char key = keypad.getKey();
// Solo continuar si se recibió un carácter válido
if (key) {
// Filtrar solo caracteres válidos
if ((key >= '0' && key <= '9') || key == '*' || key == '#') {
Serial.print("Tecla presionada: ");
Serial.println(key);
if (key == '#') {
if (input == password) {
authenticated = true;
intentosFallidos = 0;
showMenu();
} else {
intentosFallidos++;
if (intentosFallidos >= MAX_INTENTOS) {
showError("¡3 intentos fallidos!");
delay(3000);
tft.fillScreen(ILI9341_BLACK);
tft.setCursor(40, 80);
tft.setTextSize(2);
tft.setTextColor(ILI9341_WHITE);
tft.println("Sistema bloqueado");
delay(10000); // Bloqueo de 10 segundos
intentosFallidos = 0;
} else {
showError("CLAVE INCORRECTA");
delay(1000);
}
input = "";
showLoginScreen();
}
}else if (key == '*') {
input = "";
drawAsterisks();
} else if (input.length() < 8) {
input += key;
drawAsterisks();
}
} else {
// Ignorar cualquier otro carácter extraño (ruido al inicio)
Serial.print("Tecla ignorada (ASCII): ");
Serial.println((int)key);
}
}
} else {
handleEncoder();
handleSelect();
}
}
void showLoginScreen() {
tft.fillScreen(ILI9341_BLACK);
tft.setTextColor(ILI9341_WHITE);
tft.setTextSize(2);
tft.setCursor(40, 30);
tft.println("Ingrese la clave:");
tft.setTextSize(2);
tft.setCursor(0, 150);
tft.println("Presione '#' para ingresar");
drawAsterisks();
}
void drawAsterisks() {
// Dibuja el recuadro blanco
tft.drawRect(38, 80, 150, 30, ILI9341_WHITE);
tft.fillRect(40, 82, 146, 26, ILI9341_BLACK);
tft.setCursor(45, 90);
tft.setTextSize(2);
for (int i = 0; i < input.length(); i++) {
tft.print("*");
}
}
void showError(String msg) {
tft.fillScreen(ILI9341_BLACK);
tft.setCursor(20, 60);
tft.setTextColor(ILI9341_RED);
tft.print(msg);
}
void showMenu() {
tft.fillScreen(ILI9341_BLACK);
for (int i = 0; i < numItems; i++) {
if (i == menuIndex) {
tft.setTextColor(ILI9341_GREEN, ILI9341_BLACK);
} else {
tft.setTextColor(ILI9341_WHITE, ILI9341_BLACK);
}
tft.setCursor(40, 40 + i * 30);
tft.print(menuItems[i]);
}
}
void handleEncoder() {
int currentCLK = digitalRead(CLK);
if (currentCLK != lastCLK && currentCLK == LOW) {
if (digitalRead(DT) == HIGH) {
menuIndex--;
} else {
menuIndex++;
}
if (menuIndex < 0) menuIndex = numItems - 1;
if (menuIndex >= numItems) menuIndex = 0;
showMenu();
}
lastCLK = currentCLK;
}
void handleSelect() {
static bool pressed = false;
if (digitalRead(SW) == LOW && !pressed) {
pressed = true;
tft.fillScreen(ILI9341_BLACK);
tft.setCursor(40, 100);
tft.setTextColor(ILI9341_YELLOW);
tft.println("Seleccionado: ");
tft.setCursor(40, 140);
tft.println(menuItems[menuIndex]);
delay(1000);
showMenu();
} else if (digitalRead(SW) == HIGH && pressed) {
pressed = false;
}
}