#include <Keypad.h>
#include <LiquidCrystal_I2C.h>
#include <Wire.h>
// https://docs.wokwi.com/parts/wokwi-lcd1602#attributes
#define I2C_ADDR 0x27
#define LCD_COLUMNS 16
#define LCD_LINES 2
// https://docs.wokwi.com/parts/wokwi-membrane-keypad
#define KEYPAD_ROWS 4
#define KEYPAD_COLS 4
#define ENDKEY_DIGIT 2
#define ENDKEY_ACTION 4
#define ENDKEY_RESULT 8
#define BUF_SIZE 32
LiquidCrystal_I2C lcd(I2C_ADDR, LCD_COLUMNS, LCD_LINES);
const char keys[KEYPAD_ROWS][KEYPAD_COLS] = {{'1', '2', '3', '+'},
{'4', '5', '6', '-'},
{'7', '8', '9', '*'},
{'=', '0', 'l', '/'}};
uint8_t rowPins[KEYPAD_ROWS] = {11, 10, 9, 8}; // R1, R2, R3, R4
uint8_t colPins[KEYPAD_COLS] = {7, 6, 5, 4}; // C1, C2, C3, C4
Keypad keypad =
Keypad(makeKeymap(keys), rowPins, colPins, KEYPAD_ROWS, KEYPAD_COLS);
uint8_t position = 0;
uint8_t endkey = 0;
char buf[BUF_SIZE] = {0};
void setup() {
Serial.begin(9600);
lcd.init();
lcd.backlight();
lcd.cursor();
}
void loop() {
char key = keypad.getKey();
if (key != NO_KEY) {
Serial.println(key);
addkey(key);
}
}
void addkey(char k) {
switch (k) {
case '+':
case '-':
case '*':
case '/':
if (endkey == ENDKEY_DIGIT) {
buf[position] = k;
tolcd(k);
endkey = ENDKEY_ACTION;
}
break;
case 'l': // log
ResetBuf();
lcd.clear();
position = 0;
buf[position] = k;
endkey = ENDKEY_ACTION;
tolcd(k);
break;
case '=':
if (endkey == ENDKEY_DIGIT) {
endkey = ENDKEY_RESULT;
buf[position] = k;
tolcd(k);
getsumma();
}
break;
default: // 0-9
if (endkey == ENDKEY_RESULT) {
ResetBuf();
position = 0;
lcd.clear();
}
buf[position] = k;
tolcd(k);
endkey = ENDKEY_DIGIT;
break;
}
}
void getsumma() {
if (buf[0] == 'l') {
uint32_t arg = 0;
double result;
uint8_t i = 2;
while (buf[i] >= '0' && buf[i] <= '9') {
arg *= 10;
arg += buf[i] - '0';
++i;
}
lcd.setCursor(position % 15, position / 15);
if (arg == 0) lcd.print("UNDEFINED");
else {
result = log(arg);
lcd.print(result);
}
} else {
String number1 = "";
String number2 = "";
char d;
int i;
int summa;
// получить первое число
for (i = 0; i < position; i++) {
if (buf[i] >= 0x30 && buf[i] <= 0x39)
number1 += buf[i];
else
break;
}
Serial.print("number1=");
Serial.print(number1.toInt());
// действие
d = buf[i];
Serial.print(" d=");
Serial.println(buf[i]);
// получить второе число
for (i = i + 1; i < position; i++) {
if (buf[i] >= 0x30 && buf[i] <= 0x39)
number2 += buf[i];
else
break;
}
Serial.print("number2=");
Serial.print(number2.toInt());
switch (d) {
case '+':
summa = number1.toInt() + number2.toInt();
break;
case '-':
summa = number1.toInt() - number2.toInt();
break;
case '*':
summa = number1.toInt() * number2.toInt();
break;
case '/':
summa = number1.toInt() / number2.toInt();
break;
default:
break;
}
lcd.setCursor(position % 15, position / 15);
lcd.print(summa);
}
}
void tolcd(char k) {
lcd.setCursor(position % 15, position / 15);
if (k == 'l') {
lcd.print("ln");
position += 2;
} else {
lcd.print(k);
++position;
}
}
void ResetBuf() {
for (uint8_t i = 0; i < BUF_SIZE; ++i) buf[i] = 0;
}