Browse code

Oh boy... lots of changes, too many to describe

Nils Faerber authored on 21/04/2013 14:26:38
Showing 16 changed files
... ...
@@ -20,15 +20,42 @@
20 20
 /*! The number of printable characters in the font tables */
21 21
 #define PRINTABLE_CHARACTERS ( 94 )
22 22
 
23
+#if defined(__GNUC__) && (__MSP430X__ > 0)
24
+__attribute__((__far__))
25
+#endif
23 26
 const unsigned char MetaWatch5table[PRINTABLE_CHARACTERS][5];
27
+#if defined(__GNUC__) && (__MSP430X__ > 0)
28
+__attribute__((__far__))
29
+#endif
24 30
 const unsigned char MetaWatch7table[PRINTABLE_CHARACTERS][7];
31
+#if defined(__GNUC__) && (__MSP430X__ > 0)
32
+__attribute__((__far__))
33
+#endif
25 34
 const u16t MetaWatch16table[PRINTABLE_CHARACTERS][16];
35
+#if defined(__GNUC__) && (__MSP430X__ > 0)
36
+__attribute__((__far__))
37
+#endif
26 38
 const u16t MetaWatchTimeTable[TOTAL_TIME_CHARACTERS][19];
39
+#if defined(__GNUC__) && (__MSP430X__ > 0)
40
+__attribute__((__far__))
41
+#endif
27 42
 const unsigned char MetaWatchMonospaced10Table[PRINTABLE_CHARACTERS][10];
28 43
 
44
+#if defined(__GNUC__) && (__MSP430X__ > 0)
45
+__attribute__((__far__))
46
+#endif
29 47
 const unsigned char MetaWatch5width[PRINTABLE_CHARACTERS];
48
+#if defined(__GNUC__) && (__MSP430X__ > 0)
49
+__attribute__((__far__))
50
+#endif
30 51
 const unsigned char MetaWatch7width[PRINTABLE_CHARACTERS];
52
+#if defined(__GNUC__) && (__MSP430X__ > 0)
53
+__attribute__((__far__))
54
+#endif
31 55
 const unsigned char MetaWatch16width[PRINTABLE_CHARACTERS];
56
+#if defined(__GNUC__) && (__MSP430X__ > 0)
57
+__attribute__((__far__))
58
+#endif
32 59
 const unsigned char MetaWatchTimeWidth[TOTAL_TIME_CHARACTERS];
33 60
 
34 61
 /*! Font Structure
... ...
@@ -189,6 +216,9 @@ void GetCharacterBitmap(unsigned char Character, u16t *pBitmap)
189 216
 
190 217
 }
191 218
 
219
+#if defined(__GNUC__) && (__MSP430X__ > 0)
220
+__attribute__((__far__))
221
+#endif
192 222
 const unsigned char MetaWatch5table[PRINTABLE_CHARACTERS][5] = 
193 223
 {
194 224
   /* character 0x20 (' '): (width = 2) */
... ...
@@ -474,6 +504,9 @@ const unsigned char MetaWatch5table[PRINTABLE_CHARACTERS][5] =
474 504
   0x00, 0x00, 0x00, 0x00, 0x00,},
475 505
 };
476 506
 
507
+#if defined(__GNUC__) && (__MSP430X__ > 0)
508
+__attribute__((__far__))
509
+#endif
477 510
 const unsigned char MetaWatch5width[PRINTABLE_CHARACTERS] = 
478 511
 {
479 512
 /*		width    char    hexcode */
... ...
@@ -574,6 +607,9 @@ const unsigned char MetaWatch5width[PRINTABLE_CHARACTERS] =
574 607
   		  3, /*   }      7D      */
575 608
 };
576 609
 
610
+#if defined(__GNUC__) && (__MSP430X__ > 0)
611
+__attribute__((__far__))
612
+#endif
577 613
 const unsigned char MetaWatch7table[PRINTABLE_CHARACTERS][7] = 
578 614
 {
579 615
 
... ...
@@ -860,6 +896,9 @@ const unsigned char MetaWatch7table[PRINTABLE_CHARACTERS][7] =
860 896
 
861 897
 };
862 898
 
899
+#if defined(__GNUC__) && (__MSP430X__ > 0)
900
+__attribute__((__far__))
901
+#endif
863 902
 const unsigned char MetaWatch7width[PRINTABLE_CHARACTERS] = {
864 903
 /*		width    char    hexcode */
865 904
 /*		=====    ====    ======= */
... ...
@@ -960,6 +999,9 @@ const unsigned char MetaWatch7width[PRINTABLE_CHARACTERS] = {
960 999
 };
961 1000
 
962 1001
 
1002
+#if defined(__GNUC__) && (__MSP430X__ > 0)
1003
+__attribute__((__far__))
1004
+#endif
963 1005
 const u16t MetaWatch16table[PRINTABLE_CHARACTERS][16] = 
964 1006
 {
965 1007
   /* character 0x20 (' '): (width=4) */
... ...
@@ -1526,6 +1568,9 @@ const u16t MetaWatch16table[PRINTABLE_CHARACTERS][16] =
1526 1568
   0x0006, 0x0002, 0x0001, 0x0000},
1527 1569
 };
1528 1570
 
1571
+#if defined(__GNUC__) && (__MSP430X__ > 0)
1572
+__attribute__((__far__))
1573
+#endif
1529 1574
 const unsigned char MetaWatch16width[PRINTABLE_CHARACTERS] = 
1530 1575
 {
1531 1576
 /*		width    char    hexcode */
... ...
@@ -1627,6 +1672,9 @@ const unsigned char MetaWatch16width[PRINTABLE_CHARACTERS] =
1627 1672
 };
1628 1673
 
1629 1674
 /******************************************************************************/
1675
+#if defined(__GNUC__) && (__MSP430X__ > 0)
1676
+__attribute__((__far__))
1677
+#endif
1630 1678
 const u16t MetaWatchTimeTable[TOTAL_TIME_CHARACTERS][19] = 
1631 1679
 {
1632 1680
   /* character 0x30 ('0'): (width=11, offset=0) */
... ...
@@ -1714,6 +1762,9 @@ const u16t MetaWatchTimeTable[TOTAL_TIME_CHARACTERS][19] =
1714 1762
   0x0000, 0x0000, 0x0000},
1715 1763
 };
1716 1764
 
1765
+#if defined(__GNUC__) && (__MSP430X__ > 0)
1766
+__attribute__((__far__))
1767
+#endif
1717 1768
 const unsigned char MetaWatchTimeWidth[TOTAL_TIME_CHARACTERS] = 
1718 1769
 {
1719 1770
 /*		width    char    hexcode */
... ...
@@ -1734,6 +1785,9 @@ const unsigned char MetaWatchTimeWidth[TOTAL_TIME_CHARACTERS] =
1734 1785
 
1735 1786
 /******************************************************************************/
1736 1787
 
1788
+#if defined(__GNUC__) && (__MSP430X__ > 0)
1789
+__attribute__((__far__))
1790
+#endif
1737 1791
 const unsigned char MetaWatchMonospaced10Table[PRINTABLE_CHARACTERS][10] =  
1738 1792
 {
1739 1793
   {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
... ...
@@ -1,4 +1,5 @@
1
-#include "oswald-ui.h"
1
+#include "oswald.h"
2
+#include "oswald_hal.h"
2 3
 #include "oswald_strings.h"
3 4
 #include "Fonts.h"
4 5
 
... ...
@@ -32,7 +33,7 @@ void DrawLcdLineBresenham(u8t xstart, u8t ystart, u8t xend, u8t yend)
32 33
 	x = xstart;
33 34
 	y = ystart;
34 35
 	err = el/2;
35
-	lcd_set_pixel(x, y, TRUE);
36
+	hal_lcd_set_pixel(x, y, TRUE);
36 37
  
37 38
 	for (t = 0; t < el; ++t) {
38 39
 		err -= es; 
... ...
@@ -44,7 +45,7 @@ void DrawLcdLineBresenham(u8t xstart, u8t ystart, u8t xend, u8t yend)
44 45
 			x += pdx;
45 46
 			y += pdy;
46 47
 		}
47
-		lcd_set_pixel(x, y, TRUE);
48
+		hal_lcd_set_pixel(x, y, TRUE);
48 49
 	}
49 50
 	// lcd_update_display();
50 51
 }
... ...
@@ -77,12 +78,12 @@ void DrawLcdLineBresenhamWW(u8t xstart, u8t ystart, u8t xend, u8t yend, u8t thic
77 78
 	x = xstart;
78 79
 	y = ystart;
79 80
 	err = el/2;
80
-	lcd_set_pixel(x, y, TRUE);
81
+	hal_lcd_set_pixel(x, y, TRUE);
81 82
 	for (i=1; i<thickness; i++) {
82
-		lcd_set_pixel(x-i, y, TRUE);
83
-		lcd_set_pixel(x+i, y, TRUE);
84
-		lcd_set_pixel(x, y-i, TRUE);
85
-		lcd_set_pixel(x, y+i, TRUE);
83
+		hal_lcd_set_pixel(x-i, y, TRUE);
84
+		hal_lcd_set_pixel(x+i, y, TRUE);
85
+		hal_lcd_set_pixel(x, y-i, TRUE);
86
+		hal_lcd_set_pixel(x, y+i, TRUE);
86 87
 	}
87 88
  
88 89
 	for (t = 0; t < el; ++t) {
... ...
@@ -95,12 +96,12 @@ void DrawLcdLineBresenhamWW(u8t xstart, u8t ystart, u8t xend, u8t yend, u8t thic
95 96
 			x += pdx;
96 97
 			y += pdy;
97 98
 		}
98
-		lcd_set_pixel(x, y, TRUE);
99
+		hal_lcd_set_pixel(x, y, TRUE);
99 100
 		for (i=1; i<thickness; i++) {
100
-			lcd_set_pixel(x-i, y, TRUE);
101
-			lcd_set_pixel(x+i, y, TRUE);
102
-			lcd_set_pixel(x, y-i, TRUE);
103
-			lcd_set_pixel(x, y+i, TRUE);
101
+			hal_lcd_set_pixel(x-i, y, TRUE);
102
+			hal_lcd_set_pixel(x+i, y, TRUE);
103
+			hal_lcd_set_pixel(x, y-i, TRUE);
104
+			hal_lcd_set_pixel(x, y+i, TRUE);
104 105
 		}
105 106
 	}
106 107
 	// lcd_update_display();
... ...
@@ -119,10 +120,10 @@ u8t WriteLcdCharacter(u8t x, u8t y, u8t Character)
119 120
 	for (ly=0; ly<CharacterHeight; ly++) {
120 121
 		for (lx=0; lx<CharacterWidth; lx++) {
121 122
 			if (bitmap[ly] & (1<<lx)) {
122
-				lcd_set_pixel(lx+x, ly+y, TRUE);
123
+				hal_lcd_set_pixel(lx+x, ly+y, TRUE);
123 124
 				// printf(".");
124 125
 			} else {
125
-				lcd_set_pixel(lx+x, ly+y, FALSE);
126
+				hal_lcd_set_pixel(lx+x, ly+y, FALSE);
126 127
 				// printf(" ");
127 128
 			}
128 129
 		}
... ...
@@ -132,18 +133,19 @@ u8t WriteLcdCharacter(u8t x, u8t y, u8t Character)
132 133
 	return CharacterWidth + GetFontSpacing();
133 134
 }
134 135
 
135
-void WriteLcdString(u8t x, u8t y, char *str)
136
+u8t WriteLcdString(u8t x, u8t y, char *str)
136 137
 {
137 138
 	int lx, i, strl;
138 139
 
139 140
 	strl = oswald_strlen(str);
140 141
 	if (strl == 0)
141
-		return;
142
+		return 0;
142 143
 
143 144
 	lx = x;
144 145
 	for (i=0; i<strl; i++) {
145 146
 		lx += WriteLcdCharacter(lx, y, str[i]);
146 147
 	}
148
+	return lx;
147 149
 }
148 150
 
149 151
 
... ...
@@ -1,12 +1,12 @@
1 1
 #ifndef _LcdDisplay_h
2 2
 #define _LcdDisplay_h
3 3
 
4
-#include "oswald-ui.h"
4
+// #include "oswald_hal.h"
5 5
 
6 6
 void DrawLcdLineBresenham(u8t xstart, u8t ystart, u8t xend, u8t yend);
7 7
 void DrawLcdLineBresenhamWW(u8t xstart, u8t ystart, u8t xend, u8t yend, u8t thickness);
8 8
 u8t WriteLcdCharacter(u8t x, u8t y, u8t Character);
9
-void WriteLcdString(u8t x, u8t y, char *str);
9
+u8t WriteLcdString(u8t x, u8t y, char *str);
10 10
 void WriteLcdNumber(u8t x, u8t y, s16t number);
11 11
 
12 12
 #endif
... ...
@@ -3,7 +3,7 @@ ACLOCAL_AMFLAGS = -I m4
3 3
 bin_PROGRAMS = oswald-gui
4 4
 
5 5
 oswald_gui_SOURCES = oswald-ui.c LcdDisplay.c Fonts.c oswald_main.c oswald_watch_faces.c oswald_strings.c oswald_screens.c \
6
-embedvm.c oswald_fonts.c oswald_graphics.c
6
+embedvm.c oswald_fonts.c oswald_graphics.c calendar.c
7 7
 oswald_gui_CFLAGS = -g $(GTK_CFLAGS)
8 8
 oswald_gui_LDADD = $(GTK_LIBS)
9 9
 
10 10
new file mode 100644
... ...
@@ -0,0 +1,208 @@
1
+#include "oswald.h"
2
+
3
+#include "calendar.h"
4
+
5
+unsigned char is_leap(const unsigned int year)
6
+{
7
+  // Die Regel lautet: Alles, was durch 4 teilbar ist, ist ein Schaltjahr.
8
+  // Es sei denn, das Jahr ist durch 100 teilbar, dann ist es keins.
9
+  // Aber wenn es durch 400 teilbar ist, ist es doch wieder eins.
10
+
11
+	if ((year % 400) == 0)
12
+		return 1;
13
+	else if ((year % 100) == 0)
14
+		return 0;
15
+	else if ((year % 4) == 0)
16
+		return 1;
17
+
18
+	return 0;
19
+}
20
+
21
+unsigned short days_of_month(const unsigned int uMonat, const unsigned int uJahr)
22
+{
23
+	//                     ungült,Jan,Feb,Mrz,Apr,Mai,Jun,Jul,Aug,Sep,Okt,Nov,Dez
24
+	int arrTageImMonat[13] = {  0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
25
+
26
+	if (uMonat == 2) {
27
+		// Februar: Schaltjahr unterscheiden
28
+		if (is_leap(uJahr))
29
+			return 29;
30
+		else
31
+			return 28;
32
+	}
33
+
34
+	if ((uMonat >= 1) && (uMonat <= 12))
35
+		return arrTageImMonat[uMonat];
36
+	else {
37
+		return 0;
38
+	}
39
+}
40
+
41
+short getAnzahlTageImJahr(const unsigned int uJahr)
42
+{
43
+	return (is_leap(uJahr)) ? 366 : 365;
44
+}
45
+
46
+short getWochentag(const unsigned int uTag, const unsigned int uMonat, const unsigned int uJahr)
47
+{
48
+	//                       ungült Jan Feb Mrz Apr Mai Jun Jul Aug Sep Okt Nov Dez 
49
+	unsigned char arrMonatsOffset[13] = {  0,  0,  3,  3,  6,  1,  4,  6,  2,  5,  0,  3,  5};
50
+	short nErgebnis = 0;
51
+
52
+	// Monat / Tag - Plausi prüfen:
53
+	if ((uTag > 31) || (uMonat > 12) || (uMonat <= 0) 
54
+		|| (uTag <= 0) || (uJahr <= 0)) {
55
+		return -1;
56
+	}
57
+
58
+	unsigned char cbTagesziffer = (uTag % 7);
59
+	unsigned char cbMonatsziffer = arrMonatsOffset[uMonat];
60
+	unsigned char cbJahresziffer = ((uJahr % 100) + ((uJahr % 100) / 4)) % 7;
61
+	unsigned char cbJahrhundertziffer = (3 - ((uJahr / 100) % 4)) * 2;
62
+
63
+	// Schaltjahreskorrektur:
64
+	if ((uMonat <= 2) && (is_leap(uJahr)))
65
+		cbTagesziffer = cbTagesziffer + 6;
66
+  
67
+	nErgebnis = (cbTagesziffer + cbMonatsziffer + cbJahresziffer + cbJahrhundertziffer) % 7;
68
+
69
+	// Ergebnis:
70
+	// 0 = Sonntag
71
+	// 1 = Montag
72
+	// 2 = Dienstag
73
+	// 3 = Mittwoch
74
+	// 4 = Donnerstag
75
+	// 5 = Freitag
76
+	// 6 = Samstag
77
+	return nErgebnis;
78
+}
79
+
80
+short getTagDesJahres(const unsigned int uTag, const unsigned int uMonat, const unsigned int uJahr)
81
+{
82
+	// Der wievielte Tag des Jahres ist dieser Tag
83
+	if ((uMonat == 0) || (uMonat > 12)) {
84
+		return -1;
85
+	}
86
+
87
+	unsigned int uLokalTag = uTag;
88
+	unsigned int uLokalMonat = uMonat;
89
+
90
+	while (uLokalMonat > 1) {
91
+		uLokalMonat--;
92
+		uLokalTag += days_of_month(uLokalMonat, uJahr);
93
+	}
94
+
95
+	return uLokalTag;
96
+}
97
+
98
+short getKalenderwoche(short uTag, short uMonat, short uJahr)
99
+{
100
+	// Berechnung erfolgt analog DIN 1355, welche besagt:
101
+	// Der erste Donnerstag im neuen Jahr liegt immer in der KW 1.
102
+	// "Woche" ist dabei definiert als [Mo, ..., So].
103
+	short nTagDesJahres = getTagDesJahres(uTag, uMonat, uJahr);
104
+
105
+	// Berechnen des Wochentags des 1. Januar:
106
+	short nWochentag1Jan = getWochentag(1, 1, uJahr);
107
+
108
+	// Sonderfälle Freitag und Samstag
109
+	if (nWochentag1Jan >= 5) 
110
+		nWochentag1Jan = nWochentag1Jan - 7;
111
+
112
+	// Sonderfälle "Jahresanfang mit KW - Nummer aus dem Vorjahr"
113
+	if ( (nTagDesJahres + nWochentag1Jan) <= 1) {
114
+		return getKalenderwoche(31, 12, uJahr - 1);
115
+	}
116
+
117
+	short nKalenderWoche = ((nTagDesJahres + nWochentag1Jan + 5) / 7);
118
+
119
+	// 53 Kalenderwochen hat grundsätzlich nur ein Jahr, 
120
+	// welches mit einem Donnerstag anfängt !
121
+	// In Schaltjahren ist es auch mit einem Mittwoch möglich, z.B. 1992
122
+	// Andernfalls ist diese KW schon die KW1 des Folgejahres.
123
+	if (nKalenderWoche == 53) {
124
+		boolean bIstSchaltjahr = is_leap(uJahr);
125
+
126
+		if ((nWochentag1Jan  ==  4) // Donnerstag
127
+			||  (nWochentag1Jan  == -3) // auch Donnerstag
128
+			||  ((nWochentag1Jan ==  3) && bIstSchaltjahr)
129
+			||  ((nWochentag1Jan == -4) && bIstSchaltjahr)) {
130
+			; // Das ist korrekt und erlaubt
131
+		} else
132
+			nKalenderWoche = 1; // Korrektur des Wertes
133
+	}
134
+
135
+	return nKalenderWoche;
136
+}
137
+
138
+void getOsterdatum(const unsigned int uJahr, unsigned int *uTag, unsigned int *uMonat)
139
+{
140
+	// Berechnet für ein beliebiges Jahr das Osterdatum.
141
+
142
+	// Quelle des Gauss - Algorithmus: Stefan Gerth, 
143
+	// "Die Gauß'sche Osterregel", Nürnberg, Februar 2003. 
144
+	// http://krapfen.org/content/paper/Schule/Facharbeit/Berechnung_des_Osterfestes.pdf
145
+
146
+	unsigned int a = uJahr % 19;
147
+	unsigned int b = uJahr %  4;
148
+	unsigned int c = uJahr %  7;
149
+
150
+	int k = uJahr / 100;
151
+	int q = k / 4;
152
+	int p = ((8 * k) + 13) / 25;
153
+	unsigned int Egz = (38 - (k - q) + p) % 30; // Die Jahrhundertepakte
154
+	unsigned int M = (53 - Egz) % 30;
155
+	unsigned int N = (4 + k - q) % 7;
156
+
157
+	unsigned int d = ((19 * a) + M) % 30;
158
+	unsigned int e = ((2 * b) + (4 * c) + (6 * d) + N) % 7;
159
+
160
+	// Ausrechnen des Ostertermins:
161
+	if ((22 + d + e) <= 31) {
162
+		*uTag = 22 + d + e;
163
+		*uMonat = 3;
164
+	} else {
165
+		*uTag = d + e - 9;
166
+		*uMonat = 4;
167
+
168
+		// Zwei Ausnahmen berücksichtigen:
169
+		if (*uTag == 26)
170
+			*uTag = 19;
171
+		else if ((*uTag == 25) && (d == 28) && (a > 10))
172
+			*uTag = 18;
173
+	}
174
+
175
+	// Offsets für andere Feiertage:
176
+
177
+	// Schwerdonnerstag / Weiberfastnacht -52
178
+	// Rosenmontag -48
179
+	// Fastnachtsdienstag -47
180
+	// Aschermittwoch -46
181
+	// Gründonnerstag -3
182
+	// Karfreitag -2
183
+	// Ostersonntag 0
184
+	// Ostermontag +1
185
+	// Christi Himmelfahrt +39
186
+	// Pfingstsonntag +49
187
+	// Pfingstmontag +50
188
+	// Fronleichnam +60
189
+
190
+	// Mariä Himmelfahrt ist stets am 15. August (Danke an Michael Plugge!)
191
+}
192
+
193
+void getViertenAdvent(const unsigned int uJahr, unsigned int *uTag, unsigned int *uMonat)
194
+{
195
+	// Berechnet für ein beliebiges Jahr das Datum des 4. Advents-Sonntags.
196
+	// Der 4. Adventssonntag ist stets der Sonntag vor dem 1. Weihnachtsfeiertag,
197
+	// muß also stets in der Periode [18. - 24.12.] liegen:
198
+  
199
+	*uMonat = 12; // Das steht jedes Jahr fest :-)
200
+  
201
+	short nWoTag = getWochentag(24, 12, uJahr); // Wochentag des 24.12. ermitteln
202
+  
203
+	*uTag = 24 - nWoTag;
204
+
205
+	// Offsets: Der Buß- und Bettag liegt stets 32 Tage vor dem  4. Advent
206
+}
207
+
208
+
0 209
new file mode 100644
... ...
@@ -0,0 +1,21 @@
1
+#ifndef _CALENDAR_H
2
+#define _CALENDAR_H
3
+
4
+unsigned char is_leap(const unsigned int year);
5
+
6
+unsigned short days_of_month(const unsigned int uMonat, const unsigned int uJahr);
7
+
8
+short getAnzahlTageImJahr(const unsigned int uJahr);
9
+
10
+short getWochentag(const unsigned int uTag, const unsigned int uMonat, const unsigned int uJahr);
11
+
12
+short getTagDesJahres(const unsigned int uTag, const unsigned int uMonat, const unsigned int uJahr);
13
+
14
+short getKalenderwoche(short uTag, short uMonat, short uJahr);
15
+
16
+void getOsterdatum(const unsigned int uJahr, unsigned int *uTag, unsigned int *uMonat);
17
+
18
+void getViertenAdvent(const unsigned int uJahr, unsigned int *uTag, unsigned int *uMonat);
19
+
20
+#endif
21
+
... ...
@@ -23,7 +23,7 @@
23 23
 
24 24
 static oswald_ui *ui_g;
25 25
 
26
-void lcd_set_pixel(gint x, gint y, gboolean state)
26
+void hal_lcd_set_pixel(gint x, gint y, gboolean state)
27 27
 {
28 28
 	gint ix, iy;
29 29
 
... ...
@@ -39,12 +39,12 @@ void lcd_set_pixel(gint x, gint y, gboolean state)
39 39
 }
40 40
 
41 41
 /* updates the actual LCD so that drawing becomes visible */
42
-void lcd_update_display(void)
42
+void hal_lcd_update_display(void)
43 43
 {
44 44
 	gtk_widget_queue_draw(ui_g->darea);
45 45
 }
46 46
 
47
-void lcd_clear_display(void)
47
+void hal_lcd_clear_display(void)
48 48
 {
49 49
 	gdk_draw_rectangle (ui_g->pixmap,
50 50
 		ui_g->darea->style->white_gc,
... ...
@@ -219,19 +219,19 @@ static void create_mainwin(oswald_ui *ui)
219 219
 	vb = gtk_vbox_new(FALSE, 5);
220 220
 	gtk_box_pack_start (GTK_BOX(hb), vb, FALSE, FALSE, 5);
221 221
 
222
-	btn = gtk_button_new_with_label(" D ");
222
+	btn = gtk_button_new_with_label(" F ");
223 223
 	gtk_box_pack_start (GTK_BOX(vb), btn, FALSE, FALSE, 10);
224
-	g_signal_connect(G_OBJECT(btn), "clicked", G_CALLBACK(button_D_clicked), ui);
224
+	g_signal_connect(G_OBJECT(btn), "clicked", G_CALLBACK(button_F_clicked), ui);
225
+	g_signal_connect(G_OBJECT(btn), "button-press-event", G_CALLBACK(button_F_pr), ui);
226
+	g_signal_connect(G_OBJECT(btn), "button-release-event", G_CALLBACK(button_F_pr), ui);
225 227
 
226 228
 	btn = gtk_button_new_with_label(" E ");
227 229
 	gtk_box_pack_start (GTK_BOX(vb), btn, FALSE, FALSE, 10);
228 230
 	g_signal_connect(G_OBJECT(btn), "clicked", G_CALLBACK(button_E_clicked), ui);
229 231
 
230
-	btn = gtk_button_new_with_label(" F ");
232
+	btn = gtk_button_new_with_label(" D ");
231 233
 	gtk_box_pack_start (GTK_BOX(vb), btn, FALSE, FALSE, 10);
232
-	g_signal_connect(G_OBJECT(btn), "clicked", G_CALLBACK(button_F_clicked), ui);
233
-	g_signal_connect(G_OBJECT(btn), "button-press-event", G_CALLBACK(button_F_pr), ui);
234
-	g_signal_connect(G_OBJECT(btn), "button-release-event", G_CALLBACK(button_F_pr), ui);
234
+	g_signal_connect(G_OBJECT(btn), "clicked", G_CALLBACK(button_D_clicked), ui);
235 235
 
236 236
 	ui->darea = gtk_drawing_area_new ();
237 237
 	gtk_box_pack_start (GTK_BOX(hb), GTK_WIDGET(ui->darea), FALSE, FALSE, 5);
... ...
@@ -323,13 +323,13 @@ static gboolean centisecond_tmo_handler (gpointer userdata)
323 323
 	return TRUE;
324 324
 }
325 325
 
326
-void enable_centisecond_timer(void)
326
+void hal_enable_centisecond_timer(void)
327 327
 {
328 328
 	ui_g->centisecond_active = TRUE;
329 329
 	g_timeout_add(10, centisecond_tmo_handler, ui_g);
330 330
 }
331 331
 
332
-void disable_centisecond_timer(void)
332
+void hal_disable_centisecond_timer(void)
333 333
 {
334 334
 	ui_g->centisecond_active = FALSE;
335 335
 }
... ...
@@ -346,17 +346,67 @@ static gboolean halfsecond_tmo_handler (gpointer userdata)
346 346
 	return TRUE;
347 347
 }
348 348
 
349
-void enable_halfsecond_timer(void)
349
+void hal_enable_halfsecond_timer(void)
350 350
 {
351 351
 	ui_g->halfsecond_active = TRUE;
352 352
 	g_timeout_add(500, halfsecond_tmo_handler, ui_g);
353 353
 }
354 354
 
355
-void disable_halfsecond_timer(void)
355
+void hal_disable_halfsecond_timer(void)
356 356
 {
357 357
 	ui_g->halfsecond_active = FALSE;
358 358
 }
359 359
 
360
+void hal_get_rtc(clock_state *rtc)
361
+{
362
+	time_t mt;
363
+	struct tm mtime;
364
+
365
+	mt = time(NULL);
366
+	localtime_r(&mt, &mtime);
367
+
368
+	rtc->hour = mtime.tm_hour;
369
+	rtc->minute = mtime.tm_min;
370
+	rtc->second = mtime.tm_sec;
371
+	rtc->day = mtime.tm_mday;
372
+	rtc->month = (mtime.tm_mon + 1);
373
+	rtc->year = (mtime.tm_year + 1900);
374
+}
375
+
376
+void hal_set_rtc(const clock_state *rtc, boolean set_set)
377
+{
378
+}
379
+
380
+void hal_get_power_state(power_state *pwr)
381
+{
382
+}
383
+
384
+static boolean BacklightState = FALSE;
385
+
386
+/* sets the backlight on/off, on=TRUE, off=FALSE */
387
+void hal_lcd_set_backlight(boolean state)
388
+{
389
+	g_print("turn LCD backlight %s\n", state ? "on" : "off");
390
+	BacklightState = state;
391
+}
392
+
393
+boolean hal_lcd_get_backlight(void)
394
+{
395
+	return BacklightState;
396
+}
397
+
398
+
399
+/* sets the vibration motor on/off, on=TRUE, off=FALSE */
400
+void hal_vibration_set_state(boolean state)
401
+{
402
+}
403
+
404
+boolean hal_vibration_get_state(void)
405
+{
406
+	return FALSE;
407
+}
408
+
409
+
360 410
 int main(int argc , char ** argv)
361 411
 {
362 412
 	oswald_ui ui;
... ...
@@ -1,5 +1,6 @@
1 1
 #ifndef _OSWALD_H
2 2
 #define _OSWALD_H
3
+#include <stdint.h>
3 4
 
4 5
 //#define DEBUG 1
5 6
 #ifdef DEBUG
... ...
@@ -30,20 +31,36 @@ typedef struct {
30 31
 	u8t	minute;
31 32
 	u8t	second;
32 33
 	u8t	day;
34
+	u8t	wday; // day in week, 0=sunday, 1=monday,...
33 35
 	u8t	month;
34 36
 	u16t	year;
35 37
 	boolean	clk24hr;
36 38
 	boolean day_first;
37 39
 } clock_state;
38 40
 
41
+#define WDAY_SUNDAY	(1 << 0)
42
+#define WDAY_MONDAY	(1 << 1)
43
+#define WDAY_TUESDAY	(1 << 2)
44
+#define WDAY_WEDNESDAY	(1 << 3)
45
+#define WDAY_THURSDAY	(1 << 4)
46
+#define WDAY_FRIDAY	(1 << 5)
47
+#define WDAY_SATURDAY	(1 << 6)
48
+typedef struct {
49
+	u8t	hour;
50
+	u8t	minute;
51
+	u8t	wday; // bitfield 0 to 6, 1=sunday, 2=monday, 4=tuesday...
52
+} alarm_clk;
53
+
39 54
 typedef enum {
40 55
 	IDLE_SCREEN = 0,
56
+	ALARM_SETUP_SCREEN,
57
+	STOP_WATCH_SCREEN,
41 58
 	ACCEL_DISPLAY_SCREEN,
42 59
 	MENU_TEST_SCREEN,
43
-	STOP_WATCH_SCREEN,
44 60
 //	APPLICATION_SCREEN,
45 61
 	LAST_SCREEN,		// a marker for the last (not valid) screen)
46 62
 	DATETIME_SETTING_SCREEN,
63
+	ALARM_SCREEN,
47 64
 	SCREENS_END,
48 65
 } screen_number;
49 66
 
... ...
@@ -66,6 +83,8 @@ typedef enum {
66 83
 #define EVENT_AMBIENTLIGHT_UPDATE	(1<<7)		// ambient light sensor updates
67 84
 #define EVENT_POWER_CHANGE		(1<<8)		// power source status change
68 85
 #define EVENT_COMMS			(1<<9)		// communication, like Bluetooth I/O
86
+#define EVENT_POWER_STATE		(1<<10)		// power source changed or similar
87
+
69 88
 
70 89
 typedef struct {
71 90
 	u16t event_mask;				// the event the screen wants to receive
... ...
@@ -85,5 +104,26 @@ typedef struct {
85 104
 	u8t	z;
86 105
 } accel_data_t;
87 106
 
88
-#endif
107
+#define POWER_SOURCE_BATTERY	0
108
+#define POWER_SOURCE_EXTERNAL	1
109
+
110
+#define POWER_CHARGER_DONE	0
111
+#define POWER_CHARGER_PRECHARGE	1
112
+#define POWER_CHARGER_CHARGING	2
113
+#define POWER_CHARGER_UNK	3
114
+
115
+typedef struct {
116
+	u8t	source;
117
+	u8t	charge_state;
118
+	u8t	percent;
119
+	u16t	level;
120
+} power_state;
89 121
 
122
+typedef enum {
123
+	BLUETOOTH_OFF = 0,
124
+	BLUETOOTH_ON,
125
+	BLUETOOTH_CONNECTED,
126
+	BLUETOOTH_ILL
127
+} bluetooth_state;
128
+
129
+#endif
... ...
@@ -5,7 +5,19 @@
5 5
 #include "oswald_graphics.h"
6 6
 
7 7
 
8
-void oswald_draw_Line(u8t xstart, u8t ystart, u8t xend, u8t yend)
8
+void oswald_draw_bitmap(const uint8_t xstart, const uint8_t ystart, const uint8_t width, const uint8_t height, const void *bmp)
9
+{
10
+	uint8_t x, y;
11
+
12
+	// we only draw set pixel, unset pixel remain as they are
13
+	for (y=0; y<height; y++) {
14
+		for (x=0; x<width; x++) {
15
+			hal_lcd_set_pixel(x, y, TRUE);
16
+		}
17
+	}
18
+}
19
+
20
+void oswald_draw_Line(uint8_t xstart, uint8_t ystart, uint8_t xend, uint8_t yend)
9 21
 {
10 22
 	int x, y, t, dx, dy, incx, incy, pdx, pdy, ddx, ddy, es, el, err;
11 23
  
... ...
@@ -33,7 +45,7 @@ void oswald_draw_Line(u8t xstart, u8t ystart, u8t xend, u8t yend)
33 45
 	x = xstart;
34 46
 	y = ystart;
35 47
 	err = el/2;
36
-	lcd_set_pixel(x, y, TRUE);
48
+	hal_lcd_set_pixel(x, y, TRUE);
37 49
  
38 50
 	for (t = 0; t < el; ++t) {
39 51
 		err -= es; 
... ...
@@ -45,9 +57,9 @@ void oswald_draw_Line(u8t xstart, u8t ystart, u8t xend, u8t yend)
45 57
 			x += pdx;
46 58
 			y += pdy;
47 59
 		}
48
-		lcd_set_pixel(x, y, TRUE);
60
+		hal_lcd_set_pixel(x, y, TRUE);
49 61
 	}
50
-	lcd_update_display();
62
+	hal_lcd_update_display();
51 63
 }
52 64
 
53 65
 void oswald_draw_line_ww(u8t xstart, u8t ystart, u8t xend, u8t yend, u8t thickness)
... ...
@@ -78,12 +90,12 @@ void oswald_draw_line_ww(u8t xstart, u8t ystart, u8t xend, u8t yend, u8t thickne
78 90
 	x = xstart;
79 91
 	y = ystart;
80 92
 	err = el/2;
81
-	lcd_set_pixel(x, y, TRUE);
93
+	hal_lcd_set_pixel(x, y, TRUE);
82 94
 	for (i=1; i<thickness; i++) {
83
-		lcd_set_pixel(x-i, y, TRUE);
84
-		lcd_set_pixel(x+i, y, TRUE);
85
-		lcd_set_pixel(x, y-i, TRUE);
86
-		lcd_set_pixel(x, y+i, TRUE);
95
+		hal_lcd_set_pixel(x-i, y, TRUE);
96
+		hal_lcd_set_pixel(x+i, y, TRUE);
97
+		hal_lcd_set_pixel(x, y-i, TRUE);
98
+		hal_lcd_set_pixel(x, y+i, TRUE);
87 99
 	}
88 100
  
89 101
 	for (t = 0; t < el; ++t) {
... ...
@@ -96,15 +108,15 @@ void oswald_draw_line_ww(u8t xstart, u8t ystart, u8t xend, u8t yend, u8t thickne
96 108
 			x += pdx;
97 109
 			y += pdy;
98 110
 		}
99
-		lcd_set_pixel(x, y, TRUE);
111
+		hal_lcd_set_pixel(x, y, TRUE);
100 112
 		for (i=1; i<thickness; i++) {
101
-			lcd_set_pixel(x-i, y, TRUE);
102
-			lcd_set_pixel(x+i, y, TRUE);
103
-			lcd_set_pixel(x, y-i, TRUE);
104
-			lcd_set_pixel(x, y+i, TRUE);
113
+			hal_lcd_set_pixel(x-i, y, TRUE);
114
+			hal_lcd_set_pixel(x+i, y, TRUE);
115
+			hal_lcd_set_pixel(x, y-i, TRUE);
116
+			hal_lcd_set_pixel(x, y+i, TRUE);
105 117
 		}
106 118
 	}
107
-	lcd_update_display();
119
+	hal_lcd_update_display();
108 120
 }
109 121
 
110 122
 u8t oswald_write_character(u8t x, u8t y, oswald_font_face face, u8t Character)
... ...
@@ -121,10 +133,10 @@ u8t oswald_write_character(u8t x, u8t y, oswald_font_face face, u8t Character)
121 133
 	for (ly=0; ly<CharacterHeight; ly++) {
122 134
 		for (lx=0; lx<CharacterWidth; lx++) {
123 135
 			if (bitmap[ly] & (1<<lx)) {
124
-				lcd_set_pixel(lx+x, ly+y, TRUE);
136
+				hal_lcd_set_pixel(lx+x, ly+y, TRUE);
125 137
 				// printf(".");
126 138
 			} else {
127
-				lcd_set_pixel(lx+x, ly+y, FALSE);
139
+				hal_lcd_set_pixel(lx+x, ly+y, FALSE);
128 140
 				// printf(" ");
129 141
 			}
130 142
 		}
... ...
@@ -8,7 +8,7 @@
8 8
 #include "oswald_graphics.h"
9 9
 
10 10
 
11
-void oswald_draw_Line(u8t xstart, u8t ystart, u8t xend, u8t yend);
11
+void oswald_draw_Line(uint8_t xstart, uint8_t ystart, uint8_t xend, uint8_t yend);
12 12
 
13 13
 void oswald_draw_line_ww(u8t xstart, u8t ystart, u8t xend, u8t yend, u8t thickness);
14 14
 
15 15
new file mode 100644
... ...
@@ -0,0 +1,30 @@
1
+#ifndef _oswald_hal_h
2
+#define _oswald_hal_h
3
+
4
+/*
5
+ * these functions must be implemented for a concrete hardware
6
+ */
7
+
8
+void hal_lcd_set_pixel(unsigned int x, unsigned int y, unsigned char state);
9
+void hal_lcd_clear_display(void);
10
+void hal_lcd_update_display(void);
11
+/* sets the backlight on/off, on=TRUE, off=FALSE */
12
+void hal_lcd_set_backlight(boolean state);
13
+boolean hal_lcd_get_backlight(void);
14
+
15
+void hal_enable_centisecond_timer(void);
16
+void hal_disable_centisecond_timer(void);
17
+
18
+void hal_enable_halfsecond_timer(void);
19
+void hal_disable_halfsecond_timer(void);
20
+
21
+void hal_get_rtc(clock_state *rtc);
22
+void hal_set_rtc(clock_state *rtc, boolean set_set);
23
+void hal_get_power_state(power_state *pwr);
24
+
25
+/* sets the vibration motor on/off, on=TRUE, off=FALSE */
26
+void hal_vibration_set_state(boolean state);
27
+boolean hal_vibration_get_state(void);
28
+
29
+#endif
30
+
... ...
@@ -1,6 +1,7 @@
1 1
 #include "oswald.h"
2 2
 #include "oswald_watch_faces.h"
3 3
 #include "oswald_screens.h"
4
+#include "oswald_hal.h"
4 5
 
5 6
 #include "embedvm.h"
6 7
 
... ...
@@ -12,9 +13,11 @@
12 13
  * through function calls thus saving stack space
13 14
  */
14 15
 clock_state OswaldClk;
16
+alarm_clk OswaldAlarm;
15 17
 watch_state OswaldState;
16 18
 watch_screen OswaldScreens[SCREENS_END];
17
-
19
+power_state OswaldPowerState;
20
+u8t backlight_safety_off = 0;
18 21
 
19 22
 void oswald_change_to_screen(screen_number screen_id)
20 23
 {
... ...
@@ -45,29 +48,33 @@ void oswald_set_date(u8t day, u8t month, u16t year, boolean day_first)
45 48
 
46 49
 static void update_clock_state (void)
47 50
 {
48
-	OswaldClk.second += 1;
49
-	if (OswaldClk.second > 59) {
50
-		OswaldClk.second = 0;
51
-		OswaldClk.minute += 1;
52
-	} else
53
-		return;
54
-	if (OswaldClk.minute > 59) {
55
-		OswaldClk.minute = 0;
56
-		OswaldClk.hour += 1;
57
-	} else
58
-		return;
59
-	if (OswaldClk.hour > 23) {
60
-		OswaldClk.hour = 0;
61
-		// day++
62
-	} else
63
-		return;
51
+	hal_get_rtc(&OswaldClk);
52
+
53
+	/* check for pending alarm once per minute */
54
+	if (OswaldClk.second == 0) {
55
+		if (OswaldClk.hour == OswaldAlarm.hour &&
56
+			OswaldClk.minute == OswaldAlarm.minute &&
57
+			((1 << OswaldClk.wday) & OswaldAlarm.wday)) {
58
+			OswaldState.screen->event_func(EVENT_SCREEN_DESTROY, NULL);
59
+			OswaldState.screen_id = ALARM_SCREEN;
60
+			OswaldState.screen = &OswaldScreens[OswaldState.screen_id];
61
+			OswaldState.screen->event_func(EVENT_SCREEN_VISIBLE, NULL);
62
+		}
63
+	}
64 64
 }
65 65
 
66 66
 void oswald_one_second_tick(void)
67 67
 {
68
-	/* update our 'RTC' */
68
+	/* update clock - should use RTC if available */
69 69
 	update_clock_state();
70 70
 
71
+	hal_get_power_state(&OswaldPowerState);
72
+	if (backlight_safety_off) {
73
+		backlight_safety_off--;
74
+		if (!backlight_safety_off)
75
+			hal_lcd_set_backlight(FALSE);
76
+	}
77
+
71 78
 	/* wake-up screen if interested in the one-second-event */
72 79
 	if (OswaldState.screen->event_func != NULL &&
73 80
 	    (OswaldState.screen->event_mask & EVENT_ONE_SEC_TIMER))
... ...
@@ -91,10 +98,20 @@ void oswald_halfsecond_tick(void)
91 98
 void oswald_handle_button_press(watch_button button)
92 99
 {
93 100
 	switch (button) {
101
+		case BUTTON_D:
102
+			// backlight on/off
103
+			if (hal_lcd_get_backlight()) {
104
+				hal_lcd_set_backlight(FALSE);
105
+				backlight_safety_off = 0;
106
+			} else {
107
+				hal_lcd_set_backlight(TRUE);
108
+				backlight_safety_off = 2;
109
+			}
110
+			break;
94 111
 		case BUTTON_A:
95 112
 		case BUTTON_B:
96
-		case BUTTON_D:
97 113
 		case BUTTON_E:
114
+		case BUTTON_F:
98 115
 			if (OswaldState.screen->event_func != NULL &&
99 116
 			    (OswaldState.screen->event_mask & EVENT_USER_BUTTONS))
100 117
 				OswaldState.screen->event_func(EVENT_USER_BUTTONS, &button);
... ...
@@ -109,9 +126,6 @@ void oswald_handle_button_press(watch_button button)
109 126
 			OswaldState.screen = &OswaldScreens[OswaldState.screen_id];
110 127
 			OswaldState.screen->event_func(EVENT_SCREEN_VISIBLE, NULL);
111 128
 			break;
112
-		case BUTTON_F:
113
-			// backlight on/off
114
-			break;
115 129
 		default:
116 130
 			// should never get here
117 131
 			break;
... ...
@@ -149,16 +163,26 @@ void oswald_init(void)
149 163
 	OswaldScreens[DATETIME_SETTING_SCREEN].event_mask = EVENT_USER_BUTTONS | EVENT_HALF_SEC_TIMER;
150 164
 	OswaldScreens[DATETIME_SETTING_SCREEN].event_func = datetime_setup_events;
151 165
 
166
+	OswaldScreens[ALARM_SETUP_SCREEN].event_mask = EVENT_USER_BUTTONS | EVENT_HALF_SEC_TIMER;
167
+	OswaldScreens[ALARM_SETUP_SCREEN].event_func = alarm_setup_events;
168
+
152 169
 	OswaldScreens[MENU_TEST_SCREEN].event_mask = EVENT_USER_BUTTONS;
153 170
 	OswaldScreens[MENU_TEST_SCREEN].event_func = test_menu_handle_events;
154 171
 
155 172
 	OswaldScreens[STOP_WATCH_SCREEN].event_mask = EVENT_USER_BUTTONS | EVENT_CS_TIMER;
156 173
 	OswaldScreens[STOP_WATCH_SCREEN].event_func = stop_watch_handle_events;
157 174
 
175
+	OswaldScreens[ALARM_SCREEN].event_mask = EVENT_USER_BUTTONS | EVENT_HALF_SEC_TIMER;
176
+	OswaldScreens[ALARM_SCREEN].event_func = alarm_handle_events;
177
+
158 178
 	OswaldState.screen_id = IDLE_SCREEN;
159 179
 	OswaldState.screen = &OswaldScreens[OswaldState.screen_id];
160 180
 
161 181
 	if (OswaldState.screen->event_func != NULL)
162 182
 		OswaldState.screen->event_func(EVENT_SCREEN_VISIBLE, NULL);
183
+
184
+	OswaldAlarm.hour = 12;
185
+	OswaldAlarm.minute = 0;
186
+	OswaldAlarm.wday = 0x00;
163 187
 }
164 188
 
... ...
@@ -4,6 +4,8 @@
4 4
 #include "oswald.h"
5 5
 
6 6
 extern clock_state OswaldClk;
7
+extern alarm_clk OswaldAlarm;
8
+extern power_state OswaldPowerState;
7 9
 extern watch_state OswaldState;
8 10
 extern watch_screen OswaldScreens[];
9 11
 
... ...
@@ -24,4 +26,3 @@ void oswald_centisecond_tick(void);
24 26
 void oswald_init(void);
25 27
 
26 28
 #endif
27
-
... ...
@@ -1,8 +1,11 @@
1
+#include <stdio.h>
2
+
1 3
 #include "oswald.h"
2 4
 #include "oswald_main.h"
3 5
 #include "oswald_watch_faces.h"
4 6
 #include "Fonts.h"
5 7
 #include "LcdDisplay.h"
8
+#include "oswald_hal.h"
6 9
 
7 10
 #include "oswald_screens.h"
8 11
 
... ...
@@ -14,7 +17,7 @@ typedef struct {
14 17
 } idle_data_t;
15 18
 static idle_data_t idle_screen = {
16 19
 	DrawLcdDigitalClock,
17
-	FALSE,
20
+	TRUE,
18 21
 	FALSE,
19 22
 };
20 23
  
... ...
@@ -36,7 +39,7 @@ void idle_handle_user_buttons(watch_button button)
36 39
 				idle_screen.screendraw_func = DrawLcdAnaClock;
37 40
 			};
38 41
 			break;
39
-		case BUTTON_D:
42
+		case BUTTON_F:
40 43
 			OswaldState.screen_id = DATETIME_SETTING_SCREEN;
41 44
 			OswaldState.screen = &OswaldScreens[OswaldState.screen_id];
42 45
 			OswaldState.screen->event_func(EVENT_SCREEN_VISIBLE, NULL);
... ...
@@ -74,7 +77,7 @@ static accelscreen_data_t accel_screen = {
74 77
 
75 78
 void draw_accel_screen(accel_data_t *accel_data)
76 79
 {
77
-	lcd_clear_display();
80
+	hal_lcd_clear_display();
78 81
 	SetFont(MetaWatch16);
79 82
 	WriteLcdString(2, 2, "X:");
80 83
 	WriteLcdNumber(20, 2, accel_data->x);
... ...
@@ -82,7 +85,7 @@ void draw_accel_screen(accel_data_t *accel_data)
82 85
 	WriteLcdNumber(20, 18, accel_data->y);
83 86
 	WriteLcdString(2, 34, "Z:");
84 87
 	WriteLcdNumber(20, 34, accel_data->z);
85
-	lcd_update_display();
88
+	hal_lcd_update_display();
86 89
 }
87 90
 
88 91
 void accel_handle_events(u16t event, void *data)
... ...
@@ -119,7 +122,7 @@ static datetime_setup_data_t dt_setup_screen = {
119 122
 
120 123
 void draw_datetime_setup_screen(datetime_setup_data_t *sdata)
121 124
 {
122
-	lcd_clear_display();
125
+	hal_lcd_clear_display();
123 126
 	SetFont(MetaWatch16);
124 127
 	WriteLcdString(2, 2, "Set");
125 128
 
... ...
@@ -172,7 +175,7 @@ void draw_datetime_setup_screen(datetime_setup_data_t *sdata)
172 175
 	}
173 176
 	WriteLcdString(15, 79, "dd.mm.  mm/dd");
174 177
 
175
-	lcd_update_display();
178
+	hal_lcd_update_display();
176 179
 }
177 180
 
178 181
 void datetime_handle_updown(u8t pos, s8t incr)
... ...
@@ -235,6 +238,10 @@ void datetime_handle_updown(u8t pos, s8t incr)
235 238
 		default:
236 239
 			break;
237 240
 	};
241
+	if (pos == 2)
242
+		hal_set_rtc(&OswaldClk, TRUE);
243
+	else
244
+		hal_set_rtc(&OswaldClk, FALSE);
238 245
 }
239 246
 
240 247
 void handle_setup_datetime_buttons(watch_button button, datetime_setup_data_t *sdata)
... ...
@@ -246,7 +253,7 @@ void handle_setup_datetime_buttons(watch_button button, datetime_setup_data_t *s
246 253
 		case BUTTON_B:
247 254
 			datetime_handle_updown(sdata->pos, -1);
248 255
 			break;
249
-		case BUTTON_D:
256
+		case BUTTON_F:
250 257
 			sdata->pos++;
251 258
 			sdata->pos %= 8;
252 259
 			break;
... ...
@@ -260,11 +267,12 @@ void datetime_setup_events(u16t event, void *data)
260 267
 {
261 268
 	switch (event) {
262 269
 		case EVENT_SCREEN_VISIBLE:
270
+			dt_setup_screen.pos = 0;
263 271
 			draw_datetime_setup_screen(&dt_setup_screen);
264
-			enable_halfsecond_timer();
272
+			hal_enable_halfsecond_timer();
265 273
 			break;
266 274
 		case EVENT_SCREEN_DESTROY:
267
-			disable_halfsecond_timer();
275
+			hal_disable_halfsecond_timer();
268 276
 			break;
269 277
 		case EVENT_USER_BUTTONS:
270 278
 			dbg_out("button event %d\n", *(int *)data);
... ...
@@ -282,6 +290,172 @@ void datetime_setup_events(u16t event, void *data)
282 290
 	};
283 291
 }
284 292
 
293
+typedef struct {
294
+	u8t pos;
295
+	boolean on;
296
+} alarm_setup_data_t;
297
+static alarm_setup_data_t alarm_setup_screen = {
298
+	0,
299
+	TRUE
300
+};
301
+
302
+void draw_alarm_setup_screen(alarm_setup_data_t *sdata)
303
+{
304
+	hal_lcd_clear_display();
305
+
306
+	SetFont(MetaWatch16);
307
+	WriteLcdString(2, 2, "Alarm");
308
+
309
+	SetFont(MetaWatchTime);
310
+	if ((sdata->pos == 0 && sdata->on) || sdata->pos != 0) {
311
+		WriteLcdCharacter(2, 20, (OswaldAlarm.hour / 10));
312
+		WriteLcdCharacter(14, 20, (OswaldAlarm.hour % 10));
313
+	}
314
+	WriteLcdCharacter(26, 20, TIME_CHARACTER_COLON_INDEX);
315
+
316
+	if ((sdata->pos == 1 && sdata->on) || sdata->pos != 1) {
317
+		WriteLcdCharacter(31, 20, (OswaldAlarm.minute / 10));
318
+		WriteLcdCharacter(43, 20, (OswaldAlarm.minute % 10));
319
+	}
320
+
321
+	SetFont(MetaWatchMonospaced10);
322
+	WriteLcdCharacter(3, 45, 'S');
323
+	WriteLcdCharacter(15, 45, 'M');
324
+	WriteLcdCharacter(27, 45, 'T');
325
+	WriteLcdCharacter(39, 45, 'W');
326
+	WriteLcdCharacter(51, 45, 'T');
327
+	WriteLcdCharacter(63, 45, 'F');
328
+	WriteLcdCharacter(75, 45, 'S');
329
+
330
+	if ((sdata->pos == 2 && sdata->on) || sdata->pos != 2)
331
+		WriteLcdCharacter(3, 55, (OswaldAlarm.wday & WDAY_SUNDAY) ? 'x' : '_');
332
+	if ((sdata->pos == 3 && sdata->on) || sdata->pos != 3)
333
+		WriteLcdCharacter(15, 55, (OswaldAlarm.wday & WDAY_MONDAY) ? 'x' : '_');
334
+	if ((sdata->pos == 4 && sdata->on) || sdata->pos != 4)
335
+		WriteLcdCharacter(27, 55, (OswaldAlarm.wday & WDAY_TUESDAY) ? 'x' : '_');
336
+	if ((sdata->pos == 5 && sdata->on) || sdata->pos != 5)
337
+		WriteLcdCharacter(39, 55, (OswaldAlarm.wday & WDAY_WEDNESDAY) ? 'x' : '_');
338
+	if ((sdata->pos == 6 && sdata->on) || sdata->pos != 6)
339
+		WriteLcdCharacter(51, 55, (OswaldAlarm.wday & WDAY_THURSDAY) ? 'x' : '_');
340
+	if ((sdata->pos == 7 && sdata->on) || sdata->pos != 7)
341
+		WriteLcdCharacter(63, 55, (OswaldAlarm.wday & WDAY_FRIDAY) ? 'x' : '_');
342
+	if ((sdata->pos == 8 && sdata->on) || sdata->pos != 8)
343
+		WriteLcdCharacter(75, 55, (OswaldAlarm.wday & WDAY_SATURDAY) ? 'x' : '_');
344
+
345
+#if 0
346
+	SetFont(MetaWatch7);
347
+	if ((sdata->pos == 6 && sdata->on) || sdata->pos != 6) {
348
+		if (OswaldClk.clk24hr)
349
+			WriteLcdString(2, 66, "x");
350
+		else
351
+			WriteLcdString(2, 66, "_");
352
+	}
353
+	WriteLcdString(15, 66, "24hr");
354
+
355
+	if ((sdata->pos == 7 && sdata->on) || sdata->pos != 7) {
356
+		if (OswaldClk.day_first)
357
+			WriteLcdString(2, 79, "x");
358
+		else
359
+			WriteLcdString(2, 79, "_");
360
+	}
361
+	WriteLcdString(15, 79, "dd.mm.  mm/dd");
362
+#endif
363
+	hal_lcd_update_display();
364
+}
365
+
366
+void alarm_handle_updown(u8t pos, s8t incr)
367
+{
368
+	switch (pos) {
369
+		case 0: // hour
370
+			if (OswaldAlarm.hour == 0 && incr == -1) {
371
+				OswaldAlarm.hour = 23;
372
+				break;
373
+			};
374
+			OswaldAlarm.hour += incr;
375
+			if (OswaldAlarm.hour > 23)
376
+				OswaldAlarm.hour = 0;
377
+			break;
378
+		case 1: // minute
379
+			if (OswaldAlarm.minute == 0 && incr == -1) {
380
+				OswaldAlarm.minute = 59;
381
+				break;
382
+			};
383
+			OswaldAlarm.minute += incr;
384
+			if (OswaldAlarm.minute > 59)
385
+				OswaldAlarm.minute = 0;
386
+			break;
387
+		case 2: // sunday
388
+			OswaldAlarm.wday ^= WDAY_SUNDAY;
389
+			break;
390
+		case 3: // monday
391
+			OswaldAlarm.wday ^= WDAY_MONDAY;
392
+			break;
393
+		case 4: // tuesday
394
+			OswaldAlarm.wday ^= WDAY_TUESDAY;
395
+			break;
396
+		case 5: // wednesday
397
+			OswaldAlarm.wday ^= WDAY_WEDNESDAY;
398
+			break;
399
+		case 6: // thursday
400
+			OswaldAlarm.wday ^= WDAY_THURSDAY;
401
+			break;
402
+		case 7: // friday
403
+			OswaldAlarm.wday ^= WDAY_FRIDAY;
404
+			break;
405
+		case 8: // saturday
406
+			OswaldAlarm.wday ^= WDAY_SATURDAY;
407
+			break;
408
+		default:
409
+			break;
410
+	};
411
+}
412
+
413
+void handle_setup_alarm_buttons(watch_button button, alarm_setup_data_t *sdata)
414
+{
415
+	switch (button) {
416
+		case BUTTON_A:
417
+			alarm_handle_updown(sdata->pos, 1);
418
+			break;
419
+		case BUTTON_B:
420
+			alarm_handle_updown(sdata->pos, -1);
421
+			break;
422
+		case BUTTON_F:
423
+			sdata->pos++;
424
+			sdata->pos %= 9;
425
+			break;
426
+		default:
427
+			break;
428
+	}
429
+	draw_alarm_setup_screen(sdata);
430
+}
431
+
432
+void alarm_setup_events(u16t event, void *data)
433
+{
434
+	switch (event) {
435
+		case EVENT_SCREEN_VISIBLE:
436
+			alarm_setup_screen.pos = 0;
437
+			draw_alarm_setup_screen(&alarm_setup_screen);
438
+			hal_enable_halfsecond_timer();
439
+			break;
440
+		case EVENT_SCREEN_DESTROY:
441
+			hal_disable_halfsecond_timer();
442
+			break;
443
+		case EVENT_USER_BUTTONS:
444
+			dbg_out("button event %d\n", *(int *)data);
445
+			handle_setup_alarm_buttons(*(watch_button *)data, &alarm_setup_screen);
446
+			break;
447
+		case EVENT_HALF_SEC_TIMER:
448
+			if (alarm_setup_screen.on)
449
+				alarm_setup_screen.on = FALSE;
450
+			else
451
+				alarm_setup_screen.on = TRUE;
452
+			draw_alarm_setup_screen(&alarm_setup_screen);
453
+			break;
454
+		default:
455
+			break;
456
+	};
457
+}
458
+
285 459
 
286 460
 typedef struct {
287 461
 	u8t menu_pos;
... ...
@@ -290,7 +464,7 @@ static test_menu_t test_menu = { 0 };
290 464
 
291 465
 void draw_menu_test_screen(void)
292 466
 {
293
-	lcd_clear_display();
467
+	hal_lcd_clear_display();
294 468
 	SetFont(MetaWatch16);
295 469
 	WriteLcdString(2, 2, "Menu");
296 470
 	SetFont(MetaWatch7);
... ...
@@ -301,7 +475,7 @@ void draw_menu_test_screen(void)
301 475
 	WriteLcdString(2, 56, "Item 5");
302 476
 
303 477
 	WriteLcdString(50, 20+(9*test_menu.menu_pos), "*");
304
-	lcd_update_display();
478
+	hal_lcd_update_display();
305 479
 }
306 480
 
307 481
 static void handle_menu_user_buttons(watch_button button)
... ...
@@ -354,8 +528,10 @@ static stopwatch_data_t stopwatch_screen = { 0, 0, 0, 0, 0, 0, 0, 0, FALSE };
354 528
 
355 529
 static void update_stop_watch_screen(stopwatch_data_t *sdata)
356 530
 {
531
+	char tstr[16];
357 532
 	SetFont(MetaWatchMonospaced10);
358 533
 
534
+#if 0
359 535
 	WriteLcdNumber(0, 30, sdata->hr);
360 536
 	WriteLcdCharacter(14, 30, ':');
361 537
 	WriteLcdNumber(19, 30, sdata->min);
... ...
@@ -371,8 +547,14 @@ static void update_stop_watch_screen(stopwatch_data_t *sdata)
371 547
 	WriteLcdNumber(38, 50, sdata->lapse_sec);
372 548
 	WriteLcdCharacter(52, 50, '.');
373 549
 	WriteLcdNumber(57, 50, sdata->lapse_csec / 10);
374
-
375
-	lcd_update_display();
550
+#else
551
+	snprintf(tstr, 16, "%02d:%02d:%02d.%1d", sdata->hr, sdata->min, sdata->sec, sdata->csec / 10);
552
+	WriteLcdString(0, 30, tstr);
553
+	snprintf(tstr, 16, "%02d:%02d:%02d.%02d", sdata->lapse_hr, sdata->lapse_min, sdata->lapse_sec, sdata->lapse_csec);
554
+	WriteLcdString(0, 50, tstr);
555
+#endif
556
+
557
+	hal_lcd_update_display();
376 558
 }
377 559
 
378 560
 static void draw_stop_watch_screen(stopwatch_data_t *sdata)
... ...
@@ -388,10 +570,10 @@ static void handle_stop_watch_buttons(watch_button button)
388 570
 	switch (button) {
389 571
 		case BUTTON_A: // start/stop
390 572
 			if (stopwatch_screen.running) {
391
-				disable_centisecond_timer();
573
+				hal_disable_centisecond_timer();
392 574
 				stopwatch_screen.running = FALSE;
393 575
 			} else {
394
-				enable_centisecond_timer();
576
+				hal_enable_centisecond_timer();
395 577
 				stopwatch_screen.running = TRUE;
396 578
 			}
397 579
 			break;
... ...
@@ -401,7 +583,7 @@ static void handle_stop_watch_buttons(watch_button button)
401 583
 			stopwatch_screen.lapse_sec = stopwatch_screen.sec;
402 584
 			stopwatch_screen.lapse_csec = stopwatch_screen.csec;
403 585
 			break;
404
-		case BUTTON_D: // reset
586
+		case BUTTON_F: // reset
405 587
 			stopwatch_screen.hr = 0;
406 588
 			stopwatch_screen.min = 0;
407 589
 			stopwatch_screen.sec = 0;
... ...
@@ -425,11 +607,11 @@ void stop_watch_handle_events(u16t event, void *data)
425 607
 			update_stop_watch_screen(&stopwatch_screen);
426 608
 			break;
427 609
 		case EVENT_SCREEN_VISIBLE:
428
-			lcd_clear_display();
610
+			hal_lcd_clear_display();
429 611
 			draw_stop_watch_screen(&stopwatch_screen);
430 612
 			break;
431 613
 		case EVENT_SCREEN_DESTROY:
432
-			disable_centisecond_timer();
614
+			hal_disable_centisecond_timer();
433 615
 			stopwatch_screen.running = FALSE;
434 616
 			break;
435 617
 		case EVENT_CS_TIMER:
... ...
@@ -456,3 +638,42 @@ void stop_watch_handle_events(u16t event, void *data)
456 638
 			break;
457 639
 	};
458 640
 }
641
+
642
+
643
+void draw_alarm_screen(void)
644
+{
645
+	hal_lcd_clear_display();
646
+
647
+	SetFont(MetaWatch16);
648
+	WriteLcdString(2, 2, "ALARM !");
649
+
650
+	hal_lcd_update_display();
651
+}
652
+
653
+void alarm_handle_events(u16t event, void *data)
654
+{
655
+	switch (event) {
656
+		case EVENT_SCREEN_VISIBLE:
657
+			draw_alarm_screen();
658
+			hal_enable_halfsecond_timer();
659
+			hal_vibration_set_state(TRUE);
660
+			break;
661
+		case EVENT_SCREEN_DESTROY:
662
+			hal_disable_halfsecond_timer();
663
+			hal_lcd_set_backlight(FALSE);
664
+			hal_vibration_set_state(FALSE);
665
+			break;
666
+		case EVENT_USER_BUTTONS:
667
+			dbg_out("button event %d\n", *(int *)data);
668
+			// hal_lcd_set_backlight(FALSE);
669
+			break;
670
+		case EVENT_HALF_SEC_TIMER:
671
+			hal_lcd_set_backlight(!hal_lcd_get_backlight());
672
+			hal_vibration_set_state(!hal_vibration_get_state());
673
+			dbg_out("timer\n");
674
+			break;
675
+		default:
676
+			break;
677
+	};
678
+}
679
+
... ...
@@ -8,9 +8,13 @@ void accel_handle_events(u16t event, void *data);
8 8
 
9 9
 void datetime_setup_events(u16t event, void *data);
10 10
 
11
+void alarm_setup_events(u16t event, void *data);
12
+
11 13
 void test_menu_handle_events(u16t event, void *data);
12 14
 
13 15
 void stop_watch_handle_events(u16t event, void *data);
14 16
 
17
+void alarm_handle_events(u16t event, void *data);
18
+
15 19
 #endif
16 20
 
... ...
@@ -1,89 +1,203 @@
1
-#include <math.h>
1
+#include <stdio.h>
2
+#include <stdint.h>
2 3
 
3 4
 #include "oswald.h"
4 5
 #include "oswald_main.h"
5
-#include "oswald-ui.h"
6 6
 #include "Fonts.h"
7 7
 #include "LcdDisplay.h"
8
+#include "oswald_hal.h"
8 9
 
9 10
 #include "oswald_watch_faces.h"
10 11
 
12
+int16_t sintab[]={
13
+	    0,   2,   3,   5,   7,   9,  10,  12,  14,  16,
14
+	   17,  19,  21,  22,  24,  26,  28,  29,  31,  33,
15
+	   34,  36,  37,  39,  41,  42,  44,  45,  47,  48,
16
+	   50,  52,  53,  54,  56,  57,  59,  60,  62,  63,
17
+	   64,  66,  67,  68,  69,  71,  72,  73,  74,  75,
18
+	   77,  78,  79,  80,  81,  82,  83,  84,  85,  86,
19
+	   87,  87,  88,  89,  90,  91,  91,  92,  93,  93,
20
+	   94,  95,  95,  96,  96,  97,  97,  97,  98,  98,
21
+	   98,  99,  99,  99,  99, 100, 100, 100, 100, 100,
22
+	  100, 100, 100, 100, 100, 100,  99,  99,  99,  99,
23
+	   98,  98,  98,  97,  97,  97,  96,  96,  95,  95,
24
+	   94,  93,  93,  92,  91,  91,  90,  89,  88,  87,
25
+	   87,  86,  85,  84,  83,  82,  81,  80,  79,  78,
26
+	   77,  75,  74,  73,  72,  71,  69,  68,  67,  66,
27
+	   64,  63,  62,  60,  59,  57,  56,  54,  53,  52,
28
+	   50,  48,  47,  45,  44,  42,  41,  39,  37,  36,
29
+	   34,  33,  31,  29,  28,  26,  24,  22,  21,  19,
30
+	   17,  16,  14,  12,  10,   9,   7,   5,   3,   2,
31
+	    0,  -2,  -3,  -5,  -7,  -9, -10, -12, -14, -16,
32
+	  -17, -19, -21, -22, -24, -26, -28, -29, -31, -33,
33
+	  -34, -36, -37, -39, -41, -42, -44, -45, -47, -48,
34
+	  -50, -52, -53, -54, -56, -57, -59, -60, -62, -63,
35
+	  -64, -66, -67, -68, -69, -71, -72, -73, -74, -75,
36
+	  -77, -78, -79, -80, -81, -82, -83, -84, -85, -86,
37
+	  -87, -87, -88, -89, -90, -91, -91, -92, -93, -93,
38
+	  -94, -95, -95, -96, -96, -97, -97, -97, -98, -98,
39
+	  -98, -99, -99, -99, -99,-100,-100,-100,-100,-100,
40
+	 -100,-100,-100,-100,-100,-100, -99, -99, -99, -99,
41
+	  -98, -98, -98, -97, -97, -97, -96, -96, -95, -95,
42
+	  -94, -93, -93, -92, -91, -91, -90, -89, -88, -87,
43
+	  -87, -86, -85, -84, -83, -82, -81, -80, -79, -78,
44
+	  -77, -75, -74, -73, -72, -71, -69, -68, -67, -66,
45
+	  -64, -63, -62, -60, -59, -57, -56, -54, -53, -52,
46
+	  -50, -48, -47, -45, -44, -42, -41, -39, -37, -36,
47
+	  -34, -33, -31, -29, -28, -26, -24, -22, -21, -19,
48
+	  -17, -16, -14, -12, -10,  -9,  -7,  -5,  -3,  -2
49
+};
50
+
51
+int16_t f_sin(int16_t v)
52
+{
53
+	v %= 360;
54
+	return sintab[v];
55
+}
56
+
57
+int16_t f_cos(int16_t v)
58
+{
59
+	v += 90;
60
+	v %= 360;
61
+	return sintab[v];
62
+}
63
+
11 64
 void DrawLcdAnaClock(boolean show_seconds)
12 65
 {
13
-	//unsigned char *bbuf;
14
-	//char daystr[5];
15
-	//int len;
16
-	int i, x, y, x2, y2;
17
-	double tmp, mf;
18
-	s8t hour, minute, seconds;
66
+	int16_t i, x, y, x2, y2;
67
+	int16_t tmp;
68
+	int8_t hour, minute, seconds;
69
+	char tstr[16];
19 70
 
20 71
 	hour = OswaldClk.hour;
21 72
 	minute = OswaldClk.minute;
22 73
 	seconds = OswaldClk.second;
23 74
 
24 75
 	hour -= 3;
25
-	mf = (1. / 59.) * (double)minute;
76
+	if (hour < 0)
77
+		hour += 12;
78
+	// mf = (1. / 59.) * (double)minute;
26 79
 	minute -= 15;
80
+	if (minute < 0)
81
+		minute += 60;
27 82
 	seconds -= 15;
83
+	if (seconds < 0)
84
+		seconds += 60;
28 85
 
29
-	lcd_clear_display();
86
+	hal_lcd_clear_display();
87
+
88
+	SetFont(MetaWatch16);
89
+	snprintf(tstr, 16, "%02d", OswaldClk.day);
90
+	WriteLcdString(70, 40, tstr);
30 91
 
31 92
 	// plot(R*cos(360° * i/N), R*sin(360° * i/N))
32 93
 	for (i=0; i<12; i++) {
33
-		tmp = 48. + (43. * cos(((2. * M_PI) / 12.) * (double)i));
94
+		tmp = 48 + ((43 * f_cos((360 / 12) * i)) / 100);
34 95
 		x =  tmp;
35
-		tmp = 48 + (43. * sin(((2. * M_PI) / 12.) * (double)i));
96
+		tmp = 48 + ((43 * f_sin((360 / 12) * i)) / 100);
36 97
 		y =  tmp;
37
-		tmp = 48. + (48. * cos(((2. * M_PI) / 12.) * (double)i));
98
+		tmp = 48 + ((48 * f_cos((360 / 12) * i)) / 100);
38 99
 		x2 =  tmp;
39
-		tmp = 48 + (48. * sin(((2. * M_PI) / 12.) * (double)i));
100
+		tmp = 48 + ((48 * f_sin((360 / 12) * i)) / 100);
40 101
 		y2 =  tmp;
41 102
 		DrawLcdLineBresenhamWW(x, y, x2, y2, 2);
42 103
 	};
104
+
43 105
 	// Hour
44
-	tmp = 48. + (30. * cos(((2. * M_PI) / 12.) * ((double)hour + mf)));
106
+	tmp = 48 + (30 * f_cos(((360 / 12) * hour) + ((OswaldClk.minute * 360) /12 / 60)) / 100);
45 107
 	x =  tmp;
46
-	tmp = 48 + (30. * sin(((2. * M_PI) / 12.) * ((double)hour + mf)));
108
+	tmp = 48 + (30 * f_sin(((360 / 12) * hour) + ((OswaldClk.minute * 360) /12 / 60)) / 100);
47 109
 	y =  tmp;
48 110
 	DrawLcdLineBresenhamWW(48, 48, x, y, 2);
49 111
 	// Minute
50
-	tmp = 48. + (40. * cos(((2. * M_PI) / 60.) * (double)minute));
112
+	tmp = 48 + ((40 * f_cos((360 / 60) * minute)) / 100);
51 113
 	x =  tmp;
52
-	tmp = 48 + (40. * sin(((2. * M_PI) / 60.) * (double)minute));
114
+	tmp = 48 + ((40 * f_sin((360 / 60) * minute)) / 100);
53 115
 	y =  tmp;
54 116
 	DrawLcdLineBresenhamWW(48, 48, x, y, 2);
55 117
 	if (show_seconds) {
56 118
 		// Seconds
57
-		tmp = 48. + (40. * cos(((2. * M_PI) / 60.) * (double)seconds));
119
+		tmp = 48 + ((40 * f_cos((360 / 60) * seconds)) / 100);
58 120
 		x =  tmp;
59
-		tmp = 48 + (40. * sin(((2. * M_PI) / 60.) * (double)seconds));
121
+		tmp = 48 + ((40 * f_sin((360 / 60) * seconds)) / 100);
60 122
 		y =  tmp;
61 123
 		DrawLcdLineBresenham(48, 48, x, y);
62 124
 	};
63 125
 
64
-	//snprintf(daystr, 5, "%d", day);
65
-	// mw_buf_print(mwbuf, 74, 45, daystr, 0, MW_WHITE, MW_BLACK);
66
-	lcd_update_display();
126
+	hal_lcd_update_display();
67 127
 }
68 128
 
69 129
 void DrawLcdDigitalClock(boolean show_seconds)
70 130
 {
71 131
 	int gRow = 3;
72
-	int gColumn = 4;
132
+	int gColumn = 3;
133
+	char tstr[16];
73 134
 
74 135
 	SetFont(MetaWatchTime);
75 136
 
76
-	lcd_clear_display();
137
+	hal_lcd_clear_display();
77 138
 	//gRow += WriteLcdCharacter(ui, gRow, gColumn, TIME_CHARACTER_SPACE_INDEX);
78
-	gRow += WriteLcdCharacter(gRow, gColumn, (OswaldClk.hour / 10));
79
-	gRow += WriteLcdCharacter(gRow, gColumn, (OswaldClk.hour % 10));
139
+	if (OswaldClk.clk24hr) {
140
+		gRow += WriteLcdCharacter(gRow, gColumn, (OswaldClk.hour / 10));
141
+		gRow += WriteLcdCharacter(gRow, gColumn, (OswaldClk.hour % 10));
142
+	} else {
143
+		unsigned char val = OswaldClk.hour;
144
+		if (val > 12)
145
+			val -= 12;
146
+		gRow += WriteLcdCharacter(gRow, gColumn, (val / 10));
147
+		gRow += WriteLcdCharacter(gRow, gColumn, (val % 10));
148
+	}
80 149
 	gRow += WriteLcdCharacter(gRow, gColumn, TIME_CHARACTER_COLON_INDEX);
81 150
 	gRow += WriteLcdCharacter(gRow, gColumn, (OswaldClk.minute / 10));
82 151
 	gRow += WriteLcdCharacter(gRow, gColumn, (OswaldClk.minute % 10));
152
+
153
+	gRow += 3;
83 154
 	if (show_seconds) {
84
-		gRow += WriteLcdCharacter(gRow, gColumn, TIME_CHARACTER_COLON_INDEX);
85
-		gRow += WriteLcdCharacter(gRow, gColumn, (OswaldClk.second / 10));
86
-		gRow += WriteLcdCharacter(gRow, gColumn, (OswaldClk.second % 10));
155
+		SetFont(MetaWatch16);
156
+		snprintf(tstr, 16, "%02d", OswaldClk.second);
157
+		WriteLcdString(gRow, 9, tstr);
87 158
 	};
88
-	lcd_update_display();
159
+
160
+	SetFont(MetaWatch7);
161
+
162
+	if (!OswaldClk.clk24hr) {
163
+		if (OswaldClk.hour > 12) {
164
+			WriteLcdString(gRow, 3, "PM");
165
+		} else {
166
+			WriteLcdString(gRow, 3, "AM");
167
+		}
168
+	}
169
+
170
+	SetFont(MetaWatch16);
171
+
172
+	if (OswaldClk.day_first)
173
+		snprintf(tstr, 16, "%d.%d.%d", OswaldClk.day, OswaldClk.month, OswaldClk.year);
174
+	else
175
+		snprintf(tstr, 16, "%d/%d %d", OswaldClk.month, OswaldClk.day, OswaldClk.year);
176
+	WriteLcdString(3, 25, tstr);
177
+
178
+	snprintf(tstr, 16, "%d%% (%dmV)", OswaldPowerState.percent, OswaldPowerState.level);
179
+	WriteLcdString(2, 48, tstr);
180
+	WriteLcdString(2, 64, OswaldPowerState.source ? "ext" : "bat");
181
+
182
+	/* this makes only sense when the charger is active */
183
+	if (OswaldPowerState.source) {
184
+		switch (OswaldPowerState.charge_state) {
185
+			case POWER_CHARGER_DONE:
186
+				WriteLcdString(2, 80, "charge done");
187
+				break;
188
+			case POWER_CHARGER_PRECHARGE:
189
+				WriteLcdString(2, 80, "precharging");
190
+				break;
191
+			case POWER_CHARGER_CHARGING:
192
+				WriteLcdString(2, 80, "charging");
193
+				break;
194
+			case POWER_CHARGER_UNK:
195
+				WriteLcdString(2, 80, "charge unkn.");
196
+				break;
197
+			default:
198
+				break;
199
+		};
200
+	};
201
+	hal_lcd_update_display();
89 202
 }
203
+