More iPod 3G work from Seven Le Mesle
[Rockbox.git] / apps / plugins / calculator.c
blob0cce1860cb0a85a6c9322e82de7eef7d99ae9184
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2004 Pengxuan(Isaac) <tinousus@yahoo.com>
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
18 ****************************************************************************/
21 00 01 21 22 23 43 44 45 65 66 67 87 88 89 109110111
22 00 |-----------|-----------|-----------|-----------|-----------|
23 01 | | | | | |
24 |***********|***********|***********|***********|***********|
25 |***********|***********|***********|***********|***********|
26 11 | | | | | |
27 12 |-----------|-----------|-----------|-----------|-----------|
28 13 |-----------|-----------|-----------|-----------|-----------| y1
29 14 | | | | | |
30 | | | | | |
31 22 | | | | | |
32 23 |-----------|-----------|-----------|-----------|-----------| y2
33 24 | | | | | |
34 | | | | | |
35 32 | | | | | |
36 33 |-----------|-----------|-----------|-----------|-----------| y3
37 34 | | | | | |
38 | | | | | |
39 42 | | | | | |
40 43 |-----------|-----------|-----------|-----------|-----------| y4
41 44 | | | | | |
42 | | | | | |
43 52 | | | | | |
44 53 |-----------|-----------|-----------|-----------|-----------| y5
45 54 | | | | | |
46 | | | | | |
47 62 | | | | | |
48 63 |-----------|-----------|-----------|-----------|-----------| y6
49 x0 x1 x2 x3 x4 x5
52 /*---------------------------------------------------------------------------
53 Features:
54 - Scientific number format core code. Support range 10^-999 ~ 10^999
55 - Number of significant figures up to 10
57 Limitations:
58 - Right now, only accept "num, operator (+,-,*,/), num, =" input sequence.
59 Input "3, +, 5, -, 2, =", the calculator will only do 5-2 and result = 3
60 You have to input "3, +, 5, =, -, 2, =" to get 3+5-2 = 6
62 - "*,/" have no priority. Actually you can't input 3+5*2 yet.
64 User Instructions:
65 use arrow button to move cursor, "play" button to select, "off" button to exit
66 F1: if typing numbers, it's equal to "Del"; otherwise, equal to "C"
67 F2: circle input "+, -, *, /"
68 F3: equal to "="
70 "MR" : load temp memory
71 "M+" : add currently display to temp memory
72 "C" : reset calculator
73 ---------------------------------------------------------------------------*/
75 #include "plugin.h"
76 #ifdef HAVE_LCD_BITMAP
77 #include "math.h"
79 PLUGIN_HEADER
81 #define REC_HEIGHT 10 /* blank height = 9 */
82 #define REC_WIDTH 22 /* blank width = 21 */
84 #define Y_6_POS (LCD_HEIGHT - 1) /* y6 = 63 */
85 #define Y_5_POS (Y_6_POS - REC_HEIGHT) /* y5 = 53 */
86 #define Y_4_POS (Y_5_POS - REC_HEIGHT) /* y4 = 43 */
87 #define Y_3_POS (Y_4_POS - REC_HEIGHT) /* y3 = 33 */
88 #define Y_2_POS (Y_3_POS - REC_HEIGHT) /* y2 = 23 */
89 #define Y_1_POS (Y_2_POS - REC_HEIGHT) /* y1 = 13 */
90 #define Y_0_POS 0 /* y0 = 0 */
92 #define X_0_POS 0 /* x0 = 0 */
93 #define X_1_POS (X_0_POS + REC_WIDTH) /* x1 = 22 */
94 #define X_2_POS (X_1_POS + REC_WIDTH) /* x2 = 44 */
95 #define X_3_POS (X_2_POS + REC_WIDTH) /* x3 = 66 */
96 #define X_4_POS (X_3_POS + REC_WIDTH) /* x4 = 88 */
97 #define X_5_POS (X_4_POS + REC_WIDTH) /* x5 = 110, column 111 left blank */
99 #define TEXT_1_POS (Y_1_POS-10) /* y1 = 2 */ /* blank height = 12 */
100 #define TEXT_2_POS (Y_2_POS-8) /* y2 = 15 */ /* blank height = 9 */
101 #define TEXT_3_POS (Y_3_POS-8) /* y3 = 25 */
102 #define TEXT_4_POS (Y_4_POS-8) /* y4 = 35 */
103 #define TEXT_5_POS (Y_5_POS-8) /* y5 = 45 */
104 #define TEXT_6_POS (Y_6_POS-8) /* y6 = 55 */
106 #define SIGN(x) ((x)<0?-1:1)
107 #define ABS(x) ((x)<0?-(x):(x))
109 /* variable button definitions */
110 #if CONFIG_KEYPAD == RECORDER_PAD
111 #define CALCULATOR_UP BUTTON_UP
112 #define CALCULATOR_DOWN BUTTON_DOWN
113 #define CALCULATOR_QUIT BUTTON_OFF
114 #define CALCULATOR_INPUT BUTTON_PLAY
115 #define CALCULATOR_CALC BUTTON_F3
116 #define CALCULATOR_OPERATORS BUTTON_F2
117 #define CALCULATOR_CLEAR BUTTON_F1
119 #elif CONFIG_KEYPAD == ONDIO_PAD
120 #define CALCULATOR_UP BUTTON_UP
121 #define CALCULATOR_DOWN BUTTON_DOWN
122 #define CALCULATOR_QUIT BUTTON_OFF
123 #define CALCULATOR_INPUT_CALC_PRE BUTTON_MENU
124 #define CALCULATOR_INPUT (BUTTON_MENU | BUTTON_REL)
125 #define CALCULATOR_CALC (BUTTON_MENU | BUTTON_REPEAT)
127 #elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || \
128 (CONFIG_KEYPAD == IRIVER_H300_PAD)
129 #define CALCULATOR_UP BUTTON_UP
130 #define CALCULATOR_DOWN BUTTON_DOWN
131 #define CALCULATOR_QUIT BUTTON_OFF
132 #define CALCULATOR_INPUT BUTTON_SELECT
133 #define CALCULATOR_CALC BUTTON_ON
134 #define CALCULATOR_OPERATORS BUTTON_MODE
135 #define CALCULATOR_CLEAR BUTTON_REC
137 #elif (CONFIG_KEYPAD == IPOD_4G_PAD) || \
138 (CONFIG_KEYPAD == IPOD_3G_PAD)
140 #define CALCULATOR_UP BUTTON_SCROLL_BACK
141 #define CALCULATOR_DOWN BUTTON_SCROLL_FWD
142 #define CALCULATOR_QUIT BUTTON_MENU
143 #define CALCULATOR_INPUT_CALC_PRE BUTTON_SELECT
144 #define CALCULATOR_INPUT (BUTTON_SELECT | BUTTON_REL)
145 #define CALCULATOR_CALC (BUTTON_PLAY | BUTTON_REPEAT)
147 #elif (CONFIG_KEYPAD == IAUDIO_X5_PAD)
149 #define CALCULATOR_UP BUTTON_UP
150 #define CALCULATOR_DOWN BUTTON_DOWN
151 #define CALCULATOR_QUIT BUTTON_POWER
152 #define CALCULATOR_INPUT_CALC_PRE BUTTON_SELECT
153 #define CALCULATOR_INPUT (BUTTON_SELECT | BUTTON_REL)
154 #define CALCULATOR_CALC BUTTON_PLAY
155 #define CALCULATOR_CLEAR BUTTON_REC
157 #elif (CONFIG_KEYPAD == GIGABEAT_PAD)
159 #define CALCULATOR_UP BUTTON_UP
160 #define CALCULATOR_DOWN BUTTON_DOWN
161 #define CALCULATOR_QUIT BUTTON_A
162 #define CALCULATOR_INPUT_CALC_PRE BUTTON_MENU
163 #define CALCULATOR_INPUT (BUTTON_MENU | BUTTON_REL)
164 #define CALCULATOR_CALC BUTTON_SELECT
165 #define CALCULATOR_CLEAR BUTTON_POWER
167 #endif
169 static struct plugin_api* rb;
171 enum {
172 basicButtons,
173 sciButtons
174 } buttonGroup;
175 unsigned char* buttonChar[2][5][5] = {
176 { { "MR" , "M+" , "2nd" , "CE" , "C" },
177 { "7" , "8" , "9" , "/" , "sqr" },
178 { "4" , "5" , "6" , "*" , "x^2" },
179 { "1" , "2" , "3" , "-" , "1/x" },
180 { "0" , "+/-", "." , "+" , "=" } },
182 { { "n!" , "PI" , "1st" , "sin" , "asi" },
183 { "7" , "8" , "9" , "cos" , "aco" },
184 { "4" , "5" , "6" , "tan" , "ata" },
185 { "1" , "2" , "3" , "ln" , "e^x" },
186 { "0" , "+/-", "." , "log" , "x^y" } }
188 enum { btn_MR , btn_M , btn_bas , btn_CE , btn_C ,
189 btn_7 , btn_8 , btn_9 , btn_div , btn_sqr ,
190 btn_4 , btn_5 , btn_6 , btn_time , btn_square ,
191 btn_1 , btn_2 , btn_3 , btn_minus , btn_rec ,
192 btn_0 , btn_sign , btn_dot , btn_add , btn_equal
194 enum { sci_fac, sci_pi , sci_sci , sci_sin , sci_asin ,
195 sci_7 , sci_8 , sci_9 , sci_cos , sci_acos ,
196 sci_4 , sci_5 , sci_6 , sci_tan , sci_atan ,
197 sci_1 , sci_2 , sci_3 , sci_ln , sci_exp ,
198 sci_0 , sci_sign , sci_dot , sci_log , sci_xy
201 #define PI 3.14159265358979323846
202 #define MINIMUM 0.000000000001 /* e-12 */
203 /* ^ ^ ^ ^ */
204 /* 123456789abcdef */
206 #define DIGITLEN 10 /* must <= 10 */
207 #define SCIENTIFIC_FORMAT ( power < -(DIGITLEN-3) || power > (DIGITLEN))
208 /* 0.000 00000 0001 */
209 /* ^ ^ ^ ^ ^ ^ */
210 /* DIGITLEN 12345 6789a bcdef */
211 /* power 12 34567 89abc def */
212 /* 10^- 123 45678 9abcd ef */
214 unsigned char buf[19];/* 18 bytes of output line,
215 buf[0] is operator
216 buf[1] = 'M' if memTemp is not 0
217 buf[2] = ' '
219 if SCIENTIFIC_FORMAT
220 buf[2]-buf[12] or buf[3]-buf[13] = result;
221 format X.XXXXXXXX
222 buf[13] or buf[14] -buf[17] = power;
223 format eXXX or e-XXX
224 else
225 buf[3]-buf[6] = ' ';
226 buf[7]-buf[17] = result;
228 buf[18] = '\0' */
230 unsigned char typingbuf[DIGITLEN+2];/* byte 0 is sign or ' ',
231 byte 1~DIGITLEN are num and '.'
232 byte (DIGITLEN+1) is '\0' */
233 unsigned char* typingbufPointer = typingbuf;
235 double result = 0; /* main operand, format 0.xxxxx */
236 int power = 0; /* 10^power */
237 double modifier = 0.1; /* position of next input */
238 double operand = 0; /* second operand, format 0.xxxxx */
239 int operandPower = 0; /* 10^power of second operand */
240 char oper = ' '; /* operators: + - * / */
241 bool operInputted = false; /* false: do calculation first and
242 replace current oper
243 true: just replace current oper */
245 double memTemp = 0; /* temp memory */
246 int memTempPower = 0; /* 10^^power of memTemp */
248 int m, n, prev_m, prev_n; /* position index for button */
249 #define CAL_BUTTON (m*5+n)
251 int btn = BUTTON_NONE;
252 int lastbtn = BUTTON_NONE;
254 /* Status of calculator */
255 enum {cal_normal, /* 0, normal status, display result */
256 cal_typing, /* 1, currently typing, dot hasn't been typed */
257 cal_dotted, /* 2, currently typing, dot already has been typed. */
258 cal_error,
259 cal_exit,
260 cal_toDo
261 } calStatus;
263 /* constant table for CORDIC algorithm */
264 double cordicTable[51][2]= {
265 /* pow(2,0) - pow(2,-50) atan(pow(2,0) - atan(pow(2,-50) */
266 {1e+00, 7.853981633974483e-01},
267 {5e-01, 4.636476090008061e-01},
268 {2.5e-01, 2.449786631268641e-01},
269 {1.25e-01, 1.243549945467614e-01},
270 {6.25e-02, 6.241880999595735e-02},
271 {3.125e-02, 3.123983343026828e-02},
272 {1.5625e-02, 1.562372862047683e-02},
273 {7.8125e-03, 7.812341060101111e-03},
274 {3.90625e-03, 3.906230131966972e-03},
275 {1.953125e-03, 1.953122516478819e-03},
276 {9.765625e-04, 9.765621895593195e-04},
277 {4.8828125e-04, 4.882812111948983e-04},
278 {2.44140625e-04, 2.441406201493618e-04},
279 {1.220703125e-04, 1.220703118936702e-04},
280 {6.103515625e-05, 6.103515617420877e-05},
281 {3.0517578125e-05, 3.051757811552610e-05},
282 {1.52587890625e-05, 1.525878906131576e-05},
283 {7.62939453125e-06, 7.629394531101970e-06},
284 {3.814697265625e-06, 3.814697265606496e-06},
285 {1.9073486328125e-06, 1.907348632810187e-06},
286 {9.5367431640625e-07, 9.536743164059608e-07},
287 {4.76837158203125e-07, 4.768371582030888e-07},
288 {2.384185791015625e-07, 2.384185791015580e-07},
289 {1.1920928955078125e-07, 1.192092895507807e-07},
290 {5.9604644775390625e-08, 5.960464477539055e-08},
291 {2.98023223876953125e-08, 2.980232238769530e-08},
292 {1.490116119384765625e-08, 1.490116119384765e-08},
293 {7.450580596923828125e-09, 7.450580596923828e-09},
294 {3.7252902984619140625e-09, 3.725290298461914e-09},
295 {1.86264514923095703125e-09, 1.862645149230957e-09},
296 {9.31322574615478515625e-10, 9.313225746154785e-10},
297 {4.656612873077392578125e-10, 4.656612873077393e-10},
298 {2.3283064365386962890625e-10, 2.328306436538696e-10},
299 {1.16415321826934814453125e-10, 1.164153218269348e-10},
300 {5.82076609134674072265625e-11, 5.820766091346741e-11},
301 {2.910383045673370361328125e-11, 2.910383045673370e-11},
302 {1.4551915228366851806640625e-11, 1.455191522836685e-11},
303 {7.2759576141834259033203125e-12, 7.275957614183426e-12},
304 {3.63797880709171295166015625e-12, 3.637978807091713e-12},
305 {1.818989403545856475830078125e-12, 1.818989403545856e-12},
306 {9.094947017729282379150390625e-13, 9.094947017729282e-13},
307 {4.5474735088646411895751953125e-13, 4.547473508864641e-13},
308 {2.27373675443232059478759765625e-13, 2.273736754432321e-13},
309 {1.136868377216160297393798828125e-13, 1.136868377216160e-13},
310 {5.684341886080801486968994140625e-14, 5.684341886080801e-14},
311 {2.8421709430404007434844970703125e-14, 2.842170943040401e-14},
312 {1.42108547152020037174224853515625e-14, 1.421085471520200e-14},
313 {7.10542735760100185871124267578125e-15, 7.105427357601002e-15},
314 {3.552713678800500929355621337890625e-15, 3.552713678800501e-15},
315 {1.7763568394002504646778106689453125e-15, 1.776356839400250e-15},
316 {8.8817841970012523233890533447265625e-16, 8.881784197001252e-16}
319 void doMultiple(double* operandOne, int* powerOne,
320 double operandTwo, int powerTwo);
321 void doAdd (double* operandOne, int* powerOne,
322 double operandTwo, int powerTwo);
323 void printResult(void);
324 void formatResult(void);
325 void oneOperand(void);
327 /* -----------------------------------------------------------------------
328 Handy funtions
329 ----------------------------------------------------------------------- */
330 void cleartypingbuf(void)
332 int k;
333 for( k=1; k<=(DIGITLEN+1); k++)
334 typingbuf[k] = 0;
335 typingbuf[0] = ' ';
336 typingbufPointer = typingbuf+1;
338 void clearbuf(void)
340 int k;
341 for(k=0;k<18;k++)
342 buf[k]=' ';
343 buf[18] = 0;
345 void clearResult(void)
347 result = 0;
348 power = 0;
349 modifier = 0.1;
352 void clearInput(void)
354 calStatus = cal_normal;
355 clearResult();
356 cleartypingbuf();
359 void clearOperand(void)
361 operand = 0;
362 operandPower = 0;
365 void clearMemTemp(void)
367 memTemp = 0;
368 memTempPower = 0;
371 void clearOper(void)
373 oper = ' ';
374 operInputted = false;
377 void clearMem(void)
379 clearInput();
380 clearMemTemp();
381 clearOperand();
382 clearOper();
383 btn = BUTTON_NONE;
386 void switchOperands(void)
388 double tempr = operand;
389 int tempp = operandPower;
390 operand = result;
391 operandPower = power;
392 result = tempr;
393 power = tempp;
396 /* -----------------------------------------------------------------------
397 Initiate calculator
398 ----------------------------------------------------------------------- */
399 void cal_initial (void)
401 int i,j,w,h;
402 rb->lcd_setfont(FONT_SYSFIXED);
403 rb->lcd_clear_display();
405 /* draw lines */
406 rb->lcd_drawrect(X_0_POS, Y_0_POS, LCD_WIDTH-1, LCD_HEIGHT);
407 rb->lcd_drawline(X_0_POS, Y_1_POS-1, X_5_POS, Y_1_POS-1);
408 for (i = 0; i < 5 ; i++)
409 rb->lcd_drawline(X_0_POS, Y_1_POS+i*REC_HEIGHT,
410 X_5_POS, Y_1_POS+i*REC_HEIGHT);
411 for (i = 0; i < 4 ; i++)
412 rb->lcd_drawline(X_1_POS+i*REC_WIDTH, Y_1_POS,
413 X_1_POS+i*REC_WIDTH, Y_6_POS);
415 #ifdef CALCULATOR_OPERATORS
416 /* basic operators are available through separate button */
417 buttonGroup = sciButtons;
418 #else
419 buttonGroup = basicButtons;
420 #endif
421 /* draw buttons */
422 for (i = 0; i < 5; i++){
423 for (j = 0; j < 5; j++){
424 rb->lcd_getstringsize( buttonChar[buttonGroup][i][j],&w,&h);
425 rb->lcd_putsxy( X_0_POS + j*REC_WIDTH + (REC_WIDTH - w)/2,
426 TEXT_2_POS + i*REC_HEIGHT,
427 buttonChar[buttonGroup][i][j] );
431 /* initially, invert button "5" */
432 m = 2;
433 n = 1;
434 prev_m = m;
435 prev_n = n;
436 rb->lcd_set_drawmode(DRMODE_COMPLEMENT);
437 rb->lcd_fillrect( X_0_POS + n*REC_WIDTH + 1,
438 Y_1_POS + m*REC_HEIGHT + 1,
439 REC_WIDTH - 1, REC_HEIGHT - 1);
440 rb->lcd_set_drawmode(DRMODE_SOLID);
441 rb->lcd_update();
443 /* initial mem and output display*/
444 clearMem();
445 printResult();
447 /* clear button queue */
448 rb->button_clear_queue();
451 /* -----------------------------------------------------------------------
452 mySqrt uses Heron's algorithm, which is the Newtone-Raphson algorhitm
453 in it's private case for sqrt.
454 Thanks BlueChip for his intro text and Dave Straayer for the actual name.
455 ----------------------------------------------------------------------- */
456 double mySqrt(double square)
458 int k = 0;
459 double temp = 0;
460 double root= ABS(square+1)/2;
462 while( ABS(root - temp) > MINIMUM ){
463 temp = root;
464 root = (square/temp + temp)/2;
465 k++;
466 if (k>10000) return 0;
469 return root;
471 /* -----------------------------------------------------------------------
472 transcendFunc uses CORDIC (COordinate Rotation DIgital Computer) method
473 transcendFunc can do sin,cos,log,exp
474 input parameter is angle
475 ----------------------------------------------------------------------- */
476 void transcendFunc(char* func, double* tt, int* ttPower)
478 double t = (*tt)*PI/180; int tPower = *ttPower;
479 int sign = 1;
480 int n = 50; /* n <=50, tables are all <= 50 */
481 int j;
482 double x,y,z,xt,yt,zt;
484 if (tPower < -998) {
485 calStatus = cal_normal;
486 return;
488 if (tPower > 8) {
489 calStatus = cal_error;
490 return;
492 *ttPower = 0;
493 calStatus = cal_normal;
495 if( func[0] =='s' || func[0] =='S')
496 sign = SIGN(t);
497 else {
498 /* if( func[0] =='c' || func[0] =='C') */
499 sign = 1;
501 t = ABS(t);
503 while (tPower > 0){
504 t *= 10;
505 tPower--;
507 while (tPower < 0) {
508 t /= 10;
509 tPower++;
511 j = 0;
512 while (t > j*2*PI) {j++;}
513 t -= (j-1)*2*PI;
514 if (PI/2 < t && t < 3*PI/2){
515 t = PI - t;
516 if (func[0] =='c' || func[0] =='C')
517 sign = -1;
519 else if ( 3*PI/2 <= t && t <= 2*PI)
520 t -= 2*PI;
522 x = 0.60725293500888; y = 0; z = t;
523 for (j=1;j<n+2;j++){
524 xt = x - SIGN(z) * y*cordicTable[j-1][0];
525 yt = y + SIGN(z) * x*cordicTable[j-1][0];
526 zt = z - SIGN(z) * cordicTable[j-1][1];
527 x = xt;
528 y=yt;
529 z=zt;
531 if( func[0] =='s' || func[0] =='S') {
532 *tt = sign*y;
533 return;
535 else /* if( func[0] =='c' || func[0] =='C')*/ {
536 *tt = sign*x;
537 return;
541 /* -----------------------------------------------------------------------
542 add in scientific number format
543 ----------------------------------------------------------------------- */
544 void doAdd (double* operandOne, int* powerOne,
545 double operandTwo, int powerTwo)
547 if ( *powerOne >= powerTwo ){
548 if (*powerOne - powerTwo <= DIGITLEN+1){
549 while (powerTwo < *powerOne){
550 operandTwo /=10;
551 powerTwo++;
553 *operandOne += operandTwo;
555 /*do nothing if operandTwo is too small*/
557 else{
558 if (powerTwo - *powerOne <= DIGITLEN+1){
559 while(powerTwo > *powerOne){
560 *operandOne /=10;
561 (*powerOne)++;
563 (*operandOne) += operandTwo;
565 else{/* simply copy operandTwo if operandOne is too small */
566 *operandOne = operandTwo;
567 *powerOne = powerTwo;
571 /* -----------------------------------------------------------------------
572 multiple in scientific number format
573 ----------------------------------------------------------------------- */
574 void doMultiple(double* operandOne, int* powerOne,
575 double operandTwo, int powerTwo)
577 (*operandOne) *= operandTwo;
578 (*powerOne) += powerTwo;
581 /* -----------------------------------------------------------------------
582 Handles all one operand calculations
583 ----------------------------------------------------------------------- */
584 void oneOperand(void)
586 int k = 0;
587 if (buttonGroup == basicButtons){
588 switch(CAL_BUTTON){
589 case btn_sqr:
590 if (result<0)
591 calStatus = cal_error;
592 else{
593 if (power%2 == 1){
594 result = (mySqrt(result*10))/10;
595 power = (power+1) / 2;
597 else{
598 result = mySqrt(result);
599 power = power / 2;
601 calStatus = cal_normal;
603 break;
604 case btn_square:
605 power *= 2;
606 result *= result;
607 calStatus = cal_normal;
608 break;
610 case btn_rec:
611 if (result==0)
612 calStatus = cal_error;
613 else{
614 power = -power;
615 result = 1/result;
616 calStatus = cal_normal;
618 break;
619 default:
620 calStatus = cal_toDo;
621 break; /* just for the safety */
624 else{ /* sciButtons */
625 switch(CAL_BUTTON){
626 case sci_sin:
627 transcendFunc("sin", &result, &power);
628 break;
629 case sci_cos:
630 transcendFunc("cos", &result, &power);
631 break;
632 case sci_fac:
633 if (power<0 || power>8 || result<0 )
634 calStatus = cal_error;
635 else if(result == 0) {
636 result = 1;
637 power = 0;
639 else{
640 while(power > 0) {
641 result *= 10;
642 power--;
644 if ( ( result - (int)result) > MINIMUM )
645 calStatus = cal_error;
646 else {
647 k = result; result = 1;
648 while (k > 1){
649 doMultiple(&result, &power, k, 0);
650 formatResult();
651 k--;
653 calStatus = cal_normal;
656 break;
657 default:
658 calStatus = cal_toDo;
659 break; /* just for the safety */
665 /* -----------------------------------------------------------------------
666 Handles all two operands calculations
667 ----------------------------------------------------------------------- */
668 void twoOperands(void)
670 switch(oper){
671 case '-':
672 doAdd(&operand, &operandPower, -result, power);
673 break;
674 case '+':
675 doAdd(&operand, &operandPower, result, power);
676 break;
677 case '*':
678 doMultiple(&operand, &operandPower, result, power);
679 break;
680 case '/':
681 if ( ABS(result) > MINIMUM ){
682 doMultiple(&operand, &operandPower, 1/result, -power);
684 else
685 calStatus = cal_error;
686 break;
687 default: /* ' ' */
688 switchOperands(); /* counter switchOperands() below */
689 break;
690 } /* switch(oper) */
691 switchOperands();
692 clearOper();
694 /* -----------------------------------------------------------------------
695 move button index
696 Invert display new button, invert back previous button
697 ----------------------------------------------------------------------- */
698 void moveButton(void){
699 switch(btn){
700 case BUTTON_LEFT:
701 case BUTTON_LEFT | BUTTON_REPEAT:
702 if (n == 0)
703 n = 4;
704 else
705 n--;
706 break;
708 case BUTTON_RIGHT:
709 case BUTTON_RIGHT | BUTTON_REPEAT:
710 if (n == 4)
711 n = 0;
712 else
713 n++;
714 break;
716 case CALCULATOR_UP:
717 case CALCULATOR_UP | BUTTON_REPEAT:
718 if (m == 0)
719 m = 4;
720 else
721 m--;
722 break;
724 case CALCULATOR_DOWN:
725 case CALCULATOR_DOWN | BUTTON_REPEAT:
726 if (m == 4)
727 m = 0;
728 else
729 m++;
730 break;
733 rb->lcd_set_drawmode(DRMODE_COMPLEMENT);
734 rb->lcd_fillrect( X_0_POS + prev_n*REC_WIDTH + 1,
735 Y_1_POS + prev_m*REC_HEIGHT + 1,
736 REC_WIDTH - 1, REC_HEIGHT - 1);
738 rb->lcd_fillrect( X_0_POS + n*REC_WIDTH + 1,
739 Y_1_POS + m*REC_HEIGHT + 1,
740 REC_WIDTH - 1, REC_HEIGHT - 1);
741 rb->lcd_set_drawmode(DRMODE_SOLID);
743 rb->lcd_update_rect( X_0_POS + prev_n*REC_WIDTH + 1,
744 Y_1_POS + prev_m*REC_HEIGHT + 1,
745 REC_WIDTH - 1, REC_HEIGHT - 1);
747 rb->lcd_update_rect( X_0_POS + n*REC_WIDTH + 1,
748 Y_1_POS + m*REC_HEIGHT + 1,
749 REC_WIDTH - 1, REC_HEIGHT - 1);
751 prev_m = m;
752 prev_n = n;
754 /* -----------------------------------------------------------------------
755 Print buttons when switching 1st and 2nd
756 int group = {basicButtons, sciButtons}
757 ----------------------------------------------------------------------- */
758 void printButtonGroups(int group)
760 int i,j,w,h;
761 for (i = 0; i < 5; i++){
762 for (j = 3; j <= 4; j++){
763 rb->lcd_getstringsize( buttonChar[group][i][j],&w,&h);
764 rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
765 rb->lcd_fillrect( X_0_POS + j*REC_WIDTH + 1,
766 Y_1_POS + i*REC_HEIGHT + 1,
767 REC_WIDTH - 1, REC_HEIGHT - 1);
768 rb->lcd_set_drawmode(DRMODE_SOLID);
769 rb->lcd_putsxy( X_0_POS + j*REC_WIDTH + (REC_WIDTH - w)/2,
770 TEXT_2_POS + i*REC_HEIGHT,
771 buttonChar[group][i][j] );
774 for (i = 0; i <= 0; i++){
775 for (j = 0; j <= 2; j++){
776 rb->lcd_getstringsize( buttonChar[group][i][j],&w,&h);
777 rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
778 rb->lcd_fillrect( X_0_POS + j*REC_WIDTH + 1,
779 Y_1_POS + i*REC_HEIGHT + 1,
780 REC_WIDTH - 1, REC_HEIGHT - 1);
781 rb->lcd_set_drawmode(DRMODE_SOLID);
782 rb->lcd_putsxy( X_0_POS + j*REC_WIDTH + (REC_WIDTH - w)/2,
783 TEXT_2_POS + i*REC_HEIGHT,
784 buttonChar[group][i][j] );
787 rb->lcd_set_drawmode(DRMODE_COMPLEMENT);
788 rb->lcd_fillrect( X_0_POS + 2*REC_WIDTH + 1,
789 Y_1_POS + 0*REC_HEIGHT + 1,
790 REC_WIDTH - 1, REC_HEIGHT - 1);
791 rb->lcd_set_drawmode(DRMODE_SOLID);
792 rb->lcd_update_rect( X_0_POS, Y_1_POS,
793 REC_WIDTH*5, REC_HEIGHT*5);
795 /* -----------------------------------------------------------------------
796 flash the button pressed
797 ----------------------------------------------------------------------- */
798 void flashButton(int b)
800 int i = b/5; int j = b - i*5;
801 int k;
802 rb->lcd_set_drawmode(DRMODE_COMPLEMENT);
803 for (k=1*2;k>0;k--){
804 rb->lcd_fillrect( X_0_POS + j*REC_WIDTH + 1,
805 Y_1_POS + i*REC_HEIGHT + 1,
806 REC_WIDTH - 1, REC_HEIGHT - 1);
807 rb->lcd_update_rect( X_0_POS + j*REC_WIDTH + 1,
808 Y_1_POS + i*REC_HEIGHT + 1,
809 REC_WIDTH - 1, REC_HEIGHT - 1);
811 if (k!= 1)
812 rb->sleep(HZ/22);
815 rb->lcd_set_drawmode(DRMODE_SOLID);
818 /* -----------------------------------------------------------------------
819 pos is the position that needs animation. pos = [1~18]
820 ----------------------------------------------------------------------- */
821 void deleteAnimation(int pos)
823 int k;
824 if (pos<1 || pos >18)
825 return;
826 pos--;
827 rb->lcd_fillrect(1+pos*6, TEXT_1_POS, 6, 8);
828 rb->lcd_update_rect(1+pos*6, TEXT_1_POS, 6, 8);
830 for (k=1;k<=4;k++){
831 rb->sleep(HZ/32);
832 rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
833 rb->lcd_fillrect(1+pos*6, TEXT_1_POS, 6, 8);
834 rb->lcd_set_drawmode(DRMODE_SOLID);
835 rb->lcd_fillrect(1+pos*6+1+k, TEXT_1_POS+k,
836 (5-2*k)>0?(5-2*k):1, (7-2*k)>0?(7-2*k):1 );
837 rb->lcd_update_rect(1+pos*6, TEXT_1_POS, 6, 8);
842 /* -----------------------------------------------------------------------
843 result may be one of these formats:
845 xxxx.xxxx
846 0.xxxx
847 0.0000xxxx
849 formatResult() change result to standard format: 0.xxxx
850 if result is close to 0, let it be 0;
851 if result is close to 1, let it be 0.1 and power++;
852 ----------------------------------------------------------------------- */
853 void formatResult(void)
855 int resultsign = SIGN(result);
856 result = ABS(result);
857 if(result > MINIMUM ){ /* doesn't check power, might have problem
858 input wouldn't,
859 + - * / of two formatted number wouldn't.
860 only a calculation that makes a formatted
861 number (0.xxxx) less than MINIMUM in only
862 one operation */
864 if (result<1){
865 while( (int)(result*10) == 0 ){
866 result *= 10;
867 power--;
868 modifier *= 10;
871 else{ /* result >= 1 */
872 while( (int)result != 0 ){
873 result /= 10;
874 power++;
875 modifier /= 10;
877 } /* if result<1 */
879 if (result > (1-MINIMUM)){
880 result = 0.1;
881 power++;
882 modifier /= 10;
884 result *= resultsign;
886 else {
887 result = 0;
888 power = 0;
889 modifier = 0.1;
893 /* -----------------------------------------------------------------------
894 result2typingbuf() outputs standard format result to typingbuf.
895 case SCIENTIFIC_FORMAT, let temppower = 1;
896 case temppower > 0: print '.' in the middle
897 case temppower <= 0: print '.' in the begining
898 ----------------------------------------------------------------------- */
899 void result2typingbuf(void)
901 bool haveDot = false;
902 char tempchar = 0;
903 int k;
904 double tempresult = ABS(result); /* positive num makes things simple */
906 int temppower;
907 double tempmodifier = 1;
908 int count;
910 if(SCIENTIFIC_FORMAT)
911 temppower = 1; /* output x.xxxx format */
912 else
913 temppower = power;
915 cleartypingbuf();
917 if(tempresult < MINIMUM){ /* if 0,faster display and avoid complication*/
918 typingbuf[0] = ' ';
919 typingbuf[1] = '0';
921 else{ /* tempresult > 0 */
922 typingbuf[0] = (SIGN(result)<0)?'-':' ';
924 typingbufPointer = typingbuf;
925 if(temppower > 0){
926 for (k = 0; k<DIGITLEN+1 ; k++){
927 typingbufPointer++;
928 if(temppower || *(typingbufPointer-1) == '.'){
929 count = 0;
930 tempmodifier = tempmodifier/10;
931 while( (tempresult-tempmodifier*count) >
932 (tempmodifier-MINIMUM)){
933 count++;
935 tempresult -= tempmodifier*count;
936 tempresult = ABS(tempresult);
937 temppower-- ;
938 *typingbufPointer = count + '0';
940 else{ /* temppower == 0 */
941 *typingbufPointer = '.';
942 haveDot = true;
944 } /* for */
946 else{
947 haveDot = true;
948 typingbufPointer++; *typingbufPointer = '0';
949 typingbufPointer++; *typingbufPointer = '.';
950 for (k = 2; k<DIGITLEN+1 ; k++){
951 typingbufPointer++;
952 count = 0;
953 if ( (-temppower) < (k-1)){
954 tempmodifier = tempmodifier/10;
955 while((tempresult-tempmodifier*count)>(tempmodifier-MINIMUM)){
956 count++;
959 tempresult -= tempmodifier*count;
960 tempresult = ABS(tempresult);
961 temppower-- ;
963 *typingbufPointer = count + '0';
966 /* now, typingbufPointer = typingbuf + 16 */
967 /* backward strip off 0 and '.' */
968 if (haveDot){
969 while( (*typingbufPointer == '0') || (*typingbufPointer == '.')){
970 tempchar = *typingbufPointer;
971 *typingbufPointer = 0;
972 typingbufPointer--;
973 if (tempchar == '.') break;
976 typingbuf[DIGITLEN+1] = 0;
977 } /* else tempresult > 0 */
980 /* -----------------------------------------------------------------------
981 printResult() generates LCD display.
982 ----------------------------------------------------------------------- */
983 void printResult(void)
985 int k;
987 switch_Status:
988 switch(calStatus){
989 case cal_exit:
990 rb->lcd_clear_display();
991 rb->splash(HZ/3, true, "Bye now!");
992 break;
993 case cal_error:
994 clearbuf();
995 rb->snprintf(buf, 19, "%18s","Error");
996 break;
997 case cal_toDo:
998 clearbuf();
999 rb->snprintf(buf, 19, "%18s","Coming soon ^_* ");
1000 break;
1002 case cal_normal:
1003 formatResult();
1005 if( power > 1000 ){ /* power -1 > 999 */
1006 calStatus = cal_error;
1007 goto switch_Status;
1009 if (power < -998 ) /* power -1 < -999 */
1010 clearResult(); /* too small, let it be 0 */
1012 result2typingbuf();
1013 clearbuf();
1015 buf[0] = oper;
1016 buf[1] = ( ABS(memTemp) > MINIMUM )?'M':' ';
1017 buf[2] = ' ';
1019 if(SCIENTIFIC_FORMAT){
1020 /* output format: X.XXXX eXXX */
1021 if(power > -98){ /* power-1 >= -99, eXXX or e-XX */
1022 rb->snprintf(buf+3, 12, "%11s",typingbuf);
1023 for(k=14;k<=17;k++) buf[k] = ' ';
1024 cleartypingbuf();
1025 rb->snprintf(typingbuf, 5, "e%d",power-1);
1026 rb->snprintf(buf+14, 5, "%4s",typingbuf);
1028 else{ /* power-1 <= -100, e-XXX */
1029 rb->snprintf(buf+2, 12, "%11s",typingbuf);
1030 rb->snprintf(buf+13, 6, "e%d",power-1);
1033 else{
1034 rb->snprintf(buf+7, 12, "%11s",typingbuf);
1035 } /* if SCIENTIFIC_FORMAT */
1036 break;
1037 case cal_typing:
1038 case cal_dotted:
1039 clearbuf();
1040 buf[0] = oper;
1041 buf[1] = ( ABS(memTemp) > MINIMUM )?'M':' ';
1042 for(k=2;k<=6;k++)
1043 buf[k] = ' ';
1044 rb->snprintf(buf+7, 12, "%11s",typingbuf);
1045 break;
1049 rb->lcd_putsxy(1, TEXT_1_POS,buf);
1050 rb->lcd_update_rect(1, TEXT_1_POS, 6*18, 8);
1053 /* -----------------------------------------------------------------------
1054 Process typing buttons: 1-9, '.', sign
1055 main operand "result" and typingbuf are processed seperately here.
1056 ----------------------------------------------------------------------- */
1057 void typingProcess(void){
1058 switch( CAL_BUTTON ){
1059 case btn_sign:
1060 if (calStatus == cal_typing ||
1061 calStatus == cal_dotted)
1062 typingbuf[0] = (typingbuf[0]=='-')?' ':'-';
1063 result = -result;
1064 break;
1065 case btn_dot:
1066 operInputted = false;
1067 switch(calStatus){
1068 case cal_normal:
1069 clearInput();
1070 *typingbufPointer = '0';
1071 typingbufPointer++;
1072 case cal_typing:
1073 calStatus = cal_dotted;
1074 *typingbufPointer = '.';
1075 if (typingbufPointer != typingbuf+DIGITLEN+1)
1076 typingbufPointer++;
1077 break;
1078 default: /* cal_dotted */
1079 break;
1081 break;
1082 default: /* 0-9 */
1083 operInputted = false;
1084 /* normal,0; normal,1-9; typing,0; typing,1-9 */
1085 switch(calStatus){
1086 case cal_normal:
1087 if(CAL_BUTTON == btn_0 )
1088 break; /* first input is 0, ignore */
1089 clearInput();
1090 /*no operator means start a new calculation*/
1091 if (oper ==' ')
1092 clearOperand();
1093 calStatus = cal_typing;
1094 /* go on typing, no break */
1095 case cal_typing:
1096 case cal_dotted:
1097 switch(CAL_BUTTON){
1098 case btn_0:
1099 *typingbufPointer = '0';
1100 break;
1101 default:
1102 *typingbufPointer=(7+n-3*(m-1))+ '0';
1103 break;
1105 if (typingbufPointer!=typingbuf+DIGITLEN+1){
1106 typingbufPointer++;
1108 {/* result processing */
1109 if (calStatus == cal_typing) power++;
1110 if (CAL_BUTTON != btn_0)
1111 result= result +
1112 SIGN(result)*
1113 (7+n-3*(m-1))*modifier;
1114 modifier /= 10;
1117 else /* last byte always '\0' */
1118 *typingbufPointer = 0;
1119 break;
1120 default: /* cal_error, cal_exit */
1121 break;
1123 break; /* default, 0-9 */
1124 } /* switch( CAL_BUTTON ) */
1127 /* -----------------------------------------------------------------------
1128 Handle delete operation
1129 main operand "result" and typingbuf are processed seperately here.
1130 ----------------------------------------------------------------------- */
1131 void doDelete(void){
1132 deleteAnimation(18);
1133 switch(calStatus){
1134 case cal_dotted:
1135 if (*(typingbufPointer-1) == '.'){
1136 /* if dotted and deleting '.',
1137 change status and delete '.' below */
1138 calStatus = cal_typing;
1140 else{ /* if dotted and not deleting '.',
1141 power stays */
1142 power++; /* counter "power--;" below */
1144 case cal_typing:
1145 typingbufPointer--;
1147 {/* result processing */ /* 0-9, '.' */
1148 /* if deleting '.', do nothing */
1149 if ( *typingbufPointer != '.'){
1150 power--;
1151 modifier *= 10;
1152 result = result - SIGN(result)*
1153 ((*typingbufPointer)- '0')*modifier;
1157 *typingbufPointer = 0;
1159 /* if (only one digit left and it's 0)
1160 or no digit left, change status*/
1161 if ( typingbufPointer == typingbuf+1 ||
1162 ( typingbufPointer == typingbuf+2 &&
1163 *(typingbufPointer-1) == '0' ))
1164 calStatus = cal_normal;
1165 break;
1166 default: /* normal, error, exit */
1167 break;
1170 /* -----------------------------------------------------------------------
1171 Handle buttons on basic screen
1172 ----------------------------------------------------------------------- */
1173 void basicButtonsProcess(void){
1174 switch (btn) {
1175 case CALCULATOR_INPUT:
1176 if (calStatus == cal_error && (CAL_BUTTON != btn_C) ) break;
1177 flashButton(CAL_BUTTON);
1178 switch( CAL_BUTTON ){
1179 case btn_MR:
1180 operInputted = false;
1181 result = memTemp; power = memTempPower;
1182 calStatus = cal_normal;
1183 break;
1184 case btn_M:
1185 formatResult();
1186 if (memTemp > MINIMUM)
1187 doAdd(&memTemp, &memTempPower, result, power);
1188 else {
1189 /* if result is too small and memTemp = 0,
1190 doAdd will not add */
1191 memTemp = result;
1192 memTempPower = power;
1194 calStatus = cal_normal;
1195 break;
1197 case btn_C: clearMem(); break;
1198 case btn_CE: clearInput(); break;
1200 case btn_bas:
1201 buttonGroup = sciButtons;
1202 printButtonGroups(buttonGroup);
1203 break;
1205 /* one operand calculation, may be changed to
1206 like sin, cos, log, etc */
1207 case btn_sqr:
1208 case btn_square:
1209 case btn_rec:
1210 formatResult(); /* not necessary, just for safty */
1211 oneOperand();
1212 break;
1214 case_btn_equal: /* F3 shortkey entrance */
1215 case btn_equal:
1216 formatResult();
1217 calStatus = cal_normal;
1218 operInputted = false;
1219 if (oper != ' ') twoOperands();
1220 break;
1222 case btn_div:
1223 case btn_time:
1224 case btn_minus:
1225 case btn_add:
1226 if(!operInputted) {twoOperands(); operInputted = true;}
1227 oper = buttonChar[basicButtons][m][n][0];
1228 #ifdef CALCULATOR_OPERATORS
1229 case_cycle_operators: /* F2 shortkey entrance */
1230 #endif
1231 calStatus = cal_normal;
1232 formatResult();
1233 operand = result;
1234 operandPower = power;
1236 break;
1238 case btn_sign:
1239 case btn_dot:
1240 default: /* 0-9 */
1241 typingProcess();
1242 break;
1243 } /* switch (CAL_BUTTON) */
1244 break;
1246 #ifdef CALCULATOR_OPERATORS
1247 case CALCULATOR_OPERATORS:
1248 if (calStatus == cal_error) break;
1249 if (!operInputted) {twoOperands(); operInputted = true;}
1250 switch (oper){
1251 case ' ':
1252 case '/': oper = '+'; flashButton(btn_add); break;
1253 case '+': oper = '-'; flashButton(btn_minus); break;
1254 case '-': oper = '*'; flashButton(btn_time); break;
1255 case '*': oper = '/'; flashButton(btn_div); break;
1257 goto case_cycle_operators;
1258 break;
1259 #endif
1261 case CALCULATOR_CALC:
1262 if (calStatus == cal_error) break;
1263 flashButton(btn_equal);
1264 goto case_btn_equal;
1265 break;
1266 default: break;
1268 printResult();
1271 /* -----------------------------------------------------------------------
1272 Handle buttons on scientific screen
1273 ----------------------------------------------------------------------- */
1274 void sciButtonsProcess(void){
1275 switch (btn) {
1276 case CALCULATOR_INPUT:
1277 if (calStatus == cal_error && (CAL_BUTTON != sci_sci) ) break;
1278 flashButton(CAL_BUTTON);
1279 switch( CAL_BUTTON ){
1281 case sci_pi:
1282 result = PI; power = 0;
1283 calStatus = cal_normal;
1284 break;
1286 case sci_xy: break;
1288 case sci_sci:
1289 buttonGroup = basicButtons;
1290 printButtonGroups(basicButtons);
1291 break;
1293 case sci_fac:
1294 case sci_sin:
1295 case sci_asin:
1296 case sci_cos:
1297 case sci_acos:
1298 case sci_tan:
1299 case sci_atan:
1300 case sci_ln:
1301 case sci_exp:
1302 case sci_log:
1303 formatResult(); /* not necessary, just for safty */
1304 oneOperand();
1305 break;
1307 case btn_sign:
1308 case btn_dot:
1309 default: /* 0-9 */
1310 typingProcess();
1311 break;
1312 } /* switch (CAL_BUTTON) */
1313 break;
1315 #ifdef CALCULATOR_OPERATORS
1316 case CALCULATOR_OPERATORS:
1317 if (calStatus == cal_error) break;
1318 if (!operInputted) {twoOperands(); operInputted = true;}
1319 switch (oper){
1320 case ' ': oper = '+'; break;
1321 case '/': oper = '+'; deleteAnimation(1); break;
1322 case '+': oper = '-'; deleteAnimation(1); break;
1323 case '-': oper = '*'; deleteAnimation(1); break;
1324 case '*': oper = '/'; deleteAnimation(1); break;
1326 calStatus = cal_normal;
1327 formatResult();
1328 operand = result;
1329 operandPower = power;
1330 break;
1331 #endif
1333 case CALCULATOR_CALC:
1334 if (calStatus == cal_error) break;
1335 formatResult();
1336 calStatus = cal_normal;
1337 operInputted = false;
1338 if (oper != ' ') twoOperands();
1339 break;
1340 default: break;
1342 printResult();
1345 /* -----------------------------------------------------------------------
1346 Main();
1347 ----------------------------------------------------------------------- */
1348 enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
1350 (void)parameter;
1351 rb = api;
1353 /* now go ahead and have fun! */
1355 cal_initial();
1357 while (calStatus != cal_exit ) {
1358 btn = rb->button_get_w_tmo(HZ/2);
1359 switch (btn) {
1360 case CALCULATOR_INPUT:
1361 case CALCULATOR_CALC:
1362 #ifdef CALCULATOR_INPUT_CALC_PRE
1363 if (lastbtn != CALCULATOR_INPUT_CALC_PRE)
1364 break;
1365 /* no unconditional break; here! */
1366 #endif
1367 #ifdef CALCULATOR_OPERATORS
1368 case CALCULATOR_OPERATORS:
1369 #endif
1370 switch(buttonGroup){
1371 case basicButtons:
1372 basicButtonsProcess();
1373 break;
1374 case sciButtons:
1375 sciButtonsProcess();
1376 break;
1378 break;
1380 #ifdef CALCULATOR_CLEAR
1381 case CALCULATOR_CLEAR:
1382 switch(calStatus){
1383 case cal_typing:
1384 case cal_dotted:
1385 doDelete();
1386 break;
1387 default: /* cal_normal, cal_error, cal_exit */
1388 clearMem();
1389 break;
1391 printResult();
1392 break;
1393 #endif
1395 case BUTTON_LEFT:
1396 case BUTTON_LEFT | BUTTON_REPEAT:
1397 case BUTTON_RIGHT:
1398 case BUTTON_RIGHT | BUTTON_REPEAT:
1399 case CALCULATOR_UP:
1400 case CALCULATOR_UP | BUTTON_REPEAT:
1401 case CALCULATOR_DOWN:
1402 case CALCULATOR_DOWN | BUTTON_REPEAT:
1403 moveButton();
1404 break;
1405 case CALCULATOR_QUIT:
1406 calStatus = cal_exit;
1407 printResult();
1408 break;
1409 default:
1410 if(rb->default_event_handler(btn) == SYS_USB_CONNECTED)
1411 return PLUGIN_USB_CONNECTED;
1412 break;
1413 } /* switch (btn) */
1414 if (btn != BUTTON_NONE)
1415 lastbtn = btn;
1416 } /* while (calStatus != cal_exit ) */
1418 /* rb->splash(HZ*2, true, "Hello world!"); */
1419 rb->button_clear_queue();
1420 return PLUGIN_OK;
1423 #endif /* #ifdef HAVE_LCD_BITMAP */