1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright (C) 2002 Björn Stenberg
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 ****************************************************************************/
22 #include "backlight.h"
29 #include "mp3_playback.h"
38 #include "powermgmt.h"
43 #ifdef HAVE_LCD_BITMAP
44 #define BMPHEIGHT_usb_logo 32
45 #define BMPWIDTH_usb_logo 100
46 static unsigned char usb_logo
[] = {
47 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
48 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
49 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40, 0x20, 0x10, 0x08,
50 0x04, 0x04, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
51 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x81, 0x81, 0x81, 0x81,
52 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
53 0x01, 0x01, 0x01, 0x01, 0xf1, 0x4f, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
54 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0xc0,
55 0x00, 0x00, 0xe0, 0x1c, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
56 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
57 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x06, 0x81, 0xc0, 0xe0, 0xe0, 0xe0, 0xe0,
58 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80, 0xc0, 0xe0, 0x70, 0x38, 0x1c, 0x1c,
59 0x0c, 0x0e, 0x0e, 0x06, 0x06, 0x06, 0x06, 0x06, 0x0f, 0x1f, 0x1f, 0x1f, 0x1f,
60 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xc0, 0xc0, 0x80, 0x80, 0x00, 0x00,
61 0x00, 0x00, 0xe0, 0x1f, 0x00, 0xf8, 0x06, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
62 0x02, 0x02, 0x02, 0x82, 0x7e, 0x00, 0xc0, 0x3e, 0x01,
63 0x70, 0x4f, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
64 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
65 0x40, 0x40, 0x40, 0x40, 0x40, 0x80, 0x00, 0x07, 0x0f, 0x1f, 0x1f, 0x1f, 0x1f,
66 0x0f, 0x07, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x07, 0x0f,
67 0x1f, 0x3f, 0x7b, 0xf3, 0xe3, 0xc3, 0x83, 0x83, 0x83, 0x83, 0xe3, 0xe3, 0xe3,
68 0xe3, 0xe3, 0xe3, 0x03, 0x03, 0x03, 0x3f, 0x1f, 0x1f, 0x0f, 0x0f, 0x07, 0x02,
69 0xc0, 0x3e, 0x01, 0xe0, 0x9f, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
70 0x80, 0x80, 0xf0, 0x0f, 0x80, 0x78, 0x07, 0x00, 0x00,
71 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
72 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
73 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x0c, 0x10, 0x20, 0x40, 0x40, 0x80, 0x80,
74 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
75 0x80, 0x80, 0x80, 0x80, 0x80, 0x81, 0x81, 0x81, 0x81, 0x81, 0x87, 0x87, 0x87,
76 0x87, 0x87, 0x87, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xf0,
77 0x0f, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
78 0x04, 0x04, 0x04, 0x04, 0x07, 0x00, 0x00, 0x00, 0x00,
82 void usb_display_info(void)
86 #ifdef HAVE_LCD_BITMAP
87 /* lcd_bitmap() only supports 16 pixels height! */
88 lcd_bitmap(usb_logo
, 6, 16,
89 BMPWIDTH_usb_logo
, 8, false);
90 lcd_bitmap(usb_logo
+BMPWIDTH_usb_logo
, 6, 24,
91 BMPWIDTH_usb_logo
, 8, false);
92 lcd_bitmap(usb_logo
+BMPWIDTH_usb_logo
*2, 6, 32,
93 BMPWIDTH_usb_logo
, 8, false);
94 lcd_bitmap(usb_logo
+BMPWIDTH_usb_logo
*3, 6, 40,
95 BMPWIDTH_usb_logo
, 8, false);
99 lcd_puts(0, 0, "[USB Mode]");
100 status_set_param(false);
101 status_set_audio(false);
102 status_set_usb(true);
107 void usb_screen(void)
114 usb_acknowledge(SYS_USB_CONNECTED_ACK
);
116 while(usb_wait_for_disconnect_w_tmo(&button_queue
, HZ
)) {
121 #ifdef HAVE_LCD_CHARCELLS
122 status_set_usb(false);
127 #endif /* USB_NONE */
131 /* some simulator dummies */
133 #define BATTERY_SCALE_FACTOR 7000
134 unsigned short adc_read(int channel
)
142 #ifdef HAVE_LCD_BITMAP
143 void charging_display_info(bool animate
)
145 unsigned char charging_logo
[36];
146 const int pox_x
= (LCD_WIDTH
- sizeof(charging_logo
)) / 2;
147 const int pox_y
= 32;
148 static unsigned phase
= 3;
153 #ifdef NEED_ATA_POWER_BATT_MEASURE
154 if (ide_powered()) /* FM and V2 can only measure when ATA power is on */
158 int batt_int
, batt_frac
;
160 battery_voltage
= (adc_read(ADC_UNREG_POWER
) * BATTERY_SCALE_FACTOR
) / 10000;
161 batt_int
= battery_voltage
/ 100;
162 batt_frac
= battery_voltage
% 100;
164 snprintf(buf
, 32, " Batt: %d.%02dV %d%% ", batt_int
, batt_frac
,
169 #ifdef HAVE_CHARGE_CTRL
171 snprintf(buf
, 32, "Charge mode:");
174 if (charge_state
== 1)
175 snprintf(buf
, 32, str(LANG_BATTERY_CHARGE
));
176 else if (charge_state
== 2)
177 snprintf(buf
, 32, str(LANG_BATTERY_TOPOFF_CHARGE
));
178 else if (charge_state
== 3)
179 snprintf(buf
, 32, str(LANG_BATTERY_TRICKLE_CHARGE
));
181 snprintf(buf
, 32, "not charging");
186 backlight_on(); /* using the light gives good indication */
197 memset(charging_logo
+3, 0x00, 32);
198 charging_logo
[0] = 0x3C;
199 charging_logo
[1] = 0x24;
200 charging_logo
[2] = charging_logo
[35] = 0xFF;
203 { /* draw the outline */
205 lcd_bitmap(charging_logo
, pox_x
, pox_y
+ 8, sizeof(charging_logo
), 8, true);
207 charging_logo
[0] = charging_logo
[1] = 0x00;
208 memset(charging_logo
+2, 0x80, 34);
209 lcd_bitmap(charging_logo
, pox_x
, pox_y
, sizeof(charging_logo
), 8, false);
211 memset(charging_logo
+2, 0x01, 34);
212 lcd_bitmap(charging_logo
, pox_x
, pox_y
+ 16, sizeof(charging_logo
), 8, false);
215 { /* animate the middle part */
216 for (i
= 3; i
<MIN(sizeof(charging_logo
)-1, phase
); i
++)
218 if ((i
-phase
) % 8 == 0)
219 { /* draw a "bubble" here */
221 bitpos
= (phase
+ i
/8) % 15; /* "bounce" effect */
223 bitpos
= 14 - bitpos
;
224 charging_logo
[i
] = 0x01 << bitpos
;
227 lcd_bitmap(charging_logo
, pox_x
, pox_y
+ 8, sizeof(charging_logo
), 8, true);
232 #else /* not HAVE_LCD_BITMAP */
233 void charging_display_info(bool animate
)
235 /* ToDo for Player */
240 #ifdef HAVE_BATTERIES
241 /* blocks while charging, returns on event:
242 1 if charger cable was removed
243 2 if Off/Stop key was pressed
244 3 if On key was pressed
245 4 if USB was connected */
246 int charging_screen(void)
250 #ifdef HAVE_RECORDER_KEYPAD
251 const int offbutton
= BUTTON_OFF
;
253 const int offbutton
= BUTTON_STOP
;
256 ide_power_enable(false); /* power down the disk, else would be spinning */
262 #ifdef HAVE_LCD_BITMAP
263 charging_display_info(false);
265 status_set_playmode(STATUS_STOP
);
266 lcd_puts(0, 1, "[charging]");
272 charging_display_info(true);
273 button
= button_get_w_tmo(HZ
/3);
274 if (button
== (BUTTON_ON
| BUTTON_REL
))
276 else if (button
== offbutton
)
282 else if (!charger_inserted())
289 #endif /* HAVE_BATTERIES */
292 #ifdef HAVE_RECORDER_KEYPAD
294 0 if no key was pressed
295 1 if a key was pressed (or if ON was held down long enough to repeat)
296 2 if USB was connected */
299 static int pitch
= 1000;
311 lcd_setfont(FONT_SYSFIXED
);
313 ptr
= str(LANG_PITCH_UP
);
314 lcd_getstringsize(ptr
,&w
,&h
);
315 lcd_putsxy((LCD_WIDTH
-w
)/2, 0, ptr
);
316 lcd_bitmap(bitmap_icons_7x8
[Icon_UpArrow
],
317 LCD_WIDTH
/2 - 3, h
*2, 7, 8, true);
319 snprintf(buf
, sizeof buf
, "%d.%d%%", pitch
/ 10, pitch
% 10 );
320 lcd_getstringsize(buf
,&w
,&h
);
321 lcd_putsxy((LCD_WIDTH
-w
)/2, h
, buf
);
323 ptr
= str(LANG_PITCH_DOWN
);
324 lcd_getstringsize(ptr
,&w
,&h
);
325 lcd_putsxy((LCD_WIDTH
-w
)/2, LCD_HEIGHT
- h
, ptr
);
326 lcd_bitmap(bitmap_icons_7x8
[Icon_DownArrow
],
327 LCD_WIDTH
/2 - 3, LCD_HEIGHT
- h
*3, 7, 8, true);
329 ptr
= str(LANG_PAUSE
);
330 lcd_getstringsize(ptr
,&w
,&h
);
331 lcd_putsxy((LCD_WIDTH
-(w
/2))/2, LCD_HEIGHT
/2 - h
/2, ptr
);
332 lcd_bitmap(bitmap_icons_7x8
[Icon_Pause
],
333 (LCD_WIDTH
-(w
/2))/2-10, LCD_HEIGHT
/2 - h
/2, 7, 8, true);
338 /* use lastbutton, so the main loop can decide whether to
339 exit to browser or not */
340 switch (button_get(true)) {
342 case BUTTON_ON
| BUTTON_UP
:
343 case BUTTON_ON
| BUTTON_UP
| BUTTON_REPEAT
:
348 mpeg_set_pitch(pitch
);
352 case BUTTON_ON
| BUTTON_DOWN
:
353 case BUTTON_ON
| BUTTON_DOWN
| BUTTON_REPEAT
:
358 mpeg_set_pitch(pitch
);
361 case BUTTON_ON
| BUTTON_PLAY
:
366 case BUTTON_PLAY
| BUTTON_REL
:
371 case BUTTON_ON
| BUTTON_PLAY
| BUTTON_REL
:
376 case BUTTON_ON
| BUTTON_RIGHT
:
377 if ( pitch
< 2000 ) {
379 mpeg_set_pitch(pitch
);
383 case BUTTON_RIGHT
| BUTTON_REL
:
386 mpeg_set_pitch(pitch
);
390 case BUTTON_ON
| BUTTON_LEFT
:
393 mpeg_set_pitch(pitch
);
397 case BUTTON_LEFT
| BUTTON_REL
:
398 if ( pitch
< 2000 ) {
400 mpeg_set_pitch(pitch
);
407 case BUTTON_ON
| BUTTON_REL
:
408 case BUTTON_ON
| BUTTON_UP
| BUTTON_REL
:
409 case BUTTON_ON
| BUTTON_DOWN
| BUTTON_REL
:
414 case BUTTON_ON
| BUTTON_REPEAT
:
418 case SYS_USB_CONNECTED
:
424 lcd_setfont(FONT_UI
);
432 bool quick_screen(int context
, int button
)
438 int oldrepeat
= global_settings
.repeat_mode
;
440 /* just to stop compiler warning */
442 lcd_setfont(FONT_SYSFIXED
);
444 if(button
==BUTTON_F2
)
445 lcd_getstringsize("A",&w
,&h
);
456 lcd_putsxy(0, LCD_HEIGHT
/2 - h
*2, str(LANG_SHUFFLE
));
457 lcd_putsxy(0, LCD_HEIGHT
/2 - h
, str(LANG_F2_MODE
));
458 lcd_putsxy(0, LCD_HEIGHT
/2,
459 global_settings
.playlist_shuffle
?
460 str(LANG_ON
) : str(LANG_OFF
));
462 /* Directory Filter */
463 switch ( global_settings
.dirfilter
) {
465 ptr
= str(LANG_FILTER_ALL
);
469 ptr
= str(LANG_FILTER_SUPPORTED
);
473 ptr
= str(LANG_FILTER_MUSIC
);
477 ptr
= str(LANG_FILTER_PLAYLIST
);
481 snprintf(buf
, sizeof buf
, "%s:", str(LANG_FILTER
));
482 lcd_getstringsize(buf
,&w
,&h
);
483 lcd_putsxy((LCD_WIDTH
-w
)/2, LCD_HEIGHT
- h
*2, buf
);
484 lcd_getstringsize(ptr
,&w
,&h
);
485 lcd_putsxy((LCD_WIDTH
-w
)/2, LCD_HEIGHT
- h
, ptr
);
488 switch ( global_settings
.repeat_mode
) {
494 ptr
= str(LANG_REPEAT_ALL
);
498 ptr
= str(LANG_REPEAT_ONE
);
502 lcd_getstringsize(str(LANG_REPEAT
),&w
,&h
);
503 lcd_putsxy(LCD_WIDTH
- w
, LCD_HEIGHT
/2 - h
*2, str(LANG_REPEAT
));
504 lcd_putsxy(LCD_WIDTH
- w
, LCD_HEIGHT
/2 - h
, str(LANG_F2_MODE
));
505 lcd_putsxy(LCD_WIDTH
- w
, LCD_HEIGHT
/2, ptr
);
509 lcd_putsxy(0, LCD_HEIGHT
/2 - h
*2, str(LANG_F3_SCROLL
));
510 lcd_putsxy(0, LCD_HEIGHT
/2 - h
, str(LANG_F3_BAR
));
511 lcd_putsxy(0, LCD_HEIGHT
/2,
512 global_settings
.scrollbar
? str(LANG_ON
) : str(LANG_OFF
));
515 ptr
= str(LANG_F3_STATUS
);
516 lcd_getstringsize(ptr
,&w
,&h
);
517 lcd_putsxy(LCD_WIDTH
- w
, LCD_HEIGHT
/2 - h
*2, ptr
);
518 lcd_putsxy(LCD_WIDTH
- w
, LCD_HEIGHT
/2 - h
, str(LANG_F3_BAR
));
519 lcd_putsxy(LCD_WIDTH
- w
, LCD_HEIGHT
/2,
520 global_settings
.statusbar
? str(LANG_ON
) : str(LANG_OFF
));
523 ptr
= str(LANG_FLIP_DISPLAY
);
524 lcd_getstringsize(ptr
,&w
,&h
);
525 lcd_putsxy((LCD_WIDTH
-w
)/2, LCD_HEIGHT
- h
*2, str(LANG_FLIP_DISPLAY
));
526 ptr
= global_settings
.flip_display
?
527 str(LANG_SET_BOOL_YES
) : str(LANG_SET_BOOL_NO
);
528 lcd_getstringsize(ptr
,&w
,&h
);
529 lcd_putsxy((LCD_WIDTH
-w
)/2, LCD_HEIGHT
- h
, ptr
);
533 lcd_bitmap(bitmap_icons_7x8
[Icon_FastBackward
],
534 LCD_WIDTH
/2 - 16, LCD_HEIGHT
/2 - 4, 7, 8, true);
535 lcd_bitmap(bitmap_icons_7x8
[Icon_DownArrow
],
536 LCD_WIDTH
/2 - 3, LCD_HEIGHT
- h
*3, 7, 8, true);
537 lcd_bitmap(bitmap_icons_7x8
[Icon_FastForward
],
538 LCD_WIDTH
/2 + 8, LCD_HEIGHT
/2 - 4, 7, 8, true);
541 key
= button_get(true);
544 * This is a temporary kludge so that the F2 & F3 menus operate in exactly
545 * the same manner up until the full F2/F3 configurable menus are complete
548 if( key
== BUTTON_LEFT
|| key
== BUTTON_RIGHT
|| key
== BUTTON_DOWN
|| key
== ( BUTTON_LEFT
| BUTTON_REPEAT
) || key
== ( BUTTON_RIGHT
| BUTTON_REPEAT
) || key
== ( BUTTON_DOWN
| BUTTON_REPEAT
) )
552 case BUTTON_F2
| BUTTON_LEFT
:
553 case BUTTON_F2
| BUTTON_LEFT
| BUTTON_REPEAT
:
554 global_settings
.playlist_shuffle
=
555 !global_settings
.playlist_shuffle
;
557 if(mpeg_status() & MPEG_STATUS_PLAY
)
559 if (global_settings
.playlist_shuffle
)
560 playlist_randomise(NULL
, current_tick
, true);
562 playlist_sort(NULL
, true);
567 case BUTTON_F2
| BUTTON_DOWN
:
568 case BUTTON_F2
| BUTTON_DOWN
| BUTTON_REPEAT
:
569 global_settings
.dirfilter
++;
570 if ( global_settings
.dirfilter
>= NUM_FILTER_MODES
)
571 global_settings
.dirfilter
= 0;
575 case BUTTON_F2
| BUTTON_RIGHT
:
576 case BUTTON_F2
| BUTTON_RIGHT
| BUTTON_REPEAT
:
577 global_settings
.repeat_mode
++;
578 if ( global_settings
.repeat_mode
>= NUM_REPEAT_MODES
)
579 global_settings
.repeat_mode
= 0;
583 case BUTTON_F3
| BUTTON_LEFT
:
584 case BUTTON_F3
| BUTTON_LEFT
| BUTTON_REPEAT
:
585 global_settings
.scrollbar
= !global_settings
.scrollbar
;
589 case BUTTON_F3
| BUTTON_RIGHT
:
590 case BUTTON_F3
| BUTTON_RIGHT
| BUTTON_REPEAT
:
591 global_settings
.statusbar
= !global_settings
.statusbar
;
595 case BUTTON_F3
| BUTTON_DOWN
:
596 case BUTTON_F3
| BUTTON_DOWN
| BUTTON_REPEAT
:
597 case BUTTON_F3
| BUTTON_UP
:
598 case BUTTON_F3
| BUTTON_UP
| BUTTON_REPEAT
:
599 global_settings
.flip_display
= !global_settings
.flip_display
;
600 button_set_flip(global_settings
.flip_display
);
601 lcd_set_flip(global_settings
.flip_display
);
605 case BUTTON_F3
| BUTTON_REL
:
606 case BUTTON_F2
| BUTTON_REL
:
615 case BUTTON_OFF
| BUTTON_REPEAT
:
618 case SYS_USB_CONNECTED
:
630 if ( oldrepeat
!= global_settings
.repeat_mode
)
631 mpeg_flush_and_reload_tracks();
636 if (global_settings
.statusbar
)
637 lcd_setmargins(0, STATUSBAR_HEIGHT
);
639 lcd_setmargins(0, 0);
644 lcd_setfont(FONT_UI
);
650 #ifdef HAVE_LCD_BITMAP
651 #define SPACE 3 /* pixels between words */
652 #define MAXLETTERS 128 /* 16*8 */
655 #define SPACE 1 /* one letter space */
660 #define MAXLETTERS 22 /* 11 * 2 */
664 void splash(int ticks
, /* how long the splash is displayed */
665 bool center
, /* FALSE means left-justified, TRUE means
666 horizontal and vertical center */
667 char *fmt
, /* what to say *printf style */
675 unsigned char splash_buf
[MAXLETTERS
];
677 unsigned char widths
[MAXLINES
];
680 #ifdef HAVE_LCD_BITMAP
685 vsnprintf( splash_buf
, sizeof(splash_buf
), fmt
, ap
);
689 /* first a pass to measure sizes */
690 next
= strtok_r(splash_buf
, " ", &store
);
692 #ifdef HAVE_LCD_BITMAP
693 lcd_getstringsize(next
, &w
, &h
);
696 h
= 1; /* store height in characters */
703 if((y
> (LCD_HEIGHT
-h
)) || (line
> MAXLINES
))
713 /* think of it as if the text was written here at position x,y
714 being w pixels/chars wide and h high */
717 widths
[line
]=x
-SPACE
; /* don't count the trailing space */
718 #ifdef HAVE_LCD_BITMAP
719 /* store the widest line */
720 if(widths
[line
]>maxw
)
723 next
= strtok_r(NULL
, " ", &store
);
725 #ifdef HAVE_LCD_BITMAP
726 /* Start displaying the message at position y. The reason for the
727 added h here is that it isn't added until the end of lines in the
728 loop above and we always break the loop in the middle of a line. */
729 y
= (LCD_HEIGHT
- (y
+h
) )/2;
731 y
= 0; /* vertical center on 2 lines would be silly */
735 /* Now recreate the string again since the strtok_r() above has ruined
736 the one we already have! Here's room for improvements! */
737 vsnprintf( splash_buf
, sizeof(splash_buf
), fmt
, ap
);
743 x
= (LCD_WIDTH
-widths
[0])/2;
748 #ifdef HAVE_LCD_BITMAP
749 /* If we center the display and it wouldn't cover the full screen,
750 then just clear the box we need and put a nice little frame and
751 put the text in there! */
752 if(center
&& (y
> 2)) {
753 if(maxw
< (LCD_WIDTH
-4)) {
754 int xx
= (LCD_WIDTH
-maxw
)/2 - 2;
755 lcd_clearrect(xx
, y
-2, maxw
+4, LCD_HEIGHT
-y
*2+4);
756 lcd_drawrect(xx
, y
-2, maxw
+4, LCD_HEIGHT
-y
*2+4);
759 lcd_clearrect(0, y
-2, LCD_WIDTH
, LCD_HEIGHT
-y
*2+4);
760 lcd_drawline(0, y
-2, LCD_WIDTH
-1, y
-2);
761 lcd_drawline(0, LCD_HEIGHT
-y
+2, LCD_WIDTH
-1, LCD_HEIGHT
-y
+2);
768 next
= strtok_r(splash_buf
, " ", &store
);
770 #ifdef HAVE_LCD_BITMAP
771 lcd_getstringsize(next
, &w
, &h
);
780 line
++; /* goto next line */
782 if(y
> (LCD_HEIGHT
-h
))
786 x
= (LCD_WIDTH
-widths
[line
])/2;
793 #ifdef HAVE_LCD_BITMAP
794 lcd_putsxy(x
, y
, next
);
796 lcd_puts(x
, y
, next
);
798 x
+= w
+SPACE
; /* pixels space! */
799 next
= strtok_r(NULL
, " ", &store
);
808 void charging_splash(void)
810 splash(2*HZ
, true, str(LANG_BATTERY_CHARGE
));
811 while (button_get(false));
815 #ifdef HAVE_LCD_BITMAP
817 /* little helper function for voice output */
818 static void say_time(int cursorpos
, struct tm
*tm
)
820 const int unit
[] = { UNIT_HOUR
, UNIT_MIN
, UNIT_SEC
, 0, 0, 0 };
823 if (!global_settings
.talk_menu
)
838 value
= tm
->tm_year
+ 1900;
845 if (cursorpos
== 4) /* month */
846 talk_id(LANG_MONTH_JANUARY
+ tm
->tm_mon
, false);
848 talk_value(value
, unit
[cursorpos
], false);
854 #define INDEX_WIDTH 2
855 bool set_time_screen(char* string
, struct tm
*tm
)
859 int min
= 0, steps
= 0;
861 int lastcursorpos
= !cursorpos
;
862 unsigned char buffer
[19];
866 unsigned char reffub
[5];
867 unsigned int width
, height
;
868 unsigned int separator_width
, weekday_width
;
869 unsigned int line_height
, prev_line_height
;
870 const int dayname
[] = {LANG_WEEKDAY_SUNDAY
,
872 LANG_WEEKDAY_TUESDAY
,
873 LANG_WEEKDAY_WEDNESDAY
,
874 LANG_WEEKDAY_THURSDAY
,
876 LANG_WEEKDAY_SATURDAY
};
877 const int monthname
[] = {LANG_MONTH_JANUARY
,
885 LANG_MONTH_SEPTEMBER
,
888 LANG_MONTH_DECEMBER
};
889 char cursor
[][3] = {{ 0, 8, 12}, {18, 8, 12}, {36, 8, 12},
890 {24, 16, 24}, {54, 16, 18}, {78, 16, 12}};
891 char daysinmonth
[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
893 int monthname_len
= 0, dayname_len
= 0;
897 #ifdef HAVE_LCD_BITMAP
898 if(global_settings
.statusbar
)
899 lcd_setmargins(0, STATUSBAR_HEIGHT
);
901 lcd_setmargins(0, 0);
904 lcd_puts_scroll(0, 0, string
);
907 /* calculate the number of days in febuary */
908 realyear
= tm
->tm_year
+ 1900;
909 if((realyear
% 4 == 0 && !(realyear
% 100 == 0)) || realyear
% 400 == 0)
914 /* fix day if month or year changed */
915 if (tm
->tm_mday
> daysinmonth
[tm
->tm_mon
])
916 tm
->tm_mday
= daysinmonth
[tm
->tm_mon
];
918 /* calculate day of week */
920 for(i
= 0; i
< tm
->tm_mon
; i
++) {
921 julianday
+= daysinmonth
[i
];
923 julianday
+= tm
->tm_mday
;
924 tm
->tm_wday
= (realyear
+ julianday
+ (realyear
- 1) / 4 -
925 (realyear
- 1) / 100 + (realyear
- 1) / 400 + 7 - 1) % 7;
927 snprintf(buffer
, sizeof(buffer
), "%02d:%02d:%02d ",
928 tm
->tm_hour
, tm
->tm_min
, tm
->tm_sec
);
929 lcd_puts(0, 1, buffer
);
931 /* recalculate the positions and offsets */
932 lcd_getstringsize(string
, &width
, &prev_line_height
);
933 lcd_getstringsize(buffer
, &width
, &line_height
);
934 lcd_getstringsize(":", &separator_width
, &height
);
937 strncpy(reffub
, buffer
, 2);
939 lcd_getstringsize(reffub
, &width
, &height
);
940 cursor
[0][INDEX_X
] = 0;
941 cursor
[0][INDEX_Y
] = prev_line_height
;
942 cursor
[0][INDEX_WIDTH
] = width
;
945 strncpy(reffub
, buffer
+ 3, 2);
947 lcd_getstringsize(reffub
, &width
, &height
);
948 cursor
[1][INDEX_X
] = cursor
[0][INDEX_WIDTH
] + separator_width
;
949 cursor
[1][INDEX_Y
] = prev_line_height
;
950 cursor
[1][INDEX_WIDTH
] = width
;
953 strncpy(reffub
, buffer
+ 6, 2);
955 lcd_getstringsize(reffub
, &width
, &height
);
956 cursor
[2][INDEX_X
] = cursor
[0][INDEX_WIDTH
] + separator_width
+
957 cursor
[1][INDEX_WIDTH
] + separator_width
;
958 cursor
[2][INDEX_Y
] = prev_line_height
;
959 cursor
[2][INDEX_WIDTH
] = width
;
961 lcd_getstringsize(buffer
, &width
, &prev_line_height
);
963 snprintf(buffer
, sizeof(buffer
), "%s %04d %s %02d ",
964 str(dayname
[tm
->tm_wday
]), tm
->tm_year
+1900,
965 str(monthname
[tm
->tm_mon
]), tm
->tm_mday
);
966 lcd_puts(0, 2, buffer
);
968 /* recalculate the positions and offsets */
969 lcd_getstringsize(buffer
, &width
, &line_height
);
971 /* store these 2 to prevent _repeated_ strlen calls */
972 monthname_len
= strlen(str(monthname
[tm
->tm_mon
]));
973 dayname_len
= strlen(str(dayname
[tm
->tm_wday
]));
976 strncpy(reffub
, buffer
, dayname_len
);
977 reffub
[dayname_len
] = '\0';
978 lcd_getstringsize(reffub
, &weekday_width
, &height
);
979 lcd_getstringsize(" ", &separator_width
, &height
);
982 strncpy(reffub
, buffer
+ dayname_len
+ 1, 4);
984 lcd_getstringsize(reffub
, &width
, &height
);
985 cursor
[3][INDEX_X
] = weekday_width
+ separator_width
;
986 cursor
[3][INDEX_Y
] = cursor
[0][INDEX_Y
] + prev_line_height
;
987 cursor
[3][INDEX_WIDTH
] = width
;
990 strncpy(reffub
, buffer
+ dayname_len
+ 6, monthname_len
);
991 reffub
[monthname_len
] = '\0';
992 lcd_getstringsize(reffub
, &width
, &height
);
993 cursor
[4][INDEX_X
] = weekday_width
+ separator_width
+
994 cursor
[3][INDEX_WIDTH
] + separator_width
;
995 cursor
[4][INDEX_Y
] = cursor
[0][INDEX_Y
] + prev_line_height
;
996 cursor
[4][INDEX_WIDTH
] = width
;
999 strncpy(reffub
, buffer
+ dayname_len
+ monthname_len
+ 7, 2);
1001 lcd_getstringsize(reffub
, &width
, &height
);
1002 cursor
[5][INDEX_X
] = weekday_width
+ separator_width
+
1003 cursor
[3][INDEX_WIDTH
] + separator_width
+
1004 cursor
[4][INDEX_WIDTH
] + separator_width
;
1005 cursor
[5][INDEX_Y
] = cursor
[0][INDEX_Y
] + prev_line_height
;
1006 cursor
[5][INDEX_WIDTH
] = width
;
1008 lcd_invertrect(cursor
[cursorpos
][INDEX_X
],
1009 cursor
[cursorpos
][INDEX_Y
] + lcd_getymargin(),
1010 cursor
[cursorpos
][INDEX_WIDTH
],
1013 lcd_puts(0, 4, str(LANG_TIME_SET
));
1014 lcd_puts(0, 5, str(LANG_TIME_REVERT
));
1015 #ifdef HAVE_LCD_BITMAP
1020 /* calculate the minimum and maximum for the number under cursor */
1021 if(cursorpos
!=lastcursorpos
) {
1022 lastcursorpos
=cursorpos
;
1027 valptr
= &tm
->tm_hour
;
1029 case 1: /* minute */
1032 valptr
= &tm
->tm_min
;
1034 case 2: /* second */
1037 valptr
= &tm
->tm_sec
;
1042 valptr
= &tm
->tm_year
;
1047 valptr
= &tm
->tm_mon
;
1051 steps
= daysinmonth
[tm
->tm_mon
];
1052 valptr
= &tm
->tm_mday
;
1055 say_time(cursorpos
, tm
);
1058 button
= button_get_w_tmo(HZ
/2);
1061 cursorpos
= (cursorpos
+ 6 - 1) % 6;
1064 cursorpos
= (cursorpos
+ 6 + 1) % 6;
1067 case BUTTON_UP
| BUTTON_REPEAT
:
1068 *valptr
= (*valptr
+ steps
- min
+ 1) %
1072 say_time(cursorpos
, tm
);
1075 case BUTTON_DOWN
| BUTTON_REPEAT
:
1076 *valptr
= (*valptr
+ steps
- min
- 1) %
1080 say_time(cursorpos
, tm
);
1090 case SYS_USB_CONNECTED
: