Initial commit
This commit is contained in:
commit
58dc9bf8ce
|
@ -0,0 +1,30 @@
|
|||
#include "Arduino.h"
|
||||
#include "Token.h"
|
||||
|
||||
Token::Token(){}
|
||||
|
||||
Token::Token(String d, String t)
|
||||
{
|
||||
data = d;
|
||||
dType = t;
|
||||
}
|
||||
|
||||
String Token::getData()
|
||||
{
|
||||
return data;
|
||||
}
|
||||
|
||||
String Token::getDataType()
|
||||
{
|
||||
return dType;
|
||||
}
|
||||
|
||||
void Token::setData(String d)
|
||||
{
|
||||
data = d;
|
||||
}
|
||||
|
||||
void Token::setDataType(String t)
|
||||
{
|
||||
dType = t;
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
#ifndef Token_h
|
||||
#define Token_h
|
||||
|
||||
#include "Arduino.h"
|
||||
|
||||
class Token
|
||||
{
|
||||
private:
|
||||
String data;
|
||||
String dType;
|
||||
public:
|
||||
Token();
|
||||
Token(String d, String t);
|
||||
String getData();
|
||||
String getDataType();
|
||||
void setData(String d);
|
||||
void setDataType(String t);
|
||||
};
|
||||
|
||||
#endif
|
|
@ -0,0 +1,211 @@
|
|||
/*
|
||||
* LCD Wiring
|
||||
* Pin 1: Ground
|
||||
* Pin 2: +5V
|
||||
* Pin 3: Connect to wiper of potentiometer
|
||||
* Pin 4: RS
|
||||
* Pin 5: RW (Connect to Ground)
|
||||
* Pin 6: EN
|
||||
* Pins 7-10: DB0-DB3 (Unused)
|
||||
* Pin 11: DB4
|
||||
* Pin 12: DB5
|
||||
* Pin 13: DB6
|
||||
* Pin 14: DB7
|
||||
* Pin 15: Backlight (Connect to +5V)
|
||||
* Pin 16: Red
|
||||
* Pin 17: Green
|
||||
* Pin 18: Blue
|
||||
*/
|
||||
|
||||
#include <LiquidCrystal.h>
|
||||
#define RSPIN 13
|
||||
#define ENPIN 12
|
||||
#define DB4PIN 8
|
||||
#define DB5PIN 7
|
||||
#define DB6PIN 6
|
||||
#define DB7PIN 5
|
||||
|
||||
#define REDLIGHT 11
|
||||
#define GREENLIGHT 10
|
||||
#define BLUELIGHT 9
|
||||
|
||||
#include <Keypad.h>
|
||||
#define ROWS 4
|
||||
#define COLS 4
|
||||
|
||||
/* NOTE: program malfunctions if BUFFER is too big---see shunting function */
|
||||
#define BUFFER 16
|
||||
#include "Token.h"
|
||||
|
||||
LiquidCrystal lcd(RSPIN, ENPIN, DB4PIN, DB5PIN, DB6PIN, DB7PIN);
|
||||
|
||||
char keys[ROWS][COLS] = {{'1','2','3','A'},
|
||||
{'4','5','6','B'},
|
||||
{'7','8','9','C'},
|
||||
{'*','0','#','D'}};
|
||||
byte rowPins[ROWS] = {0,1,2,3};
|
||||
byte colPins[COLS] = {A0,A1,A2,A3};
|
||||
Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS);
|
||||
|
||||
void setBacklight(int r, int g, int b)
|
||||
{
|
||||
r = map(r, 0, 255, 255, 0);
|
||||
g = map(g, 0, 255, 255, 0);
|
||||
b = map(b, 0, 255, 255, 0);
|
||||
|
||||
analogWrite(REDLIGHT, r);
|
||||
analogWrite(GREENLIGHT, g);
|
||||
analogWrite(BLUELIGHT, b);
|
||||
}
|
||||
|
||||
bool isNum(char c)
|
||||
{
|
||||
return c == '1' || c == '2' || c == '3' || c == '4' || c == '5' ||
|
||||
c == '6' || c == '7' || c == '8' || c == '9' || c == '0';
|
||||
}
|
||||
|
||||
bool isOp(char c)
|
||||
{
|
||||
return c == '+' || c == '-' || c == '*' || c == '/';
|
||||
}
|
||||
|
||||
void tokenize(String input, Token *store, int *storeLen)
|
||||
{
|
||||
int currLen = 0;
|
||||
for (int i = 0; i < input.length(); i++) {
|
||||
/*
|
||||
* NOTE: When BUFFER is too big, some characters
|
||||
* are seen as a block, so the if statements fail
|
||||
*/
|
||||
if (isNum(input[i])) {
|
||||
/*
|
||||
* Scans input until non-number is read, then adds to
|
||||
* token
|
||||
*/
|
||||
String n;
|
||||
for (int j = i; isNum(input[j]); j++) {
|
||||
n += input[j];
|
||||
i = j;
|
||||
}
|
||||
store[currLen++] = Token(n, "Number");
|
||||
} else if (isOp(input[i])) {
|
||||
store[currLen++] = Token((String)input[i], "Operator");
|
||||
}
|
||||
}
|
||||
|
||||
*storeLen = currLen;
|
||||
}
|
||||
|
||||
void shunting(Token *tokenInput, Token *rpnStore, int len)
|
||||
{
|
||||
int place = 0;
|
||||
Token opStack[BUFFER];
|
||||
int opLen = 0;
|
||||
|
||||
for (int i = 0; i < len; i++) {
|
||||
Token currToken = tokenInput[i];
|
||||
if (currToken.getDataType() == "Number") {
|
||||
rpnStore[place++] = currToken;
|
||||
} else if (currToken.getDataType() == "Operator") {
|
||||
String currOp = currToken.getData();
|
||||
while (opLen > 0) {
|
||||
String topOp = opStack[opLen-1].getData();
|
||||
// These two if statements could be combined
|
||||
if (currOp == "+" || currOp == "-")
|
||||
rpnStore[place++] = opStack[--opLen];
|
||||
else if ((currOp == "*" || currOp == "/") &&
|
||||
(topOp == "*" || topOp == "/"))
|
||||
rpnStore[place++] = opStack[--opLen];
|
||||
else
|
||||
break;
|
||||
}
|
||||
opStack[opLen++] = currToken;
|
||||
}
|
||||
}
|
||||
|
||||
while (opLen > 0)
|
||||
rpnStore[place++] = opStack[--opLen];
|
||||
}
|
||||
|
||||
void calculate(Token *rpnInput, int len)
|
||||
{
|
||||
float numStack[BUFFER];
|
||||
int numStackLen = 0;
|
||||
for (int i = 0; i < len; i++) {
|
||||
Token t = rpnInput[i];
|
||||
if (t.getDataType() == "Number") {
|
||||
numStack[numStackLen++] = t.getData().toFloat();
|
||||
} else {
|
||||
float sNum = numStack[--numStackLen];
|
||||
float fNum = numStack[--numStackLen];
|
||||
if (numStackLen < 0) {
|
||||
lcd.print("ERROR");
|
||||
return;
|
||||
}
|
||||
if (t.getData() == "+")
|
||||
numStack[numStackLen++] = fNum + sNum;
|
||||
else if (t.getData() == "-")
|
||||
numStack[numStackLen++] = fNum - sNum;
|
||||
else if (t.getData() == "*")
|
||||
numStack[numStackLen++] = fNum * sNum;
|
||||
else if (t.getData() == "/")
|
||||
numStack[numStackLen++] = fNum / sNum;
|
||||
}
|
||||
}
|
||||
|
||||
lcd.print(numStack[0]);
|
||||
}
|
||||
|
||||
void getAns(String s)
|
||||
{
|
||||
Token parsedInput[BUFFER];
|
||||
Token rpnParsedInput[BUFFER];
|
||||
int inputLen;
|
||||
|
||||
tokenize(s, parsedInput, &inputLen);
|
||||
shunting(parsedInput, rpnParsedInput, inputLen);
|
||||
calculate(rpnParsedInput, inputLen);
|
||||
}
|
||||
|
||||
void setup()
|
||||
{
|
||||
lcd.begin(16, 2);
|
||||
pinMode(REDLIGHT, OUTPUT);
|
||||
pinMode(GREENLIGHT, OUTPUT);
|
||||
pinMode(BLUELIGHT, OUTPUT);
|
||||
setBacklight(0, 128, 64);
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
static String expr = "";
|
||||
|
||||
char keypress = keypad.waitForKey();
|
||||
switch (keypress) {
|
||||
case '#':
|
||||
lcd.setCursor(0,1);
|
||||
getAns(expr);
|
||||
|
||||
keypad.waitForKey();
|
||||
case '*':
|
||||
expr = "";
|
||||
break;
|
||||
case 'A':
|
||||
expr += '/';
|
||||
break;
|
||||
case 'B':
|
||||
expr += '*';
|
||||
break;
|
||||
case 'C':
|
||||
expr += '-';
|
||||
break;
|
||||
case 'D':
|
||||
expr += '+';
|
||||
break;
|
||||
default:
|
||||
expr += keypress;
|
||||
break;
|
||||
}
|
||||
lcd.clear();
|
||||
lcd.print(expr);
|
||||
}
|
Loading…
Reference in New Issue