]> git.karo-electronics.de Git - oswald.git/blobdiff - ui/oswald_screens.c
Starting to get rid of borrowed code (LcdDisplay, Fonts), integrate
[oswald.git] / ui / oswald_screens.c
index 171d7b6d22ae244aa384e418b0d626144829b059..ddca03c2a861c2aa4fc3d82aa8da2f24d50247d2 100644 (file)
@@ -1,11 +1,49 @@
+#include <stdio.h>
+
 #include "oswald.h"
 #include "oswald_main.h"
 #include "oswald_watch_faces.h"
-#include "Fonts.h"
-#include "LcdDisplay.h"
+#include "oswald_graphics.h"
+#include "oswald_hal.h"
 
 #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"
+
 
 typedef struct {
        void (*screendraw_func)(boolean show_seconds);
@@ -14,7 +52,7 @@ typedef struct {
 } idle_data_t;
 static idle_data_t idle_screen = {
        DrawLcdDigitalClock,
-       FALSE,
+       TRUE,
        FALSE,
 };
  
@@ -36,7 +74,7 @@ void idle_handle_user_buttons(watch_button button)
                                idle_screen.screendraw_func = DrawLcdAnaClock;
                        };
                        break;
-               case BUTTON_D:
+               case BUTTON_F:
                        OswaldState.screen_id = DATETIME_SETTING_SCREEN;
                        OswaldState.screen = &OswaldScreens[OswaldState.screen_id];
                        OswaldState.screen->event_func(EVENT_SCREEN_VISIBLE, NULL);
@@ -74,14 +112,22 @@ static accelscreen_data_t accel_screen = {
 
 void draw_accel_screen(accel_data_t *accel_data)
 {
-       lcd_clear_display();
-       SetFont(MetaWatch16);
-       WriteLcdString(2, 2, "X:");
-       WriteLcdNumber(20, 2, accel_data->x);
-       WriteLcdString(2, 18, "Y:");
-       WriteLcdNumber(20, 18, accel_data->y);
-       WriteLcdString(2, 34, "Z:");
-       WriteLcdNumber(20, 34, accel_data->z);
+       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_write_string(0, 54, FONT_12x16, "Light:");
+       oswald_write_number(50, 54, FONT_12x16, accel_data->z);
+
+       oswald_write_string(0, 70, FONT_12x20, "23:59");
+#endif
+       hal_lcd_update_display();
 }
 
 void accel_handle_events(u16t event, void *data)
@@ -118,58 +164,62 @@ static datetime_setup_data_t dt_setup_screen = {
 
 void draw_datetime_setup_screen(datetime_setup_data_t *sdata)
 {
-       lcd_clear_display();
-       SetFont(MetaWatch16);
-       WriteLcdString(2, 2, "Set");
+       hal_lcd_clear_display();
+
+       oswald_draw_bitmap(36, 0, timesetup_icon_width, timesetup_icon_height, timesetup_icon_bits);
+
+       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, 20, (OswaldClk.hour / 10));
-               WriteLcdCharacter(14, 20, (OswaldClk.hour % 10));
+               WriteLcdCharacter(2, 30, (OswaldClk.hour / 10));
+               WriteLcdCharacter(14, 30, (OswaldClk.hour % 10));
        }
-       WriteLcdCharacter(26, 20, TIME_CHARACTER_COLON_INDEX);
+       WriteLcdCharacter(26, 30, TIME_CHARACTER_COLON_INDEX);
 
        if ((sdata->pos == 1 && sdata->on) || sdata->pos != 1) {
-               WriteLcdCharacter(31, 20, (OswaldClk.minute / 10));
-               WriteLcdCharacter(43, 20, (OswaldClk.minute % 10));
+               WriteLcdCharacter(31, 30, (OswaldClk.minute / 10));
+               WriteLcdCharacter(43, 30, (OswaldClk.minute % 10));
        }
 
-       WriteLcdCharacter(55, 20, TIME_CHARACTER_COLON_INDEX);
-
+       SetFont(MetaWatch16);
        if ((sdata->pos == 2 && sdata->on) || sdata->pos != 2) {
-               WriteLcdCharacter(60, 20, (OswaldClk.second / 10));
-               WriteLcdCharacter(72, 20, (OswaldClk.second % 10));
+               WriteLcdCharacter(59, 36, 0x30 + (OswaldClk.second / 10));
+               WriteLcdCharacter(66, 36, 0x30 + (OswaldClk.second % 10));
        }
 
-       SetFont(MetaWatch16);
+
        if ((sdata->pos == 3 && sdata->on) || sdata->pos != 3) {
-               WriteLcdNumber(2, 45, OswaldClk.day);
+               WriteLcdNumber(2, 55, OswaldClk.day);
        }
-       WriteLcdString(18, 45, ".");
+       WriteLcdString(18, 55, ".");
        if ((sdata->pos == 4 && sdata->on) || sdata->pos != 4) {
-               WriteLcdNumber(22, 45, OswaldClk.month);
+               WriteLcdNumber(22, 55, OswaldClk.month);
        }
-       WriteLcdString(38, 45, ".");
+       WriteLcdString(38, 55, ".");
        if ((sdata->pos == 5 && sdata->on) || sdata->pos != 5) {
-               WriteLcdNumber(42, 45, OswaldClk.year);
+               WriteLcdNumber(42, 55, OswaldClk.year);
        }
 
        SetFont(MetaWatch7);
        if ((sdata->pos == 6 && sdata->on) || sdata->pos != 6) {
                if (OswaldClk.clk24hr)
-                       WriteLcdString(2, 66, "x");
+                       WriteLcdString(2, 76, "x");
                else
-                       WriteLcdString(2, 66, "_");
+                       WriteLcdString(2, 76, "_");
        }
-       WriteLcdString(15, 66, "24hr");
+       WriteLcdString(15, 76, "24hr");
 
        if ((sdata->pos == 7 && sdata->on) || sdata->pos != 7) {
                if (OswaldClk.day_first)
-                       WriteLcdString(2, 79, "x");
+                       WriteLcdString(2, 89, "x");
                else
-                       WriteLcdString(2, 79, "_");
+                       WriteLcdString(2, 89, "_");
        }
-       WriteLcdString(15, 79, "dd.mm.  mm/dd");
+       WriteLcdString(15, 89, "dd.mm.  mm/dd");
+
+       hal_lcd_update_display();
 }
 
 void datetime_handle_updown(u8t pos, s8t incr)
@@ -232,6 +282,10 @@ void datetime_handle_updown(u8t pos, s8t incr)
                default:
                        break;
        };
+       if (pos == 2)
+               hal_set_rtc(&OswaldClk, TRUE);
+       else
+               hal_set_rtc(&OswaldClk, FALSE);
 }
 
 void handle_setup_datetime_buttons(watch_button button, datetime_setup_data_t *sdata)
@@ -243,7 +297,7 @@ 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_D:
+               case BUTTON_F:
                        sdata->pos++;
                        sdata->pos %= 8;
                        break;
@@ -257,11 +311,12 @@ void datetime_setup_events(u16t event, void *data)
 {
        switch (event) {
                case EVENT_SCREEN_VISIBLE:
+                       dt_setup_screen.pos = 0;
                        draw_datetime_setup_screen(&dt_setup_screen);
-                       enable_halfsecond_timer();
+                       hal_enable_halfsecond_timer();
                        break;
                case EVENT_SCREEN_DESTROY:
-                       disable_halfsecond_timer();
+                       hal_disable_halfsecond_timer();
                        break;
                case EVENT_USER_BUTTONS:
                        dbg_out("button event %d\n", *(int *)data);
@@ -280,6 +335,165 @@ void datetime_setup_events(u16t event, void *data)
 }
 
 
+/*
+ * Alarm setup
+ */
+
+typedef struct {
+       u8t pos;
+       boolean on;
+} alarm_setup_data_t;
+static alarm_setup_data_t alarm_setup_screen = {
+       0,
+       TRUE
+};
+
+void draw_alarm_setup_screen(alarm_setup_data_t *sdata)
+{
+       hal_lcd_clear_display();
+
+       oswald_draw_bitmap(36, 0, alarm_icon_width, alarm_icon_height, alarm_icon_bits);
+
+       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));
+       }
+       WriteLcdCharacter(46, 30, TIME_CHARACTER_COLON_INDEX);
+
+       if ((sdata->pos == 1 && sdata->on) || sdata->pos != 1) {
+               WriteLcdCharacter(51, 30, (OswaldAlarm.minute / 10));
+               WriteLcdCharacter(63, 30, (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');
+
+       if ((sdata->pos == 2 && sdata->on) || sdata->pos != 2)
+               WriteLcdCharacter(3, 65, (OswaldAlarm.wday & WDAY_SUNDAY) ? 'x' : '_');
+       if ((sdata->pos == 3 && sdata->on) || sdata->pos != 3)
+               WriteLcdCharacter(15, 65, (OswaldAlarm.wday & WDAY_MONDAY) ? 'x' : '_');
+       if ((sdata->pos == 4 && sdata->on) || sdata->pos != 4)
+               WriteLcdCharacter(27, 65, (OswaldAlarm.wday & WDAY_TUESDAY) ? 'x' : '_');
+       if ((sdata->pos == 5 && sdata->on) || sdata->pos != 5)
+               WriteLcdCharacter(39, 65, (OswaldAlarm.wday & WDAY_WEDNESDAY) ? 'x' : '_');
+       if ((sdata->pos == 6 && sdata->on) || sdata->pos != 6)
+               WriteLcdCharacter(51, 65, (OswaldAlarm.wday & WDAY_THURSDAY) ? 'x' : '_');
+       if ((sdata->pos == 7 && sdata->on) || sdata->pos != 7)
+               WriteLcdCharacter(63, 65, (OswaldAlarm.wday & WDAY_FRIDAY) ? 'x' : '_');
+       if ((sdata->pos == 8 && sdata->on) || sdata->pos != 8)
+               WriteLcdCharacter(75, 65, (OswaldAlarm.wday & WDAY_SATURDAY) ? 'x' : '_');
+
+       hal_lcd_update_display();
+}
+
+void alarm_handle_updown(u8t pos, s8t incr)
+{
+       switch (pos) {
+               case 0: // hour
+                       if (OswaldAlarm.hour == 0 && incr == -1) {
+                               OswaldAlarm.hour = 23;
+                               break;
+                       };
+                       OswaldAlarm.hour += incr;
+                       if (OswaldAlarm.hour > 23)
+                               OswaldAlarm.hour = 0;
+                       break;
+               case 1: // minute
+                       if (OswaldAlarm.minute == 0 && incr == -1) {
+                               OswaldAlarm.minute = 59;
+                               break;
+                       };
+                       OswaldAlarm.minute += incr;
+                       if (OswaldAlarm.minute > 59)
+                               OswaldAlarm.minute = 0;
+                       break;
+               case 2: // sunday
+                       OswaldAlarm.wday ^= WDAY_SUNDAY;
+                       break;
+               case 3: // monday
+                       OswaldAlarm.wday ^= WDAY_MONDAY;
+                       break;
+               case 4: // tuesday
+                       OswaldAlarm.wday ^= WDAY_TUESDAY;
+                       break;
+               case 5: // wednesday
+                       OswaldAlarm.wday ^= WDAY_WEDNESDAY;
+                       break;
+               case 6: // thursday
+                       OswaldAlarm.wday ^= WDAY_THURSDAY;
+                       break;
+               case 7: // friday
+                       OswaldAlarm.wday ^= WDAY_FRIDAY;
+                       break;
+               case 8: // saturday
+                       OswaldAlarm.wday ^= WDAY_SATURDAY;
+                       break;
+               default:
+                       break;
+       };
+}
+
+void 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;
+       }
+       draw_alarm_setup_screen(sdata);
+}
+
+void alarm_setup_events(u16t event, void *data)
+{
+       switch (event) {
+               case EVENT_SCREEN_VISIBLE:
+                       alarm_setup_screen.pos = 0;
+                       draw_alarm_setup_screen(&alarm_setup_screen);
+                       hal_enable_halfsecond_timer();
+                       break;
+               case EVENT_SCREEN_DESTROY:
+                       hal_disable_halfsecond_timer();
+                       break;
+               case EVENT_USER_BUTTONS:
+                       dbg_out("button event %d\n", *(int *)data);
+                       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
+                               alarm_setup_screen.on = TRUE;
+                       draw_alarm_setup_screen(&alarm_setup_screen);
+                       break;
+               default:
+                       break;
+       };
+}
+
+
+/*
+ * Test menu
+ */
+
 typedef struct {
        u8t menu_pos;
 } test_menu_t;
@@ -287,7 +501,7 @@ static test_menu_t test_menu = { 0 };
 
 void draw_menu_test_screen(void)
 {
-       lcd_clear_display();
+       hal_lcd_clear_display();
        SetFont(MetaWatch16);
        WriteLcdString(2, 2, "Menu");
        SetFont(MetaWatch7);
@@ -298,6 +512,7 @@ void draw_menu_test_screen(void)
        WriteLcdString(2, 56, "Item 5");
 
        WriteLcdString(50, 20+(9*test_menu.menu_pos), "*");
+       hal_lcd_update_display();
 }
 
 static void handle_menu_user_buttons(watch_button button)
@@ -333,3 +548,306 @@ void test_menu_handle_events(u16t event, void *data)
        };
 }
 
+
+/*
+ * Stop Watch
+ */
+
+typedef struct {
+       u8t hr;
+       u8t min;
+       u8t sec;
+       u8t csec;
+       u8t lapse_hr;
+       u8t lapse_min;
+       u8t lapse_sec;
+       u8t lapse_csec;
+       boolean running;
+} stopwatch_data_t;
+static stopwatch_data_t stopwatch_screen = { 0, 0, 0, 0, 0, 0, 0, 0, FALSE };
+
+
+static void update_stop_watch_screen(stopwatch_data_t *sdata)
+{
+       char tstr[16];
+       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);
+
+       hal_lcd_update_display();
+}
+
+static void draw_stop_watch_screen(stopwatch_data_t *sdata)
+{
+       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);
+
+       update_stop_watch_screen(sdata);
+}
+
+static void handle_stop_watch_buttons(watch_button button)
+{
+       switch (button) {
+               case BUTTON_A: // start/stop
+                       if (stopwatch_screen.running) {
+                               hal_disable_centisecond_timer();
+                               stopwatch_screen.running = FALSE;
+                       } else {
+                               hal_enable_centisecond_timer();
+                               stopwatch_screen.running = TRUE;
+                       }
+                       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;
+                       break;
+               case BUTTON_F: // reset
+                       stopwatch_screen.hr = 0;
+                       stopwatch_screen.min = 0;
+                       stopwatch_screen.sec = 0;
+                       stopwatch_screen.csec = 0;
+                       stopwatch_screen.lapse_hr = 0;
+                       stopwatch_screen.lapse_min = 0;
+                       stopwatch_screen.lapse_sec = 0;
+                       stopwatch_screen.lapse_csec = 0;
+                       break;
+               default:
+                       break;
+       }
+}
+
+void stop_watch_handle_events(u16t 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);
+                       break;
+               case EVENT_SCREEN_VISIBLE:
+                       hal_lcd_clear_display();
+                       draw_stop_watch_screen(&stopwatch_screen);
+                       break;
+               case EVENT_SCREEN_DESTROY:
+                       hal_disable_centisecond_timer();
+                       stopwatch_screen.running = FALSE;
+                       break;
+               case EVENT_CS_TIMER:
+                       stopwatch_screen.csec++;
+                       if (stopwatch_screen.csec > 99) {
+                               stopwatch_screen.csec = 0;
+                               stopwatch_screen.sec++;
+                       };
+                       if (stopwatch_screen.sec > 59) {
+                               stopwatch_screen.sec = 0;
+                               stopwatch_screen.min++;
+                       };
+                       if (stopwatch_screen.min > 59) {
+                               stopwatch_screen.min = 0;
+                               stopwatch_screen.hr++;
+                       };
+                       if (stopwatch_screen.hr > 59) {
+                               stopwatch_screen.hr = 0;
+                       };
+                       if (stopwatch_screen.csec % 10 == 0)
+                               update_stop_watch_screen(&stopwatch_screen);
+                       break;
+               default:
+                       break;
+       };
+}
+
+
+/*
+ * 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)
+{
+       switch (event) {
+               case EVENT_SCREEN_VISIBLE:
+                       draw_alarm_screen();
+                       hal_enable_halfsecond_timer();
+                       hal_vibration_set_state(TRUE);
+                       break;
+               case EVENT_SCREEN_DESTROY:
+                       hal_disable_halfsecond_timer();
+                       hal_lcd_set_backlight(FALSE);
+                       hal_vibration_set_state(FALSE);
+                       break;
+               case EVENT_USER_BUTTONS:
+                       dbg_out("button event %d\n", *(int *)data);
+                       // hal_lcd_set_backlight(FALSE);
+                       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");
+                       break;
+               default:
+                       break;
+       };
+}
+
+
+/*
+ * Bluetooth screen
+ */
+typedef struct {
+       u8t pos;
+       boolean bt_en;
+       boolean on;
+} bluetooth_data_t;
+static bluetooth_data_t bluetooth_screen = {
+       0,
+       FALSE,
+       TRUE
+};
+
+void draw_bluetooth_screen(bluetooth_data_t *sdata)
+{
+       char bstr[20];
+       uint8_t *bd_addr;
+
+       hal_lcd_clear_display();
+
+       oswald_draw_bitmap(36, 0, Bluetooth_icon_width, Bluetooth_icon_height, Bluetooth_icon_bits);
+
+       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:");
+       if ((sdata->pos == 0 && sdata->on) || sdata->pos != 0) {
+               WriteLcdCharacter(45, 30, bluetooth_screen.bt_en ? 'x' : '_');
+       }
+       WriteLcdString(2, 39, "State:");
+       switch (hal_bluetooth_get_state()) {
+               case BLUETOOTH_OFF:
+                       WriteLcdString(45, 39, "off");
+                       break;
+               case BLUETOOTH_ON:
+                       WriteLcdString(45, 39, "on");
+                       break;
+               case BLUETOOTH_CONNECTED:
+                       WriteLcdString(45, 39, "conn.");
+                       break;
+               default:
+                       break;
+       };
+       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);
+       } 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)
+{
+       switch (pos) {
+               case 0:
+                       if (hal_bluetooth_get_state() >= BLUETOOTH_ON) {
+                               hal_bluetooth_set_state(BLUETOOTH_OFF);
+                               bluetooth_screen.bt_en = FALSE;
+                       } else {
+                               hal_bluetooth_set_state(BLUETOOTH_ON);
+                               bluetooth_screen.bt_en = TRUE;
+                       }
+                       break;
+               case 1:
+                       if (hal_bluetooth_get_state() >= BLUETOOTH_ON && !hal_bluetooth_get_visible()) {
+                               hal_bluetooth_set_visible(TRUE);
+                       } else {
+                               hal_bluetooth_set_visible(FALSE);
+                       }
+                       break;
+               case 2:
+                       break;
+               case 3:
+                       break;
+               case 4:
+                       break;
+               case 5:
+                       break;
+               case 6:
+                       break;
+               case 7:
+                       break;
+               case 8:
+                       break;
+               default:
+                       break;
+       };
+}
+
+void 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;
+       }
+       draw_bluetooth_screen(sdata);
+}
+
+void bluetooth_screen_events(u16t event, void *data)
+{
+       switch (event) {
+               case EVENT_SCREEN_VISIBLE:
+                       bluetooth_screen.pos = 0;
+                       bluetooth_screen.bt_en = (hal_bluetooth_get_state() > 0);
+                       draw_bluetooth_screen(&bluetooth_screen);
+                       hal_enable_halfsecond_timer();
+                       break;
+               case EVENT_SCREEN_DESTROY:
+                       hal_disable_halfsecond_timer();
+                       break;
+               case EVENT_USER_BUTTONS:
+                       dbg_out("button event %d\n", *(int *)data);
+                       handle_bluetooth_buttons(*(watch_button *)data, &bluetooth_screen);
+                       break;
+               case EVENT_HALF_SEC_TIMER:
+                       if (bluetooth_screen.on)
+                               bluetooth_screen.on = FALSE;
+                       else
+                               bluetooth_screen.on = TRUE;
+                       draw_bluetooth_screen(&bluetooth_screen);
+                       break;
+               default:
+                       break;
+       };
+}
+