fix wrong score recording.
[kugel-rb.git] / apps / plugins / calculator.c
blob2d276c1747fe3b9b0de2668aeb76b057bf72d5ed
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2004 Pengxuan Liu (Isaac)
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.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
23 00 01 21 22 23 43 44 45 65 66 67 87 88 89 109110111
24 00 |-----------|-----------|-----------|-----------|-----------|
25 01 | | | | | |
26 |***********|***********|***********|***********|***********|
27 |***********|***********|***********|***********|***********|
28 11 | | | | | |
29 12 |-----------|-----------|-----------|-----------|-----------|
30 13 |-----------|-----------|-----------|-----------|-----------| y1
31 14 | | | | | |
32 | | | | | |
33 22 | | | | | |
34 23 |-----------|-----------|-----------|-----------|-----------| y2
35 24 | | | | | |
36 | | | | | |
37 32 | | | | | |
38 33 |-----------|-----------|-----------|-----------|-----------| y3
39 34 | | | | | |
40 | | | | | |
41 42 | | | | | |
42 43 |-----------|-----------|-----------|-----------|-----------| y4
43 44 | | | | | |
44 | | | | | |
45 52 | | | | | |
46 53 |-----------|-----------|-----------|-----------|-----------| y5
47 54 | | | | | |
48 | | | | | |
49 62 | | | | | |
50 63 |-----------|-----------|-----------|-----------|-----------| y6
51 x0 x1 x2 x3 x4 x5
54 /*---------------------------------------------------------------------------
55 Features:
56 - Scientific number format core code. Support range 10^-999 ~ 10^999
57 - Number of significant figures up to 10
59 Limitations:
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
64 - "*,/" have no priority. Actually you can't input 3+5*2 yet.
66 User Instructions:
67 use arrow button to move cursor, "play" button to select, "off" button to exit
68 F1: if typing numbers, it's equal to "Del"; otherwise, equal to "C"
69 F2: circle input "+, -, *, /"
70 F3: equal to "="
72 "MR" : load temp memory
73 "M+" : add currently display to temp memory
74 "C" : reset calculator
75 ---------------------------------------------------------------------------*/
77 #include "plugin.h"
78 #ifdef HAVE_LCD_BITMAP
79 #include "math.h"
81 PLUGIN_HEADER
83 #define BUTTON_ROWS 5
84 #define BUTTON_COLS 5
86 #define REC_HEIGHT (int)(LCD_HEIGHT / (BUTTON_ROWS + 1))
87 #define REC_WIDTH (int)(LCD_WIDTH / BUTTON_COLS)
89 #define Y_6_POS (LCD_HEIGHT) /* Leave room for the border */
90 #define Y_5_POS (Y_6_POS - REC_HEIGHT) /* y5 = 53 */
91 #define Y_4_POS (Y_5_POS - REC_HEIGHT) /* y4 = 43 */
92 #define Y_3_POS (Y_4_POS - REC_HEIGHT) /* y3 = 33 */
93 #define Y_2_POS (Y_3_POS - REC_HEIGHT) /* y2 = 23 */
94 #define Y_1_POS (Y_2_POS - REC_HEIGHT) /* y1 = 13 */
95 #define Y_0_POS 0 /* y0 = 0 */
97 #define X_0_POS 0 /* x0 = 0 */
98 #define X_1_POS (X_0_POS + REC_WIDTH) /* x1 = 22 */
99 #define X_2_POS (X_1_POS + REC_WIDTH) /* x2 = 44 */
100 #define X_3_POS (X_2_POS + REC_WIDTH) /* x3 = 66 */
101 #define X_4_POS (X_3_POS + REC_WIDTH) /* x4 = 88 */
102 #define X_5_POS (X_4_POS + REC_WIDTH) /* x5 = 110, column 111 left blank */
104 #define TEXT_1_POS (Y_1_POS-10) /* y1 = 2 */ /* blank height = 12 */
105 #define TEXT_2_POS (Y_2_POS-8) /* y2 = 15 */ /* blank height = 9 */
106 #define TEXT_3_POS (Y_3_POS-8) /* y3 = 25 */
107 #define TEXT_4_POS (Y_4_POS-8) /* y4 = 35 */
108 #define TEXT_5_POS (Y_5_POS-8) /* y5 = 45 */
109 #define TEXT_6_POS (Y_6_POS-8) /* y6 = 55 */
111 #define SIGN(x) ((x)<0?-1:1)
112 #define ABS(x) ((x)<0?-(x):(x))
114 /* variable button definitions */
115 #if CONFIG_KEYPAD == RECORDER_PAD
116 #define CALCULATOR_LEFT BUTTON_LEFT
117 #define CALCULATOR_RIGHT BUTTON_RIGHT
118 #define CALCULATOR_UP BUTTON_UP
119 #define CALCULATOR_DOWN BUTTON_DOWN
120 #define CALCULATOR_QUIT BUTTON_OFF
121 #define CALCULATOR_INPUT BUTTON_PLAY
122 #define CALCULATOR_CALC BUTTON_F3
123 #define CALCULATOR_OPERATORS BUTTON_F2
124 #define CALCULATOR_CLEAR BUTTON_F1
126 #elif CONFIG_KEYPAD == ARCHOS_AV300_PAD
127 #define CALCULATOR_LEFT BUTTON_LEFT
128 #define CALCULATOR_RIGHT BUTTON_RIGHT
129 #define CALCULATOR_UP BUTTON_UP
130 #define CALCULATOR_DOWN BUTTON_DOWN
131 #define CALCULATOR_QUIT BUTTON_OFF
132 #define CALCULATOR_INPUT BUTTON_SELECT
133 #define CALCULATOR_CALC BUTTON_F3
134 #define CALCULATOR_OPERATORS BUTTON_F2
135 #define CALCULATOR_CLEAR BUTTON_F1
137 #elif CONFIG_KEYPAD == ONDIO_PAD
138 #define CALCULATOR_LEFT BUTTON_LEFT
139 #define CALCULATOR_RIGHT BUTTON_RIGHT
140 #define CALCULATOR_UP BUTTON_UP
141 #define CALCULATOR_DOWN BUTTON_DOWN
142 #define CALCULATOR_QUIT BUTTON_OFF
143 #define CALCULATOR_INPUT_CALC_PRE BUTTON_MENU
144 #define CALCULATOR_INPUT (BUTTON_MENU | BUTTON_REL)
145 #define CALCULATOR_CALC (BUTTON_MENU | BUTTON_REPEAT)
147 #elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || \
148 (CONFIG_KEYPAD == IRIVER_H300_PAD)
149 #define CALCULATOR_LEFT BUTTON_LEFT
150 #define CALCULATOR_RIGHT BUTTON_RIGHT
151 #define CALCULATOR_UP BUTTON_UP
152 #define CALCULATOR_DOWN BUTTON_DOWN
153 #define CALCULATOR_QUIT BUTTON_OFF
154 #define CALCULATOR_INPUT BUTTON_SELECT
155 #define CALCULATOR_CALC BUTTON_ON
156 #define CALCULATOR_OPERATORS BUTTON_MODE
157 #define CALCULATOR_CLEAR BUTTON_REC
159 #define CALCULATOR_RC_QUIT BUTTON_RC_STOP
161 #elif (CONFIG_KEYPAD == IPOD_4G_PAD) || \
162 (CONFIG_KEYPAD == IPOD_3G_PAD) || \
163 (CONFIG_KEYPAD == IPOD_1G2G_PAD)
165 #define CALCULATOR_LEFT BUTTON_LEFT
166 #define CALCULATOR_RIGHT BUTTON_RIGHT
167 #define CALCULATOR_UP_W_SHIFT BUTTON_SCROLL_BACK
168 #define CALCULATOR_DOWN_W_SHIFT BUTTON_SCROLL_FWD
169 #define CALCULATOR_QUIT BUTTON_MENU
170 #define CALCULATOR_INPUT BUTTON_SELECT
171 #define CALCULATOR_CALC BUTTON_PLAY
173 #elif (CONFIG_KEYPAD == IAUDIO_X5M5_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 BUTTON_SELECT
181 #define CALCULATOR_CALC BUTTON_PLAY
182 #define CALCULATOR_CLEAR BUTTON_REC
184 #elif (CONFIG_KEYPAD == GIGABEAT_PAD)
186 #define CALCULATOR_LEFT BUTTON_LEFT
187 #define CALCULATOR_RIGHT BUTTON_RIGHT
188 #define CALCULATOR_UP BUTTON_UP
189 #define CALCULATOR_DOWN BUTTON_DOWN
190 #define CALCULATOR_QUIT BUTTON_POWER
191 #define CALCULATOR_INPUT BUTTON_SELECT
192 #define CALCULATOR_CALC BUTTON_MENU
193 #define CALCULATOR_CLEAR BUTTON_A
195 #elif (CONFIG_KEYPAD == SANSA_E200_PAD)
196 #define CALCULATOR_LEFT BUTTON_LEFT
197 #define CALCULATOR_RIGHT BUTTON_RIGHT
198 #define CALCULATOR_UP BUTTON_UP
199 #define CALCULATOR_DOWN BUTTON_DOWN
200 #define CALCULATOR_UP_W_SHIFT BUTTON_SCROLL_BACK
201 #define CALCULATOR_DOWN_W_SHIFT BUTTON_SCROLL_FWD
202 #define CALCULATOR_QUIT BUTTON_POWER
203 #define CALCULATOR_INPUT_CALC_PRE BUTTON_SELECT
204 #define CALCULATOR_INPUT (BUTTON_SELECT|BUTTON_REL)
205 #define CALCULATOR_CALC (BUTTON_SELECT|BUTTON_REPEAT)
206 #define CALCULATOR_CLEAR BUTTON_REC
208 #elif (CONFIG_KEYPAD == SANSA_C200_PAD)
209 #define CALCULATOR_LEFT BUTTON_LEFT
210 #define CALCULATOR_RIGHT BUTTON_RIGHT
211 #define CALCULATOR_UP BUTTON_UP
212 #define CALCULATOR_DOWN BUTTON_DOWN
213 #define CALCULATOR_QUIT BUTTON_POWER
214 #define CALCULATOR_INPUT_CALC_PRE BUTTON_SELECT
215 #define CALCULATOR_INPUT (BUTTON_SELECT|BUTTON_REL)
216 #define CALCULATOR_CALC (BUTTON_SELECT|BUTTON_REPEAT)
218 #elif (CONFIG_KEYPAD == SANSA_FUZE_PAD)
219 #define CALCULATOR_LEFT BUTTON_LEFT
220 #define CALCULATOR_RIGHT BUTTON_RIGHT
221 #define CALCULATOR_UP BUTTON_UP
222 #define CALCULATOR_DOWN BUTTON_DOWN
223 #define CALCULATOR_UP_W_SHIFT BUTTON_SCROLL_BACK
224 #define CALCULATOR_DOWN_W_SHIFT BUTTON_SCROLL_FWD
225 #define CALCULATOR_QUIT (BUTTON_HOME|BUTTON_REPEAT)
226 #define CALCULATOR_INPUT_CALC_PRE BUTTON_SELECT
227 #define CALCULATOR_INPUT (BUTTON_SELECT|BUTTON_REL)
228 #define CALCULATOR_CALC (BUTTON_SELECT|BUTTON_REPEAT)
231 #elif (CONFIG_KEYPAD == SANSA_CLIP_PAD)
232 #define CALCULATOR_LEFT BUTTON_LEFT
233 #define CALCULATOR_RIGHT BUTTON_RIGHT
234 #define CALCULATOR_UP BUTTON_UP
235 #define CALCULATOR_DOWN BUTTON_DOWN
236 #define CALCULATOR_QUIT BUTTON_POWER
237 #define CALCULATOR_INPUT_CALC_PRE BUTTON_SELECT
238 #define CALCULATOR_INPUT (BUTTON_SELECT|BUTTON_REL)
239 #define CALCULATOR_CALC (BUTTON_SELECT|BUTTON_REPEAT)
240 #define CALCULATOR_CLEAR BUTTON_HOME
242 #elif (CONFIG_KEYPAD == SANSA_M200_PAD)
243 #define CALCULATOR_LEFT BUTTON_LEFT
244 #define CALCULATOR_RIGHT BUTTON_RIGHT
245 #define CALCULATOR_UP BUTTON_UP
246 #define CALCULATOR_DOWN BUTTON_DOWN
247 #define CALCULATOR_QUIT BUTTON_POWER
248 #define CALCULATOR_INPUT_CALC_PRE BUTTON_SELECT
249 #define CALCULATOR_INPUT (BUTTON_SELECT|BUTTON_REL)
250 #define CALCULATOR_CALC (BUTTON_SELECT|BUTTON_REPEAT)
251 #define CALCULATOR_CLEAR (BUTTON_SELECT|BUTTON_UP)
253 #elif (CONFIG_KEYPAD == IRIVER_H10_PAD)
255 #define CALCULATOR_LEFT BUTTON_LEFT
256 #define CALCULATOR_RIGHT BUTTON_RIGHT
257 #define CALCULATOR_UP BUTTON_SCROLL_UP
258 #define CALCULATOR_DOWN BUTTON_SCROLL_DOWN
259 #define CALCULATOR_QUIT BUTTON_POWER
260 #define CALCULATOR_INPUT_CALC_PRE BUTTON_PLAY
261 #define CALCULATOR_INPUT (BUTTON_PLAY | BUTTON_REL)
262 #define CALCULATOR_CALC (BUTTON_PLAY | BUTTON_REPEAT)
263 #define CALCULATOR_CLEAR BUTTON_REW
265 #elif (CONFIG_KEYPAD == GIGABEAT_S_PAD)
267 #define CALCULATOR_LEFT BUTTON_LEFT
268 #define CALCULATOR_RIGHT BUTTON_RIGHT
269 #define CALCULATOR_UP BUTTON_UP
270 #define CALCULATOR_DOWN BUTTON_DOWN
271 #define CALCULATOR_QUIT BUTTON_BACK
272 #define CALCULATOR_INPUT BUTTON_SELECT
273 #define CALCULATOR_CALC BUTTON_MENU
274 #define CALCULATOR_CLEAR BUTTON_PLAY
276 #elif (CONFIG_KEYPAD == MROBE100_PAD)
278 #define CALCULATOR_LEFT BUTTON_LEFT
279 #define CALCULATOR_RIGHT BUTTON_RIGHT
280 #define CALCULATOR_UP BUTTON_UP
281 #define CALCULATOR_DOWN BUTTON_DOWN
282 #define CALCULATOR_QUIT BUTTON_POWER
283 #define CALCULATOR_INPUT BUTTON_SELECT
284 #define CALCULATOR_CALC BUTTON_MENU
285 #define CALCULATOR_CLEAR BUTTON_DISPLAY
287 #elif CONFIG_KEYPAD == IAUDIO_M3_PAD
289 #define CALCULATOR_LEFT BUTTON_RC_REW
290 #define CALCULATOR_RIGHT BUTTON_RC_FF
291 #define CALCULATOR_UP BUTTON_RC_VOL_UP
292 #define CALCULATOR_DOWN BUTTON_RC_VOL_DOWN
293 #define CALCULATOR_QUIT BUTTON_RC_REC
294 #define CALCULATOR_INPUT BUTTON_RC_PLAY
295 #define CALCULATOR_CALC BUTTON_RC_MODE
296 #define CALCULATOR_CLEAR BUTTON_RC_MENU
298 #define CALCULATOR_RC_QUIT BUTTON_REC
300 #elif (CONFIG_KEYPAD == COWOND2_PAD)
302 #define CALCULATOR_QUIT BUTTON_POWER
303 #define CALCULATOR_CLEAR BUTTON_MENU
305 #elif CONFIG_KEYPAD == IAUDIO67_PAD
307 #define CALCULATOR_LEFT BUTTON_LEFT
308 #define CALCULATOR_RIGHT BUTTON_RIGHT
309 #define CALCULATOR_UP BUTTON_VOLUP
310 #define CALCULATOR_DOWN BUTTON_VOLDOWN
311 #define CALCULATOR_QUIT BUTTON_POWER
312 #define CALCULATOR_INPUT BUTTON_PLAY
313 #define CALCULATOR_CALC BUTTON_MENU
314 #define CALCULATOR_CLEAR BUTTON_STOP
316 #define CALCULATOR_RC_QUIT (BUTTON_MENU|BUTTON_PLAY)
318 #elif (CONFIG_KEYPAD == CREATIVEZVM_PAD)
320 #define CALCULATOR_LEFT BUTTON_LEFT
321 #define CALCULATOR_RIGHT BUTTON_RIGHT
322 #define CALCULATOR_UP BUTTON_UP
323 #define CALCULATOR_DOWN BUTTON_DOWN
324 #define CALCULATOR_QUIT BUTTON_BACK
325 #define CALCULATOR_INPUT BUTTON_SELECT
326 #define CALCULATOR_CALC BUTTON_MENU
327 #define CALCULATOR_CLEAR BUTTON_PLAY
329 #elif CONFIG_KEYPAD == PHILIPS_HDD1630_PAD
331 #define CALCULATOR_LEFT BUTTON_LEFT
332 #define CALCULATOR_RIGHT BUTTON_RIGHT
333 #define CALCULATOR_UP BUTTON_UP
334 #define CALCULATOR_DOWN BUTTON_DOWN
335 #define CALCULATOR_QUIT BUTTON_POWER
336 #define CALCULATOR_INPUT BUTTON_SELECT
337 #define CALCULATOR_CALC BUTTON_MENU
338 #define CALCULATOR_CLEAR BUTTON_VIEW
340 #elif (CONFIG_KEYPAD == ONDAVX747_PAD)
342 #define CALCULATOR_QUIT BUTTON_POWER
343 #define CALCULATOR_CLEAR BUTTON_MENU
345 #elif CONFIG_KEYPAD == MROBE500_PAD
346 #define CALCULATOR_QUIT BUTTON_POWER
348 #else
349 #error No keymap defined!
350 #endif
352 #ifdef HAVE_TOUCHSCREEN
353 #ifndef CALCULATOR_LEFT
354 #define CALCULATOR_LEFT BUTTON_MIDLEFT
355 #endif
356 #ifndef CALCULATOR_RIGHT
357 #define CALCULATOR_RIGHT BUTTON_MIDRIGHT
358 #endif
359 #ifndef CALCULATOR_UP
360 #define CALCULATOR_UP BUTTON_TOPMIDDLE
361 #endif
362 #ifndef CALCULATOR_DOWN
363 #define CALCULATOR_DOWN BUTTON_BOTTOMMIDDLE
364 #endif
365 #ifndef CALCULATOR_CALC
366 #define CALCULATOR_CALC BUTTON_BOTTOMRIGHT
367 #endif
368 #ifndef CALCULATOR_INPUT
369 #define CALCULATOR_INPUT BUTTON_CENTER
370 #endif
371 #ifndef CALCULATOR_CLEAR
372 #define CALCULATOR_CLEAR BUTTON_TOPRIGHT
373 #endif
375 #include "lib/touchscreen.h"
376 static struct ts_raster calc_raster = { X_0_POS, Y_1_POS, BUTTON_COLS*REC_WIDTH, BUTTON_ROWS*REC_HEIGHT, REC_WIDTH, REC_HEIGHT };
377 #endif
379 enum {
380 basicButtons,
381 sciButtons
382 } buttonGroup;
384 unsigned char* buttonChar[2][5][5] = {
385 { { "MR" , "M+" , "2nd" , "CE" , "C" },
386 { "7" , "8" , "9" , "/" , "sqr" },
387 { "4" , "5" , "6" , "*" , "x^2" },
388 { "1" , "2" , "3" , "-" , "1/x" },
389 { "0" , "+/-", "." , "+" , "=" } },
391 { { "n!" , "PI" , "1st" , "sin" , "asi" },
392 { "7" , "8" , "9" , "cos" , "aco" },
393 { "4" , "5" , "6" , "tan" , "ata" },
394 { "1" , "2" , "3" , "ln" , "e^x" },
395 { "0" , "+/-", "." , "log" , "x^y" } }
398 enum { btn_MR , btn_M , btn_bas , btn_CE , btn_C ,
399 btn_7 , btn_8 , btn_9 , btn_div , btn_sqr ,
400 btn_4 , btn_5 , btn_6 , btn_time , btn_square ,
401 btn_1 , btn_2 , btn_3 , btn_minus , btn_rec ,
402 btn_0 , btn_sign , btn_dot , btn_add , btn_equal
405 enum { sci_fac, sci_pi , sci_sci , sci_sin , sci_asin ,
406 sci_7 , sci_8 , sci_9 , sci_cos , sci_acos ,
407 sci_4 , sci_5 , sci_6 , sci_tan , sci_atan ,
408 sci_1 , sci_2 , sci_3 , sci_ln , sci_exp ,
409 sci_0 , sci_sign , sci_dot , sci_log , sci_xy
412 #define MINIMUM 0.000000000001 /* e-12 */
413 /* ^ ^ ^ ^ */
414 /* 123456789abcdef */
416 #define DIGITLEN 10 /* must <= 10 */
417 #define SCIENTIFIC_FORMAT ( power < -(DIGITLEN-3) || power > (DIGITLEN))
418 /* 0.000 00000 0001 */
419 /* ^ ^ ^ ^ ^ ^ */
420 /* DIGITLEN 12345 6789a bcdef */
421 /* power 12 34567 89abc def */
422 /* 10^- 123 45678 9abcd ef */
424 unsigned char buf[19];/* 18 bytes of output line,
425 buf[0] is operator
426 buf[1] = 'M' if memTemp is not 0
427 buf[2] = ' '
429 if SCIENTIFIC_FORMAT
430 buf[2]-buf[12] or buf[3]-buf[13] = result;
431 format X.XXXXXXXX
432 buf[13] or buf[14] -buf[17] = power;
433 format eXXX or e-XXX
434 else
435 buf[3]-buf[6] = ' ';
436 buf[7]-buf[17] = result;
438 buf[18] = '\0' */
440 unsigned char typingbuf[DIGITLEN+2];/* byte 0 is sign or ' ',
441 byte 1~DIGITLEN are num and '.'
442 byte (DIGITLEN+1) is '\0' */
443 unsigned char* typingbufPointer = typingbuf;
445 double result = 0; /* main operand, format 0.xxxxx */
446 int power = 0; /* 10^power */
447 double modifier = 0.1; /* position of next input */
448 double operand = 0; /* second operand, format 0.xxxxx */
449 int operandPower = 0; /* 10^power of second operand */
450 char oper = ' '; /* operators: + - * / */
451 bool operInputted = false; /* false: do calculation first and
452 replace current oper
453 true: just replace current oper */
455 double memTemp = 0; /* temp memory */
456 int memTempPower = 0; /* 10^^power of memTemp */
458 int btn_row, btn_col; /* current position index for button */
459 int prev_btn_row, prev_btn_col; /* previous cursor position */
460 #define CAL_BUTTON (btn_row*5+btn_col)
462 int btn = BUTTON_NONE;
463 int lastbtn = BUTTON_NONE;
465 /* Status of calculator */
466 enum {cal_normal, /* 0, normal status, display result */
467 cal_typing, /* 1, currently typing, dot hasn't been typed */
468 cal_dotted, /* 2, currently typing, dot already has been typed. */
469 cal_error,
470 cal_exit,
471 cal_toDo
472 } calStatus;
474 /* constant table for CORDIC algorithm */
475 double cordicTable[51][2]= {
476 /* pow(2,0) - pow(2,-50) atan(pow(2,0) - atan(pow(2,-50) */
477 {1e+00, 7.853981633974483e-01},
478 {5e-01, 4.636476090008061e-01},
479 {2.5e-01, 2.449786631268641e-01},
480 {1.25e-01, 1.243549945467614e-01},
481 {6.25e-02, 6.241880999595735e-02},
482 {3.125e-02, 3.123983343026828e-02},
483 {1.5625e-02, 1.562372862047683e-02},
484 {7.8125e-03, 7.812341060101111e-03},
485 {3.90625e-03, 3.906230131966972e-03},
486 {1.953125e-03, 1.953122516478819e-03},
487 {9.765625e-04, 9.765621895593195e-04},
488 {4.8828125e-04, 4.882812111948983e-04},
489 {2.44140625e-04, 2.441406201493618e-04},
490 {1.220703125e-04, 1.220703118936702e-04},
491 {6.103515625e-05, 6.103515617420877e-05},
492 {3.0517578125e-05, 3.051757811552610e-05},
493 {1.52587890625e-05, 1.525878906131576e-05},
494 {7.62939453125e-06, 7.629394531101970e-06},
495 {3.814697265625e-06, 3.814697265606496e-06},
496 {1.9073486328125e-06, 1.907348632810187e-06},
497 {9.5367431640625e-07, 9.536743164059608e-07},
498 {4.76837158203125e-07, 4.768371582030888e-07},
499 {2.384185791015625e-07, 2.384185791015580e-07},
500 {1.1920928955078125e-07, 1.192092895507807e-07},
501 {5.9604644775390625e-08, 5.960464477539055e-08},
502 {2.98023223876953125e-08, 2.980232238769530e-08},
503 {1.490116119384765625e-08, 1.490116119384765e-08},
504 {7.450580596923828125e-09, 7.450580596923828e-09},
505 {3.7252902984619140625e-09, 3.725290298461914e-09},
506 {1.86264514923095703125e-09, 1.862645149230957e-09},
507 {9.31322574615478515625e-10, 9.313225746154785e-10},
508 {4.656612873077392578125e-10, 4.656612873077393e-10},
509 {2.3283064365386962890625e-10, 2.328306436538696e-10},
510 {1.16415321826934814453125e-10, 1.164153218269348e-10},
511 {5.82076609134674072265625e-11, 5.820766091346741e-11},
512 {2.910383045673370361328125e-11, 2.910383045673370e-11},
513 {1.4551915228366851806640625e-11, 1.455191522836685e-11},
514 {7.2759576141834259033203125e-12, 7.275957614183426e-12},
515 {3.63797880709171295166015625e-12, 3.637978807091713e-12},
516 {1.818989403545856475830078125e-12, 1.818989403545856e-12},
517 {9.094947017729282379150390625e-13, 9.094947017729282e-13},
518 {4.5474735088646411895751953125e-13, 4.547473508864641e-13},
519 {2.27373675443232059478759765625e-13, 2.273736754432321e-13},
520 {1.136868377216160297393798828125e-13, 1.136868377216160e-13},
521 {5.684341886080801486968994140625e-14, 5.684341886080801e-14},
522 {2.8421709430404007434844970703125e-14, 2.842170943040401e-14},
523 {1.42108547152020037174224853515625e-14, 1.421085471520200e-14},
524 {7.10542735760100185871124267578125e-15, 7.105427357601002e-15},
525 {3.552713678800500929355621337890625e-15, 3.552713678800501e-15},
526 {1.7763568394002504646778106689453125e-15, 1.776356839400250e-15},
527 {8.8817841970012523233890533447265625e-16, 8.881784197001252e-16}
530 void doMultiple(double* operandOne, int* powerOne,
531 double operandTwo, int powerTwo);
532 void doAdd (double* operandOne, int* powerOne,
533 double operandTwo, int powerTwo);
534 void printResult(void);
535 void formatResult(void);
536 void oneOperand(void);
538 void drawLines(void);
539 void drawButtons(int group);
541 /* -----------------------------------------------------------------------
542 Handy funtions
543 ----------------------------------------------------------------------- */
544 void cleartypingbuf(void)
546 int k;
547 for( k=1; k<=(DIGITLEN+1); k++)
548 typingbuf[k] = 0;
549 typingbuf[0] = ' ';
550 typingbufPointer = typingbuf+1;
552 void clearbuf(void)
554 int k;
555 for(k=0;k<18;k++)
556 buf[k]=' ';
557 buf[18] = 0;
559 void clearResult(void)
561 result = 0;
562 power = 0;
563 modifier = 0.1;
566 void clearInput(void)
568 calStatus = cal_normal;
569 clearResult();
570 cleartypingbuf();
571 rb->lcd_clear_display();
572 drawButtons(buttonGroup);
573 drawLines();
576 void clearOperand(void)
578 operand = 0;
579 operandPower = 0;
582 void clearMemTemp(void)
584 memTemp = 0;
585 memTempPower = 0;
588 void clearOper(void)
590 oper = ' ';
591 operInputted = false;
594 void clearMem(void)
596 clearInput();
597 clearMemTemp();
598 clearOperand();
599 clearOper();
600 btn = BUTTON_NONE;
603 void switchOperands(void)
605 double tempr = operand;
606 int tempp = operandPower;
607 operand = result;
608 operandPower = power;
609 result = tempr;
610 power = tempp;
613 void drawLines(void)
615 int i;
616 rb->lcd_hline(0, LCD_WIDTH, Y_1_POS-1);
617 for (i = 0; i < 5 ; i++)
618 rb->lcd_hline(0, LCD_WIDTH, Y_1_POS+i*REC_HEIGHT);
619 for (i = 0; i < 4 ; i++)
620 rb->lcd_vline(X_1_POS+i*REC_WIDTH, Y_1_POS, LCD_HEIGHT);
623 void drawButtons(int group)
625 int i, j, w, h;
626 for (i = 0; i <= 4; i++){
627 for (j = 0; j <= 4; j++){
628 rb->lcd_getstringsize( buttonChar[group][i][j],&w,&h);
629 if (i == btn_row && j == btn_col) /* selected item */
630 rb->lcd_set_drawmode(DRMODE_SOLID);
631 else
632 rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
633 rb->lcd_fillrect( X_0_POS + j*REC_WIDTH,
634 Y_1_POS + i*REC_HEIGHT,
635 REC_WIDTH, REC_HEIGHT+1);
636 if (i == btn_row && j == btn_col) /* selected item */
637 rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
638 else
639 rb->lcd_set_drawmode(DRMODE_SOLID);
640 rb->lcd_putsxy( X_0_POS + j*REC_WIDTH + (REC_WIDTH - w)/2,
641 Y_1_POS + i*REC_HEIGHT + (REC_HEIGHT - h)/2 + 1,
642 buttonChar[group][i][j] );
645 rb->lcd_set_drawmode(DRMODE_SOLID);
648 /* -----------------------------------------------------------------------
649 Initiate calculator
650 ----------------------------------------------------------------------- */
651 void cal_initial (void)
653 int w,h;
655 rb->lcd_getstringsize("A",&w,&h);
656 if (h >= REC_HEIGHT)
657 rb->lcd_setfont(FONT_SYSFIXED);
659 rb->lcd_clear_display();
661 #ifdef CALCULATOR_OPERATORS
662 /* basic operators are available through separate button */
663 buttonGroup = sciButtons;
664 #else
665 buttonGroup = basicButtons;
666 #endif
668 /* initially, invert button "5" */
669 btn_row = 2;
670 btn_col = 1;
671 prev_btn_row = btn_row;
672 prev_btn_col = btn_col;
673 drawButtons(buttonGroup);
674 drawLines();
675 rb->lcd_update();
677 /* initial mem and output display*/
678 clearMem();
679 printResult();
681 /* clear button queue */
682 rb->button_clear_queue();
685 /* -----------------------------------------------------------------------
686 mySqrt uses Heron's algorithm, which is the Newtone-Raphson algorhitm
687 in it's private case for sqrt.
688 Thanks BlueChip for his intro text and Dave Straayer for the actual name.
689 ----------------------------------------------------------------------- */
690 double mySqrt(double square)
692 int k = 0;
693 double temp = 0;
694 double root= ABS(square+1)/2;
696 while( ABS(root - temp) > MINIMUM ){
697 temp = root;
698 root = (square/temp + temp)/2;
699 k++;
700 if (k>10000) return 0;
703 return root;
705 /* -----------------------------------------------------------------------
706 transcendFunc uses CORDIC (COordinate Rotation DIgital Computer) method
707 transcendFunc can do sin,cos,log,exp
708 input parameter is angle
709 ----------------------------------------------------------------------- */
710 void transcendFunc(char* func, double* tt, int* ttPower)
712 double t = (*tt)*M_PI/180; int tPower = *ttPower;
713 int sign = 1;
714 int n = 50; /* n <=50, tables are all <= 50 */
715 int j;
716 double x,y,z,xt,yt,zt;
718 if (tPower < -998) {
719 calStatus = cal_normal;
720 return;
722 if (tPower > 8) {
723 calStatus = cal_error;
724 return;
726 *ttPower = 0;
727 calStatus = cal_normal;
729 if( func[0] =='s' || func[0] =='S'|| func[0] =='t' || func[0] =='T')
730 sign = SIGN(t);
731 else {
732 /* if( func[0] =='c' || func[0] =='C') */
733 sign = 1;
735 t = ABS(t);
737 while (tPower > 0){
738 t *= 10;
739 tPower--;
741 while (tPower < 0) {
742 t /= 10;
743 tPower++;
745 j = 0;
746 while (t > j*M_TWOPI) {j++;}
747 t -= (j-1)*M_TWOPI;
748 if (M_PI_2 < t && t < 3*M_PI_2){
749 t = M_PI - t;
750 if (func[0] =='c' || func[0] =='C')
751 sign = -1;
752 else if (func[0] =='t' || func[0] =='T')
753 t*=-1;
755 else if ( 3*M_PI_2 <= t && t <= M_TWOPI)
756 t -= M_TWOPI;
758 x = 0.60725293500888; y = 0; z = t;
759 for (j=1;j<n+2;j++){
760 xt = x - SIGN(z) * y*cordicTable[j-1][0];
761 yt = y + SIGN(z) * x*cordicTable[j-1][0];
762 zt = z - SIGN(z) * cordicTable[j-1][1];
763 x = xt;
764 y=yt;
765 z=zt;
767 if( func[0] =='s' || func[0] =='S') {
768 *tt = sign*y;
769 return;
771 else if( func[0] =='c' || func[0] =='C') {
772 *tt = sign*x;
773 return;
775 else /*if( func[0] =='t' || func[0] =='T')*/ {
776 if(t==M_PI_2||t==-M_PI_2){
777 calStatus = cal_error;
778 return;
780 else{
781 *tt = sign*(y/x);
782 return;
787 /* -----------------------------------------------------------------------
788 add in scientific number format
789 ----------------------------------------------------------------------- */
790 void doAdd (double* operandOne, int* powerOne,
791 double operandTwo, int powerTwo)
793 if ( *powerOne >= powerTwo ){
794 if (*powerOne - powerTwo <= DIGITLEN+1){
795 while (powerTwo < *powerOne){
796 operandTwo /=10;
797 powerTwo++;
799 *operandOne += operandTwo;
801 /*do nothing if operandTwo is too small*/
803 else{
804 if (powerTwo - *powerOne <= DIGITLEN+1){
805 while(powerTwo > *powerOne){
806 *operandOne /=10;
807 (*powerOne)++;
809 (*operandOne) += operandTwo;
811 else{/* simply copy operandTwo if operandOne is too small */
812 *operandOne = operandTwo;
813 *powerOne = powerTwo;
817 /* -----------------------------------------------------------------------
818 multiple in scientific number format
819 ----------------------------------------------------------------------- */
820 void doMultiple(double* operandOne, int* powerOne,
821 double operandTwo, int powerTwo)
823 (*operandOne) *= operandTwo;
824 (*powerOne) += powerTwo;
827 /* -----------------------------------------------------------------------
828 Handles all one operand calculations
829 ----------------------------------------------------------------------- */
830 void oneOperand(void)
832 int k = 0;
833 if (buttonGroup == basicButtons){
834 switch(CAL_BUTTON){
835 case btn_sqr:
836 if (result<0)
837 calStatus = cal_error;
838 else{
839 if (power%2 == 1){
840 result = (mySqrt(result*10))/10;
841 power = (power+1) / 2;
843 else{
844 result = mySqrt(result);
845 power = power / 2;
847 calStatus = cal_normal;
849 break;
850 case btn_square:
851 power *= 2;
852 result *= result;
853 calStatus = cal_normal;
854 break;
856 case btn_rec:
857 if (result==0)
858 calStatus = cal_error;
859 else{
860 power = -power;
861 result = 1/result;
862 calStatus = cal_normal;
864 break;
865 default:
866 calStatus = cal_toDo;
867 break; /* just for the safety */
870 else{ /* sciButtons */
871 switch(CAL_BUTTON){
872 case sci_sin:
873 transcendFunc("sin", &result, &power);
874 break;
875 case sci_cos:
876 transcendFunc("cos", &result, &power);
877 break;
878 case sci_tan:
879 transcendFunc("tan", &result, &power);
880 break;
881 case sci_fac:
882 if (power<0 || power>8 || result<0 )
883 calStatus = cal_error;
884 else if(result == 0) {
885 result = 1;
886 power = 0;
888 else{
889 while(power > 0) {
890 result *= 10;
891 power--;
893 if ( ( result - (int)result) > MINIMUM )
894 calStatus = cal_error;
895 else {
896 k = result; result = 1;
897 while (k > 1){
898 doMultiple(&result, &power, k, 0);
899 formatResult();
900 k--;
902 calStatus = cal_normal;
905 break;
906 default:
907 calStatus = cal_toDo;
908 break; /* just for the safety */
914 /* -----------------------------------------------------------------------
915 Handles all two operands calculations
916 ----------------------------------------------------------------------- */
917 void twoOperands(void)
919 switch(oper){
920 case '-':
921 doAdd(&operand, &operandPower, -result, power);
922 break;
923 case '+':
924 doAdd(&operand, &operandPower, result, power);
925 break;
926 case '*':
927 doMultiple(&operand, &operandPower, result, power);
928 break;
929 case '/':
930 if ( ABS(result) > MINIMUM ){
931 doMultiple(&operand, &operandPower, 1/result, -power);
933 else
934 calStatus = cal_error;
935 break;
936 default: /* ' ' */
937 switchOperands(); /* counter switchOperands() below */
938 break;
939 } /* switch(oper) */
940 switchOperands();
941 clearOper();
944 /* First, increases *dimen1 by dimen1_delta modulo dimen1_modulo.
945 If dimen1 wraps, increases *dimen2 by dimen2_delta modulo dimen2_modulo.
947 static void move_with_wrap_and_shift(
948 int *dimen1, int dimen1_delta, int dimen1_modulo,
949 int *dimen2, int dimen2_delta, int dimen2_modulo)
951 bool wrapped = false;
953 *dimen1 += dimen1_delta;
954 if (*dimen1 < 0)
956 *dimen1 = dimen1_modulo - 1;
957 wrapped = true;
959 else if (*dimen1 >= dimen1_modulo)
961 *dimen1 = 0;
962 wrapped = true;
965 if (wrapped)
967 /* Make the dividend always positive to be sure about the result.
968 Adding dimen2_modulo does not change it since we do it modulo. */
969 *dimen2 = (*dimen2 + dimen2_modulo + dimen2_delta) % dimen2_modulo;
973 /* -----------------------------------------------------------------------
974 Print buttons when switching 1st and 2nd
975 int group = {basicButtons, sciButtons}
976 ----------------------------------------------------------------------- */
977 void printButtonGroups(int group)
979 drawButtons(group);
980 drawLines();
981 rb->lcd_update();
983 /* -----------------------------------------------------------------------
984 flash the currently marked button
985 ----------------------------------------------------------------------- */
986 void flashButton(void)
988 int k, w, h;
989 for (k=2;k>0;k--)
991 rb->lcd_getstringsize( buttonChar[buttonGroup][btn_row][btn_col],&w,&h);
992 rb->lcd_set_drawmode(DRMODE_SOLID|(k==1) ? 0 : DRMODE_INVERSEVID);
993 rb->lcd_fillrect( X_0_POS + btn_col*REC_WIDTH + 1,
994 Y_1_POS + btn_row*REC_HEIGHT + 1,
995 REC_WIDTH - 1, REC_HEIGHT - 1);
996 rb->lcd_putsxy( X_0_POS + btn_col*REC_WIDTH + (REC_WIDTH - w)/2,
997 Y_1_POS + btn_row*REC_HEIGHT + (REC_HEIGHT - h)/2 +1,
998 buttonChar[buttonGroup][btn_row][btn_col] );
999 rb->lcd_update_rect( X_0_POS + btn_col*REC_WIDTH + 1,
1000 Y_1_POS + btn_row*REC_HEIGHT + 1,
1001 REC_WIDTH - 1, REC_HEIGHT - 1);
1003 if (k!= 1)
1004 rb->sleep(HZ/22);
1009 /* -----------------------------------------------------------------------
1010 pos is the position that needs animation. pos = [1~18]
1011 ----------------------------------------------------------------------- */
1012 void deleteAnimation(int pos)
1014 int k;
1015 if (pos<1 || pos >18)
1016 return;
1017 pos--;
1018 rb->lcd_fillrect(1+pos*6, TEXT_1_POS, 6, 8);
1019 rb->lcd_update_rect(1+pos*6, TEXT_1_POS, 6, 8);
1021 for (k=1;k<=4;k++){
1022 rb->sleep(HZ/32);
1023 rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
1024 rb->lcd_fillrect(1+pos*6, TEXT_1_POS, 6, 8);
1025 rb->lcd_set_drawmode(DRMODE_SOLID);
1026 rb->lcd_fillrect(1+pos*6+1+k, TEXT_1_POS+k,
1027 (5-2*k)>0?(5-2*k):1, (7-2*k)>0?(7-2*k):1 );
1028 rb->lcd_update_rect(1+pos*6, TEXT_1_POS, 6, 8);
1033 /* -----------------------------------------------------------------------
1034 result may be one of these formats:
1036 xxxx.xxxx
1037 0.xxxx
1038 0.0000xxxx
1040 formatResult() change result to standard format: 0.xxxx
1041 if result is close to 0, let it be 0;
1042 if result is close to 1, let it be 0.1 and power++;
1043 ----------------------------------------------------------------------- */
1044 void formatResult(void)
1046 int resultsign = SIGN(result);
1047 result = ABS(result);
1048 if(result > MINIMUM ){ /* doesn't check power, might have problem
1049 input wouldn't,
1050 + - * / of two formatted number wouldn't.
1051 only a calculation that makes a formatted
1052 number (0.xxxx) less than MINIMUM in only
1053 one operation */
1055 if (result<1){
1056 while( (int)(result*10) == 0 ){
1057 result *= 10;
1058 power--;
1059 modifier *= 10;
1062 else{ /* result >= 1 */
1063 while( (int)result != 0 ){
1064 result /= 10;
1065 power++;
1066 modifier /= 10;
1068 } /* if result<1 */
1070 if (result > (1-MINIMUM)){
1071 result = 0.1;
1072 power++;
1073 modifier /= 10;
1075 result *= resultsign;
1077 else {
1078 result = 0;
1079 power = 0;
1080 modifier = 0.1;
1084 /* -----------------------------------------------------------------------
1085 result2typingbuf() outputs standard format result to typingbuf.
1086 case SCIENTIFIC_FORMAT, let temppower = 1;
1087 case temppower > 0: print '.' in the middle
1088 case temppower <= 0: print '.' in the begining
1089 ----------------------------------------------------------------------- */
1090 void result2typingbuf(void)
1092 bool haveDot = false;
1093 char tempchar = 0;
1094 int k;
1095 double tempresult = ABS(result); /* positive num makes things simple */
1097 int temppower;
1098 double tempmodifier = 1;
1099 int count;
1101 if(SCIENTIFIC_FORMAT)
1102 temppower = 1; /* output x.xxxx format */
1103 else
1104 temppower = power;
1106 cleartypingbuf();
1108 if(tempresult < MINIMUM){ /* if 0,faster display and avoid complication*/
1109 typingbuf[0] = ' ';
1110 typingbuf[1] = '0';
1112 else{ /* tempresult > 0 */
1113 typingbuf[0] = (SIGN(result)<0)?'-':' ';
1115 typingbufPointer = typingbuf;
1116 if(temppower > 0){
1117 for (k = 0; k<DIGITLEN+1 ; k++){
1118 typingbufPointer++;
1119 if(temppower || *(typingbufPointer-1) == '.'){
1120 count = 0;
1121 tempmodifier = tempmodifier/10;
1122 while( (tempresult-tempmodifier*count) >
1123 (tempmodifier-MINIMUM)){
1124 count++;
1126 tempresult -= tempmodifier*count;
1127 tempresult = ABS(tempresult);
1128 temppower-- ;
1129 *typingbufPointer = count + '0';
1131 else{ /* temppower == 0 */
1132 *typingbufPointer = '.';
1133 haveDot = true;
1135 } /* for */
1137 else{
1138 haveDot = true;
1139 typingbufPointer++; *typingbufPointer = '0';
1140 typingbufPointer++; *typingbufPointer = '.';
1141 for (k = 2; k<DIGITLEN+1 ; k++){
1142 typingbufPointer++;
1143 count = 0;
1144 if ( (-temppower) < (k-1)){
1145 tempmodifier = tempmodifier/10;
1146 while((tempresult-tempmodifier*count)>(tempmodifier-MINIMUM)){
1147 count++;
1150 tempresult -= tempmodifier*count;
1151 tempresult = ABS(tempresult);
1152 temppower-- ;
1154 *typingbufPointer = count + '0';
1157 /* now, typingbufPointer = typingbuf + 16 */
1158 /* backward strip off 0 and '.' */
1159 if (haveDot){
1160 while( (*typingbufPointer == '0') || (*typingbufPointer == '.')){
1161 tempchar = *typingbufPointer;
1162 *typingbufPointer = 0;
1163 typingbufPointer--;
1164 if (tempchar == '.') break;
1167 typingbuf[DIGITLEN+1] = 0;
1168 } /* else tempresult > 0 */
1171 /* -----------------------------------------------------------------------
1172 printResult() generates LCD display.
1173 ----------------------------------------------------------------------- */
1174 void printResult(void)
1176 int k, w, h;
1178 char operbuf[3] = {0, 0, 0};
1180 switch_Status:
1181 switch(calStatus){
1182 case cal_exit:
1183 rb->lcd_clear_display();
1184 rb->splash(HZ/3, "Bye now!");
1185 break;
1186 case cal_error:
1187 clearbuf();
1188 rb->snprintf(buf, 19, "%18s","Error");
1189 break;
1190 case cal_toDo:
1191 clearbuf();
1192 rb->snprintf(buf, 19, "%18s","Coming soon ^_* ");
1193 break;
1195 case cal_normal:
1196 formatResult();
1198 if( power > 1000 ){ /* power -1 > 999 */
1199 calStatus = cal_error;
1200 goto switch_Status;
1202 if (power < -998 ) /* power -1 < -999 */
1203 clearResult(); /* too small, let it be 0 */
1205 result2typingbuf();
1206 clearbuf();
1208 operbuf[0] = oper;
1209 operbuf[1] = ( ABS(memTemp) > MINIMUM )?'M':' ';
1210 operbuf[2] = '\0';
1212 if(SCIENTIFIC_FORMAT){
1213 /* output format: X.XXXX eXXX */
1214 if(power > -98){ /* power-1 >= -99, eXXX or e-XX */
1215 rb->snprintf(buf, 12, "%11s",typingbuf);
1216 for(k=11;k<=14;k++) buf[k] = ' ';
1217 cleartypingbuf();
1218 rb->snprintf(typingbuf, 5, "e%d",power-1);
1219 rb->snprintf(buf+11, 5, "%4s",typingbuf);
1221 else{ /* power-1 <= -100, e-XXX */
1222 rb->snprintf(buf, 12, "%11s",typingbuf);
1223 rb->snprintf(buf+11, 6, "e%d",power-1);
1226 else{
1227 rb->snprintf(buf, 12, "%11s",typingbuf);
1228 } /* if SCIENTIFIC_FORMAT */
1229 break;
1230 case cal_typing:
1231 case cal_dotted:
1232 clearbuf();
1233 operbuf[0] = oper;
1234 operbuf[1] = ( ABS(memTemp) > MINIMUM )?'M':' ';
1235 rb->snprintf(buf, 12, "%11s",typingbuf);
1236 break;
1240 rb->lcd_getstringsize(buf, &w, &h);
1241 rb->screen_clear_area(rb->screens[0], 0, 0, LCD_WIDTH, Y_1_POS - 1);
1242 rb->lcd_putsxy(4, Y_1_POS - h -1, operbuf);
1243 rb->lcd_putsxy(LCD_WIDTH - w - 4, Y_1_POS - h -1, buf);
1244 rb->lcd_update_rect(0, 1, LCD_WIDTH, Y_1_POS);
1247 /* -----------------------------------------------------------------------
1248 Process typing buttons: 1-9, '.', sign
1249 main operand "result" and typingbuf are processed seperately here.
1250 ----------------------------------------------------------------------- */
1251 void typingProcess(void){
1252 switch( CAL_BUTTON ){
1253 case btn_sign:
1254 if (calStatus == cal_typing ||
1255 calStatus == cal_dotted)
1256 typingbuf[0] = (typingbuf[0]=='-')?' ':'-';
1257 result = -result;
1258 break;
1259 case btn_dot:
1260 operInputted = false;
1261 switch(calStatus){
1262 case cal_normal:
1263 clearInput();
1264 *typingbufPointer = '0';
1265 typingbufPointer++;
1266 case cal_typing:
1267 calStatus = cal_dotted;
1268 *typingbufPointer = '.';
1269 if (typingbufPointer != typingbuf+DIGITLEN+1)
1270 typingbufPointer++;
1271 break;
1272 default: /* cal_dotted */
1273 break;
1275 break;
1276 default: /* 0-9 */
1277 operInputted = false;
1278 /* normal,0; normal,1-9; typing,0; typing,1-9 */
1279 switch(calStatus){
1280 case cal_normal:
1281 if(CAL_BUTTON == btn_0 )
1282 break; /* first input is 0, ignore */
1283 clearInput();
1284 /*no operator means start a new calculation*/
1285 if (oper ==' ')
1286 clearOperand();
1287 calStatus = cal_typing;
1288 /* go on typing, no break */
1289 case cal_typing:
1290 case cal_dotted:
1291 switch(CAL_BUTTON){
1292 case btn_0:
1293 *typingbufPointer = '0';
1294 break;
1295 default:
1296 *typingbufPointer=(7+btn_col-3*(btn_row-1))+ '0';
1297 break;
1299 if (typingbufPointer!=typingbuf+DIGITLEN+1){
1300 typingbufPointer++;
1302 {/* result processing */
1303 if (calStatus == cal_typing) power++;
1304 if (CAL_BUTTON != btn_0)
1305 result= result +
1306 SIGN(result)*
1307 (7+btn_col-3*(btn_row-1))*modifier;
1308 modifier /= 10;
1311 else /* last byte always '\0' */
1312 *typingbufPointer = 0;
1313 break;
1314 default: /* cal_error, cal_exit */
1315 break;
1317 break; /* default, 0-9 */
1318 } /* switch( CAL_BUTTON ) */
1321 /* -----------------------------------------------------------------------
1322 Handle delete operation
1323 main operand "result" and typingbuf are processed seperately here.
1324 ----------------------------------------------------------------------- */
1325 void doDelete(void){
1326 deleteAnimation(18);
1327 switch(calStatus){
1328 case cal_dotted:
1329 if (*(typingbufPointer-1) == '.'){
1330 /* if dotted and deleting '.',
1331 change status and delete '.' below */
1332 calStatus = cal_typing;
1334 else{ /* if dotted and not deleting '.',
1335 power stays */
1336 power++; /* counter "power--;" below */
1338 case cal_typing:
1339 typingbufPointer--;
1341 {/* result processing */ /* 0-9, '.' */
1342 /* if deleting '.', do nothing */
1343 if ( *typingbufPointer != '.'){
1344 power--;
1345 modifier *= 10;
1346 result = result - SIGN(result)*
1347 ((*typingbufPointer)- '0')*modifier;
1351 *typingbufPointer = 0;
1353 /* if (only one digit left and it's 0)
1354 or no digit left, change status*/
1355 if ( typingbufPointer == typingbuf+1 ||
1356 ( typingbufPointer == typingbuf+2 &&
1357 *(typingbufPointer-1) == '0' ))
1358 calStatus = cal_normal;
1359 break;
1360 default: /* normal, error, exit */
1361 break;
1364 /* -----------------------------------------------------------------------
1365 Handle buttons on basic screen
1366 ----------------------------------------------------------------------- */
1367 void basicButtonsProcess(void){
1368 switch (btn) {
1369 case CALCULATOR_INPUT:
1370 if (calStatus == cal_error && (CAL_BUTTON != btn_C) ) break;
1371 flashButton();
1372 switch( CAL_BUTTON ){
1373 case btn_MR:
1374 operInputted = false;
1375 result = memTemp; power = memTempPower;
1376 calStatus = cal_normal;
1377 break;
1378 case btn_M:
1379 formatResult();
1380 if (memTemp > MINIMUM)
1381 doAdd(&memTemp, &memTempPower, result, power);
1382 else {
1383 /* if result is too small and memTemp = 0,
1384 doAdd will not add */
1385 memTemp = result;
1386 memTempPower = power;
1388 calStatus = cal_normal;
1389 break;
1391 case btn_C: clearMem(); break;
1392 case btn_CE: clearInput(); break;
1394 case btn_bas:
1395 buttonGroup = sciButtons;
1396 printButtonGroups(buttonGroup);
1397 break;
1399 /* one operand calculation, may be changed to
1400 like sin, cos, log, etc */
1401 case btn_sqr:
1402 case btn_square:
1403 case btn_rec:
1404 formatResult(); /* not necessary, just for safty */
1405 oneOperand();
1406 break;
1408 case_btn_equal: /* F3 shortkey entrance */
1409 case btn_equal:
1410 formatResult();
1411 calStatus = cal_normal;
1412 operInputted = false;
1413 if (oper != ' ') twoOperands();
1414 break;
1416 case btn_div:
1417 case btn_time:
1418 case btn_minus:
1419 case btn_add:
1420 if(!operInputted) {twoOperands(); operInputted = true;}
1421 oper = buttonChar[basicButtons][btn_row][btn_col][0];
1422 #ifdef CALCULATOR_OPERATORS
1423 case_cycle_operators: /* F2 shortkey entrance */
1424 #endif
1425 calStatus = cal_normal;
1426 formatResult();
1427 operand = result;
1428 operandPower = power;
1430 break;
1432 case btn_sign:
1433 case btn_dot:
1434 default: /* 0-9 */
1435 typingProcess();
1436 break;
1437 } /* switch (CAL_BUTTON) */
1438 break;
1440 #ifdef CALCULATOR_OPERATORS
1441 case CALCULATOR_OPERATORS:
1442 if (calStatus == cal_error) break;
1443 if (!operInputted) {twoOperands(); operInputted = true;}
1444 switch (oper){
1445 case ' ':
1446 case '/': oper = '+'; flashButton(); break;
1447 case '+': oper = '-'; flashButton(); break;
1448 case '-': oper = '*'; flashButton(); break;
1449 case '*': oper = '/'; flashButton(); break;
1451 goto case_cycle_operators;
1452 break;
1453 #endif
1455 case CALCULATOR_CALC:
1456 if (calStatus == cal_error) break;
1457 flashButton();
1458 goto case_btn_equal;
1459 break;
1460 default: break;
1462 printResult();
1465 /* -----------------------------------------------------------------------
1466 Handle buttons on scientific screen
1467 ----------------------------------------------------------------------- */
1468 void sciButtonsProcess(void){
1469 switch (btn) {
1470 case CALCULATOR_INPUT:
1471 if (calStatus == cal_error && (CAL_BUTTON != sci_sci) ) break;
1472 flashButton();
1473 switch( CAL_BUTTON ){
1475 case sci_pi:
1476 result = M_PI; power = 0;
1477 calStatus = cal_normal;
1478 break;
1480 case sci_xy: break;
1482 case sci_sci:
1483 buttonGroup = basicButtons;
1484 printButtonGroups(basicButtons);
1485 break;
1487 case sci_fac:
1488 case sci_sin:
1489 case sci_asin:
1490 case sci_cos:
1491 case sci_acos:
1492 case sci_tan:
1493 case sci_atan:
1494 case sci_ln:
1495 case sci_exp:
1496 case sci_log:
1497 formatResult(); /* not necessary, just for safty */
1498 oneOperand();
1499 break;
1501 case btn_sign:
1502 case btn_dot:
1503 default: /* 0-9 */
1504 typingProcess();
1505 break;
1506 } /* switch (CAL_BUTTON) */
1507 break;
1509 #ifdef CALCULATOR_OPERATORS
1510 case CALCULATOR_OPERATORS:
1511 if (calStatus == cal_error) break;
1512 if (!operInputted) {twoOperands(); operInputted = true;}
1513 switch (oper){
1514 case ' ': oper = '+'; break;
1515 case '/': oper = '+'; deleteAnimation(1); break;
1516 case '+': oper = '-'; deleteAnimation(1); break;
1517 case '-': oper = '*'; deleteAnimation(1); break;
1518 case '*': oper = '/'; deleteAnimation(1); break;
1520 calStatus = cal_normal;
1521 formatResult();
1522 operand = result;
1523 operandPower = power;
1524 break;
1525 #endif
1527 case CALCULATOR_CALC:
1528 if (calStatus == cal_error) break;
1529 formatResult();
1530 calStatus = cal_normal;
1531 operInputted = false;
1532 if (oper != ' ') twoOperands();
1533 break;
1534 default: break;
1536 printResult();
1539 /* -----------------------------------------------------------------------
1540 move button index
1541 Invert display new button, invert back previous button
1542 ----------------------------------------------------------------------- */
1543 int handleButton(int button){
1544 switch(button)
1546 case CALCULATOR_INPUT:
1547 case CALCULATOR_CALC:
1548 #ifdef CALCULATOR_INPUT_CALC_PRE
1549 if (lastbtn != CALCULATOR_INPUT_CALC_PRE)
1550 break;
1551 /* no unconditional break; here! */
1552 #endif
1553 #ifdef CALCULATOR_OPERATORS
1554 case CALCULATOR_OPERATORS:
1555 #endif
1556 switch(buttonGroup){
1557 case basicButtons:
1558 basicButtonsProcess();
1559 break;
1560 case sciButtons:
1561 sciButtonsProcess();
1562 break;
1564 break;
1566 #ifdef CALCULATOR_CLEAR
1567 case CALCULATOR_CLEAR:
1568 switch(calStatus){
1569 case cal_typing:
1570 case cal_dotted:
1571 doDelete();
1572 break;
1573 default: /* cal_normal, cal_error, cal_exit */
1574 clearMem();
1575 break;
1577 printResult();
1578 break;
1579 #endif
1580 case CALCULATOR_LEFT:
1581 case CALCULATOR_LEFT | BUTTON_REPEAT:
1582 move_with_wrap_and_shift(
1583 &btn_col, -1, BUTTON_COLS,
1584 &btn_row, 0, BUTTON_ROWS);
1585 break;
1587 case CALCULATOR_RIGHT:
1588 case CALCULATOR_RIGHT | BUTTON_REPEAT:
1589 move_with_wrap_and_shift(
1590 &btn_col, 1, BUTTON_COLS,
1591 &btn_row, 0, BUTTON_ROWS);
1592 break;
1594 #ifdef CALCULATOR_UP
1595 case CALCULATOR_UP:
1596 case CALCULATOR_UP | BUTTON_REPEAT:
1597 move_with_wrap_and_shift(
1598 &btn_row, -1, BUTTON_ROWS,
1599 &btn_col, 0, BUTTON_COLS);
1600 break;
1601 #endif
1602 #ifdef CALCULATOR_DOWN
1603 case CALCULATOR_DOWN:
1604 case CALCULATOR_DOWN | BUTTON_REPEAT:
1605 move_with_wrap_and_shift(
1606 &btn_row, 1, BUTTON_ROWS,
1607 &btn_col, 0, BUTTON_COLS);
1608 break;
1609 #endif
1611 #ifdef CALCULATOR_UP_W_SHIFT
1612 case CALCULATOR_UP_W_SHIFT:
1613 case CALCULATOR_UP_W_SHIFT | BUTTON_REPEAT:
1614 move_with_wrap_and_shift(
1615 &btn_row, -1, BUTTON_ROWS,
1616 &btn_col, -1, BUTTON_COLS);
1617 break;
1618 #endif
1619 #ifdef CALCULATOR_DOWN_W_SHIFT
1620 case CALCULATOR_DOWN_W_SHIFT:
1621 case CALCULATOR_DOWN_W_SHIFT | BUTTON_REPEAT:
1622 move_with_wrap_and_shift(
1623 &btn_row, 1, BUTTON_ROWS,
1624 &btn_col, 1, BUTTON_COLS);
1625 break;
1626 #endif
1627 #ifdef CALCULATOR_LEFT_W_SHIFT
1628 case CALCULATOR_LEFT_W_SHIFT:
1629 case CALCULATOR_LEFT_W_SHIFT | BUTTON_REPEAT:
1630 move_with_wrap_and_shift(
1631 &btn_col, -1, BUTTON_COLS,
1632 &btn_row, -1, BUTTON_ROWS);
1633 break;
1634 #endif
1635 #ifdef CALCULATOR_RIGHT_W_SHIFT
1636 case CALCULATOR_RIGHT_W_SHIFT:
1637 case CALCULATOR_RIGHT_W_SHIFT | BUTTON_REPEAT:
1638 move_with_wrap_and_shift(
1639 &btn_col, 1, BUTTON_COLS,
1640 &btn_row, 1, BUTTON_ROWS);
1641 break;
1642 #endif
1643 #ifdef CALCULATOR_RC_QUIT
1644 case CALCULATOR_RC_QUIT:
1645 #endif
1646 case CALCULATOR_QUIT:
1647 return -1;
1650 return 0;
1652 prev_btn_row = btn_row;
1653 prev_btn_col = btn_col;
1656 /* -----------------------------------------------------------------------
1657 Main();
1658 ----------------------------------------------------------------------- */
1659 enum plugin_status plugin_start(const void* parameter)
1661 (void)parameter;
1663 /* now go ahead and have fun! */
1665 cal_initial();
1667 while (calStatus != cal_exit ) {
1668 btn = rb->button_get_w_tmo(HZ/2);
1669 #ifdef HAVE_TOUCHSCREEN
1670 if(btn & BUTTON_TOUCHSCREEN)
1672 struct ts_raster_result res;
1673 if(touchscreen_map_raster(&calc_raster, rb->button_get_data() >> 16,
1674 rb->button_get_data() & 0xffff, &res) == 1)
1676 btn_row = res.y;
1677 btn_col = res.x;
1678 drawButtons(buttonGroup);
1679 drawLines();
1681 rb->lcd_update();
1683 prev_btn_row = btn_row;
1684 prev_btn_col = btn_col;
1685 if(btn & BUTTON_REL)
1687 btn = CALCULATOR_INPUT;
1688 switch(buttonGroup){
1689 case basicButtons:
1690 basicButtonsProcess();
1691 break;
1692 case sciButtons:
1693 sciButtonsProcess();
1694 break;
1696 btn = BUTTON_TOUCHSCREEN;
1700 #endif
1701 if (handleButton(btn) == -1)
1703 calStatus = cal_exit;
1704 printResult();
1706 else
1708 drawButtons(buttonGroup);
1709 drawLines();
1712 rb->lcd_update();
1714 if(rb->default_event_handler(btn) == SYS_USB_CONNECTED)
1715 return PLUGIN_USB_CONNECTED;
1717 if (btn != BUTTON_NONE)
1718 lastbtn = btn;
1719 } /* while (calStatus != cal_exit ) */
1721 rb->button_clear_queue();
1722 return PLUGIN_OK;
1725 #endif /* #ifdef HAVE_LCD_BITMAP */