oswald/ui/oswald_main.c
2021-02-14 18:03:13 +01:00

248 lines
7.8 KiB
C

#include "oswald.h"
#include "oswald_watch_faces.h"
#include "oswald_screens.h"
#include "oswald_hal.h"
#include "embedvm.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;
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) {
if (OswaldClk.hour == OswaldAlarm.hour &&
OswaldClk.minute == OswaldAlarm.minute &&
((1 << OswaldClk.wday) & OswaldAlarm.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);
}
}
}
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_E:
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_C:
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[16];
snprintf(rtime, 16, "#RTC%02d%02d%02d\n", OswaldClk.hour, OswaldClk.minute, OswaldClk.second);
hal_bluetooth_send_data(rtime, strlen(rtime));
} else if (strncmp(icmd, "$SRT", 4) == 0) { // set current RTC
char rtime[16];
snprintf(rtime, 16, "#USP\n");
hal_bluetooth_send_data(rtime, strlen(rtime));
} else if (strncmp(icmd, "$MSG", 4) == 0) { // message on main screen
char *msg = (icmd+4);
mlen -= 4;
memset(MainMessage, 0, 148);
strncpy(MainMessage, msg, (mlen > 147) ? 147 : mlen);
} else if (strncmp(icmd, "$MCL", 4) == 0) { // clear message
memset(MainMessage, 0, 148);
} else if (strncmp(icmd, "$BAT", 4) == 0) { // clear message
char rtime[16];
snprintf(rtime, 16, "#BAT%d,%d\n", OswaldPowerState.charge_state, OswaldPowerState.percent);
hal_bluetooth_send_data(rtime, strlen(rtime));
} else if (strncmp(icmd, "$GAL", 4) == 0) { // get ambient light value
char rtime[16];
snprintf(rtime, 16, "#GAL%d\n", hal_amblight_get_val());
hal_bluetooth_send_data(rtime, strlen(rtime));
}
}
}
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[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[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);
OswaldAlarm.hour = 12;
OswaldAlarm.minute = 0;
OswaldAlarm.wday = 0x00;
}