#include <Keypad.h>
// —————— Configuración Hardware ——————
// Keypad 4×4
const byte ROWS = 4, COLS = 4;
byte rowPins[ROWS] = {16, 17, 18, 19}; // filas R1–R4
byte colPins[COLS] = {12, 13, 14, 15}; // columnas C1–C4
char keys[ROWS][COLS] = {
{'1','2','3','A'},
{'4','5','6','B'},
{'7','8','9','C'},
{'*','0','#','D'}
};
Keypad keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS);
// Display 7-segmentos multiplexado (4 dígitos)
// Segmentos a→g
const byte segPins[7] = {2, 4, 5, 21, 22, 23, 25};
// Dígitos D1→D4 (activación LOW)
const byte digPins[4] = {26, 27, 32, 33};
// Patrones 0–F (gfedcba order)
const byte PAT[] = {
0b0111111, // 0
0b0000110, // 1
0b1011011, // 2
0b1001111, // 3
0b1100110, // 4
0b1101101, // 5
0b1111101, // 6
0b0000111, // 7
0b1111111, // 8
0b1101111, // 9
0b1110111, // A
0b1111100, // b
0b0111001, // C
0b1011110, // d
0b1111001, // E
0b1110001 // F
};
// —————— Variables de Estado ——————
uint8_t buf[4] = {0}; // patrones a mostrar en cada dígito
uint8_t val[2]; // dígitos hex ingresados
uint8_t phase = 0; // 0=espera1, 1=espera2, 2=procesa
// —————— Setup ——————
void setup() {
// Pines de segmentos
for (auto p : segPins) pinMode(p, OUTPUT);
// Pines de dígitos (HIGH = apagado)
for (auto d : digPins) {
pinMode(d, OUTPUT);
digitalWrite(d, HIGH);
}
}
// —————— Funciones Auxiliares ——————
char getKey() {
char k;
do { k = keypad.getKey(); } while (!k);
delay(50); // debounce
if (keypad.getKey() != k) return 0;
return k;
}
// Ciclo de refresco multiplexado (~8 ms para 4 dígitos)
void show() {
for (uint8_t d = 0; d < 4; d++) {
digitalWrite(digPins[d], LOW);
for (uint8_t s = 0; s < 7; s++) {
digitalWrite(segPins[s], (buf[d] >> s) & 1);
}
delay(2);
digitalWrite(digPins[d], HIGH);
}
}
// —————— Loop Principal ——————
void loop() {
// Fases de entrada
if (phase < 2) {
char k = getKey();
if (!k) return;
uint8_t v = (k <= '9' ? k - '0' : 10 + (k - 'A'));
val[phase] = v;
buf[phase] = PAT[v];
phase++;
}
// Procesamiento tras segundo dígito
if (phase == 2) {
if (val[0] == val[1]) {
// Mostrar "Err" -> E, r, r
buf[2] = PAT[0xE];
buf[3] = PAT[0xD]; // 'D' como 'r' simplificado
} else {
uint8_t m = min(val[0], val[1]);
uint8_t c = (~m) & 0x0F;
buf[2] = PAT[c / 10];
buf[3] = PAT[c % 10];
}
// Mostrar resultado 2 segundos
unsigned long t0 = millis();
while (millis() - t0 < 2000) show();
// Reiniciar
memset(buf, 0, sizeof(buf));
phase = 0;
}
// Refrescar display continuamente
show();
}