Advertisement
Guest User

Untitled

a guest
Nov 27th, 2014
139
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 10.28 KB | None | 0 0
  1. // Configuration
  2. #define DEBUG         true    // Print debug messages to Serial?
  3. #define LCD_COLS      16  // How many columns does the LCD display have?
  4. #define LCD_ROWS      2  // How many rows does the LCD display have?
  5. #define KEYPAD_ROWS   4
  6. #define KEYPAD_COLS   4
  7. char keys[KEYPAD_ROWS][KEYPAD_COLS] = {
  8.     {'+','*','!','A'},
  9.     {'^','0','1','B'},
  10.     {'a','(','b','C'},
  11.     {'s',')','d','D'}
  12. };
  13. byte rowPins[KEYPAD_ROWS] = {12, 11, 10, 9};
  14. byte colPins[KEYPAD_COLS] = {8, 7, 6, 5};
  15. #define RESULT_PRECISION 8
  16. #define RESULT_MAX_SIZE 64
  17.  
  18. #include "ShrunkLiquidCrystal.h"
  19. #include "Keypad.h"
  20.  
  21. // Initialize the LCD object with the appropriate pins
  22. ShrunkLiquidCrystal lcd;
  23. // Initialize the keypad with the appropriate data
  24. Keypad customKeypad = Keypad(makeKeymap(keys), rowPins, colPins);
  25.  
  26. /* Writing stuff */
  27. char buffer[200];                       // Contiene l'espressione letta dal parser
  28. int posizione;
  29.  
  30. #define MAXOPSTACK 64
  31. #define MAXNUMSTACK 64
  32.  
  33. char counter = 'a' - 1;
  34.  
  35. char eval_not(char a1, char a2) {
  36.         lcd.setCursor(0,1);
  37.         lcd.write("                ");
  38.         lcd.setCursor(0,1);
  39.         counter++;
  40.         lcd.write(counter);
  41.         lcd.write(" = !");
  42.         lcd.write(a1);
  43.         for(;!customKeypad.getKey();){}
  44.         delay(50);
  45.         return counter;
  46. }
  47. char eval_or(char a1, char a2) {
  48.         lcd.setCursor(0,1);
  49.         lcd.write("                ");
  50.         lcd.setCursor(0,1);
  51.         counter++;
  52.         lcd.write(counter);
  53.         lcd.write(" = ");
  54.         lcd.write(a1);
  55.         lcd.write(" + ");
  56.         lcd.write(a2);
  57.         for(;!customKeypad.getKey();){}
  58.         delay(50);
  59.         return counter;
  60. }
  61. char eval_and(char a1, char a2) {
  62.         lcd.setCursor(0,1);
  63.         lcd.write("                ");
  64.         lcd.setCursor(0,1);
  65.         counter++;
  66.         lcd.write(counter);
  67.         lcd.write(" = ");
  68.         lcd.write(a1);
  69.         lcd.write(" * ");
  70.         lcd.write(a2);
  71.         for(;!customKeypad.getKey();){}
  72.         delay(50);
  73.         return counter;
  74. }
  75. char eval_xor(char a1, char a2) {
  76.         lcd.setCursor(0,1);
  77.         lcd.write("                ");
  78.         lcd.setCursor(0,1);
  79.         counter++;
  80.         lcd.write(counter);
  81.         lcd.write(" = ");
  82.         lcd.write(a1);
  83.         lcd.write(" + ");
  84.         lcd.write(a2);
  85.         for(;!customKeypad.getKey();){}
  86.         delay(50);
  87.         return counter;
  88. }
  89.  
  90. struct op_s {
  91.         char op;
  92.         int prec;
  93.         int unary;
  94.         char (*eval)(char a1, char a2);
  95. } ops[]={
  96.         {'!', 9, 1, eval_not},
  97.         {'*', 8, 0, eval_and},
  98.         {'^', 8, 0, eval_xor},
  99.         {'+', 7, 0, eval_or},
  100.         {'(', 0, 0, NULL},
  101.         {')', 0, 0, NULL}
  102. };
  103.  
  104. struct op_s *getop(char ch)
  105. {
  106.         int i;
  107.         for(i=0; i<sizeof ops/sizeof ops[0]; ++i) {
  108.                 if(ops[i].op==ch) return ops+i;
  109.         }
  110.         return NULL;
  111. }
  112.  
  113. struct op_s *opstack[MAXOPSTACK];
  114. int nopstack=0;
  115.  
  116. char numstack[MAXNUMSTACK];
  117. int nnumstack=0;
  118.  
  119. void push_opstack(struct op_s *op)
  120. {
  121.         if(nopstack>MAXOPSTACK-1) {
  122.                 //(stderr, "ERROR: Operator stack overflow\n");
  123.                 return;
  124.         }
  125.         opstack[nopstack++]=op;
  126. }
  127.  
  128. struct op_s *pop_opstack()
  129. {
  130.         if(!nopstack) {
  131.                 //(stderr, "ERROR: Operator stack empty\n");
  132.                 exit('0');
  133.         }
  134.         return opstack[--nopstack];
  135. }
  136.  
  137. void push_numstack(char c) {
  138.         if(nnumstack>MAXNUMSTACK-1) {
  139.                 //(stderr, "ERROR: Number stack overflow\n");
  140.                 return;
  141.         }
  142.         numstack[nnumstack++]=c;
  143. }
  144.  
  145. int pop_numstack()
  146. {
  147.         if(!nnumstack) {
  148.                 //(stderr, "ERROR: Number stack empty\n");
  149.                 exit('0');
  150.         }
  151.         return numstack[--nnumstack];
  152. }
  153.  
  154.  
  155. void shunt_op(struct op_s *op)
  156. {
  157.         struct op_s *pop;
  158.         int n1, n2;
  159.         if(op->op=='(') {
  160.                 push_opstack(op);
  161.                 return;
  162.         } else if(op->op==')') {
  163.                 while(nopstack>0 && opstack[nopstack-1]->op!='(') {
  164.                         pop=pop_opstack();
  165.                         n1=pop_numstack();
  166.                         if(pop->unary) push_numstack(pop->eval(n1, 0));
  167.                         else {
  168.                                 n2=pop_numstack();
  169.                                 push_numstack(pop->eval(n2, n1));
  170.                         }
  171.                 }
  172.                 if(!(pop=pop_opstack()) || pop->op!='(') {
  173.                         //(stderr, "ERROR: Stack error. No matching \'(\'\n");
  174.                         return;
  175.                 }
  176.                 return;
  177.         }
  178.  
  179.         while(nopstack && op->prec<=opstack[nopstack-1]->prec) {
  180.                 pop=pop_opstack();
  181.                 n1=pop_numstack();
  182.                 if(pop->unary) push_numstack(pop->eval(n1, 0));
  183.                 else {
  184.                         n2=pop_numstack();
  185.                         push_numstack(pop->eval(n2, n1));
  186.                 }
  187.         }
  188.         push_opstack(op);
  189. }
  190.  
  191. int is_valid_char(char c) {
  192.         return (c >= 'A' && c <= 'D') || (c == '0') || (c == '1');
  193. }
  194.  
  195. void eval(char buffer[200]) {
  196.         char *expr;
  197.         char *tstart=NULL;
  198.         struct op_s startop={'X', 0, 0, NULL};  /* Dummy operator to mark start */
  199.         struct op_s *op=NULL;
  200.         int n1, n2;
  201.         struct op_s *lastop=&startop;
  202.  
  203.         for(expr=buffer; *expr; ++expr) {
  204.                 if(!tstart) {
  205.  
  206.                         if((op=getop(*expr))) {
  207.                                 if(lastop && (lastop==&startop || lastop->op!=')')) {
  208.                                         if(op->op=='!') op=getop('!');
  209.                                         else if(op->op!='(') {
  210.                                                 //(stderr, "ERROR: Illegal use of binary operator (%c)\n", op->op);
  211.                                                 return;
  212.                                         }
  213.                                 }
  214.                                 shunt_op(op);
  215.                                 lastop=op;
  216.                         } else if(is_valid_char(*expr)) tstart=expr;
  217.                         else if(!isspace(*expr)) {
  218.                                 //(stderr, "ERROR: Syntax error at expr %c\n", *expr);
  219.                         }
  220.                 } else {
  221.                         if(isspace(*expr)) {
  222.                                 push_numstack(*tstart);
  223.                                 tstart=NULL;
  224.                                 lastop=NULL;
  225.                         } else if((op=getop(*expr))) {
  226.                                 push_numstack(*tstart);
  227.                                 tstart=NULL;
  228.                                 shunt_op(op);
  229.                                 lastop=op;
  230.                         } else if(!is_valid_char(*expr)) {
  231.                                 //(stderr, "ERROR: Syntax error at char %c\n", *expr);
  232.                         }
  233.                 }
  234.         }
  235.         if(tstart) push_numstack(*tstart);
  236.  
  237.         while(nopstack) {
  238.                 op=pop_opstack();
  239.                 n1=pop_numstack();
  240.                 lcd.setCursor(0,1);
  241.                 lcd.write("                ");
  242.                 lcd.setCursor(0,1);
  243.                 if(op->unary) push_numstack(op->eval(n1, 0));
  244.                 else {
  245.                         n2=pop_numstack();
  246.                         push_numstack(op->eval(n2, n1));
  247.                 }
  248.                 for(;!customKeypad.getKey();){}
  249.                 delay(50);
  250.         }
  251.         if(nnumstack!=1) {
  252.                 //(stderr, "ERROR: Number stack has %d elements after evaluation. Should be 1.\n", nnumstack);
  253.                 return;
  254.         }
  255.         return;
  256. }
  257.  
  258. /* Setup the serial interfaces and the pushbutton pins */
  259. void setup () {
  260.     #if DEBUG
  261.         // Enable the Serial interface for sending debug messages
  262.         Serial.begin (9600);
  263.     #endif
  264.         posizione = 0;
  265.     lcd.print("Ready!");
  266. }
  267.  
  268. /* Appropriately print an expression to the LCD display (deals with autoscroll and stuff) */
  269. void printExpr() {
  270.     #if DEBUG
  271.         Serial.print("Printing ");
  272.         Serial.println(buffer);
  273.     #endif
  274.  
  275.     lcd.print(buffer);
  276.  
  277.       if(strlen(buffer) > LCD_COLS - 1) { // If the text is longer than the whole screen
  278.         #if DEBUG
  279.             Serial.println("Autoscrolling");
  280.         #endif
  281.         for (int i = 0; i <= 200 - LCD_COLS; i++) {
  282.             lcd.scrollDisplayLeft(); // Scroll left exactly expression.length() - LCD_COLS times
  283.         }
  284.     }
  285. }
  286.  
  287. void loop () {
  288.     const char key = customKeypad.getKey();
  289.     bool printExpression = true;
  290.     bool clearScreen = true;
  291.  
  292.     if (key) {
  293.         /* Custom keypress behaviour */
  294.         switch (key) {
  295.                         case '+':
  296.                         case '*':
  297.                         case '!':
  298.                         case '^':
  299.             case '0':
  300.                         case '1':
  301.                         case 'A':
  302.                         case 'B':
  303.                         case 'C':
  304.                         case 'D':
  305.                         case '(':
  306.                         case ')':
  307.                           buffer[posizione++] += key;
  308.                           break;
  309.                         case 'a':
  310.                           printExpression = false;
  311.               clearScreen = false;
  312.               lcd.scrollDisplayRight(); // That's *right*, it's not a typo. This is what the users perceive as "natural" scrolling.
  313.                           break;
  314.             case 's':
  315.                           printExpression = false;
  316.               clearScreen = false;
  317.  
  318.               lcd.setCursor(0, 1);
  319.  
  320.               #if DEBUG
  321.                 Serial.print("Infix: ");
  322.                 Serial.println(buffer);
  323.               #endif
  324.               eval(buffer);
  325.                           counter = 'a' - 1;
  326.                           {
  327.                             int i;
  328.                             for(i=0;i<200;i++) buffer[i]='\0';
  329.                           }
  330.                           posizione = 0;
  331.               break;
  332.             case 'b':
  333.               printExpression = false;
  334.               clearScreen = false;
  335.               lcd.scrollDisplayLeft();
  336.                           break;
  337.             case 'd':
  338.                           if (posizione != 0) buffer[--posizione] = '\0';
  339.                           else buffer[posizione] = '\0';
  340.                           break;
  341.         }
  342.  
  343.         if (clearScreen == true) {
  344.             lcd.clear();
  345.         }
  346.  
  347.         if (printExpression == true) {
  348.             lcd.setCursor(0, 0);
  349.             printExpr();
  350.         }
  351.     }
  352. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement