#include <Keypad.h>
// Configuración del teclado
const byte ROWS = 4;
const byte COLS = 4;
char keys[ROWS][COLS] = {
{'1', '2', '3', 'A'},
{'4', '5', '6', 'B'},
{'7', '8', '9', 'C'},
{'*', '0', '#', 'D'}
};
byte rowPins[ROWS] = {13, 12, 14, 27}; // Conectados a R1, R2, R3, R4
byte colPins[COLS] = {26, 25, 33, 32}; // Conectados a C1, C2, C3, C4
Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS);
// Pines para los segmentos (compartidos entre ambos displays)
const byte SEGMENT_PINS[] = {23, 22, 21, 19, 18, 5, 15, 2}; // A, B, C, D, E, F, G, DP
// Pines para los dígitos
const byte DIGIT_PINS[] = {17, 0, 35, 34}; // Display de 4 dígitos
// Patrones para representar números hexadecimales del 0-F en display de 7 segmentos
// Orden: A, B, C, D, E, F, G, DP
const byte SEGMENT_PATTERNS[] = {
0b11111100, // 0
0b01100000, // 1
0b11011010, // 2
0b11110010, // 3
0b01100110, // 4
0b10110110, // 5
0b10111110, // 6
0b11100000, // 7
0b11111110, // 8
0b11110110, // 9
0b11101110, // A
0b00111110, // B
0b10011100, // C
0b01111010, // D
0b10011110, // E
0b10001110 // F
};
// Patrones especiales para mensajes de error
const byte PATTERN_E = 0b10011110; // E
const byte PATTERN_r = 0b00001010; // r
const byte PATTERN_O = 0b00011010; // o
// Variables para almacenar los números hexadecimales ingresados
int firstHexDigit = -1;
int secondHexDigit = -1;
int resultDecimal = 0;
bool showError = false;
unsigned long lastRefreshTime = 0;
const int refreshInterval = 5; // ms
// Contenido de cada dígito del display
int displayContent[4] = {-1, -1, -1, -1}; // -1 = apagado, 0-15 = dígito, 16+ = caracteres especiales
// Estados del sistema
enum SystemState {
WAITING_FIRST_DIGIT,
WAITING_SECOND_DIGIT,
SHOWING_RESULT,
SHOWING_ERROR
};
SystemState currentState = WAITING_FIRST_DIGIT;
void setup() {
Serial.begin(115200);
// Inicializar pines de segmentos
for (int i = 0; i < 8; i++) {
pinMode(SEGMENT_PINS[i], OUTPUT);
digitalWrite(SEGMENT_PINS[i], HIGH); // Los displays suelen ser de lógica negativa
}
// Inicializar pines de dígitos
for (int i = 0; i < 4; i++) {
pinMode(DIGIT_PINS[i], OUTPUT);
digitalWrite(DIGIT_PINS[i], HIGH); // Apagar todos los dígitos
}
// Mostrar mensaje inicial en el Serial Monitor
Serial.println("Sistema iniciado. Ingrese dos dígitos hexadecimales.");
}
void loop() {
char key = keypad.getKey();
if (key) {
processKeyInput(key);
}
// Actualizar displays
if (millis() - lastRefreshTime >= refreshInterval) {
updateDisplays();
lastRefreshTime = millis();
}
}
// Procesar entrada del teclado
void processKeyInput(char key) {
int hexValue = getHexValue(key);
// Si la tecla es un valor hexadecimal válido (0-F)
if (hexValue != -1) {
if (currentState == WAITING_FIRST_DIGIT) {
firstHexDigit = hexValue;
displayContent[0] = hexValue; // Mostrar en el primer dígito
currentState = WAITING_SECOND_DIGIT;
Serial.print("Primer dígito: ");
Serial.println(getHexChar(firstHexDigit));
} else if (currentState == WAITING_SECOND_DIGIT) {
secondHexDigit = hexValue;
displayContent[1] = hexValue; // Mostrar en el segundo dígito
Serial.print("Segundo dígito: ");
Serial.println(getHexChar(secondHexDigit));
// Procesar los números ingresados
processNumbers();
} else {
// Si ya mostró resultado o error, reinicia con el nuevo dígito
resetInput();
firstHexDigit = hexValue;
displayContent[0] = hexValue; // Mostrar en el primer dígito
currentState = WAITING_SECOND_DIGIT;
Serial.print("Primer dígito: ");
Serial.println(getHexChar(firstHexDigit));
}
} else if (key == '*') { // Reiniciar
resetInput();
Serial.println("Sistema reiniciado. Ingrese dos dígitos hexadecimales.");
}
}
// Convertir tecla a valor hexadecimal
int getHexValue(char key) {
if (key >= '0' && key <= '9') {
return key - '0';
} else if (key >= 'A' && key <= 'D') {
return 10 + (key - 'A');
} else {
return -1; // No es un valor hexadecimal válido
}
}
// Convertir valor hexadecimal a carácter
char getHexChar(int value) {
if (value >= 0 && value <= 9) {
return '0' + value;
} else if (value >= 10 && value <= 15) {
return 'A' + (value - 10);
} else {
return 'X'; // Error
}
}
// Procesar los números hexadecimales ingresados
void processNumbers() {
if (firstHexDigit == secondHexDigit) {
// Si los números son iguales, mostrar mensaje de error
Serial.println("ERROR: Números iguales");
showError = true;
// Configurar el display para mostrar "Erro"
displayContent[0] = 100; // E (código especial)
displayContent[1] = 101; // r (código especial)
displayContent[2] = 101; // r (código especial)
displayContent[3] = 102; // o (código especial)
currentState = SHOWING_ERROR;
} else {
// Si son diferentes, calcular el complemento a 1 del menor
int menor = (firstHexDigit < secondHexDigit) ? firstHexDigit : secondHexDigit;
int complemento = 15 - menor; // Complemento a 1 es invertir todos los bits (F - valor)
// Convertir resultado a decimal
resultDecimal = complemento;
// Configurar dígitos para mostrar resultado
// Los primeros dos dígitos mantienen los números hex ingresados
// Los últimos dos dígitos muestran el resultado decimal
int decenas = resultDecimal / 10;
int unidades = resultDecimal % 10;
displayContent[2] = (decenas > 0) ? decenas : -1; // No mostrar ceros a la izquierda
displayContent[3] = unidades;
Serial.print("Complemento a 1 de ");
Serial.print(getHexChar(menor));
Serial.print(": ");
Serial.print(getHexChar(complemento));
Serial.print(" (Decimal: ");
Serial.print(resultDecimal);
Serial.println(")");
showError = false;
currentState = SHOWING_RESULT;
}
}
// Actualizar los displays de 7 segmentos
void updateDisplays() {
static int currentDigit = 0;
// Apagar todos los dígitos primero
for (int i = 0; i < 4; i++) {
digitalWrite(DIGIT_PINS[i], HIGH);
}
// Apagar todos los segmentos
for (int i = 0; i < 8; i++) {
digitalWrite(SEGMENT_PINS[i], HIGH);
}
// Mostrar el contenido del dígito actual
int content = displayContent[currentDigit];
if (content >= 0) {
if (content < 16) {
// Es un dígito hexadecimal normal
displayPattern(SEGMENT_PATTERNS[content]);
} else {
// Es un carácter especial
switch (content) {
case 100: displayPattern(PATTERN_E); break; // E
case 101: displayPattern(PATTERN_r); break; // r
case 102: displayPattern(PATTERN_O); break; // o
default: break; // No mostrar nada
}
}
// Activar el dígito actual
digitalWrite(DIGIT_PINS[currentDigit], LOW);
}
// Avanzar al siguiente dígito en la próxima actualización
currentDigit = (currentDigit + 1) % 4;
}
// Mostrar un patrón específico en el display de 7 segmentos
void displayPattern(byte pattern) {
for (int i = 0; i < 8; i++) {
digitalWrite(SEGMENT_PINS[i], !bitRead(pattern, 7 - i)); // Lógica negativa
}
}
// Reiniciar la entrada
void resetInput() {
firstHexDigit = -1;
secondHexDigit = -1;
showError = false;
currentState = WAITING_FIRST_DIGIT;
// Limpiar el display
for (int i = 0; i < 4; i++) {
displayContent[i] = -1;
}
}