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