1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
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 |-----------|-----------|-----------|-----------|-----------|
24 |***********|***********|***********|***********|***********|
25 |***********|***********|***********|***********|***********|
27 12 |-----------|-----------|-----------|-----------|-----------|
28 13 |-----------|-----------|-----------|-----------|-----------| y1
32 23 |-----------|-----------|-----------|-----------|-----------| y2
36 33 |-----------|-----------|-----------|-----------|-----------| y3
40 43 |-----------|-----------|-----------|-----------|-----------| y4
44 53 |-----------|-----------|-----------|-----------|-----------| y5
48 63 |-----------|-----------|-----------|-----------|-----------| y6
52 /*---------------------------------------------------------------------------
54 - Scientific number format core code. Support range 10^-999 ~ 10^999
55 - Number of significant figures up to 10
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.
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 "+, -, *, /"
70 "MR" : load temp memory
71 "M+" : add currently display to temp memory
72 "C" : reset calculator
73 ---------------------------------------------------------------------------*/
76 #ifdef HAVE_LCD_BITMAP
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
265 #error No keymap defined!
268 static struct plugin_api
* rb
;
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 */
302 /* 123456789abcdef */
304 #define DIGITLEN 10 /* must <= 10 */
305 #define SCIENTIFIC_FORMAT ( power < -(DIGITLEN-3) || power > (DIGITLEN))
306 /* 0.000 00000 0001 */
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,
314 buf[1] = 'M' if memTemp is not 0
318 buf[2]-buf[12] or buf[3]-buf[13] = result;
320 buf[13] or buf[14] -buf[17] = power;
324 buf[7]-buf[17] = result;
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
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. */
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 /* -----------------------------------------------------------------------
427 ----------------------------------------------------------------------- */
428 void cleartypingbuf(void)
431 for( k
=1; k
<=(DIGITLEN
+1); k
++)
434 typingbufPointer
= typingbuf
+1;
443 void clearResult(void)
450 void clearInput(void)
452 calStatus
= cal_normal
;
457 void clearOperand(void)
463 void clearMemTemp(void)
472 operInputted
= false;
484 void switchOperands(void)
486 double tempr
= operand
;
487 int tempp
= operandPower
;
489 operandPower
= power
;
494 /* -----------------------------------------------------------------------
496 ----------------------------------------------------------------------- */
497 void cal_initial (void)
500 rb
->lcd_setfont(FONT_SYSFIXED
);
501 rb
->lcd_clear_display();
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
;
515 buttonGroup
= basicButtons
;
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" */
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
);
539 /* initial mem and output display*/
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
)
556 double root
= ABS(square
+1)/2;
558 while( ABS(root
- temp
) > MINIMUM
){
560 root
= (square
/temp
+ temp
)/2;
562 if (k
>10000) return 0;
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
;
576 int n
= 50; /* n <=50, tables are all <= 50 */
578 double x
,y
,z
,xt
,yt
,zt
;
581 calStatus
= cal_normal
;
585 calStatus
= cal_error
;
589 calStatus
= cal_normal
;
591 if( func
[0] =='s' || func
[0] =='S'|| func
[0] =='t' || func
[0] =='T')
594 /* if( func[0] =='c' || func[0] =='C') */
608 while (t
> j
*M_TWOPI
) {j
++;}
610 if (M_PI_2
< t
&& t
< 3*M_PI_2
){
612 if (func
[0] =='c' || func
[0] =='C')
614 else if (func
[0] =='t' || func
[0] =='T')
617 else if ( 3*M_PI_2
<= t
&& t
<= M_TWOPI
)
620 x
= 0.60725293500888; y
= 0; z
= t
;
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];
629 if( func
[0] =='s' || func
[0] =='S') {
633 else if( func
[0] =='c' || func
[0] =='C') {
637 else /*if( func[0] =='t' || func[0] =='T')*/ {
638 if(t
==M_PI_2
||t
==-M_PI_2
){
639 calStatus
= cal_error
;
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
){
661 *operandOne
+= operandTwo
;
663 /*do nothing if operandTwo is too small*/
666 if (powerTwo
- *powerOne
<= DIGITLEN
+1){
667 while(powerTwo
> *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)
695 if (buttonGroup
== basicButtons
){
699 calStatus
= cal_error
;
702 result
= (mySqrt(result
*10))/10;
703 power
= (power
+1) / 2;
706 result
= mySqrt(result
);
709 calStatus
= cal_normal
;
715 calStatus
= cal_normal
;
720 calStatus
= cal_error
;
724 calStatus
= cal_normal
;
728 calStatus
= cal_toDo
;
729 break; /* just for the safety */
732 else{ /* sciButtons */
735 transcendFunc("sin", &result
, &power
);
738 transcendFunc("cos", &result
, &power
);
741 transcendFunc("tan", &result
, &power
);
744 if (power
<0 || power
>8 || result
<0 )
745 calStatus
= cal_error
;
746 else if(result
== 0) {
755 if ( ( result
- (int)result
) > MINIMUM
)
756 calStatus
= cal_error
;
758 k
= result
; result
= 1;
760 doMultiple(&result
, &power
, k
, 0);
764 calStatus
= cal_normal
;
769 calStatus
= cal_toDo
;
770 break; /* just for the safety */
776 /* -----------------------------------------------------------------------
777 Handles all two operands calculations
778 ----------------------------------------------------------------------- */
779 void twoOperands(void)
783 doAdd(&operand
, &operandPower
, -result
, power
);
786 doAdd(&operand
, &operandPower
, result
, power
);
789 doMultiple(&operand
, &operandPower
, result
, power
);
792 if ( ABS(result
) > MINIMUM
){
793 doMultiple(&operand
, &operandPower
, 1/result
, -power
);
796 calStatus
= cal_error
;
799 switchOperands(); /* counter switchOperands() below */
805 /* -----------------------------------------------------------------------
807 Invert display new button, invert back previous button
808 ----------------------------------------------------------------------- */
809 void moveButton(void){
811 case CALCULATOR_LEFT
:
812 case CALCULATOR_LEFT
| BUTTON_REPEAT
:
819 case CALCULATOR_RIGHT
:
820 case CALCULATOR_RIGHT
| BUTTON_REPEAT
:
828 case CALCULATOR_UP
| BUTTON_REPEAT
:
835 case CALCULATOR_DOWN
:
836 case CALCULATOR_DOWN
| BUTTON_REPEAT
:
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);
865 /* -----------------------------------------------------------------------
866 Print buttons when switching 1st and 2nd
867 int group = {basicButtons, sciButtons}
868 ----------------------------------------------------------------------- */
869 void printButtonGroups(int group
)
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;
913 rb
->lcd_set_drawmode(DRMODE_COMPLEMENT
);
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);
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
)
935 if (pos
<1 || pos
>18)
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);
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:
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
970 + - * / of two formatted number wouldn't.
971 only a calculation that makes a formatted
972 number (0.xxxx) less than MINIMUM in only
976 while( (int)(result
*10) == 0 ){
982 else{ /* result >= 1 */
983 while( (int)result
!= 0 ){
990 if (result
> (1-MINIMUM
)){
995 result
*= resultsign
;
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;
1015 double tempresult
= ABS(result
); /* positive num makes things simple */
1018 double tempmodifier
= 1;
1021 if(SCIENTIFIC_FORMAT
)
1022 temppower
= 1; /* output x.xxxx format */
1028 if(tempresult
< MINIMUM
){ /* if 0,faster display and avoid complication*/
1032 else{ /* tempresult > 0 */
1033 typingbuf
[0] = (SIGN(result
)<0)?'-':' ';
1035 typingbufPointer
= typingbuf
;
1037 for (k
= 0; k
<DIGITLEN
+1 ; k
++){
1039 if(temppower
|| *(typingbufPointer
-1) == '.'){
1041 tempmodifier
= tempmodifier
/10;
1042 while( (tempresult
-tempmodifier
*count
) >
1043 (tempmodifier
-MINIMUM
)){
1046 tempresult
-= tempmodifier
*count
;
1047 tempresult
= ABS(tempresult
);
1049 *typingbufPointer
= count
+ '0';
1051 else{ /* temppower == 0 */
1052 *typingbufPointer
= '.';
1059 typingbufPointer
++; *typingbufPointer
= '0';
1060 typingbufPointer
++; *typingbufPointer
= '.';
1061 for (k
= 2; k
<DIGITLEN
+1 ; k
++){
1064 if ( (-temppower
) < (k
-1)){
1065 tempmodifier
= tempmodifier
/10;
1066 while((tempresult
-tempmodifier
*count
)>(tempmodifier
-MINIMUM
)){
1070 tempresult
-= tempmodifier
*count
;
1071 tempresult
= ABS(tempresult
);
1074 *typingbufPointer
= count
+ '0';
1077 /* now, typingbufPointer = typingbuf + 16 */
1078 /* backward strip off 0 and '.' */
1080 while( (*typingbufPointer
== '0') || (*typingbufPointer
== '.')){
1081 tempchar
= *typingbufPointer
;
1082 *typingbufPointer
= 0;
1084 if (tempchar
== '.') break;
1087 typingbuf
[DIGITLEN
+1] = 0;
1088 } /* else tempresult > 0 */
1091 /* -----------------------------------------------------------------------
1092 printResult() generates LCD display.
1093 ----------------------------------------------------------------------- */
1094 void printResult(void)
1101 rb
->lcd_clear_display();
1102 rb
->splash(HZ
/3, "Bye now!");
1106 rb
->snprintf(buf
, 19, "%18s","Error");
1110 rb
->snprintf(buf
, 19, "%18s","Coming soon ^_* ");
1116 if( power
> 1000 ){ /* power -1 > 999 */
1117 calStatus
= cal_error
;
1120 if (power
< -998 ) /* power -1 < -999 */
1121 clearResult(); /* too small, let it be 0 */
1127 buf
[1] = ( ABS(memTemp
) > MINIMUM
)?'M':' ';
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
] = ' ';
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);
1145 rb
->snprintf(buf
+7, 12, "%11s",typingbuf
);
1146 } /* if SCIENTIFIC_FORMAT */
1152 buf
[1] = ( ABS(memTemp
) > MINIMUM
)?'M':' ';
1155 rb
->snprintf(buf
+7, 12, "%11s",typingbuf
);
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
){
1171 if (calStatus
== cal_typing
||
1172 calStatus
== cal_dotted
)
1173 typingbuf
[0] = (typingbuf
[0]=='-')?' ':'-';
1177 operInputted
= false;
1181 *typingbufPointer
= '0';
1184 calStatus
= cal_dotted
;
1185 *typingbufPointer
= '.';
1186 if (typingbufPointer
!= typingbuf
+DIGITLEN
+1)
1189 default: /* cal_dotted */
1194 operInputted
= false;
1195 /* normal,0; normal,1-9; typing,0; typing,1-9 */
1198 if(CAL_BUTTON
== btn_0
)
1199 break; /* first input is 0, ignore */
1201 /*no operator means start a new calculation*/
1204 calStatus
= cal_typing
;
1205 /* go on typing, no break */
1210 *typingbufPointer
= '0';
1213 *typingbufPointer
=(7+n
-3*(m
-1))+ '0';
1216 if (typingbufPointer
!=typingbuf
+DIGITLEN
+1){
1219 {/* result processing */
1220 if (calStatus
== cal_typing
) power
++;
1221 if (CAL_BUTTON
!= btn_0
)
1224 (7+n
-3*(m
-1))*modifier
;
1228 else /* last byte always '\0' */
1229 *typingbufPointer
= 0;
1231 default: /* cal_error, cal_exit */
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);
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 '.',
1253 power
++; /* counter "power--;" below */
1258 {/* result processing */ /* 0-9, '.' */
1259 /* if deleting '.', do nothing */
1260 if ( *typingbufPointer
!= '.'){
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
;
1277 default: /* normal, error, exit */
1281 /* -----------------------------------------------------------------------
1282 Handle buttons on basic screen
1283 ----------------------------------------------------------------------- */
1284 void basicButtonsProcess(void){
1286 case CALCULATOR_INPUT
:
1287 if (calStatus
== cal_error
&& (CAL_BUTTON
!= btn_C
) ) break;
1288 flashButton(CAL_BUTTON
);
1289 switch( CAL_BUTTON
){
1291 operInputted
= false;
1292 result
= memTemp
; power
= memTempPower
;
1293 calStatus
= cal_normal
;
1297 if (memTemp
> MINIMUM
)
1298 doAdd(&memTemp
, &memTempPower
, result
, power
);
1300 /* if result is too small and memTemp = 0,
1301 doAdd will not add */
1303 memTempPower
= power
;
1305 calStatus
= cal_normal
;
1308 case btn_C
: clearMem(); break;
1309 case btn_CE
: clearInput(); break;
1312 buttonGroup
= sciButtons
;
1313 printButtonGroups(buttonGroup
);
1316 /* one operand calculation, may be changed to
1317 like sin, cos, log, etc */
1321 formatResult(); /* not necessary, just for safty */
1325 case_btn_equal
: /* F3 shortkey entrance */
1328 calStatus
= cal_normal
;
1329 operInputted
= false;
1330 if (oper
!= ' ') twoOperands();
1337 if(!operInputted
) {twoOperands(); operInputted
= true;}
1338 oper
= buttonChar
[basicButtons
][m
][n
][0];
1339 #ifdef CALCULATOR_OPERATORS
1340 case_cycle_operators
: /* F2 shortkey entrance */
1342 calStatus
= cal_normal
;
1345 operandPower
= power
;
1354 } /* switch (CAL_BUTTON) */
1357 #ifdef CALCULATOR_OPERATORS
1358 case CALCULATOR_OPERATORS
:
1359 if (calStatus
== cal_error
) break;
1360 if (!operInputted
) {twoOperands(); operInputted
= true;}
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
;
1372 case CALCULATOR_CALC
:
1373 if (calStatus
== cal_error
) break;
1374 flashButton(btn_equal
);
1375 goto case_btn_equal
;
1382 /* -----------------------------------------------------------------------
1383 Handle buttons on scientific screen
1384 ----------------------------------------------------------------------- */
1385 void sciButtonsProcess(void){
1387 case CALCULATOR_INPUT
:
1388 if (calStatus
== cal_error
&& (CAL_BUTTON
!= sci_sci
) ) break;
1389 flashButton(CAL_BUTTON
);
1390 switch( CAL_BUTTON
){
1393 result
= M_PI
; power
= 0;
1394 calStatus
= cal_normal
;
1400 buttonGroup
= basicButtons
;
1401 printButtonGroups(basicButtons
);
1414 formatResult(); /* not necessary, just for safty */
1423 } /* switch (CAL_BUTTON) */
1426 #ifdef CALCULATOR_OPERATORS
1427 case CALCULATOR_OPERATORS
:
1428 if (calStatus
== cal_error
) break;
1429 if (!operInputted
) {twoOperands(); operInputted
= true;}
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
;
1440 operandPower
= power
;
1444 case CALCULATOR_CALC
:
1445 if (calStatus
== cal_error
) break;
1447 calStatus
= cal_normal
;
1448 operInputted
= false;
1449 if (oper
!= ' ') twoOperands();
1456 /* -----------------------------------------------------------------------
1458 ----------------------------------------------------------------------- */
1459 enum plugin_status
plugin_start(struct plugin_api
* api
, void* parameter
)
1464 /* now go ahead and have fun! */
1468 while (calStatus
!= cal_exit
) {
1469 btn
= rb
->button_get_w_tmo(HZ
/2);
1471 case CALCULATOR_INPUT
:
1472 case CALCULATOR_CALC
:
1473 #ifdef CALCULATOR_INPUT_CALC_PRE
1474 if (lastbtn
!= CALCULATOR_INPUT_CALC_PRE
)
1476 /* no unconditional break; here! */
1478 #ifdef CALCULATOR_OPERATORS
1479 case CALCULATOR_OPERATORS
:
1481 switch(buttonGroup
){
1483 basicButtonsProcess();
1486 sciButtonsProcess();
1491 #ifdef CALCULATOR_CLEAR
1492 case CALCULATOR_CLEAR
:
1498 default: /* cal_normal, cal_error, cal_exit */
1506 case CALCULATOR_LEFT
:
1507 case CALCULATOR_LEFT
| BUTTON_REPEAT
:
1508 case CALCULATOR_RIGHT
:
1509 case CALCULATOR_RIGHT
| BUTTON_REPEAT
:
1511 case CALCULATOR_UP
| BUTTON_REPEAT
:
1512 case CALCULATOR_DOWN
:
1513 case CALCULATOR_DOWN
| BUTTON_REPEAT
:
1516 #ifdef CALCULATOR_RC_QUIT
1517 case CALCULATOR_RC_QUIT
:
1519 case CALCULATOR_QUIT
:
1520 calStatus
= cal_exit
;
1524 if(rb
->default_event_handler(btn
) == SYS_USB_CONNECTED
)
1525 return PLUGIN_USB_CONNECTED
;
1527 } /* switch (btn) */
1528 if (btn
!= BUTTON_NONE
)
1530 } /* while (calStatus != cal_exit ) */
1532 /* rb->splash(HZ*2, "Hello world!"); */
1533 rb
->button_clear_queue();
1537 #endif /* #ifdef HAVE_LCD_BITMAP */