New makefile solution: A single invocation of 'make' to build the entire tree. Fully...
[kugel-rb.git] / apps / plugins / euroconverter.c
blob02617abc39db44b89c15f50653e4d2fbd97d8505
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2003 Pierre Delore
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
21 #include "plugin.h"
22 #include "lib/configfile.h"
24 #ifdef HAVE_LCD_CHARCELLS
26 /* Euro converter for the player */
28 Use:
29 + : Digit +1
30 - : Digit -1
31 PLAY : Next digit
32 STOP : Prev digit
33 ON : RESET
34 ON+PLAY : Swap Euro<>Home
35 MENU : Display the Menu
36 Currency -> Allows to choose the currency
37 Exit-> Exit the plugin
39 Notes:
40 I don't use float.
41 I use signed long long (64 bits).
42 A value have 5 digits after the . (123.45 = 12345000)
44 To do:
45 - The Irish currency needs 6 digits after the . to have sufficient precision on big number
48 PLUGIN_HEADER
50 /* Name and path of the config file*/
51 static const char cfg_filename[] = "euroconverter.cfg";
52 #define CFGFILE_VERSION 0 /* Current config file version */
53 #define CFGFILE_MINVERSION 0 /* Minimum config file version to accept */
55 /* typedef for simplifying usage of long long type */
56 typedef long long int longlong_t;
58 /*Pattern for the converter*/
59 static unsigned char pattern_euro[]={0x07, 0x08, 0x1E, 0x10, 0x1E, 0x08, 0x07}; /* € */
60 static unsigned char pattern_home[]={0x04, 0x0A, 0x11, 0x1F, 0x11, 0x11, 0x1F}; /* Home icon*/
62 /* 1 euro = ... (remenber 5 digits after the .)*/
63 static int currency[12]={
64 655957, /*FRF France*/
65 195583, /*DEM Germany*/
66 1376030, /*ATS Austria*/
67 4033990, /*BEF Belgium*/
68 16638600, /*ESP Spain*/
69 594573, /*FIM Finland*/
70 78756, /*IEP Ireland*/
71 193627000, /*ITL Italy*/
72 4033990, /*LUF Luxemburg*/
73 220371, /*NLG Netherlands*/
74 20048200, /*PTE Portugal*/
75 34075100, /*GRD Greece*/
78 /* Number of digit of the currency (for the display) */
79 static int nb_digit[12]={
80 2, /*FRF France*/
81 2, /*DEM Germany*/
82 2, /*ATS Austria*/
83 2, /*BEF Belgium*/
84 0, /*ESP Spain*/
85 2, /*FIM Finland*/
86 2, /*IEP Ireland*/
87 0, /*ITL Italy*/
88 2, /*LUF Luxemburg*/
89 2, /*NLG Netherlands*/
90 0, /*PTE Portugal*/
91 0 /*GRD Greece*/
94 /* max euro to have home currency */
95 static longlong_t max_euro[12]={
96 99999999000LL, /*FRF France 999 999.99 */
97 99999999000LL, /*DEM Germany 999 999.99 */
98 99999999000LL, /*ATS Austria 999 999.99 */
99 99999999000LL, /*BEF Belgium 999 999.99 */
100 99999999000LL, /*ESP Spain 99 999 999 */
101 99999999000LL, /*FIM Finland 999 999.99 */
102 99999999000LL, /*IEP Ireland 999 999.99 */
103 51645690000LL, /*ITL Italy 999 999 999 */
104 99999999000LL, /*LUF Luxemburg 999 999.99 */
105 99999999000LL, /*NLG Netherlands 999 999.99 */
106 99999999000LL, /*PTE Portugal 99 999 999 */
107 29347028000LL /*GRD Greece 99 999 999 */
110 /* max home to have euro currency */
111 /* 92233720300000 Limitation due to the max capacity of long long (2^63)*/
112 static longlong_t max_curr[12]={
113 99999999000LL, /*FRF France 152449.02 */
114 99999999000LL, /*DEM Germany 511291.88 */
115 99999999000LL, /*ATS Austria 72672.83 */
116 99999999000LL, /*BEF Belgium 24789.35 */
117 92233720300000LL,/*ESP Spain 5543358.23 */
118 99999999000LL, /*FIM Finland 168187.92 */
119 9999999900LL, /*IEP Ireland 1269744.51 exact value=1269738.07 */
120 92233720300000LL,/*ITL Italy 476347.41 */
121 99999999000LL, /*LUF Luxemburg 24789.35 */
122 99999999000LL, /*NLG Netherlands 453780.21 */
123 92233720300000LL,/*PTE Portugal 4600598.57 */
124 92233720300000LL /*GRD Greece 2706777.69 */
127 static unsigned char *abbrev_str[12] = {
128 "...FRF...", /*France*/
129 "...DEM...", /*Germany*/
130 "...ATS...", /*Austria*/
131 "...BEF...", /*Belgium*/
132 "...ESP...", /*Spain*/
133 "...FIM...", /*Finland*/
134 "...IEP...", /*Ireland*/
135 "...ITL...", /*Italy*/
136 "...LUF...", /*Luxemburg*/
137 "...NLG...", /*Netherlands*/
138 "...PTE...", /*Portugal*/
139 "...GRD..." /*Greece*/
143 static unsigned long heuro,hhome; /*Handles for the new patterns*/
145 static const struct plugin_api* rb;
147 static char *currency_str[12] = {
148 "France",
149 "Germany",
150 "Austria",
151 "Belgium",
152 "Spain",
153 "Finland",
154 "Ireland",
155 "Italy",
156 "Luxemburg",
157 "Netherlands",
158 "Portugal",
159 "Greece"
163 static int country; /*Country selected*/
164 static int cur_pos; /*Cursor position*/
165 static longlong_t inc;
167 /* Persistent settings */
168 static struct configdata config[] = {
169 { TYPE_ENUM, 0, 12, &country, "country", currency_str, NULL }
173 /* 64bits*64 bits with 5 digits after the . */
174 static longlong_t mymul(longlong_t a, longlong_t b)
176 return((a*b)/100000LL);
180 /* 64bits/64 bits with 5 digits after the . */
181 static longlong_t mydiv(longlong_t a, longlong_t b)
183 return((a*100000LL)/b);
187 /* 123.45=12345000 split => i=123 f=45000*/
188 static void split(longlong_t v, longlong_t* i, longlong_t* f)
190 longlong_t t;
192 t=v/100000LL;
193 (*i)=t;
194 (*f)=(v-(t*100000LL));
198 /* result=10^n */
199 static longlong_t pow10(int n)
201 int i;
202 longlong_t r;
204 r=1;
205 for (i=0;i<n;i++)
206 r=r*10LL;
207 return(r);
211 /* round the i.f at n digit after the . */
212 static void round(longlong_t* i, longlong_t* f, int n)
215 longlong_t m;
216 int add=0;
218 m=(int)pow10(5-n-1);
219 if (((*f)/m)%10>=5)
220 add=1;
221 if (n>0)
223 (*f)=((*f)/(int)pow10(5-n))+add;
224 if ((*f)==100LL)
226 (*i)+=1;
227 (*f)=0;
230 else
232 (*i)+=add;
233 (*f)=0;
238 /* Display the imput and the result
239 pos: false : first line
240 : true : second line
242 static void display(longlong_t euro, longlong_t home, bool pos)
244 longlong_t i,f;
245 unsigned char str[20];
246 unsigned char s1[20];
247 unsigned char s2[20];
249 if (pos)
250 { /*Edit the second line*/
251 rb->strcpy(s1," %6d.%02d");
252 if (nb_digit[country]==2)
253 rb->strcpy(s2,"\xee\x84\x90%06d.%02d");
254 else
255 rb->strcpy(s2,"\xee\x84\x90%09d");
257 else
259 rb->strcpy(s1,"\xee\x84\x90%06d.%02d");
260 if (nb_digit[country]==2)
261 rb->strcpy(s2," %6d.%02d");
262 else
263 rb->strcpy(s2," %9d");
266 rb->lcd_remove_cursor();
267 /*First line*/
268 rb->lcd_putc(0,0,heuro);
269 split(euro,&i,&f);
270 if (pos)
271 round(&i,&f,2);
272 rb->snprintf(str,sizeof(str),s1,(int)i,(int)f);
274 if (!pos)
276 rb->lcd_puts(1,0,str);
277 rb->lcd_put_cursor(10-cur_pos,0,0x5F);
279 else
280 rb->lcd_puts_scroll(1,0,str);
282 /*Second line*/
283 rb->lcd_putc(0,1,hhome);
284 split(home,&i,&f);
285 if (!pos)
286 round(&i,&f,nb_digit[country]);
287 rb->snprintf(str,sizeof(str),s2,(int)i,(int)f);
288 if (pos)
290 rb->lcd_puts(1,1,str);
291 rb->lcd_put_cursor(10-cur_pos,1,0x5F);
293 else
294 rb->lcd_puts_scroll(1,1,str);
296 rb->lcd_update();
300 /* Show country Abbreviation */
301 static void show_abbrev(void)
303 rb->splash(HZ*3/4,abbrev_str[country]);
307 /* Save the config to disk */
308 static void save_config(void)
310 configfile_save(cfg_filename, config, 1, CFGFILE_VERSION);
314 /* Load the config from disk */
315 static void load_config(void)
317 configfile_load(cfg_filename, config, 1, CFGFILE_MINVERSION);
321 /*Currency choice*/
322 static void currency_menu(void)
324 int c=country;
326 rb->lcd_clear_display();
327 while (true)
329 rb->lcd_puts(0,0,"Currency:");
330 rb->lcd_puts(0,1,currency_str[c]);
331 rb->lcd_update();
332 switch (rb->button_get(true))
334 case BUTTON_RIGHT|BUTTON_REL:
335 c++;
336 if (c>11)
337 c=0;
338 break;
339 case BUTTON_LEFT|BUTTON_REL:
340 c--;
341 if (c<0)
342 c=11;
343 break;
344 case BUTTON_PLAY|BUTTON_REL:
345 country=c;
346 save_config();
347 return;
348 break;
349 case BUTTON_STOP|BUTTON_REL:
350 return;
356 /* Display the choice menu. */
357 static int euro_menu(void)
359 int c=0;
362 while (true)
364 rb->lcd_clear_display();
365 rb->lcd_puts(0,0," Currency");
366 rb->lcd_puts(0,1," Exit");
367 rb->lcd_putc(0,c,0xe110);
368 rb->lcd_update();
370 switch (rb->button_get(true))
372 case BUTTON_RIGHT|BUTTON_REL:
373 c=1;
374 break;
375 case BUTTON_LEFT|BUTTON_REL:
376 c=0;
377 break;
378 case BUTTON_PLAY|BUTTON_REL:
379 if (c==0)
380 currency_menu();
381 else
382 return 1;
383 break;
384 case BUTTON_STOP|BUTTON_REL:
385 return 0;
391 /* Call when the program end */
392 static void euro_exit(void *parameter)
394 (void)parameter;
396 //Restore the old pattern (i don't find another way to do this. An idea?)
397 rb->lcd_unlock_pattern(heuro);
398 rb->lcd_unlock_pattern(hhome);
400 //Clear the screen
401 rb->lcd_clear_display();
402 rb->lcd_update();
406 /* this is the plugin entry point */
407 enum plugin_status plugin_start(const struct plugin_api* api, const void* parameter)
409 bool end, pos;
410 longlong_t e,h,old_e,old_h;
411 int button;
413 /* if you don't use the parameter, you can do like
414 this to avoid the compiler warning about it */
415 (void)parameter;
417 /* if you are using a global api pointer, don't forget to copy it!
418 otherwise you will get lovely "I04: IllInstr" errors... :-) */
419 rb = api;
421 /*Get the pattern handle*/
422 heuro=rb->lcd_get_locked_pattern();
423 hhome=rb->lcd_get_locked_pattern();
424 rb->lcd_define_pattern(heuro, pattern_euro);
425 rb->lcd_define_pattern(hhome, pattern_home);
427 h=0;
428 e=0;
429 end=false;
430 pos=false;
431 country=0;
432 cur_pos=3;
433 inc=100000;
435 configfile_init(rb);
437 load_config();
439 /*Empty the event queue*/
440 rb->button_clear_queue();
442 display(e,h,false);
443 show_abbrev();
444 display(e,h,false);
446 /*Main loop*/
447 while(end!=true)
449 button = rb->button_get(true);
450 switch (button)
452 case BUTTON_MENU|BUTTON_REL:
453 switch (euro_menu())
455 case 1:
456 end=true;
457 break;
459 if (!pos)
461 if (e>max_euro[country])
462 e=0;
463 cur_pos=3;
465 else
467 if (h>max_curr[country])
468 h=0;
469 if (nb_digit[country]==2)
470 cur_pos=3;
471 else
472 cur_pos=0;
475 display(e,h,pos);
476 break;
478 case BUTTON_ON | BUTTON_PLAY:
479 pos=!pos;
481 case BUTTON_ON | BUTTON_REL:
482 e=0;
483 h=0;
484 if (!pos)
486 cur_pos=3;
487 inc=100000;
489 else
491 inc=100000;
492 if (nb_digit[country]==2)
493 cur_pos=3;
494 else
495 cur_pos=0;
497 show_abbrev();
498 break;
500 case BUTTON_STOP|BUTTON_REL:
501 cur_pos--;
502 if (!pos)
504 if (cur_pos<0)
505 cur_pos=0;
506 if (cur_pos==2)
507 cur_pos=1;
508 if (cur_pos>2)
509 inc=pow10(3+cur_pos-1);
510 else
511 inc=pow10(3+cur_pos);
513 else
515 if (cur_pos<0)
516 cur_pos=0;
517 if (nb_digit[country]==2)
519 if (cur_pos==2)
520 cur_pos=1;
521 if (cur_pos>2)
522 inc=pow10(3+cur_pos-1);
523 else
524 inc=pow10(3+cur_pos);
526 else
527 inc=pow10(5+cur_pos);
530 break;
532 case BUTTON_PLAY|BUTTON_REL:
533 cur_pos++;
534 if (!pos)
536 if (cur_pos>8)
537 cur_pos=8;
538 if (cur_pos==2)
539 cur_pos=3;
540 if (cur_pos>2)
541 inc=pow10(3+cur_pos-1);
542 else
543 inc=pow10(3+cur_pos);
545 else
547 if (cur_pos>8)
548 cur_pos=8;
549 if (nb_digit[country]==2)
551 if (cur_pos==2)
552 cur_pos=3;
553 if (cur_pos>2)
554 inc=pow10(3+cur_pos-1);
555 else
556 inc=pow10(3+cur_pos);
558 else
559 inc=pow10(5+cur_pos);
561 break;
563 case BUTTON_LEFT|BUTTON_REL:
564 case BUTTON_LEFT|BUTTON_REPEAT:
565 if (!pos)
567 e-=inc;
568 if (e<0)
569 e=0;
571 else
573 h-=inc;
574 if (h<0)
575 h=0;
577 break;
579 case BUTTON_RIGHT|BUTTON_REL:
580 case BUTTON_RIGHT|BUTTON_REPEAT:
581 old_e=e;
582 old_h=h;
583 if (!pos)
585 e+=inc;
586 if (e>max_euro[country])
587 e=old_e;
589 else
591 h+=inc;
592 if (h>max_curr[country])
593 h=old_h;
595 break;
597 default:
598 if (rb->default_event_handler_ex(button, euro_exit, NULL)
599 == SYS_USB_CONNECTED)
600 return PLUGIN_USB_CONNECTED;
601 break;
603 /*Display*/
604 if (!pos) /*Euro>home*/
605 h=mymul(e,currency[country]);
606 else /*Home>euro*/
607 e=mydiv(h,currency[country]);
608 display(e,h,pos);
610 euro_exit(NULL);
611 return PLUGIN_OK;
614 #endif