A modern Music Player Daemon based on Rockbox open source high quality audio player
libadwaita audio rust zig deno mpris rockbox mpd
at master 2309 lines 78 kB view raw
1/*************************************************************************** 2 * __________ __ ___. 3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___ 4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / 5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < 6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ 7 * \/ \/ \/ \/ \/ 8 * $Id$ 9 * 10 * Copyright (C) 2004 Pengxuan Liu (Isaac) 11 * 12 * This program is free software; you can redistribute it and/or 13 * modify it under the terms of the GNU General Public License 14 * as published by the Free Software Foundation; either version 2 15 * of the License, or (at your option) any later version. 16 * 17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 18 * KIND, either express or implied. 19 * 20 ****************************************************************************/ 21 22/* 23 00 01 21 22 23 43 44 45 65 66 67 87 88 89 109110111 2400 |-----------|-----------|-----------|-----------|-----------| 2501 | | | | | | 26 |***********|***********|***********|***********|***********| 27 |***********|***********|***********|***********|***********| 2811 | | | | | | 2912 |-----------|-----------|-----------|-----------|-----------| 3013 |-----------|-----------|-----------|-----------|-----------| y1 3114 | | | | | | 32 | | | | | | 3322 | | | | | | 3423 |-----------|-----------|-----------|-----------|-----------| y2 3524 | | | | | | 36 | | | | | | 3732 | | | | | | 3833 |-----------|-----------|-----------|-----------|-----------| y3 3934 | | | | | | 40 | | | | | | 4142 | | | | | | 4243 |-----------|-----------|-----------|-----------|-----------| y4 4344 | | | | | | 44 | | | | | | 4552 | | | | | | 4653 |-----------|-----------|-----------|-----------|-----------| y5 4754 | | | | | | 48 | | | | | | 4962 | | | | | | 5063 |-----------|-----------|-----------|-----------|-----------| y6 51 x0 x1 x2 x3 x4 x5 52*/ 53 54/*--------------------------------------------------------------------------- 55Features: 56- Scientific number format core code. Support range 10^-999 ~ 10^999 57- Number of significant figures up to 10 58 59Limitations: 60- Right now, only accept "num, operator (+,-,*,/), num, =" input sequence. 61 Input "3, +, 5, -, 2, =", the calculator will only do 5-2 and result = 3 62 You have to input "3, +, 5, =, -, 2, =" to get 3+5-2 = 6 63 64- "*,/" have no priority. Actually you can't input 3+5*2 yet. 65 66User Instructions: 67use arrow button to move cursor, "play" button to select, "off" button to exit 68F1: if typing numbers, it's equal to "Del"; otherwise, equal to "C" 69F2: circle input "+, -, *, /" 70F3: equal to "=" 71 72"MR" : load temp memory 73"M+" : add currently display to temp memory 74"C" : reset calculator 75---------------------------------------------------------------------------*/ 76 77#include "plugin.h" 78 79#include "math.h" 80 81 82 83 84#define M_TWOPI (M_PI * 2.0) 85 86#define BUTTON_ROWS 5 87#define BUTTON_COLS 5 88 89#define REC_HEIGHT (int)(LCD_HEIGHT / (BUTTON_ROWS + 1)) 90#define REC_WIDTH (int)(LCD_WIDTH / BUTTON_COLS) 91 92#define Y_6_POS (LCD_HEIGHT) /* Leave room for the border */ 93#define Y_5_POS (Y_6_POS - REC_HEIGHT) /* y5 = 53 */ 94#define Y_4_POS (Y_5_POS - REC_HEIGHT) /* y4 = 43 */ 95#define Y_3_POS (Y_4_POS - REC_HEIGHT) /* y3 = 33 */ 96#define Y_2_POS (Y_3_POS - REC_HEIGHT) /* y2 = 23 */ 97#define Y_1_POS (Y_2_POS - REC_HEIGHT) /* y1 = 13 */ 98#define Y_0_POS 0 /* y0 = 0 */ 99 100#define X_0_POS 0 /* x0 = 0 */ 101#define X_1_POS (X_0_POS + REC_WIDTH) /* x1 = 22 */ 102#define X_2_POS (X_1_POS + REC_WIDTH) /* x2 = 44 */ 103#define X_3_POS (X_2_POS + REC_WIDTH) /* x3 = 66 */ 104#define X_4_POS (X_3_POS + REC_WIDTH) /* x4 = 88 */ 105#define X_5_POS (X_4_POS + REC_WIDTH) /* x5 = 110, column 111 left blank */ 106 107#define SIGN(x) ((x)<0?-1:1) 108#ifndef ABS 109#define ABS(a) (((a) < 0) ? -(a) : (a)) 110#endif 111 112/* variable button definitions */ 113#if (CONFIG_KEYPAD == IRIVER_H100_PAD) || \ 114 (CONFIG_KEYPAD == IRIVER_H300_PAD) 115#define CALCULATOR_LEFT BUTTON_LEFT 116#define CALCULATOR_RIGHT BUTTON_RIGHT 117#define CALCULATOR_UP BUTTON_UP 118#define CALCULATOR_DOWN BUTTON_DOWN 119#define CALCULATOR_QUIT BUTTON_OFF 120#define CALCULATOR_INPUT BUTTON_SELECT 121#define CALCULATOR_CALC BUTTON_ON 122#define CALCULATOR_OPERATORS BUTTON_MODE 123#define CALCULATOR_CLEAR BUTTON_REC 124 125#define CALCULATOR_RC_QUIT BUTTON_RC_STOP 126 127#elif (CONFIG_KEYPAD == IPOD_4G_PAD) || \ 128 (CONFIG_KEYPAD == IPOD_3G_PAD) || \ 129 (CONFIG_KEYPAD == IPOD_1G2G_PAD) 130 131#define CALCULATOR_LEFT BUTTON_LEFT 132#define CALCULATOR_RIGHT BUTTON_RIGHT 133#define CALCULATOR_UP_W_SHIFT BUTTON_SCROLL_BACK 134#define CALCULATOR_DOWN_W_SHIFT BUTTON_SCROLL_FWD 135#define CALCULATOR_QUIT BUTTON_MENU 136#define CALCULATOR_INPUT BUTTON_SELECT 137#define CALCULATOR_CALC BUTTON_PLAY 138 139#elif (CONFIG_KEYPAD == IAUDIO_X5M5_PAD) 140 141#define CALCULATOR_LEFT BUTTON_LEFT 142#define CALCULATOR_RIGHT BUTTON_RIGHT 143#define CALCULATOR_UP BUTTON_UP 144#define CALCULATOR_DOWN BUTTON_DOWN 145#define CALCULATOR_QUIT BUTTON_POWER 146#define CALCULATOR_INPUT BUTTON_SELECT 147#define CALCULATOR_CALC BUTTON_PLAY 148#define CALCULATOR_CLEAR BUTTON_REC 149 150#elif (CONFIG_KEYPAD == GIGABEAT_PAD) 151 152#define CALCULATOR_LEFT BUTTON_LEFT 153#define CALCULATOR_RIGHT BUTTON_RIGHT 154#define CALCULATOR_UP BUTTON_UP 155#define CALCULATOR_DOWN BUTTON_DOWN 156#define CALCULATOR_QUIT BUTTON_POWER 157#define CALCULATOR_INPUT BUTTON_SELECT 158#define CALCULATOR_CALC BUTTON_MENU 159#define CALCULATOR_CLEAR BUTTON_A 160 161#elif (CONFIG_KEYPAD == SANSA_E200_PAD) 162#define CALCULATOR_LEFT BUTTON_LEFT 163#define CALCULATOR_RIGHT BUTTON_RIGHT 164#define CALCULATOR_UP BUTTON_UP 165#define CALCULATOR_DOWN BUTTON_DOWN 166#define CALCULATOR_UP_W_SHIFT BUTTON_SCROLL_BACK 167#define CALCULATOR_DOWN_W_SHIFT BUTTON_SCROLL_FWD 168#define CALCULATOR_QUIT BUTTON_POWER 169#define CALCULATOR_INPUT_CALC_PRE BUTTON_SELECT 170#define CALCULATOR_INPUT (BUTTON_SELECT|BUTTON_REL) 171#define CALCULATOR_CALC (BUTTON_SELECT|BUTTON_REPEAT) 172#define CALCULATOR_CLEAR BUTTON_REC 173 174#elif (CONFIG_KEYPAD == SANSA_C200_PAD) 175#define CALCULATOR_LEFT BUTTON_LEFT 176#define CALCULATOR_RIGHT BUTTON_RIGHT 177#define CALCULATOR_UP BUTTON_UP 178#define CALCULATOR_DOWN BUTTON_DOWN 179#define CALCULATOR_QUIT BUTTON_POWER 180#define CALCULATOR_INPUT_CALC_PRE BUTTON_SELECT 181#define CALCULATOR_INPUT (BUTTON_SELECT|BUTTON_REL) 182#define CALCULATOR_CALC (BUTTON_SELECT|BUTTON_REPEAT) 183 184#elif (CONFIG_KEYPAD == SANSA_FUZE_PAD) 185#define CALCULATOR_LEFT BUTTON_LEFT 186#define CALCULATOR_RIGHT BUTTON_RIGHT 187#define CALCULATOR_UP BUTTON_UP 188#define CALCULATOR_DOWN BUTTON_DOWN 189#define CALCULATOR_UP_W_SHIFT BUTTON_SCROLL_BACK 190#define CALCULATOR_DOWN_W_SHIFT BUTTON_SCROLL_FWD 191#define CALCULATOR_QUIT (BUTTON_HOME|BUTTON_REPEAT) 192#define CALCULATOR_INPUT_CALC_PRE BUTTON_SELECT 193#define CALCULATOR_INPUT (BUTTON_SELECT|BUTTON_REL) 194#define CALCULATOR_CALC (BUTTON_SELECT|BUTTON_REPEAT) 195#define CALCULATOR_CLEAR BUTTON_HOME 196 197 198#elif (CONFIG_KEYPAD == SANSA_CLIP_PAD) 199#define CALCULATOR_LEFT BUTTON_LEFT 200#define CALCULATOR_RIGHT BUTTON_RIGHT 201#define CALCULATOR_UP BUTTON_UP 202#define CALCULATOR_DOWN BUTTON_DOWN 203#define CALCULATOR_QUIT BUTTON_POWER 204#define CALCULATOR_INPUT_CALC_PRE BUTTON_SELECT 205#define CALCULATOR_INPUT (BUTTON_SELECT|BUTTON_REL) 206#define CALCULATOR_CALC (BUTTON_SELECT|BUTTON_REPEAT) 207#define CALCULATOR_CLEAR BUTTON_HOME 208 209#elif (CONFIG_KEYPAD == SANSA_M200_PAD) 210#define CALCULATOR_LEFT BUTTON_LEFT 211#define CALCULATOR_RIGHT BUTTON_RIGHT 212#define CALCULATOR_UP BUTTON_UP 213#define CALCULATOR_DOWN BUTTON_DOWN 214#define CALCULATOR_QUIT BUTTON_POWER 215#define CALCULATOR_INPUT_CALC_PRE BUTTON_SELECT 216#define CALCULATOR_INPUT (BUTTON_SELECT|BUTTON_REL) 217#define CALCULATOR_CALC (BUTTON_SELECT|BUTTON_REPEAT) 218#define CALCULATOR_CLEAR (BUTTON_SELECT|BUTTON_UP) 219 220#elif (CONFIG_KEYPAD == IRIVER_H10_PAD) 221 222#define CALCULATOR_LEFT BUTTON_LEFT 223#define CALCULATOR_RIGHT BUTTON_RIGHT 224#define CALCULATOR_UP BUTTON_SCROLL_UP 225#define CALCULATOR_DOWN BUTTON_SCROLL_DOWN 226#define CALCULATOR_QUIT BUTTON_POWER 227#define CALCULATOR_INPUT_CALC_PRE BUTTON_PLAY 228#define CALCULATOR_INPUT (BUTTON_PLAY | BUTTON_REL) 229#define CALCULATOR_CALC (BUTTON_PLAY | BUTTON_REPEAT) 230#define CALCULATOR_CLEAR BUTTON_REW 231 232#elif (CONFIG_KEYPAD == GIGABEAT_S_PAD) 233 234#define CALCULATOR_LEFT BUTTON_LEFT 235#define CALCULATOR_RIGHT BUTTON_RIGHT 236#define CALCULATOR_UP BUTTON_UP 237#define CALCULATOR_DOWN BUTTON_DOWN 238#define CALCULATOR_QUIT BUTTON_BACK 239#define CALCULATOR_INPUT BUTTON_SELECT 240#define CALCULATOR_CALC BUTTON_MENU 241#define CALCULATOR_CLEAR BUTTON_PLAY 242 243#elif (CONFIG_KEYPAD == MROBE100_PAD) 244 245#define CALCULATOR_LEFT BUTTON_LEFT 246#define CALCULATOR_RIGHT BUTTON_RIGHT 247#define CALCULATOR_UP BUTTON_UP 248#define CALCULATOR_DOWN BUTTON_DOWN 249#define CALCULATOR_QUIT BUTTON_POWER 250#define CALCULATOR_INPUT BUTTON_SELECT 251#define CALCULATOR_CALC BUTTON_MENU 252#define CALCULATOR_CLEAR BUTTON_DISPLAY 253 254#elif CONFIG_KEYPAD == IAUDIO_M3_PAD 255 256#define CALCULATOR_LEFT BUTTON_RC_REW 257#define CALCULATOR_RIGHT BUTTON_RC_FF 258#define CALCULATOR_UP BUTTON_RC_VOL_UP 259#define CALCULATOR_DOWN BUTTON_RC_VOL_DOWN 260#define CALCULATOR_QUIT BUTTON_RC_REC 261#define CALCULATOR_INPUT BUTTON_RC_PLAY 262#define CALCULATOR_CALC BUTTON_RC_MODE 263#define CALCULATOR_CLEAR BUTTON_RC_MENU 264 265#define CALCULATOR_RC_QUIT BUTTON_REC 266 267#elif (CONFIG_KEYPAD == COWON_D2_PAD) 268 269#define CALCULATOR_QUIT BUTTON_POWER 270#define CALCULATOR_CLEAR BUTTON_MENU 271 272#elif (CONFIG_KEYPAD == CREATIVEZVM_PAD) 273 274#define CALCULATOR_LEFT BUTTON_LEFT 275#define CALCULATOR_RIGHT BUTTON_RIGHT 276#define CALCULATOR_UP BUTTON_UP 277#define CALCULATOR_DOWN BUTTON_DOWN 278#define CALCULATOR_QUIT BUTTON_BACK 279#define CALCULATOR_INPUT BUTTON_SELECT 280#define CALCULATOR_CALC BUTTON_MENU 281#define CALCULATOR_CLEAR BUTTON_PLAY 282 283#elif CONFIG_KEYPAD == CREATIVE_ZENXFI3_PAD 284 285#define CALCULATOR_LEFT (BUTTON_BACK|BUTTON_REL) 286#define CALCULATOR_RIGHT BUTTON_MENU 287#define CALCULATOR_UP BUTTON_UP 288#define CALCULATOR_DOWN BUTTON_DOWN 289#define CALCULATOR_QUIT BUTTON_POWER 290#define CALCULATOR_INPUT (BUTTON_PLAY|BUTTON_REL) 291#define CALCULATOR_CALC (BUTTON_PLAY|BUTTON_REPEAT) 292#define CALCULATOR_CLEAR (BUTTON_BACK|BUTTON_REPEAT) 293 294#elif CONFIG_KEYPAD == PHILIPS_HDD1630_PAD 295 296#define CALCULATOR_LEFT BUTTON_LEFT 297#define CALCULATOR_RIGHT BUTTON_RIGHT 298#define CALCULATOR_UP BUTTON_UP 299#define CALCULATOR_DOWN BUTTON_DOWN 300#define CALCULATOR_QUIT BUTTON_POWER 301#define CALCULATOR_INPUT BUTTON_SELECT 302#define CALCULATOR_CALC BUTTON_MENU 303#define CALCULATOR_CLEAR BUTTON_VIEW 304 305#elif CONFIG_KEYPAD == PHILIPS_HDD6330_PAD 306 307#define CALCULATOR_LEFT BUTTON_PREV 308#define CALCULATOR_RIGHT BUTTON_NEXT 309#define CALCULATOR_UP BUTTON_UP 310#define CALCULATOR_DOWN BUTTON_DOWN 311#define CALCULATOR_QUIT BUTTON_POWER 312#define CALCULATOR_INPUT BUTTON_PLAY 313#define CALCULATOR_CALC BUTTON_MENU 314#define CALCULATOR_CLEAR BUTTON_RIGHT 315 316#elif CONFIG_KEYPAD == PHILIPS_SA9200_PAD 317 318#define CALCULATOR_LEFT BUTTON_PREV 319#define CALCULATOR_RIGHT BUTTON_NEXT 320#define CALCULATOR_UP BUTTON_UP 321#define CALCULATOR_DOWN BUTTON_DOWN 322#define CALCULATOR_QUIT BUTTON_POWER 323#define CALCULATOR_INPUT BUTTON_PLAY 324#define CALCULATOR_CALC BUTTON_MENU 325#define CALCULATOR_CLEAR BUTTON_RIGHT 326 327#elif (CONFIG_KEYPAD == ONDAVX747_PAD) 328 329#define CALCULATOR_QUIT BUTTON_POWER 330#define CALCULATOR_CLEAR BUTTON_MENU 331 332#elif (CONFIG_KEYPAD == ONDAVX777_PAD) 333#define CALCULATOR_QUIT BUTTON_POWER 334 335#elif CONFIG_KEYPAD == MROBE500_PAD 336#define CALCULATOR_QUIT BUTTON_POWER 337 338#elif CONFIG_KEYPAD == SAMSUNG_YH820_PAD 339 340#define CALCULATOR_LEFT BUTTON_LEFT 341#define CALCULATOR_RIGHT BUTTON_RIGHT 342#define CALCULATOR_UP BUTTON_UP 343#define CALCULATOR_DOWN BUTTON_DOWN 344#define CALCULATOR_QUIT (BUTTON_REW|BUTTON_REPEAT) 345#define CALCULATOR_INPUT BUTTON_PLAY 346#define CALCULATOR_CALC BUTTON_FFWD 347#define CALCULATOR_CLEAR (BUTTON_REW|BUTTON_REL) 348#define CALCULATOR_OPERATORS BUTTON_REC 349 350#elif CONFIG_KEYPAD == SAMSUNG_YH92X_PAD 351 352#define CALCULATOR_LEFT BUTTON_LEFT 353#define CALCULATOR_RIGHT BUTTON_RIGHT 354#define CALCULATOR_UP BUTTON_UP 355#define CALCULATOR_DOWN BUTTON_DOWN 356#define CALCULATOR_QUIT (BUTTON_REW|BUTTON_REPEAT) 357#define CALCULATOR_INPUT BUTTON_PLAY 358#define CALCULATOR_CALC BUTTON_FFWD 359#define CALCULATOR_CLEAR (BUTTON_REW|BUTTON_REL) 360 361#elif CONFIG_KEYPAD == PBELL_VIBE500_PAD 362 363#define CALCULATOR_LEFT BUTTON_PREV 364#define CALCULATOR_RIGHT BUTTON_NEXT 365#define CALCULATOR_UP BUTTON_UP 366#define CALCULATOR_DOWN BUTTON_DOWN 367#define CALCULATOR_QUIT BUTTON_REC 368#define CALCULATOR_INPUT BUTTON_OK 369#define CALCULATOR_CALC BUTTON_PLAY 370#define CALCULATOR_CLEAR BUTTON_CANCEL 371 372#elif CONFIG_KEYPAD == MPIO_HD200_PAD 373#define CALCULATOR_LEFT BUTTON_REW 374#define CALCULATOR_RIGHT BUTTON_FF 375#define CALCULATOR_QUIT (BUTTON_REC|BUTTON_PLAY) 376#define CALCULATOR_INPUT BUTTON_FUNC 377#define CALCULATOR_CALC BUTTON_PLAY 378#define CALCULATOR_CLEAR BUTTON_REC 379 380#elif CONFIG_KEYPAD == MPIO_HD300_PAD 381#define CALCULATOR_LEFT BUTTON_REW 382#define CALCULATOR_RIGHT BUTTON_FF 383#define CALCULATOR_UP BUTTON_UP 384#define CALCULATOR_DOWN BUTTON_DOWN 385#define CALCULATOR_QUIT (BUTTON_MENU|BUTTON_REPEAT) 386#define CALCULATOR_INPUT BUTTON_ENTER 387#define CALCULATOR_CALC BUTTON_PLAY 388#define CALCULATOR_CLEAR BUTTON_MENU 389 390#elif CONFIG_KEYPAD == SANSA_FUZEPLUS_PAD 391#define CALCULATOR_LEFT BUTTON_LEFT 392#define CALCULATOR_RIGHT BUTTON_RIGHT 393#define CALCULATOR_UP BUTTON_UP 394#define CALCULATOR_DOWN BUTTON_DOWN 395#define CALCULATOR_QUIT (BUTTON_BACK|BUTTON_REPEAT) 396#define CALCULATOR_INPUT BUTTON_SELECT 397#define CALCULATOR_CALC BUTTON_PLAYPAUSE 398#define CALCULATOR_CLEAR (BUTTON_BACK|BUTTON_REL) 399 400#elif (CONFIG_KEYPAD == SANSA_CONNECT_PAD) 401#define CALCULATOR_LEFT BUTTON_LEFT 402#define CALCULATOR_RIGHT BUTTON_RIGHT 403#define CALCULATOR_UP BUTTON_UP 404#define CALCULATOR_DOWN BUTTON_DOWN 405#define CALCULATOR_UP_W_SHIFT BUTTON_SCROLL_BACK 406#define CALCULATOR_DOWN_W_SHIFT BUTTON_SCROLL_FWD 407#define CALCULATOR_QUIT BUTTON_POWER 408#define CALCULATOR_INPUT_CALC_PRE BUTTON_SELECT 409#define CALCULATOR_INPUT (BUTTON_SELECT|BUTTON_REL) 410#define CALCULATOR_CALC BUTTON_NEXT 411#define CALCULATOR_CLEAR BUTTON_PREV 412 413#elif (CONFIG_KEYPAD == SAMSUNG_YPR0_PAD) 414 415#define CALCULATOR_LEFT BUTTON_LEFT 416#define CALCULATOR_RIGHT BUTTON_RIGHT 417#define CALCULATOR_UP BUTTON_UP 418#define CALCULATOR_DOWN BUTTON_DOWN 419#define CALCULATOR_QUIT BUTTON_BACK 420#define CALCULATOR_INPUT BUTTON_SELECT 421#define CALCULATOR_CALC BUTTON_MENU 422#define CALCULATOR_CLEAR BUTTON_USER 423 424#elif (CONFIG_KEYPAD == HM60X_PAD) 425 426#define CALCULATOR_LEFT BUTTON_LEFT 427#define CALCULATOR_RIGHT BUTTON_RIGHT 428#define CALCULATOR_UP BUTTON_UP 429#define CALCULATOR_DOWN BUTTON_DOWN 430#define CALCULATOR_QUIT BUTTON_POWER 431#define CALCULATOR_INPUT BUTTON_SELECT 432#define CALCULATOR_CALC (BUTTON_UP|BUTTON_POWER) 433#define CALCULATOR_CLEAR (BUTTON_DOWN|BUTTON_POWER) 434 435#elif (CONFIG_KEYPAD == HM801_PAD) 436 437#define CALCULATOR_LEFT BUTTON_LEFT 438#define CALCULATOR_RIGHT BUTTON_RIGHT 439#define CALCULATOR_UP BUTTON_UP 440#define CALCULATOR_DOWN BUTTON_DOWN 441#define CALCULATOR_QUIT BUTTON_POWER 442#define CALCULATOR_INPUT BUTTON_SELECT 443#define CALCULATOR_CALC BUTTON_PLAY 444#define CALCULATOR_CLEAR BUTTON_PREV 445 446#elif CONFIG_KEYPAD == SONY_NWZ_PAD 447#define CALCULATOR_LEFT BUTTON_LEFT 448#define CALCULATOR_RIGHT BUTTON_RIGHT 449#define CALCULATOR_UP BUTTON_UP 450#define CALCULATOR_DOWN BUTTON_DOWN 451#define CALCULATOR_QUIT (BUTTON_BACK|BUTTON_REPEAT) 452#define CALCULATOR_INPUT BUTTON_PLAY 453#define CALCULATOR_CALC BUTTON_POWER 454#define CALCULATOR_CLEAR BUTTON_BACK 455 456#elif CONFIG_KEYPAD == CREATIVE_ZEN_PAD 457#define CALCULATOR_LEFT BUTTON_LEFT 458#define CALCULATOR_RIGHT BUTTON_RIGHT 459#define CALCULATOR_UP BUTTON_UP 460#define CALCULATOR_DOWN BUTTON_DOWN 461#define CALCULATOR_QUIT BUTTON_BACK 462#define CALCULATOR_INPUT BUTTON_SELECT 463#define CALCULATOR_CALC BUTTON_PLAYPAUSE 464#define CALCULATOR_CLEAR BUTTON_SHORTCUT 465 466#elif CONFIG_KEYPAD == DX50_PAD 467#define CALCULATOR_QUIT BUTTON_POWER 468 469#elif CONFIG_KEYPAD == CREATIVE_ZENXFI2_PAD 470#define CALCULATOR_QUIT BUTTON_POWER 471#define CALCULATOR_INPUT BUTTON_MENU 472 473#elif CONFIG_KEYPAD == AGPTEK_ROCKER_PAD 474#define CALCULATOR_LEFT BUTTON_LEFT 475#define CALCULATOR_RIGHT BUTTON_RIGHT 476#define CALCULATOR_UP BUTTON_UP 477#define CALCULATOR_DOWN BUTTON_DOWN 478#define CALCULATOR_QUIT BUTTON_POWER 479#define CALCULATOR_INPUT BUTTON_SELECT 480#define CALCULATOR_CALC BUTTON_VOLUP 481#define CALCULATOR_CLEAR (BUTTON_SELECT|BUTTON_REPEAT) 482 483#elif CONFIG_KEYPAD == XDUOO_X3_PAD || CONFIG_KEYPAD == XDUOO_X3II_PAD || CONFIG_KEYPAD == XDUOO_X20_PAD 484#define CALCULATOR_LEFT BUTTON_PREV 485#define CALCULATOR_RIGHT BUTTON_NEXT 486#define CALCULATOR_UP BUTTON_HOME 487#define CALCULATOR_DOWN BUTTON_OPTION 488#define CALCULATOR_QUIT BUTTON_POWER 489#define CALCULATOR_INPUT_CALC_PRE (BUTTON_OPTION|BUTTON_REPEAT) 490#define CALCULATOR_INPUT (BUTTON_PLAY|BUTTON_REL) 491#define CALCULATOR_CALC (BUTTON_PLAY|BUTTON_REPEAT) 492#define CALCULATOR_CLEAR (BUTTON_POWER|BUTTON_REPEAT) 493 494#elif CONFIG_KEYPAD == FIIO_M3K_LINUX_PAD 495#define CALCULATOR_LEFT BUTTON_PREV 496#define CALCULATOR_RIGHT BUTTON_NEXT 497#define CALCULATOR_UP BUTTON_HOME 498#define CALCULATOR_DOWN BUTTON_OPTION 499#define CALCULATOR_QUIT BUTTON_POWER 500#define CALCULATOR_INPUT_CALC_PRE (BUTTON_OPTION|BUTTON_REPEAT) 501#define CALCULATOR_INPUT (BUTTON_PLAY|BUTTON_REL) 502#define CALCULATOR_CALC (BUTTON_PLAY|BUTTON_REPEAT) 503#define CALCULATOR_CLEAR (BUTTON_POWER|BUTTON_REPEAT) 504 505#elif CONFIG_KEYPAD == IHIFI_770_PAD || CONFIG_KEYPAD == IHIFI_800_PAD 506#define CALCULATOR_LEFT BUTTON_HOME 507#define CALCULATOR_RIGHT BUTTON_VOL_DOWN 508#define CALCULATOR_UP BUTTON_PREV 509#define CALCULATOR_DOWN BUTTON_NEXT 510#define CALCULATOR_QUIT BUTTON_POWER 511#define CALCULATOR_INPUT_CALC_PRE (BUTTON_HOME|BUTTON_REPEAT) 512#define CALCULATOR_INPUT (BUTTON_PLAY|BUTTON_REL) 513#define CALCULATOR_CALC (BUTTON_PLAY|BUTTON_REPEAT) 514#define CALCULATOR_CLEAR (BUTTON_POWER|BUTTON_REPEAT) 515 516#elif CONFIG_KEYPAD == EROSQ_PAD 517#define CALCULATOR_LEFT BUTTON_SCROLL_BACK 518#define CALCULATOR_RIGHT BUTTON_SCROLL_FWD 519#define CALCULATOR_UP BUTTON_PREV 520#define CALCULATOR_DOWN BUTTON_NEXT 521#define CALCULATOR_QUIT BUTTON_POWER 522#define CALCULATOR_INPUT BUTTON_PLAY 523#define CALCULATOR_CALC BUTTON_MENU 524#define CALCULATOR_CLEAR BUTTON_BACK 525 526#elif CONFIG_KEYPAD == FIIO_M3K_PAD 527#define CALCULATOR_LEFT BUTTON_LEFT 528#define CALCULATOR_RIGHT BUTTON_RIGHT 529#define CALCULATOR_UP BUTTON_UP 530#define CALCULATOR_DOWN BUTTON_DOWN 531#define CALCULATOR_QUIT BUTTON_POWER 532#define CALCULATOR_INPUT BUTTON_PLAY 533#define CALCULATOR_CALC BUTTON_MENU 534#define CALCULATOR_CLEAR BUTTON_BACK 535 536#elif CONFIG_KEYPAD == SHANLING_Q1_PAD 537#define CALCULATOR_QUIT BUTTON_POWER 538 539#elif CONFIG_KEYPAD == SDL_PAD 540/* use touchscreen */ 541#elif CONFIG_KEYPAD == MA_PAD 542#define CALCULATOR_LEFT BUTTON_LEFT 543#define CALCULATOR_RIGHT BUTTON_RIGHT 544#define CALCULATOR_UP BUTTON_UP 545#define CALCULATOR_DOWN BUTTON_DOWN 546#define CALCULATOR_QUIT (BUTTON_BACK|BUTTON_REPEAT) 547#define CALCULATOR_INPUT BUTTON_PLAY 548#define CALCULATOR_CALC BUTTON_MENU 549#define CALCULATOR_CLEAR BUTTON_BACK 550 551#elif CONFIG_KEYPAD == RG_NANO_PAD 552 553#define CALCULATOR_LEFT BUTTON_LEFT 554#define CALCULATOR_RIGHT BUTTON_RIGHT 555#define CALCULATOR_UP BUTTON_UP 556#define CALCULATOR_DOWN BUTTON_DOWN 557#define CALCULATOR_QUIT BUTTON_START 558#define CALCULATOR_INPUT BUTTON_A 559#define CALCULATOR_CALC BUTTON_X 560#define CALCULATOR_CLEAR BUTTON_B 561 562#else 563#error No keymap defined! 564#endif 565 566#ifdef HAVE_TOUCHSCREEN 567#ifndef CALCULATOR_LEFT 568#define CALCULATOR_LEFT BUTTON_MIDLEFT 569#endif 570#ifndef CALCULATOR_RIGHT 571#define CALCULATOR_RIGHT BUTTON_MIDRIGHT 572#endif 573#ifndef CALCULATOR_UP 574#define CALCULATOR_UP BUTTON_TOPMIDDLE 575#endif 576#ifndef CALCULATOR_DOWN 577#define CALCULATOR_DOWN BUTTON_BOTTOMMIDDLE 578#endif 579#ifndef CALCULATOR_CALC 580#define CALCULATOR_CALC BUTTON_BOTTOMRIGHT 581#endif 582#ifndef CALCULATOR_INPUT 583#define CALCULATOR_INPUT BUTTON_CENTER 584#endif 585#ifndef CALCULATOR_CLEAR 586#define CALCULATOR_CLEAR BUTTON_TOPRIGHT 587#endif 588 589#include "lib/pluginlib_touchscreen.h" 590static struct ts_raster calc_raster = { X_0_POS, Y_1_POS, 591 BUTTON_COLS*REC_WIDTH, BUTTON_ROWS*REC_HEIGHT, REC_WIDTH, REC_HEIGHT }; 592#endif 593 594enum { 595 basicButtons, 596 sciButtons 597} buttonGroup; 598 599unsigned char* buttonChar[2][5][5] = { 600 { { "MR" , "M+" , "2nd" , "CE" , "C" }, 601 { "7" , "8" , "9" , "/" , "sqr" }, 602 { "4" , "5" , "6" , "*" , "x^2" }, 603 { "1" , "2" , "3" , "-" , "1/x" }, 604 { "0" , "+/-", "." , "+" , "=" } }, 605 606 { { "n!" , "PI" , "1st" , "sin" , "asi" }, 607 { "7" , "8" , "9" , "cos" , "aco" }, 608 { "4" , "5" , "6" , "tan" , "ata" }, 609 { "1" , "2" , "3" , "ln" , "e^x" }, 610 { "0" , "+/-", "." , "log" , "x^y" } } 611}; 612 613enum { btn_MR , btn_M , btn_bas , btn_CE , btn_C , 614 btn_7 , btn_8 , btn_9 , btn_div , btn_sqr , 615 btn_4 , btn_5 , btn_6 , btn_time , btn_square , 616 btn_1 , btn_2 , btn_3 , btn_minus , btn_rec , 617 btn_0 , btn_sign , btn_dot , btn_add , btn_equal 618 }; 619 620enum { sci_fac, sci_pi , sci_sci , sci_sin , sci_asin , 621 sci_7 , sci_8 , sci_9 , sci_cos , sci_acos , 622 sci_4 , sci_5 , sci_6 , sci_tan , sci_atan , 623 sci_1 , sci_2 , sci_3 , sci_ln , sci_exp , 624 sci_0 , sci_sign , sci_dot , sci_log , sci_xy 625 }; 626 627#define MINIMUM 0.000000000001 /* e-12 */ 628 /* ^ ^ ^ ^ */ 629 /* 123456789abcdef */ 630 631#define DIGITLEN 10 /* must <= 10 */ 632#define SCIENTIFIC_FORMAT ( power < -(DIGITLEN-3) || power > (DIGITLEN)) 633 /* 0.000 00000 0001 */ 634 /* ^ ^ ^ ^ ^ ^ */ 635 /* DIGITLEN 12345 6789a bcdef */ 636 /* power 12 34567 89abc def */ 637 /* 10^- 123 45678 9abcd ef */ 638 639unsigned char buf[19];/* 18 bytes of output line, 640 buf[0] is operator 641 buf[1] = 'M' if memTemp is not 0 642 buf[2] = ' ' 643 644 if SCIENTIFIC_FORMAT 645 buf[2]-buf[12] or buf[3]-buf[13] = result; 646 format X.XXXXXXXX 647 buf[13] or buf[14] -buf[17] = power; 648 format eXXX or e-XXX 649 else 650 buf[3]-buf[6] = ' '; 651 buf[7]-buf[17] = result; 652 653 buf[18] = '\0' */ 654 655unsigned char typingbuf[DIGITLEN+2];/* byte 0 is sign or ' ', 656 byte 1~DIGITLEN are num and '.' 657 byte (DIGITLEN+1) is '\0' */ 658unsigned char* typingbufPointer = typingbuf; 659 660double result = 0; /* main operand, format 0.xxxxx */ 661int power = 0; /* 10^power */ 662double modifier = 0.1; /* position of next input */ 663double operand = 0; /* second operand, format 0.xxxxx */ 664int operandPower = 0; /* 10^power of second operand */ 665char oper = ' '; /* operators: + - * / */ 666bool operInputted = false; /* false: do calculation first and 667 replace current oper 668 true: just replace current oper */ 669 670double memTemp = 0; /* temp memory */ 671int memTempPower = 0; /* 10^^power of memTemp */ 672 673int btn_row, btn_col; /* current position index for button */ 674int prev_btn_row, prev_btn_col; /* previous cursor position */ 675#define CAL_BUTTON (btn_row*5+btn_col) 676 677int btn = BUTTON_NONE; 678int lastbtn = BUTTON_NONE; 679 680/* Status of calculator */ 681enum {cal_normal, /* 0, normal status, display result */ 682 cal_typing, /* 1, currently typing, dot hasn't been typed */ 683 cal_dotted, /* 2, currently typing, dot already has been typed. */ 684 cal_error, 685 cal_exit, 686 cal_toDo 687} calStatus; 688 689/* constant table for CORDIC algorithm */ 690static const double cordicTable[51][2]= { 691 /* pow(2,0) - pow(2,-50) atan(pow(2,0) - atan(pow(2,-50) */ 692 {1e+00, 7.853981633974483e-01}, 693 {5e-01, 4.636476090008061e-01}, 694 {2.5e-01, 2.449786631268641e-01}, 695 {1.25e-01, 1.243549945467614e-01}, 696 {6.25e-02, 6.241880999595735e-02}, 697 {3.125e-02, 3.123983343026828e-02}, 698 {1.5625e-02, 1.562372862047683e-02}, 699 {7.8125e-03, 7.812341060101111e-03}, 700 {3.90625e-03, 3.906230131966972e-03}, 701 {1.953125e-03, 1.953122516478819e-03}, 702 {9.765625e-04, 9.765621895593195e-04}, 703 {4.8828125e-04, 4.882812111948983e-04}, 704 {2.44140625e-04, 2.441406201493618e-04}, 705 {1.220703125e-04, 1.220703118936702e-04}, 706 {6.103515625e-05, 6.103515617420877e-05}, 707 {3.0517578125e-05, 3.051757811552610e-05}, 708 {1.52587890625e-05, 1.525878906131576e-05}, 709 {7.62939453125e-06, 7.629394531101970e-06}, 710 {3.814697265625e-06, 3.814697265606496e-06}, 711 {1.9073486328125e-06, 1.907348632810187e-06}, 712 {9.5367431640625e-07, 9.536743164059608e-07}, 713 {4.76837158203125e-07, 4.768371582030888e-07}, 714 {2.384185791015625e-07, 2.384185791015580e-07}, 715 {1.1920928955078125e-07, 1.192092895507807e-07}, 716 {5.9604644775390625e-08, 5.960464477539055e-08}, 717 {2.98023223876953125e-08, 2.980232238769530e-08}, 718 {1.490116119384765625e-08, 1.490116119384765e-08}, 719 {7.450580596923828125e-09, 7.450580596923828e-09}, 720 {3.7252902984619140625e-09, 3.725290298461914e-09}, 721 {1.86264514923095703125e-09, 1.862645149230957e-09}, 722 {9.31322574615478515625e-10, 9.313225746154785e-10}, 723 {4.656612873077392578125e-10, 4.656612873077393e-10}, 724 {2.3283064365386962890625e-10, 2.328306436538696e-10}, 725 {1.16415321826934814453125e-10, 1.164153218269348e-10}, 726 {5.82076609134674072265625e-11, 5.820766091346741e-11}, 727 {2.910383045673370361328125e-11, 2.910383045673370e-11}, 728 {1.4551915228366851806640625e-11, 1.455191522836685e-11}, 729 {7.2759576141834259033203125e-12, 7.275957614183426e-12}, 730 {3.63797880709171295166015625e-12, 3.637978807091713e-12}, 731 {1.818989403545856475830078125e-12, 1.818989403545856e-12}, 732 {9.094947017729282379150390625e-13, 9.094947017729282e-13}, 733 {4.5474735088646411895751953125e-13, 4.547473508864641e-13}, 734 {2.27373675443232059478759765625e-13, 2.273736754432321e-13}, 735 {1.136868377216160297393798828125e-13, 1.136868377216160e-13}, 736 {5.684341886080801486968994140625e-14, 5.684341886080801e-14}, 737 {2.8421709430404007434844970703125e-14, 2.842170943040401e-14}, 738 {1.42108547152020037174224853515625e-14, 1.421085471520200e-14}, 739 {7.10542735760100185871124267578125e-15, 7.105427357601002e-15}, 740 {3.552713678800500929355621337890625e-15, 3.552713678800501e-15}, 741 {1.7763568394002504646778106689453125e-15, 1.776356839400250e-15}, 742 {8.8817841970012523233890533447265625e-16, 8.881784197001252e-16} 743}; 744 745static void doMultiple(double* operandOne, int* powerOne, 746 double operandTwo, int powerTwo); 747static void doAdd (double* operandOne, int* powerOne, 748 double operandTwo, int powerTwo); 749static void doExponent(double* operandOne, int* powerOne, 750 double operandTwo, int powerTwo); 751static void printResult(void); 752static void formatResult(void); 753static void oneOperand(void); 754 755static void drawLines(void); 756static void drawButtons(int group); 757 758#ifndef _WIN32 759double strtod(const char *nptr, char **endptr); 760#endif 761long long atoll(const char *nptr); 762 763/* ----------------------------------------------------------------------- 764Standard library function 765----------------------------------------------------------------------- */ 766#ifndef _WIN32 767double strtod(const char *nptr, char **endptr) 768{ 769 double out; 770 long mantissa; 771 int length=0, end=0; 772 mantissa=atoll(nptr); 773 while(!end) 774 { 775 switch(*nptr) 776 { 777 case '\0': 778 end=1; 779 break; 780 case ',': 781 case '.': 782 case '\'': 783 end=1; 784 /* fallthrough */ 785 default: 786 nptr++; 787 } 788 } 789 out=atoll(nptr); 790 while( (*nptr == '0')||(*nptr == '1')||(*nptr == '2')||(*nptr == '3')||(*nptr == '4')|| 791 (*nptr == '5')||(*nptr == '6')||(*nptr == '7')||(*nptr == '8')||(*nptr == '9') ) 792 { 793 nptr++; 794 length++; 795 } 796 for(;length;length--) 797 out /= 10; 798 out += mantissa; 799 if(endptr != NULL) 800 *endptr=(char *) nptr; 801 return out; 802} 803#endif 804 805// WARNING Unsafe: Use strtoll instead 806long long atoll(const char *nptr) 807{ 808 long long result=0; 809 char negative=0; 810 while( (*nptr == ' ') || (*nptr == '\f') || (*nptr == '\n')|| 811 (*nptr == '\r') || (*nptr == '\t') || (*nptr == '\v') ) 812 nptr++; 813 if(*nptr == '+') 814 nptr++; 815 if(*nptr == '-') 816 { 817 negative++; 818 nptr++; 819 } 820 while (*nptr) 821 { 822 if( (*nptr < '0') || (*nptr > '9') ) 823 break; 824 result *=10; 825 result+= (*(nptr++) -'0'); 826 } 827 if(negative) 828 result = 0 - result; 829 return result; 830} 831 832/* ----------------------------------------------------------------------- 833Handy functions 834----------------------------------------------------------------------- */ 835static void cleartypingbuf(void) 836{ 837 int k; 838 for( k=1; k<=(DIGITLEN+1); k++) 839 typingbuf[k] = 0; 840 typingbuf[0] = ' '; 841 typingbufPointer = typingbuf+1; 842} 843static void clearbuf(void) 844{ 845 int k; 846 for(k=0;k<18;k++) 847 buf[k]=' '; 848 buf[18] = 0; 849} 850static void clearResult(void) 851{ 852 result = 0; 853 power = 0; 854 modifier = 0.1; 855} 856 857static void clearInput(void) 858{ 859 calStatus = cal_normal; 860 clearResult(); 861 cleartypingbuf(); 862 rb->lcd_clear_display(); 863 drawButtons(buttonGroup); 864 drawLines(); 865} 866 867static void clearOperand(void) 868{ 869 operand = 0; 870 operandPower = 0; 871} 872 873static void clearMemTemp(void) 874{ 875 memTemp = 0; 876 memTempPower = 0; 877} 878 879static void clearOper(void) 880{ 881 oper = ' '; 882 operInputted = false; 883} 884 885static void clearMem(void) 886{ 887 clearInput(); 888 clearMemTemp(); 889 clearOperand(); 890 clearOper(); 891 btn = BUTTON_NONE; 892} 893 894static void switchOperands(void) 895{ 896 double tempr = operand; 897 int tempp = operandPower; 898 operand = result; 899 operandPower = power; 900 result = tempr; 901 power = tempp; 902} 903 904static void drawLines(void) 905{ 906 int i; 907 rb->lcd_hline(0, LCD_WIDTH, Y_1_POS-1); 908 for (i = 0; i < 5 ; i++) 909 rb->lcd_hline(0, LCD_WIDTH, Y_1_POS+i*REC_HEIGHT); 910 for (i = 0; i < 4 ; i++) 911 rb->lcd_vline(X_1_POS+i*REC_WIDTH, Y_1_POS, LCD_HEIGHT); 912} 913 914static void drawButtons(int group) 915{ 916 int i, j, w, h; 917 for (i = 0; i <= 4; i++){ 918 for (j = 0; j <= 4; j++){ 919 rb->lcd_getstringsize( buttonChar[group][i][j],&w,&h); 920 if (i == btn_row && j == btn_col) /* selected item */ 921 rb->lcd_set_drawmode(DRMODE_SOLID); 922 else 923 rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID); 924 rb->lcd_fillrect( X_0_POS + j*REC_WIDTH, 925 Y_1_POS + i*REC_HEIGHT, 926 REC_WIDTH, REC_HEIGHT+1); 927 if (i == btn_row && j == btn_col) /* selected item */ 928 rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID); 929 else 930 rb->lcd_set_drawmode(DRMODE_SOLID); 931 rb->lcd_putsxy( X_0_POS + j*REC_WIDTH + (REC_WIDTH - w)/2, 932 Y_1_POS + i*REC_HEIGHT + (REC_HEIGHT - h)/2 + 1, 933 buttonChar[group][i][j] ); 934 } 935 } 936 rb->lcd_set_drawmode(DRMODE_SOLID); 937} 938 939/* ----------------------------------------------------------------------- 940Initiate calculator 941----------------------------------------------------------------------- */ 942static void cal_initial (void) 943{ 944 int w,h; 945 946 rb->lcd_getstringsize("2nd",&w,&h); 947 if (w > REC_WIDTH || h > REC_HEIGHT) 948 rb->lcd_setfont(FONT_SYSFIXED); 949 950 rb->lcd_clear_display(); 951 952#ifdef CALCULATOR_OPERATORS 953 /* basic operators are available through separate button */ 954 buttonGroup = sciButtons; 955#else 956 buttonGroup = basicButtons; 957#endif 958 959 /* initially, invert button "5" */ 960 btn_row = 2; 961 btn_col = 1; 962 prev_btn_row = btn_row; 963 prev_btn_col = btn_col; 964 drawButtons(buttonGroup); 965 drawLines(); 966 rb->lcd_update(); 967 968 /* initial mem and output display*/ 969 clearMem(); 970 printResult(); 971 972 /* clear button queue */ 973 rb->button_clear_queue(); 974} 975 976/* ----------------------------------------------------------------------- 977 mySqrt uses Heron's algorithm, which is the Newtone-Raphson algorhitm 978 in it's private case for sqrt. 979 Thanks BlueChip for his intro text and Dave Straayer for the actual name. 980 ----------------------------------------------------------------------- */ 981static double mySqrt(double square) 982{ 983 int k = 0; 984 double temp = 0; 985 double root= ABS(square+1)/2; 986 987 while( ABS(root - temp) > MINIMUM ){ 988 temp = root; 989 root = (square/temp + temp)/2; 990 k++; 991 if (k>10000) return 0; 992 } 993 994 return root; 995} 996 997/*Uses the sequence sum(x^k/k!) that tends to exp(x)*/ 998static double myExp (double x) { 999 unsigned int k=0; 1000 double res=0, xPow=1,fact=1,toAdd; 1001 1002 do { 1003 toAdd = xPow/fact; 1004 res += toAdd; 1005 xPow *= x; //xPow = x^k 1006 k++; 1007 fact*=k; //fact = k! 1008 } while (ABS(toAdd) > MINIMUM && xPow<1e302); 1009 return res; 1010} 1011 1012/*myLn : uses the series ln⁡(a) = 2 * ∑(1/(2n+1) * ((a-1)/(a+1))^(2k+1) )*/ 1013static double myLn (double a) { 1014 unsigned int k=1; 1015 double res=0,xPow,xSquare,fract=1,toAdd; 1016 1017 xPow = (a-1)/(a+1); 1018 xSquare = xPow*xPow; 1019 1020 do { 1021 toAdd = fract*xPow; 1022 res += toAdd; 1023 xPow *= xSquare; // ((a-1)/(a+1))^k 1024 k+=2; 1025 fract=1./k; 1026 } while (ABS(toAdd) > MINIMUM); 1027 return res * 2; 1028} 1029 1030 1031/* ----------------------------------------------------------------------- 1032 transcendFunc uses CORDIC (COordinate Rotation DIgital Computer) method 1033 transcendFunc can do sin,cos,log,exp,asin,acos,atan 1034 input parameter is angle 1035----------------------------------------------------------------------- */ 1036static void transcendFunc(char* func, double* tt, int* ttPower) 1037{ 1038 double t = (*tt); 1039 int tPower = *ttPower; 1040 int sign = 1; 1041 int n = 50; /* n <=50, tables are all <= 50 */ 1042 int j; 1043 double x,y,z,xt,yt,zt; 1044 1045 if (tPower < -998) { 1046 calStatus = cal_normal; 1047 return; 1048 } 1049 if (tPower > 8) { 1050 calStatus = cal_error; 1051 return; 1052 } 1053 *ttPower = 0; 1054 calStatus = cal_normal; 1055 1056 /* Powerscale */ 1057 while (tPower > 0){ 1058 t *= 10; 1059 tPower--; 1060 } 1061 while (tPower < 0) { 1062 t /= 10; 1063 tPower++; 1064 } 1065 1066 /* Vectoring mode */ 1067 if(func[0] == 'a' || func[0] == 'A') { 1068 if(func[1] == 's' || func[1] == 'S') { /* arcsin */ 1069 /* arcsin input must be in [-1, 1] */ 1070 if(t < -1.0 || t > 1.0) { 1071 calStatus = cal_error; 1072 return; 1073 } 1074 /* Avoid division by zero */ 1075 if(t == 1.0) { 1076 *tt = 90.0; /* arcsin(1) = 90° */ 1077 return; 1078 } 1079 if(t == -1.0) { 1080 *tt = -90.0; /* arcsin(-1) = -90° */ 1081 return; 1082 } 1083 1084 /* Vectoring mode */ 1085 /* Start with vector (sqrt(1-t^2), t) and find its angle */ 1086 double magnitude = mySqrt(1.0 - t*t); 1087 x = magnitude; 1088 y = t; 1089 z = 0.0; 1090 1091 /* Vectoring mode: drive y to 0 */ 1092 for (j = 1; j < n + 2; j++) { 1093 if(y >= 0) { 1094 /* Rotate clockwise (negative direction) */ 1095 xt = x + y * cordicTable[j-1][0]; 1096 yt = y - x * cordicTable[j-1][0]; 1097 zt = z - cordicTable[j-1][1]; 1098 } else { 1099 /* Rotate anticlockwise (positive direction) */ 1100 xt = x - y * cordicTable[j-1][0]; 1101 yt = y + x * cordicTable[j-1][0]; 1102 zt = z + cordicTable[j-1][1]; 1103 } 1104 x = xt; 1105 y = yt; 1106 z = zt; 1107 } 1108 *tt = z * 180/M_PI * -1; /* Convert to degrees and invert sign */ 1109 return; 1110 } 1111 else if(func[1] == 'c' || func[1] == 'C') { /* arccos */ 1112 /* arccos input must be in [-1, 1] */ 1113 if(t < -1.0 || t > 1.0) { 1114 calStatus = cal_error; 1115 return; 1116 } 1117 /* For arccos: use arcsin relationship: arccos(t) = π/2 - arcsin(t) */ 1118 double arcsin_input = t; 1119 int arcsin_power = 0; 1120 1121 /* Save current function context */ 1122 char original_func[3]; 1123 strncpy(original_func, func, 3); 1124 1125 transcendFunc("asin", &arcsin_input, &arcsin_power); 1126 1127 if (calStatus == cal_error) { 1128 return; 1129 } 1130 1131 /* arccos(t) = 90° - arcsin(t) */ 1132 /* arcsin_input now contains arcsin(t) in degrees */ 1133 double arccos_degrees = 90.0 - arcsin_input; 1134 *tt = arccos_degrees; 1135 return; 1136 } 1137 else if(func[1] == 't' || func[1] == 'T') { /* arctan */ 1138 /* start with x=1, y=input, z=0 and drive y to 0 */ 1139 x = 1.0; 1140 y = t; 1141 z = 0.0; 1142 1143 /* Vectoring mode: drive y to 0 */ 1144 for (j=1; j<n+2; j++){ 1145 if(y < 0) { 1146 /* Rotate anticlockwise */ 1147 xt = x - y*cordicTable[j-1][0]; 1148 yt = y + x*cordicTable[j-1][0]; 1149 zt = z + cordicTable[j-1][1]; 1150 } else { 1151 /* Rotate clockwise */ 1152 xt = x + y*cordicTable[j-1][0]; 1153 yt = y - x*cordicTable[j-1][0]; 1154 zt = z - cordicTable[j-1][1]; 1155 } 1156 x = xt; y = yt; z = zt; 1157 } 1158 *tt = z * 180/M_PI * -1; /* Convert back to degrees and invert sign */ 1159 return; 1160 } 1161 } 1162 1163 if( func[0] =='s' || func[0] =='S'|| func[0] =='t' || func[0] =='T') 1164 sign = SIGN(t); 1165 else { 1166 /* if( func[0] =='c' || func[0] =='C') */ 1167 sign = 1; 1168 } 1169 t = ABS(t); 1170 1171 /* Jump to radians for rotation mode */ 1172 t = t * M_PI / 180; 1173 1174 while (tPower > 0){ 1175 t *= 10; 1176 tPower--; 1177 } 1178 while (tPower < 0) { 1179 t /= 10; 1180 tPower++; 1181 } 1182 j = 0; 1183 while (t > j*M_TWOPI) {j++;} 1184 t -= (j-1)*M_TWOPI; 1185 if (M_PI_2 < t && t < 3*M_PI_2){ 1186 t = M_PI - t; 1187 if (func[0] =='c' || func[0] =='C') 1188 sign = -1; 1189 else if (func[0] =='t' || func[0] =='T') 1190 t*=-1; 1191 } 1192 else if ( 3*M_PI_2 <= t && t <= M_TWOPI) 1193 t -= M_TWOPI; 1194 1195 x = 0.60725293500888; y = 0; z = t; 1196 for (j=1;j<n+2;j++){ 1197 xt = x - SIGN(z) * y*cordicTable[j-1][0]; 1198 yt = y + SIGN(z) * x*cordicTable[j-1][0]; 1199 zt = z - SIGN(z) * cordicTable[j-1][1]; 1200 x = xt; 1201 y=yt; 1202 z=zt; 1203 } 1204 if( func[0] =='s' || func[0] =='S') { 1205 *tt = sign*y; 1206 return; 1207 } 1208 else if( func[0] =='c' || func[0] =='C') { 1209 *tt = sign*x; 1210 return; 1211 } 1212 else /*if( func[0] =='t' || func[0] =='T')*/ { 1213 if(t==M_PI_2||t==-M_PI_2){ 1214 calStatus = cal_error; 1215 return; 1216 } 1217 else{ 1218 *tt = sign*(y/x); 1219 return; 1220 } 1221 } 1222 1223} 1224/* ----------------------------------------------------------------------- 1225 add in scientific number format 1226----------------------------------------------------------------------- */ 1227static void doAdd (double* operandOne, int* powerOne, 1228 double operandTwo, int powerTwo) 1229{ 1230 if ( *powerOne >= powerTwo ){ 1231 if (*powerOne - powerTwo <= DIGITLEN+1){ 1232 while (powerTwo < *powerOne){ 1233 operandTwo /=10; 1234 powerTwo++; 1235 } 1236 *operandOne += operandTwo; 1237 } 1238 /*do nothing if operandTwo is too small*/ 1239 } 1240 else{ 1241 if (powerTwo - *powerOne <= DIGITLEN+1){ 1242 while(powerTwo > *powerOne){ 1243 *operandOne /=10; 1244 (*powerOne)++; 1245 } 1246 (*operandOne) += operandTwo; 1247 } 1248 else{/* simply copy operandTwo if operandOne is too small */ 1249 *operandOne = operandTwo; 1250 *powerOne = powerTwo; 1251 } 1252 } 1253} 1254/* ----------------------------------------------------------------------- 1255multiple in scientific number format 1256----------------------------------------------------------------------- */ 1257static void doMultiple(double* operandOne, int* powerOne, 1258 double operandTwo, int powerTwo) 1259{ 1260 (*operandOne) *= operandTwo; 1261 (*powerOne) += powerTwo; 1262} 1263 1264/* ----------------------------------------------------------------------- 1265exponentiate in scientific number format 1266----------------------------------------------------------------------- */ 1267static void doExponent(double* operandOne, int* powerOne, 1268 double operandTwo, int powerTwo) 1269{ 1270 char negative=0; 1271 char *lastDigit; 1272 char negativeBuffer[25]; 1273 if (*operandOne == 0) 1274 { 1275 if (operandTwo == 0) 1276 { 1277 calStatus=cal_error; // result is undefined 1278 } 1279 else{ 1280 *powerOne = 0; 1281 *operandOne = 0; 1282 } 1283 return; 1284 } 1285 if (operandTwo == 0) 1286 { 1287 *powerOne = 1; 1288 *operandOne = 0.1; 1289 return; 1290 } 1291 if (operandTwo < 0) 1292 { 1293 negative+=2; 1294 operandTwo= ABS(operandTwo); 1295 } 1296 if (*operandOne < 0) 1297 { 1298#if MEMORYSIZE < 8 1299 (void)negativeBuffer; 1300 (void)lastDigit; 1301 calStatus=cal_error; 1302 return; 1303#else 1304 if(powerTwo < 0) 1305 { 1306 calStatus=cal_error; // result is imaginary 1307 return; 1308 } 1309 1310 /*Truncate operandTwo to three places past the radix 1311 in order to eliminate floating point artifacts 1312 (function should set error if truncating a non-integer) */ 1313 rb->snprintf(negativeBuffer, 25, "%.*f", powerTwo+3, operandTwo); 1314 operandTwo = strtod(negativeBuffer, NULL); 1315 1316 /*Truncate operandTwo to powerTwo digits by way of string 1317 in order to confirm operandTwo *10^powerTwo is an integer*/ 1318 rb->snprintf(negativeBuffer, 25, "%.*f", powerTwo, operandTwo); 1319 1320 if(strtod(negativeBuffer, &lastDigit) != operandTwo) 1321 { 1322 calStatus=cal_error; // result is imaginary 1323 return; 1324 } 1325 if(rb->atoi(lastDigit-1) % 2) 1326 negative++; 1327#endif 1328 } 1329 (*operandOne) = myLn(ABS(*operandOne)) + (double) (*powerOne) * 2.302585092994046; 1330 (*powerOne) = 0; 1331 doMultiple(operandOne, powerOne, ABS(operandTwo), powerTwo); 1332 while(*powerOne) 1333 { 1334 if(*powerOne > 0) 1335 { 1336 (*operandOne) *= 10; 1337 (*powerOne) --; 1338 } 1339 else{ 1340 (*operandOne) /= 10; 1341 (*powerOne) ++; 1342 } 1343 } 1344 (*operandOne) = myExp(*operandOne); 1345 if(negative & 2) 1346 (*operandOne) = 1/(*operandOne); 1347 if(negative & 1) 1348 *operandOne = -(*operandOne); 1349} 1350 1351/* ----------------------------------------------------------------------- 1352Handles all one operand calculations 1353----------------------------------------------------------------------- */ 1354static void oneOperand(void) 1355{ 1356 int k = 0; 1357 1358 if (buttonGroup == basicButtons){ 1359 switch(CAL_BUTTON){ 1360 case btn_sqr: 1361 if (result<0) 1362 calStatus = cal_error; 1363 else{ 1364 if (power%2 == 1){ 1365 result = (mySqrt(result*10))/10; 1366 power = (power+1) / 2; 1367 } 1368 else{ 1369 result = mySqrt(result); 1370 power = power / 2; 1371 } 1372 calStatus = cal_normal; 1373 } 1374 break; 1375 case btn_square: 1376 power *= 2; 1377 result *= result; 1378 calStatus = cal_normal; 1379 break; 1380 1381 case btn_rec: 1382 if (result==0) 1383 calStatus = cal_error; 1384 else{ 1385 power = -power; 1386 result = 1/result; 1387 calStatus = cal_normal; 1388 } 1389 break; 1390 default: 1391 calStatus = cal_toDo; 1392 break; /* just for the safety */ 1393 } 1394 } 1395 else{ /* sciButtons */ 1396 switch(CAL_BUTTON){ 1397 case sci_sin: 1398 transcendFunc("sin", &result, &power); 1399 break; 1400 case sci_cos: 1401 transcendFunc("cos", &result, &power); 1402 break; 1403 case sci_tan: 1404 transcendFunc("tan", &result, &power); 1405 break; 1406 case sci_asin: 1407 transcendFunc("asin", &result, &power); 1408 break; 1409 case sci_acos: 1410 transcendFunc("acos", &result, &power); 1411 break; 1412 case sci_atan: 1413 transcendFunc("atan", &result, &power); 1414 break; 1415 case sci_fac: 1416 if (power<0 || power>8 || result<0 ) 1417 calStatus = cal_error; 1418 else if(result == 0) { 1419 result = 1; 1420 power = 0; 1421 } 1422 else{ 1423 while(power > 0) { 1424 result *= 10; 1425 power--; 1426 } 1427 if ( ( result - (int)result) > MINIMUM ) 1428 calStatus = cal_error; 1429 else { 1430 k = result; result = 1; 1431 while (k > 1){ 1432 doMultiple(&result, &power, k, 0); 1433 formatResult(); 1434 k--; 1435 } 1436 calStatus = cal_normal; 1437 } 1438 } 1439 break; 1440 case sci_exp: 1441 /*Uses the sequence (1+a/n)^n -> exp(a) */ 1442 if (power>3 || result > 1e3) calStatus = cal_error; 1443 else { 1444 while(power < 0) { 1445 result /= 10; 1446 power++; 1447 } 1448 while (power > 0){ 1449 power--; 1450 result*=10; 1451 } 1452 result = myExp(result); 1453 calStatus = cal_normal; 1454 } 1455 break; 1456 case sci_ln: 1457 if (result<=0) calStatus = cal_error; 1458 else { 1459 //ln(a*10^n) = ln(a) + n*ln(10), with ln(10) ≈ 2.30 1460 result = myLn(result) + power * 2.302585092994046; 1461 power=0; 1462 calStatus = cal_normal; 1463 } 1464 break; 1465 case sci_log: 1466 if (result<=0) calStatus = cal_error; 1467 else { 1468 //log10(a+10^n) = ln(a)/ln(10) + n, with ln(10) ≈ 2.30 1469 result = myLn(result)/2.302585092994046 + power; 1470 power=0; 1471 calStatus = cal_normal; 1472 } 1473 break; 1474 default: 1475 calStatus = cal_toDo; 1476 break; /* just for the safety */ 1477 } 1478 } 1479} 1480 1481 1482/* ----------------------------------------------------------------------- 1483Handles all two operands calculations 1484----------------------------------------------------------------------- */ 1485static void twoOperands(void) 1486{ 1487 switch(oper){ 1488 case '-': 1489 doAdd(&operand, &operandPower, -result, power); 1490 break; 1491 case '+': 1492 doAdd(&operand, &operandPower, result, power); 1493 break; 1494 case '*': 1495 doMultiple(&operand, &operandPower, result, power); 1496 break; 1497 case '/': 1498 if ( ABS(result) > MINIMUM ){ 1499 doMultiple(&operand, &operandPower, 1/result, -power); 1500 } 1501 else 1502 calStatus = cal_error; 1503 break; 1504 case '^': 1505 doExponent(&operand, &operandPower, result, power); 1506 break; 1507 default: /* ' ' */ 1508 switchOperands(); /* counter switchOperands() below */ 1509 break; 1510 } /* switch(oper) */ 1511 switchOperands(); 1512 clearOper(); 1513} 1514 1515/* First, increases *dimen1 by dimen1_delta modulo dimen1_modulo. 1516 If dimen1 wraps, increases *dimen2 by dimen2_delta modulo dimen2_modulo. 1517*/ 1518static void move_with_wrap_and_shift( 1519 int *dimen1, int dimen1_delta, int dimen1_modulo, 1520 int *dimen2, int dimen2_delta, int dimen2_modulo) 1521{ 1522 bool wrapped = false; 1523 1524 *dimen1 += dimen1_delta; 1525 if (*dimen1 < 0) 1526 { 1527 *dimen1 = dimen1_modulo - 1; 1528 wrapped = true; 1529 } 1530 else if (*dimen1 >= dimen1_modulo) 1531 { 1532 *dimen1 = 0; 1533 wrapped = true; 1534 } 1535 1536 if (wrapped) 1537 { 1538 /* Make the dividend always positive to be sure about the result. 1539 Adding dimen2_modulo does not change it since we do it modulo. */ 1540 *dimen2 = (*dimen2 + dimen2_modulo + dimen2_delta) % dimen2_modulo; 1541 } 1542} 1543 1544/* ----------------------------------------------------------------------- 1545Print buttons when switching 1st and 2nd 1546int group = {basicButtons, sciButtons} 1547----------------------------------------------------------------------- */ 1548static void printButtonGroups(int group) 1549{ 1550 drawButtons(group); 1551 drawLines(); 1552 rb->lcd_update(); 1553} 1554/* ----------------------------------------------------------------------- 1555flash the currently marked button 1556----------------------------------------------------------------------- */ 1557static void flashButton(void) 1558{ 1559 int k, w, h; 1560 for (k=2;k>0;k--) 1561 { 1562 rb->lcd_getstringsize( buttonChar[buttonGroup][btn_row][btn_col],&w,&h); 1563 rb->lcd_set_drawmode(DRMODE_SOLID|(k==1) ? 0 : DRMODE_INVERSEVID); 1564 rb->lcd_fillrect( X_0_POS + btn_col*REC_WIDTH + 1, 1565 Y_1_POS + btn_row*REC_HEIGHT + 1, 1566 REC_WIDTH - 1, REC_HEIGHT - 1); 1567 rb->lcd_putsxy( X_0_POS + btn_col*REC_WIDTH + (REC_WIDTH - w)/2, 1568 Y_1_POS + btn_row*REC_HEIGHT + (REC_HEIGHT - h)/2 +1, 1569 buttonChar[buttonGroup][btn_row][btn_col] ); 1570 rb->lcd_update_rect( X_0_POS + btn_col*REC_WIDTH + 1, 1571 Y_1_POS + btn_row*REC_HEIGHT + 1, 1572 REC_WIDTH - 1, REC_HEIGHT - 1); 1573 1574 if (k!= 1) 1575 rb->sleep(HZ/22); 1576 1577 } 1578} 1579 1580/* ----------------------------------------------------------------------- 1581pos is the position that needs animation. pos = [1~18] 1582----------------------------------------------------------------------- */ 1583#if defined(CALCULATOR_CLEAR) || defined(CALCULATOR_OPERATORS) 1584static void deleteAnimation(int pos) 1585{ 1586 int k, w, h, x; 1587 if (pos<1 || pos >18) 1588 return; 1589 1590 rb->lcd_getstringsize("0", &w, &h); 1591 x = (pos==1? 4: LCD_WIDTH - 4 - w); 1592 1593 for (k=0;k<4;k++){ 1594 rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID); 1595 rb->lcd_fillrect(x, Y_1_POS - h -1, w, h); 1596 rb->lcd_set_drawmode(DRMODE_SOLID); 1597 rb->lcd_fillrect(x + (w*k)/8, Y_1_POS - h -1 + (h*k)/8, 1598 (w*(4-k))/4, (h*(4-k))/4); 1599 rb->lcd_update_rect(x, Y_1_POS - h -1, w, h); 1600 rb->sleep(HZ/32); 1601 } 1602} 1603#endif 1604 1605/* ----------------------------------------------------------------------- 1606result may be one of these formats: 16070 1608xxxx.xxxx 16090.xxxx 16100.0000xxxx 1611 1612formatResult() change result to standard format: 0.xxxx 1613if result is close to 0, let it be 0; 1614if result is close to 1, let it be 0.1 and power++; 1615----------------------------------------------------------------------- */ 1616static void formatResult(void) 1617{ 1618 int resultsign = SIGN(result); 1619 result = ABS(result); 1620 if(result > MINIMUM ){ /* doesn't check power, might have problem 1621 input wouldn't, 1622 + - * / of two formatted number wouldn't. 1623 only a calculation that makes a formatted 1624 number (0.xxxx) less than MINIMUM in only 1625 one operation */ 1626 1627 if (result<1){ 1628 while( (int)(result*10) == 0 ){ 1629 result *= 10; 1630 power--; 1631 modifier *= 10; 1632 } 1633 } 1634 else{ /* result >= 1 */ 1635 while( (int)result != 0 ){ 1636 result /= 10; 1637 power++; 1638 modifier /= 10; 1639 } 1640 } /* if result<1 */ 1641 1642 if (result > (1-MINIMUM)){ 1643 result = 0.1; 1644 power++; 1645 modifier /= 10; 1646 } 1647 result *= resultsign; 1648 } 1649 else { 1650 result = 0; 1651 power = 0; 1652 modifier = 0.1; 1653 } 1654} 1655 1656/* ----------------------------------------------------------------------- 1657result2typingbuf() outputs standard format result to typingbuf. 1658case SCIENTIFIC_FORMAT, let temppower = 1; 1659case temppower > 0: print '.' in the middle 1660case temppower <= 0: print '.' in the begining 1661----------------------------------------------------------------------- */ 1662static void result2typingbuf(void) 1663{ 1664 bool haveDot = false; 1665 char tempchar = 0; 1666 int k; 1667 double tempresult = ABS(result); /* positive num makes things simple */ 1668 1669 int temppower; 1670 double tempmodifier = 1; 1671 int count; 1672 1673 if(SCIENTIFIC_FORMAT) 1674 temppower = 1; /* output x.xxxx format */ 1675 else 1676 temppower = power; 1677 1678 cleartypingbuf(); 1679 1680 if(tempresult < MINIMUM){ /* if 0,faster display and avoid complication*/ 1681 typingbuf[0] = ' '; 1682 typingbuf[1] = '0'; 1683 } 1684 else{ /* tempresult > 0 */ 1685 typingbuf[0] = (SIGN(result)<0)?'-':' '; 1686 1687 typingbufPointer = typingbuf; 1688 if(temppower > 0){ 1689 for (k = 0; k<DIGITLEN+1 ; k++){ 1690 typingbufPointer++; 1691 if(temppower || *(typingbufPointer-1) == '.'){ 1692 count = 0; 1693 tempmodifier = tempmodifier/10; 1694 while( (tempresult-tempmodifier*count) > 1695 (tempmodifier-MINIMUM)){ 1696 count++; 1697 } 1698 tempresult -= tempmodifier*count; 1699 tempresult = ABS(tempresult); 1700 temppower-- ; 1701 *typingbufPointer = count + '0'; 1702 } 1703 else{ /* temppower == 0 */ 1704 *typingbufPointer = '.'; 1705 haveDot = true; 1706 } 1707 } /* for */ 1708 } 1709 else{ 1710 haveDot = true; 1711 typingbufPointer++; *typingbufPointer = '0'; 1712 typingbufPointer++; *typingbufPointer = '.'; 1713 for (k = 2; k<DIGITLEN+1 ; k++){ 1714 typingbufPointer++; 1715 count = 0; 1716 if ( (-temppower) < (k-1)){ 1717 tempmodifier = tempmodifier/10; 1718 while((tempresult-tempmodifier*count)>(tempmodifier-MINIMUM)){ 1719 count++; 1720 1721 } 1722 tempresult -= tempmodifier*count; 1723 tempresult = ABS(tempresult); 1724 temppower-- ; 1725 } 1726 *typingbufPointer = count + '0'; 1727 } 1728 } 1729 /* now, typingbufPointer = typingbuf + 16 */ 1730 /* backward strip off 0 and '.' */ 1731 if (haveDot){ 1732 while( (*typingbufPointer == '0') || (*typingbufPointer == '.')){ 1733 tempchar = *typingbufPointer; 1734 *typingbufPointer = 0; 1735 typingbufPointer--; 1736 if (tempchar == '.') break; 1737 } 1738 } 1739 typingbuf[DIGITLEN+1] = 0; 1740 } /* else tempresult > 0 */ 1741} 1742 1743/* ----------------------------------------------------------------------- 1744printResult() generates LCD display. 1745----------------------------------------------------------------------- */ 1746static void printResult(void) 1747{ 1748 int k, w, h; 1749 1750 char operbuf[3] = {0, 0, 0}; 1751 1752 switch_Status: 1753 switch(calStatus){ 1754 case cal_exit: 1755 return; 1756 case cal_error: 1757 clearbuf(); 1758 rb->snprintf(buf, 19, "%18s","Error"); 1759 break; 1760 case cal_toDo: 1761 clearbuf(); 1762 rb->snprintf(buf, 19, "%18s","Coming soon ^_* "); 1763 break; 1764 1765 case cal_normal: 1766 formatResult(); 1767 1768 if( power > 1000 ){ /* power -1 > 999 */ 1769 calStatus = cal_error; 1770 goto switch_Status; 1771 } 1772 if (power < -998 ) /* power -1 < -999 */ 1773 clearResult(); /* too small, let it be 0 */ 1774 1775 result2typingbuf(); 1776 clearbuf(); 1777 1778 operbuf[0] = oper; 1779 operbuf[1] = ( ABS(memTemp) > MINIMUM )?'M':' '; 1780 operbuf[2] = '\0'; 1781 1782 if(SCIENTIFIC_FORMAT){ 1783 /* output format: X.XXXX eXXX */ 1784 if(power > -98){ /* power-1 >= -99, eXXX or e-XX */ 1785 rb->snprintf(buf, 12, "%11s",typingbuf); 1786 for(k=11;k<=14;k++) buf[k] = ' '; 1787 cleartypingbuf(); 1788 rb->snprintf(typingbuf, 5, "e%d",power-1); 1789 rb->snprintf(buf+11, 5, "%4s",typingbuf); 1790 } 1791 else{ /* power-1 <= -100, e-XXX */ 1792 rb->snprintf(buf, 12, "%11s",typingbuf); 1793 rb->snprintf(buf+11, 6, "e%d",power-1); 1794 } 1795 } 1796 else{ 1797 rb->snprintf(buf, 12, "%11s",typingbuf); 1798 } /* if SCIENTIFIC_FORMAT */ 1799 break; 1800 case cal_typing: 1801 case cal_dotted: 1802 clearbuf(); 1803 operbuf[0] = oper; 1804 operbuf[1] = ( ABS(memTemp) > MINIMUM )?'M':' '; 1805 rb->snprintf(buf, 12, "%11s",typingbuf); 1806 break; 1807 1808 } 1809 1810 rb->lcd_getstringsize(buf, &w, &h); 1811 rb->screen_clear_area(rb->screens[0], 0, 0, LCD_WIDTH, Y_1_POS - 1); 1812 rb->lcd_putsxy(4, Y_1_POS - h -1, operbuf); 1813 rb->lcd_putsxy(LCD_WIDTH - w - 4, Y_1_POS - h -1, buf); 1814 rb->lcd_update_rect(0, 1, LCD_WIDTH, Y_1_POS); 1815} 1816 1817/* ----------------------------------------------------------------------- 1818Process typing buttons: 1-9, '.', sign 1819main operand "result" and typingbuf are processed seperately here. 1820----------------------------------------------------------------------- */ 1821static void typingProcess(void){ 1822 switch( CAL_BUTTON ){ 1823 case btn_sign: 1824 if (calStatus == cal_typing || 1825 calStatus == cal_dotted) 1826 typingbuf[0] = (typingbuf[0]=='-')?' ':'-'; 1827 result = -result; 1828 break; 1829 case btn_dot: 1830 operInputted = false; 1831 switch(calStatus){ 1832 case cal_normal: 1833 clearInput(); 1834 *typingbufPointer = '0'; 1835 typingbufPointer++; 1836 /* Fallthrough */ 1837 case cal_typing: 1838 calStatus = cal_dotted; 1839 *typingbufPointer = '.'; 1840 if (typingbufPointer != typingbuf+DIGITLEN+1) 1841 typingbufPointer++; 1842 break; 1843 default: /* cal_dotted */ 1844 break; 1845 } 1846 break; 1847 default: /* 0-9 */ 1848 operInputted = false; 1849 /* normal,0; normal,1-9; typing,0; typing,1-9 */ 1850 switch(calStatus){ 1851 case cal_normal: 1852 if(CAL_BUTTON == btn_0 ) 1853 break; /* first input is 0, ignore */ 1854 clearInput(); 1855 /*no operator means start a new calculation*/ 1856 if (oper ==' ') 1857 clearOperand(); 1858 calStatus = cal_typing; 1859 /* go on typing, no break */ 1860 /* Intentional fallthrough */ 1861 case cal_typing: 1862 case cal_dotted: 1863 switch(CAL_BUTTON){ 1864 case btn_0: 1865 *typingbufPointer = '0'; 1866 break; 1867 default: 1868 *typingbufPointer=(7+btn_col-3*(btn_row-1))+ '0'; 1869 break; 1870 } 1871 if (typingbufPointer!=typingbuf+DIGITLEN+1){ 1872 typingbufPointer++; 1873 1874 {/* result processing */ 1875 if (calStatus == cal_typing) power++; 1876 if (CAL_BUTTON != btn_0) 1877 result= result + 1878 SIGN(result)* 1879 (7+btn_col-3*(btn_row-1))*modifier; 1880 modifier /= 10; 1881 } 1882 } 1883 else /* last byte always '\0' */ 1884 *typingbufPointer = 0; 1885 break; 1886 default: /* cal_error, cal_exit */ 1887 break; 1888 } 1889 break; /* default, 0-9 */ 1890 } /* switch( CAL_BUTTON ) */ 1891} 1892 1893/* ----------------------------------------------------------------------- 1894Handle delete operation 1895main operand "result" and typingbuf are processed seperately here. 1896----------------------------------------------------------------------- */ 1897#ifdef CALCULATOR_CLEAR 1898static void doDelete(void){ 1899 deleteAnimation(18); 1900 switch(calStatus){ 1901 case cal_dotted: 1902 if (*(typingbufPointer-1) == '.'){ 1903 /* if dotted and deleting '.', 1904 change status and delete '.' below */ 1905 calStatus = cal_typing; 1906 } 1907 else{ /* if dotted and not deleting '.', 1908 power stays */ 1909 power++; /* counter "power--;" below */ 1910 } 1911 case cal_typing: 1912 typingbufPointer--; 1913 1914 {/* result processing */ /* 0-9, '.' */ 1915 /* if deleting '.', do nothing */ 1916 if ( *typingbufPointer != '.'){ 1917 power--; 1918 modifier *= 10; 1919 result = result - SIGN(result)* 1920 ((*typingbufPointer)- '0')*modifier; 1921 } 1922 } 1923 1924 *typingbufPointer = 0; 1925 1926 /* if (only one digit left and it's 0) 1927 or no digit left, change status*/ 1928 if ( typingbufPointer == typingbuf+1 || 1929 ( typingbufPointer == typingbuf+2 && 1930 *(typingbufPointer-1) == '0' )) 1931 calStatus = cal_normal; 1932 break; 1933 default: /* normal, error, exit */ 1934 break; 1935 } 1936} 1937#endif 1938/* ----------------------------------------------------------------------- 1939Handle buttons on basic screen 1940----------------------------------------------------------------------- */ 1941static void basicButtonsProcess(void){ 1942 switch (btn) { 1943 case CALCULATOR_INPUT: 1944 if (calStatus == cal_error && (CAL_BUTTON != btn_C) ) break; 1945 flashButton(); 1946 switch( CAL_BUTTON ){ 1947 case btn_MR: 1948 operInputted = false; 1949 result = memTemp; power = memTempPower; 1950 calStatus = cal_normal; 1951 break; 1952 case btn_M: 1953 formatResult(); 1954 if (memTemp > MINIMUM) 1955 doAdd(&memTemp, &memTempPower, result, power); 1956 else { 1957 /* if result is too small and memTemp = 0, 1958 doAdd will not add */ 1959 memTemp = result; 1960 memTempPower = power; 1961 } 1962 calStatus = cal_normal; 1963 break; 1964 1965 case btn_C: clearMem(); break; 1966 case btn_CE: clearInput(); break; 1967 1968 case btn_bas: 1969 buttonGroup = sciButtons; 1970 printButtonGroups(buttonGroup); 1971 break; 1972 1973 /* one operand calculation, may be changed to 1974 like sin, cos, log, etc */ 1975 case btn_sqr: 1976 case btn_square: 1977 case btn_rec: 1978 formatResult(); /* not necessary, just for safty */ 1979 oneOperand(); 1980 break; 1981 1982 case_btn_equal: /* F3 shortkey entrance */ 1983 case btn_equal: 1984 formatResult(); 1985 calStatus = cal_normal; 1986 operInputted = false; 1987 if (oper != ' ') twoOperands(); 1988 break; 1989 1990 case btn_div: 1991 case btn_time: 1992 case btn_minus: 1993 case btn_add: 1994 if(!operInputted) {twoOperands(); operInputted = true;} 1995 oper = buttonChar[basicButtons][btn_row][btn_col][0]; 1996#ifdef CALCULATOR_OPERATORS 1997 case_cycle_operators: /* F2 shortkey entrance */ 1998#endif 1999 if (calStatus == cal_typing || 2000 calStatus == cal_dotted) 2001 calStatus = cal_normal; 2002 formatResult(); 2003 operand = result; 2004 operandPower = power; 2005 2006 break; 2007 2008 case btn_sign: 2009 case btn_dot: 2010 default: /* 0-9 */ 2011 typingProcess(); 2012 break; 2013 } /* switch (CAL_BUTTON) */ 2014 break; 2015 2016#ifdef CALCULATOR_OPERATORS 2017 case CALCULATOR_OPERATORS: 2018 if (calStatus == cal_error) break; 2019 if (!operInputted) {twoOperands(); operInputted = true;} 2020 switch (oper){ 2021 case ' ': 2022 case '/': oper = '+'; flashButton(); break; 2023 case '+': oper = '-'; flashButton(); break; 2024 case '-': oper = '*'; flashButton(); break; 2025 case '*': oper = '/'; flashButton(); break; 2026 } 2027 goto case_cycle_operators; 2028 break; 2029#endif 2030 2031 case CALCULATOR_CALC: 2032 if (calStatus == cal_error) break; 2033 flashButton(); 2034 goto case_btn_equal; 2035 break; 2036 default: break; 2037 } 2038 printResult(); 2039} 2040 2041/* ----------------------------------------------------------------------- 2042Handle buttons on scientific screen 2043----------------------------------------------------------------------- */ 2044static void sciButtonsProcess(void){ 2045 switch (btn) { 2046 case CALCULATOR_INPUT: 2047 if (calStatus == cal_error && (CAL_BUTTON != sci_sci) ) break; 2048 flashButton(); 2049 switch( CAL_BUTTON ){ 2050 2051 case sci_pi: 2052 result = M_PI; power = 0; 2053 calStatus = cal_normal; 2054 break; 2055 2056 case sci_xy: 2057 if(!operInputted) {twoOperands(); operInputted = true;} 2058 oper = '^'; 2059 if (calStatus == cal_typing || 2060 calStatus == cal_dotted) 2061 calStatus = cal_normal; 2062 formatResult(); 2063 operand = result; 2064 operandPower = power; 2065 break; 2066 2067 case sci_sci: 2068 buttonGroup = basicButtons; 2069 printButtonGroups(basicButtons); 2070 break; 2071 2072 case sci_fac: 2073 case sci_sin: 2074 case sci_asin: 2075 case sci_cos: 2076 case sci_acos: 2077 case sci_tan: 2078 case sci_atan: 2079 case sci_ln: 2080 case sci_exp: 2081 case sci_log: 2082 formatResult(); /* not necessary, just for safty */ 2083 oneOperand(); 2084 break; 2085 2086 case btn_sign: 2087 case btn_dot: 2088 default: /* 0-9 */ 2089 typingProcess(); 2090 break; 2091 } /* switch (CAL_BUTTON) */ 2092 break; 2093 2094#ifdef CALCULATOR_OPERATORS 2095 case CALCULATOR_OPERATORS: 2096 if (calStatus == cal_error) break; 2097 if (!operInputted) {twoOperands(); operInputted = true;} 2098 switch (oper){ 2099 case ' ': oper = '+'; break; 2100 case '/': oper = '+'; deleteAnimation(1); break; 2101 case '+': oper = '-'; deleteAnimation(1); break; 2102 case '-': oper = '*'; deleteAnimation(1); break; 2103 case '*': oper = '/'; deleteAnimation(1); break; 2104 } 2105 calStatus = cal_normal; 2106 formatResult(); 2107 operand = result; 2108 operandPower = power; 2109 break; 2110#endif 2111 2112 case CALCULATOR_CALC: 2113 if (calStatus == cal_error) break; 2114 formatResult(); 2115 calStatus = cal_normal; 2116 operInputted = false; 2117 if (oper != ' ') twoOperands(); 2118 break; 2119 default: break; 2120 } 2121 printResult(); 2122} 2123 2124/* ----------------------------------------------------------------------- 2125move button index 2126Invert display new button, invert back previous button 2127----------------------------------------------------------------------- */ 2128static int handleButton(int button){ 2129 switch(button) 2130 { 2131 case CALCULATOR_INPUT: 2132 case CALCULATOR_CALC: 2133#ifdef CALCULATOR_INPUT_CALC_PRE 2134 if (lastbtn != CALCULATOR_INPUT_CALC_PRE) 2135 break; 2136 /* no unconditional break; here! */ 2137#endif 2138#ifdef CALCULATOR_OPERATORS 2139 case CALCULATOR_OPERATORS: 2140#endif 2141 switch(buttonGroup){ 2142 case basicButtons: 2143 basicButtonsProcess(); 2144 break; 2145 case sciButtons: 2146 sciButtonsProcess(); 2147 break; 2148 } 2149 break; 2150 2151#ifdef CALCULATOR_CLEAR 2152 case CALCULATOR_CLEAR: 2153 switch(calStatus){ 2154 case cal_typing: 2155 case cal_dotted: 2156 doDelete(); 2157 break; 2158 default: /* cal_normal, cal_error, cal_exit */ 2159 clearMem(); 2160 break; 2161 } 2162 printResult(); 2163 break; 2164#endif 2165 case CALCULATOR_LEFT: 2166 case CALCULATOR_LEFT | BUTTON_REPEAT: 2167 move_with_wrap_and_shift( 2168 &btn_col, -1, BUTTON_COLS, 2169 &btn_row, 0, BUTTON_ROWS); 2170 break; 2171 2172 case CALCULATOR_RIGHT: 2173 case CALCULATOR_RIGHT | BUTTON_REPEAT: 2174 move_with_wrap_and_shift( 2175 &btn_col, 1, BUTTON_COLS, 2176 &btn_row, 0, BUTTON_ROWS); 2177 break; 2178 2179#ifdef CALCULATOR_UP 2180 case CALCULATOR_UP: 2181 case CALCULATOR_UP | BUTTON_REPEAT: 2182 move_with_wrap_and_shift( 2183 &btn_row, -1, BUTTON_ROWS, 2184 &btn_col, 0, BUTTON_COLS); 2185 break; 2186#endif 2187#ifdef CALCULATOR_DOWN 2188 case CALCULATOR_DOWN: 2189 case CALCULATOR_DOWN | BUTTON_REPEAT: 2190 move_with_wrap_and_shift( 2191 &btn_row, 1, BUTTON_ROWS, 2192 &btn_col, 0, BUTTON_COLS); 2193 break; 2194#endif 2195 2196#ifdef CALCULATOR_UP_W_SHIFT 2197 case CALCULATOR_UP_W_SHIFT: 2198 case CALCULATOR_UP_W_SHIFT | BUTTON_REPEAT: 2199 move_with_wrap_and_shift( 2200 &btn_row, -1, BUTTON_ROWS, 2201 &btn_col, -1, BUTTON_COLS); 2202 break; 2203#endif 2204#ifdef CALCULATOR_DOWN_W_SHIFT 2205 case CALCULATOR_DOWN_W_SHIFT: 2206 case CALCULATOR_DOWN_W_SHIFT | BUTTON_REPEAT: 2207 move_with_wrap_and_shift( 2208 &btn_row, 1, BUTTON_ROWS, 2209 &btn_col, 1, BUTTON_COLS); 2210 break; 2211#endif 2212#ifdef CALCULATOR_LEFT_W_SHIFT 2213 case CALCULATOR_LEFT_W_SHIFT: 2214 case CALCULATOR_LEFT_W_SHIFT | BUTTON_REPEAT: 2215 move_with_wrap_and_shift( 2216 &btn_col, -1, BUTTON_COLS, 2217 &btn_row, -1, BUTTON_ROWS); 2218 break; 2219#endif 2220#ifdef CALCULATOR_RIGHT_W_SHIFT 2221 case CALCULATOR_RIGHT_W_SHIFT: 2222 case CALCULATOR_RIGHT_W_SHIFT | BUTTON_REPEAT: 2223 move_with_wrap_and_shift( 2224 &btn_col, 1, BUTTON_COLS, 2225 &btn_row, 1, BUTTON_ROWS); 2226 break; 2227#endif 2228#ifdef CALCULATOR_RC_QUIT 2229 case CALCULATOR_RC_QUIT: 2230#endif 2231 case CALCULATOR_QUIT: 2232 return -1; 2233 } 2234 2235 return 0; 2236} 2237 2238/* ----------------------------------------------------------------------- 2239Main(); 2240----------------------------------------------------------------------- */ 2241enum plugin_status plugin_start(const void* parameter) 2242{ 2243 (void)parameter; 2244 2245 /* now go ahead and have fun! */ 2246 2247#ifdef HAVE_TOUCHSCREEN 2248 rb->touchscreen_set_mode(TOUCHSCREEN_POINT); 2249#endif 2250 2251 cal_initial(); 2252 2253 while (calStatus != cal_exit ) { 2254 btn = rb->button_get_w_tmo(HZ/2); 2255#ifdef HAVE_TOUCHSCREEN 2256 if(btn & BUTTON_TOUCHSCREEN) 2257 { 2258 struct ts_raster_result res; 2259 if(touchscreen_map_raster(&calc_raster, rb->button_get_data() >> 16, 2260 rb->button_get_data() & 0xffff, &res) == 1) 2261 { 2262 btn_row = res.y; 2263 btn_col = res.x; 2264 drawButtons(buttonGroup); 2265 drawLines(); 2266 2267 rb->lcd_update(); 2268 2269 prev_btn_row = btn_row; 2270 prev_btn_col = btn_col; 2271 if(btn & BUTTON_REL) 2272 { 2273 btn = CALCULATOR_INPUT; 2274 switch(buttonGroup){ 2275 case basicButtons: 2276 basicButtonsProcess(); 2277 break; 2278 case sciButtons: 2279 sciButtonsProcess(); 2280 break; 2281 } 2282 btn = BUTTON_TOUCHSCREEN; 2283 } 2284 } 2285 } 2286#endif 2287 if (handleButton(btn) == -1) 2288 { 2289 calStatus = cal_exit; 2290 printResult(); 2291 } 2292 else 2293 { 2294 drawButtons(buttonGroup); 2295 drawLines(); 2296 } 2297 2298 rb->lcd_update(); 2299 2300 if(rb->default_event_handler(btn) == SYS_USB_CONNECTED) 2301 return PLUGIN_USB_CONNECTED; 2302 2303 if (btn != BUTTON_NONE) 2304 lastbtn = btn; 2305 } /* while (calStatus != cal_exit ) */ 2306 2307 rb->button_clear_queue(); 2308 return PLUGIN_OK; 2309}