Packard Bell Vibe 500: More plugin keymaps (second portion).
[kugel-rb.git] / apps / plugins / calculator.c
blob4e40625356aa4d1ffd4cb5693d876c5dc217eeb1
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2004 Pengxuan Liu (Isaac)
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
23 00 01 21 22 23 43 44 45 65 66 67 87 88 89 109110111
24 00 |-----------|-----------|-----------|-----------|-----------|
25 01 | | | | | |
26 |***********|***********|***********|***********|***********|
27 |***********|***********|***********|***********|***********|
28 11 | | | | | |
29 12 |-----------|-----------|-----------|-----------|-----------|
30 13 |-----------|-----------|-----------|-----------|-----------| y1
31 14 | | | | | |
32 | | | | | |
33 22 | | | | | |
34 23 |-----------|-----------|-----------|-----------|-----------| y2
35 24 | | | | | |
36 | | | | | |
37 32 | | | | | |
38 33 |-----------|-----------|-----------|-----------|-----------| y3
39 34 | | | | | |
40 | | | | | |
41 42 | | | | | |
42 43 |-----------|-----------|-----------|-----------|-----------| y4
43 44 | | | | | |
44 | | | | | |
45 52 | | | | | |
46 53 |-----------|-----------|-----------|-----------|-----------| y5
47 54 | | | | | |
48 | | | | | |
49 62 | | | | | |
50 63 |-----------|-----------|-----------|-----------|-----------| y6
51 x0 x1 x2 x3 x4 x5
54 /*---------------------------------------------------------------------------
55 Features:
56 - Scientific number format core code. Support range 10^-999 ~ 10^999
57 - Number of significant figures up to 10
59 Limitations:
60 - Right now, only accept "num, operator (+,-,*,/), num, =" input sequence.
61 Input "3, +, 5, -, 2, =", the calculator will only do 5-2 and result = 3
62 You have to input "3, +, 5, =, -, 2, =" to get 3+5-2 = 6
64 - "*,/" have no priority. Actually you can't input 3+5*2 yet.
66 User Instructions:
67 use arrow button to move cursor, "play" button to select, "off" button to exit
68 F1: if typing numbers, it's equal to "Del"; otherwise, equal to "C"
69 F2: circle input "+, -, *, /"
70 F3: equal to "="
72 "MR" : load temp memory
73 "M+" : add currently display to temp memory
74 "C" : reset calculator
75 ---------------------------------------------------------------------------*/
77 #include "plugin.h"
78 #ifdef HAVE_LCD_BITMAP
79 #include "math.h"
81 PLUGIN_HEADER
83 #define BUTTON_ROWS 5
84 #define BUTTON_COLS 5
86 #define REC_HEIGHT (int)(LCD_HEIGHT / (BUTTON_ROWS + 1))
87 #define REC_WIDTH (int)(LCD_WIDTH / BUTTON_COLS)
89 #define Y_6_POS (LCD_HEIGHT) /* Leave room for the border */
90 #define Y_5_POS (Y_6_POS - REC_HEIGHT) /* y5 = 53 */
91 #define Y_4_POS (Y_5_POS - REC_HEIGHT) /* y4 = 43 */
92 #define Y_3_POS (Y_4_POS - REC_HEIGHT) /* y3 = 33 */
93 #define Y_2_POS (Y_3_POS - REC_HEIGHT) /* y2 = 23 */
94 #define Y_1_POS (Y_2_POS - REC_HEIGHT) /* y1 = 13 */
95 #define Y_0_POS 0 /* y0 = 0 */
97 #define X_0_POS 0 /* x0 = 0 */
98 #define X_1_POS (X_0_POS + REC_WIDTH) /* x1 = 22 */
99 #define X_2_POS (X_1_POS + REC_WIDTH) /* x2 = 44 */
100 #define X_3_POS (X_2_POS + REC_WIDTH) /* x3 = 66 */
101 #define X_4_POS (X_3_POS + REC_WIDTH) /* x4 = 88 */
102 #define X_5_POS (X_4_POS + REC_WIDTH) /* x5 = 110, column 111 left blank */
104 #define SIGN(x) ((x)<0?-1:1)
106 /* variable button definitions */
107 #if CONFIG_KEYPAD == RECORDER_PAD
108 #define CALCULATOR_LEFT BUTTON_LEFT
109 #define CALCULATOR_RIGHT BUTTON_RIGHT
110 #define CALCULATOR_UP BUTTON_UP
111 #define CALCULATOR_DOWN BUTTON_DOWN
112 #define CALCULATOR_QUIT BUTTON_OFF
113 #define CALCULATOR_INPUT BUTTON_PLAY
114 #define CALCULATOR_CALC BUTTON_F3
115 #define CALCULATOR_OPERATORS BUTTON_F2
116 #define CALCULATOR_CLEAR BUTTON_F1
118 #elif CONFIG_KEYPAD == ARCHOS_AV300_PAD
119 #define CALCULATOR_LEFT BUTTON_LEFT
120 #define CALCULATOR_RIGHT BUTTON_RIGHT
121 #define CALCULATOR_UP BUTTON_UP
122 #define CALCULATOR_DOWN BUTTON_DOWN
123 #define CALCULATOR_QUIT BUTTON_OFF
124 #define CALCULATOR_INPUT BUTTON_SELECT
125 #define CALCULATOR_CALC BUTTON_F3
126 #define CALCULATOR_OPERATORS BUTTON_F2
127 #define CALCULATOR_CLEAR BUTTON_F1
129 #elif CONFIG_KEYPAD == ONDIO_PAD
130 #define CALCULATOR_LEFT BUTTON_LEFT
131 #define CALCULATOR_RIGHT BUTTON_RIGHT
132 #define CALCULATOR_UP BUTTON_UP
133 #define CALCULATOR_DOWN BUTTON_DOWN
134 #define CALCULATOR_QUIT BUTTON_OFF
135 #define CALCULATOR_INPUT_CALC_PRE BUTTON_MENU
136 #define CALCULATOR_INPUT (BUTTON_MENU | BUTTON_REL)
137 #define CALCULATOR_CALC (BUTTON_MENU | BUTTON_REPEAT)
139 #elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || \
140 (CONFIG_KEYPAD == IRIVER_H300_PAD)
141 #define CALCULATOR_LEFT BUTTON_LEFT
142 #define CALCULATOR_RIGHT BUTTON_RIGHT
143 #define CALCULATOR_UP BUTTON_UP
144 #define CALCULATOR_DOWN BUTTON_DOWN
145 #define CALCULATOR_QUIT BUTTON_OFF
146 #define CALCULATOR_INPUT BUTTON_SELECT
147 #define CALCULATOR_CALC BUTTON_ON
148 #define CALCULATOR_OPERATORS BUTTON_MODE
149 #define CALCULATOR_CLEAR BUTTON_REC
151 #define CALCULATOR_RC_QUIT BUTTON_RC_STOP
153 #elif (CONFIG_KEYPAD == IPOD_4G_PAD) || \
154 (CONFIG_KEYPAD == IPOD_3G_PAD) || \
155 (CONFIG_KEYPAD == IPOD_1G2G_PAD)
157 #define CALCULATOR_LEFT BUTTON_LEFT
158 #define CALCULATOR_RIGHT BUTTON_RIGHT
159 #define CALCULATOR_UP_W_SHIFT BUTTON_SCROLL_BACK
160 #define CALCULATOR_DOWN_W_SHIFT BUTTON_SCROLL_FWD
161 #define CALCULATOR_QUIT BUTTON_MENU
162 #define CALCULATOR_INPUT BUTTON_SELECT
163 #define CALCULATOR_CALC BUTTON_PLAY
165 #elif (CONFIG_KEYPAD == IAUDIO_X5M5_PAD)
167 #define CALCULATOR_LEFT BUTTON_LEFT
168 #define CALCULATOR_RIGHT BUTTON_RIGHT
169 #define CALCULATOR_UP BUTTON_UP
170 #define CALCULATOR_DOWN BUTTON_DOWN
171 #define CALCULATOR_QUIT BUTTON_POWER
172 #define CALCULATOR_INPUT BUTTON_SELECT
173 #define CALCULATOR_CALC BUTTON_PLAY
174 #define CALCULATOR_CLEAR BUTTON_REC
176 #elif (CONFIG_KEYPAD == GIGABEAT_PAD)
178 #define CALCULATOR_LEFT BUTTON_LEFT
179 #define CALCULATOR_RIGHT BUTTON_RIGHT
180 #define CALCULATOR_UP BUTTON_UP
181 #define CALCULATOR_DOWN BUTTON_DOWN
182 #define CALCULATOR_QUIT BUTTON_POWER
183 #define CALCULATOR_INPUT BUTTON_SELECT
184 #define CALCULATOR_CALC BUTTON_MENU
185 #define CALCULATOR_CLEAR BUTTON_A
187 #elif (CONFIG_KEYPAD == SANSA_E200_PAD)
188 #define CALCULATOR_LEFT BUTTON_LEFT
189 #define CALCULATOR_RIGHT BUTTON_RIGHT
190 #define CALCULATOR_UP BUTTON_UP
191 #define CALCULATOR_DOWN BUTTON_DOWN
192 #define CALCULATOR_UP_W_SHIFT BUTTON_SCROLL_BACK
193 #define CALCULATOR_DOWN_W_SHIFT BUTTON_SCROLL_FWD
194 #define CALCULATOR_QUIT BUTTON_POWER
195 #define CALCULATOR_INPUT_CALC_PRE BUTTON_SELECT
196 #define CALCULATOR_INPUT (BUTTON_SELECT|BUTTON_REL)
197 #define CALCULATOR_CALC (BUTTON_SELECT|BUTTON_REPEAT)
198 #define CALCULATOR_CLEAR BUTTON_REC
200 #elif (CONFIG_KEYPAD == SANSA_C200_PAD)
201 #define CALCULATOR_LEFT BUTTON_LEFT
202 #define CALCULATOR_RIGHT BUTTON_RIGHT
203 #define CALCULATOR_UP BUTTON_UP
204 #define CALCULATOR_DOWN BUTTON_DOWN
205 #define CALCULATOR_QUIT BUTTON_POWER
206 #define CALCULATOR_INPUT_CALC_PRE BUTTON_SELECT
207 #define CALCULATOR_INPUT (BUTTON_SELECT|BUTTON_REL)
208 #define CALCULATOR_CALC (BUTTON_SELECT|BUTTON_REPEAT)
210 #elif (CONFIG_KEYPAD == SANSA_FUZE_PAD)
211 #define CALCULATOR_LEFT BUTTON_LEFT
212 #define CALCULATOR_RIGHT BUTTON_RIGHT
213 #define CALCULATOR_UP BUTTON_UP
214 #define CALCULATOR_DOWN BUTTON_DOWN
215 #define CALCULATOR_UP_W_SHIFT BUTTON_SCROLL_BACK
216 #define CALCULATOR_DOWN_W_SHIFT BUTTON_SCROLL_FWD
217 #define CALCULATOR_QUIT (BUTTON_HOME|BUTTON_REPEAT)
218 #define CALCULATOR_INPUT_CALC_PRE BUTTON_SELECT
219 #define CALCULATOR_INPUT (BUTTON_SELECT|BUTTON_REL)
220 #define CALCULATOR_CALC (BUTTON_SELECT|BUTTON_REPEAT)
221 #define CALCULATOR_CLEAR BUTTON_HOME
224 #elif (CONFIG_KEYPAD == SANSA_CLIP_PAD)
225 #define CALCULATOR_LEFT BUTTON_LEFT
226 #define CALCULATOR_RIGHT BUTTON_RIGHT
227 #define CALCULATOR_UP BUTTON_UP
228 #define CALCULATOR_DOWN BUTTON_DOWN
229 #define CALCULATOR_QUIT BUTTON_POWER
230 #define CALCULATOR_INPUT_CALC_PRE BUTTON_SELECT
231 #define CALCULATOR_INPUT (BUTTON_SELECT|BUTTON_REL)
232 #define CALCULATOR_CALC (BUTTON_SELECT|BUTTON_REPEAT)
233 #define CALCULATOR_CLEAR BUTTON_HOME
235 #elif (CONFIG_KEYPAD == SANSA_M200_PAD)
236 #define CALCULATOR_LEFT BUTTON_LEFT
237 #define CALCULATOR_RIGHT BUTTON_RIGHT
238 #define CALCULATOR_UP BUTTON_UP
239 #define CALCULATOR_DOWN BUTTON_DOWN
240 #define CALCULATOR_QUIT BUTTON_POWER
241 #define CALCULATOR_INPUT_CALC_PRE BUTTON_SELECT
242 #define CALCULATOR_INPUT (BUTTON_SELECT|BUTTON_REL)
243 #define CALCULATOR_CALC (BUTTON_SELECT|BUTTON_REPEAT)
244 #define CALCULATOR_CLEAR (BUTTON_SELECT|BUTTON_UP)
246 #elif (CONFIG_KEYPAD == IRIVER_H10_PAD)
248 #define CALCULATOR_LEFT BUTTON_LEFT
249 #define CALCULATOR_RIGHT BUTTON_RIGHT
250 #define CALCULATOR_UP BUTTON_SCROLL_UP
251 #define CALCULATOR_DOWN BUTTON_SCROLL_DOWN
252 #define CALCULATOR_QUIT BUTTON_POWER
253 #define CALCULATOR_INPUT_CALC_PRE BUTTON_PLAY
254 #define CALCULATOR_INPUT (BUTTON_PLAY | BUTTON_REL)
255 #define CALCULATOR_CALC (BUTTON_PLAY | BUTTON_REPEAT)
256 #define CALCULATOR_CLEAR BUTTON_REW
258 #elif (CONFIG_KEYPAD == GIGABEAT_S_PAD)
260 #define CALCULATOR_LEFT BUTTON_LEFT
261 #define CALCULATOR_RIGHT BUTTON_RIGHT
262 #define CALCULATOR_UP BUTTON_UP
263 #define CALCULATOR_DOWN BUTTON_DOWN
264 #define CALCULATOR_QUIT BUTTON_BACK
265 #define CALCULATOR_INPUT BUTTON_SELECT
266 #define CALCULATOR_CALC BUTTON_MENU
267 #define CALCULATOR_CLEAR BUTTON_PLAY
269 #elif (CONFIG_KEYPAD == MROBE100_PAD)
271 #define CALCULATOR_LEFT BUTTON_LEFT
272 #define CALCULATOR_RIGHT BUTTON_RIGHT
273 #define CALCULATOR_UP BUTTON_UP
274 #define CALCULATOR_DOWN BUTTON_DOWN
275 #define CALCULATOR_QUIT BUTTON_POWER
276 #define CALCULATOR_INPUT BUTTON_SELECT
277 #define CALCULATOR_CALC BUTTON_MENU
278 #define CALCULATOR_CLEAR BUTTON_DISPLAY
280 #elif CONFIG_KEYPAD == IAUDIO_M3_PAD
282 #define CALCULATOR_LEFT BUTTON_RC_REW
283 #define CALCULATOR_RIGHT BUTTON_RC_FF
284 #define CALCULATOR_UP BUTTON_RC_VOL_UP
285 #define CALCULATOR_DOWN BUTTON_RC_VOL_DOWN
286 #define CALCULATOR_QUIT BUTTON_RC_REC
287 #define CALCULATOR_INPUT BUTTON_RC_PLAY
288 #define CALCULATOR_CALC BUTTON_RC_MODE
289 #define CALCULATOR_CLEAR BUTTON_RC_MENU
291 #define CALCULATOR_RC_QUIT BUTTON_REC
293 #elif (CONFIG_KEYPAD == COWON_D2_PAD)
295 #define CALCULATOR_QUIT BUTTON_POWER
296 #define CALCULATOR_CLEAR BUTTON_MENU
298 #elif CONFIG_KEYPAD == IAUDIO67_PAD
300 #define CALCULATOR_LEFT BUTTON_LEFT
301 #define CALCULATOR_RIGHT BUTTON_RIGHT
302 #define CALCULATOR_UP BUTTON_VOLUP
303 #define CALCULATOR_DOWN BUTTON_VOLDOWN
304 #define CALCULATOR_QUIT BUTTON_POWER
305 #define CALCULATOR_INPUT BUTTON_PLAY
306 #define CALCULATOR_CALC BUTTON_MENU
307 #define CALCULATOR_CLEAR BUTTON_STOP
309 #define CALCULATOR_RC_QUIT (BUTTON_MENU|BUTTON_PLAY)
311 #elif (CONFIG_KEYPAD == CREATIVEZVM_PAD)
313 #define CALCULATOR_LEFT BUTTON_LEFT
314 #define CALCULATOR_RIGHT BUTTON_RIGHT
315 #define CALCULATOR_UP BUTTON_UP
316 #define CALCULATOR_DOWN BUTTON_DOWN
317 #define CALCULATOR_QUIT BUTTON_BACK
318 #define CALCULATOR_INPUT BUTTON_SELECT
319 #define CALCULATOR_CALC BUTTON_MENU
320 #define CALCULATOR_CLEAR BUTTON_PLAY
322 #elif CONFIG_KEYPAD == PHILIPS_HDD1630_PAD
324 #define CALCULATOR_LEFT BUTTON_LEFT
325 #define CALCULATOR_RIGHT BUTTON_RIGHT
326 #define CALCULATOR_UP BUTTON_UP
327 #define CALCULATOR_DOWN BUTTON_DOWN
328 #define CALCULATOR_QUIT BUTTON_POWER
329 #define CALCULATOR_INPUT BUTTON_SELECT
330 #define CALCULATOR_CALC BUTTON_MENU
331 #define CALCULATOR_CLEAR BUTTON_VIEW
333 #elif CONFIG_KEYPAD == PHILIPS_SA9200_PAD
335 #define CALCULATOR_LEFT BUTTON_PREV
336 #define CALCULATOR_RIGHT BUTTON_NEXT
337 #define CALCULATOR_UP BUTTON_UP
338 #define CALCULATOR_DOWN BUTTON_DOWN
339 #define CALCULATOR_QUIT BUTTON_POWER
340 #define CALCULATOR_INPUT BUTTON_PLAY
341 #define CALCULATOR_CALC BUTTON_MENU
342 #define CALCULATOR_CLEAR BUTTON_RIGHT
344 #elif (CONFIG_KEYPAD == ONDAVX747_PAD)
346 #define CALCULATOR_QUIT BUTTON_POWER
347 #define CALCULATOR_CLEAR BUTTON_MENU
349 #elif (CONFIG_KEYPAD == ONDAVX777_PAD)
350 #define CALCULATOR_QUIT BUTTON_POWER
352 #elif CONFIG_KEYPAD == MROBE500_PAD
353 #define CALCULATOR_QUIT BUTTON_POWER
355 #elif CONFIG_KEYPAD == SAMSUNG_YH_PAD
357 #define CALCULATOR_LEFT BUTTON_LEFT
358 #define CALCULATOR_RIGHT BUTTON_RIGHT
359 #define CALCULATOR_UP BUTTON_UP
360 #define CALCULATOR_DOWN BUTTON_DOWN
361 #define CALCULATOR_QUIT BUTTON_REC
362 #define CALCULATOR_INPUT BUTTON_PLAY
363 #define CALCULATOR_CALC BUTTON_FFWD
364 #define CALCULATOR_CLEAR BUTTON_REW
366 #elif CONFIG_KEYPAD == PBELL_VIBE500_PAD
368 #define CALCULATOR_LEFT BUTTON_PREV
369 #define CALCULATOR_RIGHT BUTTON_NEXT
370 #define CALCULATOR_UP BUTTON_UP
371 #define CALCULATOR_DOWN BUTTON_DOWN
372 #define CALCULATOR_QUIT BUTTON_REC
373 #define CALCULATOR_INPUT BUTTON_OK
374 #define CALCULATOR_CALC BUTTON_PLAY
375 #define CALCULATOR_CLEAR BUTTON_CANCEL
377 #else
378 #error No keymap defined!
379 #endif
381 #ifdef HAVE_TOUCHSCREEN
382 #ifndef CALCULATOR_LEFT
383 #define CALCULATOR_LEFT BUTTON_MIDLEFT
384 #endif
385 #ifndef CALCULATOR_RIGHT
386 #define CALCULATOR_RIGHT BUTTON_MIDRIGHT
387 #endif
388 #ifndef CALCULATOR_UP
389 #define CALCULATOR_UP BUTTON_TOPMIDDLE
390 #endif
391 #ifndef CALCULATOR_DOWN
392 #define CALCULATOR_DOWN BUTTON_BOTTOMMIDDLE
393 #endif
394 #ifndef CALCULATOR_CALC
395 #define CALCULATOR_CALC BUTTON_BOTTOMRIGHT
396 #endif
397 #ifndef CALCULATOR_INPUT
398 #define CALCULATOR_INPUT BUTTON_CENTER
399 #endif
400 #ifndef CALCULATOR_CLEAR
401 #define CALCULATOR_CLEAR BUTTON_TOPRIGHT
402 #endif
404 #include "lib/pluginlib_touchscreen.h"
405 static struct ts_raster calc_raster = { X_0_POS, Y_1_POS,
406 BUTTON_COLS*REC_WIDTH, BUTTON_ROWS*REC_HEIGHT, REC_WIDTH, REC_HEIGHT };
407 #endif
409 enum {
410 basicButtons,
411 sciButtons
412 } buttonGroup;
414 unsigned char* buttonChar[2][5][5] = {
415 { { "MR" , "M+" , "2nd" , "CE" , "C" },
416 { "7" , "8" , "9" , "/" , "sqr" },
417 { "4" , "5" , "6" , "*" , "x^2" },
418 { "1" , "2" , "3" , "-" , "1/x" },
419 { "0" , "+/-", "." , "+" , "=" } },
421 { { "n!" , "PI" , "1st" , "sin" , "asi" },
422 { "7" , "8" , "9" , "cos" , "aco" },
423 { "4" , "5" , "6" , "tan" , "ata" },
424 { "1" , "2" , "3" , "ln" , "e^x" },
425 { "0" , "+/-", "." , "log" , "x^y" } }
428 enum { btn_MR , btn_M , btn_bas , btn_CE , btn_C ,
429 btn_7 , btn_8 , btn_9 , btn_div , btn_sqr ,
430 btn_4 , btn_5 , btn_6 , btn_time , btn_square ,
431 btn_1 , btn_2 , btn_3 , btn_minus , btn_rec ,
432 btn_0 , btn_sign , btn_dot , btn_add , btn_equal
435 enum { sci_fac, sci_pi , sci_sci , sci_sin , sci_asin ,
436 sci_7 , sci_8 , sci_9 , sci_cos , sci_acos ,
437 sci_4 , sci_5 , sci_6 , sci_tan , sci_atan ,
438 sci_1 , sci_2 , sci_3 , sci_ln , sci_exp ,
439 sci_0 , sci_sign , sci_dot , sci_log , sci_xy
442 #define MINIMUM 0.000000000001 /* e-12 */
443 /* ^ ^ ^ ^ */
444 /* 123456789abcdef */
446 #define DIGITLEN 10 /* must <= 10 */
447 #define SCIENTIFIC_FORMAT ( power < -(DIGITLEN-3) || power > (DIGITLEN))
448 /* 0.000 00000 0001 */
449 /* ^ ^ ^ ^ ^ ^ */
450 /* DIGITLEN 12345 6789a bcdef */
451 /* power 12 34567 89abc def */
452 /* 10^- 123 45678 9abcd ef */
454 unsigned char buf[19];/* 18 bytes of output line,
455 buf[0] is operator
456 buf[1] = 'M' if memTemp is not 0
457 buf[2] = ' '
459 if SCIENTIFIC_FORMAT
460 buf[2]-buf[12] or buf[3]-buf[13] = result;
461 format X.XXXXXXXX
462 buf[13] or buf[14] -buf[17] = power;
463 format eXXX or e-XXX
464 else
465 buf[3]-buf[6] = ' ';
466 buf[7]-buf[17] = result;
468 buf[18] = '\0' */
470 unsigned char typingbuf[DIGITLEN+2];/* byte 0 is sign or ' ',
471 byte 1~DIGITLEN are num and '.'
472 byte (DIGITLEN+1) is '\0' */
473 unsigned char* typingbufPointer = typingbuf;
475 double result = 0; /* main operand, format 0.xxxxx */
476 int power = 0; /* 10^power */
477 double modifier = 0.1; /* position of next input */
478 double operand = 0; /* second operand, format 0.xxxxx */
479 int operandPower = 0; /* 10^power of second operand */
480 char oper = ' '; /* operators: + - * / */
481 bool operInputted = false; /* false: do calculation first and
482 replace current oper
483 true: just replace current oper */
485 double memTemp = 0; /* temp memory */
486 int memTempPower = 0; /* 10^^power of memTemp */
488 int btn_row, btn_col; /* current position index for button */
489 int prev_btn_row, prev_btn_col; /* previous cursor position */
490 #define CAL_BUTTON (btn_row*5+btn_col)
492 int btn = BUTTON_NONE;
493 int lastbtn = BUTTON_NONE;
495 /* Status of calculator */
496 enum {cal_normal, /* 0, normal status, display result */
497 cal_typing, /* 1, currently typing, dot hasn't been typed */
498 cal_dotted, /* 2, currently typing, dot already has been typed. */
499 cal_error,
500 cal_exit,
501 cal_toDo
502 } calStatus;
504 /* constant table for CORDIC algorithm */
505 double cordicTable[51][2]= {
506 /* pow(2,0) - pow(2,-50) atan(pow(2,0) - atan(pow(2,-50) */
507 {1e+00, 7.853981633974483e-01},
508 {5e-01, 4.636476090008061e-01},
509 {2.5e-01, 2.449786631268641e-01},
510 {1.25e-01, 1.243549945467614e-01},
511 {6.25e-02, 6.241880999595735e-02},
512 {3.125e-02, 3.123983343026828e-02},
513 {1.5625e-02, 1.562372862047683e-02},
514 {7.8125e-03, 7.812341060101111e-03},
515 {3.90625e-03, 3.906230131966972e-03},
516 {1.953125e-03, 1.953122516478819e-03},
517 {9.765625e-04, 9.765621895593195e-04},
518 {4.8828125e-04, 4.882812111948983e-04},
519 {2.44140625e-04, 2.441406201493618e-04},
520 {1.220703125e-04, 1.220703118936702e-04},
521 {6.103515625e-05, 6.103515617420877e-05},
522 {3.0517578125e-05, 3.051757811552610e-05},
523 {1.52587890625e-05, 1.525878906131576e-05},
524 {7.62939453125e-06, 7.629394531101970e-06},
525 {3.814697265625e-06, 3.814697265606496e-06},
526 {1.9073486328125e-06, 1.907348632810187e-06},
527 {9.5367431640625e-07, 9.536743164059608e-07},
528 {4.76837158203125e-07, 4.768371582030888e-07},
529 {2.384185791015625e-07, 2.384185791015580e-07},
530 {1.1920928955078125e-07, 1.192092895507807e-07},
531 {5.9604644775390625e-08, 5.960464477539055e-08},
532 {2.98023223876953125e-08, 2.980232238769530e-08},
533 {1.490116119384765625e-08, 1.490116119384765e-08},
534 {7.450580596923828125e-09, 7.450580596923828e-09},
535 {3.7252902984619140625e-09, 3.725290298461914e-09},
536 {1.86264514923095703125e-09, 1.862645149230957e-09},
537 {9.31322574615478515625e-10, 9.313225746154785e-10},
538 {4.656612873077392578125e-10, 4.656612873077393e-10},
539 {2.3283064365386962890625e-10, 2.328306436538696e-10},
540 {1.16415321826934814453125e-10, 1.164153218269348e-10},
541 {5.82076609134674072265625e-11, 5.820766091346741e-11},
542 {2.910383045673370361328125e-11, 2.910383045673370e-11},
543 {1.4551915228366851806640625e-11, 1.455191522836685e-11},
544 {7.2759576141834259033203125e-12, 7.275957614183426e-12},
545 {3.63797880709171295166015625e-12, 3.637978807091713e-12},
546 {1.818989403545856475830078125e-12, 1.818989403545856e-12},
547 {9.094947017729282379150390625e-13, 9.094947017729282e-13},
548 {4.5474735088646411895751953125e-13, 4.547473508864641e-13},
549 {2.27373675443232059478759765625e-13, 2.273736754432321e-13},
550 {1.136868377216160297393798828125e-13, 1.136868377216160e-13},
551 {5.684341886080801486968994140625e-14, 5.684341886080801e-14},
552 {2.8421709430404007434844970703125e-14, 2.842170943040401e-14},
553 {1.42108547152020037174224853515625e-14, 1.421085471520200e-14},
554 {7.10542735760100185871124267578125e-15, 7.105427357601002e-15},
555 {3.552713678800500929355621337890625e-15, 3.552713678800501e-15},
556 {1.7763568394002504646778106689453125e-15, 1.776356839400250e-15},
557 {8.8817841970012523233890533447265625e-16, 8.881784197001252e-16}
560 void doMultiple(double* operandOne, int* powerOne,
561 double operandTwo, int powerTwo);
562 void doAdd (double* operandOne, int* powerOne,
563 double operandTwo, int powerTwo);
564 void printResult(void);
565 void formatResult(void);
566 void oneOperand(void);
568 void drawLines(void);
569 void drawButtons(int group);
571 /* -----------------------------------------------------------------------
572 Handy funtions
573 ----------------------------------------------------------------------- */
574 void cleartypingbuf(void)
576 int k;
577 for( k=1; k<=(DIGITLEN+1); k++)
578 typingbuf[k] = 0;
579 typingbuf[0] = ' ';
580 typingbufPointer = typingbuf+1;
582 void clearbuf(void)
584 int k;
585 for(k=0;k<18;k++)
586 buf[k]=' ';
587 buf[18] = 0;
589 void clearResult(void)
591 result = 0;
592 power = 0;
593 modifier = 0.1;
596 void clearInput(void)
598 calStatus = cal_normal;
599 clearResult();
600 cleartypingbuf();
601 rb->lcd_clear_display();
602 drawButtons(buttonGroup);
603 drawLines();
606 void clearOperand(void)
608 operand = 0;
609 operandPower = 0;
612 void clearMemTemp(void)
614 memTemp = 0;
615 memTempPower = 0;
618 void clearOper(void)
620 oper = ' ';
621 operInputted = false;
624 void clearMem(void)
626 clearInput();
627 clearMemTemp();
628 clearOperand();
629 clearOper();
630 btn = BUTTON_NONE;
633 void switchOperands(void)
635 double tempr = operand;
636 int tempp = operandPower;
637 operand = result;
638 operandPower = power;
639 result = tempr;
640 power = tempp;
643 void drawLines(void)
645 int i;
646 rb->lcd_hline(0, LCD_WIDTH, Y_1_POS-1);
647 for (i = 0; i < 5 ; i++)
648 rb->lcd_hline(0, LCD_WIDTH, Y_1_POS+i*REC_HEIGHT);
649 for (i = 0; i < 4 ; i++)
650 rb->lcd_vline(X_1_POS+i*REC_WIDTH, Y_1_POS, LCD_HEIGHT);
653 void drawButtons(int group)
655 int i, j, w, h;
656 for (i = 0; i <= 4; i++){
657 for (j = 0; j <= 4; j++){
658 rb->lcd_getstringsize( buttonChar[group][i][j],&w,&h);
659 if (i == btn_row && j == btn_col) /* selected item */
660 rb->lcd_set_drawmode(DRMODE_SOLID);
661 else
662 rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
663 rb->lcd_fillrect( X_0_POS + j*REC_WIDTH,
664 Y_1_POS + i*REC_HEIGHT,
665 REC_WIDTH, REC_HEIGHT+1);
666 if (i == btn_row && j == btn_col) /* selected item */
667 rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
668 else
669 rb->lcd_set_drawmode(DRMODE_SOLID);
670 rb->lcd_putsxy( X_0_POS + j*REC_WIDTH + (REC_WIDTH - w)/2,
671 Y_1_POS + i*REC_HEIGHT + (REC_HEIGHT - h)/2 + 1,
672 buttonChar[group][i][j] );
675 rb->lcd_set_drawmode(DRMODE_SOLID);
678 /* -----------------------------------------------------------------------
679 Initiate calculator
680 ----------------------------------------------------------------------- */
681 void cal_initial (void)
683 int w,h;
685 rb->lcd_getstringsize("2nd",&w,&h);
686 if (w > REC_WIDTH || h > REC_HEIGHT)
687 rb->lcd_setfont(FONT_SYSFIXED);
689 rb->lcd_clear_display();
691 #ifdef CALCULATOR_OPERATORS
692 /* basic operators are available through separate button */
693 buttonGroup = sciButtons;
694 #else
695 buttonGroup = basicButtons;
696 #endif
698 /* initially, invert button "5" */
699 btn_row = 2;
700 btn_col = 1;
701 prev_btn_row = btn_row;
702 prev_btn_col = btn_col;
703 drawButtons(buttonGroup);
704 drawLines();
705 rb->lcd_update();
707 /* initial mem and output display*/
708 clearMem();
709 printResult();
711 /* clear button queue */
712 rb->button_clear_queue();
715 /* -----------------------------------------------------------------------
716 mySqrt uses Heron's algorithm, which is the Newtone-Raphson algorhitm
717 in it's private case for sqrt.
718 Thanks BlueChip for his intro text and Dave Straayer for the actual name.
719 ----------------------------------------------------------------------- */
720 double mySqrt(double square)
722 int k = 0;
723 double temp = 0;
724 double root= ABS(square+1)/2;
726 while( ABS(root - temp) > MINIMUM ){
727 temp = root;
728 root = (square/temp + temp)/2;
729 k++;
730 if (k>10000) return 0;
733 return root;
735 /* -----------------------------------------------------------------------
736 transcendFunc uses CORDIC (COordinate Rotation DIgital Computer) method
737 transcendFunc can do sin,cos,log,exp
738 input parameter is angle
739 ----------------------------------------------------------------------- */
740 void transcendFunc(char* func, double* tt, int* ttPower)
742 double t = (*tt)*M_PI/180; int tPower = *ttPower;
743 int sign = 1;
744 int n = 50; /* n <=50, tables are all <= 50 */
745 int j;
746 double x,y,z,xt,yt,zt;
748 if (tPower < -998) {
749 calStatus = cal_normal;
750 return;
752 if (tPower > 8) {
753 calStatus = cal_error;
754 return;
756 *ttPower = 0;
757 calStatus = cal_normal;
759 if( func[0] =='s' || func[0] =='S'|| func[0] =='t' || func[0] =='T')
760 sign = SIGN(t);
761 else {
762 /* if( func[0] =='c' || func[0] =='C') */
763 sign = 1;
765 t = ABS(t);
767 while (tPower > 0){
768 t *= 10;
769 tPower--;
771 while (tPower < 0) {
772 t /= 10;
773 tPower++;
775 j = 0;
776 while (t > j*M_TWOPI) {j++;}
777 t -= (j-1)*M_TWOPI;
778 if (M_PI_2 < t && t < 3*M_PI_2){
779 t = M_PI - t;
780 if (func[0] =='c' || func[0] =='C')
781 sign = -1;
782 else if (func[0] =='t' || func[0] =='T')
783 t*=-1;
785 else if ( 3*M_PI_2 <= t && t <= M_TWOPI)
786 t -= M_TWOPI;
788 x = 0.60725293500888; y = 0; z = t;
789 for (j=1;j<n+2;j++){
790 xt = x - SIGN(z) * y*cordicTable[j-1][0];
791 yt = y + SIGN(z) * x*cordicTable[j-1][0];
792 zt = z - SIGN(z) * cordicTable[j-1][1];
793 x = xt;
794 y=yt;
795 z=zt;
797 if( func[0] =='s' || func[0] =='S') {
798 *tt = sign*y;
799 return;
801 else if( func[0] =='c' || func[0] =='C') {
802 *tt = sign*x;
803 return;
805 else /*if( func[0] =='t' || func[0] =='T')*/ {
806 if(t==M_PI_2||t==-M_PI_2){
807 calStatus = cal_error;
808 return;
810 else{
811 *tt = sign*(y/x);
812 return;
817 /* -----------------------------------------------------------------------
818 add in scientific number format
819 ----------------------------------------------------------------------- */
820 void doAdd (double* operandOne, int* powerOne,
821 double operandTwo, int powerTwo)
823 if ( *powerOne >= powerTwo ){
824 if (*powerOne - powerTwo <= DIGITLEN+1){
825 while (powerTwo < *powerOne){
826 operandTwo /=10;
827 powerTwo++;
829 *operandOne += operandTwo;
831 /*do nothing if operandTwo is too small*/
833 else{
834 if (powerTwo - *powerOne <= DIGITLEN+1){
835 while(powerTwo > *powerOne){
836 *operandOne /=10;
837 (*powerOne)++;
839 (*operandOne) += operandTwo;
841 else{/* simply copy operandTwo if operandOne is too small */
842 *operandOne = operandTwo;
843 *powerOne = powerTwo;
847 /* -----------------------------------------------------------------------
848 multiple in scientific number format
849 ----------------------------------------------------------------------- */
850 void doMultiple(double* operandOne, int* powerOne,
851 double operandTwo, int powerTwo)
853 (*operandOne) *= operandTwo;
854 (*powerOne) += powerTwo;
857 /* -----------------------------------------------------------------------
858 Handles all one operand calculations
859 ----------------------------------------------------------------------- */
860 void oneOperand(void)
862 int k = 0;
863 if (buttonGroup == basicButtons){
864 switch(CAL_BUTTON){
865 case btn_sqr:
866 if (result<0)
867 calStatus = cal_error;
868 else{
869 if (power%2 == 1){
870 result = (mySqrt(result*10))/10;
871 power = (power+1) / 2;
873 else{
874 result = mySqrt(result);
875 power = power / 2;
877 calStatus = cal_normal;
879 break;
880 case btn_square:
881 power *= 2;
882 result *= result;
883 calStatus = cal_normal;
884 break;
886 case btn_rec:
887 if (result==0)
888 calStatus = cal_error;
889 else{
890 power = -power;
891 result = 1/result;
892 calStatus = cal_normal;
894 break;
895 default:
896 calStatus = cal_toDo;
897 break; /* just for the safety */
900 else{ /* sciButtons */
901 switch(CAL_BUTTON){
902 case sci_sin:
903 transcendFunc("sin", &result, &power);
904 break;
905 case sci_cos:
906 transcendFunc("cos", &result, &power);
907 break;
908 case sci_tan:
909 transcendFunc("tan", &result, &power);
910 break;
911 case sci_fac:
912 if (power<0 || power>8 || result<0 )
913 calStatus = cal_error;
914 else if(result == 0) {
915 result = 1;
916 power = 0;
918 else{
919 while(power > 0) {
920 result *= 10;
921 power--;
923 if ( ( result - (int)result) > MINIMUM )
924 calStatus = cal_error;
925 else {
926 k = result; result = 1;
927 while (k > 1){
928 doMultiple(&result, &power, k, 0);
929 formatResult();
930 k--;
932 calStatus = cal_normal;
935 break;
936 default:
937 calStatus = cal_toDo;
938 break; /* just for the safety */
944 /* -----------------------------------------------------------------------
945 Handles all two operands calculations
946 ----------------------------------------------------------------------- */
947 void twoOperands(void)
949 switch(oper){
950 case '-':
951 doAdd(&operand, &operandPower, -result, power);
952 break;
953 case '+':
954 doAdd(&operand, &operandPower, result, power);
955 break;
956 case '*':
957 doMultiple(&operand, &operandPower, result, power);
958 break;
959 case '/':
960 if ( ABS(result) > MINIMUM ){
961 doMultiple(&operand, &operandPower, 1/result, -power);
963 else
964 calStatus = cal_error;
965 break;
966 default: /* ' ' */
967 switchOperands(); /* counter switchOperands() below */
968 break;
969 } /* switch(oper) */
970 switchOperands();
971 clearOper();
974 /* First, increases *dimen1 by dimen1_delta modulo dimen1_modulo.
975 If dimen1 wraps, increases *dimen2 by dimen2_delta modulo dimen2_modulo.
977 static void move_with_wrap_and_shift(
978 int *dimen1, int dimen1_delta, int dimen1_modulo,
979 int *dimen2, int dimen2_delta, int dimen2_modulo)
981 bool wrapped = false;
983 *dimen1 += dimen1_delta;
984 if (*dimen1 < 0)
986 *dimen1 = dimen1_modulo - 1;
987 wrapped = true;
989 else if (*dimen1 >= dimen1_modulo)
991 *dimen1 = 0;
992 wrapped = true;
995 if (wrapped)
997 /* Make the dividend always positive to be sure about the result.
998 Adding dimen2_modulo does not change it since we do it modulo. */
999 *dimen2 = (*dimen2 + dimen2_modulo + dimen2_delta) % dimen2_modulo;
1003 /* -----------------------------------------------------------------------
1004 Print buttons when switching 1st and 2nd
1005 int group = {basicButtons, sciButtons}
1006 ----------------------------------------------------------------------- */
1007 void printButtonGroups(int group)
1009 drawButtons(group);
1010 drawLines();
1011 rb->lcd_update();
1013 /* -----------------------------------------------------------------------
1014 flash the currently marked button
1015 ----------------------------------------------------------------------- */
1016 void flashButton(void)
1018 int k, w, h;
1019 for (k=2;k>0;k--)
1021 rb->lcd_getstringsize( buttonChar[buttonGroup][btn_row][btn_col],&w,&h);
1022 rb->lcd_set_drawmode(DRMODE_SOLID|(k==1) ? 0 : DRMODE_INVERSEVID);
1023 rb->lcd_fillrect( X_0_POS + btn_col*REC_WIDTH + 1,
1024 Y_1_POS + btn_row*REC_HEIGHT + 1,
1025 REC_WIDTH - 1, REC_HEIGHT - 1);
1026 rb->lcd_putsxy( X_0_POS + btn_col*REC_WIDTH + (REC_WIDTH - w)/2,
1027 Y_1_POS + btn_row*REC_HEIGHT + (REC_HEIGHT - h)/2 +1,
1028 buttonChar[buttonGroup][btn_row][btn_col] );
1029 rb->lcd_update_rect( X_0_POS + btn_col*REC_WIDTH + 1,
1030 Y_1_POS + btn_row*REC_HEIGHT + 1,
1031 REC_WIDTH - 1, REC_HEIGHT - 1);
1033 if (k!= 1)
1034 rb->sleep(HZ/22);
1039 /* -----------------------------------------------------------------------
1040 pos is the position that needs animation. pos = [1~18]
1041 ----------------------------------------------------------------------- */
1042 void deleteAnimation(int pos)
1044 int k, w, h, x;
1045 if (pos<1 || pos >18)
1046 return;
1048 rb->lcd_getstringsize("0", &w, &h);
1049 x = (pos==1? 4: LCD_WIDTH - 4 - w);
1051 for (k=0;k<4;k++){
1052 rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
1053 rb->lcd_fillrect(x, Y_1_POS - h -1, w, h);
1054 rb->lcd_set_drawmode(DRMODE_SOLID);
1055 rb->lcd_fillrect(x + (w*k)/8, Y_1_POS - h -1 + (h*k)/8,
1056 (w*(4-k))/4, (h*(4-k))/4);
1057 rb->lcd_update_rect(x, Y_1_POS - h -1, w, h);
1058 rb->sleep(HZ/32);
1062 /* -----------------------------------------------------------------------
1063 result may be one of these formats:
1065 xxxx.xxxx
1066 0.xxxx
1067 0.0000xxxx
1069 formatResult() change result to standard format: 0.xxxx
1070 if result is close to 0, let it be 0;
1071 if result is close to 1, let it be 0.1 and power++;
1072 ----------------------------------------------------------------------- */
1073 void formatResult(void)
1075 int resultsign = SIGN(result);
1076 result = ABS(result);
1077 if(result > MINIMUM ){ /* doesn't check power, might have problem
1078 input wouldn't,
1079 + - * / of two formatted number wouldn't.
1080 only a calculation that makes a formatted
1081 number (0.xxxx) less than MINIMUM in only
1082 one operation */
1084 if (result<1){
1085 while( (int)(result*10) == 0 ){
1086 result *= 10;
1087 power--;
1088 modifier *= 10;
1091 else{ /* result >= 1 */
1092 while( (int)result != 0 ){
1093 result /= 10;
1094 power++;
1095 modifier /= 10;
1097 } /* if result<1 */
1099 if (result > (1-MINIMUM)){
1100 result = 0.1;
1101 power++;
1102 modifier /= 10;
1104 result *= resultsign;
1106 else {
1107 result = 0;
1108 power = 0;
1109 modifier = 0.1;
1113 /* -----------------------------------------------------------------------
1114 result2typingbuf() outputs standard format result to typingbuf.
1115 case SCIENTIFIC_FORMAT, let temppower = 1;
1116 case temppower > 0: print '.' in the middle
1117 case temppower <= 0: print '.' in the begining
1118 ----------------------------------------------------------------------- */
1119 void result2typingbuf(void)
1121 bool haveDot = false;
1122 char tempchar = 0;
1123 int k;
1124 double tempresult = ABS(result); /* positive num makes things simple */
1126 int temppower;
1127 double tempmodifier = 1;
1128 int count;
1130 if(SCIENTIFIC_FORMAT)
1131 temppower = 1; /* output x.xxxx format */
1132 else
1133 temppower = power;
1135 cleartypingbuf();
1137 if(tempresult < MINIMUM){ /* if 0,faster display and avoid complication*/
1138 typingbuf[0] = ' ';
1139 typingbuf[1] = '0';
1141 else{ /* tempresult > 0 */
1142 typingbuf[0] = (SIGN(result)<0)?'-':' ';
1144 typingbufPointer = typingbuf;
1145 if(temppower > 0){
1146 for (k = 0; k<DIGITLEN+1 ; k++){
1147 typingbufPointer++;
1148 if(temppower || *(typingbufPointer-1) == '.'){
1149 count = 0;
1150 tempmodifier = tempmodifier/10;
1151 while( (tempresult-tempmodifier*count) >
1152 (tempmodifier-MINIMUM)){
1153 count++;
1155 tempresult -= tempmodifier*count;
1156 tempresult = ABS(tempresult);
1157 temppower-- ;
1158 *typingbufPointer = count + '0';
1160 else{ /* temppower == 0 */
1161 *typingbufPointer = '.';
1162 haveDot = true;
1164 } /* for */
1166 else{
1167 haveDot = true;
1168 typingbufPointer++; *typingbufPointer = '0';
1169 typingbufPointer++; *typingbufPointer = '.';
1170 for (k = 2; k<DIGITLEN+1 ; k++){
1171 typingbufPointer++;
1172 count = 0;
1173 if ( (-temppower) < (k-1)){
1174 tempmodifier = tempmodifier/10;
1175 while((tempresult-tempmodifier*count)>(tempmodifier-MINIMUM)){
1176 count++;
1179 tempresult -= tempmodifier*count;
1180 tempresult = ABS(tempresult);
1181 temppower-- ;
1183 *typingbufPointer = count + '0';
1186 /* now, typingbufPointer = typingbuf + 16 */
1187 /* backward strip off 0 and '.' */
1188 if (haveDot){
1189 while( (*typingbufPointer == '0') || (*typingbufPointer == '.')){
1190 tempchar = *typingbufPointer;
1191 *typingbufPointer = 0;
1192 typingbufPointer--;
1193 if (tempchar == '.') break;
1196 typingbuf[DIGITLEN+1] = 0;
1197 } /* else tempresult > 0 */
1200 /* -----------------------------------------------------------------------
1201 printResult() generates LCD display.
1202 ----------------------------------------------------------------------- */
1203 void printResult(void)
1205 int k, w, h;
1207 char operbuf[3] = {0, 0, 0};
1209 switch_Status:
1210 switch(calStatus){
1211 case cal_exit:
1212 rb->lcd_clear_display();
1213 rb->splash(HZ/3, "Bye now!");
1214 break;
1215 case cal_error:
1216 clearbuf();
1217 rb->snprintf(buf, 19, "%18s","Error");
1218 break;
1219 case cal_toDo:
1220 clearbuf();
1221 rb->snprintf(buf, 19, "%18s","Coming soon ^_* ");
1222 break;
1224 case cal_normal:
1225 formatResult();
1227 if( power > 1000 ){ /* power -1 > 999 */
1228 calStatus = cal_error;
1229 goto switch_Status;
1231 if (power < -998 ) /* power -1 < -999 */
1232 clearResult(); /* too small, let it be 0 */
1234 result2typingbuf();
1235 clearbuf();
1237 operbuf[0] = oper;
1238 operbuf[1] = ( ABS(memTemp) > MINIMUM )?'M':' ';
1239 operbuf[2] = '\0';
1241 if(SCIENTIFIC_FORMAT){
1242 /* output format: X.XXXX eXXX */
1243 if(power > -98){ /* power-1 >= -99, eXXX or e-XX */
1244 rb->snprintf(buf, 12, "%11s",typingbuf);
1245 for(k=11;k<=14;k++) buf[k] = ' ';
1246 cleartypingbuf();
1247 rb->snprintf(typingbuf, 5, "e%d",power-1);
1248 rb->snprintf(buf+11, 5, "%4s",typingbuf);
1250 else{ /* power-1 <= -100, e-XXX */
1251 rb->snprintf(buf, 12, "%11s",typingbuf);
1252 rb->snprintf(buf+11, 6, "e%d",power-1);
1255 else{
1256 rb->snprintf(buf, 12, "%11s",typingbuf);
1257 } /* if SCIENTIFIC_FORMAT */
1258 break;
1259 case cal_typing:
1260 case cal_dotted:
1261 clearbuf();
1262 operbuf[0] = oper;
1263 operbuf[1] = ( ABS(memTemp) > MINIMUM )?'M':' ';
1264 rb->snprintf(buf, 12, "%11s",typingbuf);
1265 break;
1269 rb->lcd_getstringsize(buf, &w, &h);
1270 rb->screen_clear_area(rb->screens[0], 0, 0, LCD_WIDTH, Y_1_POS - 1);
1271 rb->lcd_putsxy(4, Y_1_POS - h -1, operbuf);
1272 rb->lcd_putsxy(LCD_WIDTH - w - 4, Y_1_POS - h -1, buf);
1273 rb->lcd_update_rect(0, 1, LCD_WIDTH, Y_1_POS);
1276 /* -----------------------------------------------------------------------
1277 Process typing buttons: 1-9, '.', sign
1278 main operand "result" and typingbuf are processed seperately here.
1279 ----------------------------------------------------------------------- */
1280 void typingProcess(void){
1281 switch( CAL_BUTTON ){
1282 case btn_sign:
1283 if (calStatus == cal_typing ||
1284 calStatus == cal_dotted)
1285 typingbuf[0] = (typingbuf[0]=='-')?' ':'-';
1286 result = -result;
1287 break;
1288 case btn_dot:
1289 operInputted = false;
1290 switch(calStatus){
1291 case cal_normal:
1292 clearInput();
1293 *typingbufPointer = '0';
1294 typingbufPointer++;
1295 case cal_typing:
1296 calStatus = cal_dotted;
1297 *typingbufPointer = '.';
1298 if (typingbufPointer != typingbuf+DIGITLEN+1)
1299 typingbufPointer++;
1300 break;
1301 default: /* cal_dotted */
1302 break;
1304 break;
1305 default: /* 0-9 */
1306 operInputted = false;
1307 /* normal,0; normal,1-9; typing,0; typing,1-9 */
1308 switch(calStatus){
1309 case cal_normal:
1310 if(CAL_BUTTON == btn_0 )
1311 break; /* first input is 0, ignore */
1312 clearInput();
1313 /*no operator means start a new calculation*/
1314 if (oper ==' ')
1315 clearOperand();
1316 calStatus = cal_typing;
1317 /* go on typing, no break */
1318 case cal_typing:
1319 case cal_dotted:
1320 switch(CAL_BUTTON){
1321 case btn_0:
1322 *typingbufPointer = '0';
1323 break;
1324 default:
1325 *typingbufPointer=(7+btn_col-3*(btn_row-1))+ '0';
1326 break;
1328 if (typingbufPointer!=typingbuf+DIGITLEN+1){
1329 typingbufPointer++;
1331 {/* result processing */
1332 if (calStatus == cal_typing) power++;
1333 if (CAL_BUTTON != btn_0)
1334 result= result +
1335 SIGN(result)*
1336 (7+btn_col-3*(btn_row-1))*modifier;
1337 modifier /= 10;
1340 else /* last byte always '\0' */
1341 *typingbufPointer = 0;
1342 break;
1343 default: /* cal_error, cal_exit */
1344 break;
1346 break; /* default, 0-9 */
1347 } /* switch( CAL_BUTTON ) */
1350 /* -----------------------------------------------------------------------
1351 Handle delete operation
1352 main operand "result" and typingbuf are processed seperately here.
1353 ----------------------------------------------------------------------- */
1354 void doDelete(void){
1355 deleteAnimation(18);
1356 switch(calStatus){
1357 case cal_dotted:
1358 if (*(typingbufPointer-1) == '.'){
1359 /* if dotted and deleting '.',
1360 change status and delete '.' below */
1361 calStatus = cal_typing;
1363 else{ /* if dotted and not deleting '.',
1364 power stays */
1365 power++; /* counter "power--;" below */
1367 case cal_typing:
1368 typingbufPointer--;
1370 {/* result processing */ /* 0-9, '.' */
1371 /* if deleting '.', do nothing */
1372 if ( *typingbufPointer != '.'){
1373 power--;
1374 modifier *= 10;
1375 result = result - SIGN(result)*
1376 ((*typingbufPointer)- '0')*modifier;
1380 *typingbufPointer = 0;
1382 /* if (only one digit left and it's 0)
1383 or no digit left, change status*/
1384 if ( typingbufPointer == typingbuf+1 ||
1385 ( typingbufPointer == typingbuf+2 &&
1386 *(typingbufPointer-1) == '0' ))
1387 calStatus = cal_normal;
1388 break;
1389 default: /* normal, error, exit */
1390 break;
1393 /* -----------------------------------------------------------------------
1394 Handle buttons on basic screen
1395 ----------------------------------------------------------------------- */
1396 void basicButtonsProcess(void){
1397 switch (btn) {
1398 case CALCULATOR_INPUT:
1399 if (calStatus == cal_error && (CAL_BUTTON != btn_C) ) break;
1400 flashButton();
1401 switch( CAL_BUTTON ){
1402 case btn_MR:
1403 operInputted = false;
1404 result = memTemp; power = memTempPower;
1405 calStatus = cal_normal;
1406 break;
1407 case btn_M:
1408 formatResult();
1409 if (memTemp > MINIMUM)
1410 doAdd(&memTemp, &memTempPower, result, power);
1411 else {
1412 /* if result is too small and memTemp = 0,
1413 doAdd will not add */
1414 memTemp = result;
1415 memTempPower = power;
1417 calStatus = cal_normal;
1418 break;
1420 case btn_C: clearMem(); break;
1421 case btn_CE: clearInput(); break;
1423 case btn_bas:
1424 buttonGroup = sciButtons;
1425 printButtonGroups(buttonGroup);
1426 break;
1428 /* one operand calculation, may be changed to
1429 like sin, cos, log, etc */
1430 case btn_sqr:
1431 case btn_square:
1432 case btn_rec:
1433 formatResult(); /* not necessary, just for safty */
1434 oneOperand();
1435 break;
1437 case_btn_equal: /* F3 shortkey entrance */
1438 case btn_equal:
1439 formatResult();
1440 calStatus = cal_normal;
1441 operInputted = false;
1442 if (oper != ' ') twoOperands();
1443 break;
1445 case btn_div:
1446 case btn_time:
1447 case btn_minus:
1448 case btn_add:
1449 if(!operInputted) {twoOperands(); operInputted = true;}
1450 oper = buttonChar[basicButtons][btn_row][btn_col][0];
1451 #ifdef CALCULATOR_OPERATORS
1452 case_cycle_operators: /* F2 shortkey entrance */
1453 #endif
1454 calStatus = cal_normal;
1455 formatResult();
1456 operand = result;
1457 operandPower = power;
1459 break;
1461 case btn_sign:
1462 case btn_dot:
1463 default: /* 0-9 */
1464 typingProcess();
1465 break;
1466 } /* switch (CAL_BUTTON) */
1467 break;
1469 #ifdef CALCULATOR_OPERATORS
1470 case CALCULATOR_OPERATORS:
1471 if (calStatus == cal_error) break;
1472 if (!operInputted) {twoOperands(); operInputted = true;}
1473 switch (oper){
1474 case ' ':
1475 case '/': oper = '+'; flashButton(); break;
1476 case '+': oper = '-'; flashButton(); break;
1477 case '-': oper = '*'; flashButton(); break;
1478 case '*': oper = '/'; flashButton(); break;
1480 goto case_cycle_operators;
1481 break;
1482 #endif
1484 case CALCULATOR_CALC:
1485 if (calStatus == cal_error) break;
1486 flashButton();
1487 goto case_btn_equal;
1488 break;
1489 default: break;
1491 printResult();
1494 /* -----------------------------------------------------------------------
1495 Handle buttons on scientific screen
1496 ----------------------------------------------------------------------- */
1497 void sciButtonsProcess(void){
1498 switch (btn) {
1499 case CALCULATOR_INPUT:
1500 if (calStatus == cal_error && (CAL_BUTTON != sci_sci) ) break;
1501 flashButton();
1502 switch( CAL_BUTTON ){
1504 case sci_pi:
1505 result = M_PI; power = 0;
1506 calStatus = cal_normal;
1507 break;
1509 case sci_xy: break;
1511 case sci_sci:
1512 buttonGroup = basicButtons;
1513 printButtonGroups(basicButtons);
1514 break;
1516 case sci_fac:
1517 case sci_sin:
1518 case sci_asin:
1519 case sci_cos:
1520 case sci_acos:
1521 case sci_tan:
1522 case sci_atan:
1523 case sci_ln:
1524 case sci_exp:
1525 case sci_log:
1526 formatResult(); /* not necessary, just for safty */
1527 oneOperand();
1528 break;
1530 case btn_sign:
1531 case btn_dot:
1532 default: /* 0-9 */
1533 typingProcess();
1534 break;
1535 } /* switch (CAL_BUTTON) */
1536 break;
1538 #ifdef CALCULATOR_OPERATORS
1539 case CALCULATOR_OPERATORS:
1540 if (calStatus == cal_error) break;
1541 if (!operInputted) {twoOperands(); operInputted = true;}
1542 switch (oper){
1543 case ' ': oper = '+'; break;
1544 case '/': oper = '+'; deleteAnimation(1); break;
1545 case '+': oper = '-'; deleteAnimation(1); break;
1546 case '-': oper = '*'; deleteAnimation(1); break;
1547 case '*': oper = '/'; deleteAnimation(1); break;
1549 calStatus = cal_normal;
1550 formatResult();
1551 operand = result;
1552 operandPower = power;
1553 break;
1554 #endif
1556 case CALCULATOR_CALC:
1557 if (calStatus == cal_error) break;
1558 formatResult();
1559 calStatus = cal_normal;
1560 operInputted = false;
1561 if (oper != ' ') twoOperands();
1562 break;
1563 default: break;
1565 printResult();
1568 /* -----------------------------------------------------------------------
1569 move button index
1570 Invert display new button, invert back previous button
1571 ----------------------------------------------------------------------- */
1572 int handleButton(int button){
1573 switch(button)
1575 case CALCULATOR_INPUT:
1576 case CALCULATOR_CALC:
1577 #ifdef CALCULATOR_INPUT_CALC_PRE
1578 if (lastbtn != CALCULATOR_INPUT_CALC_PRE)
1579 break;
1580 /* no unconditional break; here! */
1581 #endif
1582 #ifdef CALCULATOR_OPERATORS
1583 case CALCULATOR_OPERATORS:
1584 #endif
1585 switch(buttonGroup){
1586 case basicButtons:
1587 basicButtonsProcess();
1588 break;
1589 case sciButtons:
1590 sciButtonsProcess();
1591 break;
1593 break;
1595 #ifdef CALCULATOR_CLEAR
1596 case CALCULATOR_CLEAR:
1597 switch(calStatus){
1598 case cal_typing:
1599 case cal_dotted:
1600 doDelete();
1601 break;
1602 default: /* cal_normal, cal_error, cal_exit */
1603 clearMem();
1604 break;
1606 printResult();
1607 break;
1608 #endif
1609 case CALCULATOR_LEFT:
1610 case CALCULATOR_LEFT | BUTTON_REPEAT:
1611 move_with_wrap_and_shift(
1612 &btn_col, -1, BUTTON_COLS,
1613 &btn_row, 0, BUTTON_ROWS);
1614 break;
1616 case CALCULATOR_RIGHT:
1617 case CALCULATOR_RIGHT | BUTTON_REPEAT:
1618 move_with_wrap_and_shift(
1619 &btn_col, 1, BUTTON_COLS,
1620 &btn_row, 0, BUTTON_ROWS);
1621 break;
1623 #ifdef CALCULATOR_UP
1624 case CALCULATOR_UP:
1625 case CALCULATOR_UP | BUTTON_REPEAT:
1626 move_with_wrap_and_shift(
1627 &btn_row, -1, BUTTON_ROWS,
1628 &btn_col, 0, BUTTON_COLS);
1629 break;
1630 #endif
1631 #ifdef CALCULATOR_DOWN
1632 case CALCULATOR_DOWN:
1633 case CALCULATOR_DOWN | BUTTON_REPEAT:
1634 move_with_wrap_and_shift(
1635 &btn_row, 1, BUTTON_ROWS,
1636 &btn_col, 0, BUTTON_COLS);
1637 break;
1638 #endif
1640 #ifdef CALCULATOR_UP_W_SHIFT
1641 case CALCULATOR_UP_W_SHIFT:
1642 case CALCULATOR_UP_W_SHIFT | BUTTON_REPEAT:
1643 move_with_wrap_and_shift(
1644 &btn_row, -1, BUTTON_ROWS,
1645 &btn_col, -1, BUTTON_COLS);
1646 break;
1647 #endif
1648 #ifdef CALCULATOR_DOWN_W_SHIFT
1649 case CALCULATOR_DOWN_W_SHIFT:
1650 case CALCULATOR_DOWN_W_SHIFT | BUTTON_REPEAT:
1651 move_with_wrap_and_shift(
1652 &btn_row, 1, BUTTON_ROWS,
1653 &btn_col, 1, BUTTON_COLS);
1654 break;
1655 #endif
1656 #ifdef CALCULATOR_LEFT_W_SHIFT
1657 case CALCULATOR_LEFT_W_SHIFT:
1658 case CALCULATOR_LEFT_W_SHIFT | BUTTON_REPEAT:
1659 move_with_wrap_and_shift(
1660 &btn_col, -1, BUTTON_COLS,
1661 &btn_row, -1, BUTTON_ROWS);
1662 break;
1663 #endif
1664 #ifdef CALCULATOR_RIGHT_W_SHIFT
1665 case CALCULATOR_RIGHT_W_SHIFT:
1666 case CALCULATOR_RIGHT_W_SHIFT | BUTTON_REPEAT:
1667 move_with_wrap_and_shift(
1668 &btn_col, 1, BUTTON_COLS,
1669 &btn_row, 1, BUTTON_ROWS);
1670 break;
1671 #endif
1672 #ifdef CALCULATOR_RC_QUIT
1673 case CALCULATOR_RC_QUIT:
1674 #endif
1675 case CALCULATOR_QUIT:
1676 return -1;
1679 return 0;
1681 prev_btn_row = btn_row;
1682 prev_btn_col = btn_col;
1685 /* -----------------------------------------------------------------------
1686 Main();
1687 ----------------------------------------------------------------------- */
1688 enum plugin_status plugin_start(const void* parameter)
1690 (void)parameter;
1692 /* now go ahead and have fun! */
1694 #ifdef HAVE_TOUCHSCREEN
1695 rb->touchscreen_set_mode(TOUCHSCREEN_POINT);
1696 #endif
1698 cal_initial();
1700 while (calStatus != cal_exit ) {
1701 btn = rb->button_get_w_tmo(HZ/2);
1702 #ifdef HAVE_TOUCHSCREEN
1703 if(btn & BUTTON_TOUCHSCREEN)
1705 struct ts_raster_result res;
1706 if(touchscreen_map_raster(&calc_raster, rb->button_get_data() >> 16,
1707 rb->button_get_data() & 0xffff, &res) == 1)
1709 btn_row = res.y;
1710 btn_col = res.x;
1711 drawButtons(buttonGroup);
1712 drawLines();
1714 rb->lcd_update();
1716 prev_btn_row = btn_row;
1717 prev_btn_col = btn_col;
1718 if(btn & BUTTON_REL)
1720 btn = CALCULATOR_INPUT;
1721 switch(buttonGroup){
1722 case basicButtons:
1723 basicButtonsProcess();
1724 break;
1725 case sciButtons:
1726 sciButtonsProcess();
1727 break;
1729 btn = BUTTON_TOUCHSCREEN;
1733 #endif
1734 if (handleButton(btn) == -1)
1736 calStatus = cal_exit;
1737 printResult();
1739 else
1741 drawButtons(buttonGroup);
1742 drawLines();
1745 rb->lcd_update();
1747 if(rb->default_event_handler(btn) == SYS_USB_CONNECTED)
1748 return PLUGIN_USB_CONNECTED;
1750 if (btn != BUTTON_NONE)
1751 lastbtn = btn;
1752 } /* while (calStatus != cal_exit ) */
1754 rb->button_clear_queue();
1755 return PLUGIN_OK;
1758 #endif /* #ifdef HAVE_LCD_BITMAP */