#include #include #include #include #include #include // PS/2 keyboard variables unsigned char disp_buffer[40],r_buffer[40],t_buffer[40],command[20]; unsigned char r_char,r_ready,t_char,t_ready,r_index,t_index; unsigned char graph_command[12][20]; unsigned char kybd_index,kybd_bits[11],kybd_ready,kybd_bit_ready,key_pressed,flush_kybd_bits; unsigned char keyboard_in[20],kybd_in_index; unsigned char i,j,k; int temp,temp2,temp3,temp4; unsigned char stemp,stemp2; unsigned char lcdx,lcdy; // Graphing calculator state machine variables unsigned char calcState; #define Limbo 0 #define ClearScreen 1 #define Calculating 2 #define Statistics 3 #define StatisticsPrep 4 #define StatisticsCalc 5 #define Graphing 6 #define Xmin 7 #define Xmax 8 #define Ymin 9 #define Ymax 10 #define GraphReady 11 #define Graphing2 12 #define GraphReady2 13 unsigned char equation[20],equation_copy[20]; unsigned char neg_flag; int xmin,xmax,ymin,ymax,xdiff; long graph_pt[128]; int graph_color[11] = {0x6E,137,252,128,236,224,227,34,31,30,28}; unsigned char graph_color_index=0; int xvar; int stats_array[5] = {0,0,0,0,0}; int stats_array2[5] = {0,0,0,0,0}; unsigned char remainder; // LCD variables #define Lmargin 5 #define Tmargin 5 #define Cshift 6 #define Vshift 8 // declaring some functions void initialize(void); void LCDInit(void); int doMath(int var1, int var2, unsigned char func); int doCalculation(unsigned char equation[20]); int fixInt(unsigned char in); unsigned char fixChar(int in); // PS/2 keyboard scan code tables unsigned char scan_code[65] = { 0x1C, //A 0x32, //B 0x21, //C 0x23, //D 0x24, //E 0x2B, //F 0x34, //G 0x33, //H 0x43, //I 0x3B, //J 0x42, //K 0x4B, //L 0x3A, //M 0x31, //N 0x44, //O 0x4D, //P 0x15, //Q 0x2D, //R 0x1B, //S 0x2C, //T 0x3C, //U 0x2A, //V 0x1D, //W 0x22, //X 0x35, //Y 0x1A, //Z 0x45, //0 0x16, //1 0x1E, //2 0x26, //3 0x25, //4 0x2E, //5 0x36, //6 0x3D, //7 0x3E, //8 0x46, //9 0x4E, //- 0x55, //= 0x66, //bksp 0x29, //space 0x5A, //enter 0x49, //. 0x4A, /// 0x7C, //KP * 0x7B, //KP - 0x79, //KP + 0x71, //KP . 0x70, //KP 0 0x69, //KP 1 0x72, //KP 2 0x7A, //KP 3 0x6B, //KP 4 0x73, //KP 5 0x74, //KP 6 0x6C, //KP 7 0x75, //KP 8 0x7D, //KP 9 0xF0 //break_code }; char key_code[65] = { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '-', '=', 'B', ' ', 'E', '.', '/', '*', '-', '+', '.', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'X' }; // Load of LCD functions #define begin { #define end } #include // the interrupt routine interrupt [TIM0_COMP] void timer0_comp(void) begin // counts by 10us // polls PORTA for the keyboard input // PORTA.2 is clock // PORTA.3 is data // keyboard clock speed is between 60-100us if (PINA.2 == 0) { // if the clock falls to low if ((kybd_ready == 0) && (kybd_bit_ready == 1)) kybd_bits[kybd_index++] = PINA.3; kybd_bit_ready = 0; // don't read the same keyboard bit again } else { // clock is on high side again kybd_bit_ready = 1; } if (kybd_index >= 11) { kybd_ready = 1; kybd_index = 0; } end // start the program! void main(void) begin LCDInit(); initialize(); while(1) { if (kybd_ready == 1) { // output the keyboard input to the LCD temp = 0; for (i=0;i<8;i++) { temp = temp << 1 | kybd_bits[8-i]; // read in the 8-bit scan code (flip the LSB to MSB order) } for (i=0;i<65;i++) { if (temp==scan_code[i]) { key_pressed = key_code[i]; break; } // look up the scan code in the table } if (temp == 0xF0) { // found a break code, skip the next set flush_kybd_bits = 1; } else if ((i != 65) && (flush_kybd_bits == 0) && (key_pressed != 'E')) { // a regular key was pressed if (lcdx > 123) { // if it reaches the bottom of the screen, clear the entire screen clear_LCD(); lcdx = Tmargin; } else if (key_pressed == 'B') { // backspace keyboard_in[--kybd_in_index] = ''; // erase the latest character LCD_unsay(lcdx,lcdy); // erase the character off the LCD lcdy = lcdy - Cshift; } else if ((calcState == Calculating) && (kybd_in_index == 0) && ((key_pressed == '+') || (key_pressed == '-') || (key_pressed == '*') || (key_pressed == '/') || (key_pressed == '^'))) { sprintf(keyboard_in,"%d",temp2); while (keyboard_in[kybd_in_index] != '') { kybd_in_index++; } keyboard_in[kybd_in_index++] = key_pressed; LCD_say(keyboard_in,lcdx,lcdy); lcdy = lcdy + Cshift*kybd_in_index; } else { keyboard_in[kybd_in_index++] = key_pressed; sprintf(disp_buffer,"%c",key_pressed); LCD_say(disp_buffer,lcdx,lcdy); lcdy = lcdy + Cshift; } } else if ((flush_kybd_bits == 1) && (key_pressed == 'E')) { // quick fix for double-enter scan code reading key_pressed = ''; flush_kybd_bits = 0; } else { flush_kybd_bits = 0; } kybd_ready = 0; // don't output any keyboard bits until a full 11-set has been clocked in again } // start the calculator!! if (key_pressed == 'E') { sscanf(keyboard_in,"%s",command); // parse the incoming command if (strcmp(command,graph_command[0]) == 0) { // The command entered was "graph" calcState = Graphing; } else if (strcmp(command,graph_command[1]) == 0) { // The command entered was "clear" calcState = ClearScreen; } else if (strcmp(command,graph_command[2]) == 0) { // The command entered was "stats" calcState = Statistics; } else if ((keyboard_in[0] == 'y') && ((calcState == GraphReady) || (calcState == GraphReady2))) { // layering on a second equation calcState = Graphing2; } else if (calcState < Statistics) { calcState = Calculating; } // defaults to scientific calculator switch (calcState) { case ClearScreen: clear_LCD(); lcdx = Tmargin; lcdy = Lmargin; break; // scientific calculator case Calculating: temp = doCalculation(keyboard_in); if (remainder == 0) { sprintf(disp_buffer," = %d",temp); } else { sprintf(disp_buffer," = %d r%d",temp,remainder); // prints out special quotient/remainder pair for division remainder=0; } temp2 = temp; LCD_say(disp_buffer,lcdx,lcdy); lcdx = lcdx + Vshift; lcdy = Lmargin; break; case Statistics: // clear the screen so there's room clear_LCD(); lcdx = Tmargin; lcdy = Lmargin; sprintf(disp_buffer,"enter set - 5 max"); LCD_say(disp_buffer,lcdx,lcdy); lcdy = Lmargin; lcdx = lcdx + Vshift; sprintf(disp_buffer,"separate with space"); LCD_say(disp_buffer,lcdx,lcdy); lcdy = Lmargin; lcdx = lcdx + Vshift; calcState = StatisticsPrep; break; case StatisticsPrep: // parse the keyboard_in string i=0; j=0; k=0; temp=0; while (keyboard_in[j] != '') { if (keyboard_in[j] == ' ') { stats_array[k++] = temp; temp = 0; if (k == 5) break; } else { temp = temp*10 + fixInt(keyboard_in[j]); } j++; } if (k < 5) stats_array[k] = temp; k++; clear_LCD(); lcdx = Tmargin; lcdy = Lmargin; sprintf(disp_buffer,"pick operation"); LCD_say(disp_buffer,lcdx,lcdy); lcdx = lcdx + Vshift; lcdy = Lmargin; sprintf(disp_buffer,"1 - min"); LCD_say(disp_buffer,lcdx,lcdy); lcdx = lcdx + Vshift; lcdy = Lmargin; sprintf(disp_buffer,"2 - max"); LCD_say(disp_buffer,lcdx,lcdy); lcdx = lcdx + Vshift; lcdy = Lmargin; sprintf(disp_buffer,"3 - mean"); LCD_say(disp_buffer,lcdx,lcdy); lcdx = lcdx + Vshift; lcdy = Lmargin; sprintf(disp_buffer,"4 - median"); LCD_say(disp_buffer,lcdx,lcdy); lcdx = lcdx + Vshift; lcdy = Lmargin; sprintf(disp_buffer,"5 - mode"); LCD_say(disp_buffer,lcdx,lcdy); lcdx = lcdx + Vshift; lcdy = Lmargin; sprintf(disp_buffer,"6 - show vector"); LCD_say(disp_buffer,lcdx,lcdy); lcdx = lcdx + Vshift; lcdy = Lmargin; sprintf(disp_buffer,"7 - exit"); LCD_say(disp_buffer,lcdx,lcdy); lcdx = lcdx + 2*Vshift; lcdy = Lmargin; calcState = StatisticsCalc; break; case StatisticsCalc: // loop in this state until exit LCD_clear_ln(lcdx); lcdx = lcdx - Vshift; LCD_clear_ln(lcdx); lcdy = Lmargin; if (keyboard_in[0] == '1') { // min temp = stats_array[0]; for (i=1;i temp) temp = stats_array[i]; } sprintf(disp_buffer,"max - %d",temp); LCD_say(disp_buffer,lcdx,lcdy); } else if (keyboard_in[0] == '3') { // mean temp = 0; for (i=0;i temp2) temp2 = stats_array[i]; } temp3=0; if (k == 1) { // only 1 element in array temp3 = stats_array[0]; } else if (k==2) { temp3 = (temp+temp2)/2; } else if (k==3) { for (i=0;i<3;i++) { if ((stats_array[i] != temp) && (stats_array[i] != temp2)) { temp3 = stats_array[i]; break; } } } else if (k==4) { for (i=0;i<4;i++) { temp3 = temp3 + stats_array[i]; } temp3 = (temp3 - temp - temp2)/2; } else { // that means there should be 5 elements in the array // build another array, sorting the numbers in order j=1; for (i=0;i<5;i++) { if ((stats_array[i] != temp) && (stats_array[i] != temp2)) { stats_array2[j++] = stats_array[i]; } } stats_array2[0] = temp; // min stats_array2[4] = temp2; // max if (stats_array2[1] > stats_array2[2]) { temp4 = stats_array2[2]; stats_array2[2] = stats_array2[1]; stats_array2[1] = temp4; } if (stats_array2[2] > stats_array2[3]) { temp4 = stats_array2[3]; stats_array2[3] = stats_array2[2]; stats_array2[2] = temp4; } if (stats_array2[1] > stats_array2[2]) { temp4 = stats_array2[2]; stats_array2[2] = stats_array2[1]; stats_array2[1] = temp4; } temp3 = stats_array2[2]; } sprintf(disp_buffer,"median - %d",temp3); LCD_say(disp_buffer,lcdx,lcdy); } else if (keyboard_in[0] == '5') { // mode temp = 1; // highest number of occurances temp2 = 1; // temp counter temp3 = stats_array[0]; // value of mode answer for (i=0;i temp) { temp3 = temp4; temp = temp2; } temp2 = 1; } sprintf(disp_buffer,"mode - %d - %d times",temp3,temp); LCD_say(disp_buffer,lcdx,lcdy); } else if (keyboard_in[0] == '6') { // print out the vector disp_buffer[0] = ''; for (i=0;i ymax) temp = ymax; LCD_put_pixel(graph_color[graph_color_index++],64-temp,i); } lcdx = lcdx + Vshift; lcdy = Lmargin; break; } // end switch calcState key_pressed = ''; for (i=0;i<20;i++) { keyboard_in[i] = ''; } kybd_in_index = 0; } // end if 'E' } // end while end //end main void initialize(void) { DDRA = 0x00; // keyboard input TIMSK = 2; OCR0 = 124; TCCR0 = 0b00001001; // For Mega32: UCSRB = 0b00011000 ; //hex 0x18 UBRRL = 103 ; //using a 16 MHz crystal (9600 baud) // In addition if you want to enable the receive-complete interrupt you must instead set // USCRB = 0b10011000; //hex 0x98 // fill the potential commands array sprintf(graph_command[0],"graph"); sprintf(graph_command[1],"clear"); sprintf(graph_command[2],"stats"); // initialize variables kybd_index = 0; kybd_in_index = 0; lcdx = 5; lcdy = 5; receive(); sprintf(disp_buffer,"initialized"); LCD_say(disp_buffer,lcdx,lcdy); lcdx = lcdx + Vshift; lcdy = Lmargin; remainder=0; #asm sei #endasm } int doMath(int var1, int var2, unsigned char func) { if (func == '+') { return var1+var2; } else if (func == '-') { return var1-var2; } else if (func == '*') { return var1*var2; } else if (func == '/') { remainder = var1%var2; return var1/var2; } else return 0; } int doCalculation(unsigned char equation[20]) { // temporary holding variables int i,t1,t2; unsigned char func; t1=0; t2=0; func = '+'; // put the first number into t1 for (i=0;i<20;i++) { if (((calcState == GraphReady) || (calcState == GraphReady2)) && (equation[i] == 'x')) { t1 = xvar; i++; break; } else if ((equation[i] != '+') && (equation[i] != '-') && (equation[i] != '*') && (equation[i] != '/') && (equation[i] != '^') && (equation[i] != '')) { t1 = t1*10+fixInt(equation[i]); } else break; } if (equation[i] != '') func = equation[i++]; for (i=i;i<20;i++) { // calculate the rest of the equation if (equation[i] == '') break; // if it's the end of the equation string else if (((calcState == GraphReady) || (calcState == GraphReady2)) && (equation[i] == 'x')) { t2 = xvar; t1 = doMath(t1,t2,func); t2 = 0; i++; if (equation[i] != '') func = equation[i]; else func = '+'; } else if ((equation[i] != '+') && (equation[i] != '-') && (equation[i] != '*') && (equation[i] != '/') && (equation[i] != '^')) { t2 = t2*10+fixInt(equation[i]); } else { t1 = doMath(t1,t2,func); t2 = 0; func = equation[i]; } } return doMath(t1,t2,func); } int fixInt(unsigned char in) { if (in == '0') return 0; else if (in == '1') return 1; else if (in == '2') return 2; else if (in == '3') return 3; else if (in == '4') return 4; else if (in == '5') return 5; else if (in == '6') return 6; else if (in == '7') return 7; else if (in == '8') return 8; else if (in == '9') return 9; } unsigned char fixChar(int in) { if (in == 0) return '0'; else if (in == 1) return '1'; else if (in == 2) return '2'; else if (in == 3) return '3'; else if (in == 4) return '4'; else if (in == 5) return '5'; else if (in == 6) return '6'; else if (in == 7) return '7'; else if (in == 8) return '8'; else if (in == 9) return '9'; }