#include <Keypad.h>
// Define the pins for the 7-segment displays
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 for each digit (d1, d2, d3, d4)
// Define the keypad pins and keys
const byte ROWS = 4; // Four rows
const byte COLS = 4; // Four columns
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}; // Connect to the row pinouts of the keypad
byte colPins[COLS] = {12, 13, 14, 15}; // Connect to the column pinouts of the keypad
Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS);
// Variables for input and output
char inputValues[2] = {0, 0}; // Store the two hex inputs
int currentInputIndex = 0; // Track which input we're on (0 or 1)
int result = 0; // Store the result
bool errorState = false; // Flag for error state
bool calcComplete = false; // Flag to indicate calculation is done
// Segment patterns for hexadecimal digits (0-9, A-F)
// Segments: 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
};
// Error display pattern - displays "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() {
// Initialize segment pins
for (int i = 0; i < 8; i++) {
pinMode(segmentPins[i], OUTPUT);
digitalWrite(segmentPins[i], HIGH); // Turn off all segments (common anode)
}
// Initialize digit pins
for (int i = 0; i < 4; i++) {
pinMode(digitPins[i], OUTPUT);
digitalWrite(digitPins[i], LOW); // Turn off all digits (common anode)
}
Serial.begin(115200);
Serial.println("ESP32 Hex Calculator Ready");
resetSystem(); // Initialize the system
}
void loop() {
// Update display
updateDisplay();
// Check for keypad input
char key = keypad.getKey();
if (key) {
processKey(key);
}
}
void processKey(char key) {
// If we're done calculating and user presses any key, reset the system
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) {
// Convert key to hex value
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);
// If we've entered two digits, calculate result
if (currentInputIndex == 2) {
calculateResult();
}
}
}
}
void calculateResult() {
// Compare the two hex values
if (inputValues[0] == inputValues[1]) {
// If equal, set error state
errorState = true;
Serial.println("Error: Input values are equal");
} else {
// Find the smaller value
int smallerValue = (inputValues[0] < inputValues[1]) ? inputValues[0] : inputValues[1];
// Calculate 1's complement of the smaller value (invert all bits)
int complement = (~smallerValue) & 0xF; // Only keep the lower 4 bits
// Convert to 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; // 5ms per digit refresh
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);
}
// If in error state, display error message
if (errorState) {
displayError(currentDigit);
} else {
// Normal display mode
if (currentDigit == 0) { // First digit (d1)
if (currentInputIndex > 0) {
displayHexDigit(inputValues[0], false);
} else {
displayHexDigit(0, true); // Blank if not yet entered
}
}
else if (currentDigit == 1) { // Second digit (d2)
if (currentInputIndex > 1) {
displayHexDigit(inputValues[1], false);
} else {
displayHexDigit(0, true); // Blank if not yet entered
}
}
else if (currentDigit == 2) { // Third digit (d3)
if (calcComplete) {
// Show result tens digit or blank if single digit
displayHexDigit((result > 9) ? 1 : 0, (result <= 9));
} else {
displayHexDigit(0, true); // Blank if calculation not complete
}
}
else if (currentDigit == 3) { // Fourth digit (d4)
if (calcComplete) {
// Show result units digit
displayHexDigit(result % 10, false);
} else {
displayHexDigit(0, true); // Blank if calculation not complete
}
}
}
// Activate the current digit
digitalWrite(digitPins[currentDigit], HIGH);
// Move to the next digit
currentDigit = (currentDigit + 1) % 4;
lastRefresh = millis();
}
}
void displayHexDigit(byte digit, bool blank) {
if (blank) {
// All segments off for blank display
for (int i = 0; i < 8; i++) {
digitalWrite(segmentPins[i], HIGH);
}
return;
}
// Ensure digit is in valid range
if (digit > 15) digit = 0;
// Set segments according to pattern for this digit
for (int i = 0; i < 8; i++) {
digitalWrite(segmentPins[i], digitPatterns[digit][i]);
}
}
void displayError(int digitIndex) {
// Display "Err" on the display
for (int i = 0; i < 8; i++) {
digitalWrite(segmentPins[i], errorPattern[digitIndex][i]);
}
}