├── README.md └── calc.ino /README.md: -------------------------------------------------------------------------------- 1 | # ARC (Arduino RPN Calculator) 1.0 2 | 3 | ## What is ARC? 4 | ARC is a scientific calculator which can do basic (+-*/) and high level mathematical operations (trigonometric, statistics, regression). See below for detailed commands. 5 | 6 | ## On which hardware does ARC run? 7 | ARC runs on the popular arduino platform (AVR/ATmega) with 32 kbyte flash memory and 1 kbyte RAM. Due to the 8-bit-processor ARC calculates only 5 to 6 digits exactly. This should be enough for most calculations (except you are a bookkeeper who wants to add billion-amounts with cent-accuracy). 8 | 9 | ## How do I run ARC? 10 | Buy an arduino, install the arduino software (including appropriate libraries) on your PC and compile/upload "calc.ino" to your arduino. By defining (and compiling) one input and one output channel ARC can be operated by a serial keyboard (terminal software like screen or putty) or a 12 key keyboard (4 rows, 3 columns). Output will be shown on a terminal or a 128x64 OLED-display. 11 | 12 | ## Which Commands does ARC support? 13 | * Basic keys: ENTER, DEL, +, -, *, /, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, EE, CHS, STO, RCL 14 | * Stack operations: SWAP, LASTx, ROT+, ROT- 15 | * Settings: DEG, RAD, FIX, SCI, SCROFF (screen off time in s, 2...200), CLOCK (counts h.ms) 16 | * Mathematics: SQRT, SQR, 1/X, POWER, FACT (!), PI 17 | * Logarithmic, exponential: LN, EXP, LOG, 10x, Py,x, Cy,x 18 | * Trigonometric: SIN, COS, TAN, ASIN, ACOS, ATAN 19 | * Hyperbolic: SINH, COSH, TANH, ASINH, ACOSH, ATANH 20 | * Statistic: CLRSUM, SUM+, SUM-, MEAN/STDDEV (mean value and standard deviation) 21 | * Linear regression: A+BX (interception and slope), ->X,Y (estimation of x and y) 22 | * Other: ANNU (present value for a given interest rate and duration), GAUSS (density and distribution), ->P (convert to polar and ...), ->R (... rectangular coordinates), ->H.MS (convert hours to hours, minutes, seconds ...), ->H (... and back), ->RAD (convert degrees to radians), ->DEG (and back) 23 | 24 | ## A short Video of a Miniaturized Mobile ARC 25 | http://youtu.be/F3uRQhoFq40 26 | 27 | In this video you can see the following calculations: 28 | * Approximating PI with 22/7 29 | * Inserting -3.14159265E-2 30 | * Setting to 6 decimal places (FIX) 31 | * Calculating the mean value and standard deviation of 4, 5 and 6 (including SWAP) 32 | * Convert a rectangular vector (1,1) to polar and back (swap to change arguments) 33 | * Calculating the Gauss normal distribution and density function at 0 (swap to change results) 34 | * Starting a clock at 8:16 (and 50 seconds) 35 | 36 | ## Some Pictures of a Miniaturized Mobile ARC 37 | 38 | ![ARC pictures](https://cloud.githubusercontent.com/assets/16148023/18578469/618225e8-7bf0-11e6-8ab1-5494e8903779.jpg "pictures") 39 | 40 | ## The Circuit Diagram 41 | ![ARC circuit diagram](https://cloud.githubusercontent.com/assets/16148023/18578474/65d0e99a-7bf0-11e6-9758-1d2680048e55.png "circuit") 42 | 43 | ## Key Assignment for the 12-Key-Keyboard 44 | ![ARC assignment of keys](https://cloud.githubusercontent.com/assets/16148023/18578478/6a3a0458-7bf0-11e6-8bd6-32abda655e6e.png "keys") 45 | 46 | -------------------------------------------------------------------------------- /calc.ino: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Welcome to ARC (Arduino RPN Calculator) v. 1.0 ... (c) 2016 by deetee aka zooxo 4 | 5 | ARC is a scientific calculator which can do basic (+*-/) and high level 6 | mathematical operations (trigonometric, statistics, regression). See below for 7 | detailed commands. 8 | 9 | By defining (and compiling) one input- and one output channel ARC can be operated 10 | by a serial keyboard (terminal software like screen or putty) or a 12 key 11 | keyboard (4 rows, 3 columns). Output will be shown on a terminal or a 12 | 128x64 OLED-display. 13 | 14 | Note: Due to the 8-bit-processor ARC calculates only 5 to 6 digits exactly. This 15 | should be enough for most calculations (except you are a bookkeeper who 16 | wants to add billion-amounts with cent-accuracy). 17 | 18 | COMMANDS and KEYS: 19 | * Basic keys: 20 | ENTER, DEL, +, -, *, /, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, EE, CHS, STO, RCL 21 | * Stack operations: 22 | SWAP, LASTx, ROT+, ROT- 23 | * Settings: 24 | DEG, RAD, FIX, SCI, SCROFF (screen off time in s, 2...200), CLOCK (counts h.ms) 25 | * Mathematics: 26 | SQRT, SQR, 1/X, POWER, FACT (!), PI 27 | * Logarithmic, exponential: 28 | LN, EXP, LOG, 10x, Py,x, Cy,x 29 | * Trigonometric: 30 | SIN, COS, TAN, ASIN, ACOS, ATAN 31 | * Hyperbolic: 32 | SINH, COSH, TANH, ASINH, ACOSH, ATANH 33 | * Statistic: 34 | CLRSUM, SUM+, SUM-, MEAN/STDDEV (mean value and standard deviation) 35 | * Linear regression: 36 | A+BX (interception and slope), ->X,Y (estimation of x and y) 37 | * Other: 38 | ANNU (present value for a given interest rate and duration), 39 | GAUSS (density and distribution), 40 | ->P (convert to polar and ...), ->R (... rectangular coordinates) 41 | ->H.MS (convert hours to hours, minutes, seconds ...), ->H (... and back) 42 | ->RAD (convert degrees to radians), ->DEG (and back) 43 | 44 | */ 45 | 46 | // DEFINES & INCLUDES 47 | 48 | // Define IO-channels 49 | #define INSERIALKBD 0 // serial keyboard (9600 baud) 50 | // not implemented: #define INSERIALKBDASDW 0 // serial keyboard with ASDW-cursor only 51 | // not implemented: #define INKBD 0 // cursor-keyboard with 2 rows and 3 cols (on pins .. and ...) 52 | #define INKBD4X3 1 // keyboard with 4 rows and 3 cols (on pins 6/7/8/9 and 2/3/4) 53 | #define OUTSERIAL 0 // serial terminal (9600 baud) 54 | #define OUTOLED 1 // 128x64 OLED i2c on SCL/SDA resp. A5/A4 (nano) 55 | 56 | #define SHIFTHELP 1 // shows help screen on OLED if shift was pressed 57 | 58 | // Serial header 59 | #if OUTSERIAL || INSERIALKBD || INSERIALKBDASDW 60 | #include 61 | #endif 62 | 63 | // Initialize custom keyboard (4x3) 64 | #if INKBD4X3 65 | #include 66 | const byte ROWS = 4; //four rows 67 | const byte COLS = 3; //four columns 68 | //define the cymbols on the buttons of the keypads 69 | char hexaKeys[ROWS][COLS] = { 70 | { 71 | '7','8','9' 72 | } 73 | ,{ 74 | '4','5','6' 75 | } 76 | ,{ 77 | '1','2','3' 78 | } 79 | ,{ 80 | '0','f',' ' 81 | } 82 | }; 83 | byte rowPins[ROWS] = { 84 | 9, 8, 7, 6}; //connect to the row pinouts of the keypad 85 | byte colPins[COLS] = { 86 | 4, 3, 2}; //connect to the column pinouts of the keypad 87 | Keypad customKeypad = Keypad( makeKeymap(hexaKeys), rowPins, colPins, ROWS, COLS); 88 | #endif 89 | 90 | // Initialize OLED 91 | #if OUTOLED 92 | #include 93 | #include 94 | #include 95 | #define OLED_RESET 4 96 | Adafruit_SSD1306 display(OLED_RESET); 97 | #endif 98 | 99 | #define NUL 0x00 100 | #define CTRLC 0x03 101 | #define BS 0x08 102 | #define TAB 0x09 103 | #define LF 0x0a 104 | #define CR 0x0d 105 | #define DEL 0x7f 106 | #define NULLCHAR '\0' 107 | 108 | #define STRLEN 16 // maximal input string length 109 | #define NEARZERO 1e-37 // if value lower use FIX format 110 | #define ALMOSTSCI 1e9 // if value higher use SCI format 111 | #define DEFAULTSCREENOFFTIME 10 // screenoff in seconds 112 | #define DEFAULTDTOSTREFLAGS 255 //flags for dtostre() 113 | #define DEFAULTFIX 4 // default number of FIX-digits 114 | #define DEFAULTREGISTERVALUE 0.0 // default value for float-variables 115 | #define DEFAULTTEXTLEN1 5 // max textlength on OLED using textsize 1 116 | #define DEFAULTTEXTLEN2 10 // max textlength on OLED using textsize 2 117 | 118 | #if OUTSERIAL 119 | #define CLEARSTRING " " // clears input string (=STRLEN) 120 | #endif 121 | 122 | 123 | // GLOBAL VARIABLES 124 | 125 | float x,y,z,u,lastx,tmp,sto,rad,sx,sxx,sy,sxy; 126 | byte fix,sn; 127 | boolean stacklift; 128 | char s[STRLEN]=""; 129 | #if OUTOLED || INKBD4X3 130 | long startmillis; 131 | byte screenofftime=DEFAULTSCREENOFFTIME; // screenoff in s till keypress 132 | #endif 133 | 134 | #if OUTOLED || INKBD4X3 135 | byte menusetnr=0; 136 | #endif 137 | 138 | // SUBPROGRAMS 139 | 140 | #if OUTOLED 141 | void displayoff() { // clears display if screenofftime is extended 142 | if(millis()-startmillis>(long)screenofftime*1000) { 143 | display.clearDisplay(); 144 | display.display(); 145 | } 146 | } 147 | #endif 148 | 149 | #if INKBD4X3 150 | char getcustomkey(byte menunr) { // query keypress on custom keyboard 151 | char customKey; 152 | menusetnr=menunr; 153 | printstack(); 154 | for(;;) { // query for key 155 | #if OUTOLED 156 | displayoff(); 157 | #endif 158 | customKey=customKeypad.getKey(); 159 | if(customKey) { 160 | startmillis=millis(); // reset startmillis 161 | return(customKey); // return key 162 | } 163 | } 164 | } 165 | #endif 166 | 167 | char inchar() { // read character from in-channel 168 | #if INSERIALKBD 169 | if(Serial.available()) return Serial.read(); 170 | else return(NULLCHAR); 171 | #elif INKBD4X3 172 | char key1=getcustomkey(0); 173 | if(key1=='f') { 174 | switch(getcustomkey(1)) { 175 | case ' ': 176 | return('+'); 177 | break; 178 | case '3': 179 | return('-'); 180 | break; 181 | case '6': 182 | return('*'); 183 | break; 184 | case '9': 185 | return('/'); 186 | break; 187 | case 'f': // decimal point 188 | return('.'); 189 | break; 190 | case '0': 191 | return(DEL); 192 | break; 193 | case '1': 194 | return('e'); 195 | break; 196 | case '2': 197 | return('#'); 198 | break; 199 | case '4': // MENU 200 | switch(getcustomkey(4)) { 201 | case '4': // MENU MATH2 202 | switch(getcustomkey(44)) { 203 | case '4': 204 | return('L'); 205 | break; 206 | case '5': 207 | return('g'); 208 | break; 209 | case '6': 210 | return('I'); 211 | break; 212 | case '7': 213 | return('l'); 214 | break; 215 | case '8': 216 | return('k'); 217 | break; 218 | case '9': 219 | return('J'); 220 | break; 221 | default: 222 | return(NULLCHAR); 223 | break; 224 | } 225 | break; 226 | case '5': // MENU CONV 227 | switch(getcustomkey(45)) { 228 | case '4': 229 | return('W'); 230 | break; 231 | case '5': 232 | return('y'); 233 | break; 234 | case '6': 235 | return('H'); 236 | break; 237 | case '7': 238 | return('w'); 239 | break; 240 | case '8': 241 | return('Y'); 242 | break; 243 | case '9': 244 | return('Z'); 245 | break; 246 | default: 247 | return(NULLCHAR); 248 | break; 249 | } 250 | break; 251 | case '7': // MENU TRIG 252 | switch(getcustomkey(47)) { 253 | case '4': 254 | return('S'); 255 | break; 256 | case '5': 257 | return('C'); 258 | break; 259 | case '6': 260 | return('T'); 261 | break; 262 | case '7': 263 | return('s'); 264 | break; 265 | case '8': 266 | return('c'); 267 | break; 268 | case '9': 269 | return('t'); 270 | break; 271 | default: 272 | return(NULLCHAR); 273 | break; 274 | } 275 | break; 276 | case '8': // MENU HYP 277 | switch(getcustomkey(48)) { 278 | case '4': 279 | return('V'); 280 | break; 281 | case '5': 282 | return('B'); 283 | break; 284 | case '6': 285 | return('N'); 286 | break; 287 | case '7': 288 | return('v'); 289 | break; 290 | case '8': 291 | return('b'); 292 | break; 293 | case '9': 294 | return('n'); 295 | break; 296 | default: 297 | return(NULLCHAR); 298 | break; 299 | } 300 | break; 301 | case '9': // MENU STAT 302 | switch(getcustomkey(49)) { 303 | case '4': 304 | return('G'); 305 | break; 306 | case '5': 307 | return('O'); 308 | break; 309 | case '6': 310 | return('a'); 311 | break; 312 | case '7': 313 | return('j'); 314 | break; 315 | case '8': 316 | return('o'); 317 | break; 318 | case '9': 319 | return('z'); 320 | break; 321 | default: 322 | return(NULLCHAR); 323 | break; 324 | } 325 | break; 326 | default: 327 | return(NULLCHAR); 328 | break; 329 | } 330 | break; 331 | case '5': // SETTINGS 332 | switch(getcustomkey(5)) { 333 | case '4': 334 | return('D'); 335 | break; 336 | case '5': 337 | return('f'); 338 | break; 339 | case '6': 340 | return('!'); 341 | break; 342 | case '7': 343 | return('d'); 344 | break; 345 | case '8': 346 | return('F'); 347 | break; 348 | case '9': 349 | return(':'); 350 | break; 351 | default: 352 | return(NULLCHAR); 353 | break; 354 | } 355 | break; 356 | case '7': // STACK 357 | switch(getcustomkey(7)) { 358 | case '4': 359 | return('X'); 360 | break; 361 | case '5': 362 | return('R'); 363 | break; 364 | case '6': 365 | return('M'); 366 | break; 367 | case '7': 368 | return('x'); 369 | break; 370 | case '8': 371 | return('r'); 372 | break; 373 | case '9': 374 | return('m'); 375 | break; 376 | default: 377 | return(NULLCHAR); 378 | break; 379 | } 380 | break; 381 | case '8': // MATH 382 | switch(getcustomkey(8)) { 383 | case '4': 384 | return('P'); 385 | break; 386 | case '5': 387 | return('U'); 388 | break; 389 | case '6': 390 | return('p'); 391 | break; 392 | case '7': 393 | return('Q'); 394 | break; 395 | case '8': 396 | return('u'); 397 | break; 398 | case '9': 399 | return('i'); 400 | break; 401 | default: 402 | return(NULLCHAR); 403 | break; 404 | } 405 | break; 406 | default: 407 | return(NULLCHAR); 408 | break; 409 | } 410 | } 411 | else return(key1); 412 | #else 413 | return(NULLCHAR); 414 | #endif 415 | } 416 | 417 | #if OUTSERIAL 418 | void outchar(byte c) { // write character to outchannel 419 | Serial.write(c); 420 | } 421 | #endif 422 | 423 | #if OUTSERIAL 424 | void newline() { // start newline at outchannel 425 | outchar(CR); 426 | outchar(LF); 427 | } 428 | #endif 429 | 430 | #if OUTOLED 431 | void printoled() { // print all to OLED-display 432 | char st[STRLEN]=""; 433 | byte i,j,flags=DEFAULTDTOSTREFLAGS; 434 | display.clearDisplay(); 435 | display.setTextSize(2); 436 | display.setTextColor(WHITE); 437 | display.setCursor(0,0); 438 | if((abs(x)>=NEARZERO)&&(abs(x)<=exp(-(fix+1)*log(10)))||(abs(x)>=ALMOSTSCI)||(fix>=100)) { // print x in SCI 439 | if(fix>100||abs(x)<=exp(-(fix+1)*log(10))) dtostre(x,st,DEFAULTFIX,flags); 440 | else dtostre(x,st,fix,flags); 441 | for(j=0;jDEFAULTTEXTLEN2) st[DEFAULTTEXTLEN2]=NULLCHAR; 448 | display.print(st); 449 | } 450 | display.setTextSize(4); // print input string 451 | display.setTextColor(WHITE); 452 | display.setCursor(0,16); 453 | if(strlen(s)>DEFAULTTEXTLEN1) { // input string too long 454 | display.print("<"); 455 | for(i=strlen(s)-DEFAULTTEXTLEN1+1;iH.MS ->R ->RAD")); 484 | display.println(F("->H ->P ->DEG")); 485 | break; 486 | case 47: 487 | display.println(F("SIN COS TAN")); 488 | display.println(F("ASIN ACOS ATAN")); 489 | break; 490 | case 48: 491 | display.println(F("SINH COSH TANH")); 492 | display.println(F("ASINH ACOSH ATANH")); 493 | break; 494 | case 49: 495 | display.println(F("MEAN A+BX CLRSUM")); 496 | display.println(F("GAUSS ->X,Y ANNU")); 497 | break; 498 | case 5: 499 | display.println(F("DEG SCI CLOCK")); 500 | display.println(F("RAD FIX SCROFF")); 501 | break; 502 | case 7: 503 | display.println(F("SWAP ROT+ RCL")); 504 | display.println(F("LASTx ROT- STO")); 505 | break; 506 | case 8: 507 | display.println(F("SQRT SUM+ 1/X")); 508 | display.println(F("POWER SUM- PI")); 509 | break; 510 | } 511 | } 512 | display.display(); 513 | } 514 | void printoledstopwatch() { 515 | char st[STRLEN]=""; 516 | display.clearDisplay(); 517 | display.setTextSize(2); 518 | display.setTextColor(WHITE); 519 | display.setCursor(0,0); 520 | dtostrf(((x*100)-(int)(x*100))*100,DEFAULTTEXTLEN2,1,st); 521 | display.print(st); 522 | display.setTextSize(4); 523 | display.setTextColor(WHITE); 524 | display.setCursor(4,32); 525 | dtostrf(((int)(x*100))/100.0,DEFAULTTEXTLEN1,2,st); 526 | display.print(st); 527 | display.display(); 528 | } 529 | #endif 530 | 531 | void displaystring() { // write input string to outchannel 532 | #if OUTSERIAL 533 | outchar(CR); 534 | Serial.write(CLEARSTRING); 535 | outchar(CR); 536 | Serial.print(s); 537 | #elif OUTOLED 538 | printoled(); 539 | #endif 540 | } 541 | 542 | void printstack() { // print stack 543 | #if OUTSERIAL 544 | char st[STRLEN]; 545 | byte i,j,flags=DEFAULTDTOSTREFLAGS; 546 | if(fix>=100) { 547 | dtostre(z,st,fix-100,flags); 548 | for(j=0;jp|r Usum+|sum- I1/x|comb Oa+bx|>xy Ppi|pwr"); 582 | newline(); 583 | Serial.write("Aannu Ssin|a Ddeg|rad Ffix|sci G!|gauss Hhlp|>deg Jmean|perm Klog|10^x Lln|exp"); 584 | newline(); 585 | Serial.write("Zcsum|>rad Xswp|lstx Ccos|arc Vsinh|ar Bcosh|ar Ntanh|ar Mrcl|sto #chs :clk !scroff SPCentr"); 586 | newline(); 587 | newline(); 588 | } 589 | #endif 590 | 591 | float hmstoh(float hms) { // hms->h 592 | // return((int)hms+((int)(100*(hms-(int)hms)))/60.0+(100*(100*hms-(int)(100*hms)))/3600.0); 593 | unsigned long T=(hms+0.000005)*100000; 594 | int hh=(int)(T/100000),mm=(int)(T/1000)-hh*100,ss=T/10-hh*10000-mm*100,t=T-hh*100000-mm*1000-ss*10; 595 | return(hh+mm/60.0+ss/3600.0+t/36000.0); 596 | } 597 | float htohms(float h) { // h->hms 598 | h+=0.000005; 599 | return((int)h+((int)(60*(h-(int)h)))/100.0+(60*((60*(h-(int)h))-(int)(60*(h-(int)h))))/10000.0); 600 | } 601 | 602 | void push() { // push stack 603 | u=z; 604 | z=y; 605 | y=x; 606 | } 607 | 608 | void pop() { // pull stack 609 | x=y; 610 | y=z; 611 | z=u; 612 | } 613 | 614 | 615 | // SETUP and LOOP 616 | 617 | void setup() { 618 | x=y=z=u=lastx=tmp=sto=sx=sxx=sy=sxy=DEFAULTREGISTERVALUE; 619 | sn=0; 620 | rad=M_PI/180.0; 621 | fix=DEFAULTFIX; 622 | stacklift=false; 623 | #if OUTSERIAL || INSERIALKBD || INSERIALKBDASDW 624 | Serial.begin(9600); 625 | #endif 626 | #if OUTOLED 627 | startmillis=millis(); 628 | display.begin(SSD1306_SWITCHCAPVCC, 0x3c); 629 | display.clearDisplay(); // Welcome message 630 | display.setTextSize(2); 631 | display.setTextColor(WHITE); 632 | display.println(F(" ARC 1.0")); 633 | display.println(); 634 | display.println(); 635 | display.println(F(" WELCOME")); 636 | display.display(); 637 | delay(750); 638 | printstack(); 639 | #endif 640 | } 641 | 642 | void loop() { 643 | char key; 644 | byte i,ipos; 645 | boolean ise; // is EE (e or E) in input string? 646 | key=NULLCHAR; 647 | key=inchar(); // read character from inchannel 648 | if(key!=NULLCHAR) { // process if character input occurs 649 | #if OUTOLED 650 | startmillis=millis(); // reset startmillis 651 | printstack(); 652 | #endif 653 | if((key>='0')&&(key<='9')||(key=='.')||(key==',')||(key=='E')||(key=='e')) { 654 | if(((key=='E')||(key=='e'))&&(strlen(s)<=0)) strcat(s,"1"); 655 | ; 656 | if(key==',') key='.'; // decimal komma equals decimal point 657 | if(strlen(s)0)&&(key==DEL)) { // backspace was pressed 664 | s[strlen(s)-1]=NULLCHAR; 665 | displaystring(); 666 | } 667 | else if((strlen(s)>0)&&(key=='#')) { // change prefix of EE 668 | ise=false; 669 | ipos=1; 670 | for(i=1;i<=strlen(s);i++) if((s[i]=='e')||(s[i]=='E')) { 671 | ise=true; 672 | ipos=i; 673 | } 674 | if(ise) { // CHS of EE 675 | if(s[ipos+1]=='-') for(i=ipos+1;iipos;i--) s[i+1]=s[i]; 678 | s[ipos+1]='-'; 679 | } 680 | displaystring(); 681 | } 682 | else { // CHS 683 | if(s[0]=='-') { 684 | for(i=0;i0;i--) s[i]=s[i-1]; 689 | s[0]='-'; 690 | } 691 | displaystring(); 692 | } 693 | } 694 | else { // no digit entered 695 | if(strlen(s)>0) { // process input string with or without stacklift 696 | if(stacklift) { 697 | push(); 698 | lastx=x; 699 | x=atof(s); 700 | } 701 | else { 702 | lastx=x; 703 | x=atof(s); 704 | } 705 | } 706 | switch(key) { // operation demanded 707 | case ' ': // ENTER 708 | push(); 709 | stacklift=false; 710 | break; 711 | case DEL: // CLx 712 | lastx=x; 713 | x=0; 714 | break; 715 | case '+': 716 | lastx=x; 717 | x=x+y; 718 | y=z; 719 | z=u; 720 | stacklift=true; 721 | break; // operation 722 | case '-': 723 | lastx=x; 724 | x=y-x; 725 | y=z; 726 | z=u; 727 | stacklift=true; 728 | break; 729 | case '*': 730 | lastx=x; 731 | x=x*y; 732 | y=z; 733 | z=u; 734 | stacklift=true; 735 | break; 736 | case '/': 737 | lastx=x; 738 | x=y/x; 739 | y=z; 740 | z=u; 741 | stacklift=true; 742 | break; 743 | case '#': // change prefix of register x 744 | lastx=x; 745 | x=-x; 746 | break; 747 | case 'a': // calculate annuity 748 | lastx=x; 749 | x=(1-1/exp(x*log(1+y)))/y; 750 | y=z; 751 | z=u; 752 | break; 753 | case 'b': // sinh 754 | lastx=x; 755 | x=(exp(x)+exp(-x))/2; 756 | stacklift=true; 757 | break; 758 | case 'B': // asinh 759 | lastx=x; 760 | x=log(x+sqrt(x*x-1)); 761 | break; 762 | case 'c': // cos 763 | lastx=x; 764 | x=cos(x*rad); 765 | stacklift=true; 766 | break; 767 | case 'C': // acos 768 | lastx=x; 769 | x=(M_PI/2-atan(x/(sqrt(1-x*x))))/rad; 770 | stacklift=true; 771 | break; 772 | case 'd': // -> deg 773 | rad=M_PI/180.0; 774 | break; 775 | case 'D': // -> rad 776 | rad=1.0; 777 | break; 778 | case 'f': // fix 779 | fix=(int)abs(x); 780 | pop(); 781 | stacklift=true; 782 | break; 783 | case 'F': // SCI 784 | if(fix<100) fix+=100; 785 | break; 786 | case 'g': // ! 787 | for(tmp=i=1;i<=x;i++) tmp=tmp*i; 788 | lastx=x; 789 | x=tmp; 790 | stacklift=true; 791 | break; 792 | case 'G': // GAUSS 793 | tmp=x; 794 | push(); 795 | lastx=x; 796 | x=1/(1+exp(-0.07*tmp*tmp*tmp-1.6*tmp)); 797 | push(); 798 | x=1/sqrt(2*M_PI)*exp(-tmp*tmp/2); 799 | stacklift=true; 800 | break; 801 | #if OUTSERIAL 802 | case 'h': // help 803 | help(); 804 | break; 805 | #endif 806 | case 'H': // ->DEG 807 | lastx=x; 808 | x*=180/M_PI; 809 | stacklift=true; 810 | break; 811 | case 'i': // 1/x 812 | lastx=x; 813 | x=1.0/x; 814 | stacklift=true; 815 | break; 816 | case 'I': // COMB 817 | lastx=x; 818 | tmp=x; 819 | x=1.0; 820 | for(i=y-tmp+1;i<=y;i++) x*=i; 821 | for(i=1;i<=tmp;i++) x/=i; 822 | y=z; 823 | z=u; 824 | stacklift=true; 825 | break; 826 | case 'j': // MEAN/STDDEV 827 | push(); 828 | lastx=x; 829 | x=sqrt((sxx-sx*sx/sn)/(sn-1)); 830 | push(); 831 | x=sx/sn; 832 | stacklift=true; 833 | break; 834 | case 'J': // PERM 835 | lastx=x; 836 | tmp=x; 837 | x=1.0; 838 | for(i=y-tmp+1;i<=y;i++) x*=i; 839 | y=z; 840 | z=u; 841 | stacklift=true; 842 | break; 843 | case 'k': // log 844 | lastx=x; 845 | x=log(x)/log(10); 846 | stacklift=true; 847 | break; 848 | case 'K': // 10powX 849 | lastx=x; 850 | x=exp(x*log(10)); 851 | stacklift=true; 852 | break; 853 | case 'l': // ln 854 | lastx=x; 855 | x=log(x); 856 | stacklift=true; 857 | break; 858 | case 'L': // exp 859 | lastx=x; 860 | x=exp(x); 861 | stacklift=true; 862 | break; 863 | case 'm': // RCL 864 | push(); 865 | lastx=x; 866 | x=sto; 867 | stacklift=true; 868 | break; 869 | case 'M': // STO 870 | sto=x; 871 | break; 872 | case 'n': // tanh 873 | lastx=x; 874 | x=(exp(x)-exp(-x))/(exp(x)+exp(-x)); 875 | stacklift=true; 876 | break; 877 | case 'N': // atanh 878 | lastx=x; 879 | x=log(sqrt((1+x)/(1-x))); 880 | break; 881 | case 'o': // A+BX 882 | push(); 883 | lastx=x; 884 | x=tmp=(sxy/sn-sx/sn*sy/sn)/(sxx/sn-sx*sx/sn/sn); 885 | push(); 886 | x=sy/sn-tmp*sx/sn; 887 | stacklift=true; 888 | break; 889 | case 'O': // L.R. ->X,Y 890 | push(); 891 | tmp=(sxy/sn-sx/sn*sy/sn)/(sxx/sn-sx*sx/sn/sn); 892 | lastx=x; 893 | x=sy/sn-tmp*sx/sn+tmp*y; 894 | push(); 895 | x=(z-sy/sn+tmp*sx/sn)/tmp; 896 | stacklift=true; 897 | break; 898 | case 'p': // PI 899 | if(stacklift) push(); 900 | lastx=x; 901 | x=M_PI; 902 | stacklift=true; 903 | break; 904 | case 'P': // YpowerX 905 | lastx=x; 906 | x=exp(x*log(y)); 907 | y=z; 908 | z=u; 909 | stacklift=true; 910 | break; 911 | case 'q': // sqr 912 | lastx=x; 913 | x=x*x; 914 | stacklift=true; 915 | break; 916 | case 'Q': // sqrt 917 | lastx=x; 918 | x=sqrt(x); 919 | stacklift=true; 920 | break; 921 | case 'r': // ROT down 922 | tmp=x; 923 | pop(); 924 | u=tmp; 925 | break; 926 | case 'R': // ROT up 927 | tmp=u; 928 | push(); 929 | lastx=x; 930 | x=tmp; 931 | break; 932 | case 's': // sin 933 | lastx=x; 934 | x=sin(x*rad); 935 | stacklift=true; 936 | break; 937 | case 'S': // asin 938 | lastx=x; 939 | x=atan(x/(sqrt(1-x*x)))/rad; 940 | break; 941 | case 't': // tan 942 | lastx=x; 943 | x=sin(x*rad)/cos(x*rad); 944 | stacklift=true; 945 | break; 946 | case 'T': // atan 947 | lastx=x; 948 | x=atan(x)/rad; 949 | stacklift=true; 950 | break; 951 | case 'u': // SUM+ 952 | sn++; 953 | sx+=x; 954 | sy+=y; 955 | sxx+=x*x; 956 | sxy+=x*y; 957 | push(); 958 | lastx=x; 959 | x=sn; 960 | stacklift=false; 961 | break; 962 | case 'U': // SUM- 963 | sn--; 964 | sx-=x; 965 | sxx-=x*x; 966 | sy-=y; 967 | sxy-=x*y; 968 | push(); 969 | lastx=x; 970 | x=sn; 971 | stacklift=false; 972 | break; 973 | case 'v': // sinh 974 | lastx=x; 975 | x=(exp(x)-exp(-x))/2; 976 | stacklift=true; 977 | break; 978 | case 'V': // asinh 979 | lastx=x; 980 | x=log(x+sqrt(x*x-1)); 981 | stacklift=true; 982 | break; 983 | case 'w': // ->H.MS 984 | lastx=x; 985 | x=htohms(x); 986 | // x=(int)x+((int)(60*(x-(int)x)))/100.0+(60*((60*(x-(int)x))-(int)(60*(x-(int)x))))/10000; 987 | stacklift=true; 988 | break; 989 | case 'W': // ->H 990 | lastx=x; 991 | x=hmstoh(x); 992 | // x=(int)x+((int)(100*(x-(int)x)))/60.0+(100*(100*x-(int)(100*x)))/3600; 993 | stacklift=true; 994 | break; 995 | case 'x': // swap 996 | tmp=x; 997 | lastx=x; 998 | x=y; 999 | y=tmp; 1000 | break; 1001 | case 'X': // LASTx 1002 | push(); 1003 | x=lastx; 1004 | break; 1005 | case 'y': // ->P 1006 | tmp=y; 1007 | y=atan(tmp/x)/rad; 1008 | lastx=x; 1009 | x=sqrt(x*x+tmp*tmp); 1010 | stacklift=true; 1011 | break; 1012 | case 'Y': // ->R 1013 | tmp=y; 1014 | y=x*sin(tmp*rad); 1015 | lastx=x; 1016 | x=x*cos(tmp*rad); 1017 | stacklift=true; 1018 | break; 1019 | case 'z': // CLRSUM 1020 | sn=sx=sxx=sy=sxy=DEFAULTREGISTERVALUE; 1021 | break; 1022 | case 'Z': // ->RAD 1023 | lastx=x; 1024 | x*=M_PI/180; 1025 | stacklift=true; 1026 | break; 1027 | #if OUTOLED 1028 | case '!': // set screenofftime 1029 | if((x>=2)&&(x<=200)) screenofftime=x; 1030 | pop(); 1031 | stacklift=true; 1032 | break; 1033 | #endif 1034 | case ':': // stopwatch 1035 | char customKey; 1036 | long temp,stopmillis=millis(); 1037 | lastx=x; 1038 | temp=hmstoh(abs(x))*3600000; 1039 | for(;;) { // query for key 1040 | #if INKBD4X3 1041 | customKey=customKeypad.getKey(); 1042 | if(customKey) { 1043 | break; 1044 | } 1045 | #elif INSERIALKBD 1046 | key=inchar(); 1047 | if(key!=NULLCHAR) { 1048 | break; 1049 | } 1050 | #endif 1051 | else { 1052 | x=htohms((temp+millis()-stopmillis)/3600000.0); 1053 | if(x>=24) { 1054 | temp=0.0; 1055 | stopmillis=millis(); 1056 | } 1057 | #if OUTOLED 1058 | printoledstopwatch(); 1059 | #elif OUTSERIAL 1060 | Serial.println(x,4); 1061 | delay(1000); 1062 | #endif 1063 | } 1064 | } 1065 | startmillis=millis(); 1066 | break; 1067 | } 1068 | s[0]=NULLCHAR; 1069 | printstack(); 1070 | } 1071 | } 1072 | #if OUTOLED 1073 | else displayoff(); 1074 | #endif 1075 | } 1076 | 1077 | 1078 | 1079 | 1080 | 1081 | 1082 | 1083 | 1084 | 1085 | 1086 | 1087 | 1088 | 1089 | 1090 | 1091 | 1092 | 1093 | 1094 | 1095 | 1096 | 1097 | 1098 | 1099 | 1100 | 1101 | 1102 | 1103 | 1104 | 1105 | 1106 | 1107 | 1108 | 1109 | 1110 | 1111 | 1112 | 1113 | 1114 | 1115 | 1116 | 1117 | 1118 | 1119 | 1120 | 1121 | 1122 | 1123 | 1124 | 1125 | 1126 | 1127 | 1128 | 1129 | 1130 | 1131 | 1132 | 1133 | 1134 | 1135 | 1136 | 1137 | 1138 | 1139 | 1140 | 1141 | 1142 | 1143 | 1144 | 1145 | 1146 | 1147 | 1148 | 1149 | 1150 | 1151 | 1152 | 1153 | 1154 | 1155 | 1156 | 1157 | 1158 | 1159 | 1160 | 1161 | 1162 | 1163 | 1164 | 1165 | 1166 | 1167 | 1168 | 1169 | 1170 | 1171 | 1172 | 1173 | 1174 | 1175 | 1176 | 1177 | 1178 | 1179 | 1180 | 1181 | 1182 | 1183 | 1184 | 1185 | 1186 | 1187 | 1188 | 1189 | 1190 | 1191 | 1192 | 1193 | 1194 | 1195 | 1196 | 1197 | 1198 | 1199 | 1200 | 1201 | 1202 | 1203 | 1204 | 1205 | 1206 | 1207 | 1208 | 1209 | 1210 | 1211 | 1212 | 1213 | 1214 | 1215 | 1216 | 1217 | 1218 | 1219 | 1220 | 1221 | 1222 | 1223 | 1224 | 1225 | 1226 | 1227 | 1228 | 1229 | 1230 | 1231 | 1232 | 1233 | 1234 | 1235 | 1236 | 1237 | 1238 | 1239 | 1240 | 1241 | 1242 | 1243 | 1244 | 1245 | 1246 | 1247 | 1248 | 1249 | 1250 | 1251 | 1252 | 1253 | 1254 | 1255 | 1256 | --------------------------------------------------------------------------------