1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright (C) 2004 Pengxuan(Isaac) <tinousus@yahoo.com>
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
18 ****************************************************************************/
21 00 01 21 22 23 43 44 45 65 66 67 87 88 89 109110111
22 00 |-----------|-----------|-----------|-----------|-----------|
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_UP BUTTON_UP
112 #define CALCULATOR_DOWN BUTTON_DOWN
113 #define CALCULATOR_QUIT BUTTON_OFF
114 #define CALCULATOR_INPUT BUTTON_PLAY
115 #define CALCULATOR_CALC BUTTON_F3
116 #define CALCULATOR_OPERATORS BUTTON_F2
117 #define CALCULATOR_CLEAR BUTTON_F1
119 #elif CONFIG_KEYPAD == ONDIO_PAD
120 #define CALCULATOR_UP BUTTON_UP
121 #define CALCULATOR_DOWN BUTTON_DOWN
122 #define CALCULATOR_QUIT BUTTON_OFF
123 #define CALCULATOR_INPUT_CALC_PRE BUTTON_MENU
124 #define CALCULATOR_INPUT (BUTTON_MENU | BUTTON_REL)
125 #define CALCULATOR_CALC (BUTTON_MENU | BUTTON_REPEAT)
127 #elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || \
128 (CONFIG_KEYPAD == IRIVER_H300_PAD)
129 #define CALCULATOR_UP BUTTON_UP
130 #define CALCULATOR_DOWN BUTTON_DOWN
131 #define CALCULATOR_QUIT BUTTON_OFF
132 #define CALCULATOR_INPUT BUTTON_SELECT
133 #define CALCULATOR_CALC BUTTON_ON
134 #define CALCULATOR_OPERATORS BUTTON_MODE
135 #define CALCULATOR_CLEAR BUTTON_REC
137 #elif (CONFIG_KEYPAD == IPOD_4G_PAD) || \
138 (CONFIG_KEYPAD == IPOD_3G_PAD)
140 #define CALCULATOR_UP BUTTON_SCROLL_BACK
141 #define CALCULATOR_DOWN BUTTON_SCROLL_FWD
142 #define CALCULATOR_QUIT BUTTON_MENU
143 #define CALCULATOR_INPUT_CALC_PRE BUTTON_SELECT
144 #define CALCULATOR_INPUT (BUTTON_SELECT | BUTTON_REL)
145 #define CALCULATOR_CALC (BUTTON_PLAY | BUTTON_REPEAT)
147 #elif (CONFIG_KEYPAD == IAUDIO_X5_PAD)
149 #define CALCULATOR_UP BUTTON_UP
150 #define CALCULATOR_DOWN BUTTON_DOWN
151 #define CALCULATOR_QUIT BUTTON_POWER
152 #define CALCULATOR_INPUT_CALC_PRE BUTTON_SELECT
153 #define CALCULATOR_INPUT (BUTTON_SELECT | BUTTON_REL)
154 #define CALCULATOR_CALC BUTTON_PLAY
155 #define CALCULATOR_CLEAR BUTTON_REC
157 #elif (CONFIG_KEYPAD == GIGABEAT_PAD)
159 #define CALCULATOR_UP BUTTON_UP
160 #define CALCULATOR_DOWN BUTTON_DOWN
161 #define CALCULATOR_QUIT BUTTON_A
162 #define CALCULATOR_INPUT_CALC_PRE BUTTON_MENU
163 #define CALCULATOR_INPUT (BUTTON_MENU | BUTTON_REL)
164 #define CALCULATOR_CALC BUTTON_SELECT
165 #define CALCULATOR_CLEAR BUTTON_POWER
169 static struct plugin_api
* rb
;
175 unsigned char* buttonChar
[2][5][5] = {
176 { { "MR" , "M+" , "2nd" , "CE" , "C" },
177 { "7" , "8" , "9" , "/" , "sqr" },
178 { "4" , "5" , "6" , "*" , "x^2" },
179 { "1" , "2" , "3" , "-" , "1/x" },
180 { "0" , "+/-", "." , "+" , "=" } },
182 { { "n!" , "PI" , "1st" , "sin" , "asi" },
183 { "7" , "8" , "9" , "cos" , "aco" },
184 { "4" , "5" , "6" , "tan" , "ata" },
185 { "1" , "2" , "3" , "ln" , "e^x" },
186 { "0" , "+/-", "." , "log" , "x^y" } }
188 enum { btn_MR
, btn_M
, btn_bas
, btn_CE
, btn_C
,
189 btn_7
, btn_8
, btn_9
, btn_div
, btn_sqr
,
190 btn_4
, btn_5
, btn_6
, btn_time
, btn_square
,
191 btn_1
, btn_2
, btn_3
, btn_minus
, btn_rec
,
192 btn_0
, btn_sign
, btn_dot
, btn_add
, btn_equal
194 enum { sci_fac
, sci_pi
, sci_sci
, sci_sin
, sci_asin
,
195 sci_7
, sci_8
, sci_9
, sci_cos
, sci_acos
,
196 sci_4
, sci_5
, sci_6
, sci_tan
, sci_atan
,
197 sci_1
, sci_2
, sci_3
, sci_ln
, sci_exp
,
198 sci_0
, sci_sign
, sci_dot
, sci_log
, sci_xy
201 #define PI 3.14159265358979323846
202 #define MINIMUM 0.000000000001 /* e-12 */
204 /* 123456789abcdef */
206 #define DIGITLEN 10 /* must <= 10 */
207 #define SCIENTIFIC_FORMAT ( power < -(DIGITLEN-3) || power > (DIGITLEN))
208 /* 0.000 00000 0001 */
210 /* DIGITLEN 12345 6789a bcdef */
211 /* power 12 34567 89abc def */
212 /* 10^- 123 45678 9abcd ef */
214 unsigned char buf
[19];/* 18 bytes of output line,
216 buf[1] = 'M' if memTemp is not 0
220 buf[2]-buf[12] or buf[3]-buf[13] = result;
222 buf[13] or buf[14] -buf[17] = power;
226 buf[7]-buf[17] = result;
230 unsigned char typingbuf
[DIGITLEN
+2];/* byte 0 is sign or ' ',
231 byte 1~DIGITLEN are num and '.'
232 byte (DIGITLEN+1) is '\0' */
233 unsigned char* typingbufPointer
= typingbuf
;
235 double result
= 0; /* main operand, format 0.xxxxx */
236 int power
= 0; /* 10^power */
237 double modifier
= 0.1; /* position of next input */
238 double operand
= 0; /* second operand, format 0.xxxxx */
239 int operandPower
= 0; /* 10^power of second operand */
240 char oper
= ' '; /* operators: + - * / */
241 bool operInputted
= false; /* false: do calculation first and
243 true: just replace current oper */
245 double memTemp
= 0; /* temp memory */
246 int memTempPower
= 0; /* 10^^power of memTemp */
248 int m
, n
, prev_m
, prev_n
; /* position index for button */
249 #define CAL_BUTTON (m*5+n)
251 int btn
= BUTTON_NONE
;
252 int lastbtn
= BUTTON_NONE
;
254 /* Status of calculator */
255 enum {cal_normal
, /* 0, normal status, display result */
256 cal_typing
, /* 1, currently typing, dot hasn't been typed */
257 cal_dotted
, /* 2, currently typing, dot already has been typed. */
263 /* constant table for CORDIC algorithm */
264 double cordicTable
[51][2]= {
265 /* pow(2,0) - pow(2,-50) atan(pow(2,0) - atan(pow(2,-50) */
266 {1e+00, 7.853981633974483e-01},
267 {5e-01, 4.636476090008061e-01},
268 {2.5e-01, 2.449786631268641e-01},
269 {1.25e-01, 1.243549945467614e-01},
270 {6.25e-02, 6.241880999595735e-02},
271 {3.125e-02, 3.123983343026828e-02},
272 {1.5625e-02, 1.562372862047683e-02},
273 {7.8125e-03, 7.812341060101111e-03},
274 {3.90625e-03, 3.906230131966972e-03},
275 {1.953125e-03, 1.953122516478819e-03},
276 {9.765625e-04, 9.765621895593195e-04},
277 {4.8828125e-04, 4.882812111948983e-04},
278 {2.44140625e-04, 2.441406201493618e-04},
279 {1.220703125e-04, 1.220703118936702e-04},
280 {6.103515625e-05, 6.103515617420877e-05},
281 {3.0517578125e-05, 3.051757811552610e-05},
282 {1.52587890625e-05, 1.525878906131576e-05},
283 {7.62939453125e-06, 7.629394531101970e-06},
284 {3.814697265625e-06, 3.814697265606496e-06},
285 {1.9073486328125e-06, 1.907348632810187e-06},
286 {9.5367431640625e-07, 9.536743164059608e-07},
287 {4.76837158203125e-07, 4.768371582030888e-07},
288 {2.384185791015625e-07, 2.384185791015580e-07},
289 {1.1920928955078125e-07, 1.192092895507807e-07},
290 {5.9604644775390625e-08, 5.960464477539055e-08},
291 {2.98023223876953125e-08, 2.980232238769530e-08},
292 {1.490116119384765625e-08, 1.490116119384765e-08},
293 {7.450580596923828125e-09, 7.450580596923828e-09},
294 {3.7252902984619140625e-09, 3.725290298461914e-09},
295 {1.86264514923095703125e-09, 1.862645149230957e-09},
296 {9.31322574615478515625e-10, 9.313225746154785e-10},
297 {4.656612873077392578125e-10, 4.656612873077393e-10},
298 {2.3283064365386962890625e-10, 2.328306436538696e-10},
299 {1.16415321826934814453125e-10, 1.164153218269348e-10},
300 {5.82076609134674072265625e-11, 5.820766091346741e-11},
301 {2.910383045673370361328125e-11, 2.910383045673370e-11},
302 {1.4551915228366851806640625e-11, 1.455191522836685e-11},
303 {7.2759576141834259033203125e-12, 7.275957614183426e-12},
304 {3.63797880709171295166015625e-12, 3.637978807091713e-12},
305 {1.818989403545856475830078125e-12, 1.818989403545856e-12},
306 {9.094947017729282379150390625e-13, 9.094947017729282e-13},
307 {4.5474735088646411895751953125e-13, 4.547473508864641e-13},
308 {2.27373675443232059478759765625e-13, 2.273736754432321e-13},
309 {1.136868377216160297393798828125e-13, 1.136868377216160e-13},
310 {5.684341886080801486968994140625e-14, 5.684341886080801e-14},
311 {2.8421709430404007434844970703125e-14, 2.842170943040401e-14},
312 {1.42108547152020037174224853515625e-14, 1.421085471520200e-14},
313 {7.10542735760100185871124267578125e-15, 7.105427357601002e-15},
314 {3.552713678800500929355621337890625e-15, 3.552713678800501e-15},
315 {1.7763568394002504646778106689453125e-15, 1.776356839400250e-15},
316 {8.8817841970012523233890533447265625e-16, 8.881784197001252e-16}
319 void doMultiple(double* operandOne
, int* powerOne
,
320 double operandTwo
, int powerTwo
);
321 void doAdd (double* operandOne
, int* powerOne
,
322 double operandTwo
, int powerTwo
);
323 void printResult(void);
324 void formatResult(void);
325 void oneOperand(void);
327 /* -----------------------------------------------------------------------
329 ----------------------------------------------------------------------- */
330 void cleartypingbuf(void)
333 for( k
=1; k
<=(DIGITLEN
+1); k
++)
336 typingbufPointer
= typingbuf
+1;
345 void clearResult(void)
352 void clearInput(void)
354 calStatus
= cal_normal
;
359 void clearOperand(void)
365 void clearMemTemp(void)
374 operInputted
= false;
386 void switchOperands(void)
388 double tempr
= operand
;
389 int tempp
= operandPower
;
391 operandPower
= power
;
396 /* -----------------------------------------------------------------------
398 ----------------------------------------------------------------------- */
399 void cal_initial (void)
402 rb
->lcd_setfont(FONT_SYSFIXED
);
403 rb
->lcd_clear_display();
406 rb
->lcd_drawrect(X_0_POS
, Y_0_POS
, LCD_WIDTH
-1, LCD_HEIGHT
);
407 rb
->lcd_drawline(X_0_POS
, Y_1_POS
-1, X_5_POS
, Y_1_POS
-1);
408 for (i
= 0; i
< 5 ; i
++)
409 rb
->lcd_drawline(X_0_POS
, Y_1_POS
+i
*REC_HEIGHT
,
410 X_5_POS
, Y_1_POS
+i
*REC_HEIGHT
);
411 for (i
= 0; i
< 4 ; i
++)
412 rb
->lcd_drawline(X_1_POS
+i
*REC_WIDTH
, Y_1_POS
,
413 X_1_POS
+i
*REC_WIDTH
, Y_6_POS
);
415 #ifdef CALCULATOR_OPERATORS
416 /* basic operators are available through separate button */
417 buttonGroup
= sciButtons
;
419 buttonGroup
= basicButtons
;
422 for (i
= 0; i
< 5; i
++){
423 for (j
= 0; j
< 5; j
++){
424 rb
->lcd_getstringsize( buttonChar
[buttonGroup
][i
][j
],&w
,&h
);
425 rb
->lcd_putsxy( X_0_POS
+ j
*REC_WIDTH
+ (REC_WIDTH
- w
)/2,
426 TEXT_2_POS
+ i
*REC_HEIGHT
,
427 buttonChar
[buttonGroup
][i
][j
] );
431 /* initially, invert button "5" */
436 rb
->lcd_set_drawmode(DRMODE_COMPLEMENT
);
437 rb
->lcd_fillrect( X_0_POS
+ n
*REC_WIDTH
+ 1,
438 Y_1_POS
+ m
*REC_HEIGHT
+ 1,
439 REC_WIDTH
- 1, REC_HEIGHT
- 1);
440 rb
->lcd_set_drawmode(DRMODE_SOLID
);
443 /* initial mem and output display*/
447 /* clear button queue */
448 rb
->button_clear_queue();
451 /* -----------------------------------------------------------------------
452 mySqrt uses Heron's algorithm, which is the Newtone-Raphson algorhitm
453 in it's private case for sqrt.
454 Thanks BlueChip for his intro text and Dave Straayer for the actual name.
455 ----------------------------------------------------------------------- */
456 double mySqrt(double square
)
460 double root
= ABS(square
+1)/2;
462 while( ABS(root
- temp
) > MINIMUM
){
464 root
= (square
/temp
+ temp
)/2;
466 if (k
>10000) return 0;
471 /* -----------------------------------------------------------------------
472 transcendFunc uses CORDIC (COordinate Rotation DIgital Computer) method
473 transcendFunc can do sin,cos,log,exp
474 input parameter is angle
475 ----------------------------------------------------------------------- */
476 void transcendFunc(char* func
, double* tt
, int* ttPower
)
478 double t
= (*tt
)*PI
/180; int tPower
= *ttPower
;
480 int n
= 50; /* n <=50, tables are all <= 50 */
482 double x
,y
,z
,xt
,yt
,zt
;
485 calStatus
= cal_normal
;
489 calStatus
= cal_error
;
493 calStatus
= cal_normal
;
495 if( func
[0] =='s' || func
[0] =='S')
498 /* if( func[0] =='c' || func[0] =='C') */
512 while (t
> j
*2*PI
) {j
++;}
514 if (PI
/2 < t
&& t
< 3*PI
/2){
516 if (func
[0] =='c' || func
[0] =='C')
519 else if ( 3*PI
/2 <= t
&& t
<= 2*PI
)
522 x
= 0.60725293500888; y
= 0; z
= t
;
524 xt
= x
- SIGN(z
) * y
*cordicTable
[j
-1][0];
525 yt
= y
+ SIGN(z
) * x
*cordicTable
[j
-1][0];
526 zt
= z
- SIGN(z
) * cordicTable
[j
-1][1];
531 if( func
[0] =='s' || func
[0] =='S') {
535 else /* if( func[0] =='c' || func[0] =='C')*/ {
541 /* -----------------------------------------------------------------------
542 add in scientific number format
543 ----------------------------------------------------------------------- */
544 void doAdd (double* operandOne
, int* powerOne
,
545 double operandTwo
, int powerTwo
)
547 if ( *powerOne
>= powerTwo
){
548 if (*powerOne
- powerTwo
<= DIGITLEN
+1){
549 while (powerTwo
< *powerOne
){
553 *operandOne
+= operandTwo
;
555 /*do nothing if operandTwo is too small*/
558 if (powerTwo
- *powerOne
<= DIGITLEN
+1){
559 while(powerTwo
> *powerOne
){
563 (*operandOne
) += operandTwo
;
565 else{/* simply copy operandTwo if operandOne is too small */
566 *operandOne
= operandTwo
;
567 *powerOne
= powerTwo
;
571 /* -----------------------------------------------------------------------
572 multiple in scientific number format
573 ----------------------------------------------------------------------- */
574 void doMultiple(double* operandOne
, int* powerOne
,
575 double operandTwo
, int powerTwo
)
577 (*operandOne
) *= operandTwo
;
578 (*powerOne
) += powerTwo
;
581 /* -----------------------------------------------------------------------
582 Handles all one operand calculations
583 ----------------------------------------------------------------------- */
584 void oneOperand(void)
587 if (buttonGroup
== basicButtons
){
591 calStatus
= cal_error
;
594 result
= (mySqrt(result
*10))/10;
595 power
= (power
+1) / 2;
598 result
= mySqrt(result
);
601 calStatus
= cal_normal
;
607 calStatus
= cal_normal
;
612 calStatus
= cal_error
;
616 calStatus
= cal_normal
;
620 calStatus
= cal_toDo
;
621 break; /* just for the safety */
624 else{ /* sciButtons */
627 transcendFunc("sin", &result
, &power
);
630 transcendFunc("cos", &result
, &power
);
633 if (power
<0 || power
>8 || result
<0 )
634 calStatus
= cal_error
;
635 else if(result
== 0) {
644 if ( ( result
- (int)result
) > MINIMUM
)
645 calStatus
= cal_error
;
647 k
= result
; result
= 1;
649 doMultiple(&result
, &power
, k
, 0);
653 calStatus
= cal_normal
;
658 calStatus
= cal_toDo
;
659 break; /* just for the safety */
665 /* -----------------------------------------------------------------------
666 Handles all two operands calculations
667 ----------------------------------------------------------------------- */
668 void twoOperands(void)
672 doAdd(&operand
, &operandPower
, -result
, power
);
675 doAdd(&operand
, &operandPower
, result
, power
);
678 doMultiple(&operand
, &operandPower
, result
, power
);
681 if ( ABS(result
) > MINIMUM
){
682 doMultiple(&operand
, &operandPower
, 1/result
, -power
);
685 calStatus
= cal_error
;
688 switchOperands(); /* counter switchOperands() below */
694 /* -----------------------------------------------------------------------
696 Invert display new button, invert back previous button
697 ----------------------------------------------------------------------- */
698 void moveButton(void){
701 case BUTTON_LEFT
| BUTTON_REPEAT
:
709 case BUTTON_RIGHT
| BUTTON_REPEAT
:
717 case CALCULATOR_UP
| BUTTON_REPEAT
:
724 case CALCULATOR_DOWN
:
725 case CALCULATOR_DOWN
| BUTTON_REPEAT
:
733 rb
->lcd_set_drawmode(DRMODE_COMPLEMENT
);
734 rb
->lcd_fillrect( X_0_POS
+ prev_n
*REC_WIDTH
+ 1,
735 Y_1_POS
+ prev_m
*REC_HEIGHT
+ 1,
736 REC_WIDTH
- 1, REC_HEIGHT
- 1);
738 rb
->lcd_fillrect( X_0_POS
+ n
*REC_WIDTH
+ 1,
739 Y_1_POS
+ m
*REC_HEIGHT
+ 1,
740 REC_WIDTH
- 1, REC_HEIGHT
- 1);
741 rb
->lcd_set_drawmode(DRMODE_SOLID
);
743 rb
->lcd_update_rect( X_0_POS
+ prev_n
*REC_WIDTH
+ 1,
744 Y_1_POS
+ prev_m
*REC_HEIGHT
+ 1,
745 REC_WIDTH
- 1, REC_HEIGHT
- 1);
747 rb
->lcd_update_rect( X_0_POS
+ n
*REC_WIDTH
+ 1,
748 Y_1_POS
+ m
*REC_HEIGHT
+ 1,
749 REC_WIDTH
- 1, REC_HEIGHT
- 1);
754 /* -----------------------------------------------------------------------
755 Print buttons when switching 1st and 2nd
756 int group = {basicButtons, sciButtons}
757 ----------------------------------------------------------------------- */
758 void printButtonGroups(int group
)
761 for (i
= 0; i
< 5; i
++){
762 for (j
= 3; j
<= 4; j
++){
763 rb
->lcd_getstringsize( buttonChar
[group
][i
][j
],&w
,&h
);
764 rb
->lcd_set_drawmode(DRMODE_SOLID
|DRMODE_INVERSEVID
);
765 rb
->lcd_fillrect( X_0_POS
+ j
*REC_WIDTH
+ 1,
766 Y_1_POS
+ i
*REC_HEIGHT
+ 1,
767 REC_WIDTH
- 1, REC_HEIGHT
- 1);
768 rb
->lcd_set_drawmode(DRMODE_SOLID
);
769 rb
->lcd_putsxy( X_0_POS
+ j
*REC_WIDTH
+ (REC_WIDTH
- w
)/2,
770 TEXT_2_POS
+ i
*REC_HEIGHT
,
771 buttonChar
[group
][i
][j
] );
774 for (i
= 0; i
<= 0; i
++){
775 for (j
= 0; j
<= 2; j
++){
776 rb
->lcd_getstringsize( buttonChar
[group
][i
][j
],&w
,&h
);
777 rb
->lcd_set_drawmode(DRMODE_SOLID
|DRMODE_INVERSEVID
);
778 rb
->lcd_fillrect( X_0_POS
+ j
*REC_WIDTH
+ 1,
779 Y_1_POS
+ i
*REC_HEIGHT
+ 1,
780 REC_WIDTH
- 1, REC_HEIGHT
- 1);
781 rb
->lcd_set_drawmode(DRMODE_SOLID
);
782 rb
->lcd_putsxy( X_0_POS
+ j
*REC_WIDTH
+ (REC_WIDTH
- w
)/2,
783 TEXT_2_POS
+ i
*REC_HEIGHT
,
784 buttonChar
[group
][i
][j
] );
787 rb
->lcd_set_drawmode(DRMODE_COMPLEMENT
);
788 rb
->lcd_fillrect( X_0_POS
+ 2*REC_WIDTH
+ 1,
789 Y_1_POS
+ 0*REC_HEIGHT
+ 1,
790 REC_WIDTH
- 1, REC_HEIGHT
- 1);
791 rb
->lcd_set_drawmode(DRMODE_SOLID
);
792 rb
->lcd_update_rect( X_0_POS
, Y_1_POS
,
793 REC_WIDTH
*5, REC_HEIGHT
*5);
795 /* -----------------------------------------------------------------------
796 flash the button pressed
797 ----------------------------------------------------------------------- */
798 void flashButton(int b
)
800 int i
= b
/5; int j
= b
- i
*5;
802 rb
->lcd_set_drawmode(DRMODE_COMPLEMENT
);
804 rb
->lcd_fillrect( X_0_POS
+ j
*REC_WIDTH
+ 1,
805 Y_1_POS
+ i
*REC_HEIGHT
+ 1,
806 REC_WIDTH
- 1, REC_HEIGHT
- 1);
807 rb
->lcd_update_rect( X_0_POS
+ j
*REC_WIDTH
+ 1,
808 Y_1_POS
+ i
*REC_HEIGHT
+ 1,
809 REC_WIDTH
- 1, REC_HEIGHT
- 1);
815 rb
->lcd_set_drawmode(DRMODE_SOLID
);
818 /* -----------------------------------------------------------------------
819 pos is the position that needs animation. pos = [1~18]
820 ----------------------------------------------------------------------- */
821 void deleteAnimation(int pos
)
824 if (pos
<1 || pos
>18)
827 rb
->lcd_fillrect(1+pos
*6, TEXT_1_POS
, 6, 8);
828 rb
->lcd_update_rect(1+pos
*6, TEXT_1_POS
, 6, 8);
832 rb
->lcd_set_drawmode(DRMODE_SOLID
|DRMODE_INVERSEVID
);
833 rb
->lcd_fillrect(1+pos
*6, TEXT_1_POS
, 6, 8);
834 rb
->lcd_set_drawmode(DRMODE_SOLID
);
835 rb
->lcd_fillrect(1+pos
*6+1+k
, TEXT_1_POS
+k
,
836 (5-2*k
)>0?(5-2*k
):1, (7-2*k
)>0?(7-2*k
):1 );
837 rb
->lcd_update_rect(1+pos
*6, TEXT_1_POS
, 6, 8);
842 /* -----------------------------------------------------------------------
843 result may be one of these formats:
849 formatResult() change result to standard format: 0.xxxx
850 if result is close to 0, let it be 0;
851 if result is close to 1, let it be 0.1 and power++;
852 ----------------------------------------------------------------------- */
853 void formatResult(void)
855 int resultsign
= SIGN(result
);
856 result
= ABS(result
);
857 if(result
> MINIMUM
){ /* doesn't check power, might have problem
859 + - * / of two formatted number wouldn't.
860 only a calculation that makes a formatted
861 number (0.xxxx) less than MINIMUM in only
865 while( (int)(result
*10) == 0 ){
871 else{ /* result >= 1 */
872 while( (int)result
!= 0 ){
879 if (result
> (1-MINIMUM
)){
884 result
*= resultsign
;
893 /* -----------------------------------------------------------------------
894 result2typingbuf() outputs standard format result to typingbuf.
895 case SCIENTIFIC_FORMAT, let temppower = 1;
896 case temppower > 0: print '.' in the middle
897 case temppower <= 0: print '.' in the begining
898 ----------------------------------------------------------------------- */
899 void result2typingbuf(void)
901 bool haveDot
= false;
904 double tempresult
= ABS(result
); /* positive num makes things simple */
907 double tempmodifier
= 1;
910 if(SCIENTIFIC_FORMAT
)
911 temppower
= 1; /* output x.xxxx format */
917 if(tempresult
< MINIMUM
){ /* if 0,faster display and avoid complication*/
921 else{ /* tempresult > 0 */
922 typingbuf
[0] = (SIGN(result
)<0)?'-':' ';
924 typingbufPointer
= typingbuf
;
926 for (k
= 0; k
<DIGITLEN
+1 ; k
++){
928 if(temppower
|| *(typingbufPointer
-1) == '.'){
930 tempmodifier
= tempmodifier
/10;
931 while( (tempresult
-tempmodifier
*count
) >
932 (tempmodifier
-MINIMUM
)){
935 tempresult
-= tempmodifier
*count
;
936 tempresult
= ABS(tempresult
);
938 *typingbufPointer
= count
+ '0';
940 else{ /* temppower == 0 */
941 *typingbufPointer
= '.';
948 typingbufPointer
++; *typingbufPointer
= '0';
949 typingbufPointer
++; *typingbufPointer
= '.';
950 for (k
= 2; k
<DIGITLEN
+1 ; k
++){
953 if ( (-temppower
) < (k
-1)){
954 tempmodifier
= tempmodifier
/10;
955 while((tempresult
-tempmodifier
*count
)>(tempmodifier
-MINIMUM
)){
959 tempresult
-= tempmodifier
*count
;
960 tempresult
= ABS(tempresult
);
963 *typingbufPointer
= count
+ '0';
966 /* now, typingbufPointer = typingbuf + 16 */
967 /* backward strip off 0 and '.' */
969 while( (*typingbufPointer
== '0') || (*typingbufPointer
== '.')){
970 tempchar
= *typingbufPointer
;
971 *typingbufPointer
= 0;
973 if (tempchar
== '.') break;
976 typingbuf
[DIGITLEN
+1] = 0;
977 } /* else tempresult > 0 */
980 /* -----------------------------------------------------------------------
981 printResult() generates LCD display.
982 ----------------------------------------------------------------------- */
983 void printResult(void)
990 rb
->lcd_clear_display();
991 rb
->splash(HZ
/3, true, "Bye now!");
995 rb
->snprintf(buf
, 19, "%18s","Error");
999 rb
->snprintf(buf
, 19, "%18s","Coming soon ^_* ");
1005 if( power
> 1000 ){ /* power -1 > 999 */
1006 calStatus
= cal_error
;
1009 if (power
< -998 ) /* power -1 < -999 */
1010 clearResult(); /* too small, let it be 0 */
1016 buf
[1] = ( ABS(memTemp
) > MINIMUM
)?'M':' ';
1019 if(SCIENTIFIC_FORMAT
){
1020 /* output format: X.XXXX eXXX */
1021 if(power
> -98){ /* power-1 >= -99, eXXX or e-XX */
1022 rb
->snprintf(buf
+3, 12, "%11s",typingbuf
);
1023 for(k
=14;k
<=17;k
++) buf
[k
] = ' ';
1025 rb
->snprintf(typingbuf
, 5, "e%d",power
-1);
1026 rb
->snprintf(buf
+14, 5, "%4s",typingbuf
);
1028 else{ /* power-1 <= -100, e-XXX */
1029 rb
->snprintf(buf
+2, 12, "%11s",typingbuf
);
1030 rb
->snprintf(buf
+13, 6, "e%d",power
-1);
1034 rb
->snprintf(buf
+7, 12, "%11s",typingbuf
);
1035 } /* if SCIENTIFIC_FORMAT */
1041 buf
[1] = ( ABS(memTemp
) > MINIMUM
)?'M':' ';
1044 rb
->snprintf(buf
+7, 12, "%11s",typingbuf
);
1049 rb
->lcd_putsxy(1, TEXT_1_POS
,buf
);
1050 rb
->lcd_update_rect(1, TEXT_1_POS
, 6*18, 8);
1053 /* -----------------------------------------------------------------------
1054 Process typing buttons: 1-9, '.', sign
1055 main operand "result" and typingbuf are processed seperately here.
1056 ----------------------------------------------------------------------- */
1057 void typingProcess(void){
1058 switch( CAL_BUTTON
){
1060 if (calStatus
== cal_typing
||
1061 calStatus
== cal_dotted
)
1062 typingbuf
[0] = (typingbuf
[0]=='-')?' ':'-';
1066 operInputted
= false;
1070 *typingbufPointer
= '0';
1073 calStatus
= cal_dotted
;
1074 *typingbufPointer
= '.';
1075 if (typingbufPointer
!= typingbuf
+DIGITLEN
+1)
1078 default: /* cal_dotted */
1083 operInputted
= false;
1084 /* normal,0; normal,1-9; typing,0; typing,1-9 */
1087 if(CAL_BUTTON
== btn_0
)
1088 break; /* first input is 0, ignore */
1090 /*no operator means start a new calculation*/
1093 calStatus
= cal_typing
;
1094 /* go on typing, no break */
1099 *typingbufPointer
= '0';
1102 *typingbufPointer
=(7+n
-3*(m
-1))+ '0';
1105 if (typingbufPointer
!=typingbuf
+DIGITLEN
+1){
1108 {/* result processing */
1109 if (calStatus
== cal_typing
) power
++;
1110 if (CAL_BUTTON
!= btn_0
)
1113 (7+n
-3*(m
-1))*modifier
;
1117 else /* last byte always '\0' */
1118 *typingbufPointer
= 0;
1120 default: /* cal_error, cal_exit */
1123 break; /* default, 0-9 */
1124 } /* switch( CAL_BUTTON ) */
1127 /* -----------------------------------------------------------------------
1128 Handle delete operation
1129 main operand "result" and typingbuf are processed seperately here.
1130 ----------------------------------------------------------------------- */
1131 void doDelete(void){
1132 deleteAnimation(18);
1135 if (*(typingbufPointer
-1) == '.'){
1136 /* if dotted and deleting '.',
1137 change status and delete '.' below */
1138 calStatus
= cal_typing
;
1140 else{ /* if dotted and not deleting '.',
1142 power
++; /* counter "power--;" below */
1147 {/* result processing */ /* 0-9, '.' */
1148 /* if deleting '.', do nothing */
1149 if ( *typingbufPointer
!= '.'){
1152 result
= result
- SIGN(result
)*
1153 ((*typingbufPointer
)- '0')*modifier
;
1157 *typingbufPointer
= 0;
1159 /* if (only one digit left and it's 0)
1160 or no digit left, change status*/
1161 if ( typingbufPointer
== typingbuf
+1 ||
1162 ( typingbufPointer
== typingbuf
+2 &&
1163 *(typingbufPointer
-1) == '0' ))
1164 calStatus
= cal_normal
;
1166 default: /* normal, error, exit */
1170 /* -----------------------------------------------------------------------
1171 Handle buttons on basic screen
1172 ----------------------------------------------------------------------- */
1173 void basicButtonsProcess(void){
1175 case CALCULATOR_INPUT
:
1176 if (calStatus
== cal_error
&& (CAL_BUTTON
!= btn_C
) ) break;
1177 flashButton(CAL_BUTTON
);
1178 switch( CAL_BUTTON
){
1180 operInputted
= false;
1181 result
= memTemp
; power
= memTempPower
;
1182 calStatus
= cal_normal
;
1186 if (memTemp
> MINIMUM
)
1187 doAdd(&memTemp
, &memTempPower
, result
, power
);
1189 /* if result is too small and memTemp = 0,
1190 doAdd will not add */
1192 memTempPower
= power
;
1194 calStatus
= cal_normal
;
1197 case btn_C
: clearMem(); break;
1198 case btn_CE
: clearInput(); break;
1201 buttonGroup
= sciButtons
;
1202 printButtonGroups(buttonGroup
);
1205 /* one operand calculation, may be changed to
1206 like sin, cos, log, etc */
1210 formatResult(); /* not necessary, just for safty */
1214 case_btn_equal
: /* F3 shortkey entrance */
1217 calStatus
= cal_normal
;
1218 operInputted
= false;
1219 if (oper
!= ' ') twoOperands();
1226 if(!operInputted
) {twoOperands(); operInputted
= true;}
1227 oper
= buttonChar
[basicButtons
][m
][n
][0];
1228 #ifdef CALCULATOR_OPERATORS
1229 case_cycle_operators
: /* F2 shortkey entrance */
1231 calStatus
= cal_normal
;
1234 operandPower
= power
;
1243 } /* switch (CAL_BUTTON) */
1246 #ifdef CALCULATOR_OPERATORS
1247 case CALCULATOR_OPERATORS
:
1248 if (calStatus
== cal_error
) break;
1249 if (!operInputted
) {twoOperands(); operInputted
= true;}
1252 case '/': oper
= '+'; flashButton(btn_add
); break;
1253 case '+': oper
= '-'; flashButton(btn_minus
); break;
1254 case '-': oper
= '*'; flashButton(btn_time
); break;
1255 case '*': oper
= '/'; flashButton(btn_div
); break;
1257 goto case_cycle_operators
;
1261 case CALCULATOR_CALC
:
1262 if (calStatus
== cal_error
) break;
1263 flashButton(btn_equal
);
1264 goto case_btn_equal
;
1271 /* -----------------------------------------------------------------------
1272 Handle buttons on scientific screen
1273 ----------------------------------------------------------------------- */
1274 void sciButtonsProcess(void){
1276 case CALCULATOR_INPUT
:
1277 if (calStatus
== cal_error
&& (CAL_BUTTON
!= sci_sci
) ) break;
1278 flashButton(CAL_BUTTON
);
1279 switch( CAL_BUTTON
){
1282 result
= PI
; power
= 0;
1283 calStatus
= cal_normal
;
1289 buttonGroup
= basicButtons
;
1290 printButtonGroups(basicButtons
);
1303 formatResult(); /* not necessary, just for safty */
1312 } /* switch (CAL_BUTTON) */
1315 #ifdef CALCULATOR_OPERATORS
1316 case CALCULATOR_OPERATORS
:
1317 if (calStatus
== cal_error
) break;
1318 if (!operInputted
) {twoOperands(); operInputted
= true;}
1320 case ' ': oper
= '+'; break;
1321 case '/': oper
= '+'; deleteAnimation(1); break;
1322 case '+': oper
= '-'; deleteAnimation(1); break;
1323 case '-': oper
= '*'; deleteAnimation(1); break;
1324 case '*': oper
= '/'; deleteAnimation(1); break;
1326 calStatus
= cal_normal
;
1329 operandPower
= power
;
1333 case CALCULATOR_CALC
:
1334 if (calStatus
== cal_error
) break;
1336 calStatus
= cal_normal
;
1337 operInputted
= false;
1338 if (oper
!= ' ') twoOperands();
1345 /* -----------------------------------------------------------------------
1347 ----------------------------------------------------------------------- */
1348 enum plugin_status
plugin_start(struct plugin_api
* api
, void* parameter
)
1353 /* now go ahead and have fun! */
1357 while (calStatus
!= cal_exit
) {
1358 btn
= rb
->button_get_w_tmo(HZ
/2);
1360 case CALCULATOR_INPUT
:
1361 case CALCULATOR_CALC
:
1362 #ifdef CALCULATOR_INPUT_CALC_PRE
1363 if (lastbtn
!= CALCULATOR_INPUT_CALC_PRE
)
1365 /* no unconditional break; here! */
1367 #ifdef CALCULATOR_OPERATORS
1368 case CALCULATOR_OPERATORS
:
1370 switch(buttonGroup
){
1372 basicButtonsProcess();
1375 sciButtonsProcess();
1380 #ifdef CALCULATOR_CLEAR
1381 case CALCULATOR_CLEAR
:
1387 default: /* cal_normal, cal_error, cal_exit */
1396 case BUTTON_LEFT
| BUTTON_REPEAT
:
1398 case BUTTON_RIGHT
| BUTTON_REPEAT
:
1400 case CALCULATOR_UP
| BUTTON_REPEAT
:
1401 case CALCULATOR_DOWN
:
1402 case CALCULATOR_DOWN
| BUTTON_REPEAT
:
1405 case CALCULATOR_QUIT
:
1406 calStatus
= cal_exit
;
1410 if(rb
->default_event_handler(btn
) == SYS_USB_CONNECTED
)
1411 return PLUGIN_USB_CONNECTED
;
1413 } /* switch (btn) */
1414 if (btn
!= BUTTON_NONE
)
1416 } /* while (calStatus != cal_exit ) */
1418 /* rb->splash(HZ*2, true, "Hello world!"); */
1419 rb
->button_clear_queue();
1423 #endif /* #ifdef HAVE_LCD_BITMAP */