]> git.karo-electronics.de Git - oswald.git/blobdiff - ui/oswald_screens.c
Maybe a little sniff mode, add ambient light adc (not working),
[oswald.git] / ui / oswald_screens.c
index ddca03c2a861c2aa4fc3d82aa8da2f24d50247d2..5a29d39f3eeb0b96e7c0a26f38fcdc151a6839c5 100644 (file)
@@ -8,43 +8,61 @@
 
 #include "oswald_screens.h"
 
-#include "LcdDisplay.h"
-#include "Fonts.h"
-
 #if defined(__GNUC__) && (__MSP430X__ > 0)
 __attribute__((__far__))
 #endif
 #include "bitmaps/timesetup_icon.xbm"
+
 #if defined(__GNUC__) && (__MSP430X__ > 0)
 __attribute__((__far__))
 #endif
 #include "bitmaps/stopwatch_icon.xbm"
+
 #if defined(__GNUC__) && (__MSP430X__ > 0)
 __attribute__((__far__))
 #endif
 #include "bitmaps/alarm_icon.xbm"
+
 #if defined(__GNUC__) && (__MSP430X__ > 0)
 __attribute__((__far__))
 #endif
 #include "bitmaps/startstopbutton_icon.xbm"
+
 #if defined(__GNUC__) && (__MSP430X__ > 0)
 __attribute__((__far__))
 #endif
 #include "bitmaps/lapsebutton_icon.xbm"
+
 #if defined(__GNUC__) && (__MSP430X__ > 0)
 __attribute__((__far__))
 #endif
 #include "bitmaps/upbutton_icon.xbm"
+
 #if defined(__GNUC__) && (__MSP430X__ > 0)
 __attribute__((__far__))
 #endif
 #include "bitmaps/downbutton_icon.xbm"
+
 #if defined(__GNUC__) && (__MSP430X__ > 0)
 __attribute__((__far__))
 #endif
 #include "bitmaps/Bluetooth_icon.xbm"
 
+#if defined(__GNUC__) && (__MSP430X__ > 0)
+__attribute__((__far__))
+#endif
+#include "bitmaps/info_icon.xbm"
+
+#if defined(__GNUC__) && (__MSP430X__ > 0)
+__attribute__((__far__))
+#endif
+#include "bitmaps/acc_icon.xbm"
+
 
+
+/*
+ * Common event handler part of the watch faces
+ */
 typedef struct {
        void (*screendraw_func)(boolean show_seconds);
        boolean show_seconds;
@@ -56,7 +74,7 @@ static idle_data_t idle_screen = {
        FALSE,
 };
  
-void idle_handle_user_buttons(watch_button button)
+event_ret_t idle_handle_user_buttons(watch_button button)
 {
        switch (button) {
                case BUTTON_A:
@@ -74,35 +92,48 @@ void idle_handle_user_buttons(watch_button button)
                                idle_screen.screendraw_func = DrawLcdAnaClock;
                        };
                        break;
+               case BUTTON_C:
+                       return EVENT_RET_UNHANDLED;
+                       break;
                case BUTTON_F:
                        OswaldState.screen_id = DATETIME_SETTING_SCREEN;
                        OswaldState.screen = &OswaldScreens[OswaldState.screen_id];
                        OswaldState.screen->event_func(EVENT_SCREEN_VISIBLE, NULL);
-                       return;
+                       return EVENT_RET_HANDLED;
                        break;
                default:
+                       return EVENT_RET_UNHANDLED;
                        break;
        };
+
        idle_screen.screendraw_func(idle_screen.show_seconds);
+
+       return EVENT_RET_HANDLED;
 }
 
-void idle_handle_events(u16t event, void *data)
+event_ret_t idle_handle_events(uint16_t event, void *data)
 {
        switch (event) {
                case EVENT_ONE_SEC_TIMER:
                case EVENT_SCREEN_VISIBLE:
                        idle_screen.screendraw_func(idle_screen.show_seconds);
+                       return EVENT_RET_HANDLED;
                        break;
                case EVENT_USER_BUTTONS:
                        dbg_out("button event %d\n", *(int *)data);
-                       idle_handle_user_buttons(*(watch_button *)data);
+                       return idle_handle_user_buttons(*(watch_button *)data);
                        break;
                default:
+                       return EVENT_RET_UNHANDLED;
                        break;
        };
+       return EVENT_RET_UNHANDLED;
 }
 
 
+/*
+ * Accelerometer and sensor display screen
+ */
 typedef struct {
        accel_data_t accdata;
 } accelscreen_data_t;
@@ -112,29 +143,49 @@ static accelscreen_data_t accel_screen = {
 
 void draw_accel_screen(accel_data_t *accel_data)
 {
+       uint8_t x,y;
+
        hal_lcd_clear_display();
 
-       oswald_write_string(0, 2, FONT_7x12b, "X:");
-       oswald_write_number(20, 2, FONT_7x12b, accel_data->x);
-       oswald_write_string(0, 18, FONT_7x12b, "Y:");
-       oswald_write_number(20, 18, FONT_7x12b, accel_data->y);
-#if 0
-       oswald_write_string(0, 34, FONT_8x12, "Z:");
-       oswald_write_number(20, 34, FONT_8x12, accel_data->z);
+       oswald_draw_bitmap(36, 0, acc_icon_width, acc_icon_height, acc_icon_bits);
 
-       oswald_write_string(0, 54, FONT_12x16, "Light:");
-       oswald_write_number(50, 54, FONT_12x16, accel_data->z);
+       oswald_write_string(1, 40, FONT_6x9, "X:");
+       oswald_write_number(15, 40, FONT_6x9, accel_data->x);
+       oswald_write_string(1, 52, FONT_6x9, "Y:");
+       oswald_write_number(15, 52, FONT_6x9, accel_data->y);
+       oswald_write_string(1, 64, FONT_6x9, "Z:");
+       oswald_write_number(15, 64, FONT_6x9, accel_data->z);
+
+       oswald_write_string(1, 85, FONT_6x9, "Light:");
+       oswald_write_number(50, 85, FONT_6x9, 0);
+
+       oswald_draw_line(40, 30, 92, 30);
+       oswald_draw_line(92, 30, 92, 82);
+       oswald_draw_line(40, 82, 92, 82);
+       oswald_draw_line(40, 82, 40, 30);
+
+       x = 41+25+((accel_data->x * 50) / (254));
+       y = 31+25-((accel_data->y * 50) / (254));
+       oswald_draw_pixel(x, y);
+       oswald_draw_pixel(x+1, y);
+       oswald_draw_pixel(x-1, y);
+       oswald_draw_pixel(x, y+1);
+       oswald_draw_pixel(x, y-1);
 
-       oswald_write_string(0, 70, FONT_12x20, "23:59");
-#endif
        hal_lcd_update_display();
 }
 
-void accel_handle_events(u16t event, void *data)
+event_ret_t accel_handle_events(uint16_t event, void *data)
 {
        switch (event) {
                case EVENT_SCREEN_VISIBLE:
                        draw_accel_screen(&accel_screen.accdata);
+                       hal_accelerometer_enable();
+                       return EVENT_RET_HANDLED;
+                       break;
+               case EVENT_SCREEN_DESTROY:
+                       hal_accelerometer_disable();
+                       return EVENT_RET_HANDLED;
                        break;
                case EVENT_ACCEL_UPDATE: {
                        accel_data_t *accel_data = (accel_data_t *)data;
@@ -143,22 +194,30 @@ void accel_handle_events(u16t event, void *data)
                        accel_screen.accdata.z = accel_data->z;
                        draw_accel_screen(&accel_screen.accdata);
                        };
+                       return EVENT_RET_HANDLED;
                        break;
                case EVENT_USER_BUTTONS:
                        dbg_out("button event %d\n", *(int *)data);
                        break;
                default:
+                       return EVENT_RET_UNHANDLED;
                        break;
        };
+       return EVENT_RET_UNHANDLED;
 }
 
 
+/*
+ * Date / time setup screen
+ */
 typedef struct {
-       u8t pos;
+       uint8_t pos;
+       boolean set_mode;
        boolean on;
 } datetime_setup_data_t;
 static datetime_setup_data_t dt_setup_screen = {
        0,
+       FALSE,
        TRUE
 };
 
@@ -171,58 +230,57 @@ void draw_datetime_setup_screen(datetime_setup_data_t *sdata)
        oswald_draw_bitmap(81, 6, upbutton_icon_width, upbutton_icon_height, upbutton_icon_bits);
        oswald_draw_bitmap(81, 38, downbutton_icon_width, downbutton_icon_height, downbutton_icon_bits);
 
-       SetFont(MetaWatchTime);
        if ((sdata->pos == 0 && sdata->on) || sdata->pos != 0) {
-               WriteLcdCharacter(2, 30, (OswaldClk.hour / 10));
-               WriteLcdCharacter(14, 30, (OswaldClk.hour % 10));
+               oswald_write_character(2, 30, FONT_LCD13x21, (OswaldClk.hour / 10));
+               oswald_write_character(15, 30, FONT_LCD13x21, (OswaldClk.hour % 10));
        }
-       WriteLcdCharacter(26, 30, TIME_CHARACTER_COLON_INDEX);
+       oswald_write_character(25, 30, FONT_LCD13x21, 10);
 
        if ((sdata->pos == 1 && sdata->on) || sdata->pos != 1) {
-               WriteLcdCharacter(31, 30, (OswaldClk.minute / 10));
-               WriteLcdCharacter(43, 30, (OswaldClk.minute % 10));
+               oswald_write_character(34, 30, FONT_LCD13x21, (OswaldClk.minute / 10));
+               oswald_write_character(47, 30, FONT_LCD13x21, (OswaldClk.minute % 10));
        }
 
-       SetFont(MetaWatch16);
        if ((sdata->pos == 2 && sdata->on) || sdata->pos != 2) {
-               WriteLcdCharacter(59, 36, 0x30 + (OswaldClk.second / 10));
-               WriteLcdCharacter(66, 36, 0x30 + (OswaldClk.second % 10));
+               oswald_write_character(61, 38, FONT_LCD8x13, (OswaldClk.second / 10));
+               oswald_write_character(69, 38, FONT_LCD8x13, (OswaldClk.second % 10));
        }
 
 
        if ((sdata->pos == 3 && sdata->on) || sdata->pos != 3) {
-               WriteLcdNumber(2, 55, OswaldClk.day);
+               oswald_write_number(2, 55, FONT_DROID8x12, OswaldClk.day);
        }
-       WriteLcdString(18, 55, ".");
+       oswald_write_character(15, 55, FONT_DROID8x12, '.');
        if ((sdata->pos == 4 && sdata->on) || sdata->pos != 4) {
-               WriteLcdNumber(22, 55, OswaldClk.month);
+               oswald_write_number(21, 55, FONT_DROID8x12, OswaldClk.month);
        }
-       WriteLcdString(38, 55, ".");
+       oswald_write_character(36, 55, FONT_DROID8x12, '.');
        if ((sdata->pos == 5 && sdata->on) || sdata->pos != 5) {
-               WriteLcdNumber(42, 55, OswaldClk.year);
+               oswald_write_number(43, 55, FONT_DROID8x12, OswaldClk.year);
        }
 
-       SetFont(MetaWatch7);
        if ((sdata->pos == 6 && sdata->on) || sdata->pos != 6) {
-               if (OswaldClk.clk24hr)
-                       WriteLcdString(2, 76, "x");
-               else
-                       WriteLcdString(2, 76, "_");
+               if (OswaldClk.clk24hr) {
+                       oswald_write_character(2, 76, FONT_6x9, 'x');
+               } else {
+                       oswald_write_character(2, 76, FONT_6x9, '_');
+               }
        }
-       WriteLcdString(15, 76, "24hr");
+       oswald_write_string(15, 73, FONT_DROID8x12, "24hr");
 
        if ((sdata->pos == 7 && sdata->on) || sdata->pos != 7) {
-               if (OswaldClk.day_first)
-                       WriteLcdString(2, 89, "x");
-               else
-                       WriteLcdString(2, 89, "_");
+               if (OswaldClk.day_first) {
+                       oswald_write_character(2, 86, FONT_6x9, 'x');
+               } else {
+                       oswald_write_character(2, 86, FONT_6x9, '_');
+               }
        }
-       WriteLcdString(15, 89, "dd.mm.  mm/dd");
+       oswald_write_string(15, 83, FONT_DROID8x12, "dd.mm.  mm/dd");
 
        hal_lcd_update_display();
 }
 
-void datetime_handle_updown(u8t pos, s8t incr)
+void datetime_handle_updown(uint8_t pos, int8_t incr)
 {
        switch (pos) {
                case 0: // hour
@@ -288,7 +346,7 @@ void datetime_handle_updown(u8t pos, s8t incr)
                hal_set_rtc(&OswaldClk, FALSE);
 }
 
-void handle_setup_datetime_buttons(watch_button button, datetime_setup_data_t *sdata)
+event_ret_t handle_setup_datetime_buttons(watch_button button, datetime_setup_data_t *sdata)
 {
        switch (button) {
                case BUTTON_A:
@@ -297,30 +355,41 @@ void handle_setup_datetime_buttons(watch_button button, datetime_setup_data_t *s
                case BUTTON_B:
                        datetime_handle_updown(sdata->pos, -1);
                        break;
-               case BUTTON_F:
+               case BUTTON_C:
                        sdata->pos++;
                        sdata->pos %= 8;
                        break;
+               case BUTTON_F:
+                       OswaldState.screen->event_func(EVENT_SCREEN_DESTROY, NULL);
+                       OswaldState.screen_id = IDLE_SCREEN;
+                       OswaldState.screen = &OswaldScreens[OswaldState.screen_id];
+                       OswaldState.screen->event_func(EVENT_SCREEN_VISIBLE, NULL);
+                       return EVENT_RET_HANDLED;
+                       break;
                default:
+                       return EVENT_RET_UNHANDLED;
                        break;
        }
        draw_datetime_setup_screen(sdata);
+       return EVENT_RET_HANDLED;
 }
 
-void datetime_setup_events(u16t event, void *data)
+event_ret_t datetime_setup_events(uint16_t event, void *data)
 {
        switch (event) {
                case EVENT_SCREEN_VISIBLE:
                        dt_setup_screen.pos = 0;
                        draw_datetime_setup_screen(&dt_setup_screen);
                        hal_enable_halfsecond_timer();
+                       return EVENT_RET_HANDLED;
                        break;
                case EVENT_SCREEN_DESTROY:
                        hal_disable_halfsecond_timer();
+                       return EVENT_RET_HANDLED;
                        break;
                case EVENT_USER_BUTTONS:
                        dbg_out("button event %d\n", *(int *)data);
-                       handle_setup_datetime_buttons(*(watch_button *)data, &dt_setup_screen);
+                       return handle_setup_datetime_buttons(*(watch_button *)data, &dt_setup_screen);
                        break;
                case EVENT_HALF_SEC_TIMER:
                        if (dt_setup_screen.on)
@@ -328,23 +397,27 @@ void datetime_setup_events(u16t event, void *data)
                        else
                                dt_setup_screen.on = TRUE;
                        draw_datetime_setup_screen(&dt_setup_screen);
+                       return EVENT_RET_HANDLED;
                        break;
                default:
+                       return EVENT_RET_UNHANDLED;
                        break;
        };
+       return EVENT_RET_UNHANDLED;
 }
 
 
 /*
- * Alarm setup
+ * Alarm setup screen
  */
-
 typedef struct {
-       u8t pos;
+       uint8_t pos;
+       boolean set_mode;
        boolean on;
 } alarm_setup_data_t;
 static alarm_setup_data_t alarm_setup_screen = {
        0,
+       FALSE,
        TRUE
 };
 
@@ -357,46 +430,44 @@ void draw_alarm_setup_screen(alarm_setup_data_t *sdata)
        oswald_draw_bitmap(81, 6, upbutton_icon_width, upbutton_icon_height, upbutton_icon_bits);
        oswald_draw_bitmap(81, 38, downbutton_icon_width, downbutton_icon_height, downbutton_icon_bits);
 
-       SetFont(MetaWatchTime);
        if ((sdata->pos == 0 && sdata->on) || sdata->pos != 0) {
-               WriteLcdCharacter(22, 30, (OswaldAlarm.hour / 10));
-               WriteLcdCharacter(34, 30, (OswaldAlarm.hour % 10));
+               oswald_write_character(18, 30, FONT_LCD13x21, (OswaldAlarm.hour / 10));
+               oswald_write_character(32, 30, FONT_LCD13x21, (OswaldAlarm.hour % 10));
        }
-       WriteLcdCharacter(46, 30, TIME_CHARACTER_COLON_INDEX);
+       oswald_write_character(42, 30, FONT_LCD13x21, 10);
 
        if ((sdata->pos == 1 && sdata->on) || sdata->pos != 1) {
-               WriteLcdCharacter(51, 30, (OswaldAlarm.minute / 10));
-               WriteLcdCharacter(63, 30, (OswaldAlarm.minute % 10));
+               oswald_write_character(53, 30, FONT_LCD13x21, (OswaldAlarm.minute / 10));
+               oswald_write_character(67, 30, FONT_LCD13x21, (OswaldAlarm.minute % 10));
        }
 
-       SetFont(MetaWatchMonospaced10);
-       WriteLcdCharacter(3, 55, 'S');
-       WriteLcdCharacter(15, 55, 'M');
-       WriteLcdCharacter(27, 55, 'T');
-       WriteLcdCharacter(39, 55, 'W');
-       WriteLcdCharacter(51, 55, 'T');
-       WriteLcdCharacter(63, 55, 'F');
-       WriteLcdCharacter(75, 55, 'S');
+       oswald_write_character(3, 55, FONT_6x9, 'S');
+       oswald_write_character(15, 55, FONT_6x9, 'M');
+       oswald_write_character(27, 55, FONT_6x9, 'T');
+       oswald_write_character(39, 55, FONT_6x9, 'W');
+       oswald_write_character(51, 55, FONT_6x9, 'T');
+       oswald_write_character(63, 55, FONT_6x9, 'F');
+       oswald_write_character(75, 55, FONT_6x9, 'S');
 
        if ((sdata->pos == 2 && sdata->on) || sdata->pos != 2)
-               WriteLcdCharacter(3, 65, (OswaldAlarm.wday & WDAY_SUNDAY) ? 'x' : '_');
+               oswald_write_character(3, 65, FONT_6x9, (OswaldAlarm.wday & WDAY_SUNDAY) ? 'x' : '_');
        if ((sdata->pos == 3 && sdata->on) || sdata->pos != 3)
-               WriteLcdCharacter(15, 65, (OswaldAlarm.wday & WDAY_MONDAY) ? 'x' : '_');
+               oswald_write_character(15, 65, FONT_6x9, (OswaldAlarm.wday & WDAY_MONDAY) ? 'x' : '_');
        if ((sdata->pos == 4 && sdata->on) || sdata->pos != 4)
-               WriteLcdCharacter(27, 65, (OswaldAlarm.wday & WDAY_TUESDAY) ? 'x' : '_');
+               oswald_write_character(27, 65, FONT_6x9, (OswaldAlarm.wday & WDAY_TUESDAY) ? 'x' : '_');
        if ((sdata->pos == 5 && sdata->on) || sdata->pos != 5)
-               WriteLcdCharacter(39, 65, (OswaldAlarm.wday & WDAY_WEDNESDAY) ? 'x' : '_');
+               oswald_write_character(39, 65, FONT_6x9, (OswaldAlarm.wday & WDAY_WEDNESDAY) ? 'x' : '_');
        if ((sdata->pos == 6 && sdata->on) || sdata->pos != 6)
-               WriteLcdCharacter(51, 65, (OswaldAlarm.wday & WDAY_THURSDAY) ? 'x' : '_');
+               oswald_write_character(51, 65, FONT_6x9, (OswaldAlarm.wday & WDAY_THURSDAY) ? 'x' : '_');
        if ((sdata->pos == 7 && sdata->on) || sdata->pos != 7)
-               WriteLcdCharacter(63, 65, (OswaldAlarm.wday & WDAY_FRIDAY) ? 'x' : '_');
+               oswald_write_character(63, 65, FONT_6x9, (OswaldAlarm.wday & WDAY_FRIDAY) ? 'x' : '_');
        if ((sdata->pos == 8 && sdata->on) || sdata->pos != 8)
-               WriteLcdCharacter(75, 65, (OswaldAlarm.wday & WDAY_SATURDAY) ? 'x' : '_');
+               oswald_write_character(75, 65, FONT_6x9, (OswaldAlarm.wday & WDAY_SATURDAY) ? 'x' : '_');
 
        hal_lcd_update_display();
 }
 
-void alarm_handle_updown(u8t pos, s8t incr)
+void alarm_handle_updown(uint8_t pos, int8_t incr)
 {
        switch (pos) {
                case 0: // hour
@@ -443,65 +514,92 @@ void alarm_handle_updown(u8t pos, s8t incr)
        };
 }
 
-void handle_setup_alarm_buttons(watch_button button, alarm_setup_data_t *sdata)
+event_ret_t handle_setup_alarm_buttons(watch_button button, alarm_setup_data_t *sdata)
 {
-       switch (button) {
-               case BUTTON_A:
-                       alarm_handle_updown(sdata->pos, 1);
-                       break;
-               case BUTTON_B:
-                       alarm_handle_updown(sdata->pos, -1);
-                       break;
-               case BUTTON_F:
-                       sdata->pos++;
-                       sdata->pos %= 9;
-                       break;
-               default:
-                       break;
+       if (alarm_setup_screen.set_mode) {
+               switch (button) {
+                       case BUTTON_A:
+                               alarm_handle_updown(sdata->pos, 1);
+                               break;
+                       case BUTTON_B:
+                               alarm_handle_updown(sdata->pos, -1);
+                               break;
+                       case BUTTON_C:
+                               sdata->pos++;
+                               sdata->pos %= 9;
+                               break;
+                       case BUTTON_F:
+                               alarm_setup_screen.set_mode = FALSE;
+                               break;
+                       default:
+                               return EVENT_RET_UNHANDLED;
+                               break;
+               }
+       } else {
+               switch (button) {
+                       case BUTTON_F:
+                               alarm_setup_screen.set_mode = TRUE;
+                               break;
+                       default:
+                               return EVENT_RET_UNHANDLED;
+                               break;
+               }
        }
        draw_alarm_setup_screen(sdata);
+
+       return EVENT_RET_HANDLED;
 }
 
-void alarm_setup_events(u16t event, void *data)
+event_ret_t alarm_setup_events(uint16_t event, void *data)
 {
        switch (event) {
                case EVENT_SCREEN_VISIBLE:
                        alarm_setup_screen.pos = 0;
+                       alarm_setup_screen.on = TRUE;
+                       alarm_setup_screen.set_mode = FALSE;
                        draw_alarm_setup_screen(&alarm_setup_screen);
                        hal_enable_halfsecond_timer();
+                       return EVENT_RET_HANDLED;
                        break;
                case EVENT_SCREEN_DESTROY:
                        hal_disable_halfsecond_timer();
+                       return EVENT_RET_HANDLED;
                        break;
                case EVENT_USER_BUTTONS:
                        dbg_out("button event %d\n", *(int *)data);
-                       handle_setup_alarm_buttons(*(watch_button *)data, &alarm_setup_screen);
+                       return handle_setup_alarm_buttons(*(watch_button *)data, &alarm_setup_screen);
                        break;
                case EVENT_HALF_SEC_TIMER:
-                       if (alarm_setup_screen.on)
-                               alarm_setup_screen.on = FALSE;
-                       else
+                       if (alarm_setup_screen.set_mode) {
+                               if (alarm_setup_screen.on)
+                                       alarm_setup_screen.on = FALSE;
+                               else
+                                       alarm_setup_screen.on = TRUE;
+                       } else
                                alarm_setup_screen.on = TRUE;
                        draw_alarm_setup_screen(&alarm_setup_screen);
+                       return EVENT_RET_HANDLED;
                        break;
                default:
+                       return EVENT_RET_UNHANDLED;
                        break;
        };
+       return EVENT_RET_UNHANDLED;
 }
 
 
 /*
  * Test menu
  */
-
 typedef struct {
-       u8t menu_pos;
+       uint8_t menu_pos;
 } test_menu_t;
 static test_menu_t test_menu = { 0 };
 
 void draw_menu_test_screen(void)
 {
        hal_lcd_clear_display();
+#if 0
        SetFont(MetaWatch16);
        WriteLcdString(2, 2, "Menu");
        SetFont(MetaWatch7);
@@ -512,84 +610,134 @@ void draw_menu_test_screen(void)
        WriteLcdString(2, 56, "Item 5");
 
        WriteLcdString(50, 20+(9*test_menu.menu_pos), "*");
+#endif
+       oswald_write_string(2, 2, FONT_DROID11x14b, "Menu");
+
+       oswald_write_string(2, 20, FONT_DROID8x12, "Item 1");
+       oswald_write_string(2, 29, FONT_DROID8x12, "Item 2");
+       oswald_write_string(2, 38, FONT_DROID8x12, "Item 3");
+       oswald_write_string(2, 47, FONT_DROID8x12, "Item 4");
+       oswald_write_string(2, 56, FONT_DROID8x12, "Item 5");
+
+       oswald_write_character(50, 18+(9*test_menu.menu_pos), FONT_6x9, 0x11);
+
        hal_lcd_update_display();
 }
 
-static void handle_menu_user_buttons(watch_button button)
+event_ret_t handle_menu_user_buttons(watch_button button)
 {
        switch (button) {
                case BUTTON_A:
                        test_menu.menu_pos--;
-                       test_menu.menu_pos%=5;
+                       test_menu.menu_pos %= 5;
                        break;
                case BUTTON_B:
                        test_menu.menu_pos++;
-                       test_menu.menu_pos%=5;
+                       test_menu.menu_pos %= 5;
                        break;
                default:
+                       return EVENT_RET_UNHANDLED;
                        break;
        }
        draw_menu_test_screen();
+       return EVENT_RET_HANDLED;
 }
 
-void test_menu_handle_events(u16t event, void *data)
+event_ret_t test_menu_handle_events(uint16_t event, void *data)
 {
        switch (event) {
                case EVENT_USER_BUTTONS:
                        dbg_out("button event %d\n", *(int *)data);
-                       handle_menu_user_buttons(*(watch_button *)data);
+                       return handle_menu_user_buttons(*(watch_button *)data);
                        break;
                case EVENT_SCREEN_VISIBLE:
                        test_menu.menu_pos = 0;
                        draw_menu_test_screen();
                        break;
                default:
+                       return EVENT_RET_UNHANDLED;
                        break;
        };
+       return EVENT_RET_HANDLED;
 }
 
 
 /*
  * Stop Watch
  */
-
 typedef struct {
-       u8t hr;
-       u8t min;
-       u8t sec;
-       u8t csec;
-       u8t lapse_hr;
-       u8t lapse_min;
-       u8t lapse_sec;
-       u8t lapse_csec;
+       uint8_t hr;
+       uint8_t min;
+       uint8_t sec;
+       uint8_t csec;
+       uint8_t lapse_hr;
+       uint8_t lapse_min;
+       uint8_t lapse_sec;
+       uint8_t lapse_csec;
        boolean running;
 } stopwatch_data_t;
 static stopwatch_data_t stopwatch_screen = { 0, 0, 0, 0, 0, 0, 0, 0, FALSE };
 
-
+#if 0
 static void update_stop_watch_screen(stopwatch_data_t *sdata)
 {
-       char tstr[16];
+       //char tstr[16];
+#if 0
        SetFont(MetaWatchMonospaced10);
 
        snprintf(tstr, 16, "%02d:%02d:%02d.%1d", sdata->hr, sdata->min, sdata->sec, sdata->csec / 10);
        WriteLcdString(5, 40, tstr);
        snprintf(tstr, 16, "%02d:%02d:%02d.%02d", sdata->lapse_hr, sdata->lapse_min, sdata->lapse_sec, sdata->lapse_csec);
        WriteLcdString(5, 60, tstr);
+#endif
+#if 0
+       snprintf(tstr, 16, "%02d:%02d:%02d.%1d", sdata->hr, sdata->min, sdata->sec, sdata->csec / 10);
+       oswald_write_string(5, 40, FONT_6x9, tstr);
+
+       snprintf(tstr, 16, "%02d:%02d:%02d.%02d", sdata->lapse_hr, sdata->lapse_min, sdata->lapse_sec, sdata->lapse_csec);
+       oswald_write_string(5, 60, FONT_6x9, tstr);
+#endif
 
        hal_lcd_update_display();
 }
+#endif
 
 static void draw_stop_watch_screen(stopwatch_data_t *sdata)
 {
+       int gRow = 1;
+       int gColumn = 35;
+
+       hal_lcd_clear_display();
+
        oswald_draw_bitmap(36, 0, stopwatch_icon_width, stopwatch_icon_height, stopwatch_icon_bits);
        oswald_draw_bitmap(81, 6, startstopbutton_icon_width, startstopbutton_icon_height, startstopbutton_icon_bits);
        oswald_draw_bitmap(81, 38, lapsebutton_icon_width, lapsebutton_icon_height, lapsebutton_icon_bits);
 
+#if 0
        update_stop_watch_screen(sdata);
+#else
+       gRow += 3 + oswald_write_character(gRow, gColumn, FONT_LCD13x21, (sdata->hr % 10));
+       gRow += oswald_write_character(gRow, gColumn, FONT_LCD13x21, (sdata->min / 10));
+       gRow += 3 + oswald_write_character(gRow, gColumn, FONT_LCD13x21, (sdata->min % 10));
+       gRow += oswald_write_character(gRow, gColumn, FONT_LCD13x21, (sdata->sec / 10));
+       gRow += 3 + oswald_write_character(gRow, gColumn, FONT_LCD13x21, (sdata->sec % 10));
+       gRow += oswald_write_character(gRow, gColumn, FONT_LCD8x13, (sdata->csec / 10));
+
+       gRow = 6;
+       gColumn = 62;
+       gRow += 13 + oswald_write_character(gRow, gColumn, FONT_LCD8x13, (sdata->lapse_hr % 10));
+       gRow += oswald_write_character(gRow, gColumn, FONT_LCD8x13, (sdata->lapse_min / 10));
+       gRow += 13 + oswald_write_character(gRow, gColumn, FONT_LCD8x13, (sdata->lapse_min % 10));
+       gRow += oswald_write_character(gRow, gColumn, FONT_LCD8x13, (sdata->lapse_sec / 10));
+       gRow += 3 + oswald_write_character(gRow, gColumn, FONT_LCD8x13, (sdata->lapse_sec % 10));
+       gRow += oswald_write_character(gRow, gColumn, FONT_LCD8x13, (sdata->lapse_csec / 10));
+       gRow += oswald_write_character(gRow, gColumn, FONT_LCD8x13, (sdata->lapse_csec % 10));
+
+       hal_lcd_update_display();
+#endif
 }
 
-static void handle_stop_watch_buttons(watch_button button)
+event_ret_t handle_stop_watch_buttons(watch_button button)
 {
        switch (button) {
                case BUTTON_A: // start/stop
@@ -600,12 +748,14 @@ static void handle_stop_watch_buttons(watch_button button)
                                hal_enable_centisecond_timer();
                                stopwatch_screen.running = TRUE;
                        }
+                       return EVENT_RET_HANDLED;
                        break;
                case BUTTON_B: // lapse
                        stopwatch_screen.lapse_hr = stopwatch_screen.hr;
                        stopwatch_screen.lapse_min = stopwatch_screen.min;
                        stopwatch_screen.lapse_sec = stopwatch_screen.sec;
                        stopwatch_screen.lapse_csec = stopwatch_screen.csec;
+                       return EVENT_RET_HANDLED;
                        break;
                case BUTTON_F: // reset
                        stopwatch_screen.hr = 0;
@@ -616,27 +766,33 @@ static void handle_stop_watch_buttons(watch_button button)
                        stopwatch_screen.lapse_min = 0;
                        stopwatch_screen.lapse_sec = 0;
                        stopwatch_screen.lapse_csec = 0;
+                       return EVENT_RET_HANDLED;
                        break;
                default:
+                       return EVENT_RET_UNHANDLED;
                        break;
        }
+       return EVENT_RET_UNHANDLED;
 }
 
-void stop_watch_handle_events(u16t event, void *data)
+event_ret_t stop_watch_handle_events(uint16_t event, void *data)
 {
        switch (event) {
                case EVENT_USER_BUTTONS:
                        dbg_out("button event %d\n", *(int *)data);
-                       handle_stop_watch_buttons(*(watch_button *)data);
-                       update_stop_watch_screen(&stopwatch_screen);
+                       return handle_stop_watch_buttons(*(watch_button *)data);
+                       //update_stop_watch_screen(&stopwatch_screen);
+                       draw_stop_watch_screen(&stopwatch_screen);
                        break;
                case EVENT_SCREEN_VISIBLE:
                        hal_lcd_clear_display();
                        draw_stop_watch_screen(&stopwatch_screen);
+                       return EVENT_RET_HANDLED;
                        break;
                case EVENT_SCREEN_DESTROY:
                        hal_disable_centisecond_timer();
                        stopwatch_screen.running = FALSE;
+                       return EVENT_RET_HANDLED;
                        break;
                case EVENT_CS_TIMER:
                        stopwatch_screen.csec++;
@@ -656,68 +812,76 @@ void stop_watch_handle_events(u16t event, void *data)
                                stopwatch_screen.hr = 0;
                        };
                        if (stopwatch_screen.csec % 10 == 0)
-                               update_stop_watch_screen(&stopwatch_screen);
+                               draw_stop_watch_screen(&stopwatch_screen);
+                               //update_stop_watch_screen(&stopwatch_screen);
+                       return EVENT_RET_HANDLED;
                        break;
                default:
+                       return EVENT_RET_UNHANDLED;
                        break;
        };
+       return EVENT_RET_HANDLED;
 }
 
 
 /*
- * when alarm is fired
+ * Alarm screen, shown when alarm is fired
  */
 void draw_alarm_screen(void)
 {
        hal_lcd_clear_display();
 
-//     SetFont(MetaWatch16);
-//     WriteLcdString(2, 2, "ALARM !");
        oswald_draw_bitmap(36, 20, alarm_icon_width, alarm_icon_height, alarm_icon_bits);
 
-
        hal_lcd_update_display();
 }
 
-void alarm_handle_events(u16t event, void *data)
+event_ret_t alarm_handle_events(uint16_t event, void *data)
 {
        switch (event) {
                case EVENT_SCREEN_VISIBLE:
                        draw_alarm_screen();
                        hal_enable_halfsecond_timer();
                        hal_vibration_set_state(TRUE);
+                       return EVENT_RET_HANDLED;
                        break;
                case EVENT_SCREEN_DESTROY:
                        hal_disable_halfsecond_timer();
                        hal_lcd_set_backlight(FALSE);
                        hal_vibration_set_state(FALSE);
+                       return EVENT_RET_HANDLED;
                        break;
                case EVENT_USER_BUTTONS:
                        dbg_out("button event %d\n", *(int *)data);
-                       // hal_lcd_set_backlight(FALSE);
+                       return EVENT_RET_UNHANDLED;
                        break;
                case EVENT_HALF_SEC_TIMER:
                        hal_lcd_set_backlight(!hal_lcd_get_backlight());
                        hal_vibration_set_state(!hal_vibration_get_state());
                        dbg_out("timer\n");
+                       return EVENT_RET_HANDLED;
                        break;
                default:
+                       return EVENT_RET_UNHANDLED;
                        break;
        };
+       return EVENT_RET_HANDLED;
 }
 
 
 /*
- * Bluetooth screen
+ * Bluetooth setup screen
  */
 typedef struct {
-       u8t pos;
+       uint8_t pos;
        boolean bt_en;
+       boolean set_mode;
        boolean on;
 } bluetooth_data_t;
 static bluetooth_data_t bluetooth_screen = {
        0,
        FALSE,
+       FALSE,
        TRUE
 };
 
@@ -733,40 +897,40 @@ void draw_bluetooth_screen(bluetooth_data_t *sdata)
        oswald_draw_bitmap(81, 6, upbutton_icon_width, upbutton_icon_height, upbutton_icon_bits);
        oswald_draw_bitmap(81, 38, downbutton_icon_width, downbutton_icon_height, downbutton_icon_bits);
 
-       SetFont(MetaWatch5);
-       WriteLcdString(2, 30, "Enable:");
+       oswald_write_string(1, 30, FONT_DROID8x12, "Enable:");
        if ((sdata->pos == 0 && sdata->on) || sdata->pos != 0) {
-               WriteLcdCharacter(45, 30, bluetooth_screen.bt_en ? 'x' : '_');
+               oswald_write_character(53, 30, FONT_DROID8x12, bluetooth_screen.bt_en ? 'x' : '_');
        }
-       WriteLcdString(2, 39, "State:");
+       oswald_write_string(1, 40, FONT_DROID8x12, "State:");
        switch (hal_bluetooth_get_state()) {
                case BLUETOOTH_OFF:
-                       WriteLcdString(45, 39, "off");
+                       oswald_write_string(53, 40, FONT_DROID8x12, "off");
                        break;
                case BLUETOOTH_ON:
-                       WriteLcdString(45, 39, "on");
+                       oswald_write_string(53, 40, FONT_DROID8x12, "on");
                        break;
                case BLUETOOTH_CONNECTED:
-                       WriteLcdString(45, 39, "conn.");
+                       oswald_write_string(53, 40, FONT_DROID8x12, "conn.");
                        break;
                default:
                        break;
        };
+       oswald_write_string(1, 50, FONT_DROID8x12, "Visible:");
+       if ((sdata->pos == 1 && sdata->on) || sdata->pos != 1) {
+               oswald_write_character(53, 50, FONT_DROID8x12, hal_bluetooth_get_visible() ? 'x' : '_');
+       }
+
        if (hal_bluetooth_get_state() >= BLUETOOTH_ON) {
                bd_addr = hal_bluetooth_get_local_bdaddr();
                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]);
-               WriteLcdString(2, 48, bstr);
+               oswald_write_string(2, 85, FONT_5x7, bstr);
        } else {
        }
-       WriteLcdString(2, 57, "Visible:");
-       if ((sdata->pos == 1 && sdata->on) || sdata->pos != 1) {
-               WriteLcdCharacter(45, 57, hal_bluetooth_get_visible() ? 'x' : '_');
-       }
 
        hal_lcd_update_display();
 }
 
-void bluetooth_handle_updown(u8t pos, s8t incr)
+void bluetooth_handle_updown(uint8_t pos, int8_t incr)
 {
        switch (pos) {
                case 0:
@@ -804,26 +968,44 @@ void bluetooth_handle_updown(u8t pos, s8t incr)
        };
 }
 
-void handle_bluetooth_buttons(watch_button button, bluetooth_data_t *sdata)
+event_ret_t handle_bluetooth_buttons(watch_button button, bluetooth_data_t *sdata)
 {
-       switch (button) {
-               case BUTTON_A:
-                       bluetooth_handle_updown(sdata->pos, 1);
-                       break;
-               case BUTTON_B:
-                       bluetooth_handle_updown(sdata->pos, -1);
-                       break;
-               case BUTTON_F:
-                       sdata->pos++;
-                       sdata->pos %= 2;
-                       break;
-               default:
-                       break;
+       if (bluetooth_screen.set_mode) {
+               switch (button) {
+                       case BUTTON_A:
+                               bluetooth_handle_updown(sdata->pos, 1);
+                               break;
+                       case BUTTON_B:
+                               bluetooth_handle_updown(sdata->pos, -1);
+                               break;
+                       case BUTTON_C:
+                               sdata->pos++;
+                               sdata->pos %= 2;
+                               break;
+                       case BUTTON_F:
+                               bluetooth_screen.set_mode = FALSE;
+                               break;
+                       default:
+                               return EVENT_RET_UNHANDLED;
+                               break;
+               }
+       } else {
+               switch (button) {
+                       case BUTTON_F:
+                               bluetooth_screen.set_mode = TRUE;
+                               break;
+                       default:
+                               return EVENT_RET_UNHANDLED;
+                               break;
+               }
        }
+
        draw_bluetooth_screen(sdata);
+
+       return EVENT_RET_HANDLED;
 }
 
-void bluetooth_screen_events(u16t event, void *data)
+event_ret_t bluetooth_screen_events(uint16_t event, void *data)
 {
        switch (event) {
                case EVENT_SCREEN_VISIBLE:
@@ -837,17 +1019,61 @@ void bluetooth_screen_events(u16t event, void *data)
                        break;
                case EVENT_USER_BUTTONS:
                        dbg_out("button event %d\n", *(int *)data);
-                       handle_bluetooth_buttons(*(watch_button *)data, &bluetooth_screen);
+                       return handle_bluetooth_buttons(*(watch_button *)data, &bluetooth_screen);
                        break;
                case EVENT_HALF_SEC_TIMER:
-                       if (bluetooth_screen.on)
-                               bluetooth_screen.on = FALSE;
-                       else
+                       if (bluetooth_screen.set_mode) {
+                               if (bluetooth_screen.on)
+                                       bluetooth_screen.on = FALSE;
+                               else
+                                       bluetooth_screen.on = TRUE;
+                       } else
                                bluetooth_screen.on = TRUE;
                        draw_bluetooth_screen(&bluetooth_screen);
                        break;
                default:
+                       return EVENT_RET_UNHANDLED;
+                       break;
+       };
+       return EVENT_RET_HANDLED;
+}
+
+
+/*
+ * Info Screen
+ */
+void draw_info_screen(accel_data_t *accel_data)
+{
+       hal_lcd_clear_display();
+
+       oswald_draw_bitmap(36, 0, info_icon_width, info_icon_height, info_icon_bits);
+
+       oswald_write_string(2, 29, FONT_DROID8x12, "Oswald");
+       oswald_write_string(35, 29, FONT_DROID8x12, OSWALD_VERSION);
+       oswald_write_string(2, 41, FONT_DROID8x12, "HAL");
+       oswald_write_string(35, 41, FONT_DROID8x12, (char *)hal_get_version_string());
+       oswald_write_string(2, 53, FONT_DROID8x12, "Build");
+       oswald_write_string(35, 53, FONT_DROID8x12, (char *)hal_get_buildno_string());
+       oswald_write_string(2, 65, FONT_DROID8x12, "Radio");
+       oswald_write_string(35, 65, FONT_DROID8x12, (char *)hal_get_radio_version_string());
+
+       hal_lcd_update_display();
+}
+
+event_ret_t info_screen_handle_events(uint16_t event, void *data)
+{
+       switch (event) {
+               case EVENT_SCREEN_VISIBLE:
+                       draw_info_screen(&accel_screen.accdata);
+                       return EVENT_RET_HANDLED;
+                       break;
+               case EVENT_USER_BUTTONS:
+                       dbg_out("button event %d\n", *(int *)data);
+                       break;
+               default:
+                       return EVENT_RET_UNHANDLED;
                        break;
        };
+       return EVENT_RET_UNHANDLED;
 }