Add 2008 to the copyright notice.
[Rockbox.git] / apps / plugins / euroconverter.c
blob224fb857035ada6385845078c965ec2b442db053
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2003 Pierre Delore
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 ****************************************************************************/
19 #include "plugin.h"
20 #include "configfile.h"
22 #ifdef HAVE_LCD_CHARCELLS
24 /* Euro converter for the player */
26 Use:
27 + : Digit +1
28 - : Digit -1
29 PLAY : Next digit
30 STOP : Prev digit
31 ON : RESET
32 ON+PLAY : Swap Euro<>Home
33 MENU : Display the Menu
34 Currency -> Allows to choose the currency
35 Exit-> Exit the plugin
37 Notes:
38 I don't use float.
39 I use signed long long (64 bits).
40 A value have 5 digits after the . (123.45 = 12345000)
42 To do:
43 - The Irish currency needs 6 digits after the . to have sufficient precision on big number
46 PLUGIN_HEADER
48 /* Name and path of the config file*/
49 static const char cfg_filename[] = "euroconverter.cfg";
50 #define CFGFILE_VERSION 0 /* Current config file version */
51 #define CFGFILE_MINVERSION 0 /* Minimum config file version to accept */
53 /* typedef for simplifying usage of long long type */
54 typedef long long int longlong_t;
56 /*Pattern for the converter*/
57 static unsigned char pattern_euro[]={0x07, 0x08, 0x1E, 0x10, 0x1E, 0x08, 0x07}; /* € */
58 static unsigned char pattern_home[]={0x04, 0x0A, 0x11, 0x1F, 0x11, 0x11, 0x1F}; /* Home icon*/
60 /* 1 euro = ... (remenber 5 digits after the .)*/
61 static int currency[12]={
62 655957, /*FRF France*/
63 195583, /*DEM Germany*/
64 1376030, /*ATS Austria*/
65 4033990, /*BEF Belgium*/
66 16638600, /*ESP Spain*/
67 594573, /*FIM Finland*/
68 78756, /*IEP Ireland*/
69 193627000, /*ITL Italy*/
70 4033990, /*LUF Luxemburg*/
71 220371, /*NLG Netherlands*/
72 20048200, /*PTE Portugal*/
73 34075100, /*GRD Greece*/
76 /* Number of digit of the currency (for the display) */
77 static int nb_digit[12]={
78 2, /*FRF France*/
79 2, /*DEM Germany*/
80 2, /*ATS Austria*/
81 2, /*BEF Belgium*/
82 0, /*ESP Spain*/
83 2, /*FIM Finland*/
84 2, /*IEP Ireland*/
85 0, /*ITL Italy*/
86 2, /*LUF Luxemburg*/
87 2, /*NLG Netherlands*/
88 0, /*PTE Portugal*/
89 0 /*GRD Greece*/
92 /* max euro to have home currency */
93 static longlong_t max_euro[12]={
94 99999999000LL, /*FRF France 999 999.99 */
95 99999999000LL, /*DEM Germany 999 999.99 */
96 99999999000LL, /*ATS Austria 999 999.99 */
97 99999999000LL, /*BEF Belgium 999 999.99 */
98 99999999000LL, /*ESP Spain 99 999 999 */
99 99999999000LL, /*FIM Finland 999 999.99 */
100 99999999000LL, /*IEP Ireland 999 999.99 */
101 51645690000LL, /*ITL Italy 999 999 999 */
102 99999999000LL, /*LUF Luxemburg 999 999.99 */
103 99999999000LL, /*NLG Netherlands 999 999.99 */
104 99999999000LL, /*PTE Portugal 99 999 999 */
105 29347028000LL /*GRD Greece 99 999 999 */
108 /* max home to have euro currency */
109 /* 92233720300000 Limitation due to the max capacity of long long (2^63)*/
110 static longlong_t max_curr[12]={
111 99999999000LL, /*FRF France 152449.02 */
112 99999999000LL, /*DEM Germany 511291.88 */
113 99999999000LL, /*ATS Austria 72672.83 */
114 99999999000LL, /*BEF Belgium 24789.35 */
115 92233720300000LL,/*ESP Spain 5543358.23 */
116 99999999000LL, /*FIM Finland 168187.92 */
117 9999999900LL, /*IEP Ireland 1269744.51 exact value=1269738.07 */
118 92233720300000LL,/*ITL Italy 476347.41 */
119 99999999000LL, /*LUF Luxemburg 24789.35 */
120 99999999000LL, /*NLG Netherlands 453780.21 */
121 92233720300000LL,/*PTE Portugal 4600598.57 */
122 92233720300000LL /*GRD Greece 2706777.69 */
125 static unsigned char *abbrev_str[12] = {
126 "...FRF...", /*France*/
127 "...DEM...", /*Germany*/
128 "...ATS...", /*Austria*/
129 "...BEF...", /*Belgium*/
130 "...ESP...", /*Spain*/
131 "...FIM...", /*Finland*/
132 "...IEP...", /*Ireland*/
133 "...ITL...", /*Italy*/
134 "...LUF...", /*Luxemburg*/
135 "...NLG...", /*Netherlands*/
136 "...PTE...", /*Portugal*/
137 "...GRD..." /*Greece*/
141 static unsigned long heuro,hhome; /*Handles for the new patterns*/
143 static struct plugin_api* rb;
145 static char *currency_str[12] = {
146 "France",
147 "Germany",
148 "Austria",
149 "Belgium",
150 "Spain",
151 "Finland",
152 "Ireland",
153 "Italy",
154 "Luxemburg",
155 "Netherlands",
156 "Portugal",
157 "Greece"
161 static int country; /*Country selected*/
162 static int cur_pos; /*Cursor position*/
163 static longlong_t inc;
165 /* Persistent settings */
166 static struct configdata config[] = {
167 { TYPE_ENUM, 0, 12, &country, "country", currency_str, NULL }
171 /* 64bits*64 bits with 5 digits after the . */
172 static longlong_t mymul(longlong_t a, longlong_t b)
174 return((a*b)/100000LL);
178 /* 64bits/64 bits with 5 digits after the . */
179 static longlong_t mydiv(longlong_t a, longlong_t b)
181 return((a*100000LL)/b);
185 /* 123.45=12345000 split => i=123 f=45000*/
186 static void split(longlong_t v, longlong_t* i, longlong_t* f)
188 longlong_t t;
190 t=v/100000LL;
191 (*i)=t;
192 (*f)=(v-(t*100000LL));
196 /* result=10^n */
197 static longlong_t pow10(int n)
199 int i;
200 longlong_t r;
202 r=1;
203 for (i=0;i<n;i++)
204 r=r*10LL;
205 return(r);
209 /* round the i.f at n digit after the . */
210 static void round(longlong_t* i, longlong_t* f, int n)
213 longlong_t m;
214 int add=0;
216 m=(int)pow10(5-n-1);
217 if (((*f)/m)%10>=5)
218 add=1;
219 if (n>0)
221 (*f)=((*f)/(int)pow10(5-n))+add;
222 if ((*f)==100LL)
224 (*i)+=1;
225 (*f)=0;
228 else
230 (*i)+=add;
231 (*f)=0;
236 /* Display the imput and the result
237 pos: false : first line
238 : true : second line
240 static void display(longlong_t euro, longlong_t home, bool pos)
242 longlong_t i,f;
243 unsigned char str[20];
244 unsigned char s1[20];
245 unsigned char s2[20];
247 if (pos)
248 { /*Edit the second line*/
249 rb->strcpy(s1," %6d.%02d");
250 if (nb_digit[country]==2)
251 rb->strcpy(s2,"\xee\x84\x90%06d.%02d");
252 else
253 rb->strcpy(s2,"\xee\x84\x90%09d");
255 else
257 rb->strcpy(s1,"\xee\x84\x90%06d.%02d");
258 if (nb_digit[country]==2)
259 rb->strcpy(s2," %6d.%02d");
260 else
261 rb->strcpy(s2," %9d");
264 rb->lcd_remove_cursor();
265 /*First line*/
266 rb->lcd_putc(0,0,heuro);
267 split(euro,&i,&f);
268 if (pos)
269 round(&i,&f,2);
270 rb->snprintf(str,sizeof(str),s1,(int)i,(int)f);
272 if (!pos)
274 rb->lcd_puts(1,0,str);
275 rb->lcd_put_cursor(10-cur_pos,0,0x5F);
277 else
278 rb->lcd_puts_scroll(1,0,str);
280 /*Second line*/
281 rb->lcd_putc(0,1,hhome);
282 split(home,&i,&f);
283 if (!pos)
284 round(&i,&f,nb_digit[country]);
285 rb->snprintf(str,sizeof(str),s2,(int)i,(int)f);
286 if (pos)
288 rb->lcd_puts(1,1,str);
289 rb->lcd_put_cursor(10-cur_pos,1,0x5F);
291 else
292 rb->lcd_puts_scroll(1,1,str);
294 rb->lcd_update();
298 /* Show country Abbreviation */
299 static void show_abbrev(void)
301 rb->splash(HZ*3/4,abbrev_str[country]);
305 /* Save the config to disk */
306 static void save_config(void)
308 configfile_save(cfg_filename, config, 1, CFGFILE_VERSION);
312 /* Load the config from disk */
313 static void load_config(void)
315 configfile_load(cfg_filename, config, 1, CFGFILE_MINVERSION);
319 /*Currency choice*/
320 static void currency_menu(void)
322 int c=country;
324 rb->lcd_clear_display();
325 while (true)
327 rb->lcd_puts(0,0,"Currency:");
328 rb->lcd_puts(0,1,currency_str[c]);
329 rb->lcd_update();
330 switch (rb->button_get(true))
332 case BUTTON_RIGHT|BUTTON_REL:
333 c++;
334 if (c>11)
335 c=0;
336 break;
337 case BUTTON_LEFT|BUTTON_REL:
338 c--;
339 if (c<0)
340 c=11;
341 break;
342 case BUTTON_PLAY|BUTTON_REL:
343 country=c;
344 save_config();
345 return;
346 break;
347 case BUTTON_STOP|BUTTON_REL:
348 return;
354 /* Display the choice menu. */
355 static int euro_menu(void)
357 int c=0;
360 while (true)
362 rb->lcd_clear_display();
363 rb->lcd_puts(0,0," Currency");
364 rb->lcd_puts(0,1," Exit");
365 rb->lcd_putc(0,c,0xe110);
366 rb->lcd_update();
368 switch (rb->button_get(true))
370 case BUTTON_RIGHT|BUTTON_REL:
371 c=1;
372 break;
373 case BUTTON_LEFT|BUTTON_REL:
374 c=0;
375 break;
376 case BUTTON_PLAY|BUTTON_REL:
377 if (c==0)
378 currency_menu();
379 else
380 return 1;
381 break;
382 case BUTTON_STOP|BUTTON_REL:
383 return 0;
389 /* Call when the program end */
390 static void euro_exit(void *parameter)
392 (void)parameter;
394 //Restore the old pattern (i don't find another way to do this. An idea?)
395 rb->lcd_unlock_pattern(heuro);
396 rb->lcd_unlock_pattern(hhome);
398 //Clear the screen
399 rb->lcd_clear_display();
400 rb->lcd_update();
404 /* this is the plugin entry point */
405 enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
407 bool end, pos;
408 longlong_t e,h,old_e,old_h;
409 int button;
411 /* if you don't use the parameter, you can do like
412 this to avoid the compiler warning about it */
413 (void)parameter;
415 /* if you are using a global api pointer, don't forget to copy it!
416 otherwise you will get lovely "I04: IllInstr" errors... :-) */
417 rb = api;
419 /*Get the pattern handle*/
420 heuro=rb->lcd_get_locked_pattern();
421 hhome=rb->lcd_get_locked_pattern();
422 rb->lcd_define_pattern(heuro, pattern_euro);
423 rb->lcd_define_pattern(hhome, pattern_home);
425 h=0;
426 e=0;
427 end=false;
428 pos=false;
429 country=0;
430 cur_pos=3;
431 inc=100000;
433 configfile_init(rb);
435 load_config();
437 /*Empty the event queue*/
438 rb->button_clear_queue();
440 display(e,h,false);
441 show_abbrev();
442 display(e,h,false);
444 /*Main loop*/
445 while(end!=true)
447 button = rb->button_get(true);
448 switch (button)
450 case BUTTON_MENU|BUTTON_REL:
451 switch (euro_menu())
453 case 1:
454 end=true;
455 break;
457 if (!pos)
459 if (e>max_euro[country])
460 e=0;
461 cur_pos=3;
463 else
465 if (h>max_curr[country])
466 h=0;
467 if (nb_digit[country]==2)
468 cur_pos=3;
469 else
470 cur_pos=0;
473 display(e,h,pos);
474 break;
476 case BUTTON_ON | BUTTON_PLAY:
477 pos=!pos;
479 case BUTTON_ON | BUTTON_REL:
480 e=0;
481 h=0;
482 if (!pos)
484 cur_pos=3;
485 inc=100000;
487 else
489 inc=100000;
490 if (nb_digit[country]==2)
491 cur_pos=3;
492 else
493 cur_pos=0;
495 show_abbrev();
496 break;
498 case BUTTON_STOP|BUTTON_REL:
499 cur_pos--;
500 if (!pos)
502 if (cur_pos<0)
503 cur_pos=0;
504 if (cur_pos==2)
505 cur_pos=1;
506 if (cur_pos>2)
507 inc=pow10(3+cur_pos-1);
508 else
509 inc=pow10(3+cur_pos);
511 else
513 if (cur_pos<0)
514 cur_pos=0;
515 if (nb_digit[country]==2)
517 if (cur_pos==2)
518 cur_pos=1;
519 if (cur_pos>2)
520 inc=pow10(3+cur_pos-1);
521 else
522 inc=pow10(3+cur_pos);
524 else
525 inc=pow10(5+cur_pos);
528 break;
530 case BUTTON_PLAY|BUTTON_REL:
531 cur_pos++;
532 if (!pos)
534 if (cur_pos>8)
535 cur_pos=8;
536 if (cur_pos==2)
537 cur_pos=3;
538 if (cur_pos>2)
539 inc=pow10(3+cur_pos-1);
540 else
541 inc=pow10(3+cur_pos);
543 else
545 if (cur_pos>8)
546 cur_pos=8;
547 if (nb_digit[country]==2)
549 if (cur_pos==2)
550 cur_pos=3;
551 if (cur_pos>2)
552 inc=pow10(3+cur_pos-1);
553 else
554 inc=pow10(3+cur_pos);
556 else
557 inc=pow10(5+cur_pos);
559 break;
561 case BUTTON_LEFT|BUTTON_REL:
562 case BUTTON_LEFT|BUTTON_REPEAT:
563 if (!pos)
565 e-=inc;
566 if (e<0)
567 e=0;
569 else
571 h-=inc;
572 if (h<0)
573 h=0;
575 break;
577 case BUTTON_RIGHT|BUTTON_REL:
578 case BUTTON_RIGHT|BUTTON_REPEAT:
579 old_e=e;
580 old_h=h;
581 if (!pos)
583 e+=inc;
584 if (e>max_euro[country])
585 e=old_e;
587 else
589 h+=inc;
590 if (h>max_curr[country])
591 h=old_h;
593 break;
595 default:
596 if (rb->default_event_handler_ex(button, euro_exit, NULL)
597 == SYS_USB_CONNECTED)
598 return PLUGIN_USB_CONNECTED;
599 break;
601 /*Display*/
602 if (!pos) /*Euro>home*/
603 h=mymul(e,currency[country]);
604 else /*Home>euro*/
605 e=mydiv(h,currency[country]);
606 display(e,h,pos);
608 euro_exit(NULL);
609 return PLUGIN_OK;
612 #endif