Fix 'make fullinstall'
[kugel-rb.git] / apps / plugins / calculator.c
blob6414de645c67883b0468b50fbc413ee43f2a89f1
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 #else
346 #error No keymap defined!
347 #endif
349 #ifdef HAVE_TOUCHSCREEN
350 #ifndef CALCULATOR_LEFT
351 #define CALCULATOR_LEFT BUTTON_MIDLEFT
352 #endif
353 #ifndef CALCULATOR_RIGHT
354 #define CALCULATOR_RIGHT BUTTON_MIDRIGHT
355 #endif
356 #ifndef CALCULATOR_UP
357 #define CALCULATOR_UP BUTTON_TOPMIDDLE
358 #endif
359 #ifndef CALCULATOR_DOWN
360 #define CALCULATOR_DOWN BUTTON_BOTTOMMIDDLE
361 #endif
362 #ifndef CALCULATOR_CALC
363 #define CALCULATOR_CALC BUTTON_BOTTOMRIGHT
364 #endif
365 #ifndef CALCULATOR_INPUT
366 #define CALCULATOR_INPUT BUTTON_CENTER
367 #endif
368 #ifndef CALCULATOR_CLEAR
369 #define CALCULATOR_CLEAR BUTTON_TOPRIGHT
370 #endif
372 #include "lib/touchscreen.h"
373 static struct ts_raster calc_raster = { X_0_POS, Y_1_POS, BUTTON_COLS*REC_WIDTH, BUTTON_ROWS*REC_HEIGHT, REC_WIDTH, REC_HEIGHT };
374 #endif
376 enum {
377 basicButtons,
378 sciButtons
379 } buttonGroup;
381 unsigned char* buttonChar[2][5][5] = {
382 { { "MR" , "M+" , "2nd" , "CE" , "C" },
383 { "7" , "8" , "9" , "/" , "sqr" },
384 { "4" , "5" , "6" , "*" , "x^2" },
385 { "1" , "2" , "3" , "-" , "1/x" },
386 { "0" , "+/-", "." , "+" , "=" } },
388 { { "n!" , "PI" , "1st" , "sin" , "asi" },
389 { "7" , "8" , "9" , "cos" , "aco" },
390 { "4" , "5" , "6" , "tan" , "ata" },
391 { "1" , "2" , "3" , "ln" , "e^x" },
392 { "0" , "+/-", "." , "log" , "x^y" } }
395 enum { btn_MR , btn_M , btn_bas , btn_CE , btn_C ,
396 btn_7 , btn_8 , btn_9 , btn_div , btn_sqr ,
397 btn_4 , btn_5 , btn_6 , btn_time , btn_square ,
398 btn_1 , btn_2 , btn_3 , btn_minus , btn_rec ,
399 btn_0 , btn_sign , btn_dot , btn_add , btn_equal
402 enum { sci_fac, sci_pi , sci_sci , sci_sin , sci_asin ,
403 sci_7 , sci_8 , sci_9 , sci_cos , sci_acos ,
404 sci_4 , sci_5 , sci_6 , sci_tan , sci_atan ,
405 sci_1 , sci_2 , sci_3 , sci_ln , sci_exp ,
406 sci_0 , sci_sign , sci_dot , sci_log , sci_xy
409 #define MINIMUM 0.000000000001 /* e-12 */
410 /* ^ ^ ^ ^ */
411 /* 123456789abcdef */
413 #define DIGITLEN 10 /* must <= 10 */
414 #define SCIENTIFIC_FORMAT ( power < -(DIGITLEN-3) || power > (DIGITLEN))
415 /* 0.000 00000 0001 */
416 /* ^ ^ ^ ^ ^ ^ */
417 /* DIGITLEN 12345 6789a bcdef */
418 /* power 12 34567 89abc def */
419 /* 10^- 123 45678 9abcd ef */
421 unsigned char buf[19];/* 18 bytes of output line,
422 buf[0] is operator
423 buf[1] = 'M' if memTemp is not 0
424 buf[2] = ' '
426 if SCIENTIFIC_FORMAT
427 buf[2]-buf[12] or buf[3]-buf[13] = result;
428 format X.XXXXXXXX
429 buf[13] or buf[14] -buf[17] = power;
430 format eXXX or e-XXX
431 else
432 buf[3]-buf[6] = ' ';
433 buf[7]-buf[17] = result;
435 buf[18] = '\0' */
437 unsigned char typingbuf[DIGITLEN+2];/* byte 0 is sign or ' ',
438 byte 1~DIGITLEN are num and '.'
439 byte (DIGITLEN+1) is '\0' */
440 unsigned char* typingbufPointer = typingbuf;
442 double result = 0; /* main operand, format 0.xxxxx */
443 int power = 0; /* 10^power */
444 double modifier = 0.1; /* position of next input */
445 double operand = 0; /* second operand, format 0.xxxxx */
446 int operandPower = 0; /* 10^power of second operand */
447 char oper = ' '; /* operators: + - * / */
448 bool operInputted = false; /* false: do calculation first and
449 replace current oper
450 true: just replace current oper */
452 double memTemp = 0; /* temp memory */
453 int memTempPower = 0; /* 10^^power of memTemp */
455 int btn_row, btn_col; /* current position index for button */
456 int prev_btn_row, prev_btn_col; /* previous cursor position */
457 #define CAL_BUTTON (btn_row*5+btn_col)
459 int btn = BUTTON_NONE;
460 int lastbtn = BUTTON_NONE;
462 /* Status of calculator */
463 enum {cal_normal, /* 0, normal status, display result */
464 cal_typing, /* 1, currently typing, dot hasn't been typed */
465 cal_dotted, /* 2, currently typing, dot already has been typed. */
466 cal_error,
467 cal_exit,
468 cal_toDo
469 } calStatus;
471 /* constant table for CORDIC algorithm */
472 double cordicTable[51][2]= {
473 /* pow(2,0) - pow(2,-50) atan(pow(2,0) - atan(pow(2,-50) */
474 {1e+00, 7.853981633974483e-01},
475 {5e-01, 4.636476090008061e-01},
476 {2.5e-01, 2.449786631268641e-01},
477 {1.25e-01, 1.243549945467614e-01},
478 {6.25e-02, 6.241880999595735e-02},
479 {3.125e-02, 3.123983343026828e-02},
480 {1.5625e-02, 1.562372862047683e-02},
481 {7.8125e-03, 7.812341060101111e-03},
482 {3.90625e-03, 3.906230131966972e-03},
483 {1.953125e-03, 1.953122516478819e-03},
484 {9.765625e-04, 9.765621895593195e-04},
485 {4.8828125e-04, 4.882812111948983e-04},
486 {2.44140625e-04, 2.441406201493618e-04},
487 {1.220703125e-04, 1.220703118936702e-04},
488 {6.103515625e-05, 6.103515617420877e-05},
489 {3.0517578125e-05, 3.051757811552610e-05},
490 {1.52587890625e-05, 1.525878906131576e-05},
491 {7.62939453125e-06, 7.629394531101970e-06},
492 {3.814697265625e-06, 3.814697265606496e-06},
493 {1.9073486328125e-06, 1.907348632810187e-06},
494 {9.5367431640625e-07, 9.536743164059608e-07},
495 {4.76837158203125e-07, 4.768371582030888e-07},
496 {2.384185791015625e-07, 2.384185791015580e-07},
497 {1.1920928955078125e-07, 1.192092895507807e-07},
498 {5.9604644775390625e-08, 5.960464477539055e-08},
499 {2.98023223876953125e-08, 2.980232238769530e-08},
500 {1.490116119384765625e-08, 1.490116119384765e-08},
501 {7.450580596923828125e-09, 7.450580596923828e-09},
502 {3.7252902984619140625e-09, 3.725290298461914e-09},
503 {1.86264514923095703125e-09, 1.862645149230957e-09},
504 {9.31322574615478515625e-10, 9.313225746154785e-10},
505 {4.656612873077392578125e-10, 4.656612873077393e-10},
506 {2.3283064365386962890625e-10, 2.328306436538696e-10},
507 {1.16415321826934814453125e-10, 1.164153218269348e-10},
508 {5.82076609134674072265625e-11, 5.820766091346741e-11},
509 {2.910383045673370361328125e-11, 2.910383045673370e-11},
510 {1.4551915228366851806640625e-11, 1.455191522836685e-11},
511 {7.2759576141834259033203125e-12, 7.275957614183426e-12},
512 {3.63797880709171295166015625e-12, 3.637978807091713e-12},
513 {1.818989403545856475830078125e-12, 1.818989403545856e-12},
514 {9.094947017729282379150390625e-13, 9.094947017729282e-13},
515 {4.5474735088646411895751953125e-13, 4.547473508864641e-13},
516 {2.27373675443232059478759765625e-13, 2.273736754432321e-13},
517 {1.136868377216160297393798828125e-13, 1.136868377216160e-13},
518 {5.684341886080801486968994140625e-14, 5.684341886080801e-14},
519 {2.8421709430404007434844970703125e-14, 2.842170943040401e-14},
520 {1.42108547152020037174224853515625e-14, 1.421085471520200e-14},
521 {7.10542735760100185871124267578125e-15, 7.105427357601002e-15},
522 {3.552713678800500929355621337890625e-15, 3.552713678800501e-15},
523 {1.7763568394002504646778106689453125e-15, 1.776356839400250e-15},
524 {8.8817841970012523233890533447265625e-16, 8.881784197001252e-16}
527 void doMultiple(double* operandOne, int* powerOne,
528 double operandTwo, int powerTwo);
529 void doAdd (double* operandOne, int* powerOne,
530 double operandTwo, int powerTwo);
531 void printResult(void);
532 void formatResult(void);
533 void oneOperand(void);
535 void drawLines(void);
536 void drawButtons(int group);
538 /* -----------------------------------------------------------------------
539 Handy funtions
540 ----------------------------------------------------------------------- */
541 void cleartypingbuf(void)
543 int k;
544 for( k=1; k<=(DIGITLEN+1); k++)
545 typingbuf[k] = 0;
546 typingbuf[0] = ' ';
547 typingbufPointer = typingbuf+1;
549 void clearbuf(void)
551 int k;
552 for(k=0;k<18;k++)
553 buf[k]=' ';
554 buf[18] = 0;
556 void clearResult(void)
558 result = 0;
559 power = 0;
560 modifier = 0.1;
563 void clearInput(void)
565 calStatus = cal_normal;
566 clearResult();
567 cleartypingbuf();
568 rb->lcd_clear_display();
569 drawButtons(buttonGroup);
570 drawLines();
573 void clearOperand(void)
575 operand = 0;
576 operandPower = 0;
579 void clearMemTemp(void)
581 memTemp = 0;
582 memTempPower = 0;
585 void clearOper(void)
587 oper = ' ';
588 operInputted = false;
591 void clearMem(void)
593 clearInput();
594 clearMemTemp();
595 clearOperand();
596 clearOper();
597 btn = BUTTON_NONE;
600 void switchOperands(void)
602 double tempr = operand;
603 int tempp = operandPower;
604 operand = result;
605 operandPower = power;
606 result = tempr;
607 power = tempp;
610 void drawLines(void)
612 int i;
613 rb->lcd_hline(0, LCD_WIDTH, Y_1_POS-1);
614 for (i = 0; i < 5 ; i++)
615 rb->lcd_hline(0, LCD_WIDTH, Y_1_POS+i*REC_HEIGHT);
616 for (i = 0; i < 4 ; i++)
617 rb->lcd_vline(X_1_POS+i*REC_WIDTH, Y_1_POS, LCD_HEIGHT);
620 void drawButtons(int group)
622 int i, j, w, h;
623 for (i = 0; i <= 4; i++){
624 for (j = 0; j <= 4; j++){
625 rb->lcd_getstringsize( buttonChar[group][i][j],&w,&h);
626 if (i == btn_row && j == btn_col) /* selected item */
627 rb->lcd_set_drawmode(DRMODE_SOLID);
628 else
629 rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
630 rb->lcd_fillrect( X_0_POS + j*REC_WIDTH,
631 Y_1_POS + i*REC_HEIGHT,
632 REC_WIDTH, REC_HEIGHT+1);
633 if (i == btn_row && j == btn_col) /* selected item */
634 rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
635 else
636 rb->lcd_set_drawmode(DRMODE_SOLID);
637 rb->lcd_putsxy( X_0_POS + j*REC_WIDTH + (REC_WIDTH - w)/2,
638 Y_1_POS + i*REC_HEIGHT + (REC_HEIGHT - h)/2 + 1,
639 buttonChar[group][i][j] );
642 rb->lcd_set_drawmode(DRMODE_SOLID);
645 /* -----------------------------------------------------------------------
646 Initiate calculator
647 ----------------------------------------------------------------------- */
648 void cal_initial (void)
650 int w,h;
652 rb->lcd_getstringsize("A",&w,&h);
653 if (h >= REC_HEIGHT)
654 rb->lcd_setfont(FONT_SYSFIXED);
656 rb->lcd_clear_display();
658 #ifdef CALCULATOR_OPERATORS
659 /* basic operators are available through separate button */
660 buttonGroup = sciButtons;
661 #else
662 buttonGroup = basicButtons;
663 #endif
665 /* initially, invert button "5" */
666 btn_row = 2;
667 btn_col = 1;
668 prev_btn_row = btn_row;
669 prev_btn_col = btn_col;
670 drawButtons(buttonGroup);
671 drawLines();
672 rb->lcd_update();
674 /* initial mem and output display*/
675 clearMem();
676 printResult();
678 /* clear button queue */
679 rb->button_clear_queue();
682 /* -----------------------------------------------------------------------
683 mySqrt uses Heron's algorithm, which is the Newtone-Raphson algorhitm
684 in it's private case for sqrt.
685 Thanks BlueChip for his intro text and Dave Straayer for the actual name.
686 ----------------------------------------------------------------------- */
687 double mySqrt(double square)
689 int k = 0;
690 double temp = 0;
691 double root= ABS(square+1)/2;
693 while( ABS(root - temp) > MINIMUM ){
694 temp = root;
695 root = (square/temp + temp)/2;
696 k++;
697 if (k>10000) return 0;
700 return root;
702 /* -----------------------------------------------------------------------
703 transcendFunc uses CORDIC (COordinate Rotation DIgital Computer) method
704 transcendFunc can do sin,cos,log,exp
705 input parameter is angle
706 ----------------------------------------------------------------------- */
707 void transcendFunc(char* func, double* tt, int* ttPower)
709 double t = (*tt)*M_PI/180; int tPower = *ttPower;
710 int sign = 1;
711 int n = 50; /* n <=50, tables are all <= 50 */
712 int j;
713 double x,y,z,xt,yt,zt;
715 if (tPower < -998) {
716 calStatus = cal_normal;
717 return;
719 if (tPower > 8) {
720 calStatus = cal_error;
721 return;
723 *ttPower = 0;
724 calStatus = cal_normal;
726 if( func[0] =='s' || func[0] =='S'|| func[0] =='t' || func[0] =='T')
727 sign = SIGN(t);
728 else {
729 /* if( func[0] =='c' || func[0] =='C') */
730 sign = 1;
732 t = ABS(t);
734 while (tPower > 0){
735 t *= 10;
736 tPower--;
738 while (tPower < 0) {
739 t /= 10;
740 tPower++;
742 j = 0;
743 while (t > j*M_TWOPI) {j++;}
744 t -= (j-1)*M_TWOPI;
745 if (M_PI_2 < t && t < 3*M_PI_2){
746 t = M_PI - t;
747 if (func[0] =='c' || func[0] =='C')
748 sign = -1;
749 else if (func[0] =='t' || func[0] =='T')
750 t*=-1;
752 else if ( 3*M_PI_2 <= t && t <= M_TWOPI)
753 t -= M_TWOPI;
755 x = 0.60725293500888; y = 0; z = t;
756 for (j=1;j<n+2;j++){
757 xt = x - SIGN(z) * y*cordicTable[j-1][0];
758 yt = y + SIGN(z) * x*cordicTable[j-1][0];
759 zt = z - SIGN(z) * cordicTable[j-1][1];
760 x = xt;
761 y=yt;
762 z=zt;
764 if( func[0] =='s' || func[0] =='S') {
765 *tt = sign*y;
766 return;
768 else if( func[0] =='c' || func[0] =='C') {
769 *tt = sign*x;
770 return;
772 else /*if( func[0] =='t' || func[0] =='T')*/ {
773 if(t==M_PI_2||t==-M_PI_2){
774 calStatus = cal_error;
775 return;
777 else{
778 *tt = sign*(y/x);
779 return;
784 /* -----------------------------------------------------------------------
785 add in scientific number format
786 ----------------------------------------------------------------------- */
787 void doAdd (double* operandOne, int* powerOne,
788 double operandTwo, int powerTwo)
790 if ( *powerOne >= powerTwo ){
791 if (*powerOne - powerTwo <= DIGITLEN+1){
792 while (powerTwo < *powerOne){
793 operandTwo /=10;
794 powerTwo++;
796 *operandOne += operandTwo;
798 /*do nothing if operandTwo is too small*/
800 else{
801 if (powerTwo - *powerOne <= DIGITLEN+1){
802 while(powerTwo > *powerOne){
803 *operandOne /=10;
804 (*powerOne)++;
806 (*operandOne) += operandTwo;
808 else{/* simply copy operandTwo if operandOne is too small */
809 *operandOne = operandTwo;
810 *powerOne = powerTwo;
814 /* -----------------------------------------------------------------------
815 multiple in scientific number format
816 ----------------------------------------------------------------------- */
817 void doMultiple(double* operandOne, int* powerOne,
818 double operandTwo, int powerTwo)
820 (*operandOne) *= operandTwo;
821 (*powerOne) += powerTwo;
824 /* -----------------------------------------------------------------------
825 Handles all one operand calculations
826 ----------------------------------------------------------------------- */
827 void oneOperand(void)
829 int k = 0;
830 if (buttonGroup == basicButtons){
831 switch(CAL_BUTTON){
832 case btn_sqr:
833 if (result<0)
834 calStatus = cal_error;
835 else{
836 if (power%2 == 1){
837 result = (mySqrt(result*10))/10;
838 power = (power+1) / 2;
840 else{
841 result = mySqrt(result);
842 power = power / 2;
844 calStatus = cal_normal;
846 break;
847 case btn_square:
848 power *= 2;
849 result *= result;
850 calStatus = cal_normal;
851 break;
853 case btn_rec:
854 if (result==0)
855 calStatus = cal_error;
856 else{
857 power = -power;
858 result = 1/result;
859 calStatus = cal_normal;
861 break;
862 default:
863 calStatus = cal_toDo;
864 break; /* just for the safety */
867 else{ /* sciButtons */
868 switch(CAL_BUTTON){
869 case sci_sin:
870 transcendFunc("sin", &result, &power);
871 break;
872 case sci_cos:
873 transcendFunc("cos", &result, &power);
874 break;
875 case sci_tan:
876 transcendFunc("tan", &result, &power);
877 break;
878 case sci_fac:
879 if (power<0 || power>8 || result<0 )
880 calStatus = cal_error;
881 else if(result == 0) {
882 result = 1;
883 power = 0;
885 else{
886 while(power > 0) {
887 result *= 10;
888 power--;
890 if ( ( result - (int)result) > MINIMUM )
891 calStatus = cal_error;
892 else {
893 k = result; result = 1;
894 while (k > 1){
895 doMultiple(&result, &power, k, 0);
896 formatResult();
897 k--;
899 calStatus = cal_normal;
902 break;
903 default:
904 calStatus = cal_toDo;
905 break; /* just for the safety */
911 /* -----------------------------------------------------------------------
912 Handles all two operands calculations
913 ----------------------------------------------------------------------- */
914 void twoOperands(void)
916 switch(oper){
917 case '-':
918 doAdd(&operand, &operandPower, -result, power);
919 break;
920 case '+':
921 doAdd(&operand, &operandPower, result, power);
922 break;
923 case '*':
924 doMultiple(&operand, &operandPower, result, power);
925 break;
926 case '/':
927 if ( ABS(result) > MINIMUM ){
928 doMultiple(&operand, &operandPower, 1/result, -power);
930 else
931 calStatus = cal_error;
932 break;
933 default: /* ' ' */
934 switchOperands(); /* counter switchOperands() below */
935 break;
936 } /* switch(oper) */
937 switchOperands();
938 clearOper();
941 /* First, increases *dimen1 by dimen1_delta modulo dimen1_modulo.
942 If dimen1 wraps, increases *dimen2 by dimen2_delta modulo dimen2_modulo.
944 static void move_with_wrap_and_shift(
945 int *dimen1, int dimen1_delta, int dimen1_modulo,
946 int *dimen2, int dimen2_delta, int dimen2_modulo)
948 bool wrapped = false;
950 *dimen1 += dimen1_delta;
951 if (*dimen1 < 0)
953 *dimen1 = dimen1_modulo - 1;
954 wrapped = true;
956 else if (*dimen1 >= dimen1_modulo)
958 *dimen1 = 0;
959 wrapped = true;
962 if (wrapped)
964 /* Make the dividend always positive to be sure about the result.
965 Adding dimen2_modulo does not change it since we do it modulo. */
966 *dimen2 = (*dimen2 + dimen2_modulo + dimen2_delta) % dimen2_modulo;
970 /* -----------------------------------------------------------------------
971 Print buttons when switching 1st and 2nd
972 int group = {basicButtons, sciButtons}
973 ----------------------------------------------------------------------- */
974 void printButtonGroups(int group)
976 drawButtons(group);
977 drawLines();
978 rb->lcd_update();
980 /* -----------------------------------------------------------------------
981 flash the currently marked button
982 ----------------------------------------------------------------------- */
983 void flashButton(void)
985 int k, w, h;
986 for (k=2;k>0;k--)
988 rb->lcd_getstringsize( buttonChar[buttonGroup][btn_row][btn_col],&w,&h);
989 rb->lcd_set_drawmode(DRMODE_SOLID|(k==1) ? 0 : DRMODE_INVERSEVID);
990 rb->lcd_fillrect( X_0_POS + btn_col*REC_WIDTH + 1,
991 Y_1_POS + btn_row*REC_HEIGHT + 1,
992 REC_WIDTH - 1, REC_HEIGHT - 1);
993 rb->lcd_putsxy( X_0_POS + btn_col*REC_WIDTH + (REC_WIDTH - w)/2,
994 Y_1_POS + btn_row*REC_HEIGHT + (REC_HEIGHT - h)/2 +1,
995 buttonChar[buttonGroup][btn_row][btn_col] );
996 rb->lcd_update_rect( X_0_POS + btn_col*REC_WIDTH + 1,
997 Y_1_POS + btn_row*REC_HEIGHT + 1,
998 REC_WIDTH - 1, REC_HEIGHT - 1);
1000 if (k!= 1)
1001 rb->sleep(HZ/22);
1006 /* -----------------------------------------------------------------------
1007 pos is the position that needs animation. pos = [1~18]
1008 ----------------------------------------------------------------------- */
1009 void deleteAnimation(int pos)
1011 int k;
1012 if (pos<1 || pos >18)
1013 return;
1014 pos--;
1015 rb->lcd_fillrect(1+pos*6, TEXT_1_POS, 6, 8);
1016 rb->lcd_update_rect(1+pos*6, TEXT_1_POS, 6, 8);
1018 for (k=1;k<=4;k++){
1019 rb->sleep(HZ/32);
1020 rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
1021 rb->lcd_fillrect(1+pos*6, TEXT_1_POS, 6, 8);
1022 rb->lcd_set_drawmode(DRMODE_SOLID);
1023 rb->lcd_fillrect(1+pos*6+1+k, TEXT_1_POS+k,
1024 (5-2*k)>0?(5-2*k):1, (7-2*k)>0?(7-2*k):1 );
1025 rb->lcd_update_rect(1+pos*6, TEXT_1_POS, 6, 8);
1030 /* -----------------------------------------------------------------------
1031 result may be one of these formats:
1033 xxxx.xxxx
1034 0.xxxx
1035 0.0000xxxx
1037 formatResult() change result to standard format: 0.xxxx
1038 if result is close to 0, let it be 0;
1039 if result is close to 1, let it be 0.1 and power++;
1040 ----------------------------------------------------------------------- */
1041 void formatResult(void)
1043 int resultsign = SIGN(result);
1044 result = ABS(result);
1045 if(result > MINIMUM ){ /* doesn't check power, might have problem
1046 input wouldn't,
1047 + - * / of two formatted number wouldn't.
1048 only a calculation that makes a formatted
1049 number (0.xxxx) less than MINIMUM in only
1050 one operation */
1052 if (result<1){
1053 while( (int)(result*10) == 0 ){
1054 result *= 10;
1055 power--;
1056 modifier *= 10;
1059 else{ /* result >= 1 */
1060 while( (int)result != 0 ){
1061 result /= 10;
1062 power++;
1063 modifier /= 10;
1065 } /* if result<1 */
1067 if (result > (1-MINIMUM)){
1068 result = 0.1;
1069 power++;
1070 modifier /= 10;
1072 result *= resultsign;
1074 else {
1075 result = 0;
1076 power = 0;
1077 modifier = 0.1;
1081 /* -----------------------------------------------------------------------
1082 result2typingbuf() outputs standard format result to typingbuf.
1083 case SCIENTIFIC_FORMAT, let temppower = 1;
1084 case temppower > 0: print '.' in the middle
1085 case temppower <= 0: print '.' in the begining
1086 ----------------------------------------------------------------------- */
1087 void result2typingbuf(void)
1089 bool haveDot = false;
1090 char tempchar = 0;
1091 int k;
1092 double tempresult = ABS(result); /* positive num makes things simple */
1094 int temppower;
1095 double tempmodifier = 1;
1096 int count;
1098 if(SCIENTIFIC_FORMAT)
1099 temppower = 1; /* output x.xxxx format */
1100 else
1101 temppower = power;
1103 cleartypingbuf();
1105 if(tempresult < MINIMUM){ /* if 0,faster display and avoid complication*/
1106 typingbuf[0] = ' ';
1107 typingbuf[1] = '0';
1109 else{ /* tempresult > 0 */
1110 typingbuf[0] = (SIGN(result)<0)?'-':' ';
1112 typingbufPointer = typingbuf;
1113 if(temppower > 0){
1114 for (k = 0; k<DIGITLEN+1 ; k++){
1115 typingbufPointer++;
1116 if(temppower || *(typingbufPointer-1) == '.'){
1117 count = 0;
1118 tempmodifier = tempmodifier/10;
1119 while( (tempresult-tempmodifier*count) >
1120 (tempmodifier-MINIMUM)){
1121 count++;
1123 tempresult -= tempmodifier*count;
1124 tempresult = ABS(tempresult);
1125 temppower-- ;
1126 *typingbufPointer = count + '0';
1128 else{ /* temppower == 0 */
1129 *typingbufPointer = '.';
1130 haveDot = true;
1132 } /* for */
1134 else{
1135 haveDot = true;
1136 typingbufPointer++; *typingbufPointer = '0';
1137 typingbufPointer++; *typingbufPointer = '.';
1138 for (k = 2; k<DIGITLEN+1 ; k++){
1139 typingbufPointer++;
1140 count = 0;
1141 if ( (-temppower) < (k-1)){
1142 tempmodifier = tempmodifier/10;
1143 while((tempresult-tempmodifier*count)>(tempmodifier-MINIMUM)){
1144 count++;
1147 tempresult -= tempmodifier*count;
1148 tempresult = ABS(tempresult);
1149 temppower-- ;
1151 *typingbufPointer = count + '0';
1154 /* now, typingbufPointer = typingbuf + 16 */
1155 /* backward strip off 0 and '.' */
1156 if (haveDot){
1157 while( (*typingbufPointer == '0') || (*typingbufPointer == '.')){
1158 tempchar = *typingbufPointer;
1159 *typingbufPointer = 0;
1160 typingbufPointer--;
1161 if (tempchar == '.') break;
1164 typingbuf[DIGITLEN+1] = 0;
1165 } /* else tempresult > 0 */
1168 /* -----------------------------------------------------------------------
1169 printResult() generates LCD display.
1170 ----------------------------------------------------------------------- */
1171 void printResult(void)
1173 int k, w, h;
1175 char operbuf[3] = {0, 0, 0};
1177 switch_Status:
1178 switch(calStatus){
1179 case cal_exit:
1180 rb->lcd_clear_display();
1181 rb->splash(HZ/3, "Bye now!");
1182 break;
1183 case cal_error:
1184 clearbuf();
1185 rb->snprintf(buf, 19, "%18s","Error");
1186 break;
1187 case cal_toDo:
1188 clearbuf();
1189 rb->snprintf(buf, 19, "%18s","Coming soon ^_* ");
1190 break;
1192 case cal_normal:
1193 formatResult();
1195 if( power > 1000 ){ /* power -1 > 999 */
1196 calStatus = cal_error;
1197 goto switch_Status;
1199 if (power < -998 ) /* power -1 < -999 */
1200 clearResult(); /* too small, let it be 0 */
1202 result2typingbuf();
1203 clearbuf();
1205 operbuf[0] = oper;
1206 operbuf[1] = ( ABS(memTemp) > MINIMUM )?'M':' ';
1207 operbuf[2] = '\0';
1209 if(SCIENTIFIC_FORMAT){
1210 /* output format: X.XXXX eXXX */
1211 if(power > -98){ /* power-1 >= -99, eXXX or e-XX */
1212 rb->snprintf(buf, 12, "%11s",typingbuf);
1213 for(k=11;k<=14;k++) buf[k] = ' ';
1214 cleartypingbuf();
1215 rb->snprintf(typingbuf, 5, "e%d",power-1);
1216 rb->snprintf(buf+11, 5, "%4s",typingbuf);
1218 else{ /* power-1 <= -100, e-XXX */
1219 rb->snprintf(buf, 12, "%11s",typingbuf);
1220 rb->snprintf(buf+11, 6, "e%d",power-1);
1223 else{
1224 rb->snprintf(buf, 12, "%11s",typingbuf);
1225 } /* if SCIENTIFIC_FORMAT */
1226 break;
1227 case cal_typing:
1228 case cal_dotted:
1229 clearbuf();
1230 operbuf[0] = oper;
1231 operbuf[1] = ( ABS(memTemp) > MINIMUM )?'M':' ';
1232 rb->snprintf(buf, 12, "%11s",typingbuf);
1233 break;
1237 rb->lcd_getstringsize(buf, &w, &h);
1238 rb->screen_clear_area(rb->screens[0], 0, 0, LCD_WIDTH, REC_HEIGHT-1);
1239 rb->lcd_putsxy(4, Y_1_POS - h -1, operbuf);
1240 rb->lcd_putsxy(LCD_WIDTH - w - 4, Y_1_POS - h -1, buf);
1241 rb->lcd_update_rect(0, 1, LCD_WIDTH, Y_1_POS);
1244 /* -----------------------------------------------------------------------
1245 Process typing buttons: 1-9, '.', sign
1246 main operand "result" and typingbuf are processed seperately here.
1247 ----------------------------------------------------------------------- */
1248 void typingProcess(void){
1249 switch( CAL_BUTTON ){
1250 case btn_sign:
1251 if (calStatus == cal_typing ||
1252 calStatus == cal_dotted)
1253 typingbuf[0] = (typingbuf[0]=='-')?' ':'-';
1254 result = -result;
1255 break;
1256 case btn_dot:
1257 operInputted = false;
1258 switch(calStatus){
1259 case cal_normal:
1260 clearInput();
1261 *typingbufPointer = '0';
1262 typingbufPointer++;
1263 case cal_typing:
1264 calStatus = cal_dotted;
1265 *typingbufPointer = '.';
1266 if (typingbufPointer != typingbuf+DIGITLEN+1)
1267 typingbufPointer++;
1268 break;
1269 default: /* cal_dotted */
1270 break;
1272 break;
1273 default: /* 0-9 */
1274 operInputted = false;
1275 /* normal,0; normal,1-9; typing,0; typing,1-9 */
1276 switch(calStatus){
1277 case cal_normal:
1278 if(CAL_BUTTON == btn_0 )
1279 break; /* first input is 0, ignore */
1280 clearInput();
1281 /*no operator means start a new calculation*/
1282 if (oper ==' ')
1283 clearOperand();
1284 calStatus = cal_typing;
1285 /* go on typing, no break */
1286 case cal_typing:
1287 case cal_dotted:
1288 switch(CAL_BUTTON){
1289 case btn_0:
1290 *typingbufPointer = '0';
1291 break;
1292 default:
1293 *typingbufPointer=(7+btn_col-3*(btn_row-1))+ '0';
1294 break;
1296 if (typingbufPointer!=typingbuf+DIGITLEN+1){
1297 typingbufPointer++;
1299 {/* result processing */
1300 if (calStatus == cal_typing) power++;
1301 if (CAL_BUTTON != btn_0)
1302 result= result +
1303 SIGN(result)*
1304 (7+btn_col-3*(btn_row-1))*modifier;
1305 modifier /= 10;
1308 else /* last byte always '\0' */
1309 *typingbufPointer = 0;
1310 break;
1311 default: /* cal_error, cal_exit */
1312 break;
1314 break; /* default, 0-9 */
1315 } /* switch( CAL_BUTTON ) */
1318 /* -----------------------------------------------------------------------
1319 Handle delete operation
1320 main operand "result" and typingbuf are processed seperately here.
1321 ----------------------------------------------------------------------- */
1322 void doDelete(void){
1323 deleteAnimation(18);
1324 switch(calStatus){
1325 case cal_dotted:
1326 if (*(typingbufPointer-1) == '.'){
1327 /* if dotted and deleting '.',
1328 change status and delete '.' below */
1329 calStatus = cal_typing;
1331 else{ /* if dotted and not deleting '.',
1332 power stays */
1333 power++; /* counter "power--;" below */
1335 case cal_typing:
1336 typingbufPointer--;
1338 {/* result processing */ /* 0-9, '.' */
1339 /* if deleting '.', do nothing */
1340 if ( *typingbufPointer != '.'){
1341 power--;
1342 modifier *= 10;
1343 result = result - SIGN(result)*
1344 ((*typingbufPointer)- '0')*modifier;
1348 *typingbufPointer = 0;
1350 /* if (only one digit left and it's 0)
1351 or no digit left, change status*/
1352 if ( typingbufPointer == typingbuf+1 ||
1353 ( typingbufPointer == typingbuf+2 &&
1354 *(typingbufPointer-1) == '0' ))
1355 calStatus = cal_normal;
1356 break;
1357 default: /* normal, error, exit */
1358 break;
1361 /* -----------------------------------------------------------------------
1362 Handle buttons on basic screen
1363 ----------------------------------------------------------------------- */
1364 void basicButtonsProcess(void){
1365 switch (btn) {
1366 case CALCULATOR_INPUT:
1367 if (calStatus == cal_error && (CAL_BUTTON != btn_C) ) break;
1368 flashButton();
1369 switch( CAL_BUTTON ){
1370 case btn_MR:
1371 operInputted = false;
1372 result = memTemp; power = memTempPower;
1373 calStatus = cal_normal;
1374 break;
1375 case btn_M:
1376 formatResult();
1377 if (memTemp > MINIMUM)
1378 doAdd(&memTemp, &memTempPower, result, power);
1379 else {
1380 /* if result is too small and memTemp = 0,
1381 doAdd will not add */
1382 memTemp = result;
1383 memTempPower = power;
1385 calStatus = cal_normal;
1386 break;
1388 case btn_C: clearMem(); break;
1389 case btn_CE: clearInput(); break;
1391 case btn_bas:
1392 buttonGroup = sciButtons;
1393 printButtonGroups(buttonGroup);
1394 break;
1396 /* one operand calculation, may be changed to
1397 like sin, cos, log, etc */
1398 case btn_sqr:
1399 case btn_square:
1400 case btn_rec:
1401 formatResult(); /* not necessary, just for safty */
1402 oneOperand();
1403 break;
1405 case_btn_equal: /* F3 shortkey entrance */
1406 case btn_equal:
1407 formatResult();
1408 calStatus = cal_normal;
1409 operInputted = false;
1410 if (oper != ' ') twoOperands();
1411 break;
1413 case btn_div:
1414 case btn_time:
1415 case btn_minus:
1416 case btn_add:
1417 if(!operInputted) {twoOperands(); operInputted = true;}
1418 oper = buttonChar[basicButtons][btn_row][btn_col][0];
1419 #ifdef CALCULATOR_OPERATORS
1420 case_cycle_operators: /* F2 shortkey entrance */
1421 #endif
1422 calStatus = cal_normal;
1423 formatResult();
1424 operand = result;
1425 operandPower = power;
1427 break;
1429 case btn_sign:
1430 case btn_dot:
1431 default: /* 0-9 */
1432 typingProcess();
1433 break;
1434 } /* switch (CAL_BUTTON) */
1435 break;
1437 #ifdef CALCULATOR_OPERATORS
1438 case CALCULATOR_OPERATORS:
1439 if (calStatus == cal_error) break;
1440 if (!operInputted) {twoOperands(); operInputted = true;}
1441 switch (oper){
1442 case ' ':
1443 case '/': oper = '+'; flashButton(); break;
1444 case '+': oper = '-'; flashButton(); break;
1445 case '-': oper = '*'; flashButton(); break;
1446 case '*': oper = '/'; flashButton(); break;
1448 goto case_cycle_operators;
1449 break;
1450 #endif
1452 case CALCULATOR_CALC:
1453 if (calStatus == cal_error) break;
1454 flashButton();
1455 goto case_btn_equal;
1456 break;
1457 default: break;
1459 printResult();
1462 /* -----------------------------------------------------------------------
1463 Handle buttons on scientific screen
1464 ----------------------------------------------------------------------- */
1465 void sciButtonsProcess(void){
1466 switch (btn) {
1467 case CALCULATOR_INPUT:
1468 if (calStatus == cal_error && (CAL_BUTTON != sci_sci) ) break;
1469 flashButton();
1470 switch( CAL_BUTTON ){
1472 case sci_pi:
1473 result = M_PI; power = 0;
1474 calStatus = cal_normal;
1475 break;
1477 case sci_xy: break;
1479 case sci_sci:
1480 buttonGroup = basicButtons;
1481 printButtonGroups(basicButtons);
1482 break;
1484 case sci_fac:
1485 case sci_sin:
1486 case sci_asin:
1487 case sci_cos:
1488 case sci_acos:
1489 case sci_tan:
1490 case sci_atan:
1491 case sci_ln:
1492 case sci_exp:
1493 case sci_log:
1494 formatResult(); /* not necessary, just for safty */
1495 oneOperand();
1496 break;
1498 case btn_sign:
1499 case btn_dot:
1500 default: /* 0-9 */
1501 typingProcess();
1502 break;
1503 } /* switch (CAL_BUTTON) */
1504 break;
1506 #ifdef CALCULATOR_OPERATORS
1507 case CALCULATOR_OPERATORS:
1508 if (calStatus == cal_error) break;
1509 if (!operInputted) {twoOperands(); operInputted = true;}
1510 switch (oper){
1511 case ' ': oper = '+'; break;
1512 case '/': oper = '+'; deleteAnimation(1); break;
1513 case '+': oper = '-'; deleteAnimation(1); break;
1514 case '-': oper = '*'; deleteAnimation(1); break;
1515 case '*': oper = '/'; deleteAnimation(1); break;
1517 calStatus = cal_normal;
1518 formatResult();
1519 operand = result;
1520 operandPower = power;
1521 break;
1522 #endif
1524 case CALCULATOR_CALC:
1525 if (calStatus == cal_error) break;
1526 formatResult();
1527 calStatus = cal_normal;
1528 operInputted = false;
1529 if (oper != ' ') twoOperands();
1530 break;
1531 default: break;
1533 printResult();
1536 /* -----------------------------------------------------------------------
1537 move button index
1538 Invert display new button, invert back previous button
1539 ----------------------------------------------------------------------- */
1540 int handleButton(int button){
1541 switch(button)
1543 case CALCULATOR_INPUT:
1544 case CALCULATOR_CALC:
1545 #ifdef CALCULATOR_INPUT_CALC_PRE
1546 if (lastbtn != CALCULATOR_INPUT_CALC_PRE)
1547 break;
1548 /* no unconditional break; here! */
1549 #endif
1550 #ifdef CALCULATOR_OPERATORS
1551 case CALCULATOR_OPERATORS:
1552 #endif
1553 switch(buttonGroup){
1554 case basicButtons:
1555 basicButtonsProcess();
1556 break;
1557 case sciButtons:
1558 sciButtonsProcess();
1559 break;
1561 break;
1563 #ifdef CALCULATOR_CLEAR
1564 case CALCULATOR_CLEAR:
1565 switch(calStatus){
1566 case cal_typing:
1567 case cal_dotted:
1568 doDelete();
1569 break;
1570 default: /* cal_normal, cal_error, cal_exit */
1571 clearMem();
1572 break;
1574 printResult();
1575 break;
1576 #endif
1577 case CALCULATOR_LEFT:
1578 case CALCULATOR_LEFT | BUTTON_REPEAT:
1579 move_with_wrap_and_shift(
1580 &btn_col, -1, BUTTON_COLS,
1581 &btn_row, 0, BUTTON_ROWS);
1582 break;
1584 case CALCULATOR_RIGHT:
1585 case CALCULATOR_RIGHT | BUTTON_REPEAT:
1586 move_with_wrap_and_shift(
1587 &btn_col, 1, BUTTON_COLS,
1588 &btn_row, 0, BUTTON_ROWS);
1589 break;
1591 #ifdef CALCULATOR_UP
1592 case CALCULATOR_UP:
1593 case CALCULATOR_UP | BUTTON_REPEAT:
1594 move_with_wrap_and_shift(
1595 &btn_row, -1, BUTTON_ROWS,
1596 &btn_col, 0, BUTTON_COLS);
1597 break;
1598 #endif
1599 #ifdef CALCULATOR_DOWN
1600 case CALCULATOR_DOWN:
1601 case CALCULATOR_DOWN | BUTTON_REPEAT:
1602 move_with_wrap_and_shift(
1603 &btn_row, 1, BUTTON_ROWS,
1604 &btn_col, 0, BUTTON_COLS);
1605 break;
1606 #endif
1608 #ifdef CALCULATOR_UP_W_SHIFT
1609 case CALCULATOR_UP_W_SHIFT:
1610 case CALCULATOR_UP_W_SHIFT | BUTTON_REPEAT:
1611 move_with_wrap_and_shift(
1612 &btn_row, -1, BUTTON_ROWS,
1613 &btn_col, -1, BUTTON_COLS);
1614 break;
1615 #endif
1616 #ifdef CALCULATOR_DOWN_W_SHIFT
1617 case CALCULATOR_DOWN_W_SHIFT:
1618 case CALCULATOR_DOWN_W_SHIFT | BUTTON_REPEAT:
1619 move_with_wrap_and_shift(
1620 &btn_row, 1, BUTTON_ROWS,
1621 &btn_col, 1, BUTTON_COLS);
1622 break;
1623 #endif
1624 #ifdef CALCULATOR_LEFT_W_SHIFT
1625 case CALCULATOR_LEFT_W_SHIFT:
1626 case CALCULATOR_LEFT_W_SHIFT | BUTTON_REPEAT:
1627 move_with_wrap_and_shift(
1628 &btn_col, -1, BUTTON_COLS,
1629 &btn_row, -1, BUTTON_ROWS);
1630 break;
1631 #endif
1632 #ifdef CALCULATOR_RIGHT_W_SHIFT
1633 case CALCULATOR_RIGHT_W_SHIFT:
1634 case CALCULATOR_RIGHT_W_SHIFT | BUTTON_REPEAT:
1635 move_with_wrap_and_shift(
1636 &btn_col, 1, BUTTON_COLS,
1637 &btn_row, 1, BUTTON_ROWS);
1638 break;
1639 #endif
1640 #ifdef CALCULATOR_RC_QUIT
1641 case CALCULATOR_RC_QUIT:
1642 #endif
1643 case CALCULATOR_QUIT:
1644 return -1;
1647 return 0;
1649 prev_btn_row = btn_row;
1650 prev_btn_col = btn_col;
1653 /* -----------------------------------------------------------------------
1654 Main();
1655 ----------------------------------------------------------------------- */
1656 enum plugin_status plugin_start(const void* parameter)
1658 (void)parameter;
1660 /* now go ahead and have fun! */
1662 cal_initial();
1664 while (calStatus != cal_exit ) {
1665 btn = rb->button_get_w_tmo(HZ/2);
1666 #ifdef HAVE_TOUCHSCREEN
1667 if(btn & BUTTON_TOUCHSCREEN)
1669 struct ts_raster_result res;
1670 if(touchscreen_map_raster(&calc_raster, rb->button_get_data() >> 16,
1671 rb->button_get_data() & 0xffff, &res) == 1)
1673 btn_row = res.y;
1674 btn_col = res.x;
1675 drawButtons(buttonGroup);
1676 drawLines();
1678 rb->lcd_update();
1680 prev_btn_row = btn_row;
1681 prev_btn_col = btn_col;
1682 if(btn & BUTTON_REL)
1684 btn = CALCULATOR_INPUT;
1685 switch(buttonGroup){
1686 case basicButtons:
1687 basicButtonsProcess();
1688 break;
1689 case sciButtons:
1690 sciButtonsProcess();
1691 break;
1693 btn = BUTTON_TOUCHSCREEN;
1697 #endif
1698 if (handleButton(btn) == -1)
1700 calStatus = cal_exit;
1701 printResult();
1703 else
1705 drawButtons(buttonGroup);
1706 drawLines();
1709 rb->lcd_update();
1711 if(rb->default_event_handler(btn) == SYS_USB_CONNECTED)
1712 return PLUGIN_USB_CONNECTED;
1714 if (btn != BUTTON_NONE)
1715 lastbtn = btn;
1716 } /* while (calStatus != cal_exit ) */
1718 rb->button_clear_queue();
1719 return PLUGIN_OK;
1722 #endif /* #ifdef HAVE_LCD_BITMAP */