]> git.karo-electronics.de Git - oswald.git/blob - ui/oswald_screens.c
Handle newline
[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/startstopbutton_icon.xbm"
15
16 #if defined(__GNUC__) && (__MSP430X__ > 0)
17 __attribute__((__far__))
18 #endif
19 #include "bitmaps/lapsebutton_icon.xbm"
20
21 #if defined(__GNUC__) && (__MSP430X__ > 0)
22 __attribute__((__far__))
23 #endif
24 #include "bitmaps/upbutton_icon.xbm"
25
26 #if defined(__GNUC__) && (__MSP430X__ > 0)
27 __attribute__((__far__))
28 #endif
29 #include "bitmaps/downbutton_icon.xbm"
30
31 #if defined(__GNUC__) && (__MSP430X__ > 0)
32 __attribute__((__far__))
33 #endif
34 #include "bitmaps/leftbutton_icon.xbm"
35
36 #if defined(__GNUC__) && (__MSP430X__ > 0)
37 __attribute__((__far__))
38 #endif
39 #include "bitmaps/rightbutton_icon.xbm"
40
41 #if defined(__GNUC__) && (__MSP430X__ > 0)
42 __attribute__((__far__))
43 #endif
44 #include "bitmaps/enterbutton_icon.xbm"
45
46 #if defined(__GNUC__) && (__MSP430X__ > 0)
47 __attribute__((__far__))
48 #endif
49 #include "bitmaps/checked_icon.xbm"
50
51 #if defined(__GNUC__) && (__MSP430X__ > 0)
52 __attribute__((__far__))
53 #endif
54 #include "bitmaps/unchecked_icon.xbm"
55
56 #if defined(__GNUC__) && (__MSP430X__ > 0)
57 __attribute__((__far__))
58 #endif
59 #include "bitmaps/main_menu_icon.xbm"
60
61 #if defined(__GNUC__) && (__MSP430X__ > 0)
62 __attribute__((__far__))
63 #endif
64 #include "bitmaps/timesetup_icon.xbm"
65
66 #if defined(__GNUC__) && (__MSP430X__ > 0)
67 __attribute__((__far__))
68 #endif
69 #include "bitmaps/stopwatch_icon.xbm"
70
71 #if defined(__GNUC__) && (__MSP430X__ > 0)
72 __attribute__((__far__))
73 #endif
74 #include "bitmaps/alarm_icon.xbm"
75
76 #if defined(__GNUC__) && (__MSP430X__ > 0)
77 __attribute__((__far__))
78 #endif
79 #include "bitmaps/Bluetooth_icon.xbm"
80
81 #if defined(__GNUC__) && (__MSP430X__ > 0)
82 __attribute__((__far__))
83 #endif
84 #include "bitmaps/info_icon.xbm"
85
86 #if defined(__GNUC__) && (__MSP430X__ > 0)
87 __attribute__((__far__))
88 #endif
89 #include "bitmaps/acc_icon.xbm"
90
91 #if defined(__GNUC__) && (__MSP430X__ > 0)
92 __attribute__((__far__))
93 #endif
94 #include "bitmaps/Message_icon.xbm"
95
96 #if defined(__GNUC__) && (__MSP430X__ > 0)
97 __attribute__((__far__))
98 #endif
99 #include "bitmaps/Exit_icon.xbm"
100
101
102 /*
103  * Common event handler part of the watch faces
104  */
105 typedef struct {
106         void (*screendraw_func)(boolean show_seconds);
107         boolean show_seconds;
108         boolean analogue;
109 } idle_data_t;
110 static idle_data_t idle_screen = {
111         DrawLcdDigitalClock,
112         TRUE,
113         FALSE,
114 };
115  
116 event_ret_t idle_handle_user_buttons(watch_button button)
117 {
118         switch (button) {
119                 case BUTTON_A:
120                         if (idle_screen.show_seconds)
121                                 idle_screen.show_seconds = FALSE;
122                         else
123                                 idle_screen.show_seconds = TRUE;
124                         break;
125                 case BUTTON_B:
126                         if (idle_screen.analogue == TRUE) {
127                                 idle_screen.analogue = FALSE;
128                                 idle_screen.screendraw_func = DrawLcdDigitalClock;
129                         } else {
130                                 idle_screen.analogue = TRUE;
131                                 idle_screen.screendraw_func = DrawLcdAnaClock;
132                         };
133                         break;
134                 case BUTTON_C:
135                         OswaldState.screen_id = MAIN_MENU_SCREEN;
136                         OswaldState.screen = &OswaldScreens[OswaldState.screen_id];
137                         OswaldState.screen->event_func(EVENT_SCREEN_VISIBLE, NULL);
138                         return EVENT_RET_HANDLED;
139                         break;
140                 case BUTTON_F:
141                         OswaldState.screen_id = DATETIME_SETTING_SCREEN;
142                         OswaldState.screen = &OswaldScreens[OswaldState.screen_id];
143                         OswaldState.screen->event_func(EVENT_SCREEN_VISIBLE, NULL);
144                         return EVENT_RET_HANDLED;
145                         break;
146                 default:
147                         return EVENT_RET_UNHANDLED;
148                         break;
149         };
150
151         idle_screen.screendraw_func(idle_screen.show_seconds);
152
153         return EVENT_RET_HANDLED;
154 }
155
156 event_ret_t idle_handle_events(uint16_t event, void *data)
157 {
158         switch (event) {
159                 case EVENT_ONE_SEC_TIMER:
160                 case EVENT_SCREEN_VISIBLE:
161                         idle_screen.screendraw_func(idle_screen.show_seconds);
162                         return EVENT_RET_HANDLED;
163                         break;
164                 case EVENT_USER_BUTTONS:
165                         dbg_out("button event %d\n", *(int *)data);
166                         return idle_handle_user_buttons(*(watch_button *)data);
167                         break;
168                 default:
169                         return EVENT_RET_UNHANDLED;
170                         break;
171         };
172         return EVENT_RET_UNHANDLED;
173 }
174
175
176 /*
177  * Main Menu Screen
178  */
179 typedef struct {
180         int8_t pos;
181         uint8_t tmo;
182 } main_menu_data_t;
183 static main_menu_data_t main_menu_screen = {
184         ALARM_SETUP_SCREEN,
185         0,
186 };
187
188 #define MAIN_MENU_GRID_PIXEL    84
189 #define MAIN_MENU_GRID_X        3
190 // GRID_Y is +1 since there is one empty row for title icon
191 #define MAIN_MENU_GRID_Y        3
192 #define MAIN_MENU_GRID_SPACING  0
193 #define MAIN_MENU_OFFSET_X      3
194 #define MAIN_MENU_OFFSET_Y      10
195
196 void draw_main_menu_screen(main_menu_data_t *sdata)
197 {
198         uint8_t pf = sdata->pos - 2;
199
200         hal_lcd_clear_display();
201
202 //      oswald_draw_bitmap(36, 0, main_menu_icon_width, main_menu_icon_height, main_menu_icon_bits);
203
204         oswald_draw_bitmap(81, 6, rightbutton_icon_width, rightbutton_icon_height, rightbutton_icon_bits);
205         oswald_draw_bitmap(81, 38, leftbutton_icon_width, leftbutton_icon_height, leftbutton_icon_bits);
206         oswald_draw_bitmap(81, 70, enterbutton_icon_width, enterbutton_icon_height, enterbutton_icon_bits);
207
208         oswald_draw_bitmpa_invert_opt(MAIN_MENU_OFFSET_X+((0+1) * MAIN_MENU_GRID_SPACING) + (0 * (MAIN_MENU_GRID_PIXEL / MAIN_MENU_GRID_X)),
209                 MAIN_MENU_OFFSET_Y+(0 * (MAIN_MENU_GRID_PIXEL / MAIN_MENU_GRID_Y)),
210                 alarm_icon_width, alarm_icon_height, alarm_icon_bits, (sdata->pos == ALARM_SETUP_SCREEN));
211         oswald_draw_bitmpa_invert_opt(MAIN_MENU_OFFSET_X+((1+1) * MAIN_MENU_GRID_SPACING) + (1 * (MAIN_MENU_GRID_PIXEL / MAIN_MENU_GRID_X)),
212                 MAIN_MENU_OFFSET_Y+(0 * (MAIN_MENU_GRID_PIXEL / MAIN_MENU_GRID_Y)),
213                 stopwatch_icon_width, stopwatch_icon_height, stopwatch_icon_bits, (sdata->pos == STOP_WATCH_SCREEN));
214         oswald_draw_bitmpa_invert_opt(MAIN_MENU_OFFSET_X+((2+1) * MAIN_MENU_GRID_SPACING) + (2 * (MAIN_MENU_GRID_PIXEL / MAIN_MENU_GRID_X)),
215                 MAIN_MENU_OFFSET_Y+(0 * (MAIN_MENU_GRID_PIXEL / MAIN_MENU_GRID_Y)),
216                 Bluetooth_icon_width, Bluetooth_icon_height, Bluetooth_icon_bits, (sdata->pos == BLUETOOTH_SCREEN));
217         oswald_draw_bitmpa_invert_opt(MAIN_MENU_OFFSET_X+((0+1) * MAIN_MENU_GRID_SPACING) + (0 * (MAIN_MENU_GRID_PIXEL / MAIN_MENU_GRID_X)),
218                 MAIN_MENU_OFFSET_Y+(1 * (MAIN_MENU_GRID_PIXEL / MAIN_MENU_GRID_Y)),
219                 acc_icon_width, acc_icon_height, acc_icon_bits, (sdata->pos == ACCEL_DISPLAY_SCREEN));
220         oswald_draw_bitmpa_invert_opt(MAIN_MENU_OFFSET_X+((1+1) * MAIN_MENU_GRID_SPACING) + (1 * (MAIN_MENU_GRID_PIXEL / MAIN_MENU_GRID_X)),
221                 MAIN_MENU_OFFSET_Y+(1 * (MAIN_MENU_GRID_PIXEL / MAIN_MENU_GRID_Y)),
222                 Message_icon_width, Message_icon_height, Message_icon_bits, (sdata->pos == MESSAGES_SCREEN));
223         oswald_draw_bitmpa_invert_opt(MAIN_MENU_OFFSET_X+((2+1) * MAIN_MENU_GRID_SPACING) + (2 * (MAIN_MENU_GRID_PIXEL / MAIN_MENU_GRID_X)),
224                 MAIN_MENU_OFFSET_Y+(1 * (MAIN_MENU_GRID_PIXEL / MAIN_MENU_GRID_Y)),
225                 info_icon_width, info_icon_height, info_icon_bits, (sdata->pos == INFO_SCREEN));
226         oswald_draw_bitmpa_invert_opt(MAIN_MENU_OFFSET_X+((0+1) * MAIN_MENU_GRID_SPACING) + (0 * (MAIN_MENU_GRID_PIXEL / MAIN_MENU_GRID_X)),
227                 MAIN_MENU_OFFSET_Y+(2 * (MAIN_MENU_GRID_PIXEL / MAIN_MENU_GRID_Y)),
228                 Exit_icon_width, Exit_icon_height, Exit_icon_bits, (sdata->pos == LAST_SCREEN));
229
230         // round the corners of the inverted icon a little
231         hal_lcd_set_pixel(MAIN_MENU_OFFSET_X+((pf%MAIN_MENU_GRID_X) * (MAIN_MENU_GRID_PIXEL / MAIN_MENU_GRID_X)) % (MAIN_MENU_GRID_X*(MAIN_MENU_GRID_PIXEL / MAIN_MENU_GRID_X)),
232                 MAIN_MENU_OFFSET_Y+((pf/MAIN_MENU_GRID_X) * (MAIN_MENU_GRID_PIXEL / MAIN_MENU_GRID_Y)) % (MAIN_MENU_GRID_Y*(MAIN_MENU_GRID_PIXEL / MAIN_MENU_GRID_Y)), FALSE);
233         hal_lcd_set_pixel(MAIN_MENU_OFFSET_X+23+((pf%MAIN_MENU_GRID_X) * (MAIN_MENU_GRID_PIXEL / MAIN_MENU_GRID_X)) % (MAIN_MENU_GRID_X*(MAIN_MENU_GRID_PIXEL / MAIN_MENU_GRID_X)),
234                 MAIN_MENU_OFFSET_Y+((pf/MAIN_MENU_GRID_X) * (MAIN_MENU_GRID_PIXEL / MAIN_MENU_GRID_Y)) % (MAIN_MENU_GRID_Y*(MAIN_MENU_GRID_PIXEL / MAIN_MENU_GRID_Y)), FALSE);
235         hal_lcd_set_pixel(MAIN_MENU_OFFSET_X+((pf%MAIN_MENU_GRID_X) * (MAIN_MENU_GRID_PIXEL / MAIN_MENU_GRID_X)) % (MAIN_MENU_GRID_X*(MAIN_MENU_GRID_PIXEL / MAIN_MENU_GRID_X)),
236                 MAIN_MENU_OFFSET_Y+23+((pf/MAIN_MENU_GRID_X) * (MAIN_MENU_GRID_PIXEL / MAIN_MENU_GRID_Y)) % (MAIN_MENU_GRID_Y*(MAIN_MENU_GRID_PIXEL / MAIN_MENU_GRID_Y)), FALSE);
237         hal_lcd_set_pixel(MAIN_MENU_OFFSET_X+23+((pf%MAIN_MENU_GRID_X) * (MAIN_MENU_GRID_PIXEL / MAIN_MENU_GRID_X)) % (MAIN_MENU_GRID_X*(MAIN_MENU_GRID_PIXEL / MAIN_MENU_GRID_X)),
238                 MAIN_MENU_OFFSET_Y+23+((pf/MAIN_MENU_GRID_X) * (MAIN_MENU_GRID_PIXEL / MAIN_MENU_GRID_Y)) % (MAIN_MENU_GRID_Y*(MAIN_MENU_GRID_PIXEL / MAIN_MENU_GRID_Y)), FALSE);
239
240         hal_lcd_update_display();
241 }
242
243 event_ret_t handle_main_menu_buttons(watch_button button, main_menu_data_t *sdata)
244 {
245         switch (button) {
246                 case BUTTON_A:
247                         sdata->pos++;
248                         if (sdata->pos > LAST_SCREEN)
249                                 sdata->pos = 2;
250                         draw_main_menu_screen(&main_menu_screen);
251                         return EVENT_RET_HANDLED;
252                         break;
253                 case BUTTON_B:
254                         sdata->pos--;
255                         if (sdata->pos < 2)
256                                 sdata->pos = LAST_SCREEN;
257                         draw_main_menu_screen(&main_menu_screen);
258                         return EVENT_RET_HANDLED;
259                         break;
260                 case BUTTON_C:
261                         if (sdata->pos < LAST_SCREEN) {
262                                 OswaldState.screen_id = sdata->pos;
263                                 OswaldState.screen = &OswaldScreens[OswaldState.screen_id];
264                                 OswaldState.screen->event_func(EVENT_SCREEN_VISIBLE, NULL);
265                         } else {
266                                 OswaldState.screen_id = IDLE_SCREEN;
267                                 OswaldState.screen = &OswaldScreens[OswaldState.screen_id];
268                                 OswaldState.screen->event_func(EVENT_SCREEN_VISIBLE, NULL);
269                         }
270                         return EVENT_RET_HANDLED;
271                         break;
272                 default:
273                         break;
274         }
275
276         return EVENT_RET_UNHANDLED;
277 }
278
279 /* after MAIN_MENU_TIMEOUT seconds return to IDLE_SCREEN */
280 #define MAIN_MENU_TIMEOUT       10
281
282 event_ret_t main_menu_handle_events(uint16_t event, void *data)
283 {
284         switch (event) {
285                 case EVENT_SCREEN_VISIBLE:
286                         main_menu_screen.tmo = 0;
287                         main_menu_screen.pos = 2;
288                         draw_main_menu_screen(&main_menu_screen);
289                         return EVENT_RET_HANDLED;
290                         break;
291                 case EVENT_USER_BUTTONS:
292                         dbg_out("button event %d\n", *(int *)data);
293                         main_menu_screen.tmo = 0;
294                         return handle_main_menu_buttons(*(watch_button *)data, &main_menu_screen);
295                         break;
296                 case EVENT_ONE_SEC_TIMER:
297                         main_menu_screen.tmo++;
298                         if (main_menu_screen.tmo > MAIN_MENU_TIMEOUT) {
299                                 OswaldState.screen_id = IDLE_SCREEN;
300                                 OswaldState.screen = &OswaldScreens[OswaldState.screen_id];
301                                 OswaldState.screen->event_func(EVENT_SCREEN_VISIBLE, NULL);
302                         }
303                         return EVENT_RET_HANDLED;
304                 default:
305                         break;
306         };
307         return EVENT_RET_UNHANDLED;
308 }
309
310
311 /*
312  * Accelerometer and sensor display screen
313  */
314 typedef struct {
315         accel_data_t accdata;
316 } accelscreen_data_t;
317 static accelscreen_data_t accel_screen = {
318         { 0, 0, 0},
319 };
320
321 void draw_accel_screen(accel_data_t *accel_data)
322 {
323         uint8_t x,y;
324
325         hal_lcd_clear_display();
326
327         oswald_draw_bitmap(36, 0, acc_icon_width, acc_icon_height, acc_icon_bits);
328
329         oswald_draw_bitmap(81, 79, enterbutton_icon_width, enterbutton_icon_height, enterbutton_icon_bits);
330
331         oswald_write_string(1, 40, FONT_6x9, FALSE, "X:");
332         oswald_write_number(15, 40, FONT_6x9, FALSE, accel_data->x);
333         oswald_write_string(1, 52, FONT_6x9, FALSE, "Y:");
334         oswald_write_number(15, 52, FONT_6x9, FALSE, accel_data->y);
335         oswald_write_string(1, 64, FONT_6x9, FALSE, "Z:");
336         oswald_write_number(15, 64, FONT_6x9, FALSE, accel_data->z);
337
338         oswald_write_string(1, 85, FONT_6x9, FALSE, "Light:");
339         oswald_write_number(50, 85, FONT_6x9, FALSE, 0);
340
341         oswald_draw_line(40, 30, 92, 30);
342         oswald_draw_line(92, 30, 92, 82);
343         oswald_draw_line(40, 82, 92, 82);
344         oswald_draw_line(40, 82, 40, 30);
345
346         x = 41+25+((accel_data->x * 50) / (254));
347         y = 31+25-((accel_data->y * 50) / (254));
348         oswald_draw_pixel(x, y, TRUE);
349         oswald_draw_pixel(x+1, y, TRUE);
350         oswald_draw_pixel(x-1, y, TRUE);
351         oswald_draw_pixel(x, y+1, TRUE);
352         oswald_draw_pixel(x, y-1, TRUE);
353
354         hal_lcd_update_display();
355 }
356
357 event_ret_t accel_handle_events(uint16_t event, void *data)
358 {
359         switch (event) {
360                 case EVENT_SCREEN_VISIBLE:
361                         draw_accel_screen(&accel_screen.accdata);
362                         hal_accelerometer_enable();
363                         return EVENT_RET_HANDLED;
364                         break;
365                 case EVENT_SCREEN_DESTROY:
366                         hal_accelerometer_disable();
367                         return EVENT_RET_HANDLED;
368                         break;
369                 case EVENT_ACCEL_UPDATE: {
370                         accel_data_t *accel_data = (accel_data_t *)data;
371                         accel_screen.accdata.x = accel_data->x;
372                         accel_screen.accdata.y = accel_data->y;
373                         accel_screen.accdata.z = accel_data->z;
374                         draw_accel_screen(&accel_screen.accdata);
375                         };
376                         return EVENT_RET_HANDLED;
377                         break;
378                 case EVENT_USER_BUTTONS:
379                         dbg_out("button event %d\n", *(int *)data);
380                         break;
381                 default:
382                         return EVENT_RET_UNHANDLED;
383                         break;
384         };
385         return EVENT_RET_UNHANDLED;
386 }
387
388
389 /*
390  * Date / time setup screen
391  */
392 typedef struct {
393         uint8_t pos;
394         boolean set_mode;
395         boolean on;
396 } datetime_setup_data_t;
397 static datetime_setup_data_t dt_setup_screen = {
398         0,
399         FALSE,
400         TRUE
401 };
402
403 void draw_datetime_setup_screen(datetime_setup_data_t *sdata)
404 {
405         hal_lcd_clear_display();
406
407         oswald_draw_bitmap(36, 0, timesetup_icon_width, timesetup_icon_height, timesetup_icon_bits);
408
409         oswald_draw_bitmap(81, 6, upbutton_icon_width, upbutton_icon_height, upbutton_icon_bits);
410         oswald_draw_bitmap(81, 38, downbutton_icon_width, downbutton_icon_height, downbutton_icon_bits);
411         oswald_draw_bitmap(81, 70, rightbutton_icon_width, rightbutton_icon_height, rightbutton_icon_bits);
412
413         if ((sdata->pos == 0 && sdata->on) || sdata->pos != 0) {
414                 oswald_write_character(2, 30, FONT_LCD13x21, FALSE, (OswaldClk.hour / 10));
415                 oswald_write_character(15, 30, FONT_LCD13x21, FALSE, (OswaldClk.hour % 10));
416         }
417         oswald_write_character(25, 30, FONT_LCD13x21, FALSE, 10);
418
419         if ((sdata->pos == 1 && sdata->on) || sdata->pos != 1) {
420                 oswald_write_character(34, 30, FONT_LCD13x21, FALSE, (OswaldClk.minute / 10));
421                 oswald_write_character(47, 30, FONT_LCD13x21, FALSE, (OswaldClk.minute % 10));
422         }
423
424         if ((sdata->pos == 2 && sdata->on) || sdata->pos != 2) {
425                 oswald_write_character(61, 38, FONT_LCD8x13, FALSE, (OswaldClk.second / 10));
426                 oswald_write_character(69, 38, FONT_LCD8x13, FALSE, (OswaldClk.second % 10));
427         }
428
429
430         if ((sdata->pos == 3 && sdata->on) || sdata->pos != 3) {
431                 oswald_write_number(2, 55, FONT_DROID8x12, FALSE, OswaldClk.day);
432         }
433         oswald_write_character(15, 55, FONT_DROID8x12, FALSE, '.');
434         if ((sdata->pos == 4 && sdata->on) || sdata->pos != 4) {
435                 oswald_write_number(21, 55, FONT_DROID8x12, FALSE, OswaldClk.month);
436         }
437         oswald_write_character(36, 55, FONT_DROID8x12, FALSE, '.');
438         if ((sdata->pos == 5 && sdata->on) || sdata->pos != 5) {
439                 oswald_write_number(43, 55, FONT_DROID8x12, FALSE, OswaldClk.year);
440         }
441
442         if ((sdata->pos == 6 && sdata->on) || sdata->pos != 6) {
443                 if (OswaldClk.clk24hr) {
444                         oswald_draw_bitmap(2, 76, checked_icon_width, checked_icon_height, checked_icon_bits);
445                 } else {
446                         oswald_draw_bitmap(2, 76, unchecked_icon_width, unchecked_icon_height, unchecked_icon_bits);
447                 }
448         }
449         oswald_write_string(15, 73, FONT_DROID8x12, FALSE, "24hr");
450
451         if ((sdata->pos == 7 && sdata->on) || sdata->pos != 7) {
452                 if (OswaldClk.day_first) {
453                         oswald_draw_bitmap(2, 86, checked_icon_width, checked_icon_height, checked_icon_bits);
454                 } else {
455                         oswald_draw_bitmap(2, 86, unchecked_icon_width, unchecked_icon_height, unchecked_icon_bits);
456                 }
457         }
458         oswald_write_string(15, 83, FONT_DROID8x12, FALSE, "dd.mm.  mm/dd");
459
460         hal_lcd_update_display();
461 }
462
463 void datetime_handle_updown(uint8_t pos, int8_t incr)
464 {
465         switch (pos) {
466                 case 0: // hour
467                         if (OswaldClk.hour == 0 && incr == -1) {
468                                 OswaldClk.hour = 23;
469                                 break;
470                         };
471                         OswaldClk.hour += incr;
472                         if (OswaldClk.hour > 23)
473                                 OswaldClk.hour = 0;
474                         break;
475                 case 1: // minute
476                         if (OswaldClk.minute == 0 && incr == -1) {
477                                 OswaldClk.minute = 59;
478                                 break;
479                         };
480                         OswaldClk.minute += incr;
481                         if (OswaldClk.minute > 59)
482                                 OswaldClk.minute = 0;
483                         break;
484                 case 2: // second
485                         OswaldClk.second = 0;
486                         break;
487                 case 3: // day
488                         if (OswaldClk.day == 1 && incr == -1) {
489                                 OswaldClk.day = 31;
490                                 break;
491                         };
492                         OswaldClk.day += incr;
493                         if (OswaldClk.day > 31)
494                                 OswaldClk.day = 1;
495                         break;
496                 case 4: // month
497                         if (OswaldClk.month == 1 && incr == -1) {
498                                 OswaldClk.month = 12;
499                                 break;
500                         };
501                         OswaldClk.month += incr;
502                         if (OswaldClk.month > 12)
503                                 OswaldClk.month = 1;
504                         break;
505                 case 5: // year
506                         OswaldClk.year += incr;
507                         break;
508                 case 6: // 24hr / 12hr
509                         if (OswaldClk.clk24hr)
510                                 OswaldClk.clk24hr = FALSE;
511                         else
512                                 OswaldClk.clk24hr = TRUE;
513                         break;
514                 case 7: // dd.mm. / mm/dd
515                         if (OswaldClk.day_first)
516                                 OswaldClk.day_first = FALSE;
517                         else
518                                 OswaldClk.day_first = TRUE;
519                         break;
520                 default:
521                         break;
522         };
523         if (pos == 2)
524                 hal_set_rtc(&OswaldClk, TRUE);
525         else
526                 hal_set_rtc(&OswaldClk, FALSE);
527 }
528
529 event_ret_t handle_setup_datetime_buttons(watch_button button, datetime_setup_data_t *sdata)
530 {
531         switch (button) {
532                 case BUTTON_A:
533                         datetime_handle_updown(sdata->pos, 1);
534                         break;
535                 case BUTTON_B:
536                         datetime_handle_updown(sdata->pos, -1);
537                         break;
538                 case BUTTON_C:
539                         sdata->pos++;
540                         sdata->pos %= 8;
541                         break;
542                 case BUTTON_F:
543                         OswaldState.screen->event_func(EVENT_SCREEN_DESTROY, NULL);
544                         OswaldState.screen_id = IDLE_SCREEN;
545                         OswaldState.screen = &OswaldScreens[OswaldState.screen_id];
546                         OswaldState.screen->event_func(EVENT_SCREEN_VISIBLE, NULL);
547                         return EVENT_RET_HANDLED;
548                         break;
549                 default:
550                         return EVENT_RET_UNHANDLED;
551                         break;
552         }
553         draw_datetime_setup_screen(sdata);
554         return EVENT_RET_HANDLED;
555 }
556
557 event_ret_t datetime_setup_events(uint16_t event, void *data)
558 {
559         switch (event) {
560                 case EVENT_SCREEN_VISIBLE:
561                         dt_setup_screen.pos = 0;
562                         draw_datetime_setup_screen(&dt_setup_screen);
563                         hal_enable_halfsecond_timer();
564                         return EVENT_RET_HANDLED;
565                         break;
566                 case EVENT_SCREEN_DESTROY:
567                         hal_disable_halfsecond_timer();
568                         return EVENT_RET_HANDLED;
569                         break;
570                 case EVENT_USER_BUTTONS:
571                         dbg_out("button event %d\n", *(int *)data);
572                         return handle_setup_datetime_buttons(*(watch_button *)data, &dt_setup_screen);
573                         break;
574                 case EVENT_HALF_SEC_TIMER:
575                         if (dt_setup_screen.on)
576                                 dt_setup_screen.on = FALSE;
577                         else
578                                 dt_setup_screen.on = TRUE;
579                         draw_datetime_setup_screen(&dt_setup_screen);
580                         return EVENT_RET_HANDLED;
581                         break;
582                 default:
583                         return EVENT_RET_UNHANDLED;
584                         break;
585         };
586         return EVENT_RET_UNHANDLED;
587 }
588
589
590 /*
591  * Alarm setup screen
592  */
593 typedef struct {
594         uint8_t pos;
595         boolean set_mode;
596         boolean on;
597 } alarm_setup_data_t;
598 static alarm_setup_data_t alarm_setup_screen = {
599         0,
600         FALSE,
601         TRUE
602 };
603
604 void draw_alarm_setup_screen(alarm_setup_data_t *sdata)
605 {
606         hal_lcd_clear_display();
607
608         oswald_draw_bitmap(36, 0, alarm_icon_width, alarm_icon_height, alarm_icon_bits);
609
610         if (sdata->set_mode) {
611                 oswald_draw_bitmap(81, 6, upbutton_icon_width, upbutton_icon_height, upbutton_icon_bits);
612                 oswald_draw_bitmap(81, 38, downbutton_icon_width, downbutton_icon_height, downbutton_icon_bits);
613                 oswald_draw_bitmap(81, 70, rightbutton_icon_width, rightbutton_icon_height, rightbutton_icon_bits);
614         } else {
615                 oswald_draw_bitmap(81, 70, enterbutton_icon_width, enterbutton_icon_height, enterbutton_icon_bits);
616         }
617
618         if ((sdata->pos == 0 && sdata->on) || sdata->pos != 0) {
619                 oswald_write_character(18, 30, FONT_LCD13x21, FALSE, (OswaldAlarm.hour / 10));
620                 oswald_write_character(32, 30, FONT_LCD13x21, FALSE, (OswaldAlarm.hour % 10));
621         }
622         oswald_write_character(42, 30, FONT_LCD13x21, FALSE, 10);
623
624         if ((sdata->pos == 1 && sdata->on) || sdata->pos != 1) {
625                 oswald_write_character(53, 30, FONT_LCD13x21, FALSE, (OswaldAlarm.minute / 10));
626                 oswald_write_character(67, 30, FONT_LCD13x21, FALSE, (OswaldAlarm.minute % 10));
627         }
628
629         oswald_write_character(3, 55, FONT_6x9, FALSE, 'S');
630         oswald_write_character(15, 55, FONT_6x9, FALSE, 'M');
631         oswald_write_character(27, 55, FONT_6x9, FALSE, 'T');
632         oswald_write_character(39, 55, FONT_6x9, FALSE, 'W');
633         oswald_write_character(51, 55, FONT_6x9, FALSE, 'T');
634         oswald_write_character(63, 55, FONT_6x9, FALSE, 'F');
635         oswald_write_character(75, 55, FONT_6x9, FALSE, 'S');
636
637         if ((sdata->pos == 2 && sdata->on) || sdata->pos != 2) {
638                 // oswald_write_character(3, 65, FONT_6x9, (OswaldAlarm.wday & WDAY_SUNDAY) ? 'x' : '_');
639                 if ((OswaldAlarm.wday & WDAY_SUNDAY))
640                         oswald_draw_bitmap(3, 66, checked_icon_width, checked_icon_height, checked_icon_bits);
641                 else
642                         oswald_draw_bitmap(3, 66, unchecked_icon_width, unchecked_icon_height, unchecked_icon_bits);
643         }
644         if ((sdata->pos == 3 && sdata->on) || sdata->pos != 3) {
645                 // oswald_write_character(15, 65, FONT_6x9, (OswaldAlarm.wday & WDAY_MONDAY) ? 'x' : '_');
646                 if ((OswaldAlarm.wday & WDAY_MONDAY))
647                         oswald_draw_bitmap(15, 66, checked_icon_width, checked_icon_height, checked_icon_bits);
648                 else
649                         oswald_draw_bitmap(15, 66, unchecked_icon_width, unchecked_icon_height, unchecked_icon_bits);
650         }
651         if ((sdata->pos == 4 && sdata->on) || sdata->pos != 4) {
652                 // oswald_write_character(27, 65, FONT_6x9, (OswaldAlarm.wday & WDAY_TUESDAY) ? 'x' : '_');
653                 if ((OswaldAlarm.wday & WDAY_TUESDAY))
654                         oswald_draw_bitmap(27, 66, checked_icon_width, checked_icon_height, checked_icon_bits);
655                 else
656                         oswald_draw_bitmap(27, 66, unchecked_icon_width, unchecked_icon_height, unchecked_icon_bits);
657         }
658         if ((sdata->pos == 5 && sdata->on) || sdata->pos != 5) {
659                 // oswald_write_character(39, 65, FONT_6x9, (OswaldAlarm.wday & WDAY_WEDNESDAY) ? 'x' : '_');
660                 if ((OswaldAlarm.wday & WDAY_WEDNESDAY))
661                         oswald_draw_bitmap(39, 66, checked_icon_width, checked_icon_height, checked_icon_bits);
662                 else
663                         oswald_draw_bitmap(39, 66, unchecked_icon_width, unchecked_icon_height, unchecked_icon_bits);
664         }
665         if ((sdata->pos == 6 && sdata->on) || sdata->pos != 6) {
666                 // oswald_write_character(51, 65, FONT_6x9, (OswaldAlarm.wday & WDAY_THURSDAY) ? 'x' : '_');
667                 if ((OswaldAlarm.wday & WDAY_THURSDAY))
668                         oswald_draw_bitmap(51, 66, checked_icon_width, checked_icon_height, checked_icon_bits);
669                 else
670                         oswald_draw_bitmap(51, 66, unchecked_icon_width, unchecked_icon_height, unchecked_icon_bits);
671         }
672         if ((sdata->pos == 7 && sdata->on) || sdata->pos != 7) {
673                 // oswald_write_character(63, 65, FONT_6x9, (OswaldAlarm.wday & WDAY_FRIDAY) ? 'x' : '_');
674                 if ((OswaldAlarm.wday & WDAY_FRIDAY))
675                         oswald_draw_bitmap(63, 66, checked_icon_width, checked_icon_height, checked_icon_bits);
676                 else
677                         oswald_draw_bitmap(63, 66, unchecked_icon_width, unchecked_icon_height, unchecked_icon_bits);
678         }
679         if ((sdata->pos == 8 && sdata->on) || sdata->pos != 8) {
680                 // oswald_write_character(75, 65, FONT_6x9, (OswaldAlarm.wday & WDAY_SATURDAY) ? 'x' : '_');
681                 if ((OswaldAlarm.wday & WDAY_SATURDAY))
682                         oswald_draw_bitmap(75, 66, checked_icon_width, checked_icon_height, checked_icon_bits);
683                 else
684                         oswald_draw_bitmap(75, 66, unchecked_icon_width, unchecked_icon_height, unchecked_icon_bits);
685         }
686
687         hal_lcd_update_display();
688 }
689
690 void alarm_handle_updown(uint8_t pos, int8_t incr)
691 {
692         switch (pos) {
693                 case 0: // hour
694                         if (OswaldAlarm.hour == 0 && incr == -1) {
695                                 OswaldAlarm.hour = 23;
696                                 break;
697                         };
698                         OswaldAlarm.hour += incr;
699                         if (OswaldAlarm.hour > 23)
700                                 OswaldAlarm.hour = 0;
701                         break;
702                 case 1: // minute
703                         if (OswaldAlarm.minute == 0 && incr == -1) {
704                                 OswaldAlarm.minute = 59;
705                                 break;
706                         };
707                         OswaldAlarm.minute += incr;
708                         if (OswaldAlarm.minute > 59)
709                                 OswaldAlarm.minute = 0;
710                         break;
711                 case 2: // sunday
712                         OswaldAlarm.wday ^= WDAY_SUNDAY;
713                         break;
714                 case 3: // monday
715                         OswaldAlarm.wday ^= WDAY_MONDAY;
716                         break;
717                 case 4: // tuesday
718                         OswaldAlarm.wday ^= WDAY_TUESDAY;
719                         break;
720                 case 5: // wednesday
721                         OswaldAlarm.wday ^= WDAY_WEDNESDAY;
722                         break;
723                 case 6: // thursday
724                         OswaldAlarm.wday ^= WDAY_THURSDAY;
725                         break;
726                 case 7: // friday
727                         OswaldAlarm.wday ^= WDAY_FRIDAY;
728                         break;
729                 case 8: // saturday
730                         OswaldAlarm.wday ^= WDAY_SATURDAY;
731                         break;
732                 default:
733                         break;
734         };
735 }
736
737 event_ret_t handle_setup_alarm_buttons(watch_button button, alarm_setup_data_t *sdata)
738 {
739         if (alarm_setup_screen.set_mode) {
740                 switch (button) {
741                         case BUTTON_A:
742                                 alarm_handle_updown(sdata->pos, 1);
743                                 break;
744                         case BUTTON_B:
745                                 alarm_handle_updown(sdata->pos, -1);
746                                 break;
747                         case BUTTON_C:
748                                 sdata->pos++;
749                                 sdata->pos %= 9;
750                                 break;
751                         case BUTTON_F:
752                                 alarm_setup_screen.set_mode = FALSE;
753                                 break;
754                         default:
755                                 return EVENT_RET_UNHANDLED;
756                                 break;
757                 }
758         } else {
759                 switch (button) {
760                         case BUTTON_F:
761                                 alarm_setup_screen.set_mode = TRUE;
762                                 break;
763                         default:
764                                 return EVENT_RET_UNHANDLED;
765                                 break;
766                 }
767         }
768         draw_alarm_setup_screen(sdata);
769
770         return EVENT_RET_HANDLED;
771 }
772
773 event_ret_t alarm_setup_events(uint16_t event, void *data)
774 {
775         switch (event) {
776                 case EVENT_SCREEN_VISIBLE:
777                         alarm_setup_screen.pos = 0;
778                         alarm_setup_screen.on = TRUE;
779                         alarm_setup_screen.set_mode = FALSE;
780                         draw_alarm_setup_screen(&alarm_setup_screen);
781                         hal_enable_halfsecond_timer();
782                         return EVENT_RET_HANDLED;
783                         break;
784                 case EVENT_SCREEN_DESTROY:
785                         hal_disable_halfsecond_timer();
786                         return EVENT_RET_HANDLED;
787                         break;
788                 case EVENT_USER_BUTTONS:
789                         dbg_out("button event %d\n", *(int *)data);
790                         return handle_setup_alarm_buttons(*(watch_button *)data, &alarm_setup_screen);
791                         break;
792                 case EVENT_HALF_SEC_TIMER:
793                         if (alarm_setup_screen.set_mode) {
794                                 if (alarm_setup_screen.on)
795                                         alarm_setup_screen.on = FALSE;
796                                 else
797                                         alarm_setup_screen.on = TRUE;
798                         } else
799                                 alarm_setup_screen.on = TRUE;
800                         draw_alarm_setup_screen(&alarm_setup_screen);
801                         return EVENT_RET_HANDLED;
802                         break;
803                 default:
804                         return EVENT_RET_UNHANDLED;
805                         break;
806         };
807         return EVENT_RET_UNHANDLED;
808 }
809
810
811 /*
812  * Test menu
813  */
814 typedef struct {
815         uint8_t menu_pos;
816 } test_menu_t;
817 static test_menu_t test_menu = { 0 };
818
819 void draw_menu_test_screen(void)
820 {
821         hal_lcd_clear_display();
822 #if 0
823         SetFont(MetaWatch16);
824         WriteLcdString(2, 2, "Menu");
825         SetFont(MetaWatch7);
826         WriteLcdString(2, 20, "Item 1");
827         WriteLcdString(2, 29, "Item 2");
828         WriteLcdString(2, 38, "Item 3");
829         WriteLcdString(2, 47, "Item 4");
830         WriteLcdString(2, 56, "Item 5");
831
832         WriteLcdString(50, 20+(9*test_menu.menu_pos), "*");
833 #endif
834         oswald_write_string(2, 2, FONT_DROID8x12, FALSE, "Menu");
835
836         oswald_write_string(2, 20, FONT_DROID8x12, FALSE, "Item 1");
837         oswald_write_string(2, 29, FONT_DROID8x12, FALSE, "Item 2");
838         oswald_write_string(2, 38, FONT_DROID8x12, FALSE, "Item 3");
839         oswald_write_string(2, 47, FONT_DROID8x12, FALSE, "Item 4");
840         oswald_write_string(2, 56, FONT_DROID8x12, FALSE, "Item 5");
841
842         oswald_write_character(50, 18+(9*test_menu.menu_pos), FONT_6x9, FALSE, 0x11);
843
844         hal_lcd_update_display();
845 }
846
847 event_ret_t handle_menu_user_buttons(watch_button button)
848 {
849         switch (button) {
850                 case BUTTON_A:
851                         test_menu.menu_pos--;
852                         test_menu.menu_pos %= 5;
853                         break;
854                 case BUTTON_B:
855                         test_menu.menu_pos++;
856                         test_menu.menu_pos %= 5;
857                         break;
858                 default:
859                         return EVENT_RET_UNHANDLED;
860                         break;
861         }
862         draw_menu_test_screen();
863         return EVENT_RET_HANDLED;
864 }
865
866 event_ret_t test_menu_handle_events(uint16_t event, void *data)
867 {
868         switch (event) {
869                 case EVENT_USER_BUTTONS:
870                         dbg_out("button event %d\n", *(int *)data);
871                         return handle_menu_user_buttons(*(watch_button *)data);
872                         break;
873                 case EVENT_SCREEN_VISIBLE:
874                         test_menu.menu_pos = 0;
875                         draw_menu_test_screen();
876                         break;
877                 default:
878                         return EVENT_RET_UNHANDLED;
879                         break;
880         };
881         return EVENT_RET_HANDLED;
882 }
883
884
885 /*
886  * Stop Watch
887  */
888 typedef struct {
889         uint8_t hr;
890         uint8_t min;
891         uint8_t sec;
892         uint8_t csec;
893         uint8_t lapse_hr;
894         uint8_t lapse_min;
895         uint8_t lapse_sec;
896         uint8_t lapse_csec;
897         boolean running;
898 } stopwatch_data_t;
899 static stopwatch_data_t stopwatch_screen = { 0, 0, 0, 0, 0, 0, 0, 0, FALSE };
900
901
902 static void draw_stop_watch_screen(stopwatch_data_t *sdata)
903 {
904         int gRow = 1;
905         int gColumn = 35;
906
907         hal_lcd_clear_display();
908
909         oswald_draw_bitmap(36, 0, stopwatch_icon_width, stopwatch_icon_height, stopwatch_icon_bits);
910
911         oswald_draw_bitmap(81, 6, startstopbutton_icon_width, startstopbutton_icon_height, startstopbutton_icon_bits);
912         oswald_draw_bitmap(81, 38, lapsebutton_icon_width, lapsebutton_icon_height, lapsebutton_icon_bits);
913         oswald_draw_bitmap(81, 70, enterbutton_icon_width, enterbutton_icon_height, enterbutton_icon_bits);
914
915         gRow += 3 + oswald_write_character(gRow, gColumn, FONT_LCD13x21, FALSE, (sdata->hr % 10));
916         gRow += oswald_write_character(gRow, gColumn, FONT_LCD13x21, FALSE, (sdata->min / 10));
917         gRow += 3 + oswald_write_character(gRow, gColumn, FONT_LCD13x21, FALSE, (sdata->min % 10));
918         gRow += oswald_write_character(gRow, gColumn, FONT_LCD13x21, FALSE, (sdata->sec / 10));
919         gRow += 3 + oswald_write_character(gRow, gColumn, FONT_LCD13x21, FALSE, (sdata->sec % 10));
920         gRow += oswald_write_character(gRow, gColumn, FONT_LCD8x13, FALSE, (sdata->csec / 10));
921
922         gRow = 6;
923         gColumn = 61;
924         gRow += 13 + oswald_write_character(gRow, gColumn, FONT_LCD8x13, FALSE, (sdata->lapse_hr % 10));
925         gRow += oswald_write_character(gRow, gColumn, FONT_LCD8x13, FALSE, (sdata->lapse_min / 10));
926         gRow += 13 + oswald_write_character(gRow, gColumn, FONT_LCD8x13, FALSE, (sdata->lapse_min % 10));
927         gRow += oswald_write_character(gRow, gColumn, FONT_LCD8x13, FALSE, (sdata->lapse_sec / 10));
928         gRow += 3 + oswald_write_character(gRow, gColumn, FONT_LCD8x13, FALSE, (sdata->lapse_sec % 10));
929         gRow += oswald_write_character(gRow, gColumn, FONT_LCD8x13, FALSE, (sdata->lapse_csec / 10));
930         gRow += oswald_write_character(gRow, gColumn, FONT_LCD8x13, FALSE, (sdata->lapse_csec % 10));
931
932         hal_lcd_update_display();
933 }
934
935 event_ret_t handle_stop_watch_buttons(watch_button button)
936 {
937         switch (button) {
938                 case BUTTON_A: // start/stop
939                         if (stopwatch_screen.running) {
940                                 hal_disable_centisecond_timer();
941                                 stopwatch_screen.running = FALSE;
942                         } else {
943                                 hal_enable_centisecond_timer();
944                                 stopwatch_screen.running = TRUE;
945                         }
946                         return EVENT_RET_HANDLED;
947                         break;
948                 case BUTTON_B: // lapse
949                         stopwatch_screen.lapse_hr = stopwatch_screen.hr;
950                         stopwatch_screen.lapse_min = stopwatch_screen.min;
951                         stopwatch_screen.lapse_sec = stopwatch_screen.sec;
952                         stopwatch_screen.lapse_csec = stopwatch_screen.csec;
953                         return EVENT_RET_HANDLED;
954                         break;
955                 case BUTTON_F: // reset
956                         stopwatch_screen.hr = 0;
957                         stopwatch_screen.min = 0;
958                         stopwatch_screen.sec = 0;
959                         stopwatch_screen.csec = 0;
960                         stopwatch_screen.lapse_hr = 0;
961                         stopwatch_screen.lapse_min = 0;
962                         stopwatch_screen.lapse_sec = 0;
963                         stopwatch_screen.lapse_csec = 0;
964                         return EVENT_RET_HANDLED;
965                         break;
966                 default:
967                         return EVENT_RET_UNHANDLED;
968                         break;
969         }
970         return EVENT_RET_UNHANDLED;
971 }
972
973 event_ret_t stop_watch_handle_events(uint16_t event, void *data)
974 {
975         switch (event) {
976                 case EVENT_USER_BUTTONS:
977                         dbg_out("button event %d\n", *(int *)data);
978                         draw_stop_watch_screen(&stopwatch_screen);
979                         return handle_stop_watch_buttons(*(watch_button *)data);
980                         break;
981                 case EVENT_SCREEN_VISIBLE:
982                         draw_stop_watch_screen(&stopwatch_screen);
983                         return EVENT_RET_HANDLED;
984                         break;
985                 case EVENT_SCREEN_DESTROY:
986                         hal_disable_centisecond_timer();
987                         stopwatch_screen.running = FALSE;
988                         return EVENT_RET_HANDLED;
989                         break;
990                 case EVENT_CS_TIMER:
991                         stopwatch_screen.csec++;
992                         if (stopwatch_screen.csec > 99) {
993                                 stopwatch_screen.csec = 0;
994                                 stopwatch_screen.sec++;
995                         };
996                         if (stopwatch_screen.sec > 59) {
997                                 stopwatch_screen.sec = 0;
998                                 stopwatch_screen.min++;
999                         };
1000                         if (stopwatch_screen.min > 59) {
1001                                 stopwatch_screen.min = 0;
1002                                 stopwatch_screen.hr++;
1003                         };
1004                         if (stopwatch_screen.hr > 59) {
1005                                 stopwatch_screen.hr = 0;
1006                         };
1007                         if (stopwatch_screen.csec % 10 == 0)
1008                                 draw_stop_watch_screen(&stopwatch_screen);
1009                                 //update_stop_watch_screen(&stopwatch_screen);
1010                         return EVENT_RET_HANDLED;
1011                         break;
1012                 default:
1013                         return EVENT_RET_UNHANDLED;
1014                         break;
1015         };
1016         return EVENT_RET_HANDLED;
1017 }
1018
1019
1020 /*
1021  * Alarm screen, shown when alarm is fired
1022  */
1023 void draw_alarm_screen(void)
1024 {
1025         hal_lcd_clear_display();
1026
1027         oswald_draw_bitmap(36, 20, alarm_icon_width, alarm_icon_height, alarm_icon_bits);
1028
1029         oswald_draw_bitmap(81, 70, enterbutton_icon_width, enterbutton_icon_height, enterbutton_icon_bits);
1030
1031         hal_lcd_update_display();
1032 }
1033
1034 event_ret_t alarm_handle_events(uint16_t event, void *data)
1035 {
1036         switch (event) {
1037                 case EVENT_SCREEN_VISIBLE:
1038                         draw_alarm_screen();
1039                         hal_enable_halfsecond_timer();
1040                         hal_vibration_set_state(TRUE);
1041                         return EVENT_RET_HANDLED;
1042                         break;
1043                 case EVENT_SCREEN_DESTROY:
1044                         hal_disable_halfsecond_timer();
1045                         hal_lcd_set_backlight(FALSE);
1046                         hal_vibration_set_state(FALSE);
1047                         return EVENT_RET_HANDLED;
1048                         break;
1049                 case EVENT_USER_BUTTONS:
1050                         dbg_out("button event %d\n", *(int *)data);
1051                         return EVENT_RET_UNHANDLED;
1052                         break;
1053                 case EVENT_HALF_SEC_TIMER:
1054                         hal_lcd_set_backlight(!hal_lcd_get_backlight());
1055                         hal_vibration_set_state(!hal_vibration_get_state());
1056                         dbg_out("timer\n");
1057                         return EVENT_RET_HANDLED;
1058                         break;
1059                 default:
1060                         return EVENT_RET_UNHANDLED;
1061                         break;
1062         };
1063         return EVENT_RET_HANDLED;
1064 }
1065
1066
1067 /*
1068  * Bluetooth setup screen
1069  */
1070 typedef struct {
1071         uint8_t pos;
1072         boolean bt_en;
1073         boolean set_mode;
1074         boolean on;
1075 } bluetooth_data_t;
1076 static bluetooth_data_t bluetooth_screen = {
1077         0,
1078         FALSE,
1079         FALSE,
1080         TRUE
1081 };
1082
1083 void draw_bluetooth_screen(bluetooth_data_t *sdata)
1084 {
1085         char bstr[20];
1086         uint8_t *bd_addr;
1087
1088         hal_lcd_clear_display();
1089
1090         oswald_draw_bitmap(36, 0, Bluetooth_icon_width, Bluetooth_icon_height, Bluetooth_icon_bits);
1091
1092         if (sdata->set_mode) {
1093                 oswald_draw_bitmap(81, 6, upbutton_icon_width, upbutton_icon_height, upbutton_icon_bits);
1094                 oswald_draw_bitmap(81, 38, downbutton_icon_width, downbutton_icon_height, downbutton_icon_bits);
1095                 oswald_draw_bitmap(81, 70, rightbutton_icon_width, rightbutton_icon_height, rightbutton_icon_bits);
1096         } else {
1097                 oswald_draw_bitmap(81, 70, enterbutton_icon_width, enterbutton_icon_height, enterbutton_icon_bits);
1098         }
1099
1100         oswald_write_string(1, 30, FONT_DROID8x12, FALSE, "Enable:");
1101         if ((sdata->pos == 0 && sdata->on) || sdata->pos != 0) {
1102                 if (bluetooth_screen.bt_en)
1103                         oswald_draw_bitmap(53, 33, checked_icon_width, checked_icon_height, checked_icon_bits);
1104                 else
1105                         oswald_draw_bitmap(53, 33, unchecked_icon_width, unchecked_icon_height, unchecked_icon_bits);
1106         }
1107         oswald_write_string(1, 40, FONT_DROID8x12, FALSE, "State:");
1108         switch (hal_bluetooth_get_state()) {
1109                 case BLUETOOTH_OFF:
1110                         oswald_write_string(53, 40, FONT_DROID8x12, FALSE, "off");
1111                         break;
1112                 case BLUETOOTH_ON:
1113                         oswald_write_string(53, 40, FONT_DROID8x12, FALSE, "on");
1114                         break;
1115                 case BLUETOOTH_CONNECTED:
1116                         oswald_write_string(53, 40, FONT_DROID8x12, FALSE, "conn.");
1117                         break;
1118                 default:
1119                         break;
1120         };
1121         oswald_write_string(1, 50, FONT_DROID8x12, FALSE, "Visible:");
1122         if ((sdata->pos == 1 && sdata->on) || sdata->pos != 1) {
1123                 // oswald_write_character(53, 50, FONT_DROID8x12, hal_bluetooth_get_visible() ? 'x' : '_');
1124                 if (hal_bluetooth_get_visible())
1125                         oswald_draw_bitmap(53, 53, checked_icon_width, checked_icon_height, checked_icon_bits);
1126                 else
1127                         oswald_draw_bitmap(53, 53, unchecked_icon_width, unchecked_icon_height, unchecked_icon_bits);
1128         }
1129
1130         if (hal_bluetooth_get_state() >= BLUETOOTH_ON) {
1131                 bd_addr = hal_bluetooth_get_local_bdaddr();
1132                 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]);
1133                 oswald_write_string(2, 85, FONT_5x7, FALSE, bstr);
1134         } else {
1135         }
1136
1137         hal_lcd_update_display();
1138 }
1139
1140 void bluetooth_handle_updown(uint8_t pos, int8_t incr)
1141 {
1142         switch (pos) {
1143                 case 0:
1144                         if (hal_bluetooth_get_state() >= BLUETOOTH_ON) {
1145                                 hal_bluetooth_set_state(BLUETOOTH_OFF);
1146                                 bluetooth_screen.bt_en = FALSE;
1147                         } else {
1148                                 hal_bluetooth_set_state(BLUETOOTH_ON);
1149                                 bluetooth_screen.bt_en = TRUE;
1150                         }
1151                         break;
1152                 case 1:
1153                         if (hal_bluetooth_get_state() >= BLUETOOTH_ON && !hal_bluetooth_get_visible()) {
1154                                 hal_bluetooth_set_visible(TRUE);
1155                         } else {
1156                                 hal_bluetooth_set_visible(FALSE);
1157                         }
1158                         break;
1159                 default:
1160                         break;
1161         };
1162 }
1163
1164 event_ret_t handle_bluetooth_buttons(watch_button button, bluetooth_data_t *sdata)
1165 {
1166         if (bluetooth_screen.set_mode) {
1167                 switch (button) {
1168                         case BUTTON_A:
1169                                 bluetooth_handle_updown(sdata->pos, 1);
1170                                 break;
1171                         case BUTTON_B:
1172                                 bluetooth_handle_updown(sdata->pos, -1);
1173                                 break;
1174                         case BUTTON_C:
1175                                 sdata->pos++;
1176                                 sdata->pos %= 2;
1177                                 break;
1178                         case BUTTON_F:
1179                                 bluetooth_screen.set_mode = FALSE;
1180                                 break;
1181                         default:
1182                                 return EVENT_RET_UNHANDLED;
1183                                 break;
1184                 }
1185         } else {
1186                 switch (button) {
1187                         case BUTTON_F:
1188                                 bluetooth_screen.set_mode = TRUE;
1189                                 break;
1190                         default:
1191                                 return EVENT_RET_UNHANDLED;
1192                                 break;
1193                 }
1194         }
1195
1196         draw_bluetooth_screen(sdata);
1197
1198         return EVENT_RET_HANDLED;
1199 }
1200
1201 event_ret_t bluetooth_screen_events(uint16_t event, void *data)
1202 {
1203         switch (event) {
1204                 case EVENT_SCREEN_VISIBLE:
1205                         bluetooth_screen.pos = 0;
1206                         bluetooth_screen.bt_en = (hal_bluetooth_get_state() > 0);
1207                         draw_bluetooth_screen(&bluetooth_screen);
1208                         hal_enable_halfsecond_timer();
1209                         break;
1210                 case EVENT_SCREEN_DESTROY:
1211                         hal_disable_halfsecond_timer();
1212                         break;
1213                 case EVENT_USER_BUTTONS:
1214                         dbg_out("button event %d\n", *(int *)data);
1215                         return handle_bluetooth_buttons(*(watch_button *)data, &bluetooth_screen);
1216                         break;
1217                 case EVENT_HALF_SEC_TIMER:
1218                         if (bluetooth_screen.set_mode) {
1219                                 if (bluetooth_screen.on)
1220                                         bluetooth_screen.on = FALSE;
1221                                 else
1222                                         bluetooth_screen.on = TRUE;
1223                         } else
1224                                 bluetooth_screen.on = TRUE;
1225                         draw_bluetooth_screen(&bluetooth_screen);
1226                         break;
1227                 default:
1228                         return EVENT_RET_UNHANDLED;
1229                         break;
1230         };
1231         return EVENT_RET_HANDLED;
1232 }
1233
1234
1235 /*
1236  * Info Screen
1237  */
1238 void draw_info_screen(void)
1239 {
1240         hal_lcd_clear_display();
1241
1242         oswald_draw_bitmap(36, 0, info_icon_width, info_icon_height, info_icon_bits);
1243
1244         oswald_draw_bitmap(81, 70, enterbutton_icon_width, enterbutton_icon_height, enterbutton_icon_bits);
1245
1246         oswald_write_string(2, 29, FONT_DROID8x12, FALSE, "Oswald");
1247         oswald_write_string(35, 29, FONT_DROID8x12, FALSE, OSWALD_VERSION);
1248         oswald_write_string(2, 41, FONT_DROID8x12, FALSE, "HAL");
1249         oswald_write_string(35, 41, FONT_DROID8x12, FALSE, (char *)hal_get_version_string());
1250         oswald_write_string(2, 53, FONT_DROID8x12, FALSE, "Build");
1251         oswald_write_string(35, 53, FONT_DROID8x12, FALSE, (char *)hal_get_buildno_string());
1252         oswald_write_string(2, 65, FONT_DROID8x12, FALSE, "Radio");
1253         oswald_write_string(35, 65, FONT_DROID8x12, FALSE, (char *)hal_get_radio_version_string());
1254
1255         hal_lcd_update_display();
1256 }
1257
1258 event_ret_t info_screen_handle_events(uint16_t event, void *data)
1259 {
1260         switch (event) {
1261                 case EVENT_SCREEN_VISIBLE:
1262                         draw_info_screen();
1263                         return EVENT_RET_HANDLED;
1264                         break;
1265                 case EVENT_USER_BUTTONS:
1266                         dbg_out("button event %d\n", *(int *)data);
1267                         break;
1268                 default:
1269                         return EVENT_RET_UNHANDLED;
1270                         break;
1271         };
1272         return EVENT_RET_UNHANDLED;
1273 }
1274
1275
1276 /*
1277  * Messages Screens
1278  */
1279 typedef struct {
1280         int8_t pos;     // marker position
1281         int8_t offset;  // offset in msg list
1282 } messages_data_t;
1283 static messages_data_t messages_screen = {
1284         0,
1285         0,
1286 };
1287
1288 typedef struct {
1289         uint8_t day;
1290         uint8_t month;
1291         uint8_t year;   // without century, add +1900
1292         uint8_t hour;
1293         uint8_t minute;
1294 } msg_timedate_t;
1295
1296 #define MSG_TYPE_READ           0
1297 #define MSG_TYPE_NEW            1
1298 #define MSG_TYPE_END            127
1299
1300 typedef struct {
1301         uint8_t type;
1302         msg_timedate_t td;
1303         char *msg;
1304 } message_t;
1305
1306 uint8_t Msgs = 15;
1307 message_t Msg[] = {
1308         { MSG_TYPE_READ, {9,5,113,0,38}, "Testmessage with more text than fits into the menu." },
1309         { MSG_TYPE_NEW, {9,5,113,0,39}, "Sitting in the train waiting to arrive." },
1310         { MSG_TYPE_READ, {9,5,113,0,40}, "People in the train are annoying!" },
1311         { MSG_TYPE_READ, {9,5,113,0,40}, "Auch auf Deutsch geht das hier und Text können lang sein." },
1312         { MSG_TYPE_NEW, {8,5,113,0,40}, "Und hier noch eine neue Nachricht, die nun wirklich lang ist, laenger als die anderen." },
1313         { MSG_TYPE_READ, {9,5,113,0,38}, "Testmessage with more text than fits into the menu." },
1314         { MSG_TYPE_NEW, {9,5,113,0,39}, "Sitting in the train waiting to arrive." },
1315         { MSG_TYPE_READ, {9,5,113,0,40}, "People in the train are annoying!" },
1316         { MSG_TYPE_READ, {9,5,113,0,40}, "Auch auf Deutsch geht das hier und Text können lang sein." },
1317         { MSG_TYPE_NEW, {8,5,113,0,40}, "Und hier noch eine neue Nachricht, die nun wirklich lang ist, laenger als die anderen." },
1318         { MSG_TYPE_READ, {9,5,113,0,38}, "Testmessage with more text than fits into the menu." },
1319         { MSG_TYPE_NEW, {9,5,113,0,39}, "Sitting in the train waiting to arrive." },
1320         { MSG_TYPE_READ, {9,5,113,0,40}, "People in the train are annoying!" },
1321         { MSG_TYPE_READ, {9,5,113,0,40}, "Auch auf Deutsch geht das hier und Text können lang sein." },
1322         { MSG_TYPE_NEW, {8,5,113,0,40}, "Und hier noch eine neue Nachricht, die nun wirklich lang ist, laenger als die anderen." },
1323         { MSG_TYPE_END, {0,0,0,0,0}, "Exit" },
1324 };
1325
1326 void draw_message_screen(messages_data_t *sdata)
1327 {
1328         char dstr[32];
1329         uint8_t strpos, msglen;
1330         uint8_t line;
1331
1332         hal_lcd_clear_display();
1333
1334 #if 0
1335         oswald_draw_bitmap(81, 6, upbutton_icon_width, upbutton_icon_height, upbutton_icon_bits);
1336         oswald_draw_bitmap(81, 38, downbutton_icon_width, downbutton_icon_height, downbutton_icon_bits);
1337 #endif
1338         oswald_draw_bitmap(81, 70, enterbutton_icon_width, enterbutton_icon_height, enterbutton_icon_bits);
1339
1340         Msg[sdata->offset + sdata->pos].type = MSG_TYPE_READ;
1341         snprintf(dstr, 19, "#%02d/%02d", sdata->pos + sdata->offset + 1, Msgs);
1342         oswald_write_string(30, 0, FONT_5x7, FALSE, dstr);
1343         oswald_draw_line(0,7,95,7);
1344
1345
1346         // here goes the text
1347         msglen = strlen(Msg[sdata->pos+sdata->offset].msg);
1348         strpos=0;
1349         line=0;
1350         while ((strpos < msglen) && (line < 6)) {
1351                 strpos += oswald_write_string_length(4, 9+(line*12), 84, FONT_DROID8x12, FALSE, &Msg[sdata->pos+sdata->offset].msg[strpos]);
1352                 line++;
1353         }
1354
1355
1356         oswald_draw_line(0,87,95,87);
1357
1358         if (Msg[sdata->offset + sdata->pos].type != MSG_TYPE_END) {
1359                 snprintf(dstr, 19, "%c %02d.%02d.%04d,%02d:%02d", (Msg[sdata->pos+sdata->offset].type == MSG_TYPE_NEW) ? '*':' ', Msg[sdata->pos+sdata->offset].td.day, Msg[sdata->pos+sdata->offset].td.month, Msg[sdata->pos+sdata->offset].td.year+1900, Msg[sdata->pos+sdata->offset].td.hour, Msg[sdata->pos+sdata->offset].td.minute);
1360                 oswald_write_string(2, 89, FONT_5x7, FALSE, dstr);
1361         }
1362
1363         hal_lcd_update_display();
1364 }
1365
1366 event_ret_t handle_message_screen_buttons(watch_button button, messages_data_t *sdata)
1367 {
1368         switch (button) {
1369                 case BUTTON_A:
1370                         break;
1371                 case BUTTON_B:
1372                         return EVENT_RET_HANDLED;
1373                         break;
1374                 case BUTTON_C:
1375                         // OswaldState.screen->event_func(EVENT_SCREEN_DESTROY, NULL);
1376                         OswaldState.screen_id = MESSAGES_SCREEN;
1377                         OswaldState.screen = &OswaldScreens[OswaldState.screen_id];
1378                         OswaldState.screen->event_func(EVENT_SCREEN_VISIBLE, NULL);
1379                         return EVENT_RET_HANDLED;
1380                         break;
1381                 default:
1382                         break;
1383         }
1384
1385         return EVENT_RET_UNHANDLED;
1386 }
1387
1388 event_ret_t message_screen_handle_events(uint16_t event, void *data)
1389 {
1390         switch (event) {
1391                 case EVENT_SCREEN_VISIBLE:
1392                         draw_message_screen(&messages_screen);
1393                         return EVENT_RET_HANDLED;
1394                         break;
1395                 case EVENT_USER_BUTTONS:
1396                         dbg_out("button event %d\n", *(int *)data);
1397                         return handle_message_screen_buttons(*(watch_button *)data, &messages_screen);
1398                         break;
1399                 default:
1400                         break;
1401         };
1402         return EVENT_RET_UNHANDLED;
1403 }
1404
1405 void draw_messages_screen(messages_data_t *sdata)
1406 {
1407         char dstr[32];
1408         int i;
1409
1410         hal_lcd_clear_display();
1411
1412         // oswald_draw_bitmap(36, 0, Message_icon_width, Message_icon_height, Message_icon_bits);
1413
1414         oswald_draw_bitmap(81, 6, upbutton_icon_width, upbutton_icon_height, upbutton_icon_bits);
1415         oswald_draw_bitmap(81, 38, downbutton_icon_width, downbutton_icon_height, downbutton_icon_bits);
1416         oswald_draw_bitmap(81, 70, enterbutton_icon_width, enterbutton_icon_height, enterbutton_icon_bits);
1417
1418         if (Msg[sdata->offset + sdata->pos].type != MSG_TYPE_END) {
1419                 snprintf(dstr, 19, "#%02d/%02d", sdata->pos + sdata->offset + 1, Msgs);
1420                 oswald_write_string(30, 0, FONT_5x7, FALSE, dstr);
1421         }
1422         oswald_draw_line(0,7,95,7);
1423
1424         for (i=0; i<6; i++) {
1425                 if (Msg[i+sdata->offset].type != MSG_TYPE_END) {
1426                         //oswald_write_string_length(4, 9+(i*12), 84, FONT_DROID8x12, (Msg[i+sdata->offset].type == MSG_TYPE_NEW), Msg[i+sdata->offset].msg);
1427                         if (Msg[i+sdata->offset].type == MSG_TYPE_NEW)
1428                                 oswald_write_string_length(4, 9+(i*12), 84, FONT_DROID8x12b, (i+sdata->offset) == (sdata->offset + sdata->pos), Msg[i+sdata->offset].msg);
1429                         else
1430                                 oswald_write_string_length(4, 9+(i*12), 84, FONT_DROID8x12, (i+sdata->offset) == (sdata->offset + sdata->pos), Msg[i+sdata->offset].msg);
1431                 } else {
1432                         oswald_draw_bitmap(0, 66, leftbutton_icon_width, leftbutton_icon_height, leftbutton_icon_bits);
1433                 }
1434         }
1435
1436         // marker selected msg
1437         oswald_draw_line(1,9,1,81);
1438         oswald_draw_line_ww(1,10+(sdata->pos*12),1,20+(sdata->pos*12),2);
1439
1440         oswald_draw_line(0,87,95,87);
1441
1442         if (Msg[sdata->offset + sdata->pos].type != MSG_TYPE_END) {
1443                 snprintf(dstr, 19, "%c %02d.%02d.%04d,%02d:%02d", (Msg[sdata->pos+sdata->offset].type == MSG_TYPE_NEW) ? '*':' ', Msg[sdata->pos+sdata->offset].td.day, Msg[sdata->pos+sdata->offset].td.month, Msg[sdata->pos+sdata->offset].td.year+1900, Msg[sdata->pos+sdata->offset].td.hour, Msg[sdata->pos+sdata->offset].td.minute);
1444                 oswald_write_string(2, 89, FONT_5x7, FALSE, dstr);
1445         }
1446
1447         hal_lcd_update_display();
1448 }
1449
1450 event_ret_t handle_messages_screen_buttons(watch_button button, messages_data_t *sdata)
1451 {
1452         switch (button) {
1453                 case BUTTON_A:
1454                         sdata->pos--;
1455                         if (sdata->pos < 0) {
1456                                 if (sdata->offset > 0) {
1457                                         sdata->pos = 0;
1458                                         sdata->offset--;
1459                                         if (sdata->offset < 0)
1460                                                 sdata->offset = 0;
1461                                 } else {
1462                                         sdata->pos = 5;
1463                                         sdata->offset = (Msgs - 5);
1464                                         if (sdata->offset < 0)
1465                                                 sdata->offset = 0;
1466                                 }
1467                         }
1468                         draw_messages_screen(&messages_screen);
1469                         return EVENT_RET_HANDLED;
1470                         break;
1471                 case BUTTON_B:
1472                         sdata->pos++;
1473                         if (sdata->pos > 5) {
1474                                 sdata->pos = 5;
1475                                 sdata->offset++;
1476                                 if ((sdata->offset + 5) > Msgs) {
1477                                         sdata->offset = 0;
1478                                         sdata->pos = 0;
1479                                 }
1480                         }
1481                         draw_messages_screen(&messages_screen);
1482                         return EVENT_RET_HANDLED;
1483                         break;
1484                 case BUTTON_C:
1485                         if (Msg[sdata->offset + sdata->pos].type == MSG_TYPE_END)
1486                                 return EVENT_RET_UNHANDLED;
1487                         else
1488                                 // OswaldState.screen->event_func(EVENT_SCREEN_DESTROY, NULL);
1489                                 OswaldState.screen_id = MESSAGE_SCREEN;
1490                                 OswaldState.screen = &OswaldScreens[OswaldState.screen_id];
1491                                 OswaldState.screen->event_func(EVENT_SCREEN_VISIBLE, NULL);
1492                                 return EVENT_RET_HANDLED;
1493                         break;
1494                 default:
1495                         break;
1496         }
1497
1498         return EVENT_RET_UNHANDLED;
1499 }
1500
1501 event_ret_t messages_screen_handle_events(uint16_t event, void *data)
1502 {
1503         switch (event) {
1504                 case EVENT_SCREEN_VISIBLE:
1505 //                      messages_screen.pos = 0;
1506 //                      messages_screen.offset = 0;
1507                         draw_messages_screen(&messages_screen);
1508                         return EVENT_RET_HANDLED;
1509                         break;
1510                 case EVENT_USER_BUTTONS:
1511                         dbg_out("button event %d\n", *(int *)data);
1512                         return handle_messages_screen_buttons(*(watch_button *)data, &messages_screen);
1513                         break;
1514                 default:
1515                         break;
1516         };
1517         return EVENT_RET_UNHANDLED;
1518 }
1519