#include <Keypad.h>
// pines del display de 7 segmentos
const int segmentPins[] = {2, 4, 5, 21, 22, 23, 25}; // A, B, C, D, E, F, G, DP
const int digitPins[] = {26, 27, 32, 33}; // Common pins por cada pin(d1, d2, d3, d4)
// Pines del keypad
const byte ROWS = 4; // 4 filas
const byte COLS = 4; // 4 columnnas
char keys[ROWS][COLS] = {
{'1','2','3','A'},
{'4','5','6','B'},
{'7','8','9','C'},
{'*','0','#','D'}
};
byte rowPins[ROWS] = {16, 17, 18, 19}; //pines del keypad - filas
byte colPins[COLS] = {12, 13, 14, 15}; // pines del keypad - columnas
Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS);
// variables de entrada y salida
char inputValues[2] = {0, 0}; // almacenamiento de las dos entradas hexadecimales
int currentInputIndex = 0; // seguimiento de la entrada
int result = 0; // almacenamiento del resultado
bool errorState = false; // Flag error state
bool calcComplete = false; // Flag cuando se realiza el calculo de operacion
// sementos: patrones hexadecimales (0-9, A-F)
// Segmentos: A, B, C, D, E, F, G, DP (1 = OFF, 0 = ON)
const byte digitPatterns[16][8] = {
{0, 0, 0, 0, 0, 0, 1, 1}, // 0
{1, 0, 0, 1, 1, 1, 1, 1}, // 1
{0, 0, 1, 0, 0, 1, 0, 1}, // 2
{0, 0, 0, 0, 1, 1, 0, 1}, // 3
{1, 0, 0, 1, 1, 0, 0, 1}, // 4
{0, 1, 0, 0, 1, 0, 0, 1}, // 5
{0, 1, 0, 0, 0, 0, 0, 1}, // 6
{0, 0, 0, 1, 1, 1, 1, 1}, // 7
{0, 0, 0, 0, 0, 0, 0, 1}, // 8
{0, 0, 0, 0, 1, 0, 0, 1}, // 9
{0, 0, 0, 1, 0, 0, 0, 1}, // A
{1, 1, 0, 0, 0, 0, 0, 1}, // B
{0, 1, 1, 0, 0, 0, 1, 1}, // C
{1, 0, 0, 0, 0, 1, 0, 1}, // D
{0, 1, 1, 0, 0, 0, 0, 1}, // E
{0, 1, 1, 1, 0, 0, 0, 1} // F
};
// muestreo del error- muestra "Err"
const byte errorPattern[4][8] = {
{0, 1, 1, 0, 0, 0, 0, 1}, // E
{1, 1, 1, 1, 0, 0, 0, 1}, // r
{1, 1, 1, 1, 0, 0, 0, 1}, // r
{1, 1, 1, 1, 1, 1, 1, 1} // blank
};
void setup() {
//inicializacion de pines del display 7 seg
for (int i = 0; i < 8; i++) {
pinMode(segmentPins[i], OUTPUT);
digitalWrite(segmentPins[i], HIGH); // apagar los segmentos (common anode)
}
// inicializar pines digitales
for (int i = 0; i < 4; i++) {
pinMode(digitPins[i], OUTPUT);
digitalWrite(digitPins[i], LOW); // encender todos los digitos (common anode)
}
Serial.begin(115200);
Serial.println("ESP32 Hex Calculator Ready");
resetSystem(); // inicializar sistema
}
void loop() {
// actulizar la pantalla
updateDisplay();
// comprobacion de la entrada del keypad
char key = keypad.getKey();
if (key) {
processKey(key);
}
}
void processKey(char key) {
// si se hizo el calculo y el usuario presiona un boton, el sistema se reinicia
if (calcComplete && key) {
resetSystem();
return;
}
// Process hexadecimal digits (0-9, A-F)
if ((key >= '0' && key <= '9') || (key >= 'A' && key <= 'D') || key == '*' || key == '#') {
if (currentInputIndex < 2) {
// conversion a hexadecimal
int hexValue;
if (key >= '0' && key <= '9') {
hexValue = key - '0';
} else if (key >= 'A' && key <= 'D') {
hexValue = 10 + (key - 'A');
} else if (key == '*') {
hexValue = 15; // F
} else if (key == '#') {
hexValue = 14; // E
}
inputValues[currentInputIndex] = hexValue;
currentInputIndex++;
Serial.print("Input ");
Serial.print(currentInputIndex);
Serial.print(": 0x");
Serial.println(hexValue, HEX);
// si se ingresan dos numeros calcular el resultado del complemento del menor
if (currentInputIndex == 2) {
calculateResult();
}
}
}
}
void calculateResult() {
// comparacion de los dos valores hex
if (inputValues[0] == inputValues[1]) {
// Si son iguales hay un error
errorState = true;
Serial.println("Error: Input values are equal");
} else {
// encontrar el valor menor de los datos ingresados
int smallerValue = (inputValues[0] < inputValues[1]) ? inputValues[0] : inputValues[1];
//calcular el complemento a 1 del menor en 4 bits invirtiendo
int complement = (~smallerValue) & 0xF; // solo mantine los menor 4 bits
// convercion a decimal
result = complement;
Serial.print("Smaller value: 0x");
Serial.println(smallerValue, HEX);
Serial.print("1's complement: 0x");
Serial.println(complement, HEX);
Serial.print("Decimal result: ");
Serial.println(result);
}
calcComplete = true;
}
void resetSystem() {
// Clear input values
inputValues[0] = 0;
inputValues[1] = 0;
currentInputIndex = 0;
result = 0;
errorState = false;
calcComplete = false;
Serial.println("System reset");
}
void updateDisplay() {
static unsigned long lastRefresh = 0;
const unsigned long refreshInterval = 5; // delay refresh display
if (millis() - lastRefresh >= refreshInterval) {
static int currentDigit = 0;
// Turn off all digits during update
for (int i = 0; i < 4; i++) {
digitalWrite(digitPins[i], LOW);
}
// Clear all segments
for (int i = 0; i < 8; i++) {
digitalWrite(segmentPins[i], HIGH);
}
// mensaje de error
if (errorState) {
displayError(currentDigit);
} else {
// modo normal de display
if (currentDigit == 0) { // First digit (d1)
if (currentInputIndex > 0) {
displayHexDigit(inputValues[0], false);
} else {
displayHexDigit(0, true); // en blanco si no hay entrada
}
}
else if (currentDigit == 1) { // 2do digit (d2)
if (currentInputIndex > 1) {
displayHexDigit(inputValues[1], false);
} else {
displayHexDigit(0, true); // en blanco si todavia no hay entrada
}
}
else if (currentDigit == 2) { //3er digito (d3)
if (calcComplete) {
// mostrar resultado
displayHexDigit((result > 9) ? 1 : 0, (result <= 9));
} else {
displayHexDigit(0, true); //en blanco si el resultado no se completa
}
}
else if (currentDigit == 3) { // 4to digito (d4)
if (calcComplete) {
//mostrar resultado
displayHexDigit(result % 10, false);
} else {
displayHexDigit(0, true); //en blanco si el resultado no se completa
}
}
}
// activar el digito actual
digitalWrite(digitPins[currentDigit], HIGH);
// moverse al siguiente bit
currentDigit = (currentDigit + 1) % 4;
lastRefresh = millis();
}
}
void displayHexDigit(byte digit, bool blank) {
if (blank) {
// Limpieza de los 4 digitos
for (int i = 0; i < 8; i++) {
digitalWrite(segmentPins[i], HIGH);
}
return;
}
// Validacion de bits
if (digit > 15) digit = 0;
for (int i = 0; i < 8; i++) {
digitalWrite(segmentPins[i], digitPatterns[digit][i]);
}
}
void displayError(int digitIndex) {
// Display "Err"
for (int i = 0; i < 8; i++) {
digitalWrite(segmentPins[i], errorPattern[digitIndex][i]);
}
}