Move c/h files implementing/defining standard library stuff into a new libc directory...
[kugel-rb.git] / apps / plugins / calculator.c
blobc19d6bbc5b729206c24478be5c918170682d18d3
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)
105 #ifndef ABS
106 #define ABS(a) (((a) < 0) ? -(a) : (a))
107 #endif
109 /* variable button definitions */
110 #if CONFIG_KEYPAD == RECORDER_PAD
111 #define CALCULATOR_LEFT BUTTON_LEFT
112 #define CALCULATOR_RIGHT BUTTON_RIGHT
113 #define CALCULATOR_UP BUTTON_UP
114 #define CALCULATOR_DOWN BUTTON_DOWN
115 #define CALCULATOR_QUIT BUTTON_OFF
116 #define CALCULATOR_INPUT BUTTON_PLAY
117 #define CALCULATOR_CALC BUTTON_F3
118 #define CALCULATOR_OPERATORS BUTTON_F2
119 #define CALCULATOR_CLEAR BUTTON_F1
121 #elif CONFIG_KEYPAD == ARCHOS_AV300_PAD
122 #define CALCULATOR_LEFT BUTTON_LEFT
123 #define CALCULATOR_RIGHT BUTTON_RIGHT
124 #define CALCULATOR_UP BUTTON_UP
125 #define CALCULATOR_DOWN BUTTON_DOWN
126 #define CALCULATOR_QUIT BUTTON_OFF
127 #define CALCULATOR_INPUT BUTTON_SELECT
128 #define CALCULATOR_CALC BUTTON_F3
129 #define CALCULATOR_OPERATORS BUTTON_F2
130 #define CALCULATOR_CLEAR BUTTON_F1
132 #elif CONFIG_KEYPAD == ONDIO_PAD
133 #define CALCULATOR_LEFT BUTTON_LEFT
134 #define CALCULATOR_RIGHT BUTTON_RIGHT
135 #define CALCULATOR_UP BUTTON_UP
136 #define CALCULATOR_DOWN BUTTON_DOWN
137 #define CALCULATOR_QUIT BUTTON_OFF
138 #define CALCULATOR_INPUT_CALC_PRE BUTTON_MENU
139 #define CALCULATOR_INPUT (BUTTON_MENU | BUTTON_REL)
140 #define CALCULATOR_CALC (BUTTON_MENU | BUTTON_REPEAT)
142 #elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || \
143 (CONFIG_KEYPAD == IRIVER_H300_PAD)
144 #define CALCULATOR_LEFT BUTTON_LEFT
145 #define CALCULATOR_RIGHT BUTTON_RIGHT
146 #define CALCULATOR_UP BUTTON_UP
147 #define CALCULATOR_DOWN BUTTON_DOWN
148 #define CALCULATOR_QUIT BUTTON_OFF
149 #define CALCULATOR_INPUT BUTTON_SELECT
150 #define CALCULATOR_CALC BUTTON_ON
151 #define CALCULATOR_OPERATORS BUTTON_MODE
152 #define CALCULATOR_CLEAR BUTTON_REC
154 #define CALCULATOR_RC_QUIT BUTTON_RC_STOP
156 #elif (CONFIG_KEYPAD == IPOD_4G_PAD) || \
157 (CONFIG_KEYPAD == IPOD_3G_PAD) || \
158 (CONFIG_KEYPAD == IPOD_1G2G_PAD)
160 #define CALCULATOR_LEFT BUTTON_LEFT
161 #define CALCULATOR_RIGHT BUTTON_RIGHT
162 #define CALCULATOR_UP_W_SHIFT BUTTON_SCROLL_BACK
163 #define CALCULATOR_DOWN_W_SHIFT BUTTON_SCROLL_FWD
164 #define CALCULATOR_QUIT BUTTON_MENU
165 #define CALCULATOR_INPUT BUTTON_SELECT
166 #define CALCULATOR_CALC BUTTON_PLAY
168 #elif (CONFIG_KEYPAD == IAUDIO_X5M5_PAD)
170 #define CALCULATOR_LEFT BUTTON_LEFT
171 #define CALCULATOR_RIGHT BUTTON_RIGHT
172 #define CALCULATOR_UP BUTTON_UP
173 #define CALCULATOR_DOWN BUTTON_DOWN
174 #define CALCULATOR_QUIT BUTTON_POWER
175 #define CALCULATOR_INPUT BUTTON_SELECT
176 #define CALCULATOR_CALC BUTTON_PLAY
177 #define CALCULATOR_CLEAR BUTTON_REC
179 #elif (CONFIG_KEYPAD == GIGABEAT_PAD)
181 #define CALCULATOR_LEFT BUTTON_LEFT
182 #define CALCULATOR_RIGHT BUTTON_RIGHT
183 #define CALCULATOR_UP BUTTON_UP
184 #define CALCULATOR_DOWN BUTTON_DOWN
185 #define CALCULATOR_QUIT BUTTON_POWER
186 #define CALCULATOR_INPUT BUTTON_SELECT
187 #define CALCULATOR_CALC BUTTON_MENU
188 #define CALCULATOR_CLEAR BUTTON_A
190 #elif (CONFIG_KEYPAD == SANSA_E200_PAD)
191 #define CALCULATOR_LEFT BUTTON_LEFT
192 #define CALCULATOR_RIGHT BUTTON_RIGHT
193 #define CALCULATOR_UP BUTTON_UP
194 #define CALCULATOR_DOWN BUTTON_DOWN
195 #define CALCULATOR_UP_W_SHIFT BUTTON_SCROLL_BACK
196 #define CALCULATOR_DOWN_W_SHIFT BUTTON_SCROLL_FWD
197 #define CALCULATOR_QUIT BUTTON_POWER
198 #define CALCULATOR_INPUT_CALC_PRE BUTTON_SELECT
199 #define CALCULATOR_INPUT (BUTTON_SELECT|BUTTON_REL)
200 #define CALCULATOR_CALC (BUTTON_SELECT|BUTTON_REPEAT)
201 #define CALCULATOR_CLEAR BUTTON_REC
203 #elif (CONFIG_KEYPAD == SANSA_C200_PAD)
204 #define CALCULATOR_LEFT BUTTON_LEFT
205 #define CALCULATOR_RIGHT BUTTON_RIGHT
206 #define CALCULATOR_UP BUTTON_UP
207 #define CALCULATOR_DOWN BUTTON_DOWN
208 #define CALCULATOR_QUIT BUTTON_POWER
209 #define CALCULATOR_INPUT_CALC_PRE BUTTON_SELECT
210 #define CALCULATOR_INPUT (BUTTON_SELECT|BUTTON_REL)
211 #define CALCULATOR_CALC (BUTTON_SELECT|BUTTON_REPEAT)
213 #elif (CONFIG_KEYPAD == SANSA_FUZE_PAD)
214 #define CALCULATOR_LEFT BUTTON_LEFT
215 #define CALCULATOR_RIGHT BUTTON_RIGHT
216 #define CALCULATOR_UP BUTTON_UP
217 #define CALCULATOR_DOWN BUTTON_DOWN
218 #define CALCULATOR_UP_W_SHIFT BUTTON_SCROLL_BACK
219 #define CALCULATOR_DOWN_W_SHIFT BUTTON_SCROLL_FWD
220 #define CALCULATOR_QUIT (BUTTON_HOME|BUTTON_REPEAT)
221 #define CALCULATOR_INPUT_CALC_PRE BUTTON_SELECT
222 #define CALCULATOR_INPUT (BUTTON_SELECT|BUTTON_REL)
223 #define CALCULATOR_CALC (BUTTON_SELECT|BUTTON_REPEAT)
224 #define CALCULATOR_CLEAR BUTTON_HOME
227 #elif (CONFIG_KEYPAD == SANSA_CLIP_PAD)
228 #define CALCULATOR_LEFT BUTTON_LEFT
229 #define CALCULATOR_RIGHT BUTTON_RIGHT
230 #define CALCULATOR_UP BUTTON_UP
231 #define CALCULATOR_DOWN BUTTON_DOWN
232 #define CALCULATOR_QUIT BUTTON_POWER
233 #define CALCULATOR_INPUT_CALC_PRE BUTTON_SELECT
234 #define CALCULATOR_INPUT (BUTTON_SELECT|BUTTON_REL)
235 #define CALCULATOR_CALC (BUTTON_SELECT|BUTTON_REPEAT)
236 #define CALCULATOR_CLEAR BUTTON_HOME
238 #elif (CONFIG_KEYPAD == SANSA_M200_PAD)
239 #define CALCULATOR_LEFT BUTTON_LEFT
240 #define CALCULATOR_RIGHT BUTTON_RIGHT
241 #define CALCULATOR_UP BUTTON_UP
242 #define CALCULATOR_DOWN BUTTON_DOWN
243 #define CALCULATOR_QUIT BUTTON_POWER
244 #define CALCULATOR_INPUT_CALC_PRE BUTTON_SELECT
245 #define CALCULATOR_INPUT (BUTTON_SELECT|BUTTON_REL)
246 #define CALCULATOR_CALC (BUTTON_SELECT|BUTTON_REPEAT)
247 #define CALCULATOR_CLEAR (BUTTON_SELECT|BUTTON_UP)
249 #elif (CONFIG_KEYPAD == IRIVER_H10_PAD)
251 #define CALCULATOR_LEFT BUTTON_LEFT
252 #define CALCULATOR_RIGHT BUTTON_RIGHT
253 #define CALCULATOR_UP BUTTON_SCROLL_UP
254 #define CALCULATOR_DOWN BUTTON_SCROLL_DOWN
255 #define CALCULATOR_QUIT BUTTON_POWER
256 #define CALCULATOR_INPUT_CALC_PRE BUTTON_PLAY
257 #define CALCULATOR_INPUT (BUTTON_PLAY | BUTTON_REL)
258 #define CALCULATOR_CALC (BUTTON_PLAY | BUTTON_REPEAT)
259 #define CALCULATOR_CLEAR BUTTON_REW
261 #elif (CONFIG_KEYPAD == GIGABEAT_S_PAD)
263 #define CALCULATOR_LEFT BUTTON_LEFT
264 #define CALCULATOR_RIGHT BUTTON_RIGHT
265 #define CALCULATOR_UP BUTTON_UP
266 #define CALCULATOR_DOWN BUTTON_DOWN
267 #define CALCULATOR_QUIT BUTTON_BACK
268 #define CALCULATOR_INPUT BUTTON_SELECT
269 #define CALCULATOR_CALC BUTTON_MENU
270 #define CALCULATOR_CLEAR BUTTON_PLAY
272 #elif (CONFIG_KEYPAD == MROBE100_PAD)
274 #define CALCULATOR_LEFT BUTTON_LEFT
275 #define CALCULATOR_RIGHT BUTTON_RIGHT
276 #define CALCULATOR_UP BUTTON_UP
277 #define CALCULATOR_DOWN BUTTON_DOWN
278 #define CALCULATOR_QUIT BUTTON_POWER
279 #define CALCULATOR_INPUT BUTTON_SELECT
280 #define CALCULATOR_CALC BUTTON_MENU
281 #define CALCULATOR_CLEAR BUTTON_DISPLAY
283 #elif CONFIG_KEYPAD == IAUDIO_M3_PAD
285 #define CALCULATOR_LEFT BUTTON_RC_REW
286 #define CALCULATOR_RIGHT BUTTON_RC_FF
287 #define CALCULATOR_UP BUTTON_RC_VOL_UP
288 #define CALCULATOR_DOWN BUTTON_RC_VOL_DOWN
289 #define CALCULATOR_QUIT BUTTON_RC_REC
290 #define CALCULATOR_INPUT BUTTON_RC_PLAY
291 #define CALCULATOR_CALC BUTTON_RC_MODE
292 #define CALCULATOR_CLEAR BUTTON_RC_MENU
294 #define CALCULATOR_RC_QUIT BUTTON_REC
296 #elif (CONFIG_KEYPAD == COWON_D2_PAD)
298 #define CALCULATOR_QUIT BUTTON_POWER
299 #define CALCULATOR_CLEAR BUTTON_MENU
301 #elif CONFIG_KEYPAD == IAUDIO67_PAD
303 #define CALCULATOR_LEFT BUTTON_LEFT
304 #define CALCULATOR_RIGHT BUTTON_RIGHT
305 #define CALCULATOR_UP BUTTON_VOLUP
306 #define CALCULATOR_DOWN BUTTON_VOLDOWN
307 #define CALCULATOR_QUIT BUTTON_POWER
308 #define CALCULATOR_INPUT BUTTON_PLAY
309 #define CALCULATOR_CALC BUTTON_MENU
310 #define CALCULATOR_CLEAR BUTTON_STOP
312 #define CALCULATOR_RC_QUIT (BUTTON_MENU|BUTTON_PLAY)
314 #elif (CONFIG_KEYPAD == CREATIVEZVM_PAD)
316 #define CALCULATOR_LEFT BUTTON_LEFT
317 #define CALCULATOR_RIGHT BUTTON_RIGHT
318 #define CALCULATOR_UP BUTTON_UP
319 #define CALCULATOR_DOWN BUTTON_DOWN
320 #define CALCULATOR_QUIT BUTTON_BACK
321 #define CALCULATOR_INPUT BUTTON_SELECT
322 #define CALCULATOR_CALC BUTTON_MENU
323 #define CALCULATOR_CLEAR BUTTON_PLAY
325 #elif CONFIG_KEYPAD == PHILIPS_HDD1630_PAD
327 #define CALCULATOR_LEFT BUTTON_LEFT
328 #define CALCULATOR_RIGHT BUTTON_RIGHT
329 #define CALCULATOR_UP BUTTON_UP
330 #define CALCULATOR_DOWN BUTTON_DOWN
331 #define CALCULATOR_QUIT BUTTON_POWER
332 #define CALCULATOR_INPUT BUTTON_SELECT
333 #define CALCULATOR_CALC BUTTON_MENU
334 #define CALCULATOR_CLEAR BUTTON_VIEW
336 #elif CONFIG_KEYPAD == PHILIPS_SA9200_PAD
338 #define CALCULATOR_LEFT BUTTON_PREV
339 #define CALCULATOR_RIGHT BUTTON_NEXT
340 #define CALCULATOR_UP BUTTON_UP
341 #define CALCULATOR_DOWN BUTTON_DOWN
342 #define CALCULATOR_QUIT BUTTON_POWER
343 #define CALCULATOR_INPUT BUTTON_PLAY
344 #define CALCULATOR_CALC BUTTON_MENU
345 #define CALCULATOR_CLEAR BUTTON_RIGHT
347 #elif (CONFIG_KEYPAD == ONDAVX747_PAD)
349 #define CALCULATOR_QUIT BUTTON_POWER
350 #define CALCULATOR_CLEAR BUTTON_MENU
352 #elif (CONFIG_KEYPAD == ONDAVX777_PAD)
353 #define CALCULATOR_QUIT BUTTON_POWER
355 #elif CONFIG_KEYPAD == MROBE500_PAD
356 #define CALCULATOR_QUIT BUTTON_POWER
358 #elif CONFIG_KEYPAD == SAMSUNG_YH_PAD
360 #define CALCULATOR_LEFT BUTTON_LEFT
361 #define CALCULATOR_RIGHT BUTTON_RIGHT
362 #define CALCULATOR_UP BUTTON_UP
363 #define CALCULATOR_DOWN BUTTON_DOWN
364 #define CALCULATOR_QUIT BUTTON_REC
365 #define CALCULATOR_INPUT BUTTON_PLAY
366 #define CALCULATOR_CALC BUTTON_FFWD
367 #define CALCULATOR_CLEAR BUTTON_REW
369 #elif CONFIG_KEYPAD == PBELL_VIBE500_PAD
371 #define CALCULATOR_LEFT BUTTON_PREV
372 #define CALCULATOR_RIGHT BUTTON_NEXT
373 #define CALCULATOR_UP BUTTON_UP
374 #define CALCULATOR_DOWN BUTTON_DOWN
375 #define CALCULATOR_QUIT BUTTON_REC
376 #define CALCULATOR_INPUT BUTTON_OK
377 #define CALCULATOR_CALC BUTTON_PLAY
378 #define CALCULATOR_CLEAR BUTTON_CANCEL
380 #elif CONFIG_KEYPAD == MPIO_HD200_PAD
381 #define CALCULATOR_LEFT BUTTON_PREV
382 #define CALCULATOR_RIGHT BUTTON_NEXT
383 #define CALCULATOR_QUIT (BUTTON_REC|BUTTON_PLAY)
384 #define CALCULATOR_INPUT BUTTON_SELECT
385 #define CALCULATOR_CALC BUTTON_PLAY
387 #else
388 #error No keymap defined!
389 #endif
391 #ifdef HAVE_TOUCHSCREEN
392 #ifndef CALCULATOR_LEFT
393 #define CALCULATOR_LEFT BUTTON_MIDLEFT
394 #endif
395 #ifndef CALCULATOR_RIGHT
396 #define CALCULATOR_RIGHT BUTTON_MIDRIGHT
397 #endif
398 #ifndef CALCULATOR_UP
399 #define CALCULATOR_UP BUTTON_TOPMIDDLE
400 #endif
401 #ifndef CALCULATOR_DOWN
402 #define CALCULATOR_DOWN BUTTON_BOTTOMMIDDLE
403 #endif
404 #ifndef CALCULATOR_CALC
405 #define CALCULATOR_CALC BUTTON_BOTTOMRIGHT
406 #endif
407 #ifndef CALCULATOR_INPUT
408 #define CALCULATOR_INPUT BUTTON_CENTER
409 #endif
410 #ifndef CALCULATOR_CLEAR
411 #define CALCULATOR_CLEAR BUTTON_TOPRIGHT
412 #endif
414 #include "lib/pluginlib_touchscreen.h"
415 static struct ts_raster calc_raster = { X_0_POS, Y_1_POS,
416 BUTTON_COLS*REC_WIDTH, BUTTON_ROWS*REC_HEIGHT, REC_WIDTH, REC_HEIGHT };
417 #endif
419 enum {
420 basicButtons,
421 sciButtons
422 } buttonGroup;
424 unsigned char* buttonChar[2][5][5] = {
425 { { "MR" , "M+" , "2nd" , "CE" , "C" },
426 { "7" , "8" , "9" , "/" , "sqr" },
427 { "4" , "5" , "6" , "*" , "x^2" },
428 { "1" , "2" , "3" , "-" , "1/x" },
429 { "0" , "+/-", "." , "+" , "=" } },
431 { { "n!" , "PI" , "1st" , "sin" , "asi" },
432 { "7" , "8" , "9" , "cos" , "aco" },
433 { "4" , "5" , "6" , "tan" , "ata" },
434 { "1" , "2" , "3" , "ln" , "e^x" },
435 { "0" , "+/-", "." , "log" , "x^y" } }
438 enum { btn_MR , btn_M , btn_bas , btn_CE , btn_C ,
439 btn_7 , btn_8 , btn_9 , btn_div , btn_sqr ,
440 btn_4 , btn_5 , btn_6 , btn_time , btn_square ,
441 btn_1 , btn_2 , btn_3 , btn_minus , btn_rec ,
442 btn_0 , btn_sign , btn_dot , btn_add , btn_equal
445 enum { sci_fac, sci_pi , sci_sci , sci_sin , sci_asin ,
446 sci_7 , sci_8 , sci_9 , sci_cos , sci_acos ,
447 sci_4 , sci_5 , sci_6 , sci_tan , sci_atan ,
448 sci_1 , sci_2 , sci_3 , sci_ln , sci_exp ,
449 sci_0 , sci_sign , sci_dot , sci_log , sci_xy
452 #define MINIMUM 0.000000000001 /* e-12 */
453 /* ^ ^ ^ ^ */
454 /* 123456789abcdef */
456 #define DIGITLEN 10 /* must <= 10 */
457 #define SCIENTIFIC_FORMAT ( power < -(DIGITLEN-3) || power > (DIGITLEN))
458 /* 0.000 00000 0001 */
459 /* ^ ^ ^ ^ ^ ^ */
460 /* DIGITLEN 12345 6789a bcdef */
461 /* power 12 34567 89abc def */
462 /* 10^- 123 45678 9abcd ef */
464 unsigned char buf[19];/* 18 bytes of output line,
465 buf[0] is operator
466 buf[1] = 'M' if memTemp is not 0
467 buf[2] = ' '
469 if SCIENTIFIC_FORMAT
470 buf[2]-buf[12] or buf[3]-buf[13] = result;
471 format X.XXXXXXXX
472 buf[13] or buf[14] -buf[17] = power;
473 format eXXX or e-XXX
474 else
475 buf[3]-buf[6] = ' ';
476 buf[7]-buf[17] = result;
478 buf[18] = '\0' */
480 unsigned char typingbuf[DIGITLEN+2];/* byte 0 is sign or ' ',
481 byte 1~DIGITLEN are num and '.'
482 byte (DIGITLEN+1) is '\0' */
483 unsigned char* typingbufPointer = typingbuf;
485 double result = 0; /* main operand, format 0.xxxxx */
486 int power = 0; /* 10^power */
487 double modifier = 0.1; /* position of next input */
488 double operand = 0; /* second operand, format 0.xxxxx */
489 int operandPower = 0; /* 10^power of second operand */
490 char oper = ' '; /* operators: + - * / */
491 bool operInputted = false; /* false: do calculation first and
492 replace current oper
493 true: just replace current oper */
495 double memTemp = 0; /* temp memory */
496 int memTempPower = 0; /* 10^^power of memTemp */
498 int btn_row, btn_col; /* current position index for button */
499 int prev_btn_row, prev_btn_col; /* previous cursor position */
500 #define CAL_BUTTON (btn_row*5+btn_col)
502 int btn = BUTTON_NONE;
503 int lastbtn = BUTTON_NONE;
505 /* Status of calculator */
506 enum {cal_normal, /* 0, normal status, display result */
507 cal_typing, /* 1, currently typing, dot hasn't been typed */
508 cal_dotted, /* 2, currently typing, dot already has been typed. */
509 cal_error,
510 cal_exit,
511 cal_toDo
512 } calStatus;
514 /* constant table for CORDIC algorithm */
515 double cordicTable[51][2]= {
516 /* pow(2,0) - pow(2,-50) atan(pow(2,0) - atan(pow(2,-50) */
517 {1e+00, 7.853981633974483e-01},
518 {5e-01, 4.636476090008061e-01},
519 {2.5e-01, 2.449786631268641e-01},
520 {1.25e-01, 1.243549945467614e-01},
521 {6.25e-02, 6.241880999595735e-02},
522 {3.125e-02, 3.123983343026828e-02},
523 {1.5625e-02, 1.562372862047683e-02},
524 {7.8125e-03, 7.812341060101111e-03},
525 {3.90625e-03, 3.906230131966972e-03},
526 {1.953125e-03, 1.953122516478819e-03},
527 {9.765625e-04, 9.765621895593195e-04},
528 {4.8828125e-04, 4.882812111948983e-04},
529 {2.44140625e-04, 2.441406201493618e-04},
530 {1.220703125e-04, 1.220703118936702e-04},
531 {6.103515625e-05, 6.103515617420877e-05},
532 {3.0517578125e-05, 3.051757811552610e-05},
533 {1.52587890625e-05, 1.525878906131576e-05},
534 {7.62939453125e-06, 7.629394531101970e-06},
535 {3.814697265625e-06, 3.814697265606496e-06},
536 {1.9073486328125e-06, 1.907348632810187e-06},
537 {9.5367431640625e-07, 9.536743164059608e-07},
538 {4.76837158203125e-07, 4.768371582030888e-07},
539 {2.384185791015625e-07, 2.384185791015580e-07},
540 {1.1920928955078125e-07, 1.192092895507807e-07},
541 {5.9604644775390625e-08, 5.960464477539055e-08},
542 {2.98023223876953125e-08, 2.980232238769530e-08},
543 {1.490116119384765625e-08, 1.490116119384765e-08},
544 {7.450580596923828125e-09, 7.450580596923828e-09},
545 {3.7252902984619140625e-09, 3.725290298461914e-09},
546 {1.86264514923095703125e-09, 1.862645149230957e-09},
547 {9.31322574615478515625e-10, 9.313225746154785e-10},
548 {4.656612873077392578125e-10, 4.656612873077393e-10},
549 {2.3283064365386962890625e-10, 2.328306436538696e-10},
550 {1.16415321826934814453125e-10, 1.164153218269348e-10},
551 {5.82076609134674072265625e-11, 5.820766091346741e-11},
552 {2.910383045673370361328125e-11, 2.910383045673370e-11},
553 {1.4551915228366851806640625e-11, 1.455191522836685e-11},
554 {7.2759576141834259033203125e-12, 7.275957614183426e-12},
555 {3.63797880709171295166015625e-12, 3.637978807091713e-12},
556 {1.818989403545856475830078125e-12, 1.818989403545856e-12},
557 {9.094947017729282379150390625e-13, 9.094947017729282e-13},
558 {4.5474735088646411895751953125e-13, 4.547473508864641e-13},
559 {2.27373675443232059478759765625e-13, 2.273736754432321e-13},
560 {1.136868377216160297393798828125e-13, 1.136868377216160e-13},
561 {5.684341886080801486968994140625e-14, 5.684341886080801e-14},
562 {2.8421709430404007434844970703125e-14, 2.842170943040401e-14},
563 {1.42108547152020037174224853515625e-14, 1.421085471520200e-14},
564 {7.10542735760100185871124267578125e-15, 7.105427357601002e-15},
565 {3.552713678800500929355621337890625e-15, 3.552713678800501e-15},
566 {1.7763568394002504646778106689453125e-15, 1.776356839400250e-15},
567 {8.8817841970012523233890533447265625e-16, 8.881784197001252e-16}
570 void doMultiple(double* operandOne, int* powerOne,
571 double operandTwo, int powerTwo);
572 void doAdd (double* operandOne, int* powerOne,
573 double operandTwo, int powerTwo);
574 void printResult(void);
575 void formatResult(void);
576 void oneOperand(void);
578 void drawLines(void);
579 void drawButtons(int group);
581 /* -----------------------------------------------------------------------
582 Handy funtions
583 ----------------------------------------------------------------------- */
584 void cleartypingbuf(void)
586 int k;
587 for( k=1; k<=(DIGITLEN+1); k++)
588 typingbuf[k] = 0;
589 typingbuf[0] = ' ';
590 typingbufPointer = typingbuf+1;
592 void clearbuf(void)
594 int k;
595 for(k=0;k<18;k++)
596 buf[k]=' ';
597 buf[18] = 0;
599 void clearResult(void)
601 result = 0;
602 power = 0;
603 modifier = 0.1;
606 void clearInput(void)
608 calStatus = cal_normal;
609 clearResult();
610 cleartypingbuf();
611 rb->lcd_clear_display();
612 drawButtons(buttonGroup);
613 drawLines();
616 void clearOperand(void)
618 operand = 0;
619 operandPower = 0;
622 void clearMemTemp(void)
624 memTemp = 0;
625 memTempPower = 0;
628 void clearOper(void)
630 oper = ' ';
631 operInputted = false;
634 void clearMem(void)
636 clearInput();
637 clearMemTemp();
638 clearOperand();
639 clearOper();
640 btn = BUTTON_NONE;
643 void switchOperands(void)
645 double tempr = operand;
646 int tempp = operandPower;
647 operand = result;
648 operandPower = power;
649 result = tempr;
650 power = tempp;
653 void drawLines(void)
655 int i;
656 rb->lcd_hline(0, LCD_WIDTH, Y_1_POS-1);
657 for (i = 0; i < 5 ; i++)
658 rb->lcd_hline(0, LCD_WIDTH, Y_1_POS+i*REC_HEIGHT);
659 for (i = 0; i < 4 ; i++)
660 rb->lcd_vline(X_1_POS+i*REC_WIDTH, Y_1_POS, LCD_HEIGHT);
663 void drawButtons(int group)
665 int i, j, w, h;
666 for (i = 0; i <= 4; i++){
667 for (j = 0; j <= 4; j++){
668 rb->lcd_getstringsize( buttonChar[group][i][j],&w,&h);
669 if (i == btn_row && j == btn_col) /* selected item */
670 rb->lcd_set_drawmode(DRMODE_SOLID);
671 else
672 rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
673 rb->lcd_fillrect( X_0_POS + j*REC_WIDTH,
674 Y_1_POS + i*REC_HEIGHT,
675 REC_WIDTH, REC_HEIGHT+1);
676 if (i == btn_row && j == btn_col) /* selected item */
677 rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
678 else
679 rb->lcd_set_drawmode(DRMODE_SOLID);
680 rb->lcd_putsxy( X_0_POS + j*REC_WIDTH + (REC_WIDTH - w)/2,
681 Y_1_POS + i*REC_HEIGHT + (REC_HEIGHT - h)/2 + 1,
682 buttonChar[group][i][j] );
685 rb->lcd_set_drawmode(DRMODE_SOLID);
688 /* -----------------------------------------------------------------------
689 Initiate calculator
690 ----------------------------------------------------------------------- */
691 void cal_initial (void)
693 int w,h;
695 rb->lcd_getstringsize("2nd",&w,&h);
696 if (w > REC_WIDTH || h > REC_HEIGHT)
697 rb->lcd_setfont(FONT_SYSFIXED);
699 rb->lcd_clear_display();
701 #ifdef CALCULATOR_OPERATORS
702 /* basic operators are available through separate button */
703 buttonGroup = sciButtons;
704 #else
705 buttonGroup = basicButtons;
706 #endif
708 /* initially, invert button "5" */
709 btn_row = 2;
710 btn_col = 1;
711 prev_btn_row = btn_row;
712 prev_btn_col = btn_col;
713 drawButtons(buttonGroup);
714 drawLines();
715 rb->lcd_update();
717 /* initial mem and output display*/
718 clearMem();
719 printResult();
721 /* clear button queue */
722 rb->button_clear_queue();
725 /* -----------------------------------------------------------------------
726 mySqrt uses Heron's algorithm, which is the Newtone-Raphson algorhitm
727 in it's private case for sqrt.
728 Thanks BlueChip for his intro text and Dave Straayer for the actual name.
729 ----------------------------------------------------------------------- */
730 double mySqrt(double square)
732 int k = 0;
733 double temp = 0;
734 double root= ABS(square+1)/2;
736 while( ABS(root - temp) > MINIMUM ){
737 temp = root;
738 root = (square/temp + temp)/2;
739 k++;
740 if (k>10000) return 0;
743 return root;
745 /* -----------------------------------------------------------------------
746 transcendFunc uses CORDIC (COordinate Rotation DIgital Computer) method
747 transcendFunc can do sin,cos,log,exp
748 input parameter is angle
749 ----------------------------------------------------------------------- */
750 void transcendFunc(char* func, double* tt, int* ttPower)
752 double t = (*tt)*M_PI/180; int tPower = *ttPower;
753 int sign = 1;
754 int n = 50; /* n <=50, tables are all <= 50 */
755 int j;
756 double x,y,z,xt,yt,zt;
758 if (tPower < -998) {
759 calStatus = cal_normal;
760 return;
762 if (tPower > 8) {
763 calStatus = cal_error;
764 return;
766 *ttPower = 0;
767 calStatus = cal_normal;
769 if( func[0] =='s' || func[0] =='S'|| func[0] =='t' || func[0] =='T')
770 sign = SIGN(t);
771 else {
772 /* if( func[0] =='c' || func[0] =='C') */
773 sign = 1;
775 t = ABS(t);
777 while (tPower > 0){
778 t *= 10;
779 tPower--;
781 while (tPower < 0) {
782 t /= 10;
783 tPower++;
785 j = 0;
786 while (t > j*M_TWOPI) {j++;}
787 t -= (j-1)*M_TWOPI;
788 if (M_PI_2 < t && t < 3*M_PI_2){
789 t = M_PI - t;
790 if (func[0] =='c' || func[0] =='C')
791 sign = -1;
792 else if (func[0] =='t' || func[0] =='T')
793 t*=-1;
795 else if ( 3*M_PI_2 <= t && t <= M_TWOPI)
796 t -= M_TWOPI;
798 x = 0.60725293500888; y = 0; z = t;
799 for (j=1;j<n+2;j++){
800 xt = x - SIGN(z) * y*cordicTable[j-1][0];
801 yt = y + SIGN(z) * x*cordicTable[j-1][0];
802 zt = z - SIGN(z) * cordicTable[j-1][1];
803 x = xt;
804 y=yt;
805 z=zt;
807 if( func[0] =='s' || func[0] =='S') {
808 *tt = sign*y;
809 return;
811 else if( func[0] =='c' || func[0] =='C') {
812 *tt = sign*x;
813 return;
815 else /*if( func[0] =='t' || func[0] =='T')*/ {
816 if(t==M_PI_2||t==-M_PI_2){
817 calStatus = cal_error;
818 return;
820 else{
821 *tt = sign*(y/x);
822 return;
827 /* -----------------------------------------------------------------------
828 add in scientific number format
829 ----------------------------------------------------------------------- */
830 void doAdd (double* operandOne, int* powerOne,
831 double operandTwo, int powerTwo)
833 if ( *powerOne >= powerTwo ){
834 if (*powerOne - powerTwo <= DIGITLEN+1){
835 while (powerTwo < *powerOne){
836 operandTwo /=10;
837 powerTwo++;
839 *operandOne += operandTwo;
841 /*do nothing if operandTwo is too small*/
843 else{
844 if (powerTwo - *powerOne <= DIGITLEN+1){
845 while(powerTwo > *powerOne){
846 *operandOne /=10;
847 (*powerOne)++;
849 (*operandOne) += operandTwo;
851 else{/* simply copy operandTwo if operandOne is too small */
852 *operandOne = operandTwo;
853 *powerOne = powerTwo;
857 /* -----------------------------------------------------------------------
858 multiple in scientific number format
859 ----------------------------------------------------------------------- */
860 void doMultiple(double* operandOne, int* powerOne,
861 double operandTwo, int powerTwo)
863 (*operandOne) *= operandTwo;
864 (*powerOne) += powerTwo;
867 /* -----------------------------------------------------------------------
868 Handles all one operand calculations
869 ----------------------------------------------------------------------- */
870 void oneOperand(void)
872 int k = 0;
873 if (buttonGroup == basicButtons){
874 switch(CAL_BUTTON){
875 case btn_sqr:
876 if (result<0)
877 calStatus = cal_error;
878 else{
879 if (power%2 == 1){
880 result = (mySqrt(result*10))/10;
881 power = (power+1) / 2;
883 else{
884 result = mySqrt(result);
885 power = power / 2;
887 calStatus = cal_normal;
889 break;
890 case btn_square:
891 power *= 2;
892 result *= result;
893 calStatus = cal_normal;
894 break;
896 case btn_rec:
897 if (result==0)
898 calStatus = cal_error;
899 else{
900 power = -power;
901 result = 1/result;
902 calStatus = cal_normal;
904 break;
905 default:
906 calStatus = cal_toDo;
907 break; /* just for the safety */
910 else{ /* sciButtons */
911 switch(CAL_BUTTON){
912 case sci_sin:
913 transcendFunc("sin", &result, &power);
914 break;
915 case sci_cos:
916 transcendFunc("cos", &result, &power);
917 break;
918 case sci_tan:
919 transcendFunc("tan", &result, &power);
920 break;
921 case sci_fac:
922 if (power<0 || power>8 || result<0 )
923 calStatus = cal_error;
924 else if(result == 0) {
925 result = 1;
926 power = 0;
928 else{
929 while(power > 0) {
930 result *= 10;
931 power--;
933 if ( ( result - (int)result) > MINIMUM )
934 calStatus = cal_error;
935 else {
936 k = result; result = 1;
937 while (k > 1){
938 doMultiple(&result, &power, k, 0);
939 formatResult();
940 k--;
942 calStatus = cal_normal;
945 break;
946 default:
947 calStatus = cal_toDo;
948 break; /* just for the safety */
954 /* -----------------------------------------------------------------------
955 Handles all two operands calculations
956 ----------------------------------------------------------------------- */
957 void twoOperands(void)
959 switch(oper){
960 case '-':
961 doAdd(&operand, &operandPower, -result, power);
962 break;
963 case '+':
964 doAdd(&operand, &operandPower, result, power);
965 break;
966 case '*':
967 doMultiple(&operand, &operandPower, result, power);
968 break;
969 case '/':
970 if ( ABS(result) > MINIMUM ){
971 doMultiple(&operand, &operandPower, 1/result, -power);
973 else
974 calStatus = cal_error;
975 break;
976 default: /* ' ' */
977 switchOperands(); /* counter switchOperands() below */
978 break;
979 } /* switch(oper) */
980 switchOperands();
981 clearOper();
984 /* First, increases *dimen1 by dimen1_delta modulo dimen1_modulo.
985 If dimen1 wraps, increases *dimen2 by dimen2_delta modulo dimen2_modulo.
987 static void move_with_wrap_and_shift(
988 int *dimen1, int dimen1_delta, int dimen1_modulo,
989 int *dimen2, int dimen2_delta, int dimen2_modulo)
991 bool wrapped = false;
993 *dimen1 += dimen1_delta;
994 if (*dimen1 < 0)
996 *dimen1 = dimen1_modulo - 1;
997 wrapped = true;
999 else if (*dimen1 >= dimen1_modulo)
1001 *dimen1 = 0;
1002 wrapped = true;
1005 if (wrapped)
1007 /* Make the dividend always positive to be sure about the result.
1008 Adding dimen2_modulo does not change it since we do it modulo. */
1009 *dimen2 = (*dimen2 + dimen2_modulo + dimen2_delta) % dimen2_modulo;
1013 /* -----------------------------------------------------------------------
1014 Print buttons when switching 1st and 2nd
1015 int group = {basicButtons, sciButtons}
1016 ----------------------------------------------------------------------- */
1017 void printButtonGroups(int group)
1019 drawButtons(group);
1020 drawLines();
1021 rb->lcd_update();
1023 /* -----------------------------------------------------------------------
1024 flash the currently marked button
1025 ----------------------------------------------------------------------- */
1026 void flashButton(void)
1028 int k, w, h;
1029 for (k=2;k>0;k--)
1031 rb->lcd_getstringsize( buttonChar[buttonGroup][btn_row][btn_col],&w,&h);
1032 rb->lcd_set_drawmode(DRMODE_SOLID|(k==1) ? 0 : DRMODE_INVERSEVID);
1033 rb->lcd_fillrect( X_0_POS + btn_col*REC_WIDTH + 1,
1034 Y_1_POS + btn_row*REC_HEIGHT + 1,
1035 REC_WIDTH - 1, REC_HEIGHT - 1);
1036 rb->lcd_putsxy( X_0_POS + btn_col*REC_WIDTH + (REC_WIDTH - w)/2,
1037 Y_1_POS + btn_row*REC_HEIGHT + (REC_HEIGHT - h)/2 +1,
1038 buttonChar[buttonGroup][btn_row][btn_col] );
1039 rb->lcd_update_rect( X_0_POS + btn_col*REC_WIDTH + 1,
1040 Y_1_POS + btn_row*REC_HEIGHT + 1,
1041 REC_WIDTH - 1, REC_HEIGHT - 1);
1043 if (k!= 1)
1044 rb->sleep(HZ/22);
1049 /* -----------------------------------------------------------------------
1050 pos is the position that needs animation. pos = [1~18]
1051 ----------------------------------------------------------------------- */
1052 void deleteAnimation(int pos)
1054 int k, w, h, x;
1055 if (pos<1 || pos >18)
1056 return;
1058 rb->lcd_getstringsize("0", &w, &h);
1059 x = (pos==1? 4: LCD_WIDTH - 4 - w);
1061 for (k=0;k<4;k++){
1062 rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
1063 rb->lcd_fillrect(x, Y_1_POS - h -1, w, h);
1064 rb->lcd_set_drawmode(DRMODE_SOLID);
1065 rb->lcd_fillrect(x + (w*k)/8, Y_1_POS - h -1 + (h*k)/8,
1066 (w*(4-k))/4, (h*(4-k))/4);
1067 rb->lcd_update_rect(x, Y_1_POS - h -1, w, h);
1068 rb->sleep(HZ/32);
1072 /* -----------------------------------------------------------------------
1073 result may be one of these formats:
1075 xxxx.xxxx
1076 0.xxxx
1077 0.0000xxxx
1079 formatResult() change result to standard format: 0.xxxx
1080 if result is close to 0, let it be 0;
1081 if result is close to 1, let it be 0.1 and power++;
1082 ----------------------------------------------------------------------- */
1083 void formatResult(void)
1085 int resultsign = SIGN(result);
1086 result = ABS(result);
1087 if(result > MINIMUM ){ /* doesn't check power, might have problem
1088 input wouldn't,
1089 + - * / of two formatted number wouldn't.
1090 only a calculation that makes a formatted
1091 number (0.xxxx) less than MINIMUM in only
1092 one operation */
1094 if (result<1){
1095 while( (int)(result*10) == 0 ){
1096 result *= 10;
1097 power--;
1098 modifier *= 10;
1101 else{ /* result >= 1 */
1102 while( (int)result != 0 ){
1103 result /= 10;
1104 power++;
1105 modifier /= 10;
1107 } /* if result<1 */
1109 if (result > (1-MINIMUM)){
1110 result = 0.1;
1111 power++;
1112 modifier /= 10;
1114 result *= resultsign;
1116 else {
1117 result = 0;
1118 power = 0;
1119 modifier = 0.1;
1123 /* -----------------------------------------------------------------------
1124 result2typingbuf() outputs standard format result to typingbuf.
1125 case SCIENTIFIC_FORMAT, let temppower = 1;
1126 case temppower > 0: print '.' in the middle
1127 case temppower <= 0: print '.' in the begining
1128 ----------------------------------------------------------------------- */
1129 void result2typingbuf(void)
1131 bool haveDot = false;
1132 char tempchar = 0;
1133 int k;
1134 double tempresult = ABS(result); /* positive num makes things simple */
1136 int temppower;
1137 double tempmodifier = 1;
1138 int count;
1140 if(SCIENTIFIC_FORMAT)
1141 temppower = 1; /* output x.xxxx format */
1142 else
1143 temppower = power;
1145 cleartypingbuf();
1147 if(tempresult < MINIMUM){ /* if 0,faster display and avoid complication*/
1148 typingbuf[0] = ' ';
1149 typingbuf[1] = '0';
1151 else{ /* tempresult > 0 */
1152 typingbuf[0] = (SIGN(result)<0)?'-':' ';
1154 typingbufPointer = typingbuf;
1155 if(temppower > 0){
1156 for (k = 0; k<DIGITLEN+1 ; k++){
1157 typingbufPointer++;
1158 if(temppower || *(typingbufPointer-1) == '.'){
1159 count = 0;
1160 tempmodifier = tempmodifier/10;
1161 while( (tempresult-tempmodifier*count) >
1162 (tempmodifier-MINIMUM)){
1163 count++;
1165 tempresult -= tempmodifier*count;
1166 tempresult = ABS(tempresult);
1167 temppower-- ;
1168 *typingbufPointer = count + '0';
1170 else{ /* temppower == 0 */
1171 *typingbufPointer = '.';
1172 haveDot = true;
1174 } /* for */
1176 else{
1177 haveDot = true;
1178 typingbufPointer++; *typingbufPointer = '0';
1179 typingbufPointer++; *typingbufPointer = '.';
1180 for (k = 2; k<DIGITLEN+1 ; k++){
1181 typingbufPointer++;
1182 count = 0;
1183 if ( (-temppower) < (k-1)){
1184 tempmodifier = tempmodifier/10;
1185 while((tempresult-tempmodifier*count)>(tempmodifier-MINIMUM)){
1186 count++;
1189 tempresult -= tempmodifier*count;
1190 tempresult = ABS(tempresult);
1191 temppower-- ;
1193 *typingbufPointer = count + '0';
1196 /* now, typingbufPointer = typingbuf + 16 */
1197 /* backward strip off 0 and '.' */
1198 if (haveDot){
1199 while( (*typingbufPointer == '0') || (*typingbufPointer == '.')){
1200 tempchar = *typingbufPointer;
1201 *typingbufPointer = 0;
1202 typingbufPointer--;
1203 if (tempchar == '.') break;
1206 typingbuf[DIGITLEN+1] = 0;
1207 } /* else tempresult > 0 */
1210 /* -----------------------------------------------------------------------
1211 printResult() generates LCD display.
1212 ----------------------------------------------------------------------- */
1213 void printResult(void)
1215 int k, w, h;
1217 char operbuf[3] = {0, 0, 0};
1219 switch_Status:
1220 switch(calStatus){
1221 case cal_exit:
1222 rb->lcd_clear_display();
1223 rb->splash(HZ/3, "Bye now!");
1224 break;
1225 case cal_error:
1226 clearbuf();
1227 rb->snprintf(buf, 19, "%18s","Error");
1228 break;
1229 case cal_toDo:
1230 clearbuf();
1231 rb->snprintf(buf, 19, "%18s","Coming soon ^_* ");
1232 break;
1234 case cal_normal:
1235 formatResult();
1237 if( power > 1000 ){ /* power -1 > 999 */
1238 calStatus = cal_error;
1239 goto switch_Status;
1241 if (power < -998 ) /* power -1 < -999 */
1242 clearResult(); /* too small, let it be 0 */
1244 result2typingbuf();
1245 clearbuf();
1247 operbuf[0] = oper;
1248 operbuf[1] = ( ABS(memTemp) > MINIMUM )?'M':' ';
1249 operbuf[2] = '\0';
1251 if(SCIENTIFIC_FORMAT){
1252 /* output format: X.XXXX eXXX */
1253 if(power > -98){ /* power-1 >= -99, eXXX or e-XX */
1254 rb->snprintf(buf, 12, "%11s",typingbuf);
1255 for(k=11;k<=14;k++) buf[k] = ' ';
1256 cleartypingbuf();
1257 rb->snprintf(typingbuf, 5, "e%d",power-1);
1258 rb->snprintf(buf+11, 5, "%4s",typingbuf);
1260 else{ /* power-1 <= -100, e-XXX */
1261 rb->snprintf(buf, 12, "%11s",typingbuf);
1262 rb->snprintf(buf+11, 6, "e%d",power-1);
1265 else{
1266 rb->snprintf(buf, 12, "%11s",typingbuf);
1267 } /* if SCIENTIFIC_FORMAT */
1268 break;
1269 case cal_typing:
1270 case cal_dotted:
1271 clearbuf();
1272 operbuf[0] = oper;
1273 operbuf[1] = ( ABS(memTemp) > MINIMUM )?'M':' ';
1274 rb->snprintf(buf, 12, "%11s",typingbuf);
1275 break;
1279 rb->lcd_getstringsize(buf, &w, &h);
1280 rb->screen_clear_area(rb->screens[0], 0, 0, LCD_WIDTH, Y_1_POS - 1);
1281 rb->lcd_putsxy(4, Y_1_POS - h -1, operbuf);
1282 rb->lcd_putsxy(LCD_WIDTH - w - 4, Y_1_POS - h -1, buf);
1283 rb->lcd_update_rect(0, 1, LCD_WIDTH, Y_1_POS);
1286 /* -----------------------------------------------------------------------
1287 Process typing buttons: 1-9, '.', sign
1288 main operand "result" and typingbuf are processed seperately here.
1289 ----------------------------------------------------------------------- */
1290 void typingProcess(void){
1291 switch( CAL_BUTTON ){
1292 case btn_sign:
1293 if (calStatus == cal_typing ||
1294 calStatus == cal_dotted)
1295 typingbuf[0] = (typingbuf[0]=='-')?' ':'-';
1296 result = -result;
1297 break;
1298 case btn_dot:
1299 operInputted = false;
1300 switch(calStatus){
1301 case cal_normal:
1302 clearInput();
1303 *typingbufPointer = '0';
1304 typingbufPointer++;
1305 case cal_typing:
1306 calStatus = cal_dotted;
1307 *typingbufPointer = '.';
1308 if (typingbufPointer != typingbuf+DIGITLEN+1)
1309 typingbufPointer++;
1310 break;
1311 default: /* cal_dotted */
1312 break;
1314 break;
1315 default: /* 0-9 */
1316 operInputted = false;
1317 /* normal,0; normal,1-9; typing,0; typing,1-9 */
1318 switch(calStatus){
1319 case cal_normal:
1320 if(CAL_BUTTON == btn_0 )
1321 break; /* first input is 0, ignore */
1322 clearInput();
1323 /*no operator means start a new calculation*/
1324 if (oper ==' ')
1325 clearOperand();
1326 calStatus = cal_typing;
1327 /* go on typing, no break */
1328 case cal_typing:
1329 case cal_dotted:
1330 switch(CAL_BUTTON){
1331 case btn_0:
1332 *typingbufPointer = '0';
1333 break;
1334 default:
1335 *typingbufPointer=(7+btn_col-3*(btn_row-1))+ '0';
1336 break;
1338 if (typingbufPointer!=typingbuf+DIGITLEN+1){
1339 typingbufPointer++;
1341 {/* result processing */
1342 if (calStatus == cal_typing) power++;
1343 if (CAL_BUTTON != btn_0)
1344 result= result +
1345 SIGN(result)*
1346 (7+btn_col-3*(btn_row-1))*modifier;
1347 modifier /= 10;
1350 else /* last byte always '\0' */
1351 *typingbufPointer = 0;
1352 break;
1353 default: /* cal_error, cal_exit */
1354 break;
1356 break; /* default, 0-9 */
1357 } /* switch( CAL_BUTTON ) */
1360 /* -----------------------------------------------------------------------
1361 Handle delete operation
1362 main operand "result" and typingbuf are processed seperately here.
1363 ----------------------------------------------------------------------- */
1364 void doDelete(void){
1365 deleteAnimation(18);
1366 switch(calStatus){
1367 case cal_dotted:
1368 if (*(typingbufPointer-1) == '.'){
1369 /* if dotted and deleting '.',
1370 change status and delete '.' below */
1371 calStatus = cal_typing;
1373 else{ /* if dotted and not deleting '.',
1374 power stays */
1375 power++; /* counter "power--;" below */
1377 case cal_typing:
1378 typingbufPointer--;
1380 {/* result processing */ /* 0-9, '.' */
1381 /* if deleting '.', do nothing */
1382 if ( *typingbufPointer != '.'){
1383 power--;
1384 modifier *= 10;
1385 result = result - SIGN(result)*
1386 ((*typingbufPointer)- '0')*modifier;
1390 *typingbufPointer = 0;
1392 /* if (only one digit left and it's 0)
1393 or no digit left, change status*/
1394 if ( typingbufPointer == typingbuf+1 ||
1395 ( typingbufPointer == typingbuf+2 &&
1396 *(typingbufPointer-1) == '0' ))
1397 calStatus = cal_normal;
1398 break;
1399 default: /* normal, error, exit */
1400 break;
1403 /* -----------------------------------------------------------------------
1404 Handle buttons on basic screen
1405 ----------------------------------------------------------------------- */
1406 void basicButtonsProcess(void){
1407 switch (btn) {
1408 case CALCULATOR_INPUT:
1409 if (calStatus == cal_error && (CAL_BUTTON != btn_C) ) break;
1410 flashButton();
1411 switch( CAL_BUTTON ){
1412 case btn_MR:
1413 operInputted = false;
1414 result = memTemp; power = memTempPower;
1415 calStatus = cal_normal;
1416 break;
1417 case btn_M:
1418 formatResult();
1419 if (memTemp > MINIMUM)
1420 doAdd(&memTemp, &memTempPower, result, power);
1421 else {
1422 /* if result is too small and memTemp = 0,
1423 doAdd will not add */
1424 memTemp = result;
1425 memTempPower = power;
1427 calStatus = cal_normal;
1428 break;
1430 case btn_C: clearMem(); break;
1431 case btn_CE: clearInput(); break;
1433 case btn_bas:
1434 buttonGroup = sciButtons;
1435 printButtonGroups(buttonGroup);
1436 break;
1438 /* one operand calculation, may be changed to
1439 like sin, cos, log, etc */
1440 case btn_sqr:
1441 case btn_square:
1442 case btn_rec:
1443 formatResult(); /* not necessary, just for safty */
1444 oneOperand();
1445 break;
1447 case_btn_equal: /* F3 shortkey entrance */
1448 case btn_equal:
1449 formatResult();
1450 calStatus = cal_normal;
1451 operInputted = false;
1452 if (oper != ' ') twoOperands();
1453 break;
1455 case btn_div:
1456 case btn_time:
1457 case btn_minus:
1458 case btn_add:
1459 if(!operInputted) {twoOperands(); operInputted = true;}
1460 oper = buttonChar[basicButtons][btn_row][btn_col][0];
1461 #ifdef CALCULATOR_OPERATORS
1462 case_cycle_operators: /* F2 shortkey entrance */
1463 #endif
1464 calStatus = cal_normal;
1465 formatResult();
1466 operand = result;
1467 operandPower = power;
1469 break;
1471 case btn_sign:
1472 case btn_dot:
1473 default: /* 0-9 */
1474 typingProcess();
1475 break;
1476 } /* switch (CAL_BUTTON) */
1477 break;
1479 #ifdef CALCULATOR_OPERATORS
1480 case CALCULATOR_OPERATORS:
1481 if (calStatus == cal_error) break;
1482 if (!operInputted) {twoOperands(); operInputted = true;}
1483 switch (oper){
1484 case ' ':
1485 case '/': oper = '+'; flashButton(); break;
1486 case '+': oper = '-'; flashButton(); break;
1487 case '-': oper = '*'; flashButton(); break;
1488 case '*': oper = '/'; flashButton(); break;
1490 goto case_cycle_operators;
1491 break;
1492 #endif
1494 case CALCULATOR_CALC:
1495 if (calStatus == cal_error) break;
1496 flashButton();
1497 goto case_btn_equal;
1498 break;
1499 default: break;
1501 printResult();
1504 /* -----------------------------------------------------------------------
1505 Handle buttons on scientific screen
1506 ----------------------------------------------------------------------- */
1507 void sciButtonsProcess(void){
1508 switch (btn) {
1509 case CALCULATOR_INPUT:
1510 if (calStatus == cal_error && (CAL_BUTTON != sci_sci) ) break;
1511 flashButton();
1512 switch( CAL_BUTTON ){
1514 case sci_pi:
1515 result = M_PI; power = 0;
1516 calStatus = cal_normal;
1517 break;
1519 case sci_xy: break;
1521 case sci_sci:
1522 buttonGroup = basicButtons;
1523 printButtonGroups(basicButtons);
1524 break;
1526 case sci_fac:
1527 case sci_sin:
1528 case sci_asin:
1529 case sci_cos:
1530 case sci_acos:
1531 case sci_tan:
1532 case sci_atan:
1533 case sci_ln:
1534 case sci_exp:
1535 case sci_log:
1536 formatResult(); /* not necessary, just for safty */
1537 oneOperand();
1538 break;
1540 case btn_sign:
1541 case btn_dot:
1542 default: /* 0-9 */
1543 typingProcess();
1544 break;
1545 } /* switch (CAL_BUTTON) */
1546 break;
1548 #ifdef CALCULATOR_OPERATORS
1549 case CALCULATOR_OPERATORS:
1550 if (calStatus == cal_error) break;
1551 if (!operInputted) {twoOperands(); operInputted = true;}
1552 switch (oper){
1553 case ' ': oper = '+'; break;
1554 case '/': oper = '+'; deleteAnimation(1); break;
1555 case '+': oper = '-'; deleteAnimation(1); break;
1556 case '-': oper = '*'; deleteAnimation(1); break;
1557 case '*': oper = '/'; deleteAnimation(1); break;
1559 calStatus = cal_normal;
1560 formatResult();
1561 operand = result;
1562 operandPower = power;
1563 break;
1564 #endif
1566 case CALCULATOR_CALC:
1567 if (calStatus == cal_error) break;
1568 formatResult();
1569 calStatus = cal_normal;
1570 operInputted = false;
1571 if (oper != ' ') twoOperands();
1572 break;
1573 default: break;
1575 printResult();
1578 /* -----------------------------------------------------------------------
1579 move button index
1580 Invert display new button, invert back previous button
1581 ----------------------------------------------------------------------- */
1582 int handleButton(int button){
1583 switch(button)
1585 case CALCULATOR_INPUT:
1586 case CALCULATOR_CALC:
1587 #ifdef CALCULATOR_INPUT_CALC_PRE
1588 if (lastbtn != CALCULATOR_INPUT_CALC_PRE)
1589 break;
1590 /* no unconditional break; here! */
1591 #endif
1592 #ifdef CALCULATOR_OPERATORS
1593 case CALCULATOR_OPERATORS:
1594 #endif
1595 switch(buttonGroup){
1596 case basicButtons:
1597 basicButtonsProcess();
1598 break;
1599 case sciButtons:
1600 sciButtonsProcess();
1601 break;
1603 break;
1605 #ifdef CALCULATOR_CLEAR
1606 case CALCULATOR_CLEAR:
1607 switch(calStatus){
1608 case cal_typing:
1609 case cal_dotted:
1610 doDelete();
1611 break;
1612 default: /* cal_normal, cal_error, cal_exit */
1613 clearMem();
1614 break;
1616 printResult();
1617 break;
1618 #endif
1619 case CALCULATOR_LEFT:
1620 case CALCULATOR_LEFT | BUTTON_REPEAT:
1621 move_with_wrap_and_shift(
1622 &btn_col, -1, BUTTON_COLS,
1623 &btn_row, 0, BUTTON_ROWS);
1624 break;
1626 case CALCULATOR_RIGHT:
1627 case CALCULATOR_RIGHT | BUTTON_REPEAT:
1628 move_with_wrap_and_shift(
1629 &btn_col, 1, BUTTON_COLS,
1630 &btn_row, 0, BUTTON_ROWS);
1631 break;
1633 #ifdef CALCULATOR_UP
1634 case CALCULATOR_UP:
1635 case CALCULATOR_UP | BUTTON_REPEAT:
1636 move_with_wrap_and_shift(
1637 &btn_row, -1, BUTTON_ROWS,
1638 &btn_col, 0, BUTTON_COLS);
1639 break;
1640 #endif
1641 #ifdef CALCULATOR_DOWN
1642 case CALCULATOR_DOWN:
1643 case CALCULATOR_DOWN | BUTTON_REPEAT:
1644 move_with_wrap_and_shift(
1645 &btn_row, 1, BUTTON_ROWS,
1646 &btn_col, 0, BUTTON_COLS);
1647 break;
1648 #endif
1650 #ifdef CALCULATOR_UP_W_SHIFT
1651 case CALCULATOR_UP_W_SHIFT:
1652 case CALCULATOR_UP_W_SHIFT | BUTTON_REPEAT:
1653 move_with_wrap_and_shift(
1654 &btn_row, -1, BUTTON_ROWS,
1655 &btn_col, -1, BUTTON_COLS);
1656 break;
1657 #endif
1658 #ifdef CALCULATOR_DOWN_W_SHIFT
1659 case CALCULATOR_DOWN_W_SHIFT:
1660 case CALCULATOR_DOWN_W_SHIFT | BUTTON_REPEAT:
1661 move_with_wrap_and_shift(
1662 &btn_row, 1, BUTTON_ROWS,
1663 &btn_col, 1, BUTTON_COLS);
1664 break;
1665 #endif
1666 #ifdef CALCULATOR_LEFT_W_SHIFT
1667 case CALCULATOR_LEFT_W_SHIFT:
1668 case CALCULATOR_LEFT_W_SHIFT | BUTTON_REPEAT:
1669 move_with_wrap_and_shift(
1670 &btn_col, -1, BUTTON_COLS,
1671 &btn_row, -1, BUTTON_ROWS);
1672 break;
1673 #endif
1674 #ifdef CALCULATOR_RIGHT_W_SHIFT
1675 case CALCULATOR_RIGHT_W_SHIFT:
1676 case CALCULATOR_RIGHT_W_SHIFT | BUTTON_REPEAT:
1677 move_with_wrap_and_shift(
1678 &btn_col, 1, BUTTON_COLS,
1679 &btn_row, 1, BUTTON_ROWS);
1680 break;
1681 #endif
1682 #ifdef CALCULATOR_RC_QUIT
1683 case CALCULATOR_RC_QUIT:
1684 #endif
1685 case CALCULATOR_QUIT:
1686 return -1;
1689 return 0;
1691 prev_btn_row = btn_row;
1692 prev_btn_col = btn_col;
1695 /* -----------------------------------------------------------------------
1696 Main();
1697 ----------------------------------------------------------------------- */
1698 enum plugin_status plugin_start(const void* parameter)
1700 (void)parameter;
1702 /* now go ahead and have fun! */
1704 #ifdef HAVE_TOUCHSCREEN
1705 rb->touchscreen_set_mode(TOUCHSCREEN_POINT);
1706 #endif
1708 cal_initial();
1710 while (calStatus != cal_exit ) {
1711 btn = rb->button_get_w_tmo(HZ/2);
1712 #ifdef HAVE_TOUCHSCREEN
1713 if(btn & BUTTON_TOUCHSCREEN)
1715 struct ts_raster_result res;
1716 if(touchscreen_map_raster(&calc_raster, rb->button_get_data() >> 16,
1717 rb->button_get_data() & 0xffff, &res) == 1)
1719 btn_row = res.y;
1720 btn_col = res.x;
1721 drawButtons(buttonGroup);
1722 drawLines();
1724 rb->lcd_update();
1726 prev_btn_row = btn_row;
1727 prev_btn_col = btn_col;
1728 if(btn & BUTTON_REL)
1730 btn = CALCULATOR_INPUT;
1731 switch(buttonGroup){
1732 case basicButtons:
1733 basicButtonsProcess();
1734 break;
1735 case sciButtons:
1736 sciButtonsProcess();
1737 break;
1739 btn = BUTTON_TOUCHSCREEN;
1743 #endif
1744 if (handleButton(btn) == -1)
1746 calStatus = cal_exit;
1747 printResult();
1749 else
1751 drawButtons(buttonGroup);
1752 drawLines();
1755 rb->lcd_update();
1757 if(rb->default_event_handler(btn) == SYS_USB_CONNECTED)
1758 return PLUGIN_USB_CONNECTED;
1760 if (btn != BUTTON_NONE)
1761 lastbtn = btn;
1762 } /* while (calStatus != cal_exit ) */
1764 rb->button_clear_queue();
1765 return PLUGIN_OK;
1768 #endif /* #ifdef HAVE_LCD_BITMAP */