fix red and remove tabs
[kugel-rb.git] / apps / plugins / calculator.c
blob979705fbe142d07d8b73392c5c46709a74980cb5
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_LEFT BUTTON_LEFT
112 #define CALCULATOR_RIGHT BUTTON_RIGHT
113 #define CALCULATOR_UP BUTTON_UP
114 #define CALCULATOR_DOWN BUTTON_DOWN
115 #define CALCULATOR_QUIT BUTTON_OFF
116 #define CALCULATOR_INPUT BUTTON_PLAY
117 #define CALCULATOR_CALC BUTTON_F3
118 #define CALCULATOR_OPERATORS BUTTON_F2
119 #define CALCULATOR_CLEAR BUTTON_F1
121 #elif CONFIG_KEYPAD == ARCHOS_AV300_PAD
122 #define CALCULATOR_LEFT BUTTON_LEFT
123 #define CALCULATOR_RIGHT BUTTON_RIGHT
124 #define CALCULATOR_UP BUTTON_UP
125 #define CALCULATOR_DOWN BUTTON_DOWN
126 #define CALCULATOR_QUIT BUTTON_OFF
127 #define CALCULATOR_INPUT BUTTON_SELECT
128 #define CALCULATOR_CALC BUTTON_F3
129 #define CALCULATOR_OPERATORS BUTTON_F2
130 #define CALCULATOR_CLEAR BUTTON_F1
132 #elif CONFIG_KEYPAD == ONDIO_PAD
133 #define CALCULATOR_LEFT BUTTON_LEFT
134 #define CALCULATOR_RIGHT BUTTON_RIGHT
135 #define CALCULATOR_UP BUTTON_UP
136 #define CALCULATOR_DOWN BUTTON_DOWN
137 #define CALCULATOR_QUIT BUTTON_OFF
138 #define CALCULATOR_INPUT_CALC_PRE BUTTON_MENU
139 #define CALCULATOR_INPUT (BUTTON_MENU | BUTTON_REL)
140 #define CALCULATOR_CALC (BUTTON_MENU | BUTTON_REPEAT)
142 #elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || \
143 (CONFIG_KEYPAD == IRIVER_H300_PAD)
144 #define CALCULATOR_LEFT BUTTON_LEFT
145 #define CALCULATOR_RIGHT BUTTON_RIGHT
146 #define CALCULATOR_UP BUTTON_UP
147 #define CALCULATOR_DOWN BUTTON_DOWN
148 #define CALCULATOR_QUIT BUTTON_OFF
149 #define CALCULATOR_INPUT BUTTON_SELECT
150 #define CALCULATOR_CALC BUTTON_ON
151 #define CALCULATOR_OPERATORS BUTTON_MODE
152 #define CALCULATOR_CLEAR BUTTON_REC
154 #define CALCULATOR_RC_QUIT BUTTON_RC_STOP
156 #elif (CONFIG_KEYPAD == IPOD_4G_PAD) || \
157 (CONFIG_KEYPAD == IPOD_3G_PAD) || \
158 (CONFIG_KEYPAD == IPOD_1G2G_PAD)
160 #define CALCULATOR_LEFT BUTTON_LEFT
161 #define CALCULATOR_RIGHT BUTTON_RIGHT
162 #define CALCULATOR_UP BUTTON_SCROLL_BACK
163 #define CALCULATOR_DOWN BUTTON_SCROLL_FWD
164 #define CALCULATOR_QUIT BUTTON_MENU
165 #define CALCULATOR_INPUT_CALC_PRE BUTTON_SELECT
166 #define CALCULATOR_INPUT (BUTTON_SELECT | BUTTON_REL)
167 #define CALCULATOR_CALC (BUTTON_PLAY | BUTTON_REPEAT)
169 #elif (CONFIG_KEYPAD == IAUDIO_X5M5_PAD)
171 #define CALCULATOR_LEFT BUTTON_LEFT
172 #define CALCULATOR_RIGHT BUTTON_RIGHT
173 #define CALCULATOR_UP BUTTON_UP
174 #define CALCULATOR_DOWN BUTTON_DOWN
175 #define CALCULATOR_QUIT BUTTON_POWER
176 #define CALCULATOR_INPUT_CALC_PRE BUTTON_SELECT
177 #define CALCULATOR_INPUT (BUTTON_SELECT | BUTTON_REL)
178 #define CALCULATOR_CALC BUTTON_PLAY
179 #define CALCULATOR_CLEAR BUTTON_REC
181 #elif (CONFIG_KEYPAD == GIGABEAT_PAD)
183 #define CALCULATOR_LEFT BUTTON_LEFT
184 #define CALCULATOR_RIGHT BUTTON_RIGHT
185 #define CALCULATOR_UP BUTTON_UP
186 #define CALCULATOR_DOWN BUTTON_DOWN
187 #define CALCULATOR_QUIT BUTTON_POWER
188 #define CALCULATOR_INPUT BUTTON_SELECT
189 #define CALCULATOR_CALC BUTTON_MENU
190 #define CALCULATOR_CLEAR BUTTON_A
192 #elif (CONFIG_KEYPAD == SANSA_E200_PAD) || \
193 (CONFIG_KEYPAD == SANSA_C200_PAD)
194 #define CALCULATOR_LEFT BUTTON_LEFT
195 #define CALCULATOR_RIGHT BUTTON_RIGHT
196 #define CALCULATOR_UP BUTTON_UP
197 #define CALCULATOR_DOWN BUTTON_DOWN
198 #define CALCULATOR_QUIT BUTTON_POWER
199 #define CALCULATOR_INPUT_CALC_PRE BUTTON_SELECT
200 #define CALCULATOR_INPUT (BUTTON_SELECT|BUTTON_REL)
201 #define CALCULATOR_CALC (BUTTON_SELECT|BUTTON_REPEAT)
202 #define CALCULATOR_CLEAR BUTTON_REC
204 #elif (CONFIG_KEYPAD == IRIVER_H10_PAD)
206 #define CALCULATOR_LEFT BUTTON_LEFT
207 #define CALCULATOR_RIGHT BUTTON_RIGHT
208 #define CALCULATOR_UP BUTTON_SCROLL_UP
209 #define CALCULATOR_DOWN BUTTON_SCROLL_DOWN
210 #define CALCULATOR_QUIT BUTTON_POWER
211 #define CALCULATOR_INPUT_CALC_PRE BUTTON_PLAY
212 #define CALCULATOR_INPUT (BUTTON_PLAY | BUTTON_REL)
213 #define CALCULATOR_CALC BUTTON_PLAY
214 #define CALCULATOR_CLEAR BUTTON_REW
216 #elif (CONFIG_KEYPAD == GIGABEAT_S_PAD)
218 #define CALCULATOR_LEFT BUTTON_LEFT
219 #define CALCULATOR_RIGHT BUTTON_RIGHT
220 #define CALCULATOR_UP BUTTON_UP
221 #define CALCULATOR_DOWN BUTTON_DOWN
222 #define CALCULATOR_QUIT BUTTON_BACK
223 #define CALCULATOR_INPUT_CALC_PRE BUTTON_MENU
224 #define CALCULATOR_INPUT (BUTTON_MENU | BUTTON_REL)
225 #define CALCULATOR_CALC BUTTON_SELECT
226 #define CALCULATOR_CLEAR BUTTON_PLAY
228 #elif (CONFIG_KEYPAD == MROBE100_PAD)
230 #define CALCULATOR_LEFT BUTTON_LEFT
231 #define CALCULATOR_RIGHT BUTTON_RIGHT
232 #define CALCULATOR_UP BUTTON_UP
233 #define CALCULATOR_DOWN BUTTON_DOWN
234 #define CALCULATOR_QUIT BUTTON_POWER
235 #define CALCULATOR_INPUT BUTTON_SELECT
236 #define CALCULATOR_CALC BUTTON_MENU
237 #define CALCULATOR_CLEAR BUTTON_DISPLAY
239 #elif CONFIG_KEYPAD == IAUDIO_M3_PAD
241 #define CALCULATOR_LEFT BUTTON_RC_REW
242 #define CALCULATOR_RIGHT BUTTON_RC_FF
243 #define CALCULATOR_UP BUTTON_RC_VOL_UP
244 #define CALCULATOR_DOWN BUTTON_RC_VOL_DOWN
245 #define CALCULATOR_QUIT BUTTON_RC_REC
246 #define CALCULATOR_INPUT BUTTON_RC_PLAY
247 #define CALCULATOR_CALC BUTTON_RC_MODE
248 #define CALCULATOR_CLEAR BUTTON_RC_MENU
250 #define CALCULATOR_RC_QUIT BUTTON_REC
252 #elif (CONFIG_KEYPAD == COWOND2_PAD)
254 #define CALCULATOR_LEFT BUTTON_LEFT
255 #define CALCULATOR_RIGHT BUTTON_RIGHT
256 #define CALCULATOR_UP BUTTON_UP
257 #define CALCULATOR_DOWN BUTTON_DOWN
258 #define CALCULATOR_QUIT BUTTON_POWER
259 #define CALCULATOR_INPUT_CALC_PRE BUTTON_MINUS
260 #define CALCULATOR_INPUT BUTTON_PLUS
261 #define CALCULATOR_CALC BUTTON_SELECT
262 #define CALCULATOR_CLEAR BUTTON_MENU
264 #else
265 #error No keymap defined!
266 #endif
268 static struct plugin_api* rb;
270 enum {
271 basicButtons,
272 sciButtons
273 } buttonGroup;
274 unsigned char* buttonChar[2][5][5] = {
275 { { "MR" , "M+" , "2nd" , "CE" , "C" },
276 { "7" , "8" , "9" , "/" , "sqr" },
277 { "4" , "5" , "6" , "*" , "x^2" },
278 { "1" , "2" , "3" , "-" , "1/x" },
279 { "0" , "+/-", "." , "+" , "=" } },
281 { { "n!" , "PI" , "1st" , "sin" , "asi" },
282 { "7" , "8" , "9" , "cos" , "aco" },
283 { "4" , "5" , "6" , "tan" , "ata" },
284 { "1" , "2" , "3" , "ln" , "e^x" },
285 { "0" , "+/-", "." , "log" , "x^y" } }
287 enum { btn_MR , btn_M , btn_bas , btn_CE , btn_C ,
288 btn_7 , btn_8 , btn_9 , btn_div , btn_sqr ,
289 btn_4 , btn_5 , btn_6 , btn_time , btn_square ,
290 btn_1 , btn_2 , btn_3 , btn_minus , btn_rec ,
291 btn_0 , btn_sign , btn_dot , btn_add , btn_equal
293 enum { sci_fac, sci_pi , sci_sci , sci_sin , sci_asin ,
294 sci_7 , sci_8 , sci_9 , sci_cos , sci_acos ,
295 sci_4 , sci_5 , sci_6 , sci_tan , sci_atan ,
296 sci_1 , sci_2 , sci_3 , sci_ln , sci_exp ,
297 sci_0 , sci_sign , sci_dot , sci_log , sci_xy
300 #define MINIMUM 0.000000000001 /* e-12 */
301 /* ^ ^ ^ ^ */
302 /* 123456789abcdef */
304 #define DIGITLEN 10 /* must <= 10 */
305 #define SCIENTIFIC_FORMAT ( power < -(DIGITLEN-3) || power > (DIGITLEN))
306 /* 0.000 00000 0001 */
307 /* ^ ^ ^ ^ ^ ^ */
308 /* DIGITLEN 12345 6789a bcdef */
309 /* power 12 34567 89abc def */
310 /* 10^- 123 45678 9abcd ef */
312 unsigned char buf[19];/* 18 bytes of output line,
313 buf[0] is operator
314 buf[1] = 'M' if memTemp is not 0
315 buf[2] = ' '
317 if SCIENTIFIC_FORMAT
318 buf[2]-buf[12] or buf[3]-buf[13] = result;
319 format X.XXXXXXXX
320 buf[13] or buf[14] -buf[17] = power;
321 format eXXX or e-XXX
322 else
323 buf[3]-buf[6] = ' ';
324 buf[7]-buf[17] = result;
326 buf[18] = '\0' */
328 unsigned char typingbuf[DIGITLEN+2];/* byte 0 is sign or ' ',
329 byte 1~DIGITLEN are num and '.'
330 byte (DIGITLEN+1) is '\0' */
331 unsigned char* typingbufPointer = typingbuf;
333 double result = 0; /* main operand, format 0.xxxxx */
334 int power = 0; /* 10^power */
335 double modifier = 0.1; /* position of next input */
336 double operand = 0; /* second operand, format 0.xxxxx */
337 int operandPower = 0; /* 10^power of second operand */
338 char oper = ' '; /* operators: + - * / */
339 bool operInputted = false; /* false: do calculation first and
340 replace current oper
341 true: just replace current oper */
343 double memTemp = 0; /* temp memory */
344 int memTempPower = 0; /* 10^^power of memTemp */
346 int m, n, prev_m, prev_n; /* position index for button */
347 #define CAL_BUTTON (m*5+n)
349 int btn = BUTTON_NONE;
350 int lastbtn = BUTTON_NONE;
352 /* Status of calculator */
353 enum {cal_normal, /* 0, normal status, display result */
354 cal_typing, /* 1, currently typing, dot hasn't been typed */
355 cal_dotted, /* 2, currently typing, dot already has been typed. */
356 cal_error,
357 cal_exit,
358 cal_toDo
359 } calStatus;
361 /* constant table for CORDIC algorithm */
362 double cordicTable[51][2]= {
363 /* pow(2,0) - pow(2,-50) atan(pow(2,0) - atan(pow(2,-50) */
364 {1e+00, 7.853981633974483e-01},
365 {5e-01, 4.636476090008061e-01},
366 {2.5e-01, 2.449786631268641e-01},
367 {1.25e-01, 1.243549945467614e-01},
368 {6.25e-02, 6.241880999595735e-02},
369 {3.125e-02, 3.123983343026828e-02},
370 {1.5625e-02, 1.562372862047683e-02},
371 {7.8125e-03, 7.812341060101111e-03},
372 {3.90625e-03, 3.906230131966972e-03},
373 {1.953125e-03, 1.953122516478819e-03},
374 {9.765625e-04, 9.765621895593195e-04},
375 {4.8828125e-04, 4.882812111948983e-04},
376 {2.44140625e-04, 2.441406201493618e-04},
377 {1.220703125e-04, 1.220703118936702e-04},
378 {6.103515625e-05, 6.103515617420877e-05},
379 {3.0517578125e-05, 3.051757811552610e-05},
380 {1.52587890625e-05, 1.525878906131576e-05},
381 {7.62939453125e-06, 7.629394531101970e-06},
382 {3.814697265625e-06, 3.814697265606496e-06},
383 {1.9073486328125e-06, 1.907348632810187e-06},
384 {9.5367431640625e-07, 9.536743164059608e-07},
385 {4.76837158203125e-07, 4.768371582030888e-07},
386 {2.384185791015625e-07, 2.384185791015580e-07},
387 {1.1920928955078125e-07, 1.192092895507807e-07},
388 {5.9604644775390625e-08, 5.960464477539055e-08},
389 {2.98023223876953125e-08, 2.980232238769530e-08},
390 {1.490116119384765625e-08, 1.490116119384765e-08},
391 {7.450580596923828125e-09, 7.450580596923828e-09},
392 {3.7252902984619140625e-09, 3.725290298461914e-09},
393 {1.86264514923095703125e-09, 1.862645149230957e-09},
394 {9.31322574615478515625e-10, 9.313225746154785e-10},
395 {4.656612873077392578125e-10, 4.656612873077393e-10},
396 {2.3283064365386962890625e-10, 2.328306436538696e-10},
397 {1.16415321826934814453125e-10, 1.164153218269348e-10},
398 {5.82076609134674072265625e-11, 5.820766091346741e-11},
399 {2.910383045673370361328125e-11, 2.910383045673370e-11},
400 {1.4551915228366851806640625e-11, 1.455191522836685e-11},
401 {7.2759576141834259033203125e-12, 7.275957614183426e-12},
402 {3.63797880709171295166015625e-12, 3.637978807091713e-12},
403 {1.818989403545856475830078125e-12, 1.818989403545856e-12},
404 {9.094947017729282379150390625e-13, 9.094947017729282e-13},
405 {4.5474735088646411895751953125e-13, 4.547473508864641e-13},
406 {2.27373675443232059478759765625e-13, 2.273736754432321e-13},
407 {1.136868377216160297393798828125e-13, 1.136868377216160e-13},
408 {5.684341886080801486968994140625e-14, 5.684341886080801e-14},
409 {2.8421709430404007434844970703125e-14, 2.842170943040401e-14},
410 {1.42108547152020037174224853515625e-14, 1.421085471520200e-14},
411 {7.10542735760100185871124267578125e-15, 7.105427357601002e-15},
412 {3.552713678800500929355621337890625e-15, 3.552713678800501e-15},
413 {1.7763568394002504646778106689453125e-15, 1.776356839400250e-15},
414 {8.8817841970012523233890533447265625e-16, 8.881784197001252e-16}
417 void doMultiple(double* operandOne, int* powerOne,
418 double operandTwo, int powerTwo);
419 void doAdd (double* operandOne, int* powerOne,
420 double operandTwo, int powerTwo);
421 void printResult(void);
422 void formatResult(void);
423 void oneOperand(void);
425 /* -----------------------------------------------------------------------
426 Handy funtions
427 ----------------------------------------------------------------------- */
428 void cleartypingbuf(void)
430 int k;
431 for( k=1; k<=(DIGITLEN+1); k++)
432 typingbuf[k] = 0;
433 typingbuf[0] = ' ';
434 typingbufPointer = typingbuf+1;
436 void clearbuf(void)
438 int k;
439 for(k=0;k<18;k++)
440 buf[k]=' ';
441 buf[18] = 0;
443 void clearResult(void)
445 result = 0;
446 power = 0;
447 modifier = 0.1;
450 void clearInput(void)
452 calStatus = cal_normal;
453 clearResult();
454 cleartypingbuf();
457 void clearOperand(void)
459 operand = 0;
460 operandPower = 0;
463 void clearMemTemp(void)
465 memTemp = 0;
466 memTempPower = 0;
469 void clearOper(void)
471 oper = ' ';
472 operInputted = false;
475 void clearMem(void)
477 clearInput();
478 clearMemTemp();
479 clearOperand();
480 clearOper();
481 btn = BUTTON_NONE;
484 void switchOperands(void)
486 double tempr = operand;
487 int tempp = operandPower;
488 operand = result;
489 operandPower = power;
490 result = tempr;
491 power = tempp;
494 /* -----------------------------------------------------------------------
495 Initiate calculator
496 ----------------------------------------------------------------------- */
497 void cal_initial (void)
499 int i,j,w,h;
500 rb->lcd_setfont(FONT_SYSFIXED);
501 rb->lcd_clear_display();
503 /* draw lines */
504 rb->lcd_drawrect(X_0_POS, Y_0_POS, LCD_WIDTH-1, LCD_HEIGHT);
505 rb->lcd_hline(X_0_POS, X_5_POS, Y_1_POS-1);
506 for (i = 0; i < 5 ; i++)
507 rb->lcd_hline(X_0_POS, X_5_POS, Y_1_POS+i*REC_HEIGHT);
508 for (i = 0; i < 4 ; i++)
509 rb->lcd_vline(X_1_POS+i*REC_WIDTH, Y_1_POS, Y_6_POS);
511 #ifdef CALCULATOR_OPERATORS
512 /* basic operators are available through separate button */
513 buttonGroup = sciButtons;
514 #else
515 buttonGroup = basicButtons;
516 #endif
517 /* draw buttons */
518 for (i = 0; i < 5; i++){
519 for (j = 0; j < 5; j++){
520 rb->lcd_getstringsize( buttonChar[buttonGroup][i][j],&w,&h);
521 rb->lcd_putsxy( X_0_POS + j*REC_WIDTH + (REC_WIDTH - w)/2,
522 TEXT_2_POS + i*REC_HEIGHT,
523 buttonChar[buttonGroup][i][j] );
527 /* initially, invert button "5" */
528 m = 2;
529 n = 1;
530 prev_m = m;
531 prev_n = n;
532 rb->lcd_set_drawmode(DRMODE_COMPLEMENT);
533 rb->lcd_fillrect( X_0_POS + n*REC_WIDTH + 1,
534 Y_1_POS + m*REC_HEIGHT + 1,
535 REC_WIDTH - 1, REC_HEIGHT - 1);
536 rb->lcd_set_drawmode(DRMODE_SOLID);
537 rb->lcd_update();
539 /* initial mem and output display*/
540 clearMem();
541 printResult();
543 /* clear button queue */
544 rb->button_clear_queue();
547 /* -----------------------------------------------------------------------
548 mySqrt uses Heron's algorithm, which is the Newtone-Raphson algorhitm
549 in it's private case for sqrt.
550 Thanks BlueChip for his intro text and Dave Straayer for the actual name.
551 ----------------------------------------------------------------------- */
552 double mySqrt(double square)
554 int k = 0;
555 double temp = 0;
556 double root= ABS(square+1)/2;
558 while( ABS(root - temp) > MINIMUM ){
559 temp = root;
560 root = (square/temp + temp)/2;
561 k++;
562 if (k>10000) return 0;
565 return root;
567 /* -----------------------------------------------------------------------
568 transcendFunc uses CORDIC (COordinate Rotation DIgital Computer) method
569 transcendFunc can do sin,cos,log,exp
570 input parameter is angle
571 ----------------------------------------------------------------------- */
572 void transcendFunc(char* func, double* tt, int* ttPower)
574 double t = (*tt)*M_PI/180; int tPower = *ttPower;
575 int sign = 1;
576 int n = 50; /* n <=50, tables are all <= 50 */
577 int j;
578 double x,y,z,xt,yt,zt;
580 if (tPower < -998) {
581 calStatus = cal_normal;
582 return;
584 if (tPower > 8) {
585 calStatus = cal_error;
586 return;
588 *ttPower = 0;
589 calStatus = cal_normal;
591 if( func[0] =='s' || func[0] =='S'|| func[0] =='t' || func[0] =='T')
592 sign = SIGN(t);
593 else {
594 /* if( func[0] =='c' || func[0] =='C') */
595 sign = 1;
597 t = ABS(t);
599 while (tPower > 0){
600 t *= 10;
601 tPower--;
603 while (tPower < 0) {
604 t /= 10;
605 tPower++;
607 j = 0;
608 while (t > j*M_TWOPI) {j++;}
609 t -= (j-1)*M_TWOPI;
610 if (M_PI_2 < t && t < 3*M_PI_2){
611 t = M_PI - t;
612 if (func[0] =='c' || func[0] =='C')
613 sign = -1;
614 else if (func[0] =='t' || func[0] =='T')
615 t*=-1;
617 else if ( 3*M_PI_2 <= t && t <= M_TWOPI)
618 t -= M_TWOPI;
620 x = 0.60725293500888; y = 0; z = t;
621 for (j=1;j<n+2;j++){
622 xt = x - SIGN(z) * y*cordicTable[j-1][0];
623 yt = y + SIGN(z) * x*cordicTable[j-1][0];
624 zt = z - SIGN(z) * cordicTable[j-1][1];
625 x = xt;
626 y=yt;
627 z=zt;
629 if( func[0] =='s' || func[0] =='S') {
630 *tt = sign*y;
631 return;
633 else if( func[0] =='c' || func[0] =='C') {
634 *tt = sign*x;
635 return;
637 else /*if( func[0] =='t' || func[0] =='T')*/ {
638 if(t==M_PI_2||t==-M_PI_2){
639 calStatus = cal_error;
640 return;
642 else{
643 *tt = sign*(y/x);
644 return;
649 /* -----------------------------------------------------------------------
650 add in scientific number format
651 ----------------------------------------------------------------------- */
652 void doAdd (double* operandOne, int* powerOne,
653 double operandTwo, int powerTwo)
655 if ( *powerOne >= powerTwo ){
656 if (*powerOne - powerTwo <= DIGITLEN+1){
657 while (powerTwo < *powerOne){
658 operandTwo /=10;
659 powerTwo++;
661 *operandOne += operandTwo;
663 /*do nothing if operandTwo is too small*/
665 else{
666 if (powerTwo - *powerOne <= DIGITLEN+1){
667 while(powerTwo > *powerOne){
668 *operandOne /=10;
669 (*powerOne)++;
671 (*operandOne) += operandTwo;
673 else{/* simply copy operandTwo if operandOne is too small */
674 *operandOne = operandTwo;
675 *powerOne = powerTwo;
679 /* -----------------------------------------------------------------------
680 multiple in scientific number format
681 ----------------------------------------------------------------------- */
682 void doMultiple(double* operandOne, int* powerOne,
683 double operandTwo, int powerTwo)
685 (*operandOne) *= operandTwo;
686 (*powerOne) += powerTwo;
689 /* -----------------------------------------------------------------------
690 Handles all one operand calculations
691 ----------------------------------------------------------------------- */
692 void oneOperand(void)
694 int k = 0;
695 if (buttonGroup == basicButtons){
696 switch(CAL_BUTTON){
697 case btn_sqr:
698 if (result<0)
699 calStatus = cal_error;
700 else{
701 if (power%2 == 1){
702 result = (mySqrt(result*10))/10;
703 power = (power+1) / 2;
705 else{
706 result = mySqrt(result);
707 power = power / 2;
709 calStatus = cal_normal;
711 break;
712 case btn_square:
713 power *= 2;
714 result *= result;
715 calStatus = cal_normal;
716 break;
718 case btn_rec:
719 if (result==0)
720 calStatus = cal_error;
721 else{
722 power = -power;
723 result = 1/result;
724 calStatus = cal_normal;
726 break;
727 default:
728 calStatus = cal_toDo;
729 break; /* just for the safety */
732 else{ /* sciButtons */
733 switch(CAL_BUTTON){
734 case sci_sin:
735 transcendFunc("sin", &result, &power);
736 break;
737 case sci_cos:
738 transcendFunc("cos", &result, &power);
739 break;
740 case sci_tan:
741 transcendFunc("tan", &result, &power);
742 break;
743 case sci_fac:
744 if (power<0 || power>8 || result<0 )
745 calStatus = cal_error;
746 else if(result == 0) {
747 result = 1;
748 power = 0;
750 else{
751 while(power > 0) {
752 result *= 10;
753 power--;
755 if ( ( result - (int)result) > MINIMUM )
756 calStatus = cal_error;
757 else {
758 k = result; result = 1;
759 while (k > 1){
760 doMultiple(&result, &power, k, 0);
761 formatResult();
762 k--;
764 calStatus = cal_normal;
767 break;
768 default:
769 calStatus = cal_toDo;
770 break; /* just for the safety */
776 /* -----------------------------------------------------------------------
777 Handles all two operands calculations
778 ----------------------------------------------------------------------- */
779 void twoOperands(void)
781 switch(oper){
782 case '-':
783 doAdd(&operand, &operandPower, -result, power);
784 break;
785 case '+':
786 doAdd(&operand, &operandPower, result, power);
787 break;
788 case '*':
789 doMultiple(&operand, &operandPower, result, power);
790 break;
791 case '/':
792 if ( ABS(result) > MINIMUM ){
793 doMultiple(&operand, &operandPower, 1/result, -power);
795 else
796 calStatus = cal_error;
797 break;
798 default: /* ' ' */
799 switchOperands(); /* counter switchOperands() below */
800 break;
801 } /* switch(oper) */
802 switchOperands();
803 clearOper();
805 /* -----------------------------------------------------------------------
806 move button index
807 Invert display new button, invert back previous button
808 ----------------------------------------------------------------------- */
809 void moveButton(void){
810 switch(btn){
811 case CALCULATOR_LEFT:
812 case CALCULATOR_LEFT | BUTTON_REPEAT:
813 if (n == 0)
814 n = 4;
815 else
816 n--;
817 break;
819 case CALCULATOR_RIGHT:
820 case CALCULATOR_RIGHT | BUTTON_REPEAT:
821 if (n == 4)
822 n = 0;
823 else
824 n++;
825 break;
827 case CALCULATOR_UP:
828 case CALCULATOR_UP | BUTTON_REPEAT:
829 if (m == 0)
830 m = 4;
831 else
832 m--;
833 break;
835 case CALCULATOR_DOWN:
836 case CALCULATOR_DOWN | BUTTON_REPEAT:
837 if (m == 4)
838 m = 0;
839 else
840 m++;
841 break;
844 rb->lcd_set_drawmode(DRMODE_COMPLEMENT);
845 rb->lcd_fillrect( X_0_POS + prev_n*REC_WIDTH + 1,
846 Y_1_POS + prev_m*REC_HEIGHT + 1,
847 REC_WIDTH - 1, REC_HEIGHT - 1);
849 rb->lcd_fillrect( X_0_POS + n*REC_WIDTH + 1,
850 Y_1_POS + m*REC_HEIGHT + 1,
851 REC_WIDTH - 1, REC_HEIGHT - 1);
852 rb->lcd_set_drawmode(DRMODE_SOLID);
854 rb->lcd_update_rect( X_0_POS + prev_n*REC_WIDTH + 1,
855 Y_1_POS + prev_m*REC_HEIGHT + 1,
856 REC_WIDTH - 1, REC_HEIGHT - 1);
858 rb->lcd_update_rect( X_0_POS + n*REC_WIDTH + 1,
859 Y_1_POS + m*REC_HEIGHT + 1,
860 REC_WIDTH - 1, REC_HEIGHT - 1);
862 prev_m = m;
863 prev_n = n;
865 /* -----------------------------------------------------------------------
866 Print buttons when switching 1st and 2nd
867 int group = {basicButtons, sciButtons}
868 ----------------------------------------------------------------------- */
869 void printButtonGroups(int group)
871 int i,j,w,h;
872 for (i = 0; i < 5; i++){
873 for (j = 3; j <= 4; j++){
874 rb->lcd_getstringsize( buttonChar[group][i][j],&w,&h);
875 rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
876 rb->lcd_fillrect( X_0_POS + j*REC_WIDTH + 1,
877 Y_1_POS + i*REC_HEIGHT + 1,
878 REC_WIDTH - 1, REC_HEIGHT - 1);
879 rb->lcd_set_drawmode(DRMODE_SOLID);
880 rb->lcd_putsxy( X_0_POS + j*REC_WIDTH + (REC_WIDTH - w)/2,
881 TEXT_2_POS + i*REC_HEIGHT,
882 buttonChar[group][i][j] );
885 for (i = 0; i <= 0; i++){
886 for (j = 0; j <= 2; j++){
887 rb->lcd_getstringsize( buttonChar[group][i][j],&w,&h);
888 rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
889 rb->lcd_fillrect( X_0_POS + j*REC_WIDTH + 1,
890 Y_1_POS + i*REC_HEIGHT + 1,
891 REC_WIDTH - 1, REC_HEIGHT - 1);
892 rb->lcd_set_drawmode(DRMODE_SOLID);
893 rb->lcd_putsxy( X_0_POS + j*REC_WIDTH + (REC_WIDTH - w)/2,
894 TEXT_2_POS + i*REC_HEIGHT,
895 buttonChar[group][i][j] );
898 rb->lcd_set_drawmode(DRMODE_COMPLEMENT);
899 rb->lcd_fillrect( X_0_POS + 2*REC_WIDTH + 1,
900 Y_1_POS + 0*REC_HEIGHT + 1,
901 REC_WIDTH - 1, REC_HEIGHT - 1);
902 rb->lcd_set_drawmode(DRMODE_SOLID);
903 rb->lcd_update_rect( X_0_POS, Y_1_POS,
904 REC_WIDTH*5, REC_HEIGHT*5);
906 /* -----------------------------------------------------------------------
907 flash the button pressed
908 ----------------------------------------------------------------------- */
909 void flashButton(int b)
911 int i = b/5; int j = b - i*5;
912 int k;
913 rb->lcd_set_drawmode(DRMODE_COMPLEMENT);
914 for (k=1*2;k>0;k--){
915 rb->lcd_fillrect( X_0_POS + j*REC_WIDTH + 1,
916 Y_1_POS + i*REC_HEIGHT + 1,
917 REC_WIDTH - 1, REC_HEIGHT - 1);
918 rb->lcd_update_rect( X_0_POS + j*REC_WIDTH + 1,
919 Y_1_POS + i*REC_HEIGHT + 1,
920 REC_WIDTH - 1, REC_HEIGHT - 1);
922 if (k!= 1)
923 rb->sleep(HZ/22);
926 rb->lcd_set_drawmode(DRMODE_SOLID);
929 /* -----------------------------------------------------------------------
930 pos is the position that needs animation. pos = [1~18]
931 ----------------------------------------------------------------------- */
932 void deleteAnimation(int pos)
934 int k;
935 if (pos<1 || pos >18)
936 return;
937 pos--;
938 rb->lcd_fillrect(1+pos*6, TEXT_1_POS, 6, 8);
939 rb->lcd_update_rect(1+pos*6, TEXT_1_POS, 6, 8);
941 for (k=1;k<=4;k++){
942 rb->sleep(HZ/32);
943 rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
944 rb->lcd_fillrect(1+pos*6, TEXT_1_POS, 6, 8);
945 rb->lcd_set_drawmode(DRMODE_SOLID);
946 rb->lcd_fillrect(1+pos*6+1+k, TEXT_1_POS+k,
947 (5-2*k)>0?(5-2*k):1, (7-2*k)>0?(7-2*k):1 );
948 rb->lcd_update_rect(1+pos*6, TEXT_1_POS, 6, 8);
953 /* -----------------------------------------------------------------------
954 result may be one of these formats:
956 xxxx.xxxx
957 0.xxxx
958 0.0000xxxx
960 formatResult() change result to standard format: 0.xxxx
961 if result is close to 0, let it be 0;
962 if result is close to 1, let it be 0.1 and power++;
963 ----------------------------------------------------------------------- */
964 void formatResult(void)
966 int resultsign = SIGN(result);
967 result = ABS(result);
968 if(result > MINIMUM ){ /* doesn't check power, might have problem
969 input wouldn't,
970 + - * / of two formatted number wouldn't.
971 only a calculation that makes a formatted
972 number (0.xxxx) less than MINIMUM in only
973 one operation */
975 if (result<1){
976 while( (int)(result*10) == 0 ){
977 result *= 10;
978 power--;
979 modifier *= 10;
982 else{ /* result >= 1 */
983 while( (int)result != 0 ){
984 result /= 10;
985 power++;
986 modifier /= 10;
988 } /* if result<1 */
990 if (result > (1-MINIMUM)){
991 result = 0.1;
992 power++;
993 modifier /= 10;
995 result *= resultsign;
997 else {
998 result = 0;
999 power = 0;
1000 modifier = 0.1;
1004 /* -----------------------------------------------------------------------
1005 result2typingbuf() outputs standard format result to typingbuf.
1006 case SCIENTIFIC_FORMAT, let temppower = 1;
1007 case temppower > 0: print '.' in the middle
1008 case temppower <= 0: print '.' in the begining
1009 ----------------------------------------------------------------------- */
1010 void result2typingbuf(void)
1012 bool haveDot = false;
1013 char tempchar = 0;
1014 int k;
1015 double tempresult = ABS(result); /* positive num makes things simple */
1017 int temppower;
1018 double tempmodifier = 1;
1019 int count;
1021 if(SCIENTIFIC_FORMAT)
1022 temppower = 1; /* output x.xxxx format */
1023 else
1024 temppower = power;
1026 cleartypingbuf();
1028 if(tempresult < MINIMUM){ /* if 0,faster display and avoid complication*/
1029 typingbuf[0] = ' ';
1030 typingbuf[1] = '0';
1032 else{ /* tempresult > 0 */
1033 typingbuf[0] = (SIGN(result)<0)?'-':' ';
1035 typingbufPointer = typingbuf;
1036 if(temppower > 0){
1037 for (k = 0; k<DIGITLEN+1 ; k++){
1038 typingbufPointer++;
1039 if(temppower || *(typingbufPointer-1) == '.'){
1040 count = 0;
1041 tempmodifier = tempmodifier/10;
1042 while( (tempresult-tempmodifier*count) >
1043 (tempmodifier-MINIMUM)){
1044 count++;
1046 tempresult -= tempmodifier*count;
1047 tempresult = ABS(tempresult);
1048 temppower-- ;
1049 *typingbufPointer = count + '0';
1051 else{ /* temppower == 0 */
1052 *typingbufPointer = '.';
1053 haveDot = true;
1055 } /* for */
1057 else{
1058 haveDot = true;
1059 typingbufPointer++; *typingbufPointer = '0';
1060 typingbufPointer++; *typingbufPointer = '.';
1061 for (k = 2; k<DIGITLEN+1 ; k++){
1062 typingbufPointer++;
1063 count = 0;
1064 if ( (-temppower) < (k-1)){
1065 tempmodifier = tempmodifier/10;
1066 while((tempresult-tempmodifier*count)>(tempmodifier-MINIMUM)){
1067 count++;
1070 tempresult -= tempmodifier*count;
1071 tempresult = ABS(tempresult);
1072 temppower-- ;
1074 *typingbufPointer = count + '0';
1077 /* now, typingbufPointer = typingbuf + 16 */
1078 /* backward strip off 0 and '.' */
1079 if (haveDot){
1080 while( (*typingbufPointer == '0') || (*typingbufPointer == '.')){
1081 tempchar = *typingbufPointer;
1082 *typingbufPointer = 0;
1083 typingbufPointer--;
1084 if (tempchar == '.') break;
1087 typingbuf[DIGITLEN+1] = 0;
1088 } /* else tempresult > 0 */
1091 /* -----------------------------------------------------------------------
1092 printResult() generates LCD display.
1093 ----------------------------------------------------------------------- */
1094 void printResult(void)
1096 int k;
1098 switch_Status:
1099 switch(calStatus){
1100 case cal_exit:
1101 rb->lcd_clear_display();
1102 rb->splash(HZ/3, "Bye now!");
1103 break;
1104 case cal_error:
1105 clearbuf();
1106 rb->snprintf(buf, 19, "%18s","Error");
1107 break;
1108 case cal_toDo:
1109 clearbuf();
1110 rb->snprintf(buf, 19, "%18s","Coming soon ^_* ");
1111 break;
1113 case cal_normal:
1114 formatResult();
1116 if( power > 1000 ){ /* power -1 > 999 */
1117 calStatus = cal_error;
1118 goto switch_Status;
1120 if (power < -998 ) /* power -1 < -999 */
1121 clearResult(); /* too small, let it be 0 */
1123 result2typingbuf();
1124 clearbuf();
1126 buf[0] = oper;
1127 buf[1] = ( ABS(memTemp) > MINIMUM )?'M':' ';
1128 buf[2] = ' ';
1130 if(SCIENTIFIC_FORMAT){
1131 /* output format: X.XXXX eXXX */
1132 if(power > -98){ /* power-1 >= -99, eXXX or e-XX */
1133 rb->snprintf(buf+3, 12, "%11s",typingbuf);
1134 for(k=14;k<=17;k++) buf[k] = ' ';
1135 cleartypingbuf();
1136 rb->snprintf(typingbuf, 5, "e%d",power-1);
1137 rb->snprintf(buf+14, 5, "%4s",typingbuf);
1139 else{ /* power-1 <= -100, e-XXX */
1140 rb->snprintf(buf+2, 12, "%11s",typingbuf);
1141 rb->snprintf(buf+13, 6, "e%d",power-1);
1144 else{
1145 rb->snprintf(buf+7, 12, "%11s",typingbuf);
1146 } /* if SCIENTIFIC_FORMAT */
1147 break;
1148 case cal_typing:
1149 case cal_dotted:
1150 clearbuf();
1151 buf[0] = oper;
1152 buf[1] = ( ABS(memTemp) > MINIMUM )?'M':' ';
1153 for(k=2;k<=6;k++)
1154 buf[k] = ' ';
1155 rb->snprintf(buf+7, 12, "%11s",typingbuf);
1156 break;
1160 rb->lcd_putsxy(1, TEXT_1_POS,buf);
1161 rb->lcd_update_rect(1, TEXT_1_POS, 6*18, 8);
1164 /* -----------------------------------------------------------------------
1165 Process typing buttons: 1-9, '.', sign
1166 main operand "result" and typingbuf are processed seperately here.
1167 ----------------------------------------------------------------------- */
1168 void typingProcess(void){
1169 switch( CAL_BUTTON ){
1170 case btn_sign:
1171 if (calStatus == cal_typing ||
1172 calStatus == cal_dotted)
1173 typingbuf[0] = (typingbuf[0]=='-')?' ':'-';
1174 result = -result;
1175 break;
1176 case btn_dot:
1177 operInputted = false;
1178 switch(calStatus){
1179 case cal_normal:
1180 clearInput();
1181 *typingbufPointer = '0';
1182 typingbufPointer++;
1183 case cal_typing:
1184 calStatus = cal_dotted;
1185 *typingbufPointer = '.';
1186 if (typingbufPointer != typingbuf+DIGITLEN+1)
1187 typingbufPointer++;
1188 break;
1189 default: /* cal_dotted */
1190 break;
1192 break;
1193 default: /* 0-9 */
1194 operInputted = false;
1195 /* normal,0; normal,1-9; typing,0; typing,1-9 */
1196 switch(calStatus){
1197 case cal_normal:
1198 if(CAL_BUTTON == btn_0 )
1199 break; /* first input is 0, ignore */
1200 clearInput();
1201 /*no operator means start a new calculation*/
1202 if (oper ==' ')
1203 clearOperand();
1204 calStatus = cal_typing;
1205 /* go on typing, no break */
1206 case cal_typing:
1207 case cal_dotted:
1208 switch(CAL_BUTTON){
1209 case btn_0:
1210 *typingbufPointer = '0';
1211 break;
1212 default:
1213 *typingbufPointer=(7+n-3*(m-1))+ '0';
1214 break;
1216 if (typingbufPointer!=typingbuf+DIGITLEN+1){
1217 typingbufPointer++;
1219 {/* result processing */
1220 if (calStatus == cal_typing) power++;
1221 if (CAL_BUTTON != btn_0)
1222 result= result +
1223 SIGN(result)*
1224 (7+n-3*(m-1))*modifier;
1225 modifier /= 10;
1228 else /* last byte always '\0' */
1229 *typingbufPointer = 0;
1230 break;
1231 default: /* cal_error, cal_exit */
1232 break;
1234 break; /* default, 0-9 */
1235 } /* switch( CAL_BUTTON ) */
1238 /* -----------------------------------------------------------------------
1239 Handle delete operation
1240 main operand "result" and typingbuf are processed seperately here.
1241 ----------------------------------------------------------------------- */
1242 void doDelete(void){
1243 deleteAnimation(18);
1244 switch(calStatus){
1245 case cal_dotted:
1246 if (*(typingbufPointer-1) == '.'){
1247 /* if dotted and deleting '.',
1248 change status and delete '.' below */
1249 calStatus = cal_typing;
1251 else{ /* if dotted and not deleting '.',
1252 power stays */
1253 power++; /* counter "power--;" below */
1255 case cal_typing:
1256 typingbufPointer--;
1258 {/* result processing */ /* 0-9, '.' */
1259 /* if deleting '.', do nothing */
1260 if ( *typingbufPointer != '.'){
1261 power--;
1262 modifier *= 10;
1263 result = result - SIGN(result)*
1264 ((*typingbufPointer)- '0')*modifier;
1268 *typingbufPointer = 0;
1270 /* if (only one digit left and it's 0)
1271 or no digit left, change status*/
1272 if ( typingbufPointer == typingbuf+1 ||
1273 ( typingbufPointer == typingbuf+2 &&
1274 *(typingbufPointer-1) == '0' ))
1275 calStatus = cal_normal;
1276 break;
1277 default: /* normal, error, exit */
1278 break;
1281 /* -----------------------------------------------------------------------
1282 Handle buttons on basic screen
1283 ----------------------------------------------------------------------- */
1284 void basicButtonsProcess(void){
1285 switch (btn) {
1286 case CALCULATOR_INPUT:
1287 if (calStatus == cal_error && (CAL_BUTTON != btn_C) ) break;
1288 flashButton(CAL_BUTTON);
1289 switch( CAL_BUTTON ){
1290 case btn_MR:
1291 operInputted = false;
1292 result = memTemp; power = memTempPower;
1293 calStatus = cal_normal;
1294 break;
1295 case btn_M:
1296 formatResult();
1297 if (memTemp > MINIMUM)
1298 doAdd(&memTemp, &memTempPower, result, power);
1299 else {
1300 /* if result is too small and memTemp = 0,
1301 doAdd will not add */
1302 memTemp = result;
1303 memTempPower = power;
1305 calStatus = cal_normal;
1306 break;
1308 case btn_C: clearMem(); break;
1309 case btn_CE: clearInput(); break;
1311 case btn_bas:
1312 buttonGroup = sciButtons;
1313 printButtonGroups(buttonGroup);
1314 break;
1316 /* one operand calculation, may be changed to
1317 like sin, cos, log, etc */
1318 case btn_sqr:
1319 case btn_square:
1320 case btn_rec:
1321 formatResult(); /* not necessary, just for safty */
1322 oneOperand();
1323 break;
1325 case_btn_equal: /* F3 shortkey entrance */
1326 case btn_equal:
1327 formatResult();
1328 calStatus = cal_normal;
1329 operInputted = false;
1330 if (oper != ' ') twoOperands();
1331 break;
1333 case btn_div:
1334 case btn_time:
1335 case btn_minus:
1336 case btn_add:
1337 if(!operInputted) {twoOperands(); operInputted = true;}
1338 oper = buttonChar[basicButtons][m][n][0];
1339 #ifdef CALCULATOR_OPERATORS
1340 case_cycle_operators: /* F2 shortkey entrance */
1341 #endif
1342 calStatus = cal_normal;
1343 formatResult();
1344 operand = result;
1345 operandPower = power;
1347 break;
1349 case btn_sign:
1350 case btn_dot:
1351 default: /* 0-9 */
1352 typingProcess();
1353 break;
1354 } /* switch (CAL_BUTTON) */
1355 break;
1357 #ifdef CALCULATOR_OPERATORS
1358 case CALCULATOR_OPERATORS:
1359 if (calStatus == cal_error) break;
1360 if (!operInputted) {twoOperands(); operInputted = true;}
1361 switch (oper){
1362 case ' ':
1363 case '/': oper = '+'; flashButton(btn_add); break;
1364 case '+': oper = '-'; flashButton(btn_minus); break;
1365 case '-': oper = '*'; flashButton(btn_time); break;
1366 case '*': oper = '/'; flashButton(btn_div); break;
1368 goto case_cycle_operators;
1369 break;
1370 #endif
1372 case CALCULATOR_CALC:
1373 if (calStatus == cal_error) break;
1374 flashButton(btn_equal);
1375 goto case_btn_equal;
1376 break;
1377 default: break;
1379 printResult();
1382 /* -----------------------------------------------------------------------
1383 Handle buttons on scientific screen
1384 ----------------------------------------------------------------------- */
1385 void sciButtonsProcess(void){
1386 switch (btn) {
1387 case CALCULATOR_INPUT:
1388 if (calStatus == cal_error && (CAL_BUTTON != sci_sci) ) break;
1389 flashButton(CAL_BUTTON);
1390 switch( CAL_BUTTON ){
1392 case sci_pi:
1393 result = M_PI; power = 0;
1394 calStatus = cal_normal;
1395 break;
1397 case sci_xy: break;
1399 case sci_sci:
1400 buttonGroup = basicButtons;
1401 printButtonGroups(basicButtons);
1402 break;
1404 case sci_fac:
1405 case sci_sin:
1406 case sci_asin:
1407 case sci_cos:
1408 case sci_acos:
1409 case sci_tan:
1410 case sci_atan:
1411 case sci_ln:
1412 case sci_exp:
1413 case sci_log:
1414 formatResult(); /* not necessary, just for safty */
1415 oneOperand();
1416 break;
1418 case btn_sign:
1419 case btn_dot:
1420 default: /* 0-9 */
1421 typingProcess();
1422 break;
1423 } /* switch (CAL_BUTTON) */
1424 break;
1426 #ifdef CALCULATOR_OPERATORS
1427 case CALCULATOR_OPERATORS:
1428 if (calStatus == cal_error) break;
1429 if (!operInputted) {twoOperands(); operInputted = true;}
1430 switch (oper){
1431 case ' ': oper = '+'; break;
1432 case '/': oper = '+'; deleteAnimation(1); break;
1433 case '+': oper = '-'; deleteAnimation(1); break;
1434 case '-': oper = '*'; deleteAnimation(1); break;
1435 case '*': oper = '/'; deleteAnimation(1); break;
1437 calStatus = cal_normal;
1438 formatResult();
1439 operand = result;
1440 operandPower = power;
1441 break;
1442 #endif
1444 case CALCULATOR_CALC:
1445 if (calStatus == cal_error) break;
1446 formatResult();
1447 calStatus = cal_normal;
1448 operInputted = false;
1449 if (oper != ' ') twoOperands();
1450 break;
1451 default: break;
1453 printResult();
1456 /* -----------------------------------------------------------------------
1457 Main();
1458 ----------------------------------------------------------------------- */
1459 enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
1461 (void)parameter;
1462 rb = api;
1464 /* now go ahead and have fun! */
1466 cal_initial();
1468 while (calStatus != cal_exit ) {
1469 btn = rb->button_get_w_tmo(HZ/2);
1470 switch (btn) {
1471 case CALCULATOR_INPUT:
1472 case CALCULATOR_CALC:
1473 #ifdef CALCULATOR_INPUT_CALC_PRE
1474 if (lastbtn != CALCULATOR_INPUT_CALC_PRE)
1475 break;
1476 /* no unconditional break; here! */
1477 #endif
1478 #ifdef CALCULATOR_OPERATORS
1479 case CALCULATOR_OPERATORS:
1480 #endif
1481 switch(buttonGroup){
1482 case basicButtons:
1483 basicButtonsProcess();
1484 break;
1485 case sciButtons:
1486 sciButtonsProcess();
1487 break;
1489 break;
1491 #ifdef CALCULATOR_CLEAR
1492 case CALCULATOR_CLEAR:
1493 switch(calStatus){
1494 case cal_typing:
1495 case cal_dotted:
1496 doDelete();
1497 break;
1498 default: /* cal_normal, cal_error, cal_exit */
1499 clearMem();
1500 break;
1502 printResult();
1503 break;
1504 #endif
1506 case CALCULATOR_LEFT:
1507 case CALCULATOR_LEFT | BUTTON_REPEAT:
1508 case CALCULATOR_RIGHT:
1509 case CALCULATOR_RIGHT | BUTTON_REPEAT:
1510 case CALCULATOR_UP:
1511 case CALCULATOR_UP | BUTTON_REPEAT:
1512 case CALCULATOR_DOWN:
1513 case CALCULATOR_DOWN | BUTTON_REPEAT:
1514 moveButton();
1515 break;
1516 #ifdef CALCULATOR_RC_QUIT
1517 case CALCULATOR_RC_QUIT:
1518 #endif
1519 case CALCULATOR_QUIT:
1520 calStatus = cal_exit;
1521 printResult();
1522 break;
1523 default:
1524 if(rb->default_event_handler(btn) == SYS_USB_CONNECTED)
1525 return PLUGIN_USB_CONNECTED;
1526 break;
1527 } /* switch (btn) */
1528 if (btn != BUTTON_NONE)
1529 lastbtn = btn;
1530 } /* while (calStatus != cal_exit ) */
1532 /* rb->splash(HZ*2, "Hello world!"); */
1533 rb->button_clear_queue();
1534 return PLUGIN_OK;
1537 #endif /* #ifdef HAVE_LCD_BITMAP */