]> git.karo-electronics.de Git - oswald.git/blob - ui/oswald_screens.c
Bluetooth handling, screen reworks for icons
[oswald.git] / ui / oswald_screens.c
1 #include <stdio.h>
2
3 #include "oswald.h"
4 #include "oswald_main.h"
5 #include "oswald_watch_faces.h"
6 #include "Fonts.h"
7 #include "LcdDisplay.h"
8 #include "oswald_hal.h"
9
10 #include "oswald_screens.h"
11
12 #include "timesetup_icon.xbm"
13 #include "stopwatch_icon.xbm"
14 #include "alarm_icon.xbm"
15 #include "startstopbutton_icon.xbm"
16 #include "lapsebutton_icon.xbm"
17 #include "upbutton_icon.xbm"
18 #include "downbutton_icon.xbm"
19 #include "Bluetooth_icon.xbm"
20
21
22 typedef struct {
23         void (*screendraw_func)(boolean show_seconds);
24         boolean show_seconds;
25         boolean analogue;
26 } idle_data_t;
27 static idle_data_t idle_screen = {
28         DrawLcdDigitalClock,
29         TRUE,
30         FALSE,
31 };
32  
33 void idle_handle_user_buttons(watch_button button)
34 {
35         switch (button) {
36                 case BUTTON_A:
37                         if (idle_screen.show_seconds)
38                                 idle_screen.show_seconds = FALSE;
39                         else
40                                 idle_screen.show_seconds = TRUE;
41                         break;
42                 case BUTTON_B:
43                         if (idle_screen.analogue == TRUE) {
44                                 idle_screen.analogue = FALSE;
45                                 idle_screen.screendraw_func = DrawLcdDigitalClock;
46                         } else {
47                                 idle_screen.analogue = TRUE;
48                                 idle_screen.screendraw_func = DrawLcdAnaClock;
49                         };
50                         break;
51                 case BUTTON_F:
52                         OswaldState.screen_id = DATETIME_SETTING_SCREEN;
53                         OswaldState.screen = &OswaldScreens[OswaldState.screen_id];
54                         OswaldState.screen->event_func(EVENT_SCREEN_VISIBLE, NULL);
55                         return;
56                         break;
57                 default:
58                         break;
59         };
60         idle_screen.screendraw_func(idle_screen.show_seconds);
61 }
62
63 void idle_handle_events(u16t event, void *data)
64 {
65         switch (event) {
66                 case EVENT_ONE_SEC_TIMER:
67                 case EVENT_SCREEN_VISIBLE:
68                         idle_screen.screendraw_func(idle_screen.show_seconds);
69                         break;
70                 case EVENT_USER_BUTTONS:
71                         dbg_out("button event %d\n", *(int *)data);
72                         idle_handle_user_buttons(*(watch_button *)data);
73                         break;
74                 default:
75                         break;
76         };
77 }
78
79
80 typedef struct {
81         accel_data_t accdata;
82 } accelscreen_data_t;
83 static accelscreen_data_t accel_screen = {
84         { 0, 0, 0},
85 };
86
87 void draw_accel_screen(accel_data_t *accel_data)
88 {
89         hal_lcd_clear_display();
90         SetFont(MetaWatch16);
91         WriteLcdString(2, 2, "X:");
92         WriteLcdNumber(20, 2, accel_data->x);
93         WriteLcdString(2, 18, "Y:");
94         WriteLcdNumber(20, 18, accel_data->y);
95         WriteLcdString(2, 34, "Z:");
96         WriteLcdNumber(20, 34, accel_data->z);
97
98         WriteLcdString(2, 54, "Light:");
99         WriteLcdNumber(40, 54, accel_data->z);
100
101         hal_lcd_update_display();
102 }
103
104 void accel_handle_events(u16t event, void *data)
105 {
106         switch (event) {
107                 case EVENT_SCREEN_VISIBLE:
108                         draw_accel_screen(&accel_screen.accdata);
109                         break;
110                 case EVENT_ACCEL_UPDATE: {
111                         accel_data_t *accel_data = (accel_data_t *)data;
112                         accel_screen.accdata.x = accel_data->x;
113                         accel_screen.accdata.y = accel_data->y;
114                         accel_screen.accdata.z = accel_data->z;
115                         draw_accel_screen(&accel_screen.accdata);
116                         };
117                         break;
118                 case EVENT_USER_BUTTONS:
119                         dbg_out("button event %d\n", *(int *)data);
120                         break;
121                 default:
122                         break;
123         };
124 }
125
126
127 typedef struct {
128         u8t pos;
129         boolean on;
130 } datetime_setup_data_t;
131 static datetime_setup_data_t dt_setup_screen = {
132         0,
133         TRUE
134 };
135
136 void draw_datetime_setup_screen(datetime_setup_data_t *sdata)
137 {
138         hal_lcd_clear_display();
139 //      SetFont(MetaWatch16);
140 //      WriteLcdString(2, 2, "Set");
141         oswald_draw_bitmap(36, 0, timesetup_icon_width, timesetup_icon_height, timesetup_icon_bits);
142
143         oswald_draw_bitmap(81, 6, upbutton_icon_width, upbutton_icon_height, upbutton_icon_bits);
144         oswald_draw_bitmap(81, 38, downbutton_icon_width, downbutton_icon_height, downbutton_icon_bits);
145
146         SetFont(MetaWatchTime);
147         if ((sdata->pos == 0 && sdata->on) || sdata->pos != 0) {
148                 WriteLcdCharacter(2, 30, (OswaldClk.hour / 10));
149                 WriteLcdCharacter(14, 30, (OswaldClk.hour % 10));
150         }
151         WriteLcdCharacter(26, 30, TIME_CHARACTER_COLON_INDEX);
152
153         if ((sdata->pos == 1 && sdata->on) || sdata->pos != 1) {
154                 WriteLcdCharacter(31, 30, (OswaldClk.minute / 10));
155                 WriteLcdCharacter(43, 30, (OswaldClk.minute % 10));
156         }
157 /*
158         WriteLcdCharacter(55, 20, TIME_CHARACTER_COLON_INDEX);
159
160         if ((sdata->pos == 2 && sdata->on) || sdata->pos != 2) {
161                 WriteLcdCharacter(60, 20, (OswaldClk.second / 10));
162                 WriteLcdCharacter(72, 20, (OswaldClk.second % 10));
163         }
164 */
165         SetFont(MetaWatch16);
166         if ((sdata->pos == 2 && sdata->on) || sdata->pos != 2) {
167                 WriteLcdCharacter(59, 36, 0x30 + (OswaldClk.second / 10));
168                 WriteLcdCharacter(66, 36, 0x30 + (OswaldClk.second % 10));
169         }
170
171
172         if ((sdata->pos == 3 && sdata->on) || sdata->pos != 3) {
173                 WriteLcdNumber(2, 55, OswaldClk.day);
174         }
175         WriteLcdString(18, 55, ".");
176         if ((sdata->pos == 4 && sdata->on) || sdata->pos != 4) {
177                 WriteLcdNumber(22, 55, OswaldClk.month);
178         }
179         WriteLcdString(38, 55, ".");
180         if ((sdata->pos == 5 && sdata->on) || sdata->pos != 5) {
181                 WriteLcdNumber(42, 55, OswaldClk.year);
182         }
183
184         SetFont(MetaWatch7);
185         if ((sdata->pos == 6 && sdata->on) || sdata->pos != 6) {
186                 if (OswaldClk.clk24hr)
187                         WriteLcdString(2, 76, "x");
188                 else
189                         WriteLcdString(2, 76, "_");
190         }
191         WriteLcdString(15, 76, "24hr");
192
193         if ((sdata->pos == 7 && sdata->on) || sdata->pos != 7) {
194                 if (OswaldClk.day_first)
195                         WriteLcdString(2, 89, "x");
196                 else
197                         WriteLcdString(2, 89, "_");
198         }
199         WriteLcdString(15, 89, "dd.mm.  mm/dd");
200
201         hal_lcd_update_display();
202 }
203
204 void datetime_handle_updown(u8t pos, s8t incr)
205 {
206         switch (pos) {
207                 case 0: // hour
208                         if (OswaldClk.hour == 0 && incr == -1) {
209                                 OswaldClk.hour = 23;
210                                 break;
211                         };
212                         OswaldClk.hour += incr;
213                         if (OswaldClk.hour > 23)
214                                 OswaldClk.hour = 0;
215                         break;
216                 case 1: // minute
217                         if (OswaldClk.minute == 0 && incr == -1) {
218                                 OswaldClk.minute = 59;
219                                 break;
220                         };
221                         OswaldClk.minute += incr;
222                         if (OswaldClk.minute > 59)
223                                 OswaldClk.minute = 0;
224                         break;
225                 case 2: // second
226                         OswaldClk.second = 0;
227                         break;
228                 case 3: // day
229                         if (OswaldClk.day == 1 && incr == -1) {
230                                 OswaldClk.day = 31;
231                                 break;
232                         };
233                         OswaldClk.day += incr;
234                         if (OswaldClk.day > 31)
235                                 OswaldClk.day = 1;
236                         break;
237                 case 4: // month
238                         if (OswaldClk.month == 1 && incr == -1) {
239                                 OswaldClk.month = 12;
240                                 break;
241                         };
242                         OswaldClk.month += incr;
243                         if (OswaldClk.month > 12)
244                                 OswaldClk.month = 1;
245                         break;
246                 case 5: // year
247                         OswaldClk.year += incr;
248                         break;
249                 case 6: // 24hr / 12hr
250                         if (OswaldClk.clk24hr)
251                                 OswaldClk.clk24hr = FALSE;
252                         else
253                                 OswaldClk.clk24hr = TRUE;
254                         break;
255                 case 7: // dd.mm. / mm/dd
256                         if (OswaldClk.day_first)
257                                 OswaldClk.day_first = FALSE;
258                         else
259                                 OswaldClk.day_first = TRUE;
260                         break;
261                 default:
262                         break;
263         };
264         if (pos == 2)
265                 hal_set_rtc(&OswaldClk, TRUE);
266         else
267                 hal_set_rtc(&OswaldClk, FALSE);
268 }
269
270 void handle_setup_datetime_buttons(watch_button button, datetime_setup_data_t *sdata)
271 {
272         switch (button) {
273                 case BUTTON_A:
274                         datetime_handle_updown(sdata->pos, 1);
275                         break;
276                 case BUTTON_B:
277                         datetime_handle_updown(sdata->pos, -1);
278                         break;
279                 case BUTTON_F:
280                         sdata->pos++;
281                         sdata->pos %= 8;
282                         break;
283                 default:
284                         break;
285         }
286         draw_datetime_setup_screen(sdata);
287 }
288
289 void datetime_setup_events(u16t event, void *data)
290 {
291         switch (event) {
292                 case EVENT_SCREEN_VISIBLE:
293                         dt_setup_screen.pos = 0;
294                         draw_datetime_setup_screen(&dt_setup_screen);
295                         hal_enable_halfsecond_timer();
296                         break;
297                 case EVENT_SCREEN_DESTROY:
298                         hal_disable_halfsecond_timer();
299                         break;
300                 case EVENT_USER_BUTTONS:
301                         dbg_out("button event %d\n", *(int *)data);
302                         handle_setup_datetime_buttons(*(watch_button *)data, &dt_setup_screen);
303                         break;
304                 case EVENT_HALF_SEC_TIMER:
305                         if (dt_setup_screen.on)
306                                 dt_setup_screen.on = FALSE;
307                         else
308                                 dt_setup_screen.on = TRUE;
309                         draw_datetime_setup_screen(&dt_setup_screen);
310                         break;
311                 default:
312                         break;
313         };
314 }
315
316
317 /*
318  * Alarm setup
319  */
320
321 typedef struct {
322         u8t pos;
323         boolean on;
324 } alarm_setup_data_t;
325 static alarm_setup_data_t alarm_setup_screen = {
326         0,
327         TRUE
328 };
329
330 void draw_alarm_setup_screen(alarm_setup_data_t *sdata)
331 {
332         hal_lcd_clear_display();
333
334         oswald_draw_bitmap(36, 0, alarm_icon_width, alarm_icon_height, alarm_icon_bits);
335
336         oswald_draw_bitmap(81, 6, upbutton_icon_width, upbutton_icon_height, upbutton_icon_bits);
337         oswald_draw_bitmap(81, 38, downbutton_icon_width, downbutton_icon_height, downbutton_icon_bits);
338
339         SetFont(MetaWatchTime);
340         if ((sdata->pos == 0 && sdata->on) || sdata->pos != 0) {
341                 WriteLcdCharacter(22, 30, (OswaldAlarm.hour / 10));
342                 WriteLcdCharacter(34, 30, (OswaldAlarm.hour % 10));
343         }
344         WriteLcdCharacter(46, 30, TIME_CHARACTER_COLON_INDEX);
345
346         if ((sdata->pos == 1 && sdata->on) || sdata->pos != 1) {
347                 WriteLcdCharacter(51, 30, (OswaldAlarm.minute / 10));
348                 WriteLcdCharacter(63, 30, (OswaldAlarm.minute % 10));
349         }
350
351         SetFont(MetaWatchMonospaced10);
352         WriteLcdCharacter(3, 55, 'S');
353         WriteLcdCharacter(15, 55, 'M');
354         WriteLcdCharacter(27, 55, 'T');
355         WriteLcdCharacter(39, 55, 'W');
356         WriteLcdCharacter(51, 55, 'T');
357         WriteLcdCharacter(63, 55, 'F');
358         WriteLcdCharacter(75, 55, 'S');
359
360         if ((sdata->pos == 2 && sdata->on) || sdata->pos != 2)
361                 WriteLcdCharacter(3, 65, (OswaldAlarm.wday & WDAY_SUNDAY) ? 'x' : '_');
362         if ((sdata->pos == 3 && sdata->on) || sdata->pos != 3)
363                 WriteLcdCharacter(15, 65, (OswaldAlarm.wday & WDAY_MONDAY) ? 'x' : '_');
364         if ((sdata->pos == 4 && sdata->on) || sdata->pos != 4)
365                 WriteLcdCharacter(27, 65, (OswaldAlarm.wday & WDAY_TUESDAY) ? 'x' : '_');
366         if ((sdata->pos == 5 && sdata->on) || sdata->pos != 5)
367                 WriteLcdCharacter(39, 65, (OswaldAlarm.wday & WDAY_WEDNESDAY) ? 'x' : '_');
368         if ((sdata->pos == 6 && sdata->on) || sdata->pos != 6)
369                 WriteLcdCharacter(51, 65, (OswaldAlarm.wday & WDAY_THURSDAY) ? 'x' : '_');
370         if ((sdata->pos == 7 && sdata->on) || sdata->pos != 7)
371                 WriteLcdCharacter(63, 65, (OswaldAlarm.wday & WDAY_FRIDAY) ? 'x' : '_');
372         if ((sdata->pos == 8 && sdata->on) || sdata->pos != 8)
373                 WriteLcdCharacter(75, 65, (OswaldAlarm.wday & WDAY_SATURDAY) ? 'x' : '_');
374
375         hal_lcd_update_display();
376 }
377
378 void alarm_handle_updown(u8t pos, s8t incr)
379 {
380         switch (pos) {
381                 case 0: // hour
382                         if (OswaldAlarm.hour == 0 && incr == -1) {
383                                 OswaldAlarm.hour = 23;
384                                 break;
385                         };
386                         OswaldAlarm.hour += incr;
387                         if (OswaldAlarm.hour > 23)
388                                 OswaldAlarm.hour = 0;
389                         break;
390                 case 1: // minute
391                         if (OswaldAlarm.minute == 0 && incr == -1) {
392                                 OswaldAlarm.minute = 59;
393                                 break;
394                         };
395                         OswaldAlarm.minute += incr;
396                         if (OswaldAlarm.minute > 59)
397                                 OswaldAlarm.minute = 0;
398                         break;
399                 case 2: // sunday
400                         OswaldAlarm.wday ^= WDAY_SUNDAY;
401                         break;
402                 case 3: // monday
403                         OswaldAlarm.wday ^= WDAY_MONDAY;
404                         break;
405                 case 4: // tuesday
406                         OswaldAlarm.wday ^= WDAY_TUESDAY;
407                         break;
408                 case 5: // wednesday
409                         OswaldAlarm.wday ^= WDAY_WEDNESDAY;
410                         break;
411                 case 6: // thursday
412                         OswaldAlarm.wday ^= WDAY_THURSDAY;
413                         break;
414                 case 7: // friday
415                         OswaldAlarm.wday ^= WDAY_FRIDAY;
416                         break;
417                 case 8: // saturday
418                         OswaldAlarm.wday ^= WDAY_SATURDAY;
419                         break;
420                 default:
421                         break;
422         };
423 }
424
425 void handle_setup_alarm_buttons(watch_button button, alarm_setup_data_t *sdata)
426 {
427         switch (button) {
428                 case BUTTON_A:
429                         alarm_handle_updown(sdata->pos, 1);
430                         break;
431                 case BUTTON_B:
432                         alarm_handle_updown(sdata->pos, -1);
433                         break;
434                 case BUTTON_F:
435                         sdata->pos++;
436                         sdata->pos %= 9;
437                         break;
438                 default:
439                         break;
440         }
441         draw_alarm_setup_screen(sdata);
442 }
443
444 void alarm_setup_events(u16t event, void *data)
445 {
446         switch (event) {
447                 case EVENT_SCREEN_VISIBLE:
448                         alarm_setup_screen.pos = 0;
449                         draw_alarm_setup_screen(&alarm_setup_screen);
450                         hal_enable_halfsecond_timer();
451                         break;
452                 case EVENT_SCREEN_DESTROY:
453                         hal_disable_halfsecond_timer();
454                         break;
455                 case EVENT_USER_BUTTONS:
456                         dbg_out("button event %d\n", *(int *)data);
457                         handle_setup_alarm_buttons(*(watch_button *)data, &alarm_setup_screen);
458                         break;
459                 case EVENT_HALF_SEC_TIMER:
460                         if (alarm_setup_screen.on)
461                                 alarm_setup_screen.on = FALSE;
462                         else
463                                 alarm_setup_screen.on = TRUE;
464                         draw_alarm_setup_screen(&alarm_setup_screen);
465                         break;
466                 default:
467                         break;
468         };
469 }
470
471
472 /*
473  * Test menu
474  */
475
476 typedef struct {
477         u8t menu_pos;
478 } test_menu_t;
479 static test_menu_t test_menu = { 0 };
480
481 void draw_menu_test_screen(void)
482 {
483         hal_lcd_clear_display();
484         SetFont(MetaWatch16);
485         WriteLcdString(2, 2, "Menu");
486         SetFont(MetaWatch7);
487         WriteLcdString(2, 20, "Item 1");
488         WriteLcdString(2, 29, "Item 2");
489         WriteLcdString(2, 38, "Item 3");
490         WriteLcdString(2, 47, "Item 4");
491         WriteLcdString(2, 56, "Item 5");
492
493         WriteLcdString(50, 20+(9*test_menu.menu_pos), "*");
494         hal_lcd_update_display();
495 }
496
497 static void handle_menu_user_buttons(watch_button button)
498 {
499         switch (button) {
500                 case BUTTON_A:
501                         test_menu.menu_pos--;
502                         test_menu.menu_pos%=5;
503                         break;
504                 case BUTTON_B:
505                         test_menu.menu_pos++;
506                         test_menu.menu_pos%=5;
507                         break;
508                 default:
509                         break;
510         }
511         draw_menu_test_screen();
512 }
513
514 void test_menu_handle_events(u16t event, void *data)
515 {
516         switch (event) {
517                 case EVENT_USER_BUTTONS:
518                         dbg_out("button event %d\n", *(int *)data);
519                         handle_menu_user_buttons(*(watch_button *)data);
520                         break;
521                 case EVENT_SCREEN_VISIBLE:
522                         test_menu.menu_pos = 0;
523                         draw_menu_test_screen();
524                         break;
525                 default:
526                         break;
527         };
528 }
529
530
531 /*
532  * Stop Watch
533  */
534
535 typedef struct {
536         u8t hr;
537         u8t min;
538         u8t sec;
539         u8t csec;
540         u8t lapse_hr;
541         u8t lapse_min;
542         u8t lapse_sec;
543         u8t lapse_csec;
544         boolean running;
545 } stopwatch_data_t;
546 static stopwatch_data_t stopwatch_screen = { 0, 0, 0, 0, 0, 0, 0, 0, FALSE };
547
548
549 static void update_stop_watch_screen(stopwatch_data_t *sdata)
550 {
551         char tstr[16];
552         SetFont(MetaWatchMonospaced10);
553
554         snprintf(tstr, 16, "%02d:%02d:%02d.%1d", sdata->hr, sdata->min, sdata->sec, sdata->csec / 10);
555         WriteLcdString(5, 40, tstr);
556         snprintf(tstr, 16, "%02d:%02d:%02d.%02d", sdata->lapse_hr, sdata->lapse_min, sdata->lapse_sec, sdata->lapse_csec);
557         WriteLcdString(5, 60, tstr);
558
559         hal_lcd_update_display();
560 }
561
562 static void draw_stop_watch_screen(stopwatch_data_t *sdata)
563 {
564         oswald_draw_bitmap(36, 0, stopwatch_icon_width, stopwatch_icon_height, stopwatch_icon_bits);
565         oswald_draw_bitmap(81, 6, startstopbutton_icon_width, startstopbutton_icon_height, startstopbutton_icon_bits);
566         oswald_draw_bitmap(81, 38, lapsebutton_icon_width, lapsebutton_icon_height, lapsebutton_icon_bits);
567
568         update_stop_watch_screen(sdata);
569 }
570
571 static void handle_stop_watch_buttons(watch_button button)
572 {
573         switch (button) {
574                 case BUTTON_A: // start/stop
575                         if (stopwatch_screen.running) {
576                                 hal_disable_centisecond_timer();
577                                 stopwatch_screen.running = FALSE;
578                         } else {
579                                 hal_enable_centisecond_timer();
580                                 stopwatch_screen.running = TRUE;
581                         }
582                         break;
583                 case BUTTON_B: // lapse
584                         stopwatch_screen.lapse_hr = stopwatch_screen.hr;
585                         stopwatch_screen.lapse_min = stopwatch_screen.min;
586                         stopwatch_screen.lapse_sec = stopwatch_screen.sec;
587                         stopwatch_screen.lapse_csec = stopwatch_screen.csec;
588                         break;
589                 case BUTTON_F: // reset
590                         stopwatch_screen.hr = 0;
591                         stopwatch_screen.min = 0;
592                         stopwatch_screen.sec = 0;
593                         stopwatch_screen.csec = 0;
594                         stopwatch_screen.lapse_hr = 0;
595                         stopwatch_screen.lapse_min = 0;
596                         stopwatch_screen.lapse_sec = 0;
597                         stopwatch_screen.lapse_csec = 0;
598                         break;
599                 default:
600                         break;
601         }
602 }
603
604 void stop_watch_handle_events(u16t event, void *data)
605 {
606         switch (event) {
607                 case EVENT_USER_BUTTONS:
608                         dbg_out("button event %d\n", *(int *)data);
609                         handle_stop_watch_buttons(*(watch_button *)data);
610                         update_stop_watch_screen(&stopwatch_screen);
611                         break;
612                 case EVENT_SCREEN_VISIBLE:
613                         hal_lcd_clear_display();
614                         draw_stop_watch_screen(&stopwatch_screen);
615                         break;
616                 case EVENT_SCREEN_DESTROY:
617                         hal_disable_centisecond_timer();
618                         stopwatch_screen.running = FALSE;
619                         break;
620                 case EVENT_CS_TIMER:
621                         stopwatch_screen.csec++;
622                         if (stopwatch_screen.csec > 99) {
623                                 stopwatch_screen.csec = 0;
624                                 stopwatch_screen.sec++;
625                         };
626                         if (stopwatch_screen.sec > 59) {
627                                 stopwatch_screen.sec = 0;
628                                 stopwatch_screen.min++;
629                         };
630                         if (stopwatch_screen.min > 59) {
631                                 stopwatch_screen.min = 0;
632                                 stopwatch_screen.hr++;
633                         };
634                         if (stopwatch_screen.hr > 59) {
635                                 stopwatch_screen.hr = 0;
636                         };
637                         if (stopwatch_screen.csec % 10 == 0)
638                                 update_stop_watch_screen(&stopwatch_screen);
639                         break;
640                 default:
641                         break;
642         };
643 }
644
645
646 /*
647  * when alarm is fired
648  */
649 void draw_alarm_screen(void)
650 {
651         hal_lcd_clear_display();
652
653 //      SetFont(MetaWatch16);
654 //      WriteLcdString(2, 2, "ALARM !");
655         oswald_draw_bitmap(36, 20, alarm_icon_width, alarm_icon_height, alarm_icon_bits);
656
657
658         hal_lcd_update_display();
659 }
660
661 void alarm_handle_events(u16t event, void *data)
662 {
663         switch (event) {
664                 case EVENT_SCREEN_VISIBLE:
665                         draw_alarm_screen();
666                         hal_enable_halfsecond_timer();
667                         hal_vibration_set_state(TRUE);
668                         break;
669                 case EVENT_SCREEN_DESTROY:
670                         hal_disable_halfsecond_timer();
671                         hal_lcd_set_backlight(FALSE);
672                         hal_vibration_set_state(FALSE);
673                         break;
674                 case EVENT_USER_BUTTONS:
675                         dbg_out("button event %d\n", *(int *)data);
676                         // hal_lcd_set_backlight(FALSE);
677                         break;
678                 case EVENT_HALF_SEC_TIMER:
679                         hal_lcd_set_backlight(!hal_lcd_get_backlight());
680                         hal_vibration_set_state(!hal_vibration_get_state());
681                         dbg_out("timer\n");
682                         break;
683                 default:
684                         break;
685         };
686 }
687
688
689 /*
690  * Bluetooth screen
691  */
692 typedef struct {
693         u8t pos;
694         boolean bt_en;
695         boolean on;
696 } bluetooth_data_t;
697 static bluetooth_data_t bluetooth_screen = {
698         0,
699         FALSE,
700         TRUE
701 };
702
703 void draw_bluetooth_screen(bluetooth_data_t *sdata)
704 {
705         char bstr[20];
706         uint8_t *bd_addr;
707
708         hal_lcd_clear_display();
709
710         oswald_draw_bitmap(36, 0, Bluetooth_icon_width, Bluetooth_icon_height, Bluetooth_icon_bits);
711
712         oswald_draw_bitmap(81, 6, upbutton_icon_width, upbutton_icon_height, upbutton_icon_bits);
713         oswald_draw_bitmap(81, 38, downbutton_icon_width, downbutton_icon_height, downbutton_icon_bits);
714
715         SetFont(MetaWatch5);
716         WriteLcdString(2, 30, "Enable:");
717         if ((sdata->pos == 0 && sdata->on) || sdata->pos != 0) {
718                 WriteLcdCharacter(45, 30, bluetooth_screen.bt_en ? 'x' : '_');
719         }
720         WriteLcdString(2, 39, "State:");
721         switch (hal_bluetooth_get_state()) {
722                 case BLUETOOTH_OFF:
723                         WriteLcdString(45, 39, "off");
724                         break;
725                 case BLUETOOTH_ON:
726                         WriteLcdString(45, 39, "on");
727                         break;
728                 case BLUETOOTH_CONNECTED:
729                         WriteLcdString(45, 39, "conn.");
730                         break;
731                 default:
732                         break;
733         };
734         if (hal_bluetooth_get_state() >= BLUETOOTH_ON) {
735                 bd_addr = hal_bluetooth_get_local_bdaddr();
736                 snprintf(bstr, 20, "%02x:%02x:%02x:%02x:%02x:%02x", bd_addr[5], bd_addr[4], bd_addr[3], bd_addr[2], bd_addr[1], bd_addr[0]);
737                 WriteLcdString(2, 48, bstr);
738         } else {
739         }
740         WriteLcdString(2, 57, "Visible:");
741         if ((sdata->pos == 1 && sdata->on) || sdata->pos != 1) {
742                 WriteLcdCharacter(45, 57, hal_bluetooth_get_visible() ? 'x' : '_');
743         }
744
745         hal_lcd_update_display();
746 }
747
748 void bluetooth_handle_updown(u8t pos, s8t incr)
749 {
750         switch (pos) {
751                 case 0:
752                         if (hal_bluetooth_get_state() >= BLUETOOTH_ON) {
753                                 hal_bluetooth_set_state(BLUETOOTH_OFF);
754                                 bluetooth_screen.bt_en = FALSE;
755                         } else {
756                                 hal_bluetooth_set_state(BLUETOOTH_ON);
757                                 bluetooth_screen.bt_en = TRUE;
758                         }
759                         break;
760                 case 1:
761                         if (hal_bluetooth_get_state() >= BLUETOOTH_ON && !hal_bluetooth_get_visible()) {
762                                 hal_bluetooth_set_visible(TRUE);
763                         } else {
764                                 hal_bluetooth_set_visible(FALSE);
765                         }
766                         break;
767                 case 2:
768                         break;
769                 case 3:
770                         break;
771                 case 4:
772                         break;
773                 case 5:
774                         break;
775                 case 6:
776                         break;
777                 case 7:
778                         break;
779                 case 8:
780                         break;
781                 default:
782                         break;
783         };
784 }
785
786 void handle_bluetooth_buttons(watch_button button, bluetooth_data_t *sdata)
787 {
788         switch (button) {
789                 case BUTTON_A:
790                         bluetooth_handle_updown(sdata->pos, 1);
791                         break;
792                 case BUTTON_B:
793                         bluetooth_handle_updown(sdata->pos, -1);
794                         break;
795                 case BUTTON_F:
796                         sdata->pos++;
797                         sdata->pos %= 2;
798                         break;
799                 default:
800                         break;
801         }
802         draw_bluetooth_screen(sdata);
803 }
804
805 void bluetooth_screen_events(u16t event, void *data)
806 {
807         switch (event) {
808                 case EVENT_SCREEN_VISIBLE:
809                         bluetooth_screen.pos = 0;
810                         bluetooth_screen.bt_en = (hal_bluetooth_get_state() > 0);
811                         draw_bluetooth_screen(&bluetooth_screen);
812                         hal_enable_halfsecond_timer();
813                         break;
814                 case EVENT_SCREEN_DESTROY:
815                         hal_disable_halfsecond_timer();
816                         break;
817                 case EVENT_USER_BUTTONS:
818                         dbg_out("button event %d\n", *(int *)data);
819                         handle_bluetooth_buttons(*(watch_button *)data, &bluetooth_screen);
820                         break;
821                 case EVENT_HALF_SEC_TIMER:
822                         if (bluetooth_screen.on)
823                                 bluetooth_screen.on = FALSE;
824                         else
825                                 bluetooth_screen.on = TRUE;
826                         draw_bluetooth_screen(&bluetooth_screen);
827                         break;
828                 default:
829                         break;
830         };
831 }
832