when changing settings from the Talk and Voice window also update the main widgets...
[Rockbox.git] / apps / plugins / calculator.c
blob1819e983f7cf1ae17a5ab7a9c1b10841281c1463
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 #elif (CONFIG_KEYPAD == GIGABEAT_S_PAD)
201 #define CALCULATOR_UP BUTTON_UP
202 #define CALCULATOR_DOWN BUTTON_DOWN
203 #define CALCULATOR_QUIT BUTTON_BACK
204 #define CALCULATOR_INPUT_CALC_PRE BUTTON_MENU
205 #define CALCULATOR_INPUT (BUTTON_MENU | BUTTON_REL)
206 #define CALCULATOR_CALC BUTTON_SELECT
207 #define CALCULATOR_CLEAR BUTTON_PLAY
209 #elif (CONFIG_KEYPAD == MROBE100_PAD)
211 #define CALCULATOR_UP BUTTON_UP
212 #define CALCULATOR_DOWN BUTTON_DOWN
213 #define CALCULATOR_QUIT BUTTON_POWER
214 #define CALCULATOR_INPUT_CALC_PRE BUTTON_MENU
215 #define CALCULATOR_INPUT (BUTTON_MENU | BUTTON_REL)
216 #define CALCULATOR_CALC BUTTON_SELECT
217 #define CALCULATOR_CLEAR BUTTON_DISPLAY
219 #else
220 #error No keymap defined!
221 #endif
223 static struct plugin_api* rb;
225 enum {
226 basicButtons,
227 sciButtons
228 } buttonGroup;
229 unsigned char* buttonChar[2][5][5] = {
230 { { "MR" , "M+" , "2nd" , "CE" , "C" },
231 { "7" , "8" , "9" , "/" , "sqr" },
232 { "4" , "5" , "6" , "*" , "x^2" },
233 { "1" , "2" , "3" , "-" , "1/x" },
234 { "0" , "+/-", "." , "+" , "=" } },
236 { { "n!" , "PI" , "1st" , "sin" , "asi" },
237 { "7" , "8" , "9" , "cos" , "aco" },
238 { "4" , "5" , "6" , "tan" , "ata" },
239 { "1" , "2" , "3" , "ln" , "e^x" },
240 { "0" , "+/-", "." , "log" , "x^y" } }
242 enum { btn_MR , btn_M , btn_bas , btn_CE , btn_C ,
243 btn_7 , btn_8 , btn_9 , btn_div , btn_sqr ,
244 btn_4 , btn_5 , btn_6 , btn_time , btn_square ,
245 btn_1 , btn_2 , btn_3 , btn_minus , btn_rec ,
246 btn_0 , btn_sign , btn_dot , btn_add , btn_equal
248 enum { sci_fac, sci_pi , sci_sci , sci_sin , sci_asin ,
249 sci_7 , sci_8 , sci_9 , sci_cos , sci_acos ,
250 sci_4 , sci_5 , sci_6 , sci_tan , sci_atan ,
251 sci_1 , sci_2 , sci_3 , sci_ln , sci_exp ,
252 sci_0 , sci_sign , sci_dot , sci_log , sci_xy
255 #define MINIMUM 0.000000000001 /* e-12 */
256 /* ^ ^ ^ ^ */
257 /* 123456789abcdef */
259 #define DIGITLEN 10 /* must <= 10 */
260 #define SCIENTIFIC_FORMAT ( power < -(DIGITLEN-3) || power > (DIGITLEN))
261 /* 0.000 00000 0001 */
262 /* ^ ^ ^ ^ ^ ^ */
263 /* DIGITLEN 12345 6789a bcdef */
264 /* power 12 34567 89abc def */
265 /* 10^- 123 45678 9abcd ef */
267 unsigned char buf[19];/* 18 bytes of output line,
268 buf[0] is operator
269 buf[1] = 'M' if memTemp is not 0
270 buf[2] = ' '
272 if SCIENTIFIC_FORMAT
273 buf[2]-buf[12] or buf[3]-buf[13] = result;
274 format X.XXXXXXXX
275 buf[13] or buf[14] -buf[17] = power;
276 format eXXX or e-XXX
277 else
278 buf[3]-buf[6] = ' ';
279 buf[7]-buf[17] = result;
281 buf[18] = '\0' */
283 unsigned char typingbuf[DIGITLEN+2];/* byte 0 is sign or ' ',
284 byte 1~DIGITLEN are num and '.'
285 byte (DIGITLEN+1) is '\0' */
286 unsigned char* typingbufPointer = typingbuf;
288 double result = 0; /* main operand, format 0.xxxxx */
289 int power = 0; /* 10^power */
290 double modifier = 0.1; /* position of next input */
291 double operand = 0; /* second operand, format 0.xxxxx */
292 int operandPower = 0; /* 10^power of second operand */
293 char oper = ' '; /* operators: + - * / */
294 bool operInputted = false; /* false: do calculation first and
295 replace current oper
296 true: just replace current oper */
298 double memTemp = 0; /* temp memory */
299 int memTempPower = 0; /* 10^^power of memTemp */
301 int m, n, prev_m, prev_n; /* position index for button */
302 #define CAL_BUTTON (m*5+n)
304 int btn = BUTTON_NONE;
305 int lastbtn = BUTTON_NONE;
307 /* Status of calculator */
308 enum {cal_normal, /* 0, normal status, display result */
309 cal_typing, /* 1, currently typing, dot hasn't been typed */
310 cal_dotted, /* 2, currently typing, dot already has been typed. */
311 cal_error,
312 cal_exit,
313 cal_toDo
314 } calStatus;
316 /* constant table for CORDIC algorithm */
317 double cordicTable[51][2]= {
318 /* pow(2,0) - pow(2,-50) atan(pow(2,0) - atan(pow(2,-50) */
319 {1e+00, 7.853981633974483e-01},
320 {5e-01, 4.636476090008061e-01},
321 {2.5e-01, 2.449786631268641e-01},
322 {1.25e-01, 1.243549945467614e-01},
323 {6.25e-02, 6.241880999595735e-02},
324 {3.125e-02, 3.123983343026828e-02},
325 {1.5625e-02, 1.562372862047683e-02},
326 {7.8125e-03, 7.812341060101111e-03},
327 {3.90625e-03, 3.906230131966972e-03},
328 {1.953125e-03, 1.953122516478819e-03},
329 {9.765625e-04, 9.765621895593195e-04},
330 {4.8828125e-04, 4.882812111948983e-04},
331 {2.44140625e-04, 2.441406201493618e-04},
332 {1.220703125e-04, 1.220703118936702e-04},
333 {6.103515625e-05, 6.103515617420877e-05},
334 {3.0517578125e-05, 3.051757811552610e-05},
335 {1.52587890625e-05, 1.525878906131576e-05},
336 {7.62939453125e-06, 7.629394531101970e-06},
337 {3.814697265625e-06, 3.814697265606496e-06},
338 {1.9073486328125e-06, 1.907348632810187e-06},
339 {9.5367431640625e-07, 9.536743164059608e-07},
340 {4.76837158203125e-07, 4.768371582030888e-07},
341 {2.384185791015625e-07, 2.384185791015580e-07},
342 {1.1920928955078125e-07, 1.192092895507807e-07},
343 {5.9604644775390625e-08, 5.960464477539055e-08},
344 {2.98023223876953125e-08, 2.980232238769530e-08},
345 {1.490116119384765625e-08, 1.490116119384765e-08},
346 {7.450580596923828125e-09, 7.450580596923828e-09},
347 {3.7252902984619140625e-09, 3.725290298461914e-09},
348 {1.86264514923095703125e-09, 1.862645149230957e-09},
349 {9.31322574615478515625e-10, 9.313225746154785e-10},
350 {4.656612873077392578125e-10, 4.656612873077393e-10},
351 {2.3283064365386962890625e-10, 2.328306436538696e-10},
352 {1.16415321826934814453125e-10, 1.164153218269348e-10},
353 {5.82076609134674072265625e-11, 5.820766091346741e-11},
354 {2.910383045673370361328125e-11, 2.910383045673370e-11},
355 {1.4551915228366851806640625e-11, 1.455191522836685e-11},
356 {7.2759576141834259033203125e-12, 7.275957614183426e-12},
357 {3.63797880709171295166015625e-12, 3.637978807091713e-12},
358 {1.818989403545856475830078125e-12, 1.818989403545856e-12},
359 {9.094947017729282379150390625e-13, 9.094947017729282e-13},
360 {4.5474735088646411895751953125e-13, 4.547473508864641e-13},
361 {2.27373675443232059478759765625e-13, 2.273736754432321e-13},
362 {1.136868377216160297393798828125e-13, 1.136868377216160e-13},
363 {5.684341886080801486968994140625e-14, 5.684341886080801e-14},
364 {2.8421709430404007434844970703125e-14, 2.842170943040401e-14},
365 {1.42108547152020037174224853515625e-14, 1.421085471520200e-14},
366 {7.10542735760100185871124267578125e-15, 7.105427357601002e-15},
367 {3.552713678800500929355621337890625e-15, 3.552713678800501e-15},
368 {1.7763568394002504646778106689453125e-15, 1.776356839400250e-15},
369 {8.8817841970012523233890533447265625e-16, 8.881784197001252e-16}
372 void doMultiple(double* operandOne, int* powerOne,
373 double operandTwo, int powerTwo);
374 void doAdd (double* operandOne, int* powerOne,
375 double operandTwo, int powerTwo);
376 void printResult(void);
377 void formatResult(void);
378 void oneOperand(void);
380 /* -----------------------------------------------------------------------
381 Handy funtions
382 ----------------------------------------------------------------------- */
383 void cleartypingbuf(void)
385 int k;
386 for( k=1; k<=(DIGITLEN+1); k++)
387 typingbuf[k] = 0;
388 typingbuf[0] = ' ';
389 typingbufPointer = typingbuf+1;
391 void clearbuf(void)
393 int k;
394 for(k=0;k<18;k++)
395 buf[k]=' ';
396 buf[18] = 0;
398 void clearResult(void)
400 result = 0;
401 power = 0;
402 modifier = 0.1;
405 void clearInput(void)
407 calStatus = cal_normal;
408 clearResult();
409 cleartypingbuf();
412 void clearOperand(void)
414 operand = 0;
415 operandPower = 0;
418 void clearMemTemp(void)
420 memTemp = 0;
421 memTempPower = 0;
424 void clearOper(void)
426 oper = ' ';
427 operInputted = false;
430 void clearMem(void)
432 clearInput();
433 clearMemTemp();
434 clearOperand();
435 clearOper();
436 btn = BUTTON_NONE;
439 void switchOperands(void)
441 double tempr = operand;
442 int tempp = operandPower;
443 operand = result;
444 operandPower = power;
445 result = tempr;
446 power = tempp;
449 /* -----------------------------------------------------------------------
450 Initiate calculator
451 ----------------------------------------------------------------------- */
452 void cal_initial (void)
454 int i,j,w,h;
455 rb->lcd_setfont(FONT_SYSFIXED);
456 rb->lcd_clear_display();
458 /* draw lines */
459 rb->lcd_drawrect(X_0_POS, Y_0_POS, LCD_WIDTH-1, LCD_HEIGHT);
460 rb->lcd_drawline(X_0_POS, Y_1_POS-1, X_5_POS, Y_1_POS-1);
461 for (i = 0; i < 5 ; i++)
462 rb->lcd_drawline(X_0_POS, Y_1_POS+i*REC_HEIGHT,
463 X_5_POS, Y_1_POS+i*REC_HEIGHT);
464 for (i = 0; i < 4 ; i++)
465 rb->lcd_drawline(X_1_POS+i*REC_WIDTH, Y_1_POS,
466 X_1_POS+i*REC_WIDTH, Y_6_POS);
468 #ifdef CALCULATOR_OPERATORS
469 /* basic operators are available through separate button */
470 buttonGroup = sciButtons;
471 #else
472 buttonGroup = basicButtons;
473 #endif
474 /* draw buttons */
475 for (i = 0; i < 5; i++){
476 for (j = 0; j < 5; j++){
477 rb->lcd_getstringsize( buttonChar[buttonGroup][i][j],&w,&h);
478 rb->lcd_putsxy( X_0_POS + j*REC_WIDTH + (REC_WIDTH - w)/2,
479 TEXT_2_POS + i*REC_HEIGHT,
480 buttonChar[buttonGroup][i][j] );
484 /* initially, invert button "5" */
485 m = 2;
486 n = 1;
487 prev_m = m;
488 prev_n = n;
489 rb->lcd_set_drawmode(DRMODE_COMPLEMENT);
490 rb->lcd_fillrect( X_0_POS + n*REC_WIDTH + 1,
491 Y_1_POS + m*REC_HEIGHT + 1,
492 REC_WIDTH - 1, REC_HEIGHT - 1);
493 rb->lcd_set_drawmode(DRMODE_SOLID);
494 rb->lcd_update();
496 /* initial mem and output display*/
497 clearMem();
498 printResult();
500 /* clear button queue */
501 rb->button_clear_queue();
504 /* -----------------------------------------------------------------------
505 mySqrt uses Heron's algorithm, which is the Newtone-Raphson algorhitm
506 in it's private case for sqrt.
507 Thanks BlueChip for his intro text and Dave Straayer for the actual name.
508 ----------------------------------------------------------------------- */
509 double mySqrt(double square)
511 int k = 0;
512 double temp = 0;
513 double root= ABS(square+1)/2;
515 while( ABS(root - temp) > MINIMUM ){
516 temp = root;
517 root = (square/temp + temp)/2;
518 k++;
519 if (k>10000) return 0;
522 return root;
524 /* -----------------------------------------------------------------------
525 transcendFunc uses CORDIC (COordinate Rotation DIgital Computer) method
526 transcendFunc can do sin,cos,log,exp
527 input parameter is angle
528 ----------------------------------------------------------------------- */
529 void transcendFunc(char* func, double* tt, int* ttPower)
531 double t = (*tt)*M_PI/180; int tPower = *ttPower;
532 int sign = 1;
533 int n = 50; /* n <=50, tables are all <= 50 */
534 int j;
535 double x,y,z,xt,yt,zt;
537 if (tPower < -998) {
538 calStatus = cal_normal;
539 return;
541 if (tPower > 8) {
542 calStatus = cal_error;
543 return;
545 *ttPower = 0;
546 calStatus = cal_normal;
548 if( func[0] =='s' || func[0] =='S'|| func[0] =='t' || func[0] =='T')
549 sign = SIGN(t);
550 else {
551 /* if( func[0] =='c' || func[0] =='C') */
552 sign = 1;
554 t = ABS(t);
556 while (tPower > 0){
557 t *= 10;
558 tPower--;
560 while (tPower < 0) {
561 t /= 10;
562 tPower++;
564 j = 0;
565 while (t > j*M_TWOPI) {j++;}
566 t -= (j-1)*M_TWOPI;
567 if (M_PI_2 < t && t < 3*M_PI_2){
568 t = M_PI - t;
569 if (func[0] =='c' || func[0] =='C')
570 sign = -1;
571 else if (func[0] =='t' || func[0] =='T')
572 t*=-1;
574 else if ( 3*M_PI_2 <= t && t <= M_TWOPI)
575 t -= M_TWOPI;
577 x = 0.60725293500888; y = 0; z = t;
578 for (j=1;j<n+2;j++){
579 xt = x - SIGN(z) * y*cordicTable[j-1][0];
580 yt = y + SIGN(z) * x*cordicTable[j-1][0];
581 zt = z - SIGN(z) * cordicTable[j-1][1];
582 x = xt;
583 y=yt;
584 z=zt;
586 if( func[0] =='s' || func[0] =='S') {
587 *tt = sign*y;
588 return;
590 else if( func[0] =='c' || func[0] =='C') {
591 *tt = sign*x;
592 return;
594 else /*if( func[0] =='t' || func[0] =='T')*/ {
595 if(t==M_PI_2||t==-M_PI_2){
596 calStatus = cal_error;
597 return;
599 else{
600 *tt = sign*(y/x);
601 return;
606 /* -----------------------------------------------------------------------
607 add in scientific number format
608 ----------------------------------------------------------------------- */
609 void doAdd (double* operandOne, int* powerOne,
610 double operandTwo, int powerTwo)
612 if ( *powerOne >= powerTwo ){
613 if (*powerOne - powerTwo <= DIGITLEN+1){
614 while (powerTwo < *powerOne){
615 operandTwo /=10;
616 powerTwo++;
618 *operandOne += operandTwo;
620 /*do nothing if operandTwo is too small*/
622 else{
623 if (powerTwo - *powerOne <= DIGITLEN+1){
624 while(powerTwo > *powerOne){
625 *operandOne /=10;
626 (*powerOne)++;
628 (*operandOne) += operandTwo;
630 else{/* simply copy operandTwo if operandOne is too small */
631 *operandOne = operandTwo;
632 *powerOne = powerTwo;
636 /* -----------------------------------------------------------------------
637 multiple in scientific number format
638 ----------------------------------------------------------------------- */
639 void doMultiple(double* operandOne, int* powerOne,
640 double operandTwo, int powerTwo)
642 (*operandOne) *= operandTwo;
643 (*powerOne) += powerTwo;
646 /* -----------------------------------------------------------------------
647 Handles all one operand calculations
648 ----------------------------------------------------------------------- */
649 void oneOperand(void)
651 int k = 0;
652 if (buttonGroup == basicButtons){
653 switch(CAL_BUTTON){
654 case btn_sqr:
655 if (result<0)
656 calStatus = cal_error;
657 else{
658 if (power%2 == 1){
659 result = (mySqrt(result*10))/10;
660 power = (power+1) / 2;
662 else{
663 result = mySqrt(result);
664 power = power / 2;
666 calStatus = cal_normal;
668 break;
669 case btn_square:
670 power *= 2;
671 result *= result;
672 calStatus = cal_normal;
673 break;
675 case btn_rec:
676 if (result==0)
677 calStatus = cal_error;
678 else{
679 power = -power;
680 result = 1/result;
681 calStatus = cal_normal;
683 break;
684 default:
685 calStatus = cal_toDo;
686 break; /* just for the safety */
689 else{ /* sciButtons */
690 switch(CAL_BUTTON){
691 case sci_sin:
692 transcendFunc("sin", &result, &power);
693 break;
694 case sci_cos:
695 transcendFunc("cos", &result, &power);
696 break;
697 case sci_tan:
698 transcendFunc("tan", &result, &power);
699 break;
700 case sci_fac:
701 if (power<0 || power>8 || result<0 )
702 calStatus = cal_error;
703 else if(result == 0) {
704 result = 1;
705 power = 0;
707 else{
708 while(power > 0) {
709 result *= 10;
710 power--;
712 if ( ( result - (int)result) > MINIMUM )
713 calStatus = cal_error;
714 else {
715 k = result; result = 1;
716 while (k > 1){
717 doMultiple(&result, &power, k, 0);
718 formatResult();
719 k--;
721 calStatus = cal_normal;
724 break;
725 default:
726 calStatus = cal_toDo;
727 break; /* just for the safety */
733 /* -----------------------------------------------------------------------
734 Handles all two operands calculations
735 ----------------------------------------------------------------------- */
736 void twoOperands(void)
738 switch(oper){
739 case '-':
740 doAdd(&operand, &operandPower, -result, power);
741 break;
742 case '+':
743 doAdd(&operand, &operandPower, result, power);
744 break;
745 case '*':
746 doMultiple(&operand, &operandPower, result, power);
747 break;
748 case '/':
749 if ( ABS(result) > MINIMUM ){
750 doMultiple(&operand, &operandPower, 1/result, -power);
752 else
753 calStatus = cal_error;
754 break;
755 default: /* ' ' */
756 switchOperands(); /* counter switchOperands() below */
757 break;
758 } /* switch(oper) */
759 switchOperands();
760 clearOper();
762 /* -----------------------------------------------------------------------
763 move button index
764 Invert display new button, invert back previous button
765 ----------------------------------------------------------------------- */
766 void moveButton(void){
767 switch(btn){
768 case BUTTON_LEFT:
769 case BUTTON_LEFT | BUTTON_REPEAT:
770 if (n == 0)
771 n = 4;
772 else
773 n--;
774 break;
776 case BUTTON_RIGHT:
777 case BUTTON_RIGHT | BUTTON_REPEAT:
778 if (n == 4)
779 n = 0;
780 else
781 n++;
782 break;
784 case CALCULATOR_UP:
785 case CALCULATOR_UP | BUTTON_REPEAT:
786 if (m == 0)
787 m = 4;
788 else
789 m--;
790 break;
792 case CALCULATOR_DOWN:
793 case CALCULATOR_DOWN | BUTTON_REPEAT:
794 if (m == 4)
795 m = 0;
796 else
797 m++;
798 break;
801 rb->lcd_set_drawmode(DRMODE_COMPLEMENT);
802 rb->lcd_fillrect( X_0_POS + prev_n*REC_WIDTH + 1,
803 Y_1_POS + prev_m*REC_HEIGHT + 1,
804 REC_WIDTH - 1, REC_HEIGHT - 1);
806 rb->lcd_fillrect( X_0_POS + n*REC_WIDTH + 1,
807 Y_1_POS + m*REC_HEIGHT + 1,
808 REC_WIDTH - 1, REC_HEIGHT - 1);
809 rb->lcd_set_drawmode(DRMODE_SOLID);
811 rb->lcd_update_rect( X_0_POS + prev_n*REC_WIDTH + 1,
812 Y_1_POS + prev_m*REC_HEIGHT + 1,
813 REC_WIDTH - 1, REC_HEIGHT - 1);
815 rb->lcd_update_rect( X_0_POS + n*REC_WIDTH + 1,
816 Y_1_POS + m*REC_HEIGHT + 1,
817 REC_WIDTH - 1, REC_HEIGHT - 1);
819 prev_m = m;
820 prev_n = n;
822 /* -----------------------------------------------------------------------
823 Print buttons when switching 1st and 2nd
824 int group = {basicButtons, sciButtons}
825 ----------------------------------------------------------------------- */
826 void printButtonGroups(int group)
828 int i,j,w,h;
829 for (i = 0; i < 5; i++){
830 for (j = 3; j <= 4; j++){
831 rb->lcd_getstringsize( buttonChar[group][i][j],&w,&h);
832 rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
833 rb->lcd_fillrect( X_0_POS + j*REC_WIDTH + 1,
834 Y_1_POS + i*REC_HEIGHT + 1,
835 REC_WIDTH - 1, REC_HEIGHT - 1);
836 rb->lcd_set_drawmode(DRMODE_SOLID);
837 rb->lcd_putsxy( X_0_POS + j*REC_WIDTH + (REC_WIDTH - w)/2,
838 TEXT_2_POS + i*REC_HEIGHT,
839 buttonChar[group][i][j] );
842 for (i = 0; i <= 0; i++){
843 for (j = 0; j <= 2; j++){
844 rb->lcd_getstringsize( buttonChar[group][i][j],&w,&h);
845 rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
846 rb->lcd_fillrect( X_0_POS + j*REC_WIDTH + 1,
847 Y_1_POS + i*REC_HEIGHT + 1,
848 REC_WIDTH - 1, REC_HEIGHT - 1);
849 rb->lcd_set_drawmode(DRMODE_SOLID);
850 rb->lcd_putsxy( X_0_POS + j*REC_WIDTH + (REC_WIDTH - w)/2,
851 TEXT_2_POS + i*REC_HEIGHT,
852 buttonChar[group][i][j] );
855 rb->lcd_set_drawmode(DRMODE_COMPLEMENT);
856 rb->lcd_fillrect( X_0_POS + 2*REC_WIDTH + 1,
857 Y_1_POS + 0*REC_HEIGHT + 1,
858 REC_WIDTH - 1, REC_HEIGHT - 1);
859 rb->lcd_set_drawmode(DRMODE_SOLID);
860 rb->lcd_update_rect( X_0_POS, Y_1_POS,
861 REC_WIDTH*5, REC_HEIGHT*5);
863 /* -----------------------------------------------------------------------
864 flash the button pressed
865 ----------------------------------------------------------------------- */
866 void flashButton(int b)
868 int i = b/5; int j = b - i*5;
869 int k;
870 rb->lcd_set_drawmode(DRMODE_COMPLEMENT);
871 for (k=1*2;k>0;k--){
872 rb->lcd_fillrect( X_0_POS + j*REC_WIDTH + 1,
873 Y_1_POS + i*REC_HEIGHT + 1,
874 REC_WIDTH - 1, REC_HEIGHT - 1);
875 rb->lcd_update_rect( X_0_POS + j*REC_WIDTH + 1,
876 Y_1_POS + i*REC_HEIGHT + 1,
877 REC_WIDTH - 1, REC_HEIGHT - 1);
879 if (k!= 1)
880 rb->sleep(HZ/22);
883 rb->lcd_set_drawmode(DRMODE_SOLID);
886 /* -----------------------------------------------------------------------
887 pos is the position that needs animation. pos = [1~18]
888 ----------------------------------------------------------------------- */
889 void deleteAnimation(int pos)
891 int k;
892 if (pos<1 || pos >18)
893 return;
894 pos--;
895 rb->lcd_fillrect(1+pos*6, TEXT_1_POS, 6, 8);
896 rb->lcd_update_rect(1+pos*6, TEXT_1_POS, 6, 8);
898 for (k=1;k<=4;k++){
899 rb->sleep(HZ/32);
900 rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
901 rb->lcd_fillrect(1+pos*6, TEXT_1_POS, 6, 8);
902 rb->lcd_set_drawmode(DRMODE_SOLID);
903 rb->lcd_fillrect(1+pos*6+1+k, TEXT_1_POS+k,
904 (5-2*k)>0?(5-2*k):1, (7-2*k)>0?(7-2*k):1 );
905 rb->lcd_update_rect(1+pos*6, TEXT_1_POS, 6, 8);
910 /* -----------------------------------------------------------------------
911 result may be one of these formats:
913 xxxx.xxxx
914 0.xxxx
915 0.0000xxxx
917 formatResult() change result to standard format: 0.xxxx
918 if result is close to 0, let it be 0;
919 if result is close to 1, let it be 0.1 and power++;
920 ----------------------------------------------------------------------- */
921 void formatResult(void)
923 int resultsign = SIGN(result);
924 result = ABS(result);
925 if(result > MINIMUM ){ /* doesn't check power, might have problem
926 input wouldn't,
927 + - * / of two formatted number wouldn't.
928 only a calculation that makes a formatted
929 number (0.xxxx) less than MINIMUM in only
930 one operation */
932 if (result<1){
933 while( (int)(result*10) == 0 ){
934 result *= 10;
935 power--;
936 modifier *= 10;
939 else{ /* result >= 1 */
940 while( (int)result != 0 ){
941 result /= 10;
942 power++;
943 modifier /= 10;
945 } /* if result<1 */
947 if (result > (1-MINIMUM)){
948 result = 0.1;
949 power++;
950 modifier /= 10;
952 result *= resultsign;
954 else {
955 result = 0;
956 power = 0;
957 modifier = 0.1;
961 /* -----------------------------------------------------------------------
962 result2typingbuf() outputs standard format result to typingbuf.
963 case SCIENTIFIC_FORMAT, let temppower = 1;
964 case temppower > 0: print '.' in the middle
965 case temppower <= 0: print '.' in the begining
966 ----------------------------------------------------------------------- */
967 void result2typingbuf(void)
969 bool haveDot = false;
970 char tempchar = 0;
971 int k;
972 double tempresult = ABS(result); /* positive num makes things simple */
974 int temppower;
975 double tempmodifier = 1;
976 int count;
978 if(SCIENTIFIC_FORMAT)
979 temppower = 1; /* output x.xxxx format */
980 else
981 temppower = power;
983 cleartypingbuf();
985 if(tempresult < MINIMUM){ /* if 0,faster display and avoid complication*/
986 typingbuf[0] = ' ';
987 typingbuf[1] = '0';
989 else{ /* tempresult > 0 */
990 typingbuf[0] = (SIGN(result)<0)?'-':' ';
992 typingbufPointer = typingbuf;
993 if(temppower > 0){
994 for (k = 0; k<DIGITLEN+1 ; k++){
995 typingbufPointer++;
996 if(temppower || *(typingbufPointer-1) == '.'){
997 count = 0;
998 tempmodifier = tempmodifier/10;
999 while( (tempresult-tempmodifier*count) >
1000 (tempmodifier-MINIMUM)){
1001 count++;
1003 tempresult -= tempmodifier*count;
1004 tempresult = ABS(tempresult);
1005 temppower-- ;
1006 *typingbufPointer = count + '0';
1008 else{ /* temppower == 0 */
1009 *typingbufPointer = '.';
1010 haveDot = true;
1012 } /* for */
1014 else{
1015 haveDot = true;
1016 typingbufPointer++; *typingbufPointer = '0';
1017 typingbufPointer++; *typingbufPointer = '.';
1018 for (k = 2; k<DIGITLEN+1 ; k++){
1019 typingbufPointer++;
1020 count = 0;
1021 if ( (-temppower) < (k-1)){
1022 tempmodifier = tempmodifier/10;
1023 while((tempresult-tempmodifier*count)>(tempmodifier-MINIMUM)){
1024 count++;
1027 tempresult -= tempmodifier*count;
1028 tempresult = ABS(tempresult);
1029 temppower-- ;
1031 *typingbufPointer = count + '0';
1034 /* now, typingbufPointer = typingbuf + 16 */
1035 /* backward strip off 0 and '.' */
1036 if (haveDot){
1037 while( (*typingbufPointer == '0') || (*typingbufPointer == '.')){
1038 tempchar = *typingbufPointer;
1039 *typingbufPointer = 0;
1040 typingbufPointer--;
1041 if (tempchar == '.') break;
1044 typingbuf[DIGITLEN+1] = 0;
1045 } /* else tempresult > 0 */
1048 /* -----------------------------------------------------------------------
1049 printResult() generates LCD display.
1050 ----------------------------------------------------------------------- */
1051 void printResult(void)
1053 int k;
1055 switch_Status:
1056 switch(calStatus){
1057 case cal_exit:
1058 rb->lcd_clear_display();
1059 rb->splash(HZ/3, "Bye now!");
1060 break;
1061 case cal_error:
1062 clearbuf();
1063 rb->snprintf(buf, 19, "%18s","Error");
1064 break;
1065 case cal_toDo:
1066 clearbuf();
1067 rb->snprintf(buf, 19, "%18s","Coming soon ^_* ");
1068 break;
1070 case cal_normal:
1071 formatResult();
1073 if( power > 1000 ){ /* power -1 > 999 */
1074 calStatus = cal_error;
1075 goto switch_Status;
1077 if (power < -998 ) /* power -1 < -999 */
1078 clearResult(); /* too small, let it be 0 */
1080 result2typingbuf();
1081 clearbuf();
1083 buf[0] = oper;
1084 buf[1] = ( ABS(memTemp) > MINIMUM )?'M':' ';
1085 buf[2] = ' ';
1087 if(SCIENTIFIC_FORMAT){
1088 /* output format: X.XXXX eXXX */
1089 if(power > -98){ /* power-1 >= -99, eXXX or e-XX */
1090 rb->snprintf(buf+3, 12, "%11s",typingbuf);
1091 for(k=14;k<=17;k++) buf[k] = ' ';
1092 cleartypingbuf();
1093 rb->snprintf(typingbuf, 5, "e%d",power-1);
1094 rb->snprintf(buf+14, 5, "%4s",typingbuf);
1096 else{ /* power-1 <= -100, e-XXX */
1097 rb->snprintf(buf+2, 12, "%11s",typingbuf);
1098 rb->snprintf(buf+13, 6, "e%d",power-1);
1101 else{
1102 rb->snprintf(buf+7, 12, "%11s",typingbuf);
1103 } /* if SCIENTIFIC_FORMAT */
1104 break;
1105 case cal_typing:
1106 case cal_dotted:
1107 clearbuf();
1108 buf[0] = oper;
1109 buf[1] = ( ABS(memTemp) > MINIMUM )?'M':' ';
1110 for(k=2;k<=6;k++)
1111 buf[k] = ' ';
1112 rb->snprintf(buf+7, 12, "%11s",typingbuf);
1113 break;
1117 rb->lcd_putsxy(1, TEXT_1_POS,buf);
1118 rb->lcd_update_rect(1, TEXT_1_POS, 6*18, 8);
1121 /* -----------------------------------------------------------------------
1122 Process typing buttons: 1-9, '.', sign
1123 main operand "result" and typingbuf are processed seperately here.
1124 ----------------------------------------------------------------------- */
1125 void typingProcess(void){
1126 switch( CAL_BUTTON ){
1127 case btn_sign:
1128 if (calStatus == cal_typing ||
1129 calStatus == cal_dotted)
1130 typingbuf[0] = (typingbuf[0]=='-')?' ':'-';
1131 result = -result;
1132 break;
1133 case btn_dot:
1134 operInputted = false;
1135 switch(calStatus){
1136 case cal_normal:
1137 clearInput();
1138 *typingbufPointer = '0';
1139 typingbufPointer++;
1140 case cal_typing:
1141 calStatus = cal_dotted;
1142 *typingbufPointer = '.';
1143 if (typingbufPointer != typingbuf+DIGITLEN+1)
1144 typingbufPointer++;
1145 break;
1146 default: /* cal_dotted */
1147 break;
1149 break;
1150 default: /* 0-9 */
1151 operInputted = false;
1152 /* normal,0; normal,1-9; typing,0; typing,1-9 */
1153 switch(calStatus){
1154 case cal_normal:
1155 if(CAL_BUTTON == btn_0 )
1156 break; /* first input is 0, ignore */
1157 clearInput();
1158 /*no operator means start a new calculation*/
1159 if (oper ==' ')
1160 clearOperand();
1161 calStatus = cal_typing;
1162 /* go on typing, no break */
1163 case cal_typing:
1164 case cal_dotted:
1165 switch(CAL_BUTTON){
1166 case btn_0:
1167 *typingbufPointer = '0';
1168 break;
1169 default:
1170 *typingbufPointer=(7+n-3*(m-1))+ '0';
1171 break;
1173 if (typingbufPointer!=typingbuf+DIGITLEN+1){
1174 typingbufPointer++;
1176 {/* result processing */
1177 if (calStatus == cal_typing) power++;
1178 if (CAL_BUTTON != btn_0)
1179 result= result +
1180 SIGN(result)*
1181 (7+n-3*(m-1))*modifier;
1182 modifier /= 10;
1185 else /* last byte always '\0' */
1186 *typingbufPointer = 0;
1187 break;
1188 default: /* cal_error, cal_exit */
1189 break;
1191 break; /* default, 0-9 */
1192 } /* switch( CAL_BUTTON ) */
1195 /* -----------------------------------------------------------------------
1196 Handle delete operation
1197 main operand "result" and typingbuf are processed seperately here.
1198 ----------------------------------------------------------------------- */
1199 void doDelete(void){
1200 deleteAnimation(18);
1201 switch(calStatus){
1202 case cal_dotted:
1203 if (*(typingbufPointer-1) == '.'){
1204 /* if dotted and deleting '.',
1205 change status and delete '.' below */
1206 calStatus = cal_typing;
1208 else{ /* if dotted and not deleting '.',
1209 power stays */
1210 power++; /* counter "power--;" below */
1212 case cal_typing:
1213 typingbufPointer--;
1215 {/* result processing */ /* 0-9, '.' */
1216 /* if deleting '.', do nothing */
1217 if ( *typingbufPointer != '.'){
1218 power--;
1219 modifier *= 10;
1220 result = result - SIGN(result)*
1221 ((*typingbufPointer)- '0')*modifier;
1225 *typingbufPointer = 0;
1227 /* if (only one digit left and it's 0)
1228 or no digit left, change status*/
1229 if ( typingbufPointer == typingbuf+1 ||
1230 ( typingbufPointer == typingbuf+2 &&
1231 *(typingbufPointer-1) == '0' ))
1232 calStatus = cal_normal;
1233 break;
1234 default: /* normal, error, exit */
1235 break;
1238 /* -----------------------------------------------------------------------
1239 Handle buttons on basic screen
1240 ----------------------------------------------------------------------- */
1241 void basicButtonsProcess(void){
1242 switch (btn) {
1243 case CALCULATOR_INPUT:
1244 if (calStatus == cal_error && (CAL_BUTTON != btn_C) ) break;
1245 flashButton(CAL_BUTTON);
1246 switch( CAL_BUTTON ){
1247 case btn_MR:
1248 operInputted = false;
1249 result = memTemp; power = memTempPower;
1250 calStatus = cal_normal;
1251 break;
1252 case btn_M:
1253 formatResult();
1254 if (memTemp > MINIMUM)
1255 doAdd(&memTemp, &memTempPower, result, power);
1256 else {
1257 /* if result is too small and memTemp = 0,
1258 doAdd will not add */
1259 memTemp = result;
1260 memTempPower = power;
1262 calStatus = cal_normal;
1263 break;
1265 case btn_C: clearMem(); break;
1266 case btn_CE: clearInput(); break;
1268 case btn_bas:
1269 buttonGroup = sciButtons;
1270 printButtonGroups(buttonGroup);
1271 break;
1273 /* one operand calculation, may be changed to
1274 like sin, cos, log, etc */
1275 case btn_sqr:
1276 case btn_square:
1277 case btn_rec:
1278 formatResult(); /* not necessary, just for safty */
1279 oneOperand();
1280 break;
1282 case_btn_equal: /* F3 shortkey entrance */
1283 case btn_equal:
1284 formatResult();
1285 calStatus = cal_normal;
1286 operInputted = false;
1287 if (oper != ' ') twoOperands();
1288 break;
1290 case btn_div:
1291 case btn_time:
1292 case btn_minus:
1293 case btn_add:
1294 if(!operInputted) {twoOperands(); operInputted = true;}
1295 oper = buttonChar[basicButtons][m][n][0];
1296 #ifdef CALCULATOR_OPERATORS
1297 case_cycle_operators: /* F2 shortkey entrance */
1298 #endif
1299 calStatus = cal_normal;
1300 formatResult();
1301 operand = result;
1302 operandPower = power;
1304 break;
1306 case btn_sign:
1307 case btn_dot:
1308 default: /* 0-9 */
1309 typingProcess();
1310 break;
1311 } /* switch (CAL_BUTTON) */
1312 break;
1314 #ifdef CALCULATOR_OPERATORS
1315 case CALCULATOR_OPERATORS:
1316 if (calStatus == cal_error) break;
1317 if (!operInputted) {twoOperands(); operInputted = true;}
1318 switch (oper){
1319 case ' ':
1320 case '/': oper = '+'; flashButton(btn_add); break;
1321 case '+': oper = '-'; flashButton(btn_minus); break;
1322 case '-': oper = '*'; flashButton(btn_time); break;
1323 case '*': oper = '/'; flashButton(btn_div); break;
1325 goto case_cycle_operators;
1326 break;
1327 #endif
1329 case CALCULATOR_CALC:
1330 if (calStatus == cal_error) break;
1331 flashButton(btn_equal);
1332 goto case_btn_equal;
1333 break;
1334 default: break;
1336 printResult();
1339 /* -----------------------------------------------------------------------
1340 Handle buttons on scientific screen
1341 ----------------------------------------------------------------------- */
1342 void sciButtonsProcess(void){
1343 switch (btn) {
1344 case CALCULATOR_INPUT:
1345 if (calStatus == cal_error && (CAL_BUTTON != sci_sci) ) break;
1346 flashButton(CAL_BUTTON);
1347 switch( CAL_BUTTON ){
1349 case sci_pi:
1350 result = M_PI; power = 0;
1351 calStatus = cal_normal;
1352 break;
1354 case sci_xy: break;
1356 case sci_sci:
1357 buttonGroup = basicButtons;
1358 printButtonGroups(basicButtons);
1359 break;
1361 case sci_fac:
1362 case sci_sin:
1363 case sci_asin:
1364 case sci_cos:
1365 case sci_acos:
1366 case sci_tan:
1367 case sci_atan:
1368 case sci_ln:
1369 case sci_exp:
1370 case sci_log:
1371 formatResult(); /* not necessary, just for safty */
1372 oneOperand();
1373 break;
1375 case btn_sign:
1376 case btn_dot:
1377 default: /* 0-9 */
1378 typingProcess();
1379 break;
1380 } /* switch (CAL_BUTTON) */
1381 break;
1383 #ifdef CALCULATOR_OPERATORS
1384 case CALCULATOR_OPERATORS:
1385 if (calStatus == cal_error) break;
1386 if (!operInputted) {twoOperands(); operInputted = true;}
1387 switch (oper){
1388 case ' ': oper = '+'; break;
1389 case '/': oper = '+'; deleteAnimation(1); break;
1390 case '+': oper = '-'; deleteAnimation(1); break;
1391 case '-': oper = '*'; deleteAnimation(1); break;
1392 case '*': oper = '/'; deleteAnimation(1); break;
1394 calStatus = cal_normal;
1395 formatResult();
1396 operand = result;
1397 operandPower = power;
1398 break;
1399 #endif
1401 case CALCULATOR_CALC:
1402 if (calStatus == cal_error) break;
1403 formatResult();
1404 calStatus = cal_normal;
1405 operInputted = false;
1406 if (oper != ' ') twoOperands();
1407 break;
1408 default: break;
1410 printResult();
1413 /* -----------------------------------------------------------------------
1414 Main();
1415 ----------------------------------------------------------------------- */
1416 enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
1418 (void)parameter;
1419 rb = api;
1421 /* now go ahead and have fun! */
1423 cal_initial();
1425 while (calStatus != cal_exit ) {
1426 btn = rb->button_get_w_tmo(HZ/2);
1427 switch (btn) {
1428 case CALCULATOR_INPUT:
1429 case CALCULATOR_CALC:
1430 #ifdef CALCULATOR_INPUT_CALC_PRE
1431 if (lastbtn != CALCULATOR_INPUT_CALC_PRE)
1432 break;
1433 /* no unconditional break; here! */
1434 #endif
1435 #ifdef CALCULATOR_OPERATORS
1436 case CALCULATOR_OPERATORS:
1437 #endif
1438 switch(buttonGroup){
1439 case basicButtons:
1440 basicButtonsProcess();
1441 break;
1442 case sciButtons:
1443 sciButtonsProcess();
1444 break;
1446 break;
1448 #ifdef CALCULATOR_CLEAR
1449 case CALCULATOR_CLEAR:
1450 switch(calStatus){
1451 case cal_typing:
1452 case cal_dotted:
1453 doDelete();
1454 break;
1455 default: /* cal_normal, cal_error, cal_exit */
1456 clearMem();
1457 break;
1459 printResult();
1460 break;
1461 #endif
1463 case BUTTON_LEFT:
1464 case BUTTON_LEFT | BUTTON_REPEAT:
1465 case BUTTON_RIGHT:
1466 case BUTTON_RIGHT | BUTTON_REPEAT:
1467 case CALCULATOR_UP:
1468 case CALCULATOR_UP | BUTTON_REPEAT:
1469 case CALCULATOR_DOWN:
1470 case CALCULATOR_DOWN | BUTTON_REPEAT:
1471 moveButton();
1472 break;
1473 #ifdef CALCULATOR_RC_QUIT
1474 case CALCULATOR_RC_QUIT:
1475 #endif
1476 case CALCULATOR_QUIT:
1477 calStatus = cal_exit;
1478 printResult();
1479 break;
1480 default:
1481 if(rb->default_event_handler(btn) == SYS_USB_CONNECTED)
1482 return PLUGIN_USB_CONNECTED;
1483 break;
1484 } /* switch (btn) */
1485 if (btn != BUTTON_NONE)
1486 lastbtn = btn;
1487 } /* while (calStatus != cal_exit ) */
1489 /* rb->splash(HZ*2, "Hello world!"); */
1490 rb->button_clear_queue();
1491 return PLUGIN_OK;
1494 #endif /* #ifdef HAVE_LCD_BITMAP */