#include "oswald.h" #include "oswald_watch_faces.h" #include "oswald_screens.h" #include "oswald_hal.h" #include "embedvm.h" #include "mymem.h" #include "strutils.h" #include "oswald_main.h" /* * some variable defining our curent state * these are globals in order to avoid having to pass pointers * through function calls thus saving stack space */ clock_state OswaldClk; alarm_clk OswaldAlarm[MAX_ALARM]; watch_state OswaldState; watch_screen OswaldScreens[SCREENS_END]; power_state OswaldPowerState; uint8_t backlight_safety_off = 0; char MainMessage[148]; void oswald_change_to_screen(screen_number screen_id) { // we spare the update if no change happened if (OswaldState.screen_id != screen_id) { OswaldState.screen_id = screen_id; if ((OswaldState.screen->event_func != NULL) && (OswaldState.screen->event_mask & EVENT_SCREEN_VISIBLE)) OswaldState.screen->event_func(EVENT_SCREEN_VISIBLE, NULL); } } void oswald_set_time(uint8_t hour, uint8_t minute, uint8_t second, boolean clk24hr) { OswaldClk.hour = hour; OswaldClk.minute = minute; OswaldClk.second = second; OswaldClk.clk24hr = clk24hr; } void oswald_set_date(uint8_t day, uint8_t month, uint16_t year, boolean day_first) { OswaldClk.day = day; OswaldClk.month = month; OswaldClk.year = year; OswaldClk.day_first = day_first; } static void update_clock_state (void) { hal_get_rtc(&OswaldClk); /* check for pending alarm once per minute */ if (OswaldClk.second == 0) { int i; for(i=0;i<MAX_ALARM;i++) { if (OswaldClk.hour == OswaldAlarm[i].hour && OswaldClk.minute == OswaldAlarm[i].minute && ((1 << OswaldClk.wday) & OswaldAlarm[i].wday)) { OswaldState.screen->event_func(EVENT_SCREEN_DESTROY, NULL); OswaldState.screen_id = ALARM_SCREEN; OswaldState.screen = &OswaldScreens[OswaldState.screen_id]; OswaldState.screen->event_func(EVENT_SCREEN_VISIBLE, NULL); break; } } } } void oswald_one_second_tick(void) { /* update clock - should use RTC if available */ update_clock_state(); hal_get_power_state(&OswaldPowerState); if (backlight_safety_off) { backlight_safety_off--; if (!backlight_safety_off) hal_lcd_set_backlight(FALSE); } /* wake-up screen if interested in the one-second-event */ if (OswaldState.screen->event_func != NULL && (OswaldState.screen->event_mask & EVENT_ONE_SEC_TIMER)) OswaldState.screen->event_func(EVENT_ONE_SEC_TIMER, NULL); } 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) { switch (button) { case BUTTON_A: case BUTTON_B: case BUTTON_C: case BUTTON_F: if (OswaldState.screen->event_func != NULL && (OswaldState.screen->event_mask & EVENT_USER_BUTTONS)) { OswaldState.screen->event_func(EVENT_USER_BUTTONS, &button); } break; case BUTTON_E: if (OswaldState.screen->event_func != NULL && (OswaldState.screen->event_mask & EVENT_USER_BUTTONS)) { if (OswaldState.screen->event_func(EVENT_USER_BUTTONS, &button) == EVENT_RET_HANDLED) break; } OswaldState.screen->event_func(EVENT_SCREEN_DESTROY, NULL); #if 0 // next screen OswaldState.screen_id++; if (OswaldState.screen_id >= LAST_SCREEN) { OswaldState.screen_id = IDLE_SCREEN; }; #else OswaldState.screen_id = IDLE_SCREEN; #endif OswaldState.screen = &OswaldScreens[OswaldState.screen_id]; OswaldState.screen->event_func(EVENT_SCREEN_VISIBLE, NULL); break; case BUTTON_D: // backlight on/off if (hal_lcd_get_backlight()) { hal_lcd_set_backlight(FALSE); backlight_safety_off = 0; } else { hal_lcd_set_backlight(TRUE); backlight_safety_off = 2; } break; default: // should never get here break; }; } void oswald_handle_accel_event(uint8_t x, uint8_t y, uint8_t 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(uint8_t 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_handle_comm_input(uint16_t mlen, const void *mdat) { char *icmd = (char *) mdat; if (icmd[0] == '$') { if (strncmp(icmd, "$GRT", 4) == 0) { // get current RTC char rtime[12]; mymemcpy(rtime,"#RTC",4); num2str(OswaldClk.hour,rtime+4,2,2); num2str(OswaldClk.minute,rtime+6,2,2); num2str(OswaldClk.second,rtime+8,2,2); rtime[10]='\n'; rtime[11]='\0'; hal_bluetooth_send_data(rtime, strlen(rtime)); } else if (strncmp(icmd, "$SRT", 4) == 0) { // set current RTC char rtime[16]; mymemcpy(rtime,"#USP\n",6); hal_bluetooth_send_data(rtime, strlen(rtime)); } else if (strncmp(icmd, "$MSG", 4) == 0) { // message on main screen char *msg = (icmd+4); mlen -= 4; mymemset(MainMessage, 0, 148); if(mlen>147) mlen=147; mymemcpy(MainMessage,msg,mlen); MainMessage[mlen]='\0'; } else if (strncmp(icmd, "$MCL", 4) == 0) { // clear message mymemset(MainMessage, 0, 148); } else if (strncmp(icmd, "$BAT", 4) == 0) { // clear message char rtime[16]; int off; mymemcpy(rtime,"#BAT",4); off=4; off+=num2str(OswaldPowerState.charge_state,rtime+off,1,sizeof(rtime)-3-off); rtime[off++]=','; off+=num2str(OswaldPowerState.percent,rtime+off,1,sizeof(rtime)-2-off); rtime[off++]='\n'; rtime[off++]='\0'; hal_bluetooth_send_data(rtime, strlen(rtime)); } else if (strncmp(icmd, "$GAL", 4) == 0) { // get ambient light value char rtime[16],off; mymemcpy(rtime,"#GAL",4); off=4; off+=num2str(hal_amblight_get_val(),rtime+off,1,sizeof(rtime)-2-off); rtime[off++]='\n'; rtime[off++]='\0'; hal_bluetooth_send_data(rtime, strlen(rtime)); } } } void oswald_init(void) { int i; OswaldScreens[IDLE_SCREEN].event_mask = EVENT_USER_BUTTONS | EVENT_ONE_SEC_TIMER; OswaldScreens[IDLE_SCREEN].event_func = idle_handle_events; OswaldScreens[MAIN_MENU_SCREEN].event_mask = EVENT_USER_BUTTONS | EVENT_ONE_SEC_TIMER; OswaldScreens[MAIN_MENU_SCREEN].event_func = main_menu_handle_events; OswaldScreens[ALARM_SETUP_SCREEN].event_mask = EVENT_USER_BUTTONS | EVENT_HALF_SEC_TIMER; OswaldScreens[ALARM_SETUP_SCREEN].event_func = alarm_setup_events; OswaldScreens[STOP_WATCH_SCREEN].event_mask = EVENT_USER_BUTTONS | EVENT_CS_TIMER; OswaldScreens[STOP_WATCH_SCREEN].event_func = stop_watch_handle_events; OswaldScreens[BLUETOOTH_SCREEN].event_mask = EVENT_USER_BUTTONS | EVENT_HALF_SEC_TIMER; OswaldScreens[BLUETOOTH_SCREEN].event_func = bluetooth_screen_events; OswaldScreens[ACCEL_DISPLAY_SCREEN].event_mask = EVENT_USER_BUTTONS | EVENT_ACCEL_UPDATE; OswaldScreens[ACCEL_DISPLAY_SCREEN].event_func = accel_handle_events; OswaldScreens[MESSAGES_SCREEN].event_mask = EVENT_USER_BUTTONS; OswaldScreens[MESSAGES_SCREEN].event_func = messages_screen_handle_events; OswaldScreens[MESSAGE_SCREEN].event_mask = EVENT_USER_BUTTONS; OswaldScreens[MESSAGE_SCREEN].event_func = message_screen_handle_events; OswaldScreens[INFO_SCREEN].event_mask = 0x00; // this one does not consume any events OswaldScreens[INFO_SCREEN].event_func = info_screen_handle_events; OswaldScreens[DATETIME_SETTING_SCREEN].event_mask = EVENT_USER_BUTTONS | EVENT_HALF_SEC_TIMER; OswaldScreens[DATETIME_SETTING_SCREEN].event_func = datetime_setup_events; OswaldScreens[CALENDAR_OVERVIEW_SCREEN].event_mask = EVENT_USER_BUTTONS|EVENT_ONE_SEC_TIMER; OswaldScreens[CALENDAR_OVERVIEW_SCREEN].event_func = calendar_overview_handle_events; OswaldScreens[MENU_TEST_SCREEN].event_mask = EVENT_USER_BUTTONS; OswaldScreens[MENU_TEST_SCREEN].event_func = test_menu_handle_events; OswaldScreens[ALARM_SCREEN].event_mask = EVENT_USER_BUTTONS | EVENT_HALF_SEC_TIMER; OswaldScreens[ALARM_SCREEN].event_func = alarm_handle_events; OswaldState.screen_id = IDLE_SCREEN; OswaldState.screen = &OswaldScreens[OswaldState.screen_id]; if (OswaldState.screen->event_func != NULL) OswaldState.screen->event_func(EVENT_SCREEN_VISIBLE, NULL); for(i=0;i<MAX_ALARM;i++) { OswaldAlarm[i].hour = 12; OswaldAlarm[i].minute = 0; OswaldAlarm[i].wday = 0x00; } }