Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // Configuration
- #define DEBUG true // Print debug messages to Serial?
- #define LCD_COLS 16 // How many columns does the LCD display have?
- #define LCD_ROWS 2 // How many rows does the LCD display have?
- #define KEYPAD_ROWS 4
- #define KEYPAD_COLS 4
- char keys[KEYPAD_ROWS][KEYPAD_COLS] = {
- {'+','*','!','A'},
- {'^','0','1','B'},
- {'a','(','b','C'},
- {'s',')','d','D'}
- };
- byte rowPins[KEYPAD_ROWS] = {12, 11, 10, 9};
- byte colPins[KEYPAD_COLS] = {8, 7, 6, 5};
- #define RESULT_PRECISION 8
- #define RESULT_MAX_SIZE 64
- #include "ShrunkLiquidCrystal.h"
- #include "Keypad.h"
- // Initialize the LCD object with the appropriate pins
- ShrunkLiquidCrystal lcd;
- // Initialize the keypad with the appropriate data
- Keypad customKeypad = Keypad(makeKeymap(keys), rowPins, colPins);
- /* Writing stuff */
- char buffer[200]; // Contiene l'espressione letta dal parser
- int posizione;
- #define MAXOPSTACK 64
- #define MAXNUMSTACK 64
- char counter = 'a' - 1;
- char eval_not(char a1, char a2) {
- lcd.setCursor(0,1);
- lcd.write(" ");
- lcd.setCursor(0,1);
- counter++;
- lcd.write(counter);
- lcd.write(" = !");
- lcd.write(a1);
- for(;!customKeypad.getKey();){}
- delay(50);
- return counter;
- }
- char eval_or(char a1, char a2) {
- lcd.setCursor(0,1);
- lcd.write(" ");
- lcd.setCursor(0,1);
- counter++;
- lcd.write(counter);
- lcd.write(" = ");
- lcd.write(a1);
- lcd.write(" + ");
- lcd.write(a2);
- for(;!customKeypad.getKey();){}
- delay(50);
- return counter;
- }
- char eval_and(char a1, char a2) {
- lcd.setCursor(0,1);
- lcd.write(" ");
- lcd.setCursor(0,1);
- counter++;
- lcd.write(counter);
- lcd.write(" = ");
- lcd.write(a1);
- lcd.write(" * ");
- lcd.write(a2);
- for(;!customKeypad.getKey();){}
- delay(50);
- return counter;
- }
- char eval_xor(char a1, char a2) {
- lcd.setCursor(0,1);
- lcd.write(" ");
- lcd.setCursor(0,1);
- counter++;
- lcd.write(counter);
- lcd.write(" = ");
- lcd.write(a1);
- lcd.write(" + ");
- lcd.write(a2);
- for(;!customKeypad.getKey();){}
- delay(50);
- return counter;
- }
- struct op_s {
- char op;
- int prec;
- int unary;
- char (*eval)(char a1, char a2);
- } ops[]={
- {'!', 9, 1, eval_not},
- {'*', 8, 0, eval_and},
- {'^', 8, 0, eval_xor},
- {'+', 7, 0, eval_or},
- {'(', 0, 0, NULL},
- {')', 0, 0, NULL}
- };
- struct op_s *getop(char ch)
- {
- int i;
- for(i=0; i<sizeof ops/sizeof ops[0]; ++i) {
- if(ops[i].op==ch) return ops+i;
- }
- return NULL;
- }
- struct op_s *opstack[MAXOPSTACK];
- int nopstack=0;
- char numstack[MAXNUMSTACK];
- int nnumstack=0;
- void push_opstack(struct op_s *op)
- {
- if(nopstack>MAXOPSTACK-1) {
- //(stderr, "ERROR: Operator stack overflow\n");
- return;
- }
- opstack[nopstack++]=op;
- }
- struct op_s *pop_opstack()
- {
- if(!nopstack) {
- //(stderr, "ERROR: Operator stack empty\n");
- exit('0');
- }
- return opstack[--nopstack];
- }
- void push_numstack(char c) {
- if(nnumstack>MAXNUMSTACK-1) {
- //(stderr, "ERROR: Number stack overflow\n");
- return;
- }
- numstack[nnumstack++]=c;
- }
- int pop_numstack()
- {
- if(!nnumstack) {
- //(stderr, "ERROR: Number stack empty\n");
- exit('0');
- }
- return numstack[--nnumstack];
- }
- void shunt_op(struct op_s *op)
- {
- struct op_s *pop;
- int n1, n2;
- if(op->op=='(') {
- push_opstack(op);
- return;
- } else if(op->op==')') {
- while(nopstack>0 && opstack[nopstack-1]->op!='(') {
- pop=pop_opstack();
- n1=pop_numstack();
- if(pop->unary) push_numstack(pop->eval(n1, 0));
- else {
- n2=pop_numstack();
- push_numstack(pop->eval(n2, n1));
- }
- }
- if(!(pop=pop_opstack()) || pop->op!='(') {
- //(stderr, "ERROR: Stack error. No matching \'(\'\n");
- return;
- }
- return;
- }
- while(nopstack && op->prec<=opstack[nopstack-1]->prec) {
- pop=pop_opstack();
- n1=pop_numstack();
- if(pop->unary) push_numstack(pop->eval(n1, 0));
- else {
- n2=pop_numstack();
- push_numstack(pop->eval(n2, n1));
- }
- }
- push_opstack(op);
- }
- int is_valid_char(char c) {
- return (c >= 'A' && c <= 'D') || (c == '0') || (c == '1');
- }
- void eval(char buffer[200]) {
- char *expr;
- char *tstart=NULL;
- struct op_s startop={'X', 0, 0, NULL}; /* Dummy operator to mark start */
- struct op_s *op=NULL;
- int n1, n2;
- struct op_s *lastop=&startop;
- for(expr=buffer; *expr; ++expr) {
- if(!tstart) {
- if((op=getop(*expr))) {
- if(lastop && (lastop==&startop || lastop->op!=')')) {
- if(op->op=='!') op=getop('!');
- else if(op->op!='(') {
- //(stderr, "ERROR: Illegal use of binary operator (%c)\n", op->op);
- return;
- }
- }
- shunt_op(op);
- lastop=op;
- } else if(is_valid_char(*expr)) tstart=expr;
- else if(!isspace(*expr)) {
- //(stderr, "ERROR: Syntax error at expr %c\n", *expr);
- }
- } else {
- if(isspace(*expr)) {
- push_numstack(*tstart);
- tstart=NULL;
- lastop=NULL;
- } else if((op=getop(*expr))) {
- push_numstack(*tstart);
- tstart=NULL;
- shunt_op(op);
- lastop=op;
- } else if(!is_valid_char(*expr)) {
- //(stderr, "ERROR: Syntax error at char %c\n", *expr);
- }
- }
- }
- if(tstart) push_numstack(*tstart);
- while(nopstack) {
- op=pop_opstack();
- n1=pop_numstack();
- lcd.setCursor(0,1);
- lcd.write(" ");
- lcd.setCursor(0,1);
- if(op->unary) push_numstack(op->eval(n1, 0));
- else {
- n2=pop_numstack();
- push_numstack(op->eval(n2, n1));
- }
- for(;!customKeypad.getKey();){}
- delay(50);
- }
- if(nnumstack!=1) {
- //(stderr, "ERROR: Number stack has %d elements after evaluation. Should be 1.\n", nnumstack);
- return;
- }
- return;
- }
- /* Setup the serial interfaces and the pushbutton pins */
- void setup () {
- #if DEBUG
- // Enable the Serial interface for sending debug messages
- Serial.begin (9600);
- #endif
- posizione = 0;
- lcd.print("Ready!");
- }
- /* Appropriately print an expression to the LCD display (deals with autoscroll and stuff) */
- void printExpr() {
- #if DEBUG
- Serial.print("Printing ");
- Serial.println(buffer);
- #endif
- lcd.print(buffer);
- if(strlen(buffer) > LCD_COLS - 1) { // If the text is longer than the whole screen
- #if DEBUG
- Serial.println("Autoscrolling");
- #endif
- for (int i = 0; i <= 200 - LCD_COLS; i++) {
- lcd.scrollDisplayLeft(); // Scroll left exactly expression.length() - LCD_COLS times
- }
- }
- }
- void loop () {
- const char key = customKeypad.getKey();
- bool printExpression = true;
- bool clearScreen = true;
- if (key) {
- /* Custom keypress behaviour */
- switch (key) {
- case '+':
- case '*':
- case '!':
- case '^':
- case '0':
- case '1':
- case 'A':
- case 'B':
- case 'C':
- case 'D':
- case '(':
- case ')':
- buffer[posizione++] += key;
- break;
- case 'a':
- printExpression = false;
- clearScreen = false;
- lcd.scrollDisplayRight(); // That's *right*, it's not a typo. This is what the users perceive as "natural" scrolling.
- break;
- case 's':
- printExpression = false;
- clearScreen = false;
- lcd.setCursor(0, 1);
- #if DEBUG
- Serial.print("Infix: ");
- Serial.println(buffer);
- #endif
- eval(buffer);
- counter = 'a' - 1;
- {
- int i;
- for(i=0;i<200;i++) buffer[i]='\0';
- }
- posizione = 0;
- break;
- case 'b':
- printExpression = false;
- clearScreen = false;
- lcd.scrollDisplayLeft();
- break;
- case 'd':
- if (posizione != 0) buffer[--posizione] = '\0';
- else buffer[posizione] = '\0';
- break;
- }
- if (clearScreen == true) {
- lcd.clear();
- }
- if (printExpression == true) {
- lcd.setCursor(0, 0);
- printExpr();
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement