Remove various ABS() definitions with a single one using typeof (if using gcc) to...
[kugel-rb/myfork.git] / apps / plugins / calculator.c
blob3d0105e33d6ea161b98257325715a56a3309f28f
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 SIGN(x) ((x)<0?-1:1)
106 /* variable button definitions */
107 #if CONFIG_KEYPAD == RECORDER_PAD
108 #define CALCULATOR_LEFT BUTTON_LEFT
109 #define CALCULATOR_RIGHT BUTTON_RIGHT
110 #define CALCULATOR_UP BUTTON_UP
111 #define CALCULATOR_DOWN BUTTON_DOWN
112 #define CALCULATOR_QUIT BUTTON_OFF
113 #define CALCULATOR_INPUT BUTTON_PLAY
114 #define CALCULATOR_CALC BUTTON_F3
115 #define CALCULATOR_OPERATORS BUTTON_F2
116 #define CALCULATOR_CLEAR BUTTON_F1
118 #elif CONFIG_KEYPAD == ARCHOS_AV300_PAD
119 #define CALCULATOR_LEFT BUTTON_LEFT
120 #define CALCULATOR_RIGHT BUTTON_RIGHT
121 #define CALCULATOR_UP BUTTON_UP
122 #define CALCULATOR_DOWN BUTTON_DOWN
123 #define CALCULATOR_QUIT BUTTON_OFF
124 #define CALCULATOR_INPUT BUTTON_SELECT
125 #define CALCULATOR_CALC BUTTON_F3
126 #define CALCULATOR_OPERATORS BUTTON_F2
127 #define CALCULATOR_CLEAR BUTTON_F1
129 #elif CONFIG_KEYPAD == ONDIO_PAD
130 #define CALCULATOR_LEFT BUTTON_LEFT
131 #define CALCULATOR_RIGHT BUTTON_RIGHT
132 #define CALCULATOR_UP BUTTON_UP
133 #define CALCULATOR_DOWN BUTTON_DOWN
134 #define CALCULATOR_QUIT BUTTON_OFF
135 #define CALCULATOR_INPUT_CALC_PRE BUTTON_MENU
136 #define CALCULATOR_INPUT (BUTTON_MENU | BUTTON_REL)
137 #define CALCULATOR_CALC (BUTTON_MENU | BUTTON_REPEAT)
139 #elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || \
140 (CONFIG_KEYPAD == IRIVER_H300_PAD)
141 #define CALCULATOR_LEFT BUTTON_LEFT
142 #define CALCULATOR_RIGHT BUTTON_RIGHT
143 #define CALCULATOR_UP BUTTON_UP
144 #define CALCULATOR_DOWN BUTTON_DOWN
145 #define CALCULATOR_QUIT BUTTON_OFF
146 #define CALCULATOR_INPUT BUTTON_SELECT
147 #define CALCULATOR_CALC BUTTON_ON
148 #define CALCULATOR_OPERATORS BUTTON_MODE
149 #define CALCULATOR_CLEAR BUTTON_REC
151 #define CALCULATOR_RC_QUIT BUTTON_RC_STOP
153 #elif (CONFIG_KEYPAD == IPOD_4G_PAD) || \
154 (CONFIG_KEYPAD == IPOD_3G_PAD) || \
155 (CONFIG_KEYPAD == IPOD_1G2G_PAD)
157 #define CALCULATOR_LEFT BUTTON_LEFT
158 #define CALCULATOR_RIGHT BUTTON_RIGHT
159 #define CALCULATOR_UP_W_SHIFT BUTTON_SCROLL_BACK
160 #define CALCULATOR_DOWN_W_SHIFT BUTTON_SCROLL_FWD
161 #define CALCULATOR_QUIT BUTTON_MENU
162 #define CALCULATOR_INPUT BUTTON_SELECT
163 #define CALCULATOR_CALC BUTTON_PLAY
165 #elif (CONFIG_KEYPAD == IAUDIO_X5M5_PAD)
167 #define CALCULATOR_LEFT BUTTON_LEFT
168 #define CALCULATOR_RIGHT BUTTON_RIGHT
169 #define CALCULATOR_UP BUTTON_UP
170 #define CALCULATOR_DOWN BUTTON_DOWN
171 #define CALCULATOR_QUIT BUTTON_POWER
172 #define CALCULATOR_INPUT BUTTON_SELECT
173 #define CALCULATOR_CALC BUTTON_PLAY
174 #define CALCULATOR_CLEAR BUTTON_REC
176 #elif (CONFIG_KEYPAD == GIGABEAT_PAD)
178 #define CALCULATOR_LEFT BUTTON_LEFT
179 #define CALCULATOR_RIGHT BUTTON_RIGHT
180 #define CALCULATOR_UP BUTTON_UP
181 #define CALCULATOR_DOWN BUTTON_DOWN
182 #define CALCULATOR_QUIT BUTTON_POWER
183 #define CALCULATOR_INPUT BUTTON_SELECT
184 #define CALCULATOR_CALC BUTTON_MENU
185 #define CALCULATOR_CLEAR BUTTON_A
187 #elif (CONFIG_KEYPAD == SANSA_E200_PAD)
188 #define CALCULATOR_LEFT BUTTON_LEFT
189 #define CALCULATOR_RIGHT BUTTON_RIGHT
190 #define CALCULATOR_UP BUTTON_UP
191 #define CALCULATOR_DOWN BUTTON_DOWN
192 #define CALCULATOR_UP_W_SHIFT BUTTON_SCROLL_BACK
193 #define CALCULATOR_DOWN_W_SHIFT BUTTON_SCROLL_FWD
194 #define CALCULATOR_QUIT BUTTON_POWER
195 #define CALCULATOR_INPUT_CALC_PRE BUTTON_SELECT
196 #define CALCULATOR_INPUT (BUTTON_SELECT|BUTTON_REL)
197 #define CALCULATOR_CALC (BUTTON_SELECT|BUTTON_REPEAT)
198 #define CALCULATOR_CLEAR BUTTON_REC
200 #elif (CONFIG_KEYPAD == SANSA_C200_PAD)
201 #define CALCULATOR_LEFT BUTTON_LEFT
202 #define CALCULATOR_RIGHT BUTTON_RIGHT
203 #define CALCULATOR_UP BUTTON_UP
204 #define CALCULATOR_DOWN BUTTON_DOWN
205 #define CALCULATOR_QUIT BUTTON_POWER
206 #define CALCULATOR_INPUT_CALC_PRE BUTTON_SELECT
207 #define CALCULATOR_INPUT (BUTTON_SELECT|BUTTON_REL)
208 #define CALCULATOR_CALC (BUTTON_SELECT|BUTTON_REPEAT)
210 #elif (CONFIG_KEYPAD == SANSA_FUZE_PAD)
211 #define CALCULATOR_LEFT BUTTON_LEFT
212 #define CALCULATOR_RIGHT BUTTON_RIGHT
213 #define CALCULATOR_UP BUTTON_UP
214 #define CALCULATOR_DOWN BUTTON_DOWN
215 #define CALCULATOR_UP_W_SHIFT BUTTON_SCROLL_BACK
216 #define CALCULATOR_DOWN_W_SHIFT BUTTON_SCROLL_FWD
217 #define CALCULATOR_QUIT (BUTTON_HOME|BUTTON_REPEAT)
218 #define CALCULATOR_INPUT_CALC_PRE BUTTON_SELECT
219 #define CALCULATOR_INPUT (BUTTON_SELECT|BUTTON_REL)
220 #define CALCULATOR_CALC (BUTTON_SELECT|BUTTON_REPEAT)
223 #elif (CONFIG_KEYPAD == SANSA_CLIP_PAD)
224 #define CALCULATOR_LEFT BUTTON_LEFT
225 #define CALCULATOR_RIGHT BUTTON_RIGHT
226 #define CALCULATOR_UP BUTTON_UP
227 #define CALCULATOR_DOWN BUTTON_DOWN
228 #define CALCULATOR_QUIT BUTTON_POWER
229 #define CALCULATOR_INPUT_CALC_PRE BUTTON_SELECT
230 #define CALCULATOR_INPUT (BUTTON_SELECT|BUTTON_REL)
231 #define CALCULATOR_CALC (BUTTON_SELECT|BUTTON_REPEAT)
232 #define CALCULATOR_CLEAR BUTTON_HOME
234 #elif (CONFIG_KEYPAD == SANSA_M200_PAD)
235 #define CALCULATOR_LEFT BUTTON_LEFT
236 #define CALCULATOR_RIGHT BUTTON_RIGHT
237 #define CALCULATOR_UP BUTTON_UP
238 #define CALCULATOR_DOWN BUTTON_DOWN
239 #define CALCULATOR_QUIT BUTTON_POWER
240 #define CALCULATOR_INPUT_CALC_PRE BUTTON_SELECT
241 #define CALCULATOR_INPUT (BUTTON_SELECT|BUTTON_REL)
242 #define CALCULATOR_CALC (BUTTON_SELECT|BUTTON_REPEAT)
243 #define CALCULATOR_CLEAR (BUTTON_SELECT|BUTTON_UP)
245 #elif (CONFIG_KEYPAD == IRIVER_H10_PAD)
247 #define CALCULATOR_LEFT BUTTON_LEFT
248 #define CALCULATOR_RIGHT BUTTON_RIGHT
249 #define CALCULATOR_UP BUTTON_SCROLL_UP
250 #define CALCULATOR_DOWN BUTTON_SCROLL_DOWN
251 #define CALCULATOR_QUIT BUTTON_POWER
252 #define CALCULATOR_INPUT_CALC_PRE BUTTON_PLAY
253 #define CALCULATOR_INPUT (BUTTON_PLAY | BUTTON_REL)
254 #define CALCULATOR_CALC (BUTTON_PLAY | BUTTON_REPEAT)
255 #define CALCULATOR_CLEAR BUTTON_REW
257 #elif (CONFIG_KEYPAD == GIGABEAT_S_PAD)
259 #define CALCULATOR_LEFT BUTTON_LEFT
260 #define CALCULATOR_RIGHT BUTTON_RIGHT
261 #define CALCULATOR_UP BUTTON_UP
262 #define CALCULATOR_DOWN BUTTON_DOWN
263 #define CALCULATOR_QUIT BUTTON_BACK
264 #define CALCULATOR_INPUT BUTTON_SELECT
265 #define CALCULATOR_CALC BUTTON_MENU
266 #define CALCULATOR_CLEAR BUTTON_PLAY
268 #elif (CONFIG_KEYPAD == MROBE100_PAD)
270 #define CALCULATOR_LEFT BUTTON_LEFT
271 #define CALCULATOR_RIGHT BUTTON_RIGHT
272 #define CALCULATOR_UP BUTTON_UP
273 #define CALCULATOR_DOWN BUTTON_DOWN
274 #define CALCULATOR_QUIT BUTTON_POWER
275 #define CALCULATOR_INPUT BUTTON_SELECT
276 #define CALCULATOR_CALC BUTTON_MENU
277 #define CALCULATOR_CLEAR BUTTON_DISPLAY
279 #elif CONFIG_KEYPAD == IAUDIO_M3_PAD
281 #define CALCULATOR_LEFT BUTTON_RC_REW
282 #define CALCULATOR_RIGHT BUTTON_RC_FF
283 #define CALCULATOR_UP BUTTON_RC_VOL_UP
284 #define CALCULATOR_DOWN BUTTON_RC_VOL_DOWN
285 #define CALCULATOR_QUIT BUTTON_RC_REC
286 #define CALCULATOR_INPUT BUTTON_RC_PLAY
287 #define CALCULATOR_CALC BUTTON_RC_MODE
288 #define CALCULATOR_CLEAR BUTTON_RC_MENU
290 #define CALCULATOR_RC_QUIT BUTTON_REC
292 #elif (CONFIG_KEYPAD == COWOND2_PAD)
294 #define CALCULATOR_QUIT BUTTON_POWER
295 #define CALCULATOR_CLEAR BUTTON_MENU
297 #elif CONFIG_KEYPAD == IAUDIO67_PAD
299 #define CALCULATOR_LEFT BUTTON_LEFT
300 #define CALCULATOR_RIGHT BUTTON_RIGHT
301 #define CALCULATOR_UP BUTTON_VOLUP
302 #define CALCULATOR_DOWN BUTTON_VOLDOWN
303 #define CALCULATOR_QUIT BUTTON_POWER
304 #define CALCULATOR_INPUT BUTTON_PLAY
305 #define CALCULATOR_CALC BUTTON_MENU
306 #define CALCULATOR_CLEAR BUTTON_STOP
308 #define CALCULATOR_RC_QUIT (BUTTON_MENU|BUTTON_PLAY)
310 #elif (CONFIG_KEYPAD == CREATIVEZVM_PAD)
312 #define CALCULATOR_LEFT BUTTON_LEFT
313 #define CALCULATOR_RIGHT BUTTON_RIGHT
314 #define CALCULATOR_UP BUTTON_UP
315 #define CALCULATOR_DOWN BUTTON_DOWN
316 #define CALCULATOR_QUIT BUTTON_BACK
317 #define CALCULATOR_INPUT BUTTON_SELECT
318 #define CALCULATOR_CALC BUTTON_MENU
319 #define CALCULATOR_CLEAR BUTTON_PLAY
321 #elif CONFIG_KEYPAD == PHILIPS_HDD1630_PAD
323 #define CALCULATOR_LEFT BUTTON_LEFT
324 #define CALCULATOR_RIGHT BUTTON_RIGHT
325 #define CALCULATOR_UP BUTTON_UP
326 #define CALCULATOR_DOWN BUTTON_DOWN
327 #define CALCULATOR_QUIT BUTTON_POWER
328 #define CALCULATOR_INPUT BUTTON_SELECT
329 #define CALCULATOR_CALC BUTTON_MENU
330 #define CALCULATOR_CLEAR BUTTON_VIEW
332 #elif (CONFIG_KEYPAD == ONDAVX747_PAD)
334 #define CALCULATOR_QUIT BUTTON_POWER
335 #define CALCULATOR_CLEAR BUTTON_MENU
337 #elif CONFIG_KEYPAD == MROBE500_PAD
338 #define CALCULATOR_QUIT BUTTON_POWER
340 #else
341 #error No keymap defined!
342 #endif
344 #ifdef HAVE_TOUCHSCREEN
345 #ifndef CALCULATOR_LEFT
346 #define CALCULATOR_LEFT BUTTON_MIDLEFT
347 #endif
348 #ifndef CALCULATOR_RIGHT
349 #define CALCULATOR_RIGHT BUTTON_MIDRIGHT
350 #endif
351 #ifndef CALCULATOR_UP
352 #define CALCULATOR_UP BUTTON_TOPMIDDLE
353 #endif
354 #ifndef CALCULATOR_DOWN
355 #define CALCULATOR_DOWN BUTTON_BOTTOMMIDDLE
356 #endif
357 #ifndef CALCULATOR_CALC
358 #define CALCULATOR_CALC BUTTON_BOTTOMRIGHT
359 #endif
360 #ifndef CALCULATOR_INPUT
361 #define CALCULATOR_INPUT BUTTON_CENTER
362 #endif
363 #ifndef CALCULATOR_CLEAR
364 #define CALCULATOR_CLEAR BUTTON_TOPRIGHT
365 #endif
367 #include "lib/pluginlib_touchscreen.h"
368 static struct ts_raster calc_raster = { X_0_POS, Y_1_POS,
369 BUTTON_COLS*REC_WIDTH, BUTTON_ROWS*REC_HEIGHT, REC_WIDTH, REC_HEIGHT };
370 #endif
372 enum {
373 basicButtons,
374 sciButtons
375 } buttonGroup;
377 unsigned char* buttonChar[2][5][5] = {
378 { { "MR" , "M+" , "2nd" , "CE" , "C" },
379 { "7" , "8" , "9" , "/" , "sqr" },
380 { "4" , "5" , "6" , "*" , "x^2" },
381 { "1" , "2" , "3" , "-" , "1/x" },
382 { "0" , "+/-", "." , "+" , "=" } },
384 { { "n!" , "PI" , "1st" , "sin" , "asi" },
385 { "7" , "8" , "9" , "cos" , "aco" },
386 { "4" , "5" , "6" , "tan" , "ata" },
387 { "1" , "2" , "3" , "ln" , "e^x" },
388 { "0" , "+/-", "." , "log" , "x^y" } }
391 enum { btn_MR , btn_M , btn_bas , btn_CE , btn_C ,
392 btn_7 , btn_8 , btn_9 , btn_div , btn_sqr ,
393 btn_4 , btn_5 , btn_6 , btn_time , btn_square ,
394 btn_1 , btn_2 , btn_3 , btn_minus , btn_rec ,
395 btn_0 , btn_sign , btn_dot , btn_add , btn_equal
398 enum { sci_fac, sci_pi , sci_sci , sci_sin , sci_asin ,
399 sci_7 , sci_8 , sci_9 , sci_cos , sci_acos ,
400 sci_4 , sci_5 , sci_6 , sci_tan , sci_atan ,
401 sci_1 , sci_2 , sci_3 , sci_ln , sci_exp ,
402 sci_0 , sci_sign , sci_dot , sci_log , sci_xy
405 #define MINIMUM 0.000000000001 /* e-12 */
406 /* ^ ^ ^ ^ */
407 /* 123456789abcdef */
409 #define DIGITLEN 10 /* must <= 10 */
410 #define SCIENTIFIC_FORMAT ( power < -(DIGITLEN-3) || power > (DIGITLEN))
411 /* 0.000 00000 0001 */
412 /* ^ ^ ^ ^ ^ ^ */
413 /* DIGITLEN 12345 6789a bcdef */
414 /* power 12 34567 89abc def */
415 /* 10^- 123 45678 9abcd ef */
417 unsigned char buf[19];/* 18 bytes of output line,
418 buf[0] is operator
419 buf[1] = 'M' if memTemp is not 0
420 buf[2] = ' '
422 if SCIENTIFIC_FORMAT
423 buf[2]-buf[12] or buf[3]-buf[13] = result;
424 format X.XXXXXXXX
425 buf[13] or buf[14] -buf[17] = power;
426 format eXXX or e-XXX
427 else
428 buf[3]-buf[6] = ' ';
429 buf[7]-buf[17] = result;
431 buf[18] = '\0' */
433 unsigned char typingbuf[DIGITLEN+2];/* byte 0 is sign or ' ',
434 byte 1~DIGITLEN are num and '.'
435 byte (DIGITLEN+1) is '\0' */
436 unsigned char* typingbufPointer = typingbuf;
438 double result = 0; /* main operand, format 0.xxxxx */
439 int power = 0; /* 10^power */
440 double modifier = 0.1; /* position of next input */
441 double operand = 0; /* second operand, format 0.xxxxx */
442 int operandPower = 0; /* 10^power of second operand */
443 char oper = ' '; /* operators: + - * / */
444 bool operInputted = false; /* false: do calculation first and
445 replace current oper
446 true: just replace current oper */
448 double memTemp = 0; /* temp memory */
449 int memTempPower = 0; /* 10^^power of memTemp */
451 int btn_row, btn_col; /* current position index for button */
452 int prev_btn_row, prev_btn_col; /* previous cursor position */
453 #define CAL_BUTTON (btn_row*5+btn_col)
455 int btn = BUTTON_NONE;
456 int lastbtn = BUTTON_NONE;
458 /* Status of calculator */
459 enum {cal_normal, /* 0, normal status, display result */
460 cal_typing, /* 1, currently typing, dot hasn't been typed */
461 cal_dotted, /* 2, currently typing, dot already has been typed. */
462 cal_error,
463 cal_exit,
464 cal_toDo
465 } calStatus;
467 /* constant table for CORDIC algorithm */
468 double cordicTable[51][2]= {
469 /* pow(2,0) - pow(2,-50) atan(pow(2,0) - atan(pow(2,-50) */
470 {1e+00, 7.853981633974483e-01},
471 {5e-01, 4.636476090008061e-01},
472 {2.5e-01, 2.449786631268641e-01},
473 {1.25e-01, 1.243549945467614e-01},
474 {6.25e-02, 6.241880999595735e-02},
475 {3.125e-02, 3.123983343026828e-02},
476 {1.5625e-02, 1.562372862047683e-02},
477 {7.8125e-03, 7.812341060101111e-03},
478 {3.90625e-03, 3.906230131966972e-03},
479 {1.953125e-03, 1.953122516478819e-03},
480 {9.765625e-04, 9.765621895593195e-04},
481 {4.8828125e-04, 4.882812111948983e-04},
482 {2.44140625e-04, 2.441406201493618e-04},
483 {1.220703125e-04, 1.220703118936702e-04},
484 {6.103515625e-05, 6.103515617420877e-05},
485 {3.0517578125e-05, 3.051757811552610e-05},
486 {1.52587890625e-05, 1.525878906131576e-05},
487 {7.62939453125e-06, 7.629394531101970e-06},
488 {3.814697265625e-06, 3.814697265606496e-06},
489 {1.9073486328125e-06, 1.907348632810187e-06},
490 {9.5367431640625e-07, 9.536743164059608e-07},
491 {4.76837158203125e-07, 4.768371582030888e-07},
492 {2.384185791015625e-07, 2.384185791015580e-07},
493 {1.1920928955078125e-07, 1.192092895507807e-07},
494 {5.9604644775390625e-08, 5.960464477539055e-08},
495 {2.98023223876953125e-08, 2.980232238769530e-08},
496 {1.490116119384765625e-08, 1.490116119384765e-08},
497 {7.450580596923828125e-09, 7.450580596923828e-09},
498 {3.7252902984619140625e-09, 3.725290298461914e-09},
499 {1.86264514923095703125e-09, 1.862645149230957e-09},
500 {9.31322574615478515625e-10, 9.313225746154785e-10},
501 {4.656612873077392578125e-10, 4.656612873077393e-10},
502 {2.3283064365386962890625e-10, 2.328306436538696e-10},
503 {1.16415321826934814453125e-10, 1.164153218269348e-10},
504 {5.82076609134674072265625e-11, 5.820766091346741e-11},
505 {2.910383045673370361328125e-11, 2.910383045673370e-11},
506 {1.4551915228366851806640625e-11, 1.455191522836685e-11},
507 {7.2759576141834259033203125e-12, 7.275957614183426e-12},
508 {3.63797880709171295166015625e-12, 3.637978807091713e-12},
509 {1.818989403545856475830078125e-12, 1.818989403545856e-12},
510 {9.094947017729282379150390625e-13, 9.094947017729282e-13},
511 {4.5474735088646411895751953125e-13, 4.547473508864641e-13},
512 {2.27373675443232059478759765625e-13, 2.273736754432321e-13},
513 {1.136868377216160297393798828125e-13, 1.136868377216160e-13},
514 {5.684341886080801486968994140625e-14, 5.684341886080801e-14},
515 {2.8421709430404007434844970703125e-14, 2.842170943040401e-14},
516 {1.42108547152020037174224853515625e-14, 1.421085471520200e-14},
517 {7.10542735760100185871124267578125e-15, 7.105427357601002e-15},
518 {3.552713678800500929355621337890625e-15, 3.552713678800501e-15},
519 {1.7763568394002504646778106689453125e-15, 1.776356839400250e-15},
520 {8.8817841970012523233890533447265625e-16, 8.881784197001252e-16}
523 void doMultiple(double* operandOne, int* powerOne,
524 double operandTwo, int powerTwo);
525 void doAdd (double* operandOne, int* powerOne,
526 double operandTwo, int powerTwo);
527 void printResult(void);
528 void formatResult(void);
529 void oneOperand(void);
531 void drawLines(void);
532 void drawButtons(int group);
534 /* -----------------------------------------------------------------------
535 Handy funtions
536 ----------------------------------------------------------------------- */
537 void cleartypingbuf(void)
539 int k;
540 for( k=1; k<=(DIGITLEN+1); k++)
541 typingbuf[k] = 0;
542 typingbuf[0] = ' ';
543 typingbufPointer = typingbuf+1;
545 void clearbuf(void)
547 int k;
548 for(k=0;k<18;k++)
549 buf[k]=' ';
550 buf[18] = 0;
552 void clearResult(void)
554 result = 0;
555 power = 0;
556 modifier = 0.1;
559 void clearInput(void)
561 calStatus = cal_normal;
562 clearResult();
563 cleartypingbuf();
564 rb->lcd_clear_display();
565 drawButtons(buttonGroup);
566 drawLines();
569 void clearOperand(void)
571 operand = 0;
572 operandPower = 0;
575 void clearMemTemp(void)
577 memTemp = 0;
578 memTempPower = 0;
581 void clearOper(void)
583 oper = ' ';
584 operInputted = false;
587 void clearMem(void)
589 clearInput();
590 clearMemTemp();
591 clearOperand();
592 clearOper();
593 btn = BUTTON_NONE;
596 void switchOperands(void)
598 double tempr = operand;
599 int tempp = operandPower;
600 operand = result;
601 operandPower = power;
602 result = tempr;
603 power = tempp;
606 void drawLines(void)
608 int i;
609 rb->lcd_hline(0, LCD_WIDTH, Y_1_POS-1);
610 for (i = 0; i < 5 ; i++)
611 rb->lcd_hline(0, LCD_WIDTH, Y_1_POS+i*REC_HEIGHT);
612 for (i = 0; i < 4 ; i++)
613 rb->lcd_vline(X_1_POS+i*REC_WIDTH, Y_1_POS, LCD_HEIGHT);
616 void drawButtons(int group)
618 int i, j, w, h;
619 for (i = 0; i <= 4; i++){
620 for (j = 0; j <= 4; j++){
621 rb->lcd_getstringsize( buttonChar[group][i][j],&w,&h);
622 if (i == btn_row && j == btn_col) /* selected item */
623 rb->lcd_set_drawmode(DRMODE_SOLID);
624 else
625 rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
626 rb->lcd_fillrect( X_0_POS + j*REC_WIDTH,
627 Y_1_POS + i*REC_HEIGHT,
628 REC_WIDTH, REC_HEIGHT+1);
629 if (i == btn_row && j == btn_col) /* selected item */
630 rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
631 else
632 rb->lcd_set_drawmode(DRMODE_SOLID);
633 rb->lcd_putsxy( X_0_POS + j*REC_WIDTH + (REC_WIDTH - w)/2,
634 Y_1_POS + i*REC_HEIGHT + (REC_HEIGHT - h)/2 + 1,
635 buttonChar[group][i][j] );
638 rb->lcd_set_drawmode(DRMODE_SOLID);
641 /* -----------------------------------------------------------------------
642 Initiate calculator
643 ----------------------------------------------------------------------- */
644 void cal_initial (void)
646 int w,h;
648 rb->lcd_getstringsize("2nd",&w,&h);
649 if (w > REC_WIDTH || h > REC_HEIGHT)
650 rb->lcd_setfont(FONT_SYSFIXED);
652 rb->lcd_clear_display();
654 #ifdef CALCULATOR_OPERATORS
655 /* basic operators are available through separate button */
656 buttonGroup = sciButtons;
657 #else
658 buttonGroup = basicButtons;
659 #endif
661 /* initially, invert button "5" */
662 btn_row = 2;
663 btn_col = 1;
664 prev_btn_row = btn_row;
665 prev_btn_col = btn_col;
666 drawButtons(buttonGroup);
667 drawLines();
668 rb->lcd_update();
670 /* initial mem and output display*/
671 clearMem();
672 printResult();
674 /* clear button queue */
675 rb->button_clear_queue();
678 /* -----------------------------------------------------------------------
679 mySqrt uses Heron's algorithm, which is the Newtone-Raphson algorhitm
680 in it's private case for sqrt.
681 Thanks BlueChip for his intro text and Dave Straayer for the actual name.
682 ----------------------------------------------------------------------- */
683 double mySqrt(double square)
685 int k = 0;
686 double temp = 0;
687 double root= ABS(square+1)/2;
689 while( ABS(root - temp) > MINIMUM ){
690 temp = root;
691 root = (square/temp + temp)/2;
692 k++;
693 if (k>10000) return 0;
696 return root;
698 /* -----------------------------------------------------------------------
699 transcendFunc uses CORDIC (COordinate Rotation DIgital Computer) method
700 transcendFunc can do sin,cos,log,exp
701 input parameter is angle
702 ----------------------------------------------------------------------- */
703 void transcendFunc(char* func, double* tt, int* ttPower)
705 double t = (*tt)*M_PI/180; int tPower = *ttPower;
706 int sign = 1;
707 int n = 50; /* n <=50, tables are all <= 50 */
708 int j;
709 double x,y,z,xt,yt,zt;
711 if (tPower < -998) {
712 calStatus = cal_normal;
713 return;
715 if (tPower > 8) {
716 calStatus = cal_error;
717 return;
719 *ttPower = 0;
720 calStatus = cal_normal;
722 if( func[0] =='s' || func[0] =='S'|| func[0] =='t' || func[0] =='T')
723 sign = SIGN(t);
724 else {
725 /* if( func[0] =='c' || func[0] =='C') */
726 sign = 1;
728 t = ABS(t);
730 while (tPower > 0){
731 t *= 10;
732 tPower--;
734 while (tPower < 0) {
735 t /= 10;
736 tPower++;
738 j = 0;
739 while (t > j*M_TWOPI) {j++;}
740 t -= (j-1)*M_TWOPI;
741 if (M_PI_2 < t && t < 3*M_PI_2){
742 t = M_PI - t;
743 if (func[0] =='c' || func[0] =='C')
744 sign = -1;
745 else if (func[0] =='t' || func[0] =='T')
746 t*=-1;
748 else if ( 3*M_PI_2 <= t && t <= M_TWOPI)
749 t -= M_TWOPI;
751 x = 0.60725293500888; y = 0; z = t;
752 for (j=1;j<n+2;j++){
753 xt = x - SIGN(z) * y*cordicTable[j-1][0];
754 yt = y + SIGN(z) * x*cordicTable[j-1][0];
755 zt = z - SIGN(z) * cordicTable[j-1][1];
756 x = xt;
757 y=yt;
758 z=zt;
760 if( func[0] =='s' || func[0] =='S') {
761 *tt = sign*y;
762 return;
764 else if( func[0] =='c' || func[0] =='C') {
765 *tt = sign*x;
766 return;
768 else /*if( func[0] =='t' || func[0] =='T')*/ {
769 if(t==M_PI_2||t==-M_PI_2){
770 calStatus = cal_error;
771 return;
773 else{
774 *tt = sign*(y/x);
775 return;
780 /* -----------------------------------------------------------------------
781 add in scientific number format
782 ----------------------------------------------------------------------- */
783 void doAdd (double* operandOne, int* powerOne,
784 double operandTwo, int powerTwo)
786 if ( *powerOne >= powerTwo ){
787 if (*powerOne - powerTwo <= DIGITLEN+1){
788 while (powerTwo < *powerOne){
789 operandTwo /=10;
790 powerTwo++;
792 *operandOne += operandTwo;
794 /*do nothing if operandTwo is too small*/
796 else{
797 if (powerTwo - *powerOne <= DIGITLEN+1){
798 while(powerTwo > *powerOne){
799 *operandOne /=10;
800 (*powerOne)++;
802 (*operandOne) += operandTwo;
804 else{/* simply copy operandTwo if operandOne is too small */
805 *operandOne = operandTwo;
806 *powerOne = powerTwo;
810 /* -----------------------------------------------------------------------
811 multiple in scientific number format
812 ----------------------------------------------------------------------- */
813 void doMultiple(double* operandOne, int* powerOne,
814 double operandTwo, int powerTwo)
816 (*operandOne) *= operandTwo;
817 (*powerOne) += powerTwo;
820 /* -----------------------------------------------------------------------
821 Handles all one operand calculations
822 ----------------------------------------------------------------------- */
823 void oneOperand(void)
825 int k = 0;
826 if (buttonGroup == basicButtons){
827 switch(CAL_BUTTON){
828 case btn_sqr:
829 if (result<0)
830 calStatus = cal_error;
831 else{
832 if (power%2 == 1){
833 result = (mySqrt(result*10))/10;
834 power = (power+1) / 2;
836 else{
837 result = mySqrt(result);
838 power = power / 2;
840 calStatus = cal_normal;
842 break;
843 case btn_square:
844 power *= 2;
845 result *= result;
846 calStatus = cal_normal;
847 break;
849 case btn_rec:
850 if (result==0)
851 calStatus = cal_error;
852 else{
853 power = -power;
854 result = 1/result;
855 calStatus = cal_normal;
857 break;
858 default:
859 calStatus = cal_toDo;
860 break; /* just for the safety */
863 else{ /* sciButtons */
864 switch(CAL_BUTTON){
865 case sci_sin:
866 transcendFunc("sin", &result, &power);
867 break;
868 case sci_cos:
869 transcendFunc("cos", &result, &power);
870 break;
871 case sci_tan:
872 transcendFunc("tan", &result, &power);
873 break;
874 case sci_fac:
875 if (power<0 || power>8 || result<0 )
876 calStatus = cal_error;
877 else if(result == 0) {
878 result = 1;
879 power = 0;
881 else{
882 while(power > 0) {
883 result *= 10;
884 power--;
886 if ( ( result - (int)result) > MINIMUM )
887 calStatus = cal_error;
888 else {
889 k = result; result = 1;
890 while (k > 1){
891 doMultiple(&result, &power, k, 0);
892 formatResult();
893 k--;
895 calStatus = cal_normal;
898 break;
899 default:
900 calStatus = cal_toDo;
901 break; /* just for the safety */
907 /* -----------------------------------------------------------------------
908 Handles all two operands calculations
909 ----------------------------------------------------------------------- */
910 void twoOperands(void)
912 switch(oper){
913 case '-':
914 doAdd(&operand, &operandPower, -result, power);
915 break;
916 case '+':
917 doAdd(&operand, &operandPower, result, power);
918 break;
919 case '*':
920 doMultiple(&operand, &operandPower, result, power);
921 break;
922 case '/':
923 if ( ABS(result) > MINIMUM ){
924 doMultiple(&operand, &operandPower, 1/result, -power);
926 else
927 calStatus = cal_error;
928 break;
929 default: /* ' ' */
930 switchOperands(); /* counter switchOperands() below */
931 break;
932 } /* switch(oper) */
933 switchOperands();
934 clearOper();
937 /* First, increases *dimen1 by dimen1_delta modulo dimen1_modulo.
938 If dimen1 wraps, increases *dimen2 by dimen2_delta modulo dimen2_modulo.
940 static void move_with_wrap_and_shift(
941 int *dimen1, int dimen1_delta, int dimen1_modulo,
942 int *dimen2, int dimen2_delta, int dimen2_modulo)
944 bool wrapped = false;
946 *dimen1 += dimen1_delta;
947 if (*dimen1 < 0)
949 *dimen1 = dimen1_modulo - 1;
950 wrapped = true;
952 else if (*dimen1 >= dimen1_modulo)
954 *dimen1 = 0;
955 wrapped = true;
958 if (wrapped)
960 /* Make the dividend always positive to be sure about the result.
961 Adding dimen2_modulo does not change it since we do it modulo. */
962 *dimen2 = (*dimen2 + dimen2_modulo + dimen2_delta) % dimen2_modulo;
966 /* -----------------------------------------------------------------------
967 Print buttons when switching 1st and 2nd
968 int group = {basicButtons, sciButtons}
969 ----------------------------------------------------------------------- */
970 void printButtonGroups(int group)
972 drawButtons(group);
973 drawLines();
974 rb->lcd_update();
976 /* -----------------------------------------------------------------------
977 flash the currently marked button
978 ----------------------------------------------------------------------- */
979 void flashButton(void)
981 int k, w, h;
982 for (k=2;k>0;k--)
984 rb->lcd_getstringsize( buttonChar[buttonGroup][btn_row][btn_col],&w,&h);
985 rb->lcd_set_drawmode(DRMODE_SOLID|(k==1) ? 0 : DRMODE_INVERSEVID);
986 rb->lcd_fillrect( X_0_POS + btn_col*REC_WIDTH + 1,
987 Y_1_POS + btn_row*REC_HEIGHT + 1,
988 REC_WIDTH - 1, REC_HEIGHT - 1);
989 rb->lcd_putsxy( X_0_POS + btn_col*REC_WIDTH + (REC_WIDTH - w)/2,
990 Y_1_POS + btn_row*REC_HEIGHT + (REC_HEIGHT - h)/2 +1,
991 buttonChar[buttonGroup][btn_row][btn_col] );
992 rb->lcd_update_rect( X_0_POS + btn_col*REC_WIDTH + 1,
993 Y_1_POS + btn_row*REC_HEIGHT + 1,
994 REC_WIDTH - 1, REC_HEIGHT - 1);
996 if (k!= 1)
997 rb->sleep(HZ/22);
1002 /* -----------------------------------------------------------------------
1003 pos is the position that needs animation. pos = [1~18]
1004 ----------------------------------------------------------------------- */
1005 void deleteAnimation(int pos)
1007 int k, w, h, x;
1008 if (pos<1 || pos >18)
1009 return;
1011 rb->lcd_getstringsize("0", &w, &h);
1012 x = (pos==1? 4: LCD_WIDTH - 4 - w);
1014 for (k=0;k<4;k++){
1015 rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
1016 rb->lcd_fillrect(x, Y_1_POS - h -1, w, h);
1017 rb->lcd_set_drawmode(DRMODE_SOLID);
1018 rb->lcd_fillrect(x + (w*k)/8, Y_1_POS - h -1 + (h*k)/8,
1019 (w*(4-k))/4, (h*(4-k))/4);
1020 rb->lcd_update_rect(x, Y_1_POS - h -1, w, h);
1021 rb->sleep(HZ/32);
1025 /* -----------------------------------------------------------------------
1026 result may be one of these formats:
1028 xxxx.xxxx
1029 0.xxxx
1030 0.0000xxxx
1032 formatResult() change result to standard format: 0.xxxx
1033 if result is close to 0, let it be 0;
1034 if result is close to 1, let it be 0.1 and power++;
1035 ----------------------------------------------------------------------- */
1036 void formatResult(void)
1038 int resultsign = SIGN(result);
1039 result = ABS(result);
1040 if(result > MINIMUM ){ /* doesn't check power, might have problem
1041 input wouldn't,
1042 + - * / of two formatted number wouldn't.
1043 only a calculation that makes a formatted
1044 number (0.xxxx) less than MINIMUM in only
1045 one operation */
1047 if (result<1){
1048 while( (int)(result*10) == 0 ){
1049 result *= 10;
1050 power--;
1051 modifier *= 10;
1054 else{ /* result >= 1 */
1055 while( (int)result != 0 ){
1056 result /= 10;
1057 power++;
1058 modifier /= 10;
1060 } /* if result<1 */
1062 if (result > (1-MINIMUM)){
1063 result = 0.1;
1064 power++;
1065 modifier /= 10;
1067 result *= resultsign;
1069 else {
1070 result = 0;
1071 power = 0;
1072 modifier = 0.1;
1076 /* -----------------------------------------------------------------------
1077 result2typingbuf() outputs standard format result to typingbuf.
1078 case SCIENTIFIC_FORMAT, let temppower = 1;
1079 case temppower > 0: print '.' in the middle
1080 case temppower <= 0: print '.' in the begining
1081 ----------------------------------------------------------------------- */
1082 void result2typingbuf(void)
1084 bool haveDot = false;
1085 char tempchar = 0;
1086 int k;
1087 double tempresult = ABS(result); /* positive num makes things simple */
1089 int temppower;
1090 double tempmodifier = 1;
1091 int count;
1093 if(SCIENTIFIC_FORMAT)
1094 temppower = 1; /* output x.xxxx format */
1095 else
1096 temppower = power;
1098 cleartypingbuf();
1100 if(tempresult < MINIMUM){ /* if 0,faster display and avoid complication*/
1101 typingbuf[0] = ' ';
1102 typingbuf[1] = '0';
1104 else{ /* tempresult > 0 */
1105 typingbuf[0] = (SIGN(result)<0)?'-':' ';
1107 typingbufPointer = typingbuf;
1108 if(temppower > 0){
1109 for (k = 0; k<DIGITLEN+1 ; k++){
1110 typingbufPointer++;
1111 if(temppower || *(typingbufPointer-1) == '.'){
1112 count = 0;
1113 tempmodifier = tempmodifier/10;
1114 while( (tempresult-tempmodifier*count) >
1115 (tempmodifier-MINIMUM)){
1116 count++;
1118 tempresult -= tempmodifier*count;
1119 tempresult = ABS(tempresult);
1120 temppower-- ;
1121 *typingbufPointer = count + '0';
1123 else{ /* temppower == 0 */
1124 *typingbufPointer = '.';
1125 haveDot = true;
1127 } /* for */
1129 else{
1130 haveDot = true;
1131 typingbufPointer++; *typingbufPointer = '0';
1132 typingbufPointer++; *typingbufPointer = '.';
1133 for (k = 2; k<DIGITLEN+1 ; k++){
1134 typingbufPointer++;
1135 count = 0;
1136 if ( (-temppower) < (k-1)){
1137 tempmodifier = tempmodifier/10;
1138 while((tempresult-tempmodifier*count)>(tempmodifier-MINIMUM)){
1139 count++;
1142 tempresult -= tempmodifier*count;
1143 tempresult = ABS(tempresult);
1144 temppower-- ;
1146 *typingbufPointer = count + '0';
1149 /* now, typingbufPointer = typingbuf + 16 */
1150 /* backward strip off 0 and '.' */
1151 if (haveDot){
1152 while( (*typingbufPointer == '0') || (*typingbufPointer == '.')){
1153 tempchar = *typingbufPointer;
1154 *typingbufPointer = 0;
1155 typingbufPointer--;
1156 if (tempchar == '.') break;
1159 typingbuf[DIGITLEN+1] = 0;
1160 } /* else tempresult > 0 */
1163 /* -----------------------------------------------------------------------
1164 printResult() generates LCD display.
1165 ----------------------------------------------------------------------- */
1166 void printResult(void)
1168 int k, w, h;
1170 char operbuf[3] = {0, 0, 0};
1172 switch_Status:
1173 switch(calStatus){
1174 case cal_exit:
1175 rb->lcd_clear_display();
1176 rb->splash(HZ/3, "Bye now!");
1177 break;
1178 case cal_error:
1179 clearbuf();
1180 rb->snprintf(buf, 19, "%18s","Error");
1181 break;
1182 case cal_toDo:
1183 clearbuf();
1184 rb->snprintf(buf, 19, "%18s","Coming soon ^_* ");
1185 break;
1187 case cal_normal:
1188 formatResult();
1190 if( power > 1000 ){ /* power -1 > 999 */
1191 calStatus = cal_error;
1192 goto switch_Status;
1194 if (power < -998 ) /* power -1 < -999 */
1195 clearResult(); /* too small, let it be 0 */
1197 result2typingbuf();
1198 clearbuf();
1200 operbuf[0] = oper;
1201 operbuf[1] = ( ABS(memTemp) > MINIMUM )?'M':' ';
1202 operbuf[2] = '\0';
1204 if(SCIENTIFIC_FORMAT){
1205 /* output format: X.XXXX eXXX */
1206 if(power > -98){ /* power-1 >= -99, eXXX or e-XX */
1207 rb->snprintf(buf, 12, "%11s",typingbuf);
1208 for(k=11;k<=14;k++) buf[k] = ' ';
1209 cleartypingbuf();
1210 rb->snprintf(typingbuf, 5, "e%d",power-1);
1211 rb->snprintf(buf+11, 5, "%4s",typingbuf);
1213 else{ /* power-1 <= -100, e-XXX */
1214 rb->snprintf(buf, 12, "%11s",typingbuf);
1215 rb->snprintf(buf+11, 6, "e%d",power-1);
1218 else{
1219 rb->snprintf(buf, 12, "%11s",typingbuf);
1220 } /* if SCIENTIFIC_FORMAT */
1221 break;
1222 case cal_typing:
1223 case cal_dotted:
1224 clearbuf();
1225 operbuf[0] = oper;
1226 operbuf[1] = ( ABS(memTemp) > MINIMUM )?'M':' ';
1227 rb->snprintf(buf, 12, "%11s",typingbuf);
1228 break;
1232 rb->lcd_getstringsize(buf, &w, &h);
1233 rb->screen_clear_area(rb->screens[0], 0, 0, LCD_WIDTH, Y_1_POS - 1);
1234 rb->lcd_putsxy(4, Y_1_POS - h -1, operbuf);
1235 rb->lcd_putsxy(LCD_WIDTH - w - 4, Y_1_POS - h -1, buf);
1236 rb->lcd_update_rect(0, 1, LCD_WIDTH, Y_1_POS);
1239 /* -----------------------------------------------------------------------
1240 Process typing buttons: 1-9, '.', sign
1241 main operand "result" and typingbuf are processed seperately here.
1242 ----------------------------------------------------------------------- */
1243 void typingProcess(void){
1244 switch( CAL_BUTTON ){
1245 case btn_sign:
1246 if (calStatus == cal_typing ||
1247 calStatus == cal_dotted)
1248 typingbuf[0] = (typingbuf[0]=='-')?' ':'-';
1249 result = -result;
1250 break;
1251 case btn_dot:
1252 operInputted = false;
1253 switch(calStatus){
1254 case cal_normal:
1255 clearInput();
1256 *typingbufPointer = '0';
1257 typingbufPointer++;
1258 case cal_typing:
1259 calStatus = cal_dotted;
1260 *typingbufPointer = '.';
1261 if (typingbufPointer != typingbuf+DIGITLEN+1)
1262 typingbufPointer++;
1263 break;
1264 default: /* cal_dotted */
1265 break;
1267 break;
1268 default: /* 0-9 */
1269 operInputted = false;
1270 /* normal,0; normal,1-9; typing,0; typing,1-9 */
1271 switch(calStatus){
1272 case cal_normal:
1273 if(CAL_BUTTON == btn_0 )
1274 break; /* first input is 0, ignore */
1275 clearInput();
1276 /*no operator means start a new calculation*/
1277 if (oper ==' ')
1278 clearOperand();
1279 calStatus = cal_typing;
1280 /* go on typing, no break */
1281 case cal_typing:
1282 case cal_dotted:
1283 switch(CAL_BUTTON){
1284 case btn_0:
1285 *typingbufPointer = '0';
1286 break;
1287 default:
1288 *typingbufPointer=(7+btn_col-3*(btn_row-1))+ '0';
1289 break;
1291 if (typingbufPointer!=typingbuf+DIGITLEN+1){
1292 typingbufPointer++;
1294 {/* result processing */
1295 if (calStatus == cal_typing) power++;
1296 if (CAL_BUTTON != btn_0)
1297 result= result +
1298 SIGN(result)*
1299 (7+btn_col-3*(btn_row-1))*modifier;
1300 modifier /= 10;
1303 else /* last byte always '\0' */
1304 *typingbufPointer = 0;
1305 break;
1306 default: /* cal_error, cal_exit */
1307 break;
1309 break; /* default, 0-9 */
1310 } /* switch( CAL_BUTTON ) */
1313 /* -----------------------------------------------------------------------
1314 Handle delete operation
1315 main operand "result" and typingbuf are processed seperately here.
1316 ----------------------------------------------------------------------- */
1317 void doDelete(void){
1318 deleteAnimation(18);
1319 switch(calStatus){
1320 case cal_dotted:
1321 if (*(typingbufPointer-1) == '.'){
1322 /* if dotted and deleting '.',
1323 change status and delete '.' below */
1324 calStatus = cal_typing;
1326 else{ /* if dotted and not deleting '.',
1327 power stays */
1328 power++; /* counter "power--;" below */
1330 case cal_typing:
1331 typingbufPointer--;
1333 {/* result processing */ /* 0-9, '.' */
1334 /* if deleting '.', do nothing */
1335 if ( *typingbufPointer != '.'){
1336 power--;
1337 modifier *= 10;
1338 result = result - SIGN(result)*
1339 ((*typingbufPointer)- '0')*modifier;
1343 *typingbufPointer = 0;
1345 /* if (only one digit left and it's 0)
1346 or no digit left, change status*/
1347 if ( typingbufPointer == typingbuf+1 ||
1348 ( typingbufPointer == typingbuf+2 &&
1349 *(typingbufPointer-1) == '0' ))
1350 calStatus = cal_normal;
1351 break;
1352 default: /* normal, error, exit */
1353 break;
1356 /* -----------------------------------------------------------------------
1357 Handle buttons on basic screen
1358 ----------------------------------------------------------------------- */
1359 void basicButtonsProcess(void){
1360 switch (btn) {
1361 case CALCULATOR_INPUT:
1362 if (calStatus == cal_error && (CAL_BUTTON != btn_C) ) break;
1363 flashButton();
1364 switch( CAL_BUTTON ){
1365 case btn_MR:
1366 operInputted = false;
1367 result = memTemp; power = memTempPower;
1368 calStatus = cal_normal;
1369 break;
1370 case btn_M:
1371 formatResult();
1372 if (memTemp > MINIMUM)
1373 doAdd(&memTemp, &memTempPower, result, power);
1374 else {
1375 /* if result is too small and memTemp = 0,
1376 doAdd will not add */
1377 memTemp = result;
1378 memTempPower = power;
1380 calStatus = cal_normal;
1381 break;
1383 case btn_C: clearMem(); break;
1384 case btn_CE: clearInput(); break;
1386 case btn_bas:
1387 buttonGroup = sciButtons;
1388 printButtonGroups(buttonGroup);
1389 break;
1391 /* one operand calculation, may be changed to
1392 like sin, cos, log, etc */
1393 case btn_sqr:
1394 case btn_square:
1395 case btn_rec:
1396 formatResult(); /* not necessary, just for safty */
1397 oneOperand();
1398 break;
1400 case_btn_equal: /* F3 shortkey entrance */
1401 case btn_equal:
1402 formatResult();
1403 calStatus = cal_normal;
1404 operInputted = false;
1405 if (oper != ' ') twoOperands();
1406 break;
1408 case btn_div:
1409 case btn_time:
1410 case btn_minus:
1411 case btn_add:
1412 if(!operInputted) {twoOperands(); operInputted = true;}
1413 oper = buttonChar[basicButtons][btn_row][btn_col][0];
1414 #ifdef CALCULATOR_OPERATORS
1415 case_cycle_operators: /* F2 shortkey entrance */
1416 #endif
1417 calStatus = cal_normal;
1418 formatResult();
1419 operand = result;
1420 operandPower = power;
1422 break;
1424 case btn_sign:
1425 case btn_dot:
1426 default: /* 0-9 */
1427 typingProcess();
1428 break;
1429 } /* switch (CAL_BUTTON) */
1430 break;
1432 #ifdef CALCULATOR_OPERATORS
1433 case CALCULATOR_OPERATORS:
1434 if (calStatus == cal_error) break;
1435 if (!operInputted) {twoOperands(); operInputted = true;}
1436 switch (oper){
1437 case ' ':
1438 case '/': oper = '+'; flashButton(); break;
1439 case '+': oper = '-'; flashButton(); break;
1440 case '-': oper = '*'; flashButton(); break;
1441 case '*': oper = '/'; flashButton(); break;
1443 goto case_cycle_operators;
1444 break;
1445 #endif
1447 case CALCULATOR_CALC:
1448 if (calStatus == cal_error) break;
1449 flashButton();
1450 goto case_btn_equal;
1451 break;
1452 default: break;
1454 printResult();
1457 /* -----------------------------------------------------------------------
1458 Handle buttons on scientific screen
1459 ----------------------------------------------------------------------- */
1460 void sciButtonsProcess(void){
1461 switch (btn) {
1462 case CALCULATOR_INPUT:
1463 if (calStatus == cal_error && (CAL_BUTTON != sci_sci) ) break;
1464 flashButton();
1465 switch( CAL_BUTTON ){
1467 case sci_pi:
1468 result = M_PI; power = 0;
1469 calStatus = cal_normal;
1470 break;
1472 case sci_xy: break;
1474 case sci_sci:
1475 buttonGroup = basicButtons;
1476 printButtonGroups(basicButtons);
1477 break;
1479 case sci_fac:
1480 case sci_sin:
1481 case sci_asin:
1482 case sci_cos:
1483 case sci_acos:
1484 case sci_tan:
1485 case sci_atan:
1486 case sci_ln:
1487 case sci_exp:
1488 case sci_log:
1489 formatResult(); /* not necessary, just for safty */
1490 oneOperand();
1491 break;
1493 case btn_sign:
1494 case btn_dot:
1495 default: /* 0-9 */
1496 typingProcess();
1497 break;
1498 } /* switch (CAL_BUTTON) */
1499 break;
1501 #ifdef CALCULATOR_OPERATORS
1502 case CALCULATOR_OPERATORS:
1503 if (calStatus == cal_error) break;
1504 if (!operInputted) {twoOperands(); operInputted = true;}
1505 switch (oper){
1506 case ' ': oper = '+'; break;
1507 case '/': oper = '+'; deleteAnimation(1); break;
1508 case '+': oper = '-'; deleteAnimation(1); break;
1509 case '-': oper = '*'; deleteAnimation(1); break;
1510 case '*': oper = '/'; deleteAnimation(1); break;
1512 calStatus = cal_normal;
1513 formatResult();
1514 operand = result;
1515 operandPower = power;
1516 break;
1517 #endif
1519 case CALCULATOR_CALC:
1520 if (calStatus == cal_error) break;
1521 formatResult();
1522 calStatus = cal_normal;
1523 operInputted = false;
1524 if (oper != ' ') twoOperands();
1525 break;
1526 default: break;
1528 printResult();
1531 /* -----------------------------------------------------------------------
1532 move button index
1533 Invert display new button, invert back previous button
1534 ----------------------------------------------------------------------- */
1535 int handleButton(int button){
1536 switch(button)
1538 case CALCULATOR_INPUT:
1539 case CALCULATOR_CALC:
1540 #ifdef CALCULATOR_INPUT_CALC_PRE
1541 if (lastbtn != CALCULATOR_INPUT_CALC_PRE)
1542 break;
1543 /* no unconditional break; here! */
1544 #endif
1545 #ifdef CALCULATOR_OPERATORS
1546 case CALCULATOR_OPERATORS:
1547 #endif
1548 switch(buttonGroup){
1549 case basicButtons:
1550 basicButtonsProcess();
1551 break;
1552 case sciButtons:
1553 sciButtonsProcess();
1554 break;
1556 break;
1558 #ifdef CALCULATOR_CLEAR
1559 case CALCULATOR_CLEAR:
1560 switch(calStatus){
1561 case cal_typing:
1562 case cal_dotted:
1563 doDelete();
1564 break;
1565 default: /* cal_normal, cal_error, cal_exit */
1566 clearMem();
1567 break;
1569 printResult();
1570 break;
1571 #endif
1572 case CALCULATOR_LEFT:
1573 case CALCULATOR_LEFT | BUTTON_REPEAT:
1574 move_with_wrap_and_shift(
1575 &btn_col, -1, BUTTON_COLS,
1576 &btn_row, 0, BUTTON_ROWS);
1577 break;
1579 case CALCULATOR_RIGHT:
1580 case CALCULATOR_RIGHT | BUTTON_REPEAT:
1581 move_with_wrap_and_shift(
1582 &btn_col, 1, BUTTON_COLS,
1583 &btn_row, 0, BUTTON_ROWS);
1584 break;
1586 #ifdef CALCULATOR_UP
1587 case CALCULATOR_UP:
1588 case CALCULATOR_UP | BUTTON_REPEAT:
1589 move_with_wrap_and_shift(
1590 &btn_row, -1, BUTTON_ROWS,
1591 &btn_col, 0, BUTTON_COLS);
1592 break;
1593 #endif
1594 #ifdef CALCULATOR_DOWN
1595 case CALCULATOR_DOWN:
1596 case CALCULATOR_DOWN | BUTTON_REPEAT:
1597 move_with_wrap_and_shift(
1598 &btn_row, 1, BUTTON_ROWS,
1599 &btn_col, 0, BUTTON_COLS);
1600 break;
1601 #endif
1603 #ifdef CALCULATOR_UP_W_SHIFT
1604 case CALCULATOR_UP_W_SHIFT:
1605 case CALCULATOR_UP_W_SHIFT | BUTTON_REPEAT:
1606 move_with_wrap_and_shift(
1607 &btn_row, -1, BUTTON_ROWS,
1608 &btn_col, -1, BUTTON_COLS);
1609 break;
1610 #endif
1611 #ifdef CALCULATOR_DOWN_W_SHIFT
1612 case CALCULATOR_DOWN_W_SHIFT:
1613 case CALCULATOR_DOWN_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_LEFT_W_SHIFT
1620 case CALCULATOR_LEFT_W_SHIFT:
1621 case CALCULATOR_LEFT_W_SHIFT | BUTTON_REPEAT:
1622 move_with_wrap_and_shift(
1623 &btn_col, -1, BUTTON_COLS,
1624 &btn_row, -1, BUTTON_ROWS);
1625 break;
1626 #endif
1627 #ifdef CALCULATOR_RIGHT_W_SHIFT
1628 case CALCULATOR_RIGHT_W_SHIFT:
1629 case CALCULATOR_RIGHT_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_RC_QUIT
1636 case CALCULATOR_RC_QUIT:
1637 #endif
1638 case CALCULATOR_QUIT:
1639 return -1;
1642 return 0;
1644 prev_btn_row = btn_row;
1645 prev_btn_col = btn_col;
1648 /* -----------------------------------------------------------------------
1649 Main();
1650 ----------------------------------------------------------------------- */
1651 enum plugin_status plugin_start(const void* parameter)
1653 (void)parameter;
1655 /* now go ahead and have fun! */
1657 cal_initial();
1659 while (calStatus != cal_exit ) {
1660 btn = rb->button_get_w_tmo(HZ/2);
1661 #ifdef HAVE_TOUCHSCREEN
1662 if(btn & BUTTON_TOUCHSCREEN)
1664 struct ts_raster_result res;
1665 if(touchscreen_map_raster(&calc_raster, rb->button_get_data() >> 16,
1666 rb->button_get_data() & 0xffff, &res) == 1)
1668 btn_row = res.y;
1669 btn_col = res.x;
1670 drawButtons(buttonGroup);
1671 drawLines();
1673 rb->lcd_update();
1675 prev_btn_row = btn_row;
1676 prev_btn_col = btn_col;
1677 if(btn & BUTTON_REL)
1679 btn = CALCULATOR_INPUT;
1680 switch(buttonGroup){
1681 case basicButtons:
1682 basicButtonsProcess();
1683 break;
1684 case sciButtons:
1685 sciButtonsProcess();
1686 break;
1688 btn = BUTTON_TOUCHSCREEN;
1692 #endif
1693 if (handleButton(btn) == -1)
1695 calStatus = cal_exit;
1696 printResult();
1698 else
1700 drawButtons(buttonGroup);
1701 drawLines();
1704 rb->lcd_update();
1706 if(rb->default_event_handler(btn) == SYS_USB_CONNECTED)
1707 return PLUGIN_USB_CONNECTED;
1709 if (btn != BUTTON_NONE)
1710 lastbtn = btn;
1711 } /* while (calStatus != cal_exit ) */
1713 rb->button_clear_queue();
1714 return PLUGIN_OK;
1717 #endif /* #ifdef HAVE_LCD_BITMAP */