e86991f484
exponential implementation uses the series e^x = 1 + x + x^2/2 + x^3/6 + ... natural logarithm uses ln(a) = 2 * ( (a-1)/(a+1) + 1/3 * ((a-1)/(a+1))^3 +... ) log10 uses log10(a) = ln(a)/ln(10) Change-Id: I7303404b2b5a2bf60aad0706ca964a7cea19a27c Reviewed-on: http://gerrit.rockbox.org/333 Reviewed-by: Frank Gevaerts <frank@gevaerts.be>
1921 lines
63 KiB
C
1921 lines
63 KiB
C
/***************************************************************************
|
||
* __________ __ ___.
|
||
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
||
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
||
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
||
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
||
* \/ \/ \/ \/ \/
|
||
* $Id$
|
||
*
|
||
* Copyright (C) 2004 Pengxuan Liu (Isaac)
|
||
*
|
||
* This program is free software; you can redistribute it and/or
|
||
* modify it under the terms of the GNU General Public License
|
||
* as published by the Free Software Foundation; either version 2
|
||
* of the License, or (at your option) any later version.
|
||
*
|
||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||
* KIND, either express or implied.
|
||
*
|
||
****************************************************************************/
|
||
|
||
/*
|
||
00 01 21 22 23 43 44 45 65 66 67 87 88 89 109110111
|
||
00 |-----------|-----------|-----------|-----------|-----------|
|
||
01 | | | | | |
|
||
|***********|***********|***********|***********|***********|
|
||
|***********|***********|***********|***********|***********|
|
||
11 | | | | | |
|
||
12 |-----------|-----------|-----------|-----------|-----------|
|
||
13 |-----------|-----------|-----------|-----------|-----------| y1
|
||
14 | | | | | |
|
||
| | | | | |
|
||
22 | | | | | |
|
||
23 |-----------|-----------|-----------|-----------|-----------| y2
|
||
24 | | | | | |
|
||
| | | | | |
|
||
32 | | | | | |
|
||
33 |-----------|-----------|-----------|-----------|-----------| y3
|
||
34 | | | | | |
|
||
| | | | | |
|
||
42 | | | | | |
|
||
43 |-----------|-----------|-----------|-----------|-----------| y4
|
||
44 | | | | | |
|
||
| | | | | |
|
||
52 | | | | | |
|
||
53 |-----------|-----------|-----------|-----------|-----------| y5
|
||
54 | | | | | |
|
||
| | | | | |
|
||
62 | | | | | |
|
||
63 |-----------|-----------|-----------|-----------|-----------| y6
|
||
x0 x1 x2 x3 x4 x5
|
||
*/
|
||
|
||
/*---------------------------------------------------------------------------
|
||
Features:
|
||
- Scientific number format core code. Support range 10^-999 ~ 10^999
|
||
- Number of significant figures up to 10
|
||
|
||
Limitations:
|
||
- Right now, only accept "num, operator (+,-,*,/), num, =" input sequence.
|
||
Input "3, +, 5, -, 2, =", the calculator will only do 5-2 and result = 3
|
||
You have to input "3, +, 5, =, -, 2, =" to get 3+5-2 = 6
|
||
|
||
- "*,/" have no priority. Actually you can't input 3+5*2 yet.
|
||
|
||
User Instructions:
|
||
use arrow button to move cursor, "play" button to select, "off" button to exit
|
||
F1: if typing numbers, it's equal to "Del"; otherwise, equal to "C"
|
||
F2: circle input "+, -, *, /"
|
||
F3: equal to "="
|
||
|
||
"MR" : load temp memory
|
||
"M+" : add currently display to temp memory
|
||
"C" : reset calculator
|
||
---------------------------------------------------------------------------*/
|
||
|
||
#include "plugin.h"
|
||
|
||
#include "math.h"
|
||
|
||
|
||
|
||
|
||
#define M_TWOPI (M_PI * 2.0)
|
||
|
||
#define BUTTON_ROWS 5
|
||
#define BUTTON_COLS 5
|
||
|
||
#define REC_HEIGHT (int)(LCD_HEIGHT / (BUTTON_ROWS + 1))
|
||
#define REC_WIDTH (int)(LCD_WIDTH / BUTTON_COLS)
|
||
|
||
#define Y_6_POS (LCD_HEIGHT) /* Leave room for the border */
|
||
#define Y_5_POS (Y_6_POS - REC_HEIGHT) /* y5 = 53 */
|
||
#define Y_4_POS (Y_5_POS - REC_HEIGHT) /* y4 = 43 */
|
||
#define Y_3_POS (Y_4_POS - REC_HEIGHT) /* y3 = 33 */
|
||
#define Y_2_POS (Y_3_POS - REC_HEIGHT) /* y2 = 23 */
|
||
#define Y_1_POS (Y_2_POS - REC_HEIGHT) /* y1 = 13 */
|
||
#define Y_0_POS 0 /* y0 = 0 */
|
||
|
||
#define X_0_POS 0 /* x0 = 0 */
|
||
#define X_1_POS (X_0_POS + REC_WIDTH) /* x1 = 22 */
|
||
#define X_2_POS (X_1_POS + REC_WIDTH) /* x2 = 44 */
|
||
#define X_3_POS (X_2_POS + REC_WIDTH) /* x3 = 66 */
|
||
#define X_4_POS (X_3_POS + REC_WIDTH) /* x4 = 88 */
|
||
#define X_5_POS (X_4_POS + REC_WIDTH) /* x5 = 110, column 111 left blank */
|
||
|
||
#define SIGN(x) ((x)<0?-1:1)
|
||
#ifndef ABS
|
||
#define ABS(a) (((a) < 0) ? -(a) : (a))
|
||
#endif
|
||
|
||
/* variable button definitions */
|
||
#if CONFIG_KEYPAD == RECORDER_PAD
|
||
#define CALCULATOR_LEFT BUTTON_LEFT
|
||
#define CALCULATOR_RIGHT BUTTON_RIGHT
|
||
#define CALCULATOR_UP BUTTON_UP
|
||
#define CALCULATOR_DOWN BUTTON_DOWN
|
||
#define CALCULATOR_QUIT BUTTON_OFF
|
||
#define CALCULATOR_INPUT BUTTON_PLAY
|
||
#define CALCULATOR_CALC BUTTON_F3
|
||
#define CALCULATOR_OPERATORS BUTTON_F2
|
||
#define CALCULATOR_CLEAR BUTTON_F1
|
||
|
||
#elif CONFIG_KEYPAD == ARCHOS_AV300_PAD
|
||
#define CALCULATOR_LEFT BUTTON_LEFT
|
||
#define CALCULATOR_RIGHT BUTTON_RIGHT
|
||
#define CALCULATOR_UP BUTTON_UP
|
||
#define CALCULATOR_DOWN BUTTON_DOWN
|
||
#define CALCULATOR_QUIT BUTTON_OFF
|
||
#define CALCULATOR_INPUT BUTTON_SELECT
|
||
#define CALCULATOR_CALC BUTTON_F3
|
||
#define CALCULATOR_OPERATORS BUTTON_F2
|
||
#define CALCULATOR_CLEAR BUTTON_F1
|
||
|
||
#elif CONFIG_KEYPAD == ONDIO_PAD
|
||
#define CALCULATOR_LEFT BUTTON_LEFT
|
||
#define CALCULATOR_RIGHT BUTTON_RIGHT
|
||
#define CALCULATOR_UP BUTTON_UP
|
||
#define CALCULATOR_DOWN BUTTON_DOWN
|
||
#define CALCULATOR_QUIT BUTTON_OFF
|
||
#define CALCULATOR_INPUT_CALC_PRE BUTTON_MENU
|
||
#define CALCULATOR_INPUT (BUTTON_MENU | BUTTON_REL)
|
||
#define CALCULATOR_CALC (BUTTON_MENU | BUTTON_REPEAT)
|
||
|
||
#elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || \
|
||
(CONFIG_KEYPAD == IRIVER_H300_PAD)
|
||
#define CALCULATOR_LEFT BUTTON_LEFT
|
||
#define CALCULATOR_RIGHT BUTTON_RIGHT
|
||
#define CALCULATOR_UP BUTTON_UP
|
||
#define CALCULATOR_DOWN BUTTON_DOWN
|
||
#define CALCULATOR_QUIT BUTTON_OFF
|
||
#define CALCULATOR_INPUT BUTTON_SELECT
|
||
#define CALCULATOR_CALC BUTTON_ON
|
||
#define CALCULATOR_OPERATORS BUTTON_MODE
|
||
#define CALCULATOR_CLEAR BUTTON_REC
|
||
|
||
#define CALCULATOR_RC_QUIT BUTTON_RC_STOP
|
||
|
||
#elif (CONFIG_KEYPAD == IPOD_4G_PAD) || \
|
||
(CONFIG_KEYPAD == IPOD_3G_PAD) || \
|
||
(CONFIG_KEYPAD == IPOD_1G2G_PAD)
|
||
|
||
#define CALCULATOR_LEFT BUTTON_LEFT
|
||
#define CALCULATOR_RIGHT BUTTON_RIGHT
|
||
#define CALCULATOR_UP_W_SHIFT BUTTON_SCROLL_BACK
|
||
#define CALCULATOR_DOWN_W_SHIFT BUTTON_SCROLL_FWD
|
||
#define CALCULATOR_QUIT BUTTON_MENU
|
||
#define CALCULATOR_INPUT BUTTON_SELECT
|
||
#define CALCULATOR_CALC BUTTON_PLAY
|
||
|
||
#elif (CONFIG_KEYPAD == IAUDIO_X5M5_PAD)
|
||
|
||
#define CALCULATOR_LEFT BUTTON_LEFT
|
||
#define CALCULATOR_RIGHT BUTTON_RIGHT
|
||
#define CALCULATOR_UP BUTTON_UP
|
||
#define CALCULATOR_DOWN BUTTON_DOWN
|
||
#define CALCULATOR_QUIT BUTTON_POWER
|
||
#define CALCULATOR_INPUT BUTTON_SELECT
|
||
#define CALCULATOR_CALC BUTTON_PLAY
|
||
#define CALCULATOR_CLEAR BUTTON_REC
|
||
|
||
#elif (CONFIG_KEYPAD == GIGABEAT_PAD)
|
||
|
||
#define CALCULATOR_LEFT BUTTON_LEFT
|
||
#define CALCULATOR_RIGHT BUTTON_RIGHT
|
||
#define CALCULATOR_UP BUTTON_UP
|
||
#define CALCULATOR_DOWN BUTTON_DOWN
|
||
#define CALCULATOR_QUIT BUTTON_POWER
|
||
#define CALCULATOR_INPUT BUTTON_SELECT
|
||
#define CALCULATOR_CALC BUTTON_MENU
|
||
#define CALCULATOR_CLEAR BUTTON_A
|
||
|
||
#elif (CONFIG_KEYPAD == SANSA_E200_PAD)
|
||
#define CALCULATOR_LEFT BUTTON_LEFT
|
||
#define CALCULATOR_RIGHT BUTTON_RIGHT
|
||
#define CALCULATOR_UP BUTTON_UP
|
||
#define CALCULATOR_DOWN BUTTON_DOWN
|
||
#define CALCULATOR_UP_W_SHIFT BUTTON_SCROLL_BACK
|
||
#define CALCULATOR_DOWN_W_SHIFT BUTTON_SCROLL_FWD
|
||
#define CALCULATOR_QUIT BUTTON_POWER
|
||
#define CALCULATOR_INPUT_CALC_PRE BUTTON_SELECT
|
||
#define CALCULATOR_INPUT (BUTTON_SELECT|BUTTON_REL)
|
||
#define CALCULATOR_CALC (BUTTON_SELECT|BUTTON_REPEAT)
|
||
#define CALCULATOR_CLEAR BUTTON_REC
|
||
|
||
#elif (CONFIG_KEYPAD == SANSA_C200_PAD)
|
||
#define CALCULATOR_LEFT BUTTON_LEFT
|
||
#define CALCULATOR_RIGHT BUTTON_RIGHT
|
||
#define CALCULATOR_UP BUTTON_UP
|
||
#define CALCULATOR_DOWN BUTTON_DOWN
|
||
#define CALCULATOR_QUIT BUTTON_POWER
|
||
#define CALCULATOR_INPUT_CALC_PRE BUTTON_SELECT
|
||
#define CALCULATOR_INPUT (BUTTON_SELECT|BUTTON_REL)
|
||
#define CALCULATOR_CALC (BUTTON_SELECT|BUTTON_REPEAT)
|
||
|
||
#elif (CONFIG_KEYPAD == SANSA_FUZE_PAD)
|
||
#define CALCULATOR_LEFT BUTTON_LEFT
|
||
#define CALCULATOR_RIGHT BUTTON_RIGHT
|
||
#define CALCULATOR_UP BUTTON_UP
|
||
#define CALCULATOR_DOWN BUTTON_DOWN
|
||
#define CALCULATOR_UP_W_SHIFT BUTTON_SCROLL_BACK
|
||
#define CALCULATOR_DOWN_W_SHIFT BUTTON_SCROLL_FWD
|
||
#define CALCULATOR_QUIT (BUTTON_HOME|BUTTON_REPEAT)
|
||
#define CALCULATOR_INPUT_CALC_PRE BUTTON_SELECT
|
||
#define CALCULATOR_INPUT (BUTTON_SELECT|BUTTON_REL)
|
||
#define CALCULATOR_CALC (BUTTON_SELECT|BUTTON_REPEAT)
|
||
#define CALCULATOR_CLEAR BUTTON_HOME
|
||
|
||
|
||
#elif (CONFIG_KEYPAD == SANSA_CLIP_PAD)
|
||
#define CALCULATOR_LEFT BUTTON_LEFT
|
||
#define CALCULATOR_RIGHT BUTTON_RIGHT
|
||
#define CALCULATOR_UP BUTTON_UP
|
||
#define CALCULATOR_DOWN BUTTON_DOWN
|
||
#define CALCULATOR_QUIT BUTTON_POWER
|
||
#define CALCULATOR_INPUT_CALC_PRE BUTTON_SELECT
|
||
#define CALCULATOR_INPUT (BUTTON_SELECT|BUTTON_REL)
|
||
#define CALCULATOR_CALC (BUTTON_SELECT|BUTTON_REPEAT)
|
||
#define CALCULATOR_CLEAR BUTTON_HOME
|
||
|
||
#elif (CONFIG_KEYPAD == SANSA_M200_PAD)
|
||
#define CALCULATOR_LEFT BUTTON_LEFT
|
||
#define CALCULATOR_RIGHT BUTTON_RIGHT
|
||
#define CALCULATOR_UP BUTTON_UP
|
||
#define CALCULATOR_DOWN BUTTON_DOWN
|
||
#define CALCULATOR_QUIT BUTTON_POWER
|
||
#define CALCULATOR_INPUT_CALC_PRE BUTTON_SELECT
|
||
#define CALCULATOR_INPUT (BUTTON_SELECT|BUTTON_REL)
|
||
#define CALCULATOR_CALC (BUTTON_SELECT|BUTTON_REPEAT)
|
||
#define CALCULATOR_CLEAR (BUTTON_SELECT|BUTTON_UP)
|
||
|
||
#elif (CONFIG_KEYPAD == IRIVER_H10_PAD)
|
||
|
||
#define CALCULATOR_LEFT BUTTON_LEFT
|
||
#define CALCULATOR_RIGHT BUTTON_RIGHT
|
||
#define CALCULATOR_UP BUTTON_SCROLL_UP
|
||
#define CALCULATOR_DOWN BUTTON_SCROLL_DOWN
|
||
#define CALCULATOR_QUIT BUTTON_POWER
|
||
#define CALCULATOR_INPUT_CALC_PRE BUTTON_PLAY
|
||
#define CALCULATOR_INPUT (BUTTON_PLAY | BUTTON_REL)
|
||
#define CALCULATOR_CALC (BUTTON_PLAY | BUTTON_REPEAT)
|
||
#define CALCULATOR_CLEAR BUTTON_REW
|
||
|
||
#elif (CONFIG_KEYPAD == GIGABEAT_S_PAD)
|
||
|
||
#define CALCULATOR_LEFT BUTTON_LEFT
|
||
#define CALCULATOR_RIGHT BUTTON_RIGHT
|
||
#define CALCULATOR_UP BUTTON_UP
|
||
#define CALCULATOR_DOWN BUTTON_DOWN
|
||
#define CALCULATOR_QUIT BUTTON_BACK
|
||
#define CALCULATOR_INPUT BUTTON_SELECT
|
||
#define CALCULATOR_CALC BUTTON_MENU
|
||
#define CALCULATOR_CLEAR BUTTON_PLAY
|
||
|
||
#elif (CONFIG_KEYPAD == MROBE100_PAD)
|
||
|
||
#define CALCULATOR_LEFT BUTTON_LEFT
|
||
#define CALCULATOR_RIGHT BUTTON_RIGHT
|
||
#define CALCULATOR_UP BUTTON_UP
|
||
#define CALCULATOR_DOWN BUTTON_DOWN
|
||
#define CALCULATOR_QUIT BUTTON_POWER
|
||
#define CALCULATOR_INPUT BUTTON_SELECT
|
||
#define CALCULATOR_CALC BUTTON_MENU
|
||
#define CALCULATOR_CLEAR BUTTON_DISPLAY
|
||
|
||
#elif CONFIG_KEYPAD == IAUDIO_M3_PAD
|
||
|
||
#define CALCULATOR_LEFT BUTTON_RC_REW
|
||
#define CALCULATOR_RIGHT BUTTON_RC_FF
|
||
#define CALCULATOR_UP BUTTON_RC_VOL_UP
|
||
#define CALCULATOR_DOWN BUTTON_RC_VOL_DOWN
|
||
#define CALCULATOR_QUIT BUTTON_RC_REC
|
||
#define CALCULATOR_INPUT BUTTON_RC_PLAY
|
||
#define CALCULATOR_CALC BUTTON_RC_MODE
|
||
#define CALCULATOR_CLEAR BUTTON_RC_MENU
|
||
|
||
#define CALCULATOR_RC_QUIT BUTTON_REC
|
||
|
||
#elif (CONFIG_KEYPAD == COWON_D2_PAD)
|
||
|
||
#define CALCULATOR_QUIT BUTTON_POWER
|
||
#define CALCULATOR_CLEAR BUTTON_MENU
|
||
|
||
#elif CONFIG_KEYPAD == IAUDIO67_PAD
|
||
|
||
#define CALCULATOR_LEFT BUTTON_LEFT
|
||
#define CALCULATOR_RIGHT BUTTON_RIGHT
|
||
#define CALCULATOR_UP BUTTON_VOLUP
|
||
#define CALCULATOR_DOWN BUTTON_VOLDOWN
|
||
#define CALCULATOR_QUIT BUTTON_POWER
|
||
#define CALCULATOR_INPUT BUTTON_PLAY
|
||
#define CALCULATOR_CALC BUTTON_MENU
|
||
#define CALCULATOR_CLEAR BUTTON_STOP
|
||
|
||
#define CALCULATOR_RC_QUIT (BUTTON_MENU|BUTTON_PLAY)
|
||
|
||
#elif (CONFIG_KEYPAD == CREATIVEZVM_PAD)
|
||
|
||
#define CALCULATOR_LEFT BUTTON_LEFT
|
||
#define CALCULATOR_RIGHT BUTTON_RIGHT
|
||
#define CALCULATOR_UP BUTTON_UP
|
||
#define CALCULATOR_DOWN BUTTON_DOWN
|
||
#define CALCULATOR_QUIT BUTTON_BACK
|
||
#define CALCULATOR_INPUT BUTTON_SELECT
|
||
#define CALCULATOR_CALC BUTTON_MENU
|
||
#define CALCULATOR_CLEAR BUTTON_PLAY
|
||
|
||
#elif CONFIG_KEYPAD == PHILIPS_HDD1630_PAD
|
||
|
||
#define CALCULATOR_LEFT BUTTON_LEFT
|
||
#define CALCULATOR_RIGHT BUTTON_RIGHT
|
||
#define CALCULATOR_UP BUTTON_UP
|
||
#define CALCULATOR_DOWN BUTTON_DOWN
|
||
#define CALCULATOR_QUIT BUTTON_POWER
|
||
#define CALCULATOR_INPUT BUTTON_SELECT
|
||
#define CALCULATOR_CALC BUTTON_MENU
|
||
#define CALCULATOR_CLEAR BUTTON_VIEW
|
||
|
||
#elif CONFIG_KEYPAD == PHILIPS_HDD6330_PAD
|
||
|
||
#define CALCULATOR_LEFT BUTTON_PREV
|
||
#define CALCULATOR_RIGHT BUTTON_NEXT
|
||
#define CALCULATOR_UP BUTTON_UP
|
||
#define CALCULATOR_DOWN BUTTON_DOWN
|
||
#define CALCULATOR_QUIT BUTTON_POWER
|
||
#define CALCULATOR_INPUT BUTTON_PLAY
|
||
#define CALCULATOR_CALC BUTTON_MENU
|
||
#define CALCULATOR_CLEAR BUTTON_RIGHT
|
||
|
||
#elif CONFIG_KEYPAD == PHILIPS_SA9200_PAD
|
||
|
||
#define CALCULATOR_LEFT BUTTON_PREV
|
||
#define CALCULATOR_RIGHT BUTTON_NEXT
|
||
#define CALCULATOR_UP BUTTON_UP
|
||
#define CALCULATOR_DOWN BUTTON_DOWN
|
||
#define CALCULATOR_QUIT BUTTON_POWER
|
||
#define CALCULATOR_INPUT BUTTON_PLAY
|
||
#define CALCULATOR_CALC BUTTON_MENU
|
||
#define CALCULATOR_CLEAR BUTTON_RIGHT
|
||
|
||
#elif (CONFIG_KEYPAD == ONDAVX747_PAD)
|
||
|
||
#define CALCULATOR_QUIT BUTTON_POWER
|
||
#define CALCULATOR_CLEAR BUTTON_MENU
|
||
|
||
#elif (CONFIG_KEYPAD == ONDAVX777_PAD)
|
||
#define CALCULATOR_QUIT BUTTON_POWER
|
||
|
||
#elif CONFIG_KEYPAD == MROBE500_PAD
|
||
#define CALCULATOR_QUIT BUTTON_POWER
|
||
|
||
#elif CONFIG_KEYPAD == SAMSUNG_YH_PAD
|
||
|
||
#define CALCULATOR_LEFT BUTTON_LEFT
|
||
#define CALCULATOR_RIGHT BUTTON_RIGHT
|
||
#define CALCULATOR_UP BUTTON_UP
|
||
#define CALCULATOR_DOWN BUTTON_DOWN
|
||
#define CALCULATOR_QUIT BUTTON_REC
|
||
#define CALCULATOR_INPUT BUTTON_PLAY
|
||
#define CALCULATOR_CALC BUTTON_FFWD
|
||
#define CALCULATOR_CLEAR BUTTON_REW
|
||
|
||
#elif CONFIG_KEYPAD == PBELL_VIBE500_PAD
|
||
|
||
#define CALCULATOR_LEFT BUTTON_PREV
|
||
#define CALCULATOR_RIGHT BUTTON_NEXT
|
||
#define CALCULATOR_UP BUTTON_UP
|
||
#define CALCULATOR_DOWN BUTTON_DOWN
|
||
#define CALCULATOR_QUIT BUTTON_REC
|
||
#define CALCULATOR_INPUT BUTTON_OK
|
||
#define CALCULATOR_CALC BUTTON_PLAY
|
||
#define CALCULATOR_CLEAR BUTTON_CANCEL
|
||
|
||
#elif CONFIG_KEYPAD == MPIO_HD200_PAD
|
||
#define CALCULATOR_LEFT BUTTON_REW
|
||
#define CALCULATOR_RIGHT BUTTON_FF
|
||
#define CALCULATOR_QUIT (BUTTON_REC|BUTTON_PLAY)
|
||
#define CALCULATOR_INPUT BUTTON_FUNC
|
||
#define CALCULATOR_CALC BUTTON_PLAY
|
||
#define CALCULATOR_CLEAR BUTTON_REC
|
||
|
||
#elif CONFIG_KEYPAD == MPIO_HD300_PAD
|
||
#define CALCULATOR_LEFT BUTTON_REW
|
||
#define CALCULATOR_RIGHT BUTTON_FF
|
||
#define CALCULATOR_UP BUTTON_UP
|
||
#define CALCULATOR_DOWN BUTTON_DOWN
|
||
#define CALCULATOR_QUIT (BUTTON_MENU|BUTTON_REPEAT)
|
||
#define CALCULATOR_INPUT BUTTON_ENTER
|
||
#define CALCULATOR_CALC BUTTON_PLAY
|
||
#define CALCULATOR_CLEAR BUTTON_MENU
|
||
|
||
#elif CONFIG_KEYPAD == SANSA_FUZEPLUS_PAD
|
||
#define CALCULATOR_LEFT BUTTON_LEFT
|
||
#define CALCULATOR_RIGHT BUTTON_RIGHT
|
||
#define CALCULATOR_UP BUTTON_UP
|
||
#define CALCULATOR_DOWN BUTTON_DOWN
|
||
#define CALCULATOR_QUIT BUTTON_POWER
|
||
#define CALCULATOR_INPUT BUTTON_SELECT
|
||
#define CALCULATOR_CALC BUTTON_PLAYPAUSE
|
||
#define CALCULATOR_CLEAR BUTTON_BACK
|
||
|
||
#elif (CONFIG_KEYPAD == SANSA_CONNECT_PAD)
|
||
#define CALCULATOR_LEFT BUTTON_LEFT
|
||
#define CALCULATOR_RIGHT BUTTON_RIGHT
|
||
#define CALCULATOR_UP BUTTON_UP
|
||
#define CALCULATOR_DOWN BUTTON_DOWN
|
||
#define CALCULATOR_UP_W_SHIFT BUTTON_SCROLL_BACK
|
||
#define CALCULATOR_DOWN_W_SHIFT BUTTON_SCROLL_FWD
|
||
#define CALCULATOR_QUIT BUTTON_POWER
|
||
#define CALCULATOR_INPUT_CALC_PRE BUTTON_SELECT
|
||
#define CALCULATOR_INPUT (BUTTON_SELECT|BUTTON_REL)
|
||
#define CALCULATOR_CALC BUTTON_NEXT
|
||
#define CALCULATOR_CLEAR BUTTON_PREV
|
||
|
||
#elif (CONFIG_KEYPAD == SAMSUNG_YPR0_PAD)
|
||
|
||
#define CALCULATOR_LEFT BUTTON_LEFT
|
||
#define CALCULATOR_RIGHT BUTTON_RIGHT
|
||
#define CALCULATOR_UP BUTTON_UP
|
||
#define CALCULATOR_DOWN BUTTON_DOWN
|
||
#define CALCULATOR_QUIT BUTTON_BACK
|
||
#define CALCULATOR_INPUT BUTTON_SELECT
|
||
#define CALCULATOR_CALC BUTTON_MENU
|
||
#define CALCULATOR_CLEAR BUTTON_USER
|
||
|
||
#elif (CONFIG_KEYPAD == HM60X_PAD)
|
||
|
||
#define CALCULATOR_LEFT BUTTON_LEFT
|
||
#define CALCULATOR_RIGHT BUTTON_RIGHT
|
||
#define CALCULATOR_UP BUTTON_UP
|
||
#define CALCULATOR_DOWN BUTTON_DOWN
|
||
#define CALCULATOR_QUIT BUTTON_POWER
|
||
#define CALCULATOR_INPUT BUTTON_SELECT
|
||
#define CALCULATOR_CALC (BUTTON_UP|BUTTON_POWER)
|
||
#define CALCULATOR_CLEAR (BUTTON_DOWN|BUTTON_POWER)
|
||
|
||
#elif (CONFIG_KEYPAD == HM801_PAD)
|
||
|
||
#define CALCULATOR_LEFT BUTTON_LEFT
|
||
#define CALCULATOR_RIGHT BUTTON_RIGHT
|
||
#define CALCULATOR_UP BUTTON_UP
|
||
#define CALCULATOR_DOWN BUTTON_DOWN
|
||
#define CALCULATOR_QUIT BUTTON_POWER
|
||
#define CALCULATOR_INPUT BUTTON_SELECT
|
||
#define CALCULATOR_CALC BUTTON_PLAY
|
||
#define CALCULATOR_CLEAR BUTTON_PREV
|
||
|
||
#else
|
||
#error No keymap defined!
|
||
#endif
|
||
|
||
#ifdef HAVE_TOUCHSCREEN
|
||
#ifndef CALCULATOR_LEFT
|
||
#define CALCULATOR_LEFT BUTTON_MIDLEFT
|
||
#endif
|
||
#ifndef CALCULATOR_RIGHT
|
||
#define CALCULATOR_RIGHT BUTTON_MIDRIGHT
|
||
#endif
|
||
#ifndef CALCULATOR_UP
|
||
#define CALCULATOR_UP BUTTON_TOPMIDDLE
|
||
#endif
|
||
#ifndef CALCULATOR_DOWN
|
||
#define CALCULATOR_DOWN BUTTON_BOTTOMMIDDLE
|
||
#endif
|
||
#ifndef CALCULATOR_CALC
|
||
#define CALCULATOR_CALC BUTTON_BOTTOMRIGHT
|
||
#endif
|
||
#ifndef CALCULATOR_INPUT
|
||
#define CALCULATOR_INPUT BUTTON_CENTER
|
||
#endif
|
||
#ifndef CALCULATOR_CLEAR
|
||
#define CALCULATOR_CLEAR BUTTON_TOPRIGHT
|
||
#endif
|
||
|
||
#include "lib/pluginlib_touchscreen.h"
|
||
static struct ts_raster calc_raster = { X_0_POS, Y_1_POS,
|
||
BUTTON_COLS*REC_WIDTH, BUTTON_ROWS*REC_HEIGHT, REC_WIDTH, REC_HEIGHT };
|
||
#endif
|
||
|
||
enum {
|
||
basicButtons,
|
||
sciButtons
|
||
} buttonGroup;
|
||
|
||
unsigned char* buttonChar[2][5][5] = {
|
||
{ { "MR" , "M+" , "2nd" , "CE" , "C" },
|
||
{ "7" , "8" , "9" , "/" , "sqr" },
|
||
{ "4" , "5" , "6" , "*" , "x^2" },
|
||
{ "1" , "2" , "3" , "-" , "1/x" },
|
||
{ "0" , "+/-", "." , "+" , "=" } },
|
||
|
||
{ { "n!" , "PI" , "1st" , "sin" , "asi" },
|
||
{ "7" , "8" , "9" , "cos" , "aco" },
|
||
{ "4" , "5" , "6" , "tan" , "ata" },
|
||
{ "1" , "2" , "3" , "ln" , "e^x" },
|
||
{ "0" , "+/-", "." , "log" , "x^y" } }
|
||
};
|
||
|
||
enum { btn_MR , btn_M , btn_bas , btn_CE , btn_C ,
|
||
btn_7 , btn_8 , btn_9 , btn_div , btn_sqr ,
|
||
btn_4 , btn_5 , btn_6 , btn_time , btn_square ,
|
||
btn_1 , btn_2 , btn_3 , btn_minus , btn_rec ,
|
||
btn_0 , btn_sign , btn_dot , btn_add , btn_equal
|
||
};
|
||
|
||
enum { sci_fac, sci_pi , sci_sci , sci_sin , sci_asin ,
|
||
sci_7 , sci_8 , sci_9 , sci_cos , sci_acos ,
|
||
sci_4 , sci_5 , sci_6 , sci_tan , sci_atan ,
|
||
sci_1 , sci_2 , sci_3 , sci_ln , sci_exp ,
|
||
sci_0 , sci_sign , sci_dot , sci_log , sci_xy
|
||
};
|
||
|
||
#define MINIMUM 0.000000000001 /* e-12 */
|
||
/* ^ ^ ^ ^ */
|
||
/* 123456789abcdef */
|
||
|
||
#define DIGITLEN 10 /* must <= 10 */
|
||
#define SCIENTIFIC_FORMAT ( power < -(DIGITLEN-3) || power > (DIGITLEN))
|
||
/* 0.000 00000 0001 */
|
||
/* ^ ^ ^ ^ ^ ^ */
|
||
/* DIGITLEN 12345 6789a bcdef */
|
||
/* power 12 34567 89abc def */
|
||
/* 10^- 123 45678 9abcd ef */
|
||
|
||
unsigned char buf[19];/* 18 bytes of output line,
|
||
buf[0] is operator
|
||
buf[1] = 'M' if memTemp is not 0
|
||
buf[2] = ' '
|
||
|
||
if SCIENTIFIC_FORMAT
|
||
buf[2]-buf[12] or buf[3]-buf[13] = result;
|
||
format X.XXXXXXXX
|
||
buf[13] or buf[14] -buf[17] = power;
|
||
format eXXX or e-XXX
|
||
else
|
||
buf[3]-buf[6] = ' ';
|
||
buf[7]-buf[17] = result;
|
||
|
||
buf[18] = '\0' */
|
||
|
||
unsigned char typingbuf[DIGITLEN+2];/* byte 0 is sign or ' ',
|
||
byte 1~DIGITLEN are num and '.'
|
||
byte (DIGITLEN+1) is '\0' */
|
||
unsigned char* typingbufPointer = typingbuf;
|
||
|
||
double result = 0; /* main operand, format 0.xxxxx */
|
||
int power = 0; /* 10^power */
|
||
double modifier = 0.1; /* position of next input */
|
||
double operand = 0; /* second operand, format 0.xxxxx */
|
||
int operandPower = 0; /* 10^power of second operand */
|
||
char oper = ' '; /* operators: + - * / */
|
||
bool operInputted = false; /* false: do calculation first and
|
||
replace current oper
|
||
true: just replace current oper */
|
||
|
||
double memTemp = 0; /* temp memory */
|
||
int memTempPower = 0; /* 10^^power of memTemp */
|
||
|
||
int btn_row, btn_col; /* current position index for button */
|
||
int prev_btn_row, prev_btn_col; /* previous cursor position */
|
||
#define CAL_BUTTON (btn_row*5+btn_col)
|
||
|
||
int btn = BUTTON_NONE;
|
||
int lastbtn = BUTTON_NONE;
|
||
|
||
/* Status of calculator */
|
||
enum {cal_normal, /* 0, normal status, display result */
|
||
cal_typing, /* 1, currently typing, dot hasn't been typed */
|
||
cal_dotted, /* 2, currently typing, dot already has been typed. */
|
||
cal_error,
|
||
cal_exit,
|
||
cal_toDo
|
||
} calStatus;
|
||
|
||
/* constant table for CORDIC algorithm */
|
||
static const double cordicTable[51][2]= {
|
||
/* pow(2,0) - pow(2,-50) atan(pow(2,0) - atan(pow(2,-50) */
|
||
{1e+00, 7.853981633974483e-01},
|
||
{5e-01, 4.636476090008061e-01},
|
||
{2.5e-01, 2.449786631268641e-01},
|
||
{1.25e-01, 1.243549945467614e-01},
|
||
{6.25e-02, 6.241880999595735e-02},
|
||
{3.125e-02, 3.123983343026828e-02},
|
||
{1.5625e-02, 1.562372862047683e-02},
|
||
{7.8125e-03, 7.812341060101111e-03},
|
||
{3.90625e-03, 3.906230131966972e-03},
|
||
{1.953125e-03, 1.953122516478819e-03},
|
||
{9.765625e-04, 9.765621895593195e-04},
|
||
{4.8828125e-04, 4.882812111948983e-04},
|
||
{2.44140625e-04, 2.441406201493618e-04},
|
||
{1.220703125e-04, 1.220703118936702e-04},
|
||
{6.103515625e-05, 6.103515617420877e-05},
|
||
{3.0517578125e-05, 3.051757811552610e-05},
|
||
{1.52587890625e-05, 1.525878906131576e-05},
|
||
{7.62939453125e-06, 7.629394531101970e-06},
|
||
{3.814697265625e-06, 3.814697265606496e-06},
|
||
{1.9073486328125e-06, 1.907348632810187e-06},
|
||
{9.5367431640625e-07, 9.536743164059608e-07},
|
||
{4.76837158203125e-07, 4.768371582030888e-07},
|
||
{2.384185791015625e-07, 2.384185791015580e-07},
|
||
{1.1920928955078125e-07, 1.192092895507807e-07},
|
||
{5.9604644775390625e-08, 5.960464477539055e-08},
|
||
{2.98023223876953125e-08, 2.980232238769530e-08},
|
||
{1.490116119384765625e-08, 1.490116119384765e-08},
|
||
{7.450580596923828125e-09, 7.450580596923828e-09},
|
||
{3.7252902984619140625e-09, 3.725290298461914e-09},
|
||
{1.86264514923095703125e-09, 1.862645149230957e-09},
|
||
{9.31322574615478515625e-10, 9.313225746154785e-10},
|
||
{4.656612873077392578125e-10, 4.656612873077393e-10},
|
||
{2.3283064365386962890625e-10, 2.328306436538696e-10},
|
||
{1.16415321826934814453125e-10, 1.164153218269348e-10},
|
||
{5.82076609134674072265625e-11, 5.820766091346741e-11},
|
||
{2.910383045673370361328125e-11, 2.910383045673370e-11},
|
||
{1.4551915228366851806640625e-11, 1.455191522836685e-11},
|
||
{7.2759576141834259033203125e-12, 7.275957614183426e-12},
|
||
{3.63797880709171295166015625e-12, 3.637978807091713e-12},
|
||
{1.818989403545856475830078125e-12, 1.818989403545856e-12},
|
||
{9.094947017729282379150390625e-13, 9.094947017729282e-13},
|
||
{4.5474735088646411895751953125e-13, 4.547473508864641e-13},
|
||
{2.27373675443232059478759765625e-13, 2.273736754432321e-13},
|
||
{1.136868377216160297393798828125e-13, 1.136868377216160e-13},
|
||
{5.684341886080801486968994140625e-14, 5.684341886080801e-14},
|
||
{2.8421709430404007434844970703125e-14, 2.842170943040401e-14},
|
||
{1.42108547152020037174224853515625e-14, 1.421085471520200e-14},
|
||
{7.10542735760100185871124267578125e-15, 7.105427357601002e-15},
|
||
{3.552713678800500929355621337890625e-15, 3.552713678800501e-15},
|
||
{1.7763568394002504646778106689453125e-15, 1.776356839400250e-15},
|
||
{8.8817841970012523233890533447265625e-16, 8.881784197001252e-16}
|
||
};
|
||
|
||
static void doMultiple(double* operandOne, int* powerOne,
|
||
double operandTwo, int powerTwo);
|
||
static void doAdd (double* operandOne, int* powerOne,
|
||
double operandTwo, int powerTwo);
|
||
static void printResult(void);
|
||
static void formatResult(void);
|
||
static void oneOperand(void);
|
||
|
||
static void drawLines(void);
|
||
static void drawButtons(int group);
|
||
|
||
/* -----------------------------------------------------------------------
|
||
Handy functions
|
||
----------------------------------------------------------------------- */
|
||
static void cleartypingbuf(void)
|
||
{
|
||
int k;
|
||
for( k=1; k<=(DIGITLEN+1); k++)
|
||
typingbuf[k] = 0;
|
||
typingbuf[0] = ' ';
|
||
typingbufPointer = typingbuf+1;
|
||
}
|
||
static void clearbuf(void)
|
||
{
|
||
int k;
|
||
for(k=0;k<18;k++)
|
||
buf[k]=' ';
|
||
buf[18] = 0;
|
||
}
|
||
static void clearResult(void)
|
||
{
|
||
result = 0;
|
||
power = 0;
|
||
modifier = 0.1;
|
||
}
|
||
|
||
static void clearInput(void)
|
||
{
|
||
calStatus = cal_normal;
|
||
clearResult();
|
||
cleartypingbuf();
|
||
rb->lcd_clear_display();
|
||
drawButtons(buttonGroup);
|
||
drawLines();
|
||
}
|
||
|
||
static void clearOperand(void)
|
||
{
|
||
operand = 0;
|
||
operandPower = 0;
|
||
}
|
||
|
||
static void clearMemTemp(void)
|
||
{
|
||
memTemp = 0;
|
||
memTempPower = 0;
|
||
}
|
||
|
||
static void clearOper(void)
|
||
{
|
||
oper = ' ';
|
||
operInputted = false;
|
||
}
|
||
|
||
static void clearMem(void)
|
||
{
|
||
clearInput();
|
||
clearMemTemp();
|
||
clearOperand();
|
||
clearOper();
|
||
btn = BUTTON_NONE;
|
||
}
|
||
|
||
static void switchOperands(void)
|
||
{
|
||
double tempr = operand;
|
||
int tempp = operandPower;
|
||
operand = result;
|
||
operandPower = power;
|
||
result = tempr;
|
||
power = tempp;
|
||
}
|
||
|
||
static void drawLines(void)
|
||
{
|
||
int i;
|
||
rb->lcd_hline(0, LCD_WIDTH, Y_1_POS-1);
|
||
for (i = 0; i < 5 ; i++)
|
||
rb->lcd_hline(0, LCD_WIDTH, Y_1_POS+i*REC_HEIGHT);
|
||
for (i = 0; i < 4 ; i++)
|
||
rb->lcd_vline(X_1_POS+i*REC_WIDTH, Y_1_POS, LCD_HEIGHT);
|
||
}
|
||
|
||
static void drawButtons(int group)
|
||
{
|
||
int i, j, w, h;
|
||
for (i = 0; i <= 4; i++){
|
||
for (j = 0; j <= 4; j++){
|
||
rb->lcd_getstringsize( buttonChar[group][i][j],&w,&h);
|
||
if (i == btn_row && j == btn_col) /* selected item */
|
||
rb->lcd_set_drawmode(DRMODE_SOLID);
|
||
else
|
||
rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
|
||
rb->lcd_fillrect( X_0_POS + j*REC_WIDTH,
|
||
Y_1_POS + i*REC_HEIGHT,
|
||
REC_WIDTH, REC_HEIGHT+1);
|
||
if (i == btn_row && j == btn_col) /* selected item */
|
||
rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
|
||
else
|
||
rb->lcd_set_drawmode(DRMODE_SOLID);
|
||
rb->lcd_putsxy( X_0_POS + j*REC_WIDTH + (REC_WIDTH - w)/2,
|
||
Y_1_POS + i*REC_HEIGHT + (REC_HEIGHT - h)/2 + 1,
|
||
buttonChar[group][i][j] );
|
||
}
|
||
}
|
||
rb->lcd_set_drawmode(DRMODE_SOLID);
|
||
}
|
||
|
||
/* -----------------------------------------------------------------------
|
||
Initiate calculator
|
||
----------------------------------------------------------------------- */
|
||
static void cal_initial (void)
|
||
{
|
||
int w,h;
|
||
|
||
rb->lcd_getstringsize("2nd",&w,&h);
|
||
if (w > REC_WIDTH || h > REC_HEIGHT)
|
||
rb->lcd_setfont(FONT_SYSFIXED);
|
||
|
||
rb->lcd_clear_display();
|
||
|
||
#ifdef CALCULATOR_OPERATORS
|
||
/* basic operators are available through separate button */
|
||
buttonGroup = sciButtons;
|
||
#else
|
||
buttonGroup = basicButtons;
|
||
#endif
|
||
|
||
/* initially, invert button "5" */
|
||
btn_row = 2;
|
||
btn_col = 1;
|
||
prev_btn_row = btn_row;
|
||
prev_btn_col = btn_col;
|
||
drawButtons(buttonGroup);
|
||
drawLines();
|
||
rb->lcd_update();
|
||
|
||
/* initial mem and output display*/
|
||
clearMem();
|
||
printResult();
|
||
|
||
/* clear button queue */
|
||
rb->button_clear_queue();
|
||
}
|
||
|
||
/* -----------------------------------------------------------------------
|
||
mySqrt uses Heron's algorithm, which is the Newtone-Raphson algorhitm
|
||
in it's private case for sqrt.
|
||
Thanks BlueChip for his intro text and Dave Straayer for the actual name.
|
||
----------------------------------------------------------------------- */
|
||
static double mySqrt(double square)
|
||
{
|
||
int k = 0;
|
||
double temp = 0;
|
||
double root= ABS(square+1)/2;
|
||
|
||
while( ABS(root - temp) > MINIMUM ){
|
||
temp = root;
|
||
root = (square/temp + temp)/2;
|
||
k++;
|
||
if (k>10000) return 0;
|
||
}
|
||
|
||
return root;
|
||
}
|
||
|
||
/*Uses the sequence sum(x^k/k!) that tends to exp(x)*/
|
||
static double myExp (double x) {
|
||
unsigned int k=0;
|
||
double res=0, xPow=1,fact=1,toAdd;
|
||
|
||
do {
|
||
toAdd = xPow/fact;
|
||
res += toAdd;
|
||
xPow *= x; //xPow = x^k
|
||
k++;
|
||
fact*=k; //fact = k!
|
||
} while (ABS(toAdd) > MINIMUM && xPow<1e302);
|
||
return res;
|
||
}
|
||
|
||
/*myLn : uses the series ln(a) = 2 * ∑(1/(2n+1) * ((a-1)/(a+1))^(2k+1) )*/
|
||
static double myLn (double a) {
|
||
unsigned int k=1;
|
||
double res=0,xPow,xSquare,fract=1,toAdd;
|
||
|
||
xPow = (a-1)/(a+1);
|
||
xSquare = xPow*xPow;
|
||
|
||
do {
|
||
toAdd = fract*xPow;
|
||
res += toAdd;
|
||
xPow *= xSquare; // ((a-1)/(a+1))^k
|
||
k+=2;
|
||
fract=1./k;
|
||
} while (ABS(toAdd) > MINIMUM);
|
||
return res * 2;
|
||
}
|
||
|
||
|
||
/* -----------------------------------------------------------------------
|
||
transcendFunc uses CORDIC (COordinate Rotation DIgital Computer) method
|
||
transcendFunc can do sin,cos,log,exp
|
||
input parameter is angle
|
||
----------------------------------------------------------------------- */
|
||
static void transcendFunc(char* func, double* tt, int* ttPower)
|
||
{
|
||
double t = (*tt)*M_PI/180; int tPower = *ttPower;
|
||
int sign = 1;
|
||
int n = 50; /* n <=50, tables are all <= 50 */
|
||
int j;
|
||
double x,y,z,xt,yt,zt;
|
||
|
||
if (tPower < -998) {
|
||
calStatus = cal_normal;
|
||
return;
|
||
}
|
||
if (tPower > 8) {
|
||
calStatus = cal_error;
|
||
return;
|
||
}
|
||
*ttPower = 0;
|
||
calStatus = cal_normal;
|
||
|
||
if( func[0] =='s' || func[0] =='S'|| func[0] =='t' || func[0] =='T')
|
||
sign = SIGN(t);
|
||
else {
|
||
/* if( func[0] =='c' || func[0] =='C') */
|
||
sign = 1;
|
||
}
|
||
t = ABS(t);
|
||
|
||
while (tPower > 0){
|
||
t *= 10;
|
||
tPower--;
|
||
}
|
||
while (tPower < 0) {
|
||
t /= 10;
|
||
tPower++;
|
||
}
|
||
j = 0;
|
||
while (t > j*M_TWOPI) {j++;}
|
||
t -= (j-1)*M_TWOPI;
|
||
if (M_PI_2 < t && t < 3*M_PI_2){
|
||
t = M_PI - t;
|
||
if (func[0] =='c' || func[0] =='C')
|
||
sign = -1;
|
||
else if (func[0] =='t' || func[0] =='T')
|
||
t*=-1;
|
||
}
|
||
else if ( 3*M_PI_2 <= t && t <= M_TWOPI)
|
||
t -= M_TWOPI;
|
||
|
||
x = 0.60725293500888; y = 0; z = t;
|
||
for (j=1;j<n+2;j++){
|
||
xt = x - SIGN(z) * y*cordicTable[j-1][0];
|
||
yt = y + SIGN(z) * x*cordicTable[j-1][0];
|
||
zt = z - SIGN(z) * cordicTable[j-1][1];
|
||
x = xt;
|
||
y=yt;
|
||
z=zt;
|
||
}
|
||
if( func[0] =='s' || func[0] =='S') {
|
||
*tt = sign*y;
|
||
return;
|
||
}
|
||
else if( func[0] =='c' || func[0] =='C') {
|
||
*tt = sign*x;
|
||
return;
|
||
}
|
||
else /*if( func[0] =='t' || func[0] =='T')*/ {
|
||
if(t==M_PI_2||t==-M_PI_2){
|
||
calStatus = cal_error;
|
||
return;
|
||
}
|
||
else{
|
||
*tt = sign*(y/x);
|
||
return;
|
||
}
|
||
}
|
||
|
||
}
|
||
/* -----------------------------------------------------------------------
|
||
add in scientific number format
|
||
----------------------------------------------------------------------- */
|
||
static void doAdd (double* operandOne, int* powerOne,
|
||
double operandTwo, int powerTwo)
|
||
{
|
||
if ( *powerOne >= powerTwo ){
|
||
if (*powerOne - powerTwo <= DIGITLEN+1){
|
||
while (powerTwo < *powerOne){
|
||
operandTwo /=10;
|
||
powerTwo++;
|
||
}
|
||
*operandOne += operandTwo;
|
||
}
|
||
/*do nothing if operandTwo is too small*/
|
||
}
|
||
else{
|
||
if (powerTwo - *powerOne <= DIGITLEN+1){
|
||
while(powerTwo > *powerOne){
|
||
*operandOne /=10;
|
||
(*powerOne)++;
|
||
}
|
||
(*operandOne) += operandTwo;
|
||
}
|
||
else{/* simply copy operandTwo if operandOne is too small */
|
||
*operandOne = operandTwo;
|
||
*powerOne = powerTwo;
|
||
}
|
||
}
|
||
}
|
||
/* -----------------------------------------------------------------------
|
||
multiple in scientific number format
|
||
----------------------------------------------------------------------- */
|
||
static void doMultiple(double* operandOne, int* powerOne,
|
||
double operandTwo, int powerTwo)
|
||
{
|
||
(*operandOne) *= operandTwo;
|
||
(*powerOne) += powerTwo;
|
||
}
|
||
|
||
/* -----------------------------------------------------------------------
|
||
Handles all one operand calculations
|
||
----------------------------------------------------------------------- */
|
||
static void oneOperand(void)
|
||
{
|
||
int k = 0;
|
||
|
||
if (buttonGroup == basicButtons){
|
||
switch(CAL_BUTTON){
|
||
case btn_sqr:
|
||
if (result<0)
|
||
calStatus = cal_error;
|
||
else{
|
||
if (power%2 == 1){
|
||
result = (mySqrt(result*10))/10;
|
||
power = (power+1) / 2;
|
||
}
|
||
else{
|
||
result = mySqrt(result);
|
||
power = power / 2;
|
||
}
|
||
calStatus = cal_normal;
|
||
}
|
||
break;
|
||
case btn_square:
|
||
power *= 2;
|
||
result *= result;
|
||
calStatus = cal_normal;
|
||
break;
|
||
|
||
case btn_rec:
|
||
if (result==0)
|
||
calStatus = cal_error;
|
||
else{
|
||
power = -power;
|
||
result = 1/result;
|
||
calStatus = cal_normal;
|
||
}
|
||
break;
|
||
default:
|
||
calStatus = cal_toDo;
|
||
break; /* just for the safety */
|
||
}
|
||
}
|
||
else{ /* sciButtons */
|
||
switch(CAL_BUTTON){
|
||
case sci_sin:
|
||
transcendFunc("sin", &result, &power);
|
||
break;
|
||
case sci_cos:
|
||
transcendFunc("cos", &result, &power);
|
||
break;
|
||
case sci_tan:
|
||
transcendFunc("tan", &result, &power);
|
||
break;
|
||
case sci_fac:
|
||
if (power<0 || power>8 || result<0 )
|
||
calStatus = cal_error;
|
||
else if(result == 0) {
|
||
result = 1;
|
||
power = 0;
|
||
}
|
||
else{
|
||
while(power > 0) {
|
||
result *= 10;
|
||
power--;
|
||
}
|
||
if ( ( result - (int)result) > MINIMUM )
|
||
calStatus = cal_error;
|
||
else {
|
||
k = result; result = 1;
|
||
while (k > 1){
|
||
doMultiple(&result, &power, k, 0);
|
||
formatResult();
|
||
k--;
|
||
}
|
||
calStatus = cal_normal;
|
||
}
|
||
}
|
||
break;
|
||
case sci_exp:
|
||
/*Uses the sequence (1+a/n)^n -> exp(a) */
|
||
if (power>3 || result > 1e3) calStatus = cal_error;
|
||
else {
|
||
while(power < 0) {
|
||
result /= 10;
|
||
power++;
|
||
}
|
||
while (power > 0){
|
||
power--;
|
||
result*=10;
|
||
}
|
||
result = myExp(result);
|
||
calStatus = cal_normal;
|
||
}
|
||
break;
|
||
case sci_ln:
|
||
if (result<=0) calStatus = cal_error;
|
||
else {
|
||
//ln(a*10^n) = ln(a) + n*ln(10), with ln(10) ≈ 2.30
|
||
result = myLn(result) + power * 2.302585092994046;
|
||
power=0;
|
||
calStatus = cal_normal;
|
||
}
|
||
break;
|
||
case sci_log:
|
||
if (result<=0) calStatus = cal_error;
|
||
else {
|
||
//log10(a+10^n) = ln(a)/ln(10) + n, with ln(10) ≈ 2.30
|
||
result = myLn(result)/2.302585092994046 + power;
|
||
power=0;
|
||
calStatus = cal_normal;
|
||
}
|
||
break;
|
||
default:
|
||
calStatus = cal_toDo;
|
||
break; /* just for the safety */
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
/* -----------------------------------------------------------------------
|
||
Handles all two operands calculations
|
||
----------------------------------------------------------------------- */
|
||
static void twoOperands(void)
|
||
{
|
||
switch(oper){
|
||
case '-':
|
||
doAdd(&operand, &operandPower, -result, power);
|
||
break;
|
||
case '+':
|
||
doAdd(&operand, &operandPower, result, power);
|
||
break;
|
||
case '*':
|
||
doMultiple(&operand, &operandPower, result, power);
|
||
break;
|
||
case '/':
|
||
if ( ABS(result) > MINIMUM ){
|
||
doMultiple(&operand, &operandPower, 1/result, -power);
|
||
}
|
||
else
|
||
calStatus = cal_error;
|
||
break;
|
||
default: /* ' ' */
|
||
switchOperands(); /* counter switchOperands() below */
|
||
break;
|
||
} /* switch(oper) */
|
||
switchOperands();
|
||
clearOper();
|
||
}
|
||
|
||
/* First, increases *dimen1 by dimen1_delta modulo dimen1_modulo.
|
||
If dimen1 wraps, increases *dimen2 by dimen2_delta modulo dimen2_modulo.
|
||
*/
|
||
static void move_with_wrap_and_shift(
|
||
int *dimen1, int dimen1_delta, int dimen1_modulo,
|
||
int *dimen2, int dimen2_delta, int dimen2_modulo)
|
||
{
|
||
bool wrapped = false;
|
||
|
||
*dimen1 += dimen1_delta;
|
||
if (*dimen1 < 0)
|
||
{
|
||
*dimen1 = dimen1_modulo - 1;
|
||
wrapped = true;
|
||
}
|
||
else if (*dimen1 >= dimen1_modulo)
|
||
{
|
||
*dimen1 = 0;
|
||
wrapped = true;
|
||
}
|
||
|
||
if (wrapped)
|
||
{
|
||
/* Make the dividend always positive to be sure about the result.
|
||
Adding dimen2_modulo does not change it since we do it modulo. */
|
||
*dimen2 = (*dimen2 + dimen2_modulo + dimen2_delta) % dimen2_modulo;
|
||
}
|
||
}
|
||
|
||
/* -----------------------------------------------------------------------
|
||
Print buttons when switching 1st and 2nd
|
||
int group = {basicButtons, sciButtons}
|
||
----------------------------------------------------------------------- */
|
||
static void printButtonGroups(int group)
|
||
{
|
||
drawButtons(group);
|
||
drawLines();
|
||
rb->lcd_update();
|
||
}
|
||
/* -----------------------------------------------------------------------
|
||
flash the currently marked button
|
||
----------------------------------------------------------------------- */
|
||
static void flashButton(void)
|
||
{
|
||
int k, w, h;
|
||
for (k=2;k>0;k--)
|
||
{
|
||
rb->lcd_getstringsize( buttonChar[buttonGroup][btn_row][btn_col],&w,&h);
|
||
rb->lcd_set_drawmode(DRMODE_SOLID|(k==1) ? 0 : DRMODE_INVERSEVID);
|
||
rb->lcd_fillrect( X_0_POS + btn_col*REC_WIDTH + 1,
|
||
Y_1_POS + btn_row*REC_HEIGHT + 1,
|
||
REC_WIDTH - 1, REC_HEIGHT - 1);
|
||
rb->lcd_putsxy( X_0_POS + btn_col*REC_WIDTH + (REC_WIDTH - w)/2,
|
||
Y_1_POS + btn_row*REC_HEIGHT + (REC_HEIGHT - h)/2 +1,
|
||
buttonChar[buttonGroup][btn_row][btn_col] );
|
||
rb->lcd_update_rect( X_0_POS + btn_col*REC_WIDTH + 1,
|
||
Y_1_POS + btn_row*REC_HEIGHT + 1,
|
||
REC_WIDTH - 1, REC_HEIGHT - 1);
|
||
|
||
if (k!= 1)
|
||
rb->sleep(HZ/22);
|
||
|
||
}
|
||
}
|
||
|
||
/* -----------------------------------------------------------------------
|
||
pos is the position that needs animation. pos = [1~18]
|
||
----------------------------------------------------------------------- */
|
||
#if defined(CALCULATOR_CLEAR) || defined(CALCULATOR_OPERATORS)
|
||
static void deleteAnimation(int pos)
|
||
{
|
||
int k, w, h, x;
|
||
if (pos<1 || pos >18)
|
||
return;
|
||
|
||
rb->lcd_getstringsize("0", &w, &h);
|
||
x = (pos==1? 4: LCD_WIDTH - 4 - w);
|
||
|
||
for (k=0;k<4;k++){
|
||
rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
|
||
rb->lcd_fillrect(x, Y_1_POS - h -1, w, h);
|
||
rb->lcd_set_drawmode(DRMODE_SOLID);
|
||
rb->lcd_fillrect(x + (w*k)/8, Y_1_POS - h -1 + (h*k)/8,
|
||
(w*(4-k))/4, (h*(4-k))/4);
|
||
rb->lcd_update_rect(x, Y_1_POS - h -1, w, h);
|
||
rb->sleep(HZ/32);
|
||
}
|
||
}
|
||
#endif
|
||
|
||
/* -----------------------------------------------------------------------
|
||
result may be one of these formats:
|
||
0
|
||
xxxx.xxxx
|
||
0.xxxx
|
||
0.0000xxxx
|
||
|
||
formatResult() change result to standard format: 0.xxxx
|
||
if result is close to 0, let it be 0;
|
||
if result is close to 1, let it be 0.1 and power++;
|
||
----------------------------------------------------------------------- */
|
||
static void formatResult(void)
|
||
{
|
||
int resultsign = SIGN(result);
|
||
result = ABS(result);
|
||
if(result > MINIMUM ){ /* doesn't check power, might have problem
|
||
input wouldn't,
|
||
+ - * / of two formatted number wouldn't.
|
||
only a calculation that makes a formatted
|
||
number (0.xxxx) less than MINIMUM in only
|
||
one operation */
|
||
|
||
if (result<1){
|
||
while( (int)(result*10) == 0 ){
|
||
result *= 10;
|
||
power--;
|
||
modifier *= 10;
|
||
}
|
||
}
|
||
else{ /* result >= 1 */
|
||
while( (int)result != 0 ){
|
||
result /= 10;
|
||
power++;
|
||
modifier /= 10;
|
||
}
|
||
} /* if result<1 */
|
||
|
||
if (result > (1-MINIMUM)){
|
||
result = 0.1;
|
||
power++;
|
||
modifier /= 10;
|
||
}
|
||
result *= resultsign;
|
||
}
|
||
else {
|
||
result = 0;
|
||
power = 0;
|
||
modifier = 0.1;
|
||
}
|
||
}
|
||
|
||
/* -----------------------------------------------------------------------
|
||
result2typingbuf() outputs standard format result to typingbuf.
|
||
case SCIENTIFIC_FORMAT, let temppower = 1;
|
||
case temppower > 0: print '.' in the middle
|
||
case temppower <= 0: print '.' in the begining
|
||
----------------------------------------------------------------------- */
|
||
static void result2typingbuf(void)
|
||
{
|
||
bool haveDot = false;
|
||
char tempchar = 0;
|
||
int k;
|
||
double tempresult = ABS(result); /* positive num makes things simple */
|
||
|
||
int temppower;
|
||
double tempmodifier = 1;
|
||
int count;
|
||
|
||
if(SCIENTIFIC_FORMAT)
|
||
temppower = 1; /* output x.xxxx format */
|
||
else
|
||
temppower = power;
|
||
|
||
cleartypingbuf();
|
||
|
||
if(tempresult < MINIMUM){ /* if 0,faster display and avoid complication*/
|
||
typingbuf[0] = ' ';
|
||
typingbuf[1] = '0';
|
||
}
|
||
else{ /* tempresult > 0 */
|
||
typingbuf[0] = (SIGN(result)<0)?'-':' ';
|
||
|
||
typingbufPointer = typingbuf;
|
||
if(temppower > 0){
|
||
for (k = 0; k<DIGITLEN+1 ; k++){
|
||
typingbufPointer++;
|
||
if(temppower || *(typingbufPointer-1) == '.'){
|
||
count = 0;
|
||
tempmodifier = tempmodifier/10;
|
||
while( (tempresult-tempmodifier*count) >
|
||
(tempmodifier-MINIMUM)){
|
||
count++;
|
||
}
|
||
tempresult -= tempmodifier*count;
|
||
tempresult = ABS(tempresult);
|
||
temppower-- ;
|
||
*typingbufPointer = count + '0';
|
||
}
|
||
else{ /* temppower == 0 */
|
||
*typingbufPointer = '.';
|
||
haveDot = true;
|
||
}
|
||
} /* for */
|
||
}
|
||
else{
|
||
haveDot = true;
|
||
typingbufPointer++; *typingbufPointer = '0';
|
||
typingbufPointer++; *typingbufPointer = '.';
|
||
for (k = 2; k<DIGITLEN+1 ; k++){
|
||
typingbufPointer++;
|
||
count = 0;
|
||
if ( (-temppower) < (k-1)){
|
||
tempmodifier = tempmodifier/10;
|
||
while((tempresult-tempmodifier*count)>(tempmodifier-MINIMUM)){
|
||
count++;
|
||
|
||
}
|
||
tempresult -= tempmodifier*count;
|
||
tempresult = ABS(tempresult);
|
||
temppower-- ;
|
||
}
|
||
*typingbufPointer = count + '0';
|
||
}
|
||
}
|
||
/* now, typingbufPointer = typingbuf + 16 */
|
||
/* backward strip off 0 and '.' */
|
||
if (haveDot){
|
||
while( (*typingbufPointer == '0') || (*typingbufPointer == '.')){
|
||
tempchar = *typingbufPointer;
|
||
*typingbufPointer = 0;
|
||
typingbufPointer--;
|
||
if (tempchar == '.') break;
|
||
}
|
||
}
|
||
typingbuf[DIGITLEN+1] = 0;
|
||
} /* else tempresult > 0 */
|
||
}
|
||
|
||
/* -----------------------------------------------------------------------
|
||
printResult() generates LCD display.
|
||
----------------------------------------------------------------------- */
|
||
static void printResult(void)
|
||
{
|
||
int k, w, h;
|
||
|
||
char operbuf[3] = {0, 0, 0};
|
||
|
||
switch_Status:
|
||
switch(calStatus){
|
||
case cal_exit:
|
||
rb->lcd_clear_display();
|
||
rb->splash(HZ/3, "Bye now!");
|
||
break;
|
||
case cal_error:
|
||
clearbuf();
|
||
rb->snprintf(buf, 19, "%18s","Error");
|
||
break;
|
||
case cal_toDo:
|
||
clearbuf();
|
||
rb->snprintf(buf, 19, "%18s","Coming soon ^_* ");
|
||
break;
|
||
|
||
case cal_normal:
|
||
formatResult();
|
||
|
||
if( power > 1000 ){ /* power -1 > 999 */
|
||
calStatus = cal_error;
|
||
goto switch_Status;
|
||
}
|
||
if (power < -998 ) /* power -1 < -999 */
|
||
clearResult(); /* too small, let it be 0 */
|
||
|
||
result2typingbuf();
|
||
clearbuf();
|
||
|
||
operbuf[0] = oper;
|
||
operbuf[1] = ( ABS(memTemp) > MINIMUM )?'M':' ';
|
||
operbuf[2] = '\0';
|
||
|
||
if(SCIENTIFIC_FORMAT){
|
||
/* output format: X.XXXX eXXX */
|
||
if(power > -98){ /* power-1 >= -99, eXXX or e-XX */
|
||
rb->snprintf(buf, 12, "%11s",typingbuf);
|
||
for(k=11;k<=14;k++) buf[k] = ' ';
|
||
cleartypingbuf();
|
||
rb->snprintf(typingbuf, 5, "e%d",power-1);
|
||
rb->snprintf(buf+11, 5, "%4s",typingbuf);
|
||
}
|
||
else{ /* power-1 <= -100, e-XXX */
|
||
rb->snprintf(buf, 12, "%11s",typingbuf);
|
||
rb->snprintf(buf+11, 6, "e%d",power-1);
|
||
}
|
||
}
|
||
else{
|
||
rb->snprintf(buf, 12, "%11s",typingbuf);
|
||
} /* if SCIENTIFIC_FORMAT */
|
||
break;
|
||
case cal_typing:
|
||
case cal_dotted:
|
||
clearbuf();
|
||
operbuf[0] = oper;
|
||
operbuf[1] = ( ABS(memTemp) > MINIMUM )?'M':' ';
|
||
rb->snprintf(buf, 12, "%11s",typingbuf);
|
||
break;
|
||
|
||
}
|
||
|
||
rb->lcd_getstringsize(buf, &w, &h);
|
||
rb->screen_clear_area(rb->screens[0], 0, 0, LCD_WIDTH, Y_1_POS - 1);
|
||
rb->lcd_putsxy(4, Y_1_POS - h -1, operbuf);
|
||
rb->lcd_putsxy(LCD_WIDTH - w - 4, Y_1_POS - h -1, buf);
|
||
rb->lcd_update_rect(0, 1, LCD_WIDTH, Y_1_POS);
|
||
}
|
||
|
||
/* -----------------------------------------------------------------------
|
||
Process typing buttons: 1-9, '.', sign
|
||
main operand "result" and typingbuf are processed seperately here.
|
||
----------------------------------------------------------------------- */
|
||
static void typingProcess(void){
|
||
switch( CAL_BUTTON ){
|
||
case btn_sign:
|
||
if (calStatus == cal_typing ||
|
||
calStatus == cal_dotted)
|
||
typingbuf[0] = (typingbuf[0]=='-')?' ':'-';
|
||
result = -result;
|
||
break;
|
||
case btn_dot:
|
||
operInputted = false;
|
||
switch(calStatus){
|
||
case cal_normal:
|
||
clearInput();
|
||
*typingbufPointer = '0';
|
||
typingbufPointer++;
|
||
case cal_typing:
|
||
calStatus = cal_dotted;
|
||
*typingbufPointer = '.';
|
||
if (typingbufPointer != typingbuf+DIGITLEN+1)
|
||
typingbufPointer++;
|
||
break;
|
||
default: /* cal_dotted */
|
||
break;
|
||
}
|
||
break;
|
||
default: /* 0-9 */
|
||
operInputted = false;
|
||
/* normal,0; normal,1-9; typing,0; typing,1-9 */
|
||
switch(calStatus){
|
||
case cal_normal:
|
||
if(CAL_BUTTON == btn_0 )
|
||
break; /* first input is 0, ignore */
|
||
clearInput();
|
||
/*no operator means start a new calculation*/
|
||
if (oper ==' ')
|
||
clearOperand();
|
||
calStatus = cal_typing;
|
||
/* go on typing, no break */
|
||
case cal_typing:
|
||
case cal_dotted:
|
||
switch(CAL_BUTTON){
|
||
case btn_0:
|
||
*typingbufPointer = '0';
|
||
break;
|
||
default:
|
||
*typingbufPointer=(7+btn_col-3*(btn_row-1))+ '0';
|
||
break;
|
||
}
|
||
if (typingbufPointer!=typingbuf+DIGITLEN+1){
|
||
typingbufPointer++;
|
||
|
||
{/* result processing */
|
||
if (calStatus == cal_typing) power++;
|
||
if (CAL_BUTTON != btn_0)
|
||
result= result +
|
||
SIGN(result)*
|
||
(7+btn_col-3*(btn_row-1))*modifier;
|
||
modifier /= 10;
|
||
}
|
||
}
|
||
else /* last byte always '\0' */
|
||
*typingbufPointer = 0;
|
||
break;
|
||
default: /* cal_error, cal_exit */
|
||
break;
|
||
}
|
||
break; /* default, 0-9 */
|
||
} /* switch( CAL_BUTTON ) */
|
||
}
|
||
|
||
/* -----------------------------------------------------------------------
|
||
Handle delete operation
|
||
main operand "result" and typingbuf are processed seperately here.
|
||
----------------------------------------------------------------------- */
|
||
#ifdef CALCULATOR_CLEAR
|
||
static void doDelete(void){
|
||
deleteAnimation(18);
|
||
switch(calStatus){
|
||
case cal_dotted:
|
||
if (*(typingbufPointer-1) == '.'){
|
||
/* if dotted and deleting '.',
|
||
change status and delete '.' below */
|
||
calStatus = cal_typing;
|
||
}
|
||
else{ /* if dotted and not deleting '.',
|
||
power stays */
|
||
power++; /* counter "power--;" below */
|
||
}
|
||
case cal_typing:
|
||
typingbufPointer--;
|
||
|
||
{/* result processing */ /* 0-9, '.' */
|
||
/* if deleting '.', do nothing */
|
||
if ( *typingbufPointer != '.'){
|
||
power--;
|
||
modifier *= 10;
|
||
result = result - SIGN(result)*
|
||
((*typingbufPointer)- '0')*modifier;
|
||
}
|
||
}
|
||
|
||
*typingbufPointer = 0;
|
||
|
||
/* if (only one digit left and it's 0)
|
||
or no digit left, change status*/
|
||
if ( typingbufPointer == typingbuf+1 ||
|
||
( typingbufPointer == typingbuf+2 &&
|
||
*(typingbufPointer-1) == '0' ))
|
||
calStatus = cal_normal;
|
||
break;
|
||
default: /* normal, error, exit */
|
||
break;
|
||
}
|
||
}
|
||
#endif
|
||
/* -----------------------------------------------------------------------
|
||
Handle buttons on basic screen
|
||
----------------------------------------------------------------------- */
|
||
static void basicButtonsProcess(void){
|
||
switch (btn) {
|
||
case CALCULATOR_INPUT:
|
||
if (calStatus == cal_error && (CAL_BUTTON != btn_C) ) break;
|
||
flashButton();
|
||
switch( CAL_BUTTON ){
|
||
case btn_MR:
|
||
operInputted = false;
|
||
result = memTemp; power = memTempPower;
|
||
calStatus = cal_normal;
|
||
break;
|
||
case btn_M:
|
||
formatResult();
|
||
if (memTemp > MINIMUM)
|
||
doAdd(&memTemp, &memTempPower, result, power);
|
||
else {
|
||
/* if result is too small and memTemp = 0,
|
||
doAdd will not add */
|
||
memTemp = result;
|
||
memTempPower = power;
|
||
}
|
||
calStatus = cal_normal;
|
||
break;
|
||
|
||
case btn_C: clearMem(); break;
|
||
case btn_CE: clearInput(); break;
|
||
|
||
case btn_bas:
|
||
buttonGroup = sciButtons;
|
||
printButtonGroups(buttonGroup);
|
||
break;
|
||
|
||
/* one operand calculation, may be changed to
|
||
like sin, cos, log, etc */
|
||
case btn_sqr:
|
||
case btn_square:
|
||
case btn_rec:
|
||
formatResult(); /* not necessary, just for safty */
|
||
oneOperand();
|
||
break;
|
||
|
||
case_btn_equal: /* F3 shortkey entrance */
|
||
case btn_equal:
|
||
formatResult();
|
||
calStatus = cal_normal;
|
||
operInputted = false;
|
||
if (oper != ' ') twoOperands();
|
||
break;
|
||
|
||
case btn_div:
|
||
case btn_time:
|
||
case btn_minus:
|
||
case btn_add:
|
||
if(!operInputted) {twoOperands(); operInputted = true;}
|
||
oper = buttonChar[basicButtons][btn_row][btn_col][0];
|
||
#ifdef CALCULATOR_OPERATORS
|
||
case_cycle_operators: /* F2 shortkey entrance */
|
||
#endif
|
||
calStatus = cal_normal;
|
||
formatResult();
|
||
operand = result;
|
||
operandPower = power;
|
||
|
||
break;
|
||
|
||
case btn_sign:
|
||
case btn_dot:
|
||
default: /* 0-9 */
|
||
typingProcess();
|
||
break;
|
||
} /* switch (CAL_BUTTON) */
|
||
break;
|
||
|
||
#ifdef CALCULATOR_OPERATORS
|
||
case CALCULATOR_OPERATORS:
|
||
if (calStatus == cal_error) break;
|
||
if (!operInputted) {twoOperands(); operInputted = true;}
|
||
switch (oper){
|
||
case ' ':
|
||
case '/': oper = '+'; flashButton(); break;
|
||
case '+': oper = '-'; flashButton(); break;
|
||
case '-': oper = '*'; flashButton(); break;
|
||
case '*': oper = '/'; flashButton(); break;
|
||
}
|
||
goto case_cycle_operators;
|
||
break;
|
||
#endif
|
||
|
||
case CALCULATOR_CALC:
|
||
if (calStatus == cal_error) break;
|
||
flashButton();
|
||
goto case_btn_equal;
|
||
break;
|
||
default: break;
|
||
}
|
||
printResult();
|
||
}
|
||
|
||
/* -----------------------------------------------------------------------
|
||
Handle buttons on scientific screen
|
||
----------------------------------------------------------------------- */
|
||
static void sciButtonsProcess(void){
|
||
switch (btn) {
|
||
case CALCULATOR_INPUT:
|
||
if (calStatus == cal_error && (CAL_BUTTON != sci_sci) ) break;
|
||
flashButton();
|
||
switch( CAL_BUTTON ){
|
||
|
||
case sci_pi:
|
||
result = M_PI; power = 0;
|
||
calStatus = cal_normal;
|
||
break;
|
||
|
||
case sci_xy:
|
||
/*Not implemented yet
|
||
Maybe it could use x^y = exp(y*ln(x))*/
|
||
break;
|
||
|
||
case sci_sci:
|
||
buttonGroup = basicButtons;
|
||
printButtonGroups(basicButtons);
|
||
break;
|
||
|
||
case sci_fac:
|
||
case sci_sin:
|
||
case sci_asin:
|
||
case sci_cos:
|
||
case sci_acos:
|
||
case sci_tan:
|
||
case sci_atan:
|
||
case sci_ln:
|
||
case sci_exp:
|
||
case sci_log:
|
||
formatResult(); /* not necessary, just for safty */
|
||
oneOperand();
|
||
break;
|
||
|
||
case btn_sign:
|
||
case btn_dot:
|
||
default: /* 0-9 */
|
||
typingProcess();
|
||
break;
|
||
} /* switch (CAL_BUTTON) */
|
||
break;
|
||
|
||
#ifdef CALCULATOR_OPERATORS
|
||
case CALCULATOR_OPERATORS:
|
||
if (calStatus == cal_error) break;
|
||
if (!operInputted) {twoOperands(); operInputted = true;}
|
||
switch (oper){
|
||
case ' ': oper = '+'; break;
|
||
case '/': oper = '+'; deleteAnimation(1); break;
|
||
case '+': oper = '-'; deleteAnimation(1); break;
|
||
case '-': oper = '*'; deleteAnimation(1); break;
|
||
case '*': oper = '/'; deleteAnimation(1); break;
|
||
}
|
||
calStatus = cal_normal;
|
||
formatResult();
|
||
operand = result;
|
||
operandPower = power;
|
||
break;
|
||
#endif
|
||
|
||
case CALCULATOR_CALC:
|
||
if (calStatus == cal_error) break;
|
||
formatResult();
|
||
calStatus = cal_normal;
|
||
operInputted = false;
|
||
if (oper != ' ') twoOperands();
|
||
break;
|
||
default: break;
|
||
}
|
||
printResult();
|
||
}
|
||
|
||
/* -----------------------------------------------------------------------
|
||
move button index
|
||
Invert display new button, invert back previous button
|
||
----------------------------------------------------------------------- */
|
||
static int handleButton(int button){
|
||
switch(button)
|
||
{
|
||
case CALCULATOR_INPUT:
|
||
case CALCULATOR_CALC:
|
||
#ifdef CALCULATOR_INPUT_CALC_PRE
|
||
if (lastbtn != CALCULATOR_INPUT_CALC_PRE)
|
||
break;
|
||
/* no unconditional break; here! */
|
||
#endif
|
||
#ifdef CALCULATOR_OPERATORS
|
||
case CALCULATOR_OPERATORS:
|
||
#endif
|
||
switch(buttonGroup){
|
||
case basicButtons:
|
||
basicButtonsProcess();
|
||
break;
|
||
case sciButtons:
|
||
sciButtonsProcess();
|
||
break;
|
||
}
|
||
break;
|
||
|
||
#ifdef CALCULATOR_CLEAR
|
||
case CALCULATOR_CLEAR:
|
||
switch(calStatus){
|
||
case cal_typing:
|
||
case cal_dotted:
|
||
doDelete();
|
||
break;
|
||
default: /* cal_normal, cal_error, cal_exit */
|
||
clearMem();
|
||
break;
|
||
}
|
||
printResult();
|
||
break;
|
||
#endif
|
||
case CALCULATOR_LEFT:
|
||
case CALCULATOR_LEFT | BUTTON_REPEAT:
|
||
move_with_wrap_and_shift(
|
||
&btn_col, -1, BUTTON_COLS,
|
||
&btn_row, 0, BUTTON_ROWS);
|
||
break;
|
||
|
||
case CALCULATOR_RIGHT:
|
||
case CALCULATOR_RIGHT | BUTTON_REPEAT:
|
||
move_with_wrap_and_shift(
|
||
&btn_col, 1, BUTTON_COLS,
|
||
&btn_row, 0, BUTTON_ROWS);
|
||
break;
|
||
|
||
#ifdef CALCULATOR_UP
|
||
case CALCULATOR_UP:
|
||
case CALCULATOR_UP | BUTTON_REPEAT:
|
||
move_with_wrap_and_shift(
|
||
&btn_row, -1, BUTTON_ROWS,
|
||
&btn_col, 0, BUTTON_COLS);
|
||
break;
|
||
#endif
|
||
#ifdef CALCULATOR_DOWN
|
||
case CALCULATOR_DOWN:
|
||
case CALCULATOR_DOWN | BUTTON_REPEAT:
|
||
move_with_wrap_and_shift(
|
||
&btn_row, 1, BUTTON_ROWS,
|
||
&btn_col, 0, BUTTON_COLS);
|
||
break;
|
||
#endif
|
||
|
||
#ifdef CALCULATOR_UP_W_SHIFT
|
||
case CALCULATOR_UP_W_SHIFT:
|
||
case CALCULATOR_UP_W_SHIFT | BUTTON_REPEAT:
|
||
move_with_wrap_and_shift(
|
||
&btn_row, -1, BUTTON_ROWS,
|
||
&btn_col, -1, BUTTON_COLS);
|
||
break;
|
||
#endif
|
||
#ifdef CALCULATOR_DOWN_W_SHIFT
|
||
case CALCULATOR_DOWN_W_SHIFT:
|
||
case CALCULATOR_DOWN_W_SHIFT | BUTTON_REPEAT:
|
||
move_with_wrap_and_shift(
|
||
&btn_row, 1, BUTTON_ROWS,
|
||
&btn_col, 1, BUTTON_COLS);
|
||
break;
|
||
#endif
|
||
#ifdef CALCULATOR_LEFT_W_SHIFT
|
||
case CALCULATOR_LEFT_W_SHIFT:
|
||
case CALCULATOR_LEFT_W_SHIFT | BUTTON_REPEAT:
|
||
move_with_wrap_and_shift(
|
||
&btn_col, -1, BUTTON_COLS,
|
||
&btn_row, -1, BUTTON_ROWS);
|
||
break;
|
||
#endif
|
||
#ifdef CALCULATOR_RIGHT_W_SHIFT
|
||
case CALCULATOR_RIGHT_W_SHIFT:
|
||
case CALCULATOR_RIGHT_W_SHIFT | BUTTON_REPEAT:
|
||
move_with_wrap_and_shift(
|
||
&btn_col, 1, BUTTON_COLS,
|
||
&btn_row, 1, BUTTON_ROWS);
|
||
break;
|
||
#endif
|
||
#ifdef CALCULATOR_RC_QUIT
|
||
case CALCULATOR_RC_QUIT:
|
||
#endif
|
||
case CALCULATOR_QUIT:
|
||
return -1;
|
||
}
|
||
|
||
return 0;
|
||
}
|
||
|
||
/* -----------------------------------------------------------------------
|
||
Main();
|
||
----------------------------------------------------------------------- */
|
||
enum plugin_status plugin_start(const void* parameter)
|
||
{
|
||
(void)parameter;
|
||
|
||
/* now go ahead and have fun! */
|
||
|
||
#ifdef HAVE_TOUCHSCREEN
|
||
rb->touchscreen_set_mode(TOUCHSCREEN_POINT);
|
||
#endif
|
||
|
||
cal_initial();
|
||
|
||
while (calStatus != cal_exit ) {
|
||
btn = rb->button_get_w_tmo(HZ/2);
|
||
#ifdef HAVE_TOUCHSCREEN
|
||
if(btn & BUTTON_TOUCHSCREEN)
|
||
{
|
||
struct ts_raster_result res;
|
||
if(touchscreen_map_raster(&calc_raster, rb->button_get_data() >> 16,
|
||
rb->button_get_data() & 0xffff, &res) == 1)
|
||
{
|
||
btn_row = res.y;
|
||
btn_col = res.x;
|
||
drawButtons(buttonGroup);
|
||
drawLines();
|
||
|
||
rb->lcd_update();
|
||
|
||
prev_btn_row = btn_row;
|
||
prev_btn_col = btn_col;
|
||
if(btn & BUTTON_REL)
|
||
{
|
||
btn = CALCULATOR_INPUT;
|
||
switch(buttonGroup){
|
||
case basicButtons:
|
||
basicButtonsProcess();
|
||
break;
|
||
case sciButtons:
|
||
sciButtonsProcess();
|
||
break;
|
||
}
|
||
btn = BUTTON_TOUCHSCREEN;
|
||
}
|
||
}
|
||
}
|
||
#endif
|
||
if (handleButton(btn) == -1)
|
||
{
|
||
calStatus = cal_exit;
|
||
printResult();
|
||
}
|
||
else
|
||
{
|
||
drawButtons(buttonGroup);
|
||
drawLines();
|
||
}
|
||
|
||
rb->lcd_update();
|
||
|
||
if(rb->default_event_handler(btn) == SYS_USB_CONNECTED)
|
||
return PLUGIN_USB_CONNECTED;
|
||
|
||
if (btn != BUTTON_NONE)
|
||
lastbtn = btn;
|
||
} /* while (calStatus != cal_exit ) */
|
||
|
||
rb->button_clear_queue();
|
||
return PLUGIN_OK;
|
||
}
|