/*
  Arduino | hardware-help
  Keypad calculator
  Zeruxe — 6/16/24 at 7:25 PM

  From this not-so-good example:
  https://www.hackster.io/nolimitcircuit/arduinolator-an-arduino-calculator-b544ff

  This not so great but working "4 banger" calculator...
*/

#include <Keypad.h>
#include <LiquidCrystal.h>
/*
  enum DispZone {
  operandOne,   // 0
  operandTwo,   // 1
  operateSign,  // 2
  calcResult    // 3
  };
*/
const byte ROWS = 4;
const byte COLS = 4;
const char keys [ROWS] [COLS] = {
  {'1', '2', '3', '+'},
  {'4', '5', '6', '-'},
  {'7', '8', '9', '*'},
  {'.', '0', '=', '/'}
};
const byte rowPins[ROWS] = {23, 25, 27, 29};
const byte colPins[COLS] = {31, 33, 35, 37};
const byte CLEAR_PIN = 39;

Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );
LiquidCrystal lcd(12, 11, 10, 9, 8, 7);

bool isResult = false;
char opKey;
char operandBuffer[2][8];
char operand1[8];
char operand2[8];
int operatorIdx = 0;
int operandIdx = 0;

void checkClear() {
  static int oldState = HIGH;

  int state = digitalRead(CLEAR_PIN);
  if (state != oldState)  {
    oldState = state;
    if (state == LOW) {
      doClear();
    }
    delay(20);  // debounce
  }
}

void doClear()  {
  Serial.println("Clear");
  lcd.clear();
  operatorIdx = 0;
  operandIdx = 0;
  memset(operandBuffer[0], 0, sizeof(operandBuffer[0]));
  memset(operandBuffer[1], 0, sizeof(operandBuffer[1]));
  isResult = false;
}

void charsToLCD(int zone, char* value)  {
  Serial.println(value);
  switch (zone) {
    case 0: // print op1
      lcd.setCursor(10, 0);
      break;
    case 1: // print op2
      lcd.setCursor(10, 1);
      break;
    case 2: // print result
      lcd.setCursor(10, 2);
      lcd.print("--------");
      lcd.setCursor(10, 3);
      break;
    default:
      lcd.print("Bad zone!");
      break;
  }
  lcd.print(value);
}

void setup()  {
  Serial.begin(9600);
  lcd.begin(20, 4);
  pinMode(CLEAR_PIN, INPUT_PULLUP);
  lcd.setCursor(6, 1);
  lcd.print("Arduino");
  lcd.setCursor(5, 2);
  lcd.print("Calculator");
  delay(1000);
  lcd.clear();
}

void loop() {
  double result = 0;
  char lcdBuff[16];

  char key = keypad.getKey();
  checkClear();

  if (key != NO_KEY) {
    if (isResult)   {
      doClear();
      //isResult = false;
    }
    //Serial.print(key);
    //lcd.print(key);
    if (key >= '0' && key <= '9' || key == '.') {
      //Serial.println(" is a number.");
      operandBuffer[operatorIdx][operandIdx] = key;
      operandIdx++;
      //Serial.println(operandBuffer[operatorIdx]);
      charsToLCD(operatorIdx, operandBuffer[operatorIdx]);
    } else {
      //Serial.println(" is an operator.");
      operandBuffer[operatorIdx][operandIdx] = '\0'; // terminate operand string
      operandIdx = 0;  // reset buffer index
      if (operatorIdx == 0) {
        strncpy(operand1, operandBuffer[0], 8);
        operatorIdx = 1;
      } else  {
        strncpy(operand2, operandBuffer[1], 8);
        operatorIdx = 0;
      }
      double dOp1 = atof(operand1);
      double dOp2 = atof(operand2);
      //opKey = key;  // save operator
      if (key != '=') {
        opKey = key;  // save operator
        lcd.setCursor(19, 0);
        lcd.print(opKey);
      } else if (key == '=') {
        Serial.print(opKey);
        switch (opKey)  {
          case '+':
            result = dOp1 + dOp2;
            break;
          case '-':
            result = dOp1 - dOp2;
            break;
          case '*':
            result = dOp1 * dOp2;
            break;
          case '/':
            result = dOp1 / dOp2;
            break;
          default:
            result = -9999999;
            break;
        }
        Serial.println(result);
        // dtostrf(float_value, min_width, num_digits_after_decimal, where_to_store_string)
        dtostrf(result, 3, 2, lcdBuff);
        //snprintf(lcdBuff, 8, "%4.2f", result);
        //Serial.println(lcdBuff);
        charsToLCD(2, lcdBuff);
        isResult = true;
        operatorIdx = 0;
      }
    }
  }
}
$abcdeabcde151015202530354045505560fghijfghij
Clear