summaryrefslogtreecommitdiff
path: root/apps/plugins/euroconverter.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/plugins/euroconverter.c')
-rw-r--r--apps/plugins/euroconverter.c626
1 files changed, 626 insertions, 0 deletions
diff --git a/apps/plugins/euroconverter.c b/apps/plugins/euroconverter.c
new file mode 100644
index 0000000000..e604521034
--- /dev/null
+++ b/apps/plugins/euroconverter.c
@@ -0,0 +1,626 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2003 Pierre Delore
11 *
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.
14 *
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
17 *
18 ****************************************************************************/
19#include "plugin.h"
20
21#ifdef HAVE_LCD_CHARCELLS
22
23/* Euro converter for the player */
24/*
25Use:
26+ : Digit +1
27- : Digit -1
28PLAY : Next digit
29STOP : Prev digit
30ON : RESET
31ON+PLAY : Swap Euro<>Home
32MENU : Display the Menu
33 Currency -> Allows to choose the currency
34 Exit-> Exit the plugin
35
36Notes:
37I don't use float.
38I use signed long long (64 bits).
39A value have 5 digits after the . (123.45 = 12345000)
40
41To do:
42- The Irish currency needs 6 digits after the . to have sufficient precision on big number
43- Improve the config save format to be like rockbox setting
44 (use of settings_parseline(...) of setting.c ? must be extern and export in the config.h)
45*/
46
47/* Name and path of the config file*/
48#define CFGFILE "/.rockbox/euroconverter.cfg"
49
50/*Pattern for the converter*/
51static unsigned char pattern_euro[]={0x07, 0x08, 0x1E, 0x10, 0x1E, 0x08, 0x07}; /* € */
52static unsigned char pattern_home[]={0x04, 0x0A, 0x11, 0x1F, 0x11, 0x11, 0x1F}; /* Home icon*/
53
54/* 1 euro = ... (remenber 5 digits after the .)*/
55static int currency[12]={
56 655957, /*FRF France*/
57 195583, /*DEM Germany*/
58 1376030, /*ATS Austria*/
59 4033990, /*BEF Belgium*/
60 16638600, /*ESP Spain*/
61 594573, /*FIM Finland*/
62 78756, /*IEP Irland*/
63 193627000, /*ITL Italy*/
64 4033990, /*LUF Luxemburg*/
65 220371, /*NLG Netherlands*/
66 20048200, /*PTE Portugal*/
67 34075100, /*GRD Greece*/
68 };
69
70/* Number of digit of the currency (for the display) */
71static int nb_digit[12]={
72 2, /*FRF France*/
73 2, /*DEM Germany*/
74 2, /*ATS Austria*/
75 2, /*BEF Belgium*/
76 0, /*ESP Spain*/
77 2, /*FIM Finland*/
78 2, /*IEP Irland*/
79 0, /*ITL Italy*/
80 2, /*LUF Luxemburg*/
81 2, /*NLG Netherlands*/
82 0, /*PTE Portugal*/
83 0 /*GRD Greece*/
84 };
85
86/* max euro to have home currency */
87static long long max_euro[12]={
88 99999999000LL, /*FRF France 999 999.99 */
89 99999999000LL, /*DEM Germany 999 999.99 */
90 99999999000LL, /*ATS Austria 999 999.99 */
91 99999999000LL, /*BEF Belgium 999 999.99 */
92 99999999000LL, /*ESP Spain 99 999 999 */
93 99999999000LL, /*FIM Finland 999 999.99 */
94 99999999000LL, /*IEP Irland 999 999.99 */
95 51645690000LL, /*ITL Italy 999 999 999 */
96 99999999000LL, /*LUF Luxemburg 999 999.99 */
97 99999999000LL, /*NLG Netherlands 999 999.99 */
98 99999999000LL, /*PTE Portugal 99 999 999 */
99 29347028000LL /*GRD Greece 99 999 999 */
100 };
101
102/* max home to have euro currency */
103/* 92233720300000 Limitation due to the max capacity of long long (2^63)*/
104static long long max_curr[12]={
105 99999999000LL, /*FRF France 152449.02 */
106 99999999000LL, /*DEM Germany 511291.88 */
107 99999999000LL, /*ATS Austria 72672.83 */
108 99999999000LL, /*BEF Belgium 24789.35 */
109 92233720300000LL, /*ESP Spain 5543358.23 */
110 99999999000LL, /*FIM Finland 168187.92 */
111 9999999900LL, /*IEP Irland 1269744.51 exact value=1269738.07 */
112 92233720300000LL,/*ITL Italy 476347.41 */
113 99999999000LL, /*LUF Luxemburg 24789.35 */
114 99999999000LL, /*NLG Netherlands 453780.21 */
115 92233720300000LL, /*PTE Portugal 4600598.57 */
116 92233720300000LL /*GRD Greece 2706777.69 */
117 };
118
119static unsigned char *abbrev_str[12] = {
120 "...FRF...", /*France*/
121 "...DEM...", /*Germany*/
122 "...ATS...", /*Austria*/
123 "...BEF...", /*Belgium*/
124 "...ESP...", /*Spain*/
125 "...FIM...", /*Finland*/
126 "...IEP...", /*Irland*/
127 "...ITL...", /*Italy*/
128 "...LUF...", /*Luxemburg*/
129 "...NLG...", /*Netherlands*/
130 "...PTE...", /*Portugal*/
131 "...GRD..." /*Greece*/
132 };
133
134
135static unsigned char heuro,hhome; /*Handles for the new patterns*/
136
137static struct plugin_api* rb;
138
139static int country; /*Country selected*/
140static int cur_pos; /*Cursor position*/
141static long long inc;
142
143
144/* 64bits*64 bits with 5 digits after the . */
145static long long mul(long long a, long long b)
146{
147 return((a*b)/100000);
148}
149
150
151/* 64bits/64 bits with 5 digits after the . */
152static long long mydiv(long long a, long long b)
153{
154 return((a*100000)/b);
155}
156
157
158/* 123.45=12345000 split => i=123 f=45000*/
159static void split(long long v, long long* i, long long* f)
160{
161 long long t;
162
163 t=v/100000LL;
164 (*i)=t;
165 (*f)=(v-(t*100000LL));
166}
167
168
169/* result=10^n */
170static long long pow10(int n)
171{
172 int i;
173 long long r;
174
175 r=1;
176 for (i=0;i<n;i++)
177 r=r*10LL;
178 return(r);
179}
180
181
182/* round the i.f at n digit after the . */
183static void round(long long* i, long long* f, int n)
184{
185
186 long long m;
187 int add=0;
188
189 m=(int)pow10(5-n-1);
190 if (((*f)/m)%10>=5)
191 add=1;
192 if (n>0)
193 {
194 (*f)=((*f)/(int)pow10(5-n))+add;
195 if ((*f)==100LL)
196 {
197 (*i)+=1;
198 (*f)=0;
199 }
200 }
201 else
202 {
203 (*i)+=add;
204 (*f)=0;
205 }
206}
207
208
209/* Display the imput and the result
210 pos: false : first line
211 : true : second line
212*/
213static void display(long long euro, long long home, bool pos)
214{
215 char c1,c2;
216 long long i,f;
217 unsigned char str[20];
218 unsigned char s1[20];
219 unsigned char s2[20];
220
221 if (pos)
222 { /*Edit the second line*/
223 c1=0x20;
224 rb->strcpy(s1,"%c%c%6d.%02d");
225 c2=0x81;
226 if (nb_digit[country]==2)
227 rb->strcpy(s2,"%c%c%06d.%02d");
228 else
229 rb->strcpy(s2,"%c%c%09d");
230 }
231 else
232 {
233 c1=0x81;
234 rb->strcpy(s1,"%c%c%06d.%02d");
235 c2=0x20;
236 if (nb_digit[country]==2)
237 rb->strcpy(s2,"%c%c%6d.%02d");
238 else
239 rb->strcpy(s2,"%c%c%9d");
240 }
241
242 rb->lcd_remove_cursor();
243 /*First line*/
244 split(euro,&i,&f);
245 if (pos)
246 round(&i,&f,2);
247 rb->snprintf(str,sizeof(str),s1,heuro,c1,(int)i,(int)f);
248
249 if (!pos)
250 {
251 rb->lcd_puts(0,0,str);
252 rb->lcd_put_cursor(10-cur_pos,0,0x5F);
253 }
254 else
255 rb->lcd_puts_scroll(0,0,str);
256
257 /*Second line*/
258 split(home,&i,&f);
259 if (!pos)
260 round(&i,&f,nb_digit[country]);
261 rb->snprintf(str,sizeof(str),s2,hhome,c2,(int)i,(int)f);
262 if (pos)
263 {
264 rb->lcd_puts(0,1,str);
265 rb->lcd_put_cursor(10-cur_pos,1,0x5F);
266 }
267 else
268 rb->lcd_puts_scroll(0,1,str);
269}
270
271
272/* Show country Abbreviation */
273static void show_abbrev(void)
274{
275// rb->lcd_remove_cursor();
276 rb->lcd_puts(2,1,abbrev_str[country]);
277 rb->sleep(HZ*3/4);
278}
279
280
281/* Save the config to disk */
282static void save_config(void)
283{
284 int fd;
285
286 fd = rb->creat(CFGFILE,0);
287 if (fd < 0)
288 {
289 rb->lcd_clear_display();
290 rb->lcd_puts(0,0,"Impossible");
291 rb->lcd_puts(0,1,"to save cfg");
292 rb->sleep(HZ);
293 }
294 else
295 {
296 rb->fprintf(fd, "%c", country+0x30);
297 rb->close(fd);
298 }
299 return;
300}
301
302
303/* Load the config from disk */
304static void load_config(void)
305{
306 int fd;
307 char line[128];
308
309 fd = rb->open(CFGFILE, O_RDONLY);
310 if (fd < 0)
311 return;
312
313 rb->read(fd, line,1);
314 country=line[0]-0x30;
315
316 if ((country>11)|| (country<0))
317 country=0;
318
319 rb->close(fd);
320 return;
321}
322
323
324/*Currency choice*/
325static void currency_menu(void)
326{
327 unsigned char *currency_str[12] = {
328 "France",
329 "Germany",
330 "Austria",
331 "Belgium",
332 "Spain",
333 "Finland",
334 "Irland",
335 "Italy",
336 "Luxemburg",
337 "Netherlands",
338 "Portugal",
339 "Greece"
340 };
341 int c=country;
342
343 rb->lcd_clear_display();
344 while (true)
345 {
346 rb->lcd_puts(0,0,"Currency:");
347 rb->lcd_puts(0,1,currency_str[c]);
348 switch (rb->button_get(true))
349 {
350 case BUTTON_RIGHT|BUTTON_REL:
351 c++;
352 if (c>11)
353 c=0;
354 break;
355 case BUTTON_LEFT|BUTTON_REL:
356 c--;
357 if (c<0)
358 c=11;
359 break;
360 case BUTTON_PLAY|BUTTON_REL:
361 country=c;
362 save_config();
363 return;
364 break;
365 case BUTTON_STOP|BUTTON_REL:
366 return;
367 }
368 }
369}
370
371
372/* Display the choice menu. */
373static int euro_menu(void)
374{
375 int c=0;
376
377
378 while (true)
379 {
380 rb->lcd_clear_display();
381 rb->lcd_puts(0,0," Currency");
382 rb->lcd_puts(0,1," Exit");
383 rb->lcd_putc(0,c,0x81);
384
385 switch (rb->button_get(true))
386 {
387 case BUTTON_RIGHT|BUTTON_REL:
388 c=1;
389 break;
390 case BUTTON_LEFT|BUTTON_REL:
391 c=0;
392 break;
393 case BUTTON_PLAY|BUTTON_REL:
394 if (c==0)
395 currency_menu();
396 else
397 return 1;
398 break;
399 case BUTTON_STOP|BUTTON_REL:
400 return 0;
401 }
402 }
403}
404
405
406/* Call when the program end */
407static void euro_exit(void)
408{
409 //Restore the old pattern (i don't find another way to do this. An idea?)
410 rb->lcd_unlock_pattern(heuro);
411 rb->lcd_unlock_pattern(hhome);
412
413 //Clear the screen
414 rb->lcd_clear_display();
415}
416
417
418/* this is the plugin entry point */
419enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
420{
421 bool end, pos;
422 long long e,h,old_e,old_h;
423
424 /* this macro should be called as the first thing you do in the plugin.
425 it test that the api version and model the plugin was compiled for
426 matches the machine it is running on */
427 TEST_PLUGIN_API(api);
428
429 /* if you don't use the parameter, you can do like
430 this to avoid the compiler warning about it */
431 (void)parameter;
432
433 /* if you are using a global api pointer, don't forget to copy it!
434 otherwise you will get lovely "I04: IllInstr" errors... :-) */
435 rb = api;
436
437 /*Get the pattern handle*/
438 heuro=rb->lcd_get_locked_pattern();
439 hhome=rb->lcd_get_locked_pattern();
440 rb->lcd_define_pattern(heuro, pattern_euro);
441 rb->lcd_define_pattern(hhome, pattern_home);
442
443 h=0;
444 e=0;
445 end=false;
446 pos=false;
447 country=0;
448 cur_pos=3;
449 inc=100000;
450
451 load_config();
452
453 /*Empty the event queue*/
454 while (rb->button_get(false)!=BUTTON_NONE) ;
455
456 display(e,h,false);
457 show_abbrev();
458 display(e,h,false);
459
460 /*Main loop*/
461 while(end!=true)
462 {
463 switch (rb->button_get(true))
464 {
465 case BUTTON_MENU|BUTTON_REL:
466 switch (euro_menu())
467 {
468 case 1:
469 end=true;
470 break;
471 }
472 if (!pos)
473 {
474 if (e>max_euro[country])
475 e=0;
476 cur_pos=3;
477 }
478 else
479 {
480 if (h>max_curr[country])
481 h=0;
482 if (nb_digit[country]==2)
483 cur_pos=3;
484 else
485 cur_pos=0;
486 }
487
488 display(e,h,pos);
489 break;
490
491 case BUTTON_ON | BUTTON_PLAY:
492 pos=!pos;
493
494 case BUTTON_ON | BUTTON_REL:
495 e=0;
496 h=0;
497 if (!pos)
498 {
499 cur_pos=3;
500 inc=100000;
501 }
502 else
503 {
504 inc=100000;
505 if (nb_digit[country]==2)
506 cur_pos=3;
507 else
508 cur_pos=0;
509 }
510 show_abbrev();
511 break;
512
513 case BUTTON_STOP|BUTTON_REL:
514 cur_pos--;
515 if (!pos)
516 {
517 if (cur_pos<0)
518 cur_pos=0;
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);
525 }
526 else
527 {
528 if (cur_pos<0)
529 cur_pos=0;
530 if (nb_digit[country]==2)
531 {
532 if (cur_pos==2)
533 cur_pos=1;
534 if (cur_pos>2)
535 inc=pow10(3+cur_pos-1);
536 else
537 inc=pow10(3+cur_pos);
538 }
539 else
540 inc=pow10(5+cur_pos);
541
542 }
543 break;
544
545 case BUTTON_PLAY|BUTTON_REL:
546 cur_pos++;
547 if (!pos)
548 {
549 if (cur_pos>8)
550 cur_pos=8;
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);
557 }
558 else
559 {
560 if (cur_pos>8)
561 cur_pos=8;
562 if (nb_digit[country]==2)
563 {
564 if (cur_pos==2)
565 cur_pos=3;
566 if (cur_pos>2)
567 inc=pow10(3+cur_pos-1);
568 else
569 inc=pow10(3+cur_pos);
570 }
571 else
572 inc=pow10(5+cur_pos);
573 }
574 break;
575
576 case BUTTON_LEFT|BUTTON_REL:
577 case BUTTON_LEFT|BUTTON_REPEAT:
578 if (!pos)
579 {
580 e-=inc;
581 if (e<0)
582 e=0;
583 }
584 else
585 {
586 h-=inc;
587 if (h<0)
588 h=0;
589 }
590 break;
591
592 case BUTTON_RIGHT|BUTTON_REL:
593 case BUTTON_RIGHT|BUTTON_REPEAT:
594 old_e=e;
595 old_h=h;
596 if (!pos)
597 {
598 e+=inc;
599 if (e>max_euro[country])
600 e=old_e;
601 }
602 else
603 {
604 h+=inc;
605 if (h>max_curr[country])
606 h=old_h;
607 }
608 break;
609
610 case SYS_USB_CONNECTED:
611 rb->usb_screen();
612 euro_exit();
613 return PLUGIN_USB_CONNECTED;
614 }
615 /*Display*/
616 if (!pos) /*Euro>home*/
617 h=mul(e,currency[country]);
618 else /*Home>euro*/
619 e=mydiv(h,currency[country]);
620 display(e,h,pos);
621 }
622 euro_exit();
623 return PLUGIN_OK;
624}
625
626#endif