Browse code

Countless fixes and enhancements

Nils Faerber authored on 12/08/2012 21:14:19
Showing 9 changed files
... ...
@@ -109,7 +109,6 @@ void DrawLcdLineBresenhamWW(u8t xstart, u8t ystart, u8t xend, u8t yend, u8t thic
109 109
 	}
110 110
 }
111 111
 
112
-
113 112
 u8t WriteLcdCharacter(u8t x, u8t y, u8t Character)
114 113
 {
115 114
 	u8t CharacterHeight = GetCharacterHeight();
... ...
@@ -150,3 +149,20 @@ void WriteLcdString(u8t x, u8t y, u8t *str)
150 149
 	}
151 150
 }
152 151
 
152
+
153
+void WriteLcdNumber(u8t x, u8t y, s16t number)
154
+{
155
+	register lx, i, strl;
156
+	u8t str[8];
157
+
158
+	itoa(number, str, 10);
159
+	strl = oswald_strlen(str);
160
+	if (strl == 0)
161
+		return;
162
+
163
+	lx = x;
164
+	for (i=0; i<strl; i++) {
165
+		lx += WriteLcdCharacter(lx, y, str[i]);
166
+	}
167
+}
168
+
... ...
@@ -155,6 +155,45 @@ gboolean button_F_pr (GtkWidget *widget, GdkEvent *event, gpointer user_data)
155 155
 	return FALSE;
156 156
 }
157 157
 
158
+void ambientlight_value_changed (GtkRange *range, gpointer  user_data)
159
+{
160
+	oswald_ui *ui = (oswald_ui *)user_data;
161
+	double val;
162
+
163
+	val = gtk_range_get_value(range);
164
+	oswald_handle_ambientlight_event((u8t) val);
165
+}
166
+
167
+void accelX_value_changed (GtkRange *range, gpointer  user_data)
168
+{
169
+	oswald_ui *ui = (oswald_ui *)user_data;
170
+	double val;
171
+
172
+	val = gtk_range_get_value(range);
173
+	ui->accel_x = (u8t)val;
174
+	oswald_handle_accel_event(ui->accel_x, ui->accel_y, ui->accel_z);
175
+}
176
+
177
+void accelY_value_changed (GtkRange *range, gpointer  user_data)
178
+{
179
+	oswald_ui *ui = (oswald_ui *)user_data;
180
+	double val;
181
+
182
+	val = gtk_range_get_value(range);
183
+	ui->accel_y = (u8t)val;
184
+	oswald_handle_accel_event(ui->accel_x, ui->accel_y, ui->accel_z);
185
+}
186
+
187
+void accelZ_value_changed (GtkRange *range, gpointer  user_data)
188
+{
189
+	oswald_ui *ui = (oswald_ui *)user_data;
190
+	double val;
191
+
192
+	val = gtk_range_get_value(range);
193
+	ui->accel_z = (u8t)val;
194
+	oswald_handle_accel_event(ui->accel_x, ui->accel_y, ui->accel_z);
195
+}
196
+
158 197
 static void create_mainwin(oswald_ui *ui)
159 198
 {
160 199
 	GtkWidget *mvb, *hb, *vb, *btn, *sc, *l;
... ...
@@ -218,8 +257,10 @@ static void create_mainwin(oswald_ui *ui)
218 257
 	gtk_box_pack_start (GTK_BOX(vb), btn, FALSE, FALSE, 10);
219 258
 	g_signal_connect(G_OBJECT(btn), "clicked", G_CALLBACK(button_C_clicked), ui);
220 259
 
260
+	// ambient light sensor
221 261
 	sc = gtk_vscale_new_with_range (0, 255, 1);
222 262
 	gtk_box_pack_start (GTK_BOX(hb), sc, FALSE, FALSE, 5);
263
+	g_signal_connect(G_OBJECT(sc), "value-changed", G_CALLBACK(ambientlight_value_changed), ui);
223 264
 
224 265
 	hb = gtk_hbox_new(FALSE, 0);
225 266
 	gtk_box_pack_start (GTK_BOX(mvb), hb, FALSE, FALSE, 5);
... ...
@@ -228,21 +269,24 @@ static void create_mainwin(oswald_ui *ui)
228 269
 	gtk_box_pack_start (GTK_BOX(hb), l, FALSE, FALSE, 5);
229 270
 	sc = gtk_hscale_new_with_range (0, 255, 1);
230 271
 	gtk_box_pack_start (GTK_BOX(hb), sc, TRUE, TRUE, 5);
272
+	g_signal_connect(G_OBJECT(sc), "value-changed", G_CALLBACK(accelX_value_changed), ui);
231 273
 
232 274
 	l = gtk_label_new("Y:");
233 275
 	gtk_box_pack_start (GTK_BOX(hb), l, FALSE, FALSE, 5);
234 276
 	sc = gtk_hscale_new_with_range (0, 255, 1);
235 277
 	gtk_box_pack_start (GTK_BOX(hb), sc, TRUE, TRUE, 5);
278
+	g_signal_connect(G_OBJECT(sc), "value-changed", G_CALLBACK(accelY_value_changed), ui);
236 279
 
237 280
 	l = gtk_label_new("Z:");
238 281
 	gtk_box_pack_start (GTK_BOX(hb), l, FALSE, FALSE, 5);
239 282
 	sc = gtk_hscale_new_with_range (0, 255, 1);
240 283
 	gtk_box_pack_start (GTK_BOX(hb), sc, TRUE, TRUE, 5);
284
+	g_signal_connect(G_OBJECT(sc), "value-changed", G_CALLBACK(accelZ_value_changed), ui);
241 285
 
242 286
 	gtk_widget_show_all(ui->mainwin);
243 287
 }
244 288
 
245
-gboolean one_second_tmo_handler (gpointer userdata)
289
+static gboolean one_second_tmo_handler (gpointer userdata)
246 290
 {
247 291
 	oswald_ui *ui = (oswald_ui *)userdata;
248 292
 
... ...
@@ -251,7 +295,7 @@ gboolean one_second_tmo_handler (gpointer userdata)
251 295
 	return TRUE;
252 296
 }
253 297
 
254
-gboolean app_idle_handler (gpointer user_data)
298
+static gboolean app_idle_handler (gpointer user_data)
255 299
 {
256 300
 	g_print("i");
257 301
 	if (OswaldState.pending_idle) {
... ...
@@ -261,6 +305,52 @@ gboolean app_idle_handler (gpointer user_data)
261 305
 	return FALSE;
262 306
 }
263 307
 
308
+static gboolean centisecond_tmo_handler (gpointer userdata)
309
+{
310
+	oswald_ui *ui = (oswald_ui *)userdata;
311
+
312
+	if (ui->centisecond_active)
313
+		oswald_centisecond_tick();
314
+	else
315
+		return FALSE;
316
+
317
+	return TRUE;
318
+}
319
+
320
+void enable_centisecond_timer(void)
321
+{
322
+	ui_g->centisecond_active = TRUE;
323
+	g_timeout_add(10, centisecond_tmo_handler, ui_g);
324
+}
325
+
326
+void disable_centisecond_timer(void)
327
+{
328
+	ui_g->centisecond_active = FALSE;
329
+}
330
+
331
+static gboolean halfsecond_tmo_handler (gpointer userdata)
332
+{
333
+	oswald_ui *ui = (oswald_ui *)userdata;
334
+
335
+	if (ui->halfsecond_active)
336
+		oswald_halfsecond_tick();
337
+	else
338
+		return FALSE;
339
+
340
+	return TRUE;
341
+}
342
+
343
+void enable_halfsecond_timer(void)
344
+{
345
+	ui_g->halfsecond_active = TRUE;
346
+	g_timeout_add(500, halfsecond_tmo_handler, ui_g);
347
+}
348
+
349
+void disable_halfsecond_timer(void)
350
+{
351
+	ui_g->halfsecond_active = FALSE;
352
+}
353
+
264 354
 int main(int argc , char ** argv)
265 355
 {
266 356
 	oswald_ui ui;
... ...
@@ -269,6 +359,12 @@ int main(int argc , char ** argv)
269 359
 
270 360
 	ui_g = &ui;
271 361
 
362
+	ui.accel_x = 0;
363
+	ui.accel_y = 0;
364
+	ui.accel_z = 0;
365
+	ui.halfsecond_active = FALSE;
366
+	ui.centisecond_active = FALSE;
367
+
272 368
 	mt = time(NULL);
273 369
 	localtime_r(&mt, &mtime);
274 370
 
... ...
@@ -277,7 +373,8 @@ int main(int argc , char ** argv)
277 373
 	create_mainwin(&ui);
278 374
 	gtk_widget_realize(ui.mainwin);
279 375
 
280
-	oswald_set_time(mtime.tm_hour, mtime.tm_min, mtime.tm_sec);
376
+	oswald_set_time(mtime.tm_hour, mtime.tm_min, mtime.tm_sec, TRUE);
377
+	oswald_set_date(mtime.tm_mday, (mtime.tm_mon + 1), (mtime.tm_year + 1900), TRUE);
281 378
 	oswald_init();
282 379
 
283 380
 	g_timeout_add_seconds(1, one_second_tmo_handler, &ui);
... ...
@@ -9,10 +9,21 @@ typedef struct {
9 9
 	GtkWidget *mainwin;
10 10
 	GtkWidget *darea;
11 11
 	GdkPixmap *pixmap;
12
+	u8t accel_x;
13
+	u8t accel_y;
14
+	u8t accel_z;
15
+	gboolean halfsecond_active;
16
+	gboolean centisecond_active;
12 17
 } oswald_ui;
13 18
 
14 19
 void lcd_set_pixel(gint x, gint y, gboolean state);
15 20
 void lcd_clear_display(void);
16 21
 
22
+void enable_centisecond_timer(void);
23
+void disable_centisecond_timer(void);
24
+
25
+void enable_halfsecond_timer(void);
26
+void disable_halfsecond_timer(void);
27
+
17 28
 #endif
18 29
 
... ...
@@ -31,18 +31,20 @@ typedef struct {
31 31
 	u8t	second;
32 32
 	u8t	day;
33 33
 	u8t	month;
34
-	u8t	year;
34
+	u16t	year;
35
+	boolean	clk24hr;
36
+	boolean day_first;
35 37
 } clock_state;
36 38
 
37 39
 typedef enum {
38 40
 	IDLE_SCREEN = 0,
39 41
 	ACCEL_DISPLAY_SCREEN,
40
-	DATETIME_SETTING_SCREEN,
41 42
 	MENU_TEST_SCREEN,
42 43
 //	SCREEN2_SCREEN,
43 44
 //	SCREEN3_SCREEN,
44 45
 //	APPLICATION_SCREEN,
45 46
 	LAST_SCREEN,		// a marker for the last (not valid) screen)
47
+	DATETIME_SETTING_SCREEN,
46 48
 } screen_number;
47 49
 
48 50
 typedef enum {
... ...
@@ -56,13 +58,14 @@ typedef enum {
56 58
 
57 59
 #define EVENT_SCREEN_VISIBLE		(1<<0)		// screen just became visible
58 60
 #define EVENT_SCREEN_DESTROY		(1<<1)		// screen is destroyed
59
-#define EVENT_ONE_SEC_TIMER		(1<<2)
60
-#define EVENT_MS_TIMER			(1<<3)
61
-#define EVENT_USER_BUTTONS		(1<<4)
62
-#define EVENT_ACCEL_UPDATE		(1<<5)
63
-#define EVENT_AMBIENTLIGHT_UPDATE	(1<<6)
64
-#define EVENT_POWER_CHANGE		(1<<7)
65
-#define EVENT_COMMS			(1<<8)
61
+#define EVENT_ONE_SEC_TIMER		(1<<2)		// one second timer for reguler clock
62
+#define EVENT_HALF_SEC_TIMER		(1<<3)		// half second timer for blinking displays
63
+#define EVENT_CS_TIMER			(1<<4)		// centisecond timer, e.g. for stop watch
64
+#define EVENT_USER_BUTTONS		(1<<5)		// button presses
65
+#define EVENT_ACCEL_UPDATE		(1<<6)		// accelerometer updates
66
+#define EVENT_AMBIENTLIGHT_UPDATE	(1<<7)		// ambient light sensor updates
67
+#define EVENT_POWER_CHANGE		(1<<8)		// power source status change
68
+#define EVENT_COMMS			(1<<9)		// communication, like Bluetooth I/O
66 69
 
67 70
 typedef struct {
68 71
 	u16t event_mask;				// the event the screen wants to receive
... ...
@@ -76,5 +79,11 @@ typedef struct {
76 79
 	boolean pending_idle;
77 80
 } watch_state;
78 81
 
82
+typedef struct {
83
+	u8t	x;
84
+	u8t	y;
85
+	u8t	z;
86
+} accel_data_t;
87
+
79 88
 #endif
80 89
 
... ...
@@ -27,11 +27,20 @@ void oswald_change_to_screen(screen_number screen_id)
27 27
 	}
28 28
 }
29 29
 
30
-void oswald_set_time(u8t hour, u8t minute, u8t second)
30
+void oswald_set_time(u8t hour, u8t minute, u8t second, boolean clk24hr)
31 31
 {
32 32
 	OswaldClk.hour = hour;
33 33
 	OswaldClk.minute = minute;
34 34
 	OswaldClk.second = second;
35
+	OswaldClk.clk24hr = clk24hr;
36
+}
37
+
38
+void oswald_set_date(u8t day, u8t month, u16t year, boolean day_first)
39
+{
40
+	OswaldClk.day = day;
41
+	OswaldClk.month = month;
42
+	OswaldClk.year = year;
43
+	OswaldClk.day_first = day_first;
35 44
 }
36 45
 
37 46
 static void update_clock_state (void)
... ...
@@ -63,7 +72,20 @@ void oswald_one_second_tick(void)
63 72
 	if (OswaldState.screen->event_func != NULL &&
64 73
 	    (OswaldState.screen->event_mask & EVENT_ONE_SEC_TIMER))
65 74
 		OswaldState.screen->event_func(EVENT_ONE_SEC_TIMER, NULL);
66
-	// oswald_update_screen();
75
+}
76
+
77
+void oswald_centisecond_tick(void)
78
+{
79
+	if (OswaldState.screen->event_func != NULL &&
80
+	    (OswaldState.screen->event_mask & EVENT_CS_TIMER))
81
+		OswaldState.screen->event_func(EVENT_CS_TIMER, NULL);
82
+}
83
+
84
+void oswald_halfsecond_tick(void)
85
+{
86
+	if (OswaldState.screen->event_func != NULL &&
87
+	    (OswaldState.screen->event_mask & EVENT_HALF_SEC_TIMER))
88
+		OswaldState.screen->event_func(EVENT_HALF_SEC_TIMER, NULL);
67 89
 }
68 90
 
69 91
 void oswald_handle_button_press(watch_button button)
... ...
@@ -78,6 +100,7 @@ void oswald_handle_button_press(watch_button button)
78 100
 				OswaldState.screen->event_func(EVENT_USER_BUTTONS, &button);
79 101
 			break;
80 102
 		case BUTTON_C:
103
+			OswaldState.screen->event_func(EVENT_SCREEN_DESTROY, NULL);
81 104
 			// next screen
82 105
 			OswaldState.screen_id++;
83 106
 			if (OswaldState.screen_id >= LAST_SCREEN) {
... ...
@@ -96,16 +119,35 @@ void oswald_handle_button_press(watch_button button)
96 119
 	};
97 120
 }
98 121
 
122
+void oswald_handle_accel_event(u8t x, u8t y, u8t z)
123
+{
124
+	accel_data_t accel_data;
125
+
126
+	accel_data.x = x;
127
+	accel_data.y = y;
128
+	accel_data.z = z;
129
+
130
+	if (OswaldState.screen->event_func != NULL &&
131
+	    (OswaldState.screen->event_mask & EVENT_ACCEL_UPDATE))
132
+		OswaldState.screen->event_func(EVENT_ACCEL_UPDATE, &accel_data);
133
+}
134
+
135
+void oswald_handle_ambientlight_event(u8t light_level)
136
+{
137
+	if (OswaldState.screen->event_func != NULL &&
138
+	    (OswaldState.screen->event_mask & EVENT_AMBIENTLIGHT_UPDATE))
139
+		OswaldState.screen->event_func(EVENT_AMBIENTLIGHT_UPDATE, &light_level);
140
+}
141
+
99 142
 void oswald_init(void)
100 143
 {
101 144
 	OswaldScreens[IDLE_SCREEN].event_mask = EVENT_USER_BUTTONS | EVENT_ONE_SEC_TIMER;
102 145
 	OswaldScreens[IDLE_SCREEN].event_func = idle_handle_events;
103 146
 
104
-	OswaldScreens[ACCEL_DISPLAY_SCREEN].event_mask = EVENT_USER_BUTTONS;
147
+	OswaldScreens[ACCEL_DISPLAY_SCREEN].event_mask = EVENT_USER_BUTTONS | EVENT_ACCEL_UPDATE;
105 148
 	OswaldScreens[ACCEL_DISPLAY_SCREEN].event_func = accel_handle_events;
106
-	
107 149
 
108
-	OswaldScreens[DATETIME_SETTING_SCREEN].event_mask = EVENT_USER_BUTTONS | EVENT_ONE_SEC_TIMER;
150
+	OswaldScreens[DATETIME_SETTING_SCREEN].event_mask = EVENT_USER_BUTTONS | EVENT_HALF_SEC_TIMER;
109 151
 	OswaldScreens[DATETIME_SETTING_SCREEN].event_func = datetime_setup_events;
110 152
 
111 153
 	OswaldScreens[MENU_TEST_SCREEN].event_mask = EVENT_USER_BUTTONS;
... ...
@@ -11,12 +11,16 @@ extern watch_screen OswaldScreens[];
11 11
 void oswald_one_second_tick();
12 12
 
13 13
 /* sets internal 'RTC' time */
14
-void oswald_set_time(u8t hour, u8t minute, u8t second);
14
+void oswald_set_time(u8t hour, u8t minute, u8t second, boolean clk24hr);
15
+void oswald_set_date(u8t day, u8t month, u16t year, boolean day_first);
15 16
 
16 17
 void oswald_handle_button_press(watch_button button);
17 18
 void oswald_handle_accel_event(u8t x, u8t y, u8t z);
18 19
 void oswald_handle_ambientlight_event(u8t light_level);
19 20
 void oswald_handle_idle_event(void);
21
+void oswald_one_second_tick(void);
22
+void oswald_halfsecond_tick(void);
23
+void oswald_centisecond_tick(void);
20 24
 void oswald_init(void);
21 25
 
22 26
 #endif
... ...
@@ -1,12 +1,14 @@
1 1
 #include "oswald.h"
2
+#include "oswald_main.h"
2 3
 #include "oswald_watch_faces.h"
3 4
 #include "Fonts.h"
4 5
 #include "LcdDisplay.h"
5 6
 
6 7
 #include "oswald_screens.h"
7 8
 
9
+
8 10
 typedef struct {
9
-	void (*screendraw_func)(boolean shoq_seconds);
11
+	void (*screendraw_func)(boolean show_seconds);
10 12
 	boolean show_seconds;
11 13
 	boolean analogue;
12 14
 } idle_data_t;
... ...
@@ -19,13 +21,13 @@ static idle_data_t idle_screen = {
19 21
 void idle_handle_user_buttons(watch_button button)
20 22
 {
21 23
 	switch (button) {
22
-		case BUTTON_D:
24
+		case BUTTON_A:
23 25
 			if (idle_screen.show_seconds)
24 26
 				idle_screen.show_seconds = FALSE;
25 27
 			else
26 28
 				idle_screen.show_seconds = TRUE;
27 29
 			break;
28
-		case BUTTON_E:
30
+		case BUTTON_B:
29 31
 			if (idle_screen.analogue == TRUE) {
30 32
 				idle_screen.analogue = FALSE;
31 33
 				idle_screen.screendraw_func = DrawLcdDigitalClock;
... ...
@@ -34,6 +36,12 @@ void idle_handle_user_buttons(watch_button button)
34 36
 				idle_screen.screendraw_func = DrawLcdAnaClock;
35 37
 			};
36 38
 			break;
39
+		case BUTTON_D:
40
+			OswaldState.screen_id = DATETIME_SETTING_SCREEN;
41
+			OswaldState.screen = &OswaldScreens[OswaldState.screen_id];
42
+			OswaldState.screen->event_func(EVENT_SCREEN_VISIBLE, NULL);
43
+			return;
44
+			break;
37 45
 		default:
38 46
 			break;
39 47
 	};
... ...
@@ -57,23 +65,38 @@ void idle_handle_events(u16t event, void *data)
57 65
 }
58 66
 
59 67
 
60
-void draw_accel_screen(void)
68
+typedef struct {
69
+	accel_data_t accdata;
70
+} accelscreen_data_t;
71
+static accelscreen_data_t accel_screen = {
72
+	{ 0, 0, 0},
73
+};
74
+
75
+void draw_accel_screen(accel_data_t *accel_data)
61 76
 {
62 77
 	lcd_clear_display();
63 78
 	SetFont(MetaWatch16);
64 79
 	WriteLcdString(2, 2, "X:");
65
-	WriteLcdString(20, 2, "123");
66
-	WriteLcdString(2, 18, "Z:");
67
-	WriteLcdString(20, 18, "123");
68
-	WriteLcdString(2, 34, "Y:");
69
-	WriteLcdString(20, 34, "123");
80
+	WriteLcdNumber(20, 2, accel_data->x);
81
+	WriteLcdString(2, 18, "Y:");
82
+	WriteLcdNumber(20, 18, accel_data->y);
83
+	WriteLcdString(2, 34, "Z:");
84
+	WriteLcdNumber(20, 34, accel_data->z);
70 85
 }
71 86
 
72 87
 void accel_handle_events(u16t event, void *data)
73 88
 {
74 89
 	switch (event) {
75 90
 		case EVENT_SCREEN_VISIBLE:
76
-			draw_accel_screen();
91
+			draw_accel_screen(&accel_screen.accdata);
92
+			break;
93
+		case EVENT_ACCEL_UPDATE: {
94
+			accel_data_t *accel_data = (accel_data_t *)data;
95
+			accel_screen.accdata.x = accel_data->x;
96
+			accel_screen.accdata.y = accel_data->y;
97
+			accel_screen.accdata.z = accel_data->z;
98
+			draw_accel_screen(&accel_screen.accdata);
99
+			};
77 100
 			break;
78 101
 		case EVENT_USER_BUTTONS:
79 102
 			dbg_out("button event %d\n", *(int *)data);
... ...
@@ -84,24 +107,172 @@ void accel_handle_events(u16t event, void *data)
84 107
 }
85 108
 
86 109
 
87
-void draw_datetime_setup_screen(void)
110
+typedef struct {
111
+	u8t pos;
112
+	boolean on;
113
+} datetime_setup_data_t;
114
+static datetime_setup_data_t dt_setup_screen = {
115
+	0,
116
+	TRUE
117
+};
118
+
119
+void draw_datetime_setup_screen(datetime_setup_data_t *sdata)
88 120
 {
89 121
 	lcd_clear_display();
90 122
 	SetFont(MetaWatch16);
91
-	WriteLcdString(2, 2, "Date / Time");
92
-	WriteLcdString(2, 18, "Setting");
93
-	WriteLcdString(2, 34, "22:39");
94
-	WriteLcdString(2, 50, "07.08.2012");
123
+	WriteLcdString(2, 2, "Set");
124
+
125
+	SetFont(MetaWatchTime);
126
+	if ((sdata->pos == 0 && sdata->on) || sdata->pos != 0) {
127
+		WriteLcdCharacter(2, 20, (OswaldClk.hour / 10));
128
+		WriteLcdCharacter(14, 20, (OswaldClk.hour % 10));
129
+	}
130
+	WriteLcdCharacter(26, 20, TIME_CHARACTER_COLON_INDEX);
131
+
132
+	if ((sdata->pos == 1 && sdata->on) || sdata->pos != 1) {
133
+		WriteLcdCharacter(31, 20, (OswaldClk.minute / 10));
134
+		WriteLcdCharacter(43, 20, (OswaldClk.minute % 10));
135
+	}
136
+
137
+	WriteLcdCharacter(55, 20, TIME_CHARACTER_COLON_INDEX);
138
+
139
+	if ((sdata->pos == 2 && sdata->on) || sdata->pos != 2) {
140
+		WriteLcdCharacter(60, 20, (OswaldClk.second / 10));
141
+		WriteLcdCharacter(72, 20, (OswaldClk.second % 10));
142
+	}
143
+
144
+	SetFont(MetaWatch16);
145
+	if ((sdata->pos == 3 && sdata->on) || sdata->pos != 3) {
146
+		WriteLcdNumber(2, 45, OswaldClk.day);
147
+	}
148
+	WriteLcdString(18, 45, ".");
149
+	if ((sdata->pos == 4 && sdata->on) || sdata->pos != 4) {
150
+		WriteLcdNumber(22, 45, OswaldClk.month);
151
+	}
152
+	WriteLcdString(38, 45, ".");
153
+	if ((sdata->pos == 5 && sdata->on) || sdata->pos != 5) {
154
+		WriteLcdNumber(42, 45, OswaldClk.year);
155
+	}
156
+
157
+	SetFont(MetaWatch7);
158
+	if ((sdata->pos == 6 && sdata->on) || sdata->pos != 6) {
159
+		if (OswaldClk.clk24hr)
160
+			WriteLcdString(2, 66, "x");
161
+		else
162
+			WriteLcdString(2, 66, "_");
163
+	}
164
+	WriteLcdString(15, 66, "24hr");
165
+
166
+	if ((sdata->pos == 7 && sdata->on) || sdata->pos != 7) {
167
+		if (OswaldClk.day_first)
168
+			WriteLcdString(2, 79, "x");
169
+		else
170
+			WriteLcdString(2, 79, "_");
171
+	}
172
+	WriteLcdString(15, 79, "dd.mm.  mm/dd");
173
+}
174
+
175
+void datetime_handle_updown(u8t pos, s8t incr)
176
+{
177
+	switch (pos) {
178
+		case 0: // hour
179
+			if (OswaldClk.hour == 0 && incr == -1) {
180
+				OswaldClk.hour = 23;
181
+				break;
182
+			};
183
+			OswaldClk.hour += incr;
184
+			if (OswaldClk.hour > 23)
185
+				OswaldClk.hour = 0;
186
+			break;
187
+		case 1: // minute
188
+			if (OswaldClk.minute == 0 && incr == -1) {
189
+				OswaldClk.minute = 59;
190
+				break;
191
+			};
192
+			OswaldClk.minute += incr;
193
+			if (OswaldClk.minute > 59)
194
+				OswaldClk.minute = 0;
195
+			break;
196
+		case 2: // second
197
+			OswaldClk.second = 0;
198
+			break;
199
+		case 3: // day
200
+			if (OswaldClk.day == 1 && incr == -1) {
201
+				OswaldClk.day = 31;
202
+				break;
203
+			};
204
+			OswaldClk.day += incr;
205
+			if (OswaldClk.day > 31)
206
+				OswaldClk.day = 1;
207
+			break;
208
+		case 4: // month
209
+			if (OswaldClk.month == 1 && incr == -1) {
210
+				OswaldClk.month = 12;
211
+				break;
212
+			};
213
+			OswaldClk.month += incr;
214
+			if (OswaldClk.month > 12)
215
+				OswaldClk.month = 1;
216
+			break;
217
+		case 5: // year
218
+			OswaldClk.year += incr;
219
+			break;
220
+		case 6: // 24hr / 12hr
221
+			if (OswaldClk.clk24hr)
222
+				OswaldClk.clk24hr = FALSE;
223
+			else
224
+				OswaldClk.clk24hr = TRUE;
225
+			break;
226
+		case 7: // dd.mm. / mm/dd
227
+			if (OswaldClk.day_first)
228
+				OswaldClk.day_first = FALSE;
229
+			else
230
+				OswaldClk.day_first = TRUE;
231
+			break;
232
+		default:
233
+			break;
234
+	};
235
+}
236
+
237
+void handle_setup_datetime_buttons(watch_button button, datetime_setup_data_t *sdata)
238
+{
239
+	switch (button) {
240
+		case BUTTON_A:
241
+			datetime_handle_updown(sdata->pos, 1);
242
+			break;
243
+		case BUTTON_B:
244
+			datetime_handle_updown(sdata->pos, -1);
245
+			break;
246
+		case BUTTON_D:
247
+			sdata->pos++;
248
+			sdata->pos %= 8;
249
+			break;
250
+		default:
251
+			break;
252
+	}
253
+	draw_datetime_setup_screen(sdata);
95 254
 }
96 255
 
97 256
 void datetime_setup_events(u16t event, void *data)
98 257
 {
99 258
 	switch (event) {
100 259
 		case EVENT_SCREEN_VISIBLE:
101
-			draw_datetime_setup_screen();
260
+			draw_datetime_setup_screen(&dt_setup_screen);
261
+			enable_halfsecond_timer();
262
+			break;
263
+		case EVENT_SCREEN_DESTROY:
264
+			disable_halfsecond_timer();
102 265
 			break;
103 266
 		case EVENT_USER_BUTTONS:
104 267
 			dbg_out("button event %d\n", *(int *)data);
268
+			handle_setup_datetime_buttons(*(watch_button *)data, &dt_setup_screen);
269
+			break;
270
+		case EVENT_HALF_SEC_TIMER:
271
+			if (dt_setup_screen.on)
272
+				dt_setup_screen.on = FALSE;
273
+			else
274
+				dt_setup_screen.on = TRUE;
275
+			draw_datetime_setup_screen(&dt_setup_screen);
105 276
 			break;
106 277
 		default:
107 278
 			break;
... ...
@@ -14,3 +14,35 @@ u16t oswald_strlen(u8t *string)
14 14
 	return i;
15 15
 }
16 16
 
17
+char* itoa(s16t value, char* result, int base)
18
+{
19
+	char* ptr = result, *ptr1 = result, tmp_char;
20
+	s16t tmp_value;
21
+
22
+	if (result == NULL)
23
+		return NULL;
24
+
25
+	// check that the base if valid
26
+	if (base < 2 || base > 36) {
27
+		*result = '\0';
28
+		return result;
29
+	}
30
+
31
+	do {
32
+		tmp_value = value;
33
+		value /= base;
34
+		*ptr++ = "zyxwvutsrqponmlkjihgfedcba9876543210123456789abcdefghijklmnopqrstuvwxyz" [35 + (tmp_value - value * base)];
35
+	} while ( value );
36
+
37
+	// Apply negative sign
38
+	if (tmp_value < 0)
39
+		*ptr++ = '-';
40
+	*ptr-- = '\0';
41
+	while (ptr1 < ptr) {
42
+		tmp_char = *ptr;
43
+		*ptr--= *ptr1;
44
+		*ptr1++ = tmp_char;
45
+	}
46
+	return result;
47
+}
48
+
... ...
@@ -2,6 +2,7 @@
2 2
 #define _OSWALD_STRINGS_H
3 3
 
4 4
 u16t oswald_strlen(u8t *string);
5
+char* itoa(s16t value, char* result, int base);
5 6
 
6 7
 #endif
7 8