Save a few bytes by changing unit selection strategy
[kugel-rb.git] / apps / plugins / calculator.c
blob103ce50a078cc2be282d38b7aa7e3dbcf4771b05
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2004 Pengxuan Liu (Isaac)
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 == ARCHOS_AV300_PAD
120 #define CALCULATOR_UP BUTTON_UP
121 #define CALCULATOR_DOWN BUTTON_DOWN
122 #define CALCULATOR_QUIT BUTTON_OFF
123 #define CALCULATOR_INPUT BUTTON_SELECT
124 #define CALCULATOR_CALC BUTTON_F3
125 #define CALCULATOR_OPERATORS BUTTON_F2
126 #define CALCULATOR_CLEAR BUTTON_F1
128 #elif CONFIG_KEYPAD == ONDIO_PAD
129 #define CALCULATOR_UP BUTTON_UP
130 #define CALCULATOR_DOWN BUTTON_DOWN
131 #define CALCULATOR_QUIT BUTTON_OFF
132 #define CALCULATOR_INPUT_CALC_PRE BUTTON_MENU
133 #define CALCULATOR_INPUT (BUTTON_MENU | BUTTON_REL)
134 #define CALCULATOR_CALC (BUTTON_MENU | BUTTON_REPEAT)
136 #elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || \
137 (CONFIG_KEYPAD == IRIVER_H300_PAD)
138 #define CALCULATOR_UP BUTTON_UP
139 #define CALCULATOR_DOWN BUTTON_DOWN
140 #define CALCULATOR_QUIT BUTTON_OFF
141 #define CALCULATOR_INPUT BUTTON_SELECT
142 #define CALCULATOR_CALC BUTTON_ON
143 #define CALCULATOR_OPERATORS BUTTON_MODE
144 #define CALCULATOR_CLEAR BUTTON_REC
146 #define CALCULATOR_RC_QUIT BUTTON_RC_STOP
148 #elif (CONFIG_KEYPAD == IPOD_4G_PAD) || \
149 (CONFIG_KEYPAD == IPOD_3G_PAD) || \
150 (CONFIG_KEYPAD == IPOD_1G2G_PAD)
152 #define CALCULATOR_UP BUTTON_SCROLL_BACK
153 #define CALCULATOR_DOWN BUTTON_SCROLL_FWD
154 #define CALCULATOR_QUIT BUTTON_MENU
155 #define CALCULATOR_INPUT_CALC_PRE BUTTON_SELECT
156 #define CALCULATOR_INPUT (BUTTON_SELECT | BUTTON_REL)
157 #define CALCULATOR_CALC (BUTTON_PLAY | BUTTON_REPEAT)
159 #elif (CONFIG_KEYPAD == IAUDIO_X5M5_PAD)
161 #define CALCULATOR_UP BUTTON_UP
162 #define CALCULATOR_DOWN BUTTON_DOWN
163 #define CALCULATOR_QUIT BUTTON_POWER
164 #define CALCULATOR_INPUT_CALC_PRE BUTTON_SELECT
165 #define CALCULATOR_INPUT (BUTTON_SELECT | BUTTON_REL)
166 #define CALCULATOR_CALC BUTTON_PLAY
167 #define CALCULATOR_CLEAR BUTTON_REC
169 #elif (CONFIG_KEYPAD == GIGABEAT_PAD)
171 #define CALCULATOR_UP BUTTON_UP
172 #define CALCULATOR_DOWN BUTTON_DOWN
173 #define CALCULATOR_QUIT BUTTON_POWER
174 #define CALCULATOR_INPUT_CALC_PRE BUTTON_MENU
175 #define CALCULATOR_INPUT (BUTTON_MENU | BUTTON_REL)
176 #define CALCULATOR_CALC BUTTON_SELECT
177 #define CALCULATOR_CLEAR BUTTON_A
179 #elif (CONFIG_KEYPAD == SANSA_E200_PAD) || \
180 (CONFIG_KEYPAD == SANSA_C200_PAD)
181 #define CALCULATOR_UP BUTTON_UP
182 #define CALCULATOR_DOWN BUTTON_DOWN
183 #define CALCULATOR_QUIT BUTTON_POWER
184 #define CALCULATOR_INPUT_CALC_PRE BUTTON_SELECT
185 #define CALCULATOR_INPUT (BUTTON_SELECT|BUTTON_REL)
186 #define CALCULATOR_CALC (BUTTON_SELECT|BUTTON_REPEAT)
187 #define CALCULATOR_CLEAR BUTTON_REC
189 #elif (CONFIG_KEYPAD == IRIVER_H10_PAD)
191 #define CALCULATOR_UP BUTTON_SCROLL_UP
192 #define CALCULATOR_DOWN BUTTON_SCROLL_DOWN
193 #define CALCULATOR_QUIT BUTTON_POWER
194 #define CALCULATOR_INPUT_CALC_PRE BUTTON_PLAY
195 #define CALCULATOR_INPUT (BUTTON_PLAY | BUTTON_REL)
196 #define CALCULATOR_CALC BUTTON_PLAY
197 #define CALCULATOR_CLEAR BUTTON_REW
199 #endif
201 static struct plugin_api* rb;
203 enum {
204 basicButtons,
205 sciButtons
206 } buttonGroup;
207 unsigned char* buttonChar[2][5][5] = {
208 { { "MR" , "M+" , "2nd" , "CE" , "C" },
209 { "7" , "8" , "9" , "/" , "sqr" },
210 { "4" , "5" , "6" , "*" , "x^2" },
211 { "1" , "2" , "3" , "-" , "1/x" },
212 { "0" , "+/-", "." , "+" , "=" } },
214 { { "n!" , "PI" , "1st" , "sin" , "asi" },
215 { "7" , "8" , "9" , "cos" , "aco" },
216 { "4" , "5" , "6" , "tan" , "ata" },
217 { "1" , "2" , "3" , "ln" , "e^x" },
218 { "0" , "+/-", "." , "log" , "x^y" } }
220 enum { btn_MR , btn_M , btn_bas , btn_CE , btn_C ,
221 btn_7 , btn_8 , btn_9 , btn_div , btn_sqr ,
222 btn_4 , btn_5 , btn_6 , btn_time , btn_square ,
223 btn_1 , btn_2 , btn_3 , btn_minus , btn_rec ,
224 btn_0 , btn_sign , btn_dot , btn_add , btn_equal
226 enum { sci_fac, sci_pi , sci_sci , sci_sin , sci_asin ,
227 sci_7 , sci_8 , sci_9 , sci_cos , sci_acos ,
228 sci_4 , sci_5 , sci_6 , sci_tan , sci_atan ,
229 sci_1 , sci_2 , sci_3 , sci_ln , sci_exp ,
230 sci_0 , sci_sign , sci_dot , sci_log , sci_xy
233 #define MINIMUM 0.000000000001 /* e-12 */
234 /* ^ ^ ^ ^ */
235 /* 123456789abcdef */
237 #define DIGITLEN 10 /* must <= 10 */
238 #define SCIENTIFIC_FORMAT ( power < -(DIGITLEN-3) || power > (DIGITLEN))
239 /* 0.000 00000 0001 */
240 /* ^ ^ ^ ^ ^ ^ */
241 /* DIGITLEN 12345 6789a bcdef */
242 /* power 12 34567 89abc def */
243 /* 10^- 123 45678 9abcd ef */
245 unsigned char buf[19];/* 18 bytes of output line,
246 buf[0] is operator
247 buf[1] = 'M' if memTemp is not 0
248 buf[2] = ' '
250 if SCIENTIFIC_FORMAT
251 buf[2]-buf[12] or buf[3]-buf[13] = result;
252 format X.XXXXXXXX
253 buf[13] or buf[14] -buf[17] = power;
254 format eXXX or e-XXX
255 else
256 buf[3]-buf[6] = ' ';
257 buf[7]-buf[17] = result;
259 buf[18] = '\0' */
261 unsigned char typingbuf[DIGITLEN+2];/* byte 0 is sign or ' ',
262 byte 1~DIGITLEN are num and '.'
263 byte (DIGITLEN+1) is '\0' */
264 unsigned char* typingbufPointer = typingbuf;
266 double result = 0; /* main operand, format 0.xxxxx */
267 int power = 0; /* 10^power */
268 double modifier = 0.1; /* position of next input */
269 double operand = 0; /* second operand, format 0.xxxxx */
270 int operandPower = 0; /* 10^power of second operand */
271 char oper = ' '; /* operators: + - * / */
272 bool operInputted = false; /* false: do calculation first and
273 replace current oper
274 true: just replace current oper */
276 double memTemp = 0; /* temp memory */
277 int memTempPower = 0; /* 10^^power of memTemp */
279 int m, n, prev_m, prev_n; /* position index for button */
280 #define CAL_BUTTON (m*5+n)
282 int btn = BUTTON_NONE;
283 int lastbtn = BUTTON_NONE;
285 /* Status of calculator */
286 enum {cal_normal, /* 0, normal status, display result */
287 cal_typing, /* 1, currently typing, dot hasn't been typed */
288 cal_dotted, /* 2, currently typing, dot already has been typed. */
289 cal_error,
290 cal_exit,
291 cal_toDo
292 } calStatus;
294 /* constant table for CORDIC algorithm */
295 double cordicTable[51][2]= {
296 /* pow(2,0) - pow(2,-50) atan(pow(2,0) - atan(pow(2,-50) */
297 {1e+00, 7.853981633974483e-01},
298 {5e-01, 4.636476090008061e-01},
299 {2.5e-01, 2.449786631268641e-01},
300 {1.25e-01, 1.243549945467614e-01},
301 {6.25e-02, 6.241880999595735e-02},
302 {3.125e-02, 3.123983343026828e-02},
303 {1.5625e-02, 1.562372862047683e-02},
304 {7.8125e-03, 7.812341060101111e-03},
305 {3.90625e-03, 3.906230131966972e-03},
306 {1.953125e-03, 1.953122516478819e-03},
307 {9.765625e-04, 9.765621895593195e-04},
308 {4.8828125e-04, 4.882812111948983e-04},
309 {2.44140625e-04, 2.441406201493618e-04},
310 {1.220703125e-04, 1.220703118936702e-04},
311 {6.103515625e-05, 6.103515617420877e-05},
312 {3.0517578125e-05, 3.051757811552610e-05},
313 {1.52587890625e-05, 1.525878906131576e-05},
314 {7.62939453125e-06, 7.629394531101970e-06},
315 {3.814697265625e-06, 3.814697265606496e-06},
316 {1.9073486328125e-06, 1.907348632810187e-06},
317 {9.5367431640625e-07, 9.536743164059608e-07},
318 {4.76837158203125e-07, 4.768371582030888e-07},
319 {2.384185791015625e-07, 2.384185791015580e-07},
320 {1.1920928955078125e-07, 1.192092895507807e-07},
321 {5.9604644775390625e-08, 5.960464477539055e-08},
322 {2.98023223876953125e-08, 2.980232238769530e-08},
323 {1.490116119384765625e-08, 1.490116119384765e-08},
324 {7.450580596923828125e-09, 7.450580596923828e-09},
325 {3.7252902984619140625e-09, 3.725290298461914e-09},
326 {1.86264514923095703125e-09, 1.862645149230957e-09},
327 {9.31322574615478515625e-10, 9.313225746154785e-10},
328 {4.656612873077392578125e-10, 4.656612873077393e-10},
329 {2.3283064365386962890625e-10, 2.328306436538696e-10},
330 {1.16415321826934814453125e-10, 1.164153218269348e-10},
331 {5.82076609134674072265625e-11, 5.820766091346741e-11},
332 {2.910383045673370361328125e-11, 2.910383045673370e-11},
333 {1.4551915228366851806640625e-11, 1.455191522836685e-11},
334 {7.2759576141834259033203125e-12, 7.275957614183426e-12},
335 {3.63797880709171295166015625e-12, 3.637978807091713e-12},
336 {1.818989403545856475830078125e-12, 1.818989403545856e-12},
337 {9.094947017729282379150390625e-13, 9.094947017729282e-13},
338 {4.5474735088646411895751953125e-13, 4.547473508864641e-13},
339 {2.27373675443232059478759765625e-13, 2.273736754432321e-13},
340 {1.136868377216160297393798828125e-13, 1.136868377216160e-13},
341 {5.684341886080801486968994140625e-14, 5.684341886080801e-14},
342 {2.8421709430404007434844970703125e-14, 2.842170943040401e-14},
343 {1.42108547152020037174224853515625e-14, 1.421085471520200e-14},
344 {7.10542735760100185871124267578125e-15, 7.105427357601002e-15},
345 {3.552713678800500929355621337890625e-15, 3.552713678800501e-15},
346 {1.7763568394002504646778106689453125e-15, 1.776356839400250e-15},
347 {8.8817841970012523233890533447265625e-16, 8.881784197001252e-16}
350 void doMultiple(double* operandOne, int* powerOne,
351 double operandTwo, int powerTwo);
352 void doAdd (double* operandOne, int* powerOne,
353 double operandTwo, int powerTwo);
354 void printResult(void);
355 void formatResult(void);
356 void oneOperand(void);
358 /* -----------------------------------------------------------------------
359 Handy funtions
360 ----------------------------------------------------------------------- */
361 void cleartypingbuf(void)
363 int k;
364 for( k=1; k<=(DIGITLEN+1); k++)
365 typingbuf[k] = 0;
366 typingbuf[0] = ' ';
367 typingbufPointer = typingbuf+1;
369 void clearbuf(void)
371 int k;
372 for(k=0;k<18;k++)
373 buf[k]=' ';
374 buf[18] = 0;
376 void clearResult(void)
378 result = 0;
379 power = 0;
380 modifier = 0.1;
383 void clearInput(void)
385 calStatus = cal_normal;
386 clearResult();
387 cleartypingbuf();
390 void clearOperand(void)
392 operand = 0;
393 operandPower = 0;
396 void clearMemTemp(void)
398 memTemp = 0;
399 memTempPower = 0;
402 void clearOper(void)
404 oper = ' ';
405 operInputted = false;
408 void clearMem(void)
410 clearInput();
411 clearMemTemp();
412 clearOperand();
413 clearOper();
414 btn = BUTTON_NONE;
417 void switchOperands(void)
419 double tempr = operand;
420 int tempp = operandPower;
421 operand = result;
422 operandPower = power;
423 result = tempr;
424 power = tempp;
427 /* -----------------------------------------------------------------------
428 Initiate calculator
429 ----------------------------------------------------------------------- */
430 void cal_initial (void)
432 int i,j,w,h;
433 rb->lcd_setfont(FONT_SYSFIXED);
434 rb->lcd_clear_display();
436 /* draw lines */
437 rb->lcd_drawrect(X_0_POS, Y_0_POS, LCD_WIDTH-1, LCD_HEIGHT);
438 rb->lcd_drawline(X_0_POS, Y_1_POS-1, X_5_POS, Y_1_POS-1);
439 for (i = 0; i < 5 ; i++)
440 rb->lcd_drawline(X_0_POS, Y_1_POS+i*REC_HEIGHT,
441 X_5_POS, Y_1_POS+i*REC_HEIGHT);
442 for (i = 0; i < 4 ; i++)
443 rb->lcd_drawline(X_1_POS+i*REC_WIDTH, Y_1_POS,
444 X_1_POS+i*REC_WIDTH, Y_6_POS);
446 #ifdef CALCULATOR_OPERATORS
447 /* basic operators are available through separate button */
448 buttonGroup = sciButtons;
449 #else
450 buttonGroup = basicButtons;
451 #endif
452 /* draw buttons */
453 for (i = 0; i < 5; i++){
454 for (j = 0; j < 5; j++){
455 rb->lcd_getstringsize( buttonChar[buttonGroup][i][j],&w,&h);
456 rb->lcd_putsxy( X_0_POS + j*REC_WIDTH + (REC_WIDTH - w)/2,
457 TEXT_2_POS + i*REC_HEIGHT,
458 buttonChar[buttonGroup][i][j] );
462 /* initially, invert button "5" */
463 m = 2;
464 n = 1;
465 prev_m = m;
466 prev_n = n;
467 rb->lcd_set_drawmode(DRMODE_COMPLEMENT);
468 rb->lcd_fillrect( X_0_POS + n*REC_WIDTH + 1,
469 Y_1_POS + m*REC_HEIGHT + 1,
470 REC_WIDTH - 1, REC_HEIGHT - 1);
471 rb->lcd_set_drawmode(DRMODE_SOLID);
472 rb->lcd_update();
474 /* initial mem and output display*/
475 clearMem();
476 printResult();
478 /* clear button queue */
479 rb->button_clear_queue();
482 /* -----------------------------------------------------------------------
483 mySqrt uses Heron's algorithm, which is the Newtone-Raphson algorhitm
484 in it's private case for sqrt.
485 Thanks BlueChip for his intro text and Dave Straayer for the actual name.
486 ----------------------------------------------------------------------- */
487 double mySqrt(double square)
489 int k = 0;
490 double temp = 0;
491 double root= ABS(square+1)/2;
493 while( ABS(root - temp) > MINIMUM ){
494 temp = root;
495 root = (square/temp + temp)/2;
496 k++;
497 if (k>10000) return 0;
500 return root;
502 /* -----------------------------------------------------------------------
503 transcendFunc uses CORDIC (COordinate Rotation DIgital Computer) method
504 transcendFunc can do sin,cos,log,exp
505 input parameter is angle
506 ----------------------------------------------------------------------- */
507 void transcendFunc(char* func, double* tt, int* ttPower)
509 double t = (*tt)*M_PI/180; int tPower = *ttPower;
510 int sign = 1;
511 int n = 50; /* n <=50, tables are all <= 50 */
512 int j;
513 double x,y,z,xt,yt,zt;
515 if (tPower < -998) {
516 calStatus = cal_normal;
517 return;
519 if (tPower > 8) {
520 calStatus = cal_error;
521 return;
523 *ttPower = 0;
524 calStatus = cal_normal;
526 if( func[0] =='s' || func[0] =='S'|| func[0] =='t' || func[0] =='T')
527 sign = SIGN(t);
528 else {
529 /* if( func[0] =='c' || func[0] =='C') */
530 sign = 1;
532 t = ABS(t);
534 while (tPower > 0){
535 t *= 10;
536 tPower--;
538 while (tPower < 0) {
539 t /= 10;
540 tPower++;
542 j = 0;
543 while (t > j*M_TWOPI) {j++;}
544 t -= (j-1)*M_TWOPI;
545 if (M_PI_2 < t && t < 3*M_PI_2){
546 t = M_PI - t;
547 if (func[0] =='c' || func[0] =='C')
548 sign = -1;
549 else if (func[0] =='t' || func[0] =='T')
550 t*=-1;
552 else if ( 3*M_PI_2 <= t && t <= M_TWOPI)
553 t -= M_TWOPI;
555 x = 0.60725293500888; y = 0; z = t;
556 for (j=1;j<n+2;j++){
557 xt = x - SIGN(z) * y*cordicTable[j-1][0];
558 yt = y + SIGN(z) * x*cordicTable[j-1][0];
559 zt = z - SIGN(z) * cordicTable[j-1][1];
560 x = xt;
561 y=yt;
562 z=zt;
564 if( func[0] =='s' || func[0] =='S') {
565 *tt = sign*y;
566 return;
568 else if( func[0] =='c' || func[0] =='C') {
569 *tt = sign*x;
570 return;
572 else /*if( func[0] =='t' || func[0] =='T')*/ {
573 if(t==M_PI_2||t==-M_PI_2){
574 calStatus = cal_error;
575 return;
577 else{
578 *tt = sign*(y/x);
579 return;
584 /* -----------------------------------------------------------------------
585 add in scientific number format
586 ----------------------------------------------------------------------- */
587 void doAdd (double* operandOne, int* powerOne,
588 double operandTwo, int powerTwo)
590 if ( *powerOne >= powerTwo ){
591 if (*powerOne - powerTwo <= DIGITLEN+1){
592 while (powerTwo < *powerOne){
593 operandTwo /=10;
594 powerTwo++;
596 *operandOne += operandTwo;
598 /*do nothing if operandTwo is too small*/
600 else{
601 if (powerTwo - *powerOne <= DIGITLEN+1){
602 while(powerTwo > *powerOne){
603 *operandOne /=10;
604 (*powerOne)++;
606 (*operandOne) += operandTwo;
608 else{/* simply copy operandTwo if operandOne is too small */
609 *operandOne = operandTwo;
610 *powerOne = powerTwo;
614 /* -----------------------------------------------------------------------
615 multiple in scientific number format
616 ----------------------------------------------------------------------- */
617 void doMultiple(double* operandOne, int* powerOne,
618 double operandTwo, int powerTwo)
620 (*operandOne) *= operandTwo;
621 (*powerOne) += powerTwo;
624 /* -----------------------------------------------------------------------
625 Handles all one operand calculations
626 ----------------------------------------------------------------------- */
627 void oneOperand(void)
629 int k = 0;
630 if (buttonGroup == basicButtons){
631 switch(CAL_BUTTON){
632 case btn_sqr:
633 if (result<0)
634 calStatus = cal_error;
635 else{
636 if (power%2 == 1){
637 result = (mySqrt(result*10))/10;
638 power = (power+1) / 2;
640 else{
641 result = mySqrt(result);
642 power = power / 2;
644 calStatus = cal_normal;
646 break;
647 case btn_square:
648 power *= 2;
649 result *= result;
650 calStatus = cal_normal;
651 break;
653 case btn_rec:
654 if (result==0)
655 calStatus = cal_error;
656 else{
657 power = -power;
658 result = 1/result;
659 calStatus = cal_normal;
661 break;
662 default:
663 calStatus = cal_toDo;
664 break; /* just for the safety */
667 else{ /* sciButtons */
668 switch(CAL_BUTTON){
669 case sci_sin:
670 transcendFunc("sin", &result, &power);
671 break;
672 case sci_cos:
673 transcendFunc("cos", &result, &power);
674 break;
675 case sci_tan:
676 transcendFunc("tan", &result, &power);
677 break;
678 case sci_fac:
679 if (power<0 || power>8 || result<0 )
680 calStatus = cal_error;
681 else if(result == 0) {
682 result = 1;
683 power = 0;
685 else{
686 while(power > 0) {
687 result *= 10;
688 power--;
690 if ( ( result - (int)result) > MINIMUM )
691 calStatus = cal_error;
692 else {
693 k = result; result = 1;
694 while (k > 1){
695 doMultiple(&result, &power, k, 0);
696 formatResult();
697 k--;
699 calStatus = cal_normal;
702 break;
703 default:
704 calStatus = cal_toDo;
705 break; /* just for the safety */
711 /* -----------------------------------------------------------------------
712 Handles all two operands calculations
713 ----------------------------------------------------------------------- */
714 void twoOperands(void)
716 switch(oper){
717 case '-':
718 doAdd(&operand, &operandPower, -result, power);
719 break;
720 case '+':
721 doAdd(&operand, &operandPower, result, power);
722 break;
723 case '*':
724 doMultiple(&operand, &operandPower, result, power);
725 break;
726 case '/':
727 if ( ABS(result) > MINIMUM ){
728 doMultiple(&operand, &operandPower, 1/result, -power);
730 else
731 calStatus = cal_error;
732 break;
733 default: /* ' ' */
734 switchOperands(); /* counter switchOperands() below */
735 break;
736 } /* switch(oper) */
737 switchOperands();
738 clearOper();
740 /* -----------------------------------------------------------------------
741 move button index
742 Invert display new button, invert back previous button
743 ----------------------------------------------------------------------- */
744 void moveButton(void){
745 switch(btn){
746 case BUTTON_LEFT:
747 case BUTTON_LEFT | BUTTON_REPEAT:
748 if (n == 0)
749 n = 4;
750 else
751 n--;
752 break;
754 case BUTTON_RIGHT:
755 case BUTTON_RIGHT | BUTTON_REPEAT:
756 if (n == 4)
757 n = 0;
758 else
759 n++;
760 break;
762 case CALCULATOR_UP:
763 case CALCULATOR_UP | BUTTON_REPEAT:
764 if (m == 0)
765 m = 4;
766 else
767 m--;
768 break;
770 case CALCULATOR_DOWN:
771 case CALCULATOR_DOWN | BUTTON_REPEAT:
772 if (m == 4)
773 m = 0;
774 else
775 m++;
776 break;
779 rb->lcd_set_drawmode(DRMODE_COMPLEMENT);
780 rb->lcd_fillrect( X_0_POS + prev_n*REC_WIDTH + 1,
781 Y_1_POS + prev_m*REC_HEIGHT + 1,
782 REC_WIDTH - 1, REC_HEIGHT - 1);
784 rb->lcd_fillrect( X_0_POS + n*REC_WIDTH + 1,
785 Y_1_POS + m*REC_HEIGHT + 1,
786 REC_WIDTH - 1, REC_HEIGHT - 1);
787 rb->lcd_set_drawmode(DRMODE_SOLID);
789 rb->lcd_update_rect( X_0_POS + prev_n*REC_WIDTH + 1,
790 Y_1_POS + prev_m*REC_HEIGHT + 1,
791 REC_WIDTH - 1, REC_HEIGHT - 1);
793 rb->lcd_update_rect( X_0_POS + n*REC_WIDTH + 1,
794 Y_1_POS + m*REC_HEIGHT + 1,
795 REC_WIDTH - 1, REC_HEIGHT - 1);
797 prev_m = m;
798 prev_n = n;
800 /* -----------------------------------------------------------------------
801 Print buttons when switching 1st and 2nd
802 int group = {basicButtons, sciButtons}
803 ----------------------------------------------------------------------- */
804 void printButtonGroups(int group)
806 int i,j,w,h;
807 for (i = 0; i < 5; i++){
808 for (j = 3; j <= 4; j++){
809 rb->lcd_getstringsize( buttonChar[group][i][j],&w,&h);
810 rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
811 rb->lcd_fillrect( X_0_POS + j*REC_WIDTH + 1,
812 Y_1_POS + i*REC_HEIGHT + 1,
813 REC_WIDTH - 1, REC_HEIGHT - 1);
814 rb->lcd_set_drawmode(DRMODE_SOLID);
815 rb->lcd_putsxy( X_0_POS + j*REC_WIDTH + (REC_WIDTH - w)/2,
816 TEXT_2_POS + i*REC_HEIGHT,
817 buttonChar[group][i][j] );
820 for (i = 0; i <= 0; i++){
821 for (j = 0; j <= 2; j++){
822 rb->lcd_getstringsize( buttonChar[group][i][j],&w,&h);
823 rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
824 rb->lcd_fillrect( X_0_POS + j*REC_WIDTH + 1,
825 Y_1_POS + i*REC_HEIGHT + 1,
826 REC_WIDTH - 1, REC_HEIGHT - 1);
827 rb->lcd_set_drawmode(DRMODE_SOLID);
828 rb->lcd_putsxy( X_0_POS + j*REC_WIDTH + (REC_WIDTH - w)/2,
829 TEXT_2_POS + i*REC_HEIGHT,
830 buttonChar[group][i][j] );
833 rb->lcd_set_drawmode(DRMODE_COMPLEMENT);
834 rb->lcd_fillrect( X_0_POS + 2*REC_WIDTH + 1,
835 Y_1_POS + 0*REC_HEIGHT + 1,
836 REC_WIDTH - 1, REC_HEIGHT - 1);
837 rb->lcd_set_drawmode(DRMODE_SOLID);
838 rb->lcd_update_rect( X_0_POS, Y_1_POS,
839 REC_WIDTH*5, REC_HEIGHT*5);
841 /* -----------------------------------------------------------------------
842 flash the button pressed
843 ----------------------------------------------------------------------- */
844 void flashButton(int b)
846 int i = b/5; int j = b - i*5;
847 int k;
848 rb->lcd_set_drawmode(DRMODE_COMPLEMENT);
849 for (k=1*2;k>0;k--){
850 rb->lcd_fillrect( X_0_POS + j*REC_WIDTH + 1,
851 Y_1_POS + i*REC_HEIGHT + 1,
852 REC_WIDTH - 1, REC_HEIGHT - 1);
853 rb->lcd_update_rect( X_0_POS + j*REC_WIDTH + 1,
854 Y_1_POS + i*REC_HEIGHT + 1,
855 REC_WIDTH - 1, REC_HEIGHT - 1);
857 if (k!= 1)
858 rb->sleep(HZ/22);
861 rb->lcd_set_drawmode(DRMODE_SOLID);
864 /* -----------------------------------------------------------------------
865 pos is the position that needs animation. pos = [1~18]
866 ----------------------------------------------------------------------- */
867 void deleteAnimation(int pos)
869 int k;
870 if (pos<1 || pos >18)
871 return;
872 pos--;
873 rb->lcd_fillrect(1+pos*6, TEXT_1_POS, 6, 8);
874 rb->lcd_update_rect(1+pos*6, TEXT_1_POS, 6, 8);
876 for (k=1;k<=4;k++){
877 rb->sleep(HZ/32);
878 rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
879 rb->lcd_fillrect(1+pos*6, TEXT_1_POS, 6, 8);
880 rb->lcd_set_drawmode(DRMODE_SOLID);
881 rb->lcd_fillrect(1+pos*6+1+k, TEXT_1_POS+k,
882 (5-2*k)>0?(5-2*k):1, (7-2*k)>0?(7-2*k):1 );
883 rb->lcd_update_rect(1+pos*6, TEXT_1_POS, 6, 8);
888 /* -----------------------------------------------------------------------
889 result may be one of these formats:
891 xxxx.xxxx
892 0.xxxx
893 0.0000xxxx
895 formatResult() change result to standard format: 0.xxxx
896 if result is close to 0, let it be 0;
897 if result is close to 1, let it be 0.1 and power++;
898 ----------------------------------------------------------------------- */
899 void formatResult(void)
901 int resultsign = SIGN(result);
902 result = ABS(result);
903 if(result > MINIMUM ){ /* doesn't check power, might have problem
904 input wouldn't,
905 + - * / of two formatted number wouldn't.
906 only a calculation that makes a formatted
907 number (0.xxxx) less than MINIMUM in only
908 one operation */
910 if (result<1){
911 while( (int)(result*10) == 0 ){
912 result *= 10;
913 power--;
914 modifier *= 10;
917 else{ /* result >= 1 */
918 while( (int)result != 0 ){
919 result /= 10;
920 power++;
921 modifier /= 10;
923 } /* if result<1 */
925 if (result > (1-MINIMUM)){
926 result = 0.1;
927 power++;
928 modifier /= 10;
930 result *= resultsign;
932 else {
933 result = 0;
934 power = 0;
935 modifier = 0.1;
939 /* -----------------------------------------------------------------------
940 result2typingbuf() outputs standard format result to typingbuf.
941 case SCIENTIFIC_FORMAT, let temppower = 1;
942 case temppower > 0: print '.' in the middle
943 case temppower <= 0: print '.' in the begining
944 ----------------------------------------------------------------------- */
945 void result2typingbuf(void)
947 bool haveDot = false;
948 char tempchar = 0;
949 int k;
950 double tempresult = ABS(result); /* positive num makes things simple */
952 int temppower;
953 double tempmodifier = 1;
954 int count;
956 if(SCIENTIFIC_FORMAT)
957 temppower = 1; /* output x.xxxx format */
958 else
959 temppower = power;
961 cleartypingbuf();
963 if(tempresult < MINIMUM){ /* if 0,faster display and avoid complication*/
964 typingbuf[0] = ' ';
965 typingbuf[1] = '0';
967 else{ /* tempresult > 0 */
968 typingbuf[0] = (SIGN(result)<0)?'-':' ';
970 typingbufPointer = typingbuf;
971 if(temppower > 0){
972 for (k = 0; k<DIGITLEN+1 ; k++){
973 typingbufPointer++;
974 if(temppower || *(typingbufPointer-1) == '.'){
975 count = 0;
976 tempmodifier = tempmodifier/10;
977 while( (tempresult-tempmodifier*count) >
978 (tempmodifier-MINIMUM)){
979 count++;
981 tempresult -= tempmodifier*count;
982 tempresult = ABS(tempresult);
983 temppower-- ;
984 *typingbufPointer = count + '0';
986 else{ /* temppower == 0 */
987 *typingbufPointer = '.';
988 haveDot = true;
990 } /* for */
992 else{
993 haveDot = true;
994 typingbufPointer++; *typingbufPointer = '0';
995 typingbufPointer++; *typingbufPointer = '.';
996 for (k = 2; k<DIGITLEN+1 ; k++){
997 typingbufPointer++;
998 count = 0;
999 if ( (-temppower) < (k-1)){
1000 tempmodifier = tempmodifier/10;
1001 while((tempresult-tempmodifier*count)>(tempmodifier-MINIMUM)){
1002 count++;
1005 tempresult -= tempmodifier*count;
1006 tempresult = ABS(tempresult);
1007 temppower-- ;
1009 *typingbufPointer = count + '0';
1012 /* now, typingbufPointer = typingbuf + 16 */
1013 /* backward strip off 0 and '.' */
1014 if (haveDot){
1015 while( (*typingbufPointer == '0') || (*typingbufPointer == '.')){
1016 tempchar = *typingbufPointer;
1017 *typingbufPointer = 0;
1018 typingbufPointer--;
1019 if (tempchar == '.') break;
1022 typingbuf[DIGITLEN+1] = 0;
1023 } /* else tempresult > 0 */
1026 /* -----------------------------------------------------------------------
1027 printResult() generates LCD display.
1028 ----------------------------------------------------------------------- */
1029 void printResult(void)
1031 int k;
1033 switch_Status:
1034 switch(calStatus){
1035 case cal_exit:
1036 rb->lcd_clear_display();
1037 rb->splash(HZ/3, "Bye now!");
1038 break;
1039 case cal_error:
1040 clearbuf();
1041 rb->snprintf(buf, 19, "%18s","Error");
1042 break;
1043 case cal_toDo:
1044 clearbuf();
1045 rb->snprintf(buf, 19, "%18s","Coming soon ^_* ");
1046 break;
1048 case cal_normal:
1049 formatResult();
1051 if( power > 1000 ){ /* power -1 > 999 */
1052 calStatus = cal_error;
1053 goto switch_Status;
1055 if (power < -998 ) /* power -1 < -999 */
1056 clearResult(); /* too small, let it be 0 */
1058 result2typingbuf();
1059 clearbuf();
1061 buf[0] = oper;
1062 buf[1] = ( ABS(memTemp) > MINIMUM )?'M':' ';
1063 buf[2] = ' ';
1065 if(SCIENTIFIC_FORMAT){
1066 /* output format: X.XXXX eXXX */
1067 if(power > -98){ /* power-1 >= -99, eXXX or e-XX */
1068 rb->snprintf(buf+3, 12, "%11s",typingbuf);
1069 for(k=14;k<=17;k++) buf[k] = ' ';
1070 cleartypingbuf();
1071 rb->snprintf(typingbuf, 5, "e%d",power-1);
1072 rb->snprintf(buf+14, 5, "%4s",typingbuf);
1074 else{ /* power-1 <= -100, e-XXX */
1075 rb->snprintf(buf+2, 12, "%11s",typingbuf);
1076 rb->snprintf(buf+13, 6, "e%d",power-1);
1079 else{
1080 rb->snprintf(buf+7, 12, "%11s",typingbuf);
1081 } /* if SCIENTIFIC_FORMAT */
1082 break;
1083 case cal_typing:
1084 case cal_dotted:
1085 clearbuf();
1086 buf[0] = oper;
1087 buf[1] = ( ABS(memTemp) > MINIMUM )?'M':' ';
1088 for(k=2;k<=6;k++)
1089 buf[k] = ' ';
1090 rb->snprintf(buf+7, 12, "%11s",typingbuf);
1091 break;
1095 rb->lcd_putsxy(1, TEXT_1_POS,buf);
1096 rb->lcd_update_rect(1, TEXT_1_POS, 6*18, 8);
1099 /* -----------------------------------------------------------------------
1100 Process typing buttons: 1-9, '.', sign
1101 main operand "result" and typingbuf are processed seperately here.
1102 ----------------------------------------------------------------------- */
1103 void typingProcess(void){
1104 switch( CAL_BUTTON ){
1105 case btn_sign:
1106 if (calStatus == cal_typing ||
1107 calStatus == cal_dotted)
1108 typingbuf[0] = (typingbuf[0]=='-')?' ':'-';
1109 result = -result;
1110 break;
1111 case btn_dot:
1112 operInputted = false;
1113 switch(calStatus){
1114 case cal_normal:
1115 clearInput();
1116 *typingbufPointer = '0';
1117 typingbufPointer++;
1118 case cal_typing:
1119 calStatus = cal_dotted;
1120 *typingbufPointer = '.';
1121 if (typingbufPointer != typingbuf+DIGITLEN+1)
1122 typingbufPointer++;
1123 break;
1124 default: /* cal_dotted */
1125 break;
1127 break;
1128 default: /* 0-9 */
1129 operInputted = false;
1130 /* normal,0; normal,1-9; typing,0; typing,1-9 */
1131 switch(calStatus){
1132 case cal_normal:
1133 if(CAL_BUTTON == btn_0 )
1134 break; /* first input is 0, ignore */
1135 clearInput();
1136 /*no operator means start a new calculation*/
1137 if (oper ==' ')
1138 clearOperand();
1139 calStatus = cal_typing;
1140 /* go on typing, no break */
1141 case cal_typing:
1142 case cal_dotted:
1143 switch(CAL_BUTTON){
1144 case btn_0:
1145 *typingbufPointer = '0';
1146 break;
1147 default:
1148 *typingbufPointer=(7+n-3*(m-1))+ '0';
1149 break;
1151 if (typingbufPointer!=typingbuf+DIGITLEN+1){
1152 typingbufPointer++;
1154 {/* result processing */
1155 if (calStatus == cal_typing) power++;
1156 if (CAL_BUTTON != btn_0)
1157 result= result +
1158 SIGN(result)*
1159 (7+n-3*(m-1))*modifier;
1160 modifier /= 10;
1163 else /* last byte always '\0' */
1164 *typingbufPointer = 0;
1165 break;
1166 default: /* cal_error, cal_exit */
1167 break;
1169 break; /* default, 0-9 */
1170 } /* switch( CAL_BUTTON ) */
1173 /* -----------------------------------------------------------------------
1174 Handle delete operation
1175 main operand "result" and typingbuf are processed seperately here.
1176 ----------------------------------------------------------------------- */
1177 void doDelete(void){
1178 deleteAnimation(18);
1179 switch(calStatus){
1180 case cal_dotted:
1181 if (*(typingbufPointer-1) == '.'){
1182 /* if dotted and deleting '.',
1183 change status and delete '.' below */
1184 calStatus = cal_typing;
1186 else{ /* if dotted and not deleting '.',
1187 power stays */
1188 power++; /* counter "power--;" below */
1190 case cal_typing:
1191 typingbufPointer--;
1193 {/* result processing */ /* 0-9, '.' */
1194 /* if deleting '.', do nothing */
1195 if ( *typingbufPointer != '.'){
1196 power--;
1197 modifier *= 10;
1198 result = result - SIGN(result)*
1199 ((*typingbufPointer)- '0')*modifier;
1203 *typingbufPointer = 0;
1205 /* if (only one digit left and it's 0)
1206 or no digit left, change status*/
1207 if ( typingbufPointer == typingbuf+1 ||
1208 ( typingbufPointer == typingbuf+2 &&
1209 *(typingbufPointer-1) == '0' ))
1210 calStatus = cal_normal;
1211 break;
1212 default: /* normal, error, exit */
1213 break;
1216 /* -----------------------------------------------------------------------
1217 Handle buttons on basic screen
1218 ----------------------------------------------------------------------- */
1219 void basicButtonsProcess(void){
1220 switch (btn) {
1221 case CALCULATOR_INPUT:
1222 if (calStatus == cal_error && (CAL_BUTTON != btn_C) ) break;
1223 flashButton(CAL_BUTTON);
1224 switch( CAL_BUTTON ){
1225 case btn_MR:
1226 operInputted = false;
1227 result = memTemp; power = memTempPower;
1228 calStatus = cal_normal;
1229 break;
1230 case btn_M:
1231 formatResult();
1232 if (memTemp > MINIMUM)
1233 doAdd(&memTemp, &memTempPower, result, power);
1234 else {
1235 /* if result is too small and memTemp = 0,
1236 doAdd will not add */
1237 memTemp = result;
1238 memTempPower = power;
1240 calStatus = cal_normal;
1241 break;
1243 case btn_C: clearMem(); break;
1244 case btn_CE: clearInput(); break;
1246 case btn_bas:
1247 buttonGroup = sciButtons;
1248 printButtonGroups(buttonGroup);
1249 break;
1251 /* one operand calculation, may be changed to
1252 like sin, cos, log, etc */
1253 case btn_sqr:
1254 case btn_square:
1255 case btn_rec:
1256 formatResult(); /* not necessary, just for safty */
1257 oneOperand();
1258 break;
1260 case_btn_equal: /* F3 shortkey entrance */
1261 case btn_equal:
1262 formatResult();
1263 calStatus = cal_normal;
1264 operInputted = false;
1265 if (oper != ' ') twoOperands();
1266 break;
1268 case btn_div:
1269 case btn_time:
1270 case btn_minus:
1271 case btn_add:
1272 if(!operInputted) {twoOperands(); operInputted = true;}
1273 oper = buttonChar[basicButtons][m][n][0];
1274 #ifdef CALCULATOR_OPERATORS
1275 case_cycle_operators: /* F2 shortkey entrance */
1276 #endif
1277 calStatus = cal_normal;
1278 formatResult();
1279 operand = result;
1280 operandPower = power;
1282 break;
1284 case btn_sign:
1285 case btn_dot:
1286 default: /* 0-9 */
1287 typingProcess();
1288 break;
1289 } /* switch (CAL_BUTTON) */
1290 break;
1292 #ifdef CALCULATOR_OPERATORS
1293 case CALCULATOR_OPERATORS:
1294 if (calStatus == cal_error) break;
1295 if (!operInputted) {twoOperands(); operInputted = true;}
1296 switch (oper){
1297 case ' ':
1298 case '/': oper = '+'; flashButton(btn_add); break;
1299 case '+': oper = '-'; flashButton(btn_minus); break;
1300 case '-': oper = '*'; flashButton(btn_time); break;
1301 case '*': oper = '/'; flashButton(btn_div); break;
1303 goto case_cycle_operators;
1304 break;
1305 #endif
1307 case CALCULATOR_CALC:
1308 if (calStatus == cal_error) break;
1309 flashButton(btn_equal);
1310 goto case_btn_equal;
1311 break;
1312 default: break;
1314 printResult();
1317 /* -----------------------------------------------------------------------
1318 Handle buttons on scientific screen
1319 ----------------------------------------------------------------------- */
1320 void sciButtonsProcess(void){
1321 switch (btn) {
1322 case CALCULATOR_INPUT:
1323 if (calStatus == cal_error && (CAL_BUTTON != sci_sci) ) break;
1324 flashButton(CAL_BUTTON);
1325 switch( CAL_BUTTON ){
1327 case sci_pi:
1328 result = M_PI; power = 0;
1329 calStatus = cal_normal;
1330 break;
1332 case sci_xy: break;
1334 case sci_sci:
1335 buttonGroup = basicButtons;
1336 printButtonGroups(basicButtons);
1337 break;
1339 case sci_fac:
1340 case sci_sin:
1341 case sci_asin:
1342 case sci_cos:
1343 case sci_acos:
1344 case sci_tan:
1345 case sci_atan:
1346 case sci_ln:
1347 case sci_exp:
1348 case sci_log:
1349 formatResult(); /* not necessary, just for safty */
1350 oneOperand();
1351 break;
1353 case btn_sign:
1354 case btn_dot:
1355 default: /* 0-9 */
1356 typingProcess();
1357 break;
1358 } /* switch (CAL_BUTTON) */
1359 break;
1361 #ifdef CALCULATOR_OPERATORS
1362 case CALCULATOR_OPERATORS:
1363 if (calStatus == cal_error) break;
1364 if (!operInputted) {twoOperands(); operInputted = true;}
1365 switch (oper){
1366 case ' ': oper = '+'; break;
1367 case '/': oper = '+'; deleteAnimation(1); break;
1368 case '+': oper = '-'; deleteAnimation(1); break;
1369 case '-': oper = '*'; deleteAnimation(1); break;
1370 case '*': oper = '/'; deleteAnimation(1); break;
1372 calStatus = cal_normal;
1373 formatResult();
1374 operand = result;
1375 operandPower = power;
1376 break;
1377 #endif
1379 case CALCULATOR_CALC:
1380 if (calStatus == cal_error) break;
1381 formatResult();
1382 calStatus = cal_normal;
1383 operInputted = false;
1384 if (oper != ' ') twoOperands();
1385 break;
1386 default: break;
1388 printResult();
1391 /* -----------------------------------------------------------------------
1392 Main();
1393 ----------------------------------------------------------------------- */
1394 enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
1396 (void)parameter;
1397 rb = api;
1399 /* now go ahead and have fun! */
1401 cal_initial();
1403 while (calStatus != cal_exit ) {
1404 btn = rb->button_get_w_tmo(HZ/2);
1405 switch (btn) {
1406 case CALCULATOR_INPUT:
1407 case CALCULATOR_CALC:
1408 #ifdef CALCULATOR_INPUT_CALC_PRE
1409 if (lastbtn != CALCULATOR_INPUT_CALC_PRE)
1410 break;
1411 /* no unconditional break; here! */
1412 #endif
1413 #ifdef CALCULATOR_OPERATORS
1414 case CALCULATOR_OPERATORS:
1415 #endif
1416 switch(buttonGroup){
1417 case basicButtons:
1418 basicButtonsProcess();
1419 break;
1420 case sciButtons:
1421 sciButtonsProcess();
1422 break;
1424 break;
1426 #ifdef CALCULATOR_CLEAR
1427 case CALCULATOR_CLEAR:
1428 switch(calStatus){
1429 case cal_typing:
1430 case cal_dotted:
1431 doDelete();
1432 break;
1433 default: /* cal_normal, cal_error, cal_exit */
1434 clearMem();
1435 break;
1437 printResult();
1438 break;
1439 #endif
1441 case BUTTON_LEFT:
1442 case BUTTON_LEFT | BUTTON_REPEAT:
1443 case BUTTON_RIGHT:
1444 case BUTTON_RIGHT | BUTTON_REPEAT:
1445 case CALCULATOR_UP:
1446 case CALCULATOR_UP | BUTTON_REPEAT:
1447 case CALCULATOR_DOWN:
1448 case CALCULATOR_DOWN | BUTTON_REPEAT:
1449 moveButton();
1450 break;
1451 #ifdef CALCULATOR_RC_QUIT
1452 case CALCULATOR_RC_QUIT:
1453 #endif
1454 case CALCULATOR_QUIT:
1455 calStatus = cal_exit;
1456 printResult();
1457 break;
1458 default:
1459 if(rb->default_event_handler(btn) == SYS_USB_CONNECTED)
1460 return PLUGIN_USB_CONNECTED;
1461 break;
1462 } /* switch (btn) */
1463 if (btn != BUTTON_NONE)
1464 lastbtn = btn;
1465 } /* while (calStatus != cal_exit ) */
1467 /* rb->splash(HZ*2, "Hello world!"); */
1468 rb->button_clear_queue();
1469 return PLUGIN_OK;
1472 #endif /* #ifdef HAVE_LCD_BITMAP */