]> git.karo-electronics.de Git - oswald.git/blob - ui/oswald_main.c
Some minor improvements.
[oswald.git] / ui / oswald_main.c
1 #include "oswald.h"
2 #include "oswald_watch_faces.h"
3 #include "oswald_screens.h"
4 #include "oswald_hal.h"
5
6 #include "embedvm.h"
7
8 #include "oswald_main.h"
9
10 /*
11  * some variable defining our curent state
12  * these are globals in order to avoid having to pass pointers
13  * through function calls thus saving stack space
14  */
15 clock_state OswaldClk;
16 alarm_clk OswaldAlarm;
17 watch_state OswaldState;
18 watch_screen OswaldScreens[SCREENS_END];
19 power_state OswaldPowerState;
20 uint8_t backlight_safety_off = 0;
21 char MainMessage[148];
22
23
24 void oswald_change_to_screen(screen_number screen_id)
25 {
26         // we spare the update if no change happened
27         if (OswaldState.screen_id != screen_id) {
28                 OswaldState.screen_id = screen_id;
29                 if ((OswaldState.screen->event_func != NULL) &&
30                     (OswaldState.screen->event_mask & EVENT_SCREEN_VISIBLE))
31                                 OswaldState.screen->event_func(EVENT_SCREEN_VISIBLE, NULL);
32         }
33 }
34
35 void oswald_set_time(uint8_t hour, uint8_t minute, uint8_t second, boolean clk24hr)
36 {
37         OswaldClk.hour = hour;
38         OswaldClk.minute = minute;
39         OswaldClk.second = second;
40         OswaldClk.clk24hr = clk24hr;
41 }
42
43 void oswald_set_date(uint8_t day, uint8_t month, uint16_t year, boolean day_first)
44 {
45         OswaldClk.day = day;
46         OswaldClk.month = month;
47         OswaldClk.year = year;
48         OswaldClk.day_first = day_first;
49 }
50
51 static void update_clock_state (void)
52 {
53         hal_get_rtc(&OswaldClk);
54
55         /* check for pending alarm once per minute */
56         if (OswaldClk.second == 0) {
57                 if (OswaldClk.hour == OswaldAlarm.hour &&
58                         OswaldClk.minute == OswaldAlarm.minute &&
59                         ((1 << OswaldClk.wday) & OswaldAlarm.wday)) {
60                         OswaldState.screen->event_func(EVENT_SCREEN_DESTROY, NULL);
61                         OswaldState.screen_id = ALARM_SCREEN;
62                         OswaldState.screen = &OswaldScreens[OswaldState.screen_id];
63                         OswaldState.screen->event_func(EVENT_SCREEN_VISIBLE, NULL);
64                 }
65         }
66 }
67
68 void oswald_one_second_tick(void)
69 {
70         /* update clock - should use RTC if available */
71         update_clock_state();
72
73         hal_get_power_state(&OswaldPowerState);
74         if (backlight_safety_off) {
75                 backlight_safety_off--;
76                 if (!backlight_safety_off)
77                         hal_lcd_set_backlight(FALSE);
78         }
79
80         /* wake-up screen if interested in the one-second-event */
81         if (OswaldState.screen->event_func != NULL &&
82             (OswaldState.screen->event_mask & EVENT_ONE_SEC_TIMER))
83                 OswaldState.screen->event_func(EVENT_ONE_SEC_TIMER, NULL);
84 }
85
86 void oswald_centisecond_tick(void)
87 {
88         if (OswaldState.screen->event_func != NULL &&
89             (OswaldState.screen->event_mask & EVENT_CS_TIMER))
90                 OswaldState.screen->event_func(EVENT_CS_TIMER, NULL);
91 }
92
93 void oswald_halfsecond_tick(void)
94 {
95         if (OswaldState.screen->event_func != NULL &&
96             (OswaldState.screen->event_mask & EVENT_HALF_SEC_TIMER))
97                 OswaldState.screen->event_func(EVENT_HALF_SEC_TIMER, NULL);
98 }
99
100 void oswald_handle_button_press(watch_button button)
101 {
102         switch (button) {
103                 case BUTTON_A:
104                 case BUTTON_B:
105                 case BUTTON_E:
106                 case BUTTON_F:
107                         if (OswaldState.screen->event_func != NULL &&
108                             (OswaldState.screen->event_mask & EVENT_USER_BUTTONS)) {
109                                 OswaldState.screen->event_func(EVENT_USER_BUTTONS, &button);
110                         }
111                         break;
112                 case BUTTON_C:
113                         if (OswaldState.screen->event_func != NULL &&
114                             (OswaldState.screen->event_mask & EVENT_USER_BUTTONS)) {
115                                 if (OswaldState.screen->event_func(EVENT_USER_BUTTONS, &button) == EVENT_RET_HANDLED)
116                                         break;
117                         }
118                         OswaldState.screen->event_func(EVENT_SCREEN_DESTROY, NULL);
119 #if 0
120                         // next screen
121                         OswaldState.screen_id++;
122                         if (OswaldState.screen_id >= LAST_SCREEN) {
123                                 OswaldState.screen_id = IDLE_SCREEN;
124                         };
125 #else
126                         OswaldState.screen_id = IDLE_SCREEN;
127 #endif
128                         OswaldState.screen = &OswaldScreens[OswaldState.screen_id];
129                         OswaldState.screen->event_func(EVENT_SCREEN_VISIBLE, NULL);
130                         break;
131                 case BUTTON_D:
132                         // backlight on/off
133                         if (hal_lcd_get_backlight()) {
134                                 hal_lcd_set_backlight(FALSE);
135                                 backlight_safety_off = 0;
136                         } else {
137                                 hal_lcd_set_backlight(TRUE);
138                                 backlight_safety_off = 2;
139                         }
140                         break;
141                 default:
142                         // should never get here
143                         break;
144         };
145 }
146
147 void oswald_handle_accel_event(uint8_t x, uint8_t y, uint8_t z)
148 {
149         accel_data_t accel_data;
150
151         accel_data.x = x;
152         accel_data.y = y;
153         accel_data.z = z;
154
155         if (OswaldState.screen->event_func != NULL &&
156             (OswaldState.screen->event_mask & EVENT_ACCEL_UPDATE))
157                 OswaldState.screen->event_func(EVENT_ACCEL_UPDATE, &accel_data);
158 }
159
160 void oswald_handle_ambientlight_event(uint8_t light_level)
161 {
162         if (OswaldState.screen->event_func != NULL &&
163             (OswaldState.screen->event_mask & EVENT_AMBIENTLIGHT_UPDATE))
164                 OswaldState.screen->event_func(EVENT_AMBIENTLIGHT_UPDATE, &light_level);
165 }
166
167 void oswald_handle_comm_input(uint16_t mlen, const void *mdat)
168 {
169         char *icmd = (char *) mdat;
170
171         if (icmd[0] == '$') {
172                 if (strncmp(icmd, "$GRT", 4) == 0) { // get current RTC
173                         char rtime[16];
174                         snprintf(rtime, 16, "#RTC%02d%02d%02d\n", OswaldClk.hour, OswaldClk.minute, OswaldClk.second);
175                         hal_bluetooth_send_data(rtime, strlen(rtime));
176                 } else if (strncmp(icmd, "$SRT", 4) == 0) { // set current RTC
177                         char rtime[16];
178                         snprintf(rtime, 16, "#USP\n");
179                         hal_bluetooth_send_data(rtime, strlen(rtime));
180                 } else if (strncmp(icmd, "$MSG", 4) == 0) { // message on main screen
181                         char *msg = (icmd+4);
182                         mlen -= 4;
183                         memset(MainMessage, 0, 148);
184                         strncpy(MainMessage, msg, (mlen > 147) ? 147 : mlen);
185                 } else if (strncmp(icmd, "$MCL", 4) == 0) { // clear message
186                         memset(MainMessage, 0, 148);
187                 } else if (strncmp(icmd, "$BAT", 4) == 0) { // clear message
188                         char rtime[16];
189                         snprintf(rtime, 16, "#BAT%d,%d\n", OswaldPowerState.charge_state, OswaldPowerState.percent);
190                         hal_bluetooth_send_data(rtime, strlen(rtime));
191                 } else if (strncmp(icmd, "$GAL", 4) == 0) { // get ambient light value
192                         char rtime[16];
193                         snprintf(rtime, 16, "#GAL%d\n", hal_amblight_get_val());
194                         hal_bluetooth_send_data(rtime, strlen(rtime));
195                 }
196         }
197 }
198
199 void oswald_init(void)
200 {
201         OswaldScreens[IDLE_SCREEN].event_mask = EVENT_USER_BUTTONS | EVENT_ONE_SEC_TIMER;
202         OswaldScreens[IDLE_SCREEN].event_func = idle_handle_events;
203
204         OswaldScreens[MAIN_MENU_SCREEN].event_mask = EVENT_USER_BUTTONS | EVENT_ONE_SEC_TIMER;
205         OswaldScreens[MAIN_MENU_SCREEN].event_func = main_menu_handle_events;
206
207         OswaldScreens[ALARM_SETUP_SCREEN].event_mask = EVENT_USER_BUTTONS | EVENT_HALF_SEC_TIMER;
208         OswaldScreens[ALARM_SETUP_SCREEN].event_func = alarm_setup_events;
209
210         OswaldScreens[STOP_WATCH_SCREEN].event_mask = EVENT_USER_BUTTONS | EVENT_CS_TIMER;
211         OswaldScreens[STOP_WATCH_SCREEN].event_func = stop_watch_handle_events;
212
213         OswaldScreens[BLUETOOTH_SCREEN].event_mask = EVENT_USER_BUTTONS | EVENT_HALF_SEC_TIMER;
214         OswaldScreens[BLUETOOTH_SCREEN].event_func = bluetooth_screen_events;
215
216         OswaldScreens[ACCEL_DISPLAY_SCREEN].event_mask = EVENT_USER_BUTTONS | EVENT_ACCEL_UPDATE;
217         OswaldScreens[ACCEL_DISPLAY_SCREEN].event_func = accel_handle_events;
218
219         OswaldScreens[MESSAGES_SCREEN].event_mask = EVENT_USER_BUTTONS;
220         OswaldScreens[MESSAGES_SCREEN].event_func = messages_screen_handle_events;
221
222         OswaldScreens[MESSAGE_SCREEN].event_mask = EVENT_USER_BUTTONS;
223         OswaldScreens[MESSAGE_SCREEN].event_func = message_screen_handle_events;
224
225         OswaldScreens[INFO_SCREEN].event_mask = 0x00; // this one does not consume any events
226         OswaldScreens[INFO_SCREEN].event_func = info_screen_handle_events;
227
228         OswaldScreens[DATETIME_SETTING_SCREEN].event_mask = EVENT_USER_BUTTONS | EVENT_HALF_SEC_TIMER;
229         OswaldScreens[DATETIME_SETTING_SCREEN].event_func = datetime_setup_events;
230
231         OswaldScreens[MENU_TEST_SCREEN].event_mask = EVENT_USER_BUTTONS;
232         OswaldScreens[MENU_TEST_SCREEN].event_func = test_menu_handle_events;
233
234         OswaldScreens[ALARM_SCREEN].event_mask = EVENT_USER_BUTTONS | EVENT_HALF_SEC_TIMER;
235         OswaldScreens[ALARM_SCREEN].event_func = alarm_handle_events;
236
237         OswaldState.screen_id = IDLE_SCREEN;
238         OswaldState.screen = &OswaldScreens[OswaldState.screen_id];
239
240         if (OswaldState.screen->event_func != NULL)
241                 OswaldState.screen->event_func(EVENT_SCREEN_VISIBLE, NULL);
242
243         OswaldAlarm.hour = 12;
244         OswaldAlarm.minute = 0;
245         OswaldAlarm.wday = 0x00;
246
247 }
248