#include "LiquidCrystal_I2C.h"
#include <EEPROM.h>
#include "Keypad.h"
// дисплей
#define I2C_ADDR 0x27 // для I2C
#define LCD_COLUMNS 16 // количество столбцов
#define LCD_LINES 2 // количество строк
// клавиатура
const byte ROWS = 4; // строки
const byte COLS = 4; // столбцы
//const byte rowPins[ROWS] = {2, 3, 18, 19}; // распиновка строк
//const byte colPins[COLS] = {7, 6, 5, 4}; // распиновка столбцов
const int rowPins[ROWS] = {7, 6, 5, 4}; // распиновка строк
const int colPins[COLS] = {2, 3, 18, 19}; // распиновка столбцов
// Кнопки
char keys[ROWS*COLS] = {
'1', '2', '3', 'A',
'4', '5', '6', 'B',
'7', '8', '9', 'C',
'*', '0', '#', 'D'
};
LiquidCrystal_I2C lcd_display(I2C_ADDR, LCD_COLUMNS, LCD_LINES); // init дисплей
Keypad keypad(rowPins, colPins); // init keypad
struct Data // структура для хранения вычислений, чтобы удобнее было записывать в память
{
int first_number = 0;
int second_number = 0;
int result = 0;
};
void setup()
{
Serial.begin(9600); // на всякий случай
lcd_display.init();
lcd_display.backlight();
lcd_display.print("1. Calculator");
attachInterrupt(digitalPinToInterrupt(rowPins[3]), handler, FALLING);
attachInterrupt(digitalPinToInterrupt(rowPins[0]), handler, FALLING);
initialReset();
}
volatile bool keyInterrupt = false;
void handler()
{
keyInterrupt = true;
Serial.println("Interrupted");
}
// 1) Calculator
// 2) Memory
// 3) Reset
int menu_change = 0;
void changeMenu(char key)
{
switch (key)
{
// промотка меню влево
case '*':
if (menu_change == 0)
menu_change = 2;
else
menu_change--;
break;
// промотка меню вправо
case '#':
if (menu_change == 2)
menu_change = 0;
else
menu_change++;
break;
case 'A':
confirmMenu();
break;
}
mainMenu();
}
void confirmMenu()
{
switch (menu_change)
{
case 0:
Calculate();
break;
case 2:
Reset();
break;
}
}
Data calculator_data; // структура для результата вычислений
Data memory_data; // структура для считывания из памяти
Data default_data; // структура для запуска в первый раз и сброса
void Calculate()
{
lcd_display.clear();
lcd_display.print("First number:");
lcd_display.setCursor(0, 1);
calculator_data.first_number = inputNumber();
if (calculator_data.first_number == 0)
return;
lcd_display.clear();
lcd_display.print("Second number:");
lcd_display.setCursor(0, 1);
calculator_data.second_number = inputNumber();
if (calculator_data.second_number == 0)
return;
calculator_data.result = calculator_data.first_number | calculator_data.second_number;
lcd_display.clear();
lcd_display.print("Result:");
lcd_display.print(calculator_data.result);
lcd_display.setCursor(0, 1);
lcd_display.print("Save result? A/B");
saveResult();
}
void saveResult()
{
bool is_input = true;
while(is_input)
{
noInterrupts();
char key = keypad.get_key();
interrupts();
if (key != '\0')
{
switch (key)
{
case 'A':
is_input = false;
EEPROM.put(0, calculator_data);
break;
case 'B':
is_input = false;
return;
break;
}
}
}
}
int inputNumber()
{
bool is_input = true;
int input = 0;
while(is_input)
{
noInterrupts();
char key = keypad.get_key();
interrupts();
if (key != '\0')
{
lcd_display.print(key);
if (input == 0)
input += key - '0';
else
input = input*10 + (key - '0');
// подтверждение ввода числа
if('A' == key)
{
is_input = false;
return input;
}
// отмена ввода числа
if('B' == key)
{
is_input = false;
return 0;
}
if('C' == key)
{
lcd_display.clear();
EEPROM.get(0, memory_data);
input = memory_data.result;
lcd_display.print("From mem: ");
lcd_display.setCursor(0, 1);
lcd_display.print(input);
}
}
}
}
void Reset()
{
bool is_input = true;
lcd_display.clear();
lcd_display.print("Are you sure?");
lcd_display.setCursor(0, 1);
lcd_display.print("A-yes B-no");
while(is_input)
{
noInterrupts();
char key = keypad.get_key();
interrupts();
if (key != '\0')
{
switch (key)
{
case 'A': // подтверждение сброса
is_input = false;
EEPROM.put(0, default_data);
break;
case 'B': // отмена сброса
is_input = false;
return;
break;
}
}
}
}
void initialReset()
{
EEPROM.get(0, memory_data);
if (memory_data.first_number != 0 && memory_data.second_number != 0 && memory_data.result != 0)
{
EEPROM.put(0, default_data);
}
}
void mainMenu()
{
lcd_display.clear();
switch (menu_change)
{
case 0:
lcd_display.print("1) Calculator");
break;
case 1:
lcd_display.print("2) Memory");
lcd_display.setCursor(0, 1);
EEPROM.get(0, memory_data);
lcd_display.print(memory_data.first_number);
lcd_display.print("AND");
lcd_display.print(memory_data.second_number);
lcd_display.print('=');
lcd_display.print(memory_data.result);
break;
case 2:
lcd_display.print("3) Reset");
break;
}
}
void loop()
{
if (keyInterrupt)
{
noInterrupts();
char keyPressed = keypad.get_key();
keyInterrupt = false;
interrupts();
if (keyPressed != '\0')
{
Serial.println(keyPressed);
changeMenu(keyPressed);
}
}
}
// загрузка из памяти (должен
// быть вычитан при старте программы, что бы постаянно не обращаться к ней