#include <LiquidCrystal_I2C.h> //Header file for LCD from https://www.arduino.cc/en/Reference/LiquidCrystal
#include <Wire.h>
#include <Keypad.h>
#define ENCODER_CLK 10
#define ENCODER_DT 9
#define ENCODER_BTN 8
const uint8_t ROWS = 4;
const uint8_t COLS = 4;
char keys[ROWS][COLS] = {
{ '1', '2', '3', '+' },
{ '4', '5', '6', '-' },
{ '7', '8', '9', '.' },
{ '*', '0', '/', '=' }
};
uint8_t colPins[COLS] = { 4, 5, 6, 7 }; // Pins connected to C1, C2, C3, C4
uint8_t rowPins[ROWS] = { 0, 1, 2, 3 }; // Pins connected to R1, R2, R3, R4
Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS);
LiquidCrystal_I2C lcd(0x27, 16, 2);
int counter = 0;
void setup() {
pinMode(ENCODER_CLK, INPUT);
pinMode(ENCODER_DT, INPUT);
pinMode(ENCODER_BTN, INPUT_PULLUP);
//attachInterrupt(digitalPinToInterrupt(ENCODER_CLK), readEncoder, FALLING);
lcd.init();
lcd.backlight();
Serial.begin(10000);
}
int state = 1; // 1: input needs to be a num, 2: anything
char numbers[6][15] = {"","","","","",""}; // 6 possible operands with a max length of 15 digits
int numInd = 0; // which number are we inputting right now
char operation[5] = {'e','e','e','e','e'}; // max 5 operations, e = empty
double result[6] = {0.0,0.0,0.0,0.0,0.0,0.0};
int newInd = 0; // index of new digit
int lastClk = HIGH;
void clearAll(){
state = 1; // 1: input needs to be a num, 2: anything
memset(numbers[0],0,sizeof(numbers[0]));
memset(numbers[1],0,sizeof(numbers[1]));
memset(numbers[2],0,sizeof(numbers[2]));
memset(numbers[3],0,sizeof(numbers[3]));
memset(numbers[4],0,sizeof(numbers[4]));
memset(numbers[5],0,sizeof(numbers[5]));
numInd = 0; // which number are we inputting right now
memset(operation,'e',sizeof(operation));
newInd = 0; // index of new digit
lcd.setCursor(0,0);
}
void loop() {
int newClk = digitalRead(ENCODER_CLK);
if (newClk != lastClk) {
// There was a change on the CLK pin
lastClk = newClk;
int dtValue = digitalRead(ENCODER_DT);
if (newClk == LOW && dtValue == HIGH) {
Serial.println("Rotated clockwise ⏩");
}
if (newClk == LOW && dtValue == LOW) {
Serial.println("Rotated counterclockwise ⏪");
}
}
char key = keypad.getKey();
if (key != NO_KEY) {
switch(key){
case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9':
switch(state){
case 1:
if(numInd == 0){
lcd.clear();
}
numbers[numInd][0] = key;
lcd.print(key);
newInd = 1;
state = 2;
break;
case 2:
numbers[numInd][newInd] = key;
lcd.print(key);
newInd++;
break;
}
break;
case '.':
switch(state){
case 1:
break;
case 2:
if (strchr(numbers[numInd], '.') == NULL) { //checks if the dot is already used for the second num
numbers[numInd][newInd] = key;
lcd.print(key);
newInd++;
}
break;
}
break;
case '+': case '-': case '*': case '/':
switch(state){
case 1:
break;
case 2:
operation[numInd] = key;
lcd.print(key);
numInd++;
newInd = 0;
state = 1;
break;
}
break;
case '=':
switch(state){
case 1:
break;
case 2:
if ((numInd > 0) && (newInd > 0)){ // only if we can calculate a result
for (int i = 0; i <= numInd; i++) { // Convert number strings to doubles
result[i] = strtod(numbers[i], (char **)NULL);
}
for (int phase = 0; phase < 2; phase++) { // 0 means multiplication phase, 1 means sum phase
for (int i = 0; i < numInd; i++) { // loop through operations
double firstnum = result[i];
double secondnum = result[i+1];
double newResult = 0.0;
switch(phase){
case 0: // we only multiply and divide in phase 0
switch(operation[i]){
case '*':
newResult = firstnum * secondnum;
result[i] = newResult;
result[i+1] = newResult;
// This following section updates results
if (i < numInd){ // avoid going over list bounds
for (int j = i+1; j <= numInd; j++) {
if (operation[j] == 'e'){
result[j+1] = newResult;
}
else{
break;
}
}
}
if (i > 0){
for (int j = i-1; j >= 0; j--) {
if (operation[j] == 'e'){
result[j] = newResult;
}
else{
break;
}
}
}
operation[i] = 'e'; // this operation has been calculated
break;
case '/':
newResult = firstnum / secondnum;
result[i] = newResult;
result[i+1] = newResult;
// This following section updates results
if (i < numInd){ // avoid going over list bounds
for (int j = i+1; j <= numInd; j++) {
if (operation[j] == 'e'){
result[j+1] = newResult;
}
else{
break;
}
}
}
if (i > 0){
for (int j = i-1; j >= 0; j--) {
if (operation[j] == 'e'){
result[j] = newResult;
}
else{
break;
}
}
}
operation[i] = 'e'; // this operation has been calculated
break;
}
break;
case 1: // we only add and subtract in phase 1
switch(operation[i]){
case '+':
newResult = firstnum + secondnum;
result[i] = newResult;
result[i+1] = newResult;
// This following section updates results
if (i < numInd){ // avoid going over list bounds
for (int j = i+1; j <= numInd; j++) {
if (operation[j] == 'e'){
result[j+1] = newResult;
}
else{
break;
}
}
}
if (i > 0){
for (int j = i-1; j >= 0; j--) {
if (operation[j] == 'e'){
result[j] = newResult;
}
else{
break;
}
}
}
operation[i] = 'e'; // this operation has been calculated
break;
case '-':
newResult = firstnum - secondnum;
result[i] = newResult;
result[i+1] = newResult;
// This following section updates results
if (i < numInd){ // avoid going over list bounds
for (int j = i+1; j <= numInd; j++) {
if (operation[j] == 'e'){
result[j+1] = newResult;
}
else{
break;
}
}
}
if (i > 0){
for (int j = i-1; j >= 0; j--) {
if (operation[j] == 'e'){
result[j] = newResult;
}
else{
break;
}
}
}
operation[i] = 'e'; // this operation has been calculated
break;
}
break;
}
}
}
/**
double firstnum = strtod(numbers[0], (char **)NULL);
double secondnum = strtod(numbers[1], (char **)NULL);
switch(operation){
case '+':
result = firstnum + secondnum;
break;
case '-':
result = firstnum - secondnum;
break;
case '*':
result = firstnum * secondnum;
break;
case '/':
result = firstnum / secondnum;
break;
}
**/
lcd.setCursor(0, 1);
lcd.print('=');
lcd.print(String(result[0]));
clearAll();
break;
}
}
break;
}
}
}
/**
switch(state){
case 1:
firstnum = double(int(key - '0'));
lcd.setCursor(0, 0);
lcd.print(key);
Serial.print(firstnum);
state++;
break;
case 2:
operation = key;
//Serial.print("2");
lcd.print(key);
state++;
break;
case 3:
secondnum = double(int(key - '0'));
Serial.print(secondnum);
lcd.print(key);
lcd.print('=');
switch(operation){
case '+':
result = firstnum + secondnum;
break;
case '-':
result = firstnum - secondnum;
break;
case '*':
result = firstnum * secondnum;
break;
case '/':
result = firstnum / secondnum;
break;
}
lcd.print(String(result));
state = 1;
break;
}
}
**/
//lcd.setCursor(0, 0);
//lcd.print(counter);
//if (digitalRead(ENCODER_BTN) == LOW) {
//lcd.setCursor(1, 1);
//lcd.print("press");
//} else {
//lcd.setCursor(1, 1);
//lcd.print(" no ");
//}
//delay(100);