From: Nils Faerber Date: Sun, 12 Aug 2012 21:14:19 +0000 (+0200) Subject: Countless fixes and enhancements X-Git-Url: https://git.karo-electronics.de/?p=oswald.git;a=commitdiff_plain;h=e9b651b4a531d38826d7952475b5ad0d3d8118e9 Countless fixes and enhancements --- diff --git a/ui/LcdDisplay.c b/ui/LcdDisplay.c index 4f6bf99..87bae7f 100644 --- a/ui/LcdDisplay.c +++ b/ui/LcdDisplay.c @@ -109,7 +109,6 @@ void DrawLcdLineBresenhamWW(u8t xstart, u8t ystart, u8t xend, u8t yend, u8t thic } } - u8t WriteLcdCharacter(u8t x, u8t y, u8t Character) { u8t CharacterHeight = GetCharacterHeight(); @@ -150,3 +149,20 @@ void WriteLcdString(u8t x, u8t y, u8t *str) } } + +void WriteLcdNumber(u8t x, u8t y, s16t number) +{ + register lx, i, strl; + u8t str[8]; + + itoa(number, str, 10); + strl = oswald_strlen(str); + if (strl == 0) + return; + + lx = x; + for (i=0; iaccel_x = (u8t)val; + oswald_handle_accel_event(ui->accel_x, ui->accel_y, ui->accel_z); +} + +void accelY_value_changed (GtkRange *range, gpointer user_data) +{ + oswald_ui *ui = (oswald_ui *)user_data; + double val; + + val = gtk_range_get_value(range); + ui->accel_y = (u8t)val; + oswald_handle_accel_event(ui->accel_x, ui->accel_y, ui->accel_z); +} + +void accelZ_value_changed (GtkRange *range, gpointer user_data) +{ + oswald_ui *ui = (oswald_ui *)user_data; + double val; + + val = gtk_range_get_value(range); + ui->accel_z = (u8t)val; + oswald_handle_accel_event(ui->accel_x, ui->accel_y, ui->accel_z); +} + static void create_mainwin(oswald_ui *ui) { GtkWidget *mvb, *hb, *vb, *btn, *sc, *l; @@ -218,8 +257,10 @@ static void create_mainwin(oswald_ui *ui) gtk_box_pack_start (GTK_BOX(vb), btn, FALSE, FALSE, 10); g_signal_connect(G_OBJECT(btn), "clicked", G_CALLBACK(button_C_clicked), ui); + // ambient light sensor sc = gtk_vscale_new_with_range (0, 255, 1); gtk_box_pack_start (GTK_BOX(hb), sc, FALSE, FALSE, 5); + g_signal_connect(G_OBJECT(sc), "value-changed", G_CALLBACK(ambientlight_value_changed), ui); hb = gtk_hbox_new(FALSE, 0); gtk_box_pack_start (GTK_BOX(mvb), hb, FALSE, FALSE, 5); @@ -228,21 +269,24 @@ static void create_mainwin(oswald_ui *ui) gtk_box_pack_start (GTK_BOX(hb), l, FALSE, FALSE, 5); sc = gtk_hscale_new_with_range (0, 255, 1); gtk_box_pack_start (GTK_BOX(hb), sc, TRUE, TRUE, 5); + g_signal_connect(G_OBJECT(sc), "value-changed", G_CALLBACK(accelX_value_changed), ui); l = gtk_label_new("Y:"); gtk_box_pack_start (GTK_BOX(hb), l, FALSE, FALSE, 5); sc = gtk_hscale_new_with_range (0, 255, 1); gtk_box_pack_start (GTK_BOX(hb), sc, TRUE, TRUE, 5); + g_signal_connect(G_OBJECT(sc), "value-changed", G_CALLBACK(accelY_value_changed), ui); l = gtk_label_new("Z:"); gtk_box_pack_start (GTK_BOX(hb), l, FALSE, FALSE, 5); sc = gtk_hscale_new_with_range (0, 255, 1); gtk_box_pack_start (GTK_BOX(hb), sc, TRUE, TRUE, 5); + g_signal_connect(G_OBJECT(sc), "value-changed", G_CALLBACK(accelZ_value_changed), ui); gtk_widget_show_all(ui->mainwin); } -gboolean one_second_tmo_handler (gpointer userdata) +static gboolean one_second_tmo_handler (gpointer userdata) { oswald_ui *ui = (oswald_ui *)userdata; @@ -251,7 +295,7 @@ gboolean one_second_tmo_handler (gpointer userdata) return TRUE; } -gboolean app_idle_handler (gpointer user_data) +static gboolean app_idle_handler (gpointer user_data) { g_print("i"); if (OswaldState.pending_idle) { @@ -261,6 +305,52 @@ gboolean app_idle_handler (gpointer user_data) return FALSE; } +static gboolean centisecond_tmo_handler (gpointer userdata) +{ + oswald_ui *ui = (oswald_ui *)userdata; + + if (ui->centisecond_active) + oswald_centisecond_tick(); + else + return FALSE; + + return TRUE; +} + +void enable_centisecond_timer(void) +{ + ui_g->centisecond_active = TRUE; + g_timeout_add(10, centisecond_tmo_handler, ui_g); +} + +void disable_centisecond_timer(void) +{ + ui_g->centisecond_active = FALSE; +} + +static gboolean halfsecond_tmo_handler (gpointer userdata) +{ + oswald_ui *ui = (oswald_ui *)userdata; + + if (ui->halfsecond_active) + oswald_halfsecond_tick(); + else + return FALSE; + + return TRUE; +} + +void enable_halfsecond_timer(void) +{ + ui_g->halfsecond_active = TRUE; + g_timeout_add(500, halfsecond_tmo_handler, ui_g); +} + +void disable_halfsecond_timer(void) +{ + ui_g->halfsecond_active = FALSE; +} + int main(int argc , char ** argv) { oswald_ui ui; @@ -269,6 +359,12 @@ int main(int argc , char ** argv) ui_g = &ui; + ui.accel_x = 0; + ui.accel_y = 0; + ui.accel_z = 0; + ui.halfsecond_active = FALSE; + ui.centisecond_active = FALSE; + mt = time(NULL); localtime_r(&mt, &mtime); @@ -277,7 +373,8 @@ int main(int argc , char ** argv) create_mainwin(&ui); gtk_widget_realize(ui.mainwin); - oswald_set_time(mtime.tm_hour, mtime.tm_min, mtime.tm_sec); + oswald_set_time(mtime.tm_hour, mtime.tm_min, mtime.tm_sec, TRUE); + oswald_set_date(mtime.tm_mday, (mtime.tm_mon + 1), (mtime.tm_year + 1900), TRUE); oswald_init(); g_timeout_add_seconds(1, one_second_tmo_handler, &ui); diff --git a/ui/oswald-ui.h b/ui/oswald-ui.h index 43d3e8a..90353d0 100644 --- a/ui/oswald-ui.h +++ b/ui/oswald-ui.h @@ -9,10 +9,21 @@ typedef struct { GtkWidget *mainwin; GtkWidget *darea; GdkPixmap *pixmap; + u8t accel_x; + u8t accel_y; + u8t accel_z; + gboolean halfsecond_active; + gboolean centisecond_active; } oswald_ui; void lcd_set_pixel(gint x, gint y, gboolean state); void lcd_clear_display(void); +void enable_centisecond_timer(void); +void disable_centisecond_timer(void); + +void enable_halfsecond_timer(void); +void disable_halfsecond_timer(void); + #endif diff --git a/ui/oswald.h b/ui/oswald.h index 6e641eb..f92651d 100644 --- a/ui/oswald.h +++ b/ui/oswald.h @@ -31,18 +31,20 @@ typedef struct { u8t second; u8t day; u8t month; - u8t year; + u16t year; + boolean clk24hr; + boolean day_first; } clock_state; typedef enum { IDLE_SCREEN = 0, ACCEL_DISPLAY_SCREEN, - DATETIME_SETTING_SCREEN, MENU_TEST_SCREEN, // SCREEN2_SCREEN, // SCREEN3_SCREEN, // APPLICATION_SCREEN, LAST_SCREEN, // a marker for the last (not valid) screen) + DATETIME_SETTING_SCREEN, } screen_number; typedef enum { @@ -56,13 +58,14 @@ typedef enum { #define EVENT_SCREEN_VISIBLE (1<<0) // screen just became visible #define EVENT_SCREEN_DESTROY (1<<1) // screen is destroyed -#define EVENT_ONE_SEC_TIMER (1<<2) -#define EVENT_MS_TIMER (1<<3) -#define EVENT_USER_BUTTONS (1<<4) -#define EVENT_ACCEL_UPDATE (1<<5) -#define EVENT_AMBIENTLIGHT_UPDATE (1<<6) -#define EVENT_POWER_CHANGE (1<<7) -#define EVENT_COMMS (1<<8) +#define EVENT_ONE_SEC_TIMER (1<<2) // one second timer for reguler clock +#define EVENT_HALF_SEC_TIMER (1<<3) // half second timer for blinking displays +#define EVENT_CS_TIMER (1<<4) // centisecond timer, e.g. for stop watch +#define EVENT_USER_BUTTONS (1<<5) // button presses +#define EVENT_ACCEL_UPDATE (1<<6) // accelerometer updates +#define EVENT_AMBIENTLIGHT_UPDATE (1<<7) // ambient light sensor updates +#define EVENT_POWER_CHANGE (1<<8) // power source status change +#define EVENT_COMMS (1<<9) // communication, like Bluetooth I/O typedef struct { u16t event_mask; // the event the screen wants to receive @@ -76,5 +79,11 @@ typedef struct { boolean pending_idle; } watch_state; +typedef struct { + u8t x; + u8t y; + u8t z; +} accel_data_t; + #endif diff --git a/ui/oswald_main.c b/ui/oswald_main.c index 82b8567..df95ebb 100644 --- a/ui/oswald_main.c +++ b/ui/oswald_main.c @@ -27,11 +27,20 @@ void oswald_change_to_screen(screen_number screen_id) } } -void oswald_set_time(u8t hour, u8t minute, u8t second) +void oswald_set_time(u8t hour, u8t minute, u8t second, boolean clk24hr) { OswaldClk.hour = hour; OswaldClk.minute = minute; OswaldClk.second = second; + OswaldClk.clk24hr = clk24hr; +} + +void oswald_set_date(u8t day, u8t month, u16t year, boolean day_first) +{ + OswaldClk.day = day; + OswaldClk.month = month; + OswaldClk.year = year; + OswaldClk.day_first = day_first; } static void update_clock_state (void) @@ -63,7 +72,20 @@ void oswald_one_second_tick(void) if (OswaldState.screen->event_func != NULL && (OswaldState.screen->event_mask & EVENT_ONE_SEC_TIMER)) OswaldState.screen->event_func(EVENT_ONE_SEC_TIMER, NULL); - // oswald_update_screen(); +} + +void oswald_centisecond_tick(void) +{ + if (OswaldState.screen->event_func != NULL && + (OswaldState.screen->event_mask & EVENT_CS_TIMER)) + OswaldState.screen->event_func(EVENT_CS_TIMER, NULL); +} + +void oswald_halfsecond_tick(void) +{ + if (OswaldState.screen->event_func != NULL && + (OswaldState.screen->event_mask & EVENT_HALF_SEC_TIMER)) + OswaldState.screen->event_func(EVENT_HALF_SEC_TIMER, NULL); } void oswald_handle_button_press(watch_button button) @@ -78,6 +100,7 @@ void oswald_handle_button_press(watch_button button) OswaldState.screen->event_func(EVENT_USER_BUTTONS, &button); break; case BUTTON_C: + OswaldState.screen->event_func(EVENT_SCREEN_DESTROY, NULL); // next screen OswaldState.screen_id++; if (OswaldState.screen_id >= LAST_SCREEN) { @@ -96,16 +119,35 @@ void oswald_handle_button_press(watch_button button) }; } +void oswald_handle_accel_event(u8t x, u8t y, u8t z) +{ + accel_data_t accel_data; + + accel_data.x = x; + accel_data.y = y; + accel_data.z = z; + + if (OswaldState.screen->event_func != NULL && + (OswaldState.screen->event_mask & EVENT_ACCEL_UPDATE)) + OswaldState.screen->event_func(EVENT_ACCEL_UPDATE, &accel_data); +} + +void oswald_handle_ambientlight_event(u8t light_level) +{ + if (OswaldState.screen->event_func != NULL && + (OswaldState.screen->event_mask & EVENT_AMBIENTLIGHT_UPDATE)) + OswaldState.screen->event_func(EVENT_AMBIENTLIGHT_UPDATE, &light_level); +} + void oswald_init(void) { OswaldScreens[IDLE_SCREEN].event_mask = EVENT_USER_BUTTONS | EVENT_ONE_SEC_TIMER; OswaldScreens[IDLE_SCREEN].event_func = idle_handle_events; - OswaldScreens[ACCEL_DISPLAY_SCREEN].event_mask = EVENT_USER_BUTTONS; + OswaldScreens[ACCEL_DISPLAY_SCREEN].event_mask = EVENT_USER_BUTTONS | EVENT_ACCEL_UPDATE; OswaldScreens[ACCEL_DISPLAY_SCREEN].event_func = accel_handle_events; - - OswaldScreens[DATETIME_SETTING_SCREEN].event_mask = EVENT_USER_BUTTONS | EVENT_ONE_SEC_TIMER; + OswaldScreens[DATETIME_SETTING_SCREEN].event_mask = EVENT_USER_BUTTONS | EVENT_HALF_SEC_TIMER; OswaldScreens[DATETIME_SETTING_SCREEN].event_func = datetime_setup_events; OswaldScreens[MENU_TEST_SCREEN].event_mask = EVENT_USER_BUTTONS; diff --git a/ui/oswald_main.h b/ui/oswald_main.h index 679c03f..28c5691 100644 --- a/ui/oswald_main.h +++ b/ui/oswald_main.h @@ -11,12 +11,16 @@ extern watch_screen OswaldScreens[]; void oswald_one_second_tick(); /* sets internal 'RTC' time */ -void oswald_set_time(u8t hour, u8t minute, u8t second); +void oswald_set_time(u8t hour, u8t minute, u8t second, boolean clk24hr); +void oswald_set_date(u8t day, u8t month, u16t year, boolean day_first); void oswald_handle_button_press(watch_button button); void oswald_handle_accel_event(u8t x, u8t y, u8t z); void oswald_handle_ambientlight_event(u8t light_level); void oswald_handle_idle_event(void); +void oswald_one_second_tick(void); +void oswald_halfsecond_tick(void); +void oswald_centisecond_tick(void); void oswald_init(void); #endif diff --git a/ui/oswald_screens.c b/ui/oswald_screens.c index 7790b70..171d7b6 100644 --- a/ui/oswald_screens.c +++ b/ui/oswald_screens.c @@ -1,12 +1,14 @@ #include "oswald.h" +#include "oswald_main.h" #include "oswald_watch_faces.h" #include "Fonts.h" #include "LcdDisplay.h" #include "oswald_screens.h" + typedef struct { - void (*screendraw_func)(boolean shoq_seconds); + void (*screendraw_func)(boolean show_seconds); boolean show_seconds; boolean analogue; } idle_data_t; @@ -19,13 +21,13 @@ static idle_data_t idle_screen = { void idle_handle_user_buttons(watch_button button) { switch (button) { - case BUTTON_D: + case BUTTON_A: if (idle_screen.show_seconds) idle_screen.show_seconds = FALSE; else idle_screen.show_seconds = TRUE; break; - case BUTTON_E: + case BUTTON_B: if (idle_screen.analogue == TRUE) { idle_screen.analogue = FALSE; idle_screen.screendraw_func = DrawLcdDigitalClock; @@ -34,6 +36,12 @@ void idle_handle_user_buttons(watch_button button) idle_screen.screendraw_func = DrawLcdAnaClock; }; break; + case BUTTON_D: + OswaldState.screen_id = DATETIME_SETTING_SCREEN; + OswaldState.screen = &OswaldScreens[OswaldState.screen_id]; + OswaldState.screen->event_func(EVENT_SCREEN_VISIBLE, NULL); + return; + break; default: break; }; @@ -57,23 +65,38 @@ void idle_handle_events(u16t event, void *data) } -void draw_accel_screen(void) +typedef struct { + accel_data_t accdata; +} accelscreen_data_t; +static accelscreen_data_t accel_screen = { + { 0, 0, 0}, +}; + +void draw_accel_screen(accel_data_t *accel_data) { lcd_clear_display(); SetFont(MetaWatch16); WriteLcdString(2, 2, "X:"); - WriteLcdString(20, 2, "123"); - WriteLcdString(2, 18, "Z:"); - WriteLcdString(20, 18, "123"); - WriteLcdString(2, 34, "Y:"); - WriteLcdString(20, 34, "123"); + 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); } void accel_handle_events(u16t event, void *data) { switch (event) { case EVENT_SCREEN_VISIBLE: - draw_accel_screen(); + draw_accel_screen(&accel_screen.accdata); + break; + case EVENT_ACCEL_UPDATE: { + accel_data_t *accel_data = (accel_data_t *)data; + accel_screen.accdata.x = accel_data->x; + accel_screen.accdata.y = accel_data->y; + accel_screen.accdata.z = accel_data->z; + draw_accel_screen(&accel_screen.accdata); + }; break; case EVENT_USER_BUTTONS: dbg_out("button event %d\n", *(int *)data); @@ -84,24 +107,172 @@ void accel_handle_events(u16t event, void *data) } -void draw_datetime_setup_screen(void) +typedef struct { + u8t pos; + boolean on; +} datetime_setup_data_t; +static datetime_setup_data_t dt_setup_screen = { + 0, + TRUE +}; + +void draw_datetime_setup_screen(datetime_setup_data_t *sdata) { lcd_clear_display(); SetFont(MetaWatch16); - WriteLcdString(2, 2, "Date / Time"); - WriteLcdString(2, 18, "Setting"); - WriteLcdString(2, 34, "22:39"); - WriteLcdString(2, 50, "07.08.2012"); + WriteLcdString(2, 2, "Set"); + + SetFont(MetaWatchTime); + if ((sdata->pos == 0 && sdata->on) || sdata->pos != 0) { + WriteLcdCharacter(2, 20, (OswaldClk.hour / 10)); + WriteLcdCharacter(14, 20, (OswaldClk.hour % 10)); + } + WriteLcdCharacter(26, 20, 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(55, 20, TIME_CHARACTER_COLON_INDEX); + + if ((sdata->pos == 2 && sdata->on) || sdata->pos != 2) { + WriteLcdCharacter(60, 20, (OswaldClk.second / 10)); + WriteLcdCharacter(72, 20, (OswaldClk.second % 10)); + } + + SetFont(MetaWatch16); + if ((sdata->pos == 3 && sdata->on) || sdata->pos != 3) { + WriteLcdNumber(2, 45, OswaldClk.day); + } + WriteLcdString(18, 45, "."); + if ((sdata->pos == 4 && sdata->on) || sdata->pos != 4) { + WriteLcdNumber(22, 45, OswaldClk.month); + } + WriteLcdString(38, 45, "."); + if ((sdata->pos == 5 && sdata->on) || sdata->pos != 5) { + WriteLcdNumber(42, 45, OswaldClk.year); + } + + SetFont(MetaWatch7); + if ((sdata->pos == 6 && sdata->on) || sdata->pos != 6) { + if (OswaldClk.clk24hr) + WriteLcdString(2, 66, "x"); + else + WriteLcdString(2, 66, "_"); + } + WriteLcdString(15, 66, "24hr"); + + if ((sdata->pos == 7 && sdata->on) || sdata->pos != 7) { + if (OswaldClk.day_first) + WriteLcdString(2, 79, "x"); + else + WriteLcdString(2, 79, "_"); + } + WriteLcdString(15, 79, "dd.mm. mm/dd"); +} + +void datetime_handle_updown(u8t pos, s8t incr) +{ + switch (pos) { + case 0: // hour + if (OswaldClk.hour == 0 && incr == -1) { + OswaldClk.hour = 23; + break; + }; + OswaldClk.hour += incr; + if (OswaldClk.hour > 23) + OswaldClk.hour = 0; + break; + case 1: // minute + if (OswaldClk.minute == 0 && incr == -1) { + OswaldClk.minute = 59; + break; + }; + OswaldClk.minute += incr; + if (OswaldClk.minute > 59) + OswaldClk.minute = 0; + break; + case 2: // second + OswaldClk.second = 0; + break; + case 3: // day + if (OswaldClk.day == 1 && incr == -1) { + OswaldClk.day = 31; + break; + }; + OswaldClk.day += incr; + if (OswaldClk.day > 31) + OswaldClk.day = 1; + break; + case 4: // month + if (OswaldClk.month == 1 && incr == -1) { + OswaldClk.month = 12; + break; + }; + OswaldClk.month += incr; + if (OswaldClk.month > 12) + OswaldClk.month = 1; + break; + case 5: // year + OswaldClk.year += incr; + break; + case 6: // 24hr / 12hr + if (OswaldClk.clk24hr) + OswaldClk.clk24hr = FALSE; + else + OswaldClk.clk24hr = TRUE; + break; + case 7: // dd.mm. / mm/dd + if (OswaldClk.day_first) + OswaldClk.day_first = FALSE; + else + OswaldClk.day_first = TRUE; + break; + default: + break; + }; +} + +void handle_setup_datetime_buttons(watch_button button, datetime_setup_data_t *sdata) +{ + switch (button) { + case BUTTON_A: + datetime_handle_updown(sdata->pos, 1); + break; + case BUTTON_B: + datetime_handle_updown(sdata->pos, -1); + break; + case BUTTON_D: + sdata->pos++; + sdata->pos %= 8; + break; + default: + break; + } + draw_datetime_setup_screen(sdata); } void datetime_setup_events(u16t event, void *data) { switch (event) { case EVENT_SCREEN_VISIBLE: - draw_datetime_setup_screen(); + draw_datetime_setup_screen(&dt_setup_screen); + enable_halfsecond_timer(); + break; + case EVENT_SCREEN_DESTROY: + disable_halfsecond_timer(); break; case EVENT_USER_BUTTONS: dbg_out("button event %d\n", *(int *)data); + handle_setup_datetime_buttons(*(watch_button *)data, &dt_setup_screen); + break; + case EVENT_HALF_SEC_TIMER: + if (dt_setup_screen.on) + dt_setup_screen.on = FALSE; + else + dt_setup_screen.on = TRUE; + draw_datetime_setup_screen(&dt_setup_screen); break; default: break; diff --git a/ui/oswald_strings.c b/ui/oswald_strings.c index e04da9b..1c621bc 100644 --- a/ui/oswald_strings.c +++ b/ui/oswald_strings.c @@ -14,3 +14,35 @@ u16t oswald_strlen(u8t *string) return i; } +char* itoa(s16t value, char* result, int base) +{ + char* ptr = result, *ptr1 = result, tmp_char; + s16t tmp_value; + + if (result == NULL) + return NULL; + + // check that the base if valid + if (base < 2 || base > 36) { + *result = '\0'; + return result; + } + + do { + tmp_value = value; + value /= base; + *ptr++ = "zyxwvutsrqponmlkjihgfedcba9876543210123456789abcdefghijklmnopqrstuvwxyz" [35 + (tmp_value - value * base)]; + } while ( value ); + + // Apply negative sign + if (tmp_value < 0) + *ptr++ = '-'; + *ptr-- = '\0'; + while (ptr1 < ptr) { + tmp_char = *ptr; + *ptr--= *ptr1; + *ptr1++ = tmp_char; + } + return result; +} + diff --git a/ui/oswald_strings.h b/ui/oswald_strings.h index 962cbd0..55881db 100644 --- a/ui/oswald_strings.h +++ b/ui/oswald_strings.h @@ -2,6 +2,7 @@ #define _OSWALD_STRINGS_H u16t oswald_strlen(u8t *string); +char* itoa(s16t value, char* result, int base); #endif