]> git.karo-electronics.de Git - oswald.git/commitdiff
Oh boy... lots of changes, too many to describe
authorNils Faerber <nils.faerber@kernelconcepts.de>
Sun, 21 Apr 2013 14:26:38 +0000 (16:26 +0200)
committerNils Faerber <nils.faerber@kernelconcepts.de>
Sun, 21 Apr 2013 14:26:38 +0000 (16:26 +0200)
16 files changed:
ui/Fonts.c
ui/LcdDisplay.c
ui/LcdDisplay.h
ui/Makefile.am
ui/calendar.c [new file with mode: 0644]
ui/calendar.h [new file with mode: 0644]
ui/oswald-ui.c
ui/oswald.h
ui/oswald_graphics.c
ui/oswald_graphics.h
ui/oswald_hal.h [new file with mode: 0644]
ui/oswald_main.c
ui/oswald_main.h
ui/oswald_screens.c
ui/oswald_screens.h
ui/oswald_watch_faces.c

index 54929ce5776b9ca991afdaf2c4d559106764b6da..f6083db36228b92725adbf30f864e5e77304936a 100644 (file)
 /*! The number of printable characters in the font tables */
 #define PRINTABLE_CHARACTERS ( 94 )
 
+#if defined(__GNUC__) && (__MSP430X__ > 0)
+__attribute__((__far__))
+#endif
 const unsigned char MetaWatch5table[PRINTABLE_CHARACTERS][5];
+#if defined(__GNUC__) && (__MSP430X__ > 0)
+__attribute__((__far__))
+#endif
 const unsigned char MetaWatch7table[PRINTABLE_CHARACTERS][7];
+#if defined(__GNUC__) && (__MSP430X__ > 0)
+__attribute__((__far__))
+#endif
 const u16t MetaWatch16table[PRINTABLE_CHARACTERS][16];
+#if defined(__GNUC__) && (__MSP430X__ > 0)
+__attribute__((__far__))
+#endif
 const u16t MetaWatchTimeTable[TOTAL_TIME_CHARACTERS][19];
+#if defined(__GNUC__) && (__MSP430X__ > 0)
+__attribute__((__far__))
+#endif
 const unsigned char MetaWatchMonospaced10Table[PRINTABLE_CHARACTERS][10];
 
+#if defined(__GNUC__) && (__MSP430X__ > 0)
+__attribute__((__far__))
+#endif
 const unsigned char MetaWatch5width[PRINTABLE_CHARACTERS];
+#if defined(__GNUC__) && (__MSP430X__ > 0)
+__attribute__((__far__))
+#endif
 const unsigned char MetaWatch7width[PRINTABLE_CHARACTERS];
+#if defined(__GNUC__) && (__MSP430X__ > 0)
+__attribute__((__far__))
+#endif
 const unsigned char MetaWatch16width[PRINTABLE_CHARACTERS];
+#if defined(__GNUC__) && (__MSP430X__ > 0)
+__attribute__((__far__))
+#endif
 const unsigned char MetaWatchTimeWidth[TOTAL_TIME_CHARACTERS];
 
 /*! Font Structure
@@ -189,6 +216,9 @@ void GetCharacterBitmap(unsigned char Character, u16t *pBitmap)
 
 }
 
+#if defined(__GNUC__) && (__MSP430X__ > 0)
+__attribute__((__far__))
+#endif
 const unsigned char MetaWatch5table[PRINTABLE_CHARACTERS][5] = 
 {
   /* character 0x20 (' '): (width = 2) */
@@ -474,6 +504,9 @@ const unsigned char MetaWatch5table[PRINTABLE_CHARACTERS][5] =
   0x00, 0x00, 0x00, 0x00, 0x00,},
 };
 
+#if defined(__GNUC__) && (__MSP430X__ > 0)
+__attribute__((__far__))
+#endif
 const unsigned char MetaWatch5width[PRINTABLE_CHARACTERS] = 
 {
 /*             width    char    hexcode */
@@ -574,6 +607,9 @@ const unsigned char MetaWatch5width[PRINTABLE_CHARACTERS] =
                  3, /*   }      7D      */
 };
 
+#if defined(__GNUC__) && (__MSP430X__ > 0)
+__attribute__((__far__))
+#endif
 const unsigned char MetaWatch7table[PRINTABLE_CHARACTERS][7] = 
 {
 
@@ -860,6 +896,9 @@ const unsigned char MetaWatch7table[PRINTABLE_CHARACTERS][7] =
 
 };
 
+#if defined(__GNUC__) && (__MSP430X__ > 0)
+__attribute__((__far__))
+#endif
 const unsigned char MetaWatch7width[PRINTABLE_CHARACTERS] = {
 /*             width    char    hexcode */
 /*             =====    ====    ======= */
@@ -960,6 +999,9 @@ const unsigned char MetaWatch7width[PRINTABLE_CHARACTERS] = {
 };
 
 
+#if defined(__GNUC__) && (__MSP430X__ > 0)
+__attribute__((__far__))
+#endif
 const u16t MetaWatch16table[PRINTABLE_CHARACTERS][16] = 
 {
   /* character 0x20 (' '): (width=4) */
@@ -1526,6 +1568,9 @@ const u16t MetaWatch16table[PRINTABLE_CHARACTERS][16] =
   0x0006, 0x0002, 0x0001, 0x0000},
 };
 
+#if defined(__GNUC__) && (__MSP430X__ > 0)
+__attribute__((__far__))
+#endif
 const unsigned char MetaWatch16width[PRINTABLE_CHARACTERS] = 
 {
 /*             width    char    hexcode */
@@ -1627,6 +1672,9 @@ const unsigned char MetaWatch16width[PRINTABLE_CHARACTERS] =
 };
 
 /******************************************************************************/
+#if defined(__GNUC__) && (__MSP430X__ > 0)
+__attribute__((__far__))
+#endif
 const u16t MetaWatchTimeTable[TOTAL_TIME_CHARACTERS][19] = 
 {
   /* character 0x30 ('0'): (width=11, offset=0) */
@@ -1714,6 +1762,9 @@ const u16t MetaWatchTimeTable[TOTAL_TIME_CHARACTERS][19] =
   0x0000, 0x0000, 0x0000},
 };
 
+#if defined(__GNUC__) && (__MSP430X__ > 0)
+__attribute__((__far__))
+#endif
 const unsigned char MetaWatchTimeWidth[TOTAL_TIME_CHARACTERS] = 
 {
 /*             width    char    hexcode */
@@ -1734,6 +1785,9 @@ const unsigned char MetaWatchTimeWidth[TOTAL_TIME_CHARACTERS] =
 
 /******************************************************************************/
 
+#if defined(__GNUC__) && (__MSP430X__ > 0)
+__attribute__((__far__))
+#endif
 const unsigned char MetaWatchMonospaced10Table[PRINTABLE_CHARACTERS][10] =  
 {
   {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
index dbf775fbf4b6da665017c0391f15d35a682568a3..f889bbc4ba7b7b118f95ff2212fd5379a090831d 100644 (file)
@@ -1,4 +1,5 @@
-#include "oswald-ui.h"
+#include "oswald.h"
+#include "oswald_hal.h"
 #include "oswald_strings.h"
 #include "Fonts.h"
 
@@ -32,7 +33,7 @@ void DrawLcdLineBresenham(u8t xstart, u8t ystart, u8t xend, u8t yend)
        x = xstart;
        y = ystart;
        err = el/2;
-       lcd_set_pixel(x, y, TRUE);
+       hal_lcd_set_pixel(x, y, TRUE);
  
        for (t = 0; t < el; ++t) {
                err -= es; 
@@ -44,7 +45,7 @@ void DrawLcdLineBresenham(u8t xstart, u8t ystart, u8t xend, u8t yend)
                        x += pdx;
                        y += pdy;
                }
-               lcd_set_pixel(x, y, TRUE);
+               hal_lcd_set_pixel(x, y, TRUE);
        }
        // lcd_update_display();
 }
@@ -77,12 +78,12 @@ void DrawLcdLineBresenhamWW(u8t xstart, u8t ystart, u8t xend, u8t yend, u8t thic
        x = xstart;
        y = ystart;
        err = el/2;
-       lcd_set_pixel(x, y, TRUE);
+       hal_lcd_set_pixel(x, y, TRUE);
        for (i=1; i<thickness; i++) {
-               lcd_set_pixel(x-i, y, TRUE);
-               lcd_set_pixel(x+i, y, TRUE);
-               lcd_set_pixel(x, y-i, TRUE);
-               lcd_set_pixel(x, y+i, TRUE);
+               hal_lcd_set_pixel(x-i, y, TRUE);
+               hal_lcd_set_pixel(x+i, y, TRUE);
+               hal_lcd_set_pixel(x, y-i, TRUE);
+               hal_lcd_set_pixel(x, y+i, TRUE);
        }
  
        for (t = 0; t < el; ++t) {
@@ -95,12 +96,12 @@ void DrawLcdLineBresenhamWW(u8t xstart, u8t ystart, u8t xend, u8t yend, u8t thic
                        x += pdx;
                        y += pdy;
                }
-               lcd_set_pixel(x, y, TRUE);
+               hal_lcd_set_pixel(x, y, TRUE);
                for (i=1; i<thickness; i++) {
-                       lcd_set_pixel(x-i, y, TRUE);
-                       lcd_set_pixel(x+i, y, TRUE);
-                       lcd_set_pixel(x, y-i, TRUE);
-                       lcd_set_pixel(x, y+i, TRUE);
+                       hal_lcd_set_pixel(x-i, y, TRUE);
+                       hal_lcd_set_pixel(x+i, y, TRUE);
+                       hal_lcd_set_pixel(x, y-i, TRUE);
+                       hal_lcd_set_pixel(x, y+i, TRUE);
                }
        }
        // lcd_update_display();
@@ -119,10 +120,10 @@ u8t WriteLcdCharacter(u8t x, u8t y, u8t Character)
        for (ly=0; ly<CharacterHeight; ly++) {
                for (lx=0; lx<CharacterWidth; lx++) {
                        if (bitmap[ly] & (1<<lx)) {
-                               lcd_set_pixel(lx+x, ly+y, TRUE);
+                               hal_lcd_set_pixel(lx+x, ly+y, TRUE);
                                // printf(".");
                        } else {
-                               lcd_set_pixel(lx+x, ly+y, FALSE);
+                               hal_lcd_set_pixel(lx+x, ly+y, FALSE);
                                // printf(" ");
                        }
                }
@@ -132,18 +133,19 @@ u8t WriteLcdCharacter(u8t x, u8t y, u8t Character)
        return CharacterWidth + GetFontSpacing();
 }
 
-void WriteLcdString(u8t x, u8t y, char *str)
+u8t WriteLcdString(u8t x, u8t y, char *str)
 {
        int lx, i, strl;
 
        strl = oswald_strlen(str);
        if (strl == 0)
-               return;
+               return 0;
 
        lx = x;
        for (i=0; i<strl; i++) {
                lx += WriteLcdCharacter(lx, y, str[i]);
        }
+       return lx;
 }
 
 
index d06583d16109931189ed43caab06a99ff9905bd0..e2725c921b53a1d6dd08b66d5ef5dbc1fee87c4a 100644 (file)
@@ -1,12 +1,12 @@
 #ifndef _LcdDisplay_h
 #define _LcdDisplay_h
 
-#include "oswald-ui.h"
+// #include "oswald_hal.h"
 
 void DrawLcdLineBresenham(u8t xstart, u8t ystart, u8t xend, u8t yend);
 void DrawLcdLineBresenhamWW(u8t xstart, u8t ystart, u8t xend, u8t yend, u8t thickness);
 u8t WriteLcdCharacter(u8t x, u8t y, u8t Character);
-void WriteLcdString(u8t x, u8t y, char *str);
+u8t WriteLcdString(u8t x, u8t y, char *str);
 void WriteLcdNumber(u8t x, u8t y, s16t number);
 
 #endif
index 25f606d4bb44dedc63fc8126d71028d2fe62a284..81f11b3588a19325014316707dafb327b11873ff 100644 (file)
@@ -3,7 +3,7 @@ ACLOCAL_AMFLAGS = -I m4
 bin_PROGRAMS = oswald-gui
 
 oswald_gui_SOURCES = oswald-ui.c LcdDisplay.c Fonts.c oswald_main.c oswald_watch_faces.c oswald_strings.c oswald_screens.c \
-embedvm.c oswald_fonts.c oswald_graphics.c
+embedvm.c oswald_fonts.c oswald_graphics.c calendar.c
 oswald_gui_CFLAGS = -g $(GTK_CFLAGS)
 oswald_gui_LDADD = $(GTK_LIBS)
 
diff --git a/ui/calendar.c b/ui/calendar.c
new file mode 100644 (file)
index 0000000..6271e12
--- /dev/null
@@ -0,0 +1,208 @@
+#include "oswald.h"
+
+#include "calendar.h"
+
+unsigned char is_leap(const unsigned int year)
+{
+  // Die Regel lautet: Alles, was durch 4 teilbar ist, ist ein Schaltjahr.
+  // Es sei denn, das Jahr ist durch 100 teilbar, dann ist es keins.
+  // Aber wenn es durch 400 teilbar ist, ist es doch wieder eins.
+
+       if ((year % 400) == 0)
+               return 1;
+       else if ((year % 100) == 0)
+               return 0;
+       else if ((year % 4) == 0)
+               return 1;
+
+       return 0;
+}
+
+unsigned short days_of_month(const unsigned int uMonat, const unsigned int uJahr)
+{
+       //                     ungült,Jan,Feb,Mrz,Apr,Mai,Jun,Jul,Aug,Sep,Okt,Nov,Dez
+       int arrTageImMonat[13] = {  0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
+
+       if (uMonat == 2) {
+               // Februar: Schaltjahr unterscheiden
+               if (is_leap(uJahr))
+                       return 29;
+               else
+                       return 28;
+       }
+
+       if ((uMonat >= 1) && (uMonat <= 12))
+               return arrTageImMonat[uMonat];
+       else {
+               return 0;
+       }
+}
+
+short getAnzahlTageImJahr(const unsigned int uJahr)
+{
+       return (is_leap(uJahr)) ? 366 : 365;
+}
+
+short getWochentag(const unsigned int uTag, const unsigned int uMonat, const unsigned int uJahr)
+{
+       //                       ungült Jan Feb Mrz Apr Mai Jun Jul Aug Sep Okt Nov Dez 
+       unsigned char arrMonatsOffset[13] = {  0,  0,  3,  3,  6,  1,  4,  6,  2,  5,  0,  3,  5};
+       short nErgebnis = 0;
+
+       // Monat / Tag - Plausi prüfen:
+       if ((uTag > 31) || (uMonat > 12) || (uMonat <= 0) 
+               || (uTag <= 0) || (uJahr <= 0)) {
+               return -1;
+       }
+
+       unsigned char cbTagesziffer = (uTag % 7);
+       unsigned char cbMonatsziffer = arrMonatsOffset[uMonat];
+       unsigned char cbJahresziffer = ((uJahr % 100) + ((uJahr % 100) / 4)) % 7;
+       unsigned char cbJahrhundertziffer = (3 - ((uJahr / 100) % 4)) * 2;
+
+       // Schaltjahreskorrektur:
+       if ((uMonat <= 2) && (is_leap(uJahr)))
+               cbTagesziffer = cbTagesziffer + 6;
+  
+       nErgebnis = (cbTagesziffer + cbMonatsziffer + cbJahresziffer + cbJahrhundertziffer) % 7;
+
+       // Ergebnis:
+       // 0 = Sonntag
+       // 1 = Montag
+       // 2 = Dienstag
+       // 3 = Mittwoch
+       // 4 = Donnerstag
+       // 5 = Freitag
+       // 6 = Samstag
+       return nErgebnis;
+}
+
+short getTagDesJahres(const unsigned int uTag, const unsigned int uMonat, const unsigned int uJahr)
+{
+       // Der wievielte Tag des Jahres ist dieser Tag
+       if ((uMonat == 0) || (uMonat > 12)) {
+               return -1;
+       }
+
+       unsigned int uLokalTag = uTag;
+       unsigned int uLokalMonat = uMonat;
+
+       while (uLokalMonat > 1) {
+               uLokalMonat--;
+               uLokalTag += days_of_month(uLokalMonat, uJahr);
+       }
+
+       return uLokalTag;
+}
+
+short getKalenderwoche(short uTag, short uMonat, short uJahr)
+{
+       // Berechnung erfolgt analog DIN 1355, welche besagt:
+       // Der erste Donnerstag im neuen Jahr liegt immer in der KW 1.
+       // "Woche" ist dabei definiert als [Mo, ..., So].
+       short nTagDesJahres = getTagDesJahres(uTag, uMonat, uJahr);
+
+       // Berechnen des Wochentags des 1. Januar:
+       short nWochentag1Jan = getWochentag(1, 1, uJahr);
+
+       // Sonderfälle Freitag und Samstag
+       if (nWochentag1Jan >= 5) 
+               nWochentag1Jan = nWochentag1Jan - 7;
+
+       // Sonderfälle "Jahresanfang mit KW - Nummer aus dem Vorjahr"
+       if ( (nTagDesJahres + nWochentag1Jan) <= 1) {
+               return getKalenderwoche(31, 12, uJahr - 1);
+       }
+
+       short nKalenderWoche = ((nTagDesJahres + nWochentag1Jan + 5) / 7);
+
+       // 53 Kalenderwochen hat grundsätzlich nur ein Jahr, 
+       // welches mit einem Donnerstag anfängt !
+       // In Schaltjahren ist es auch mit einem Mittwoch möglich, z.B. 1992
+       // Andernfalls ist diese KW schon die KW1 des Folgejahres.
+       if (nKalenderWoche == 53) {
+               boolean bIstSchaltjahr = is_leap(uJahr);
+
+               if ((nWochentag1Jan  ==  4) // Donnerstag
+                       ||  (nWochentag1Jan  == -3) // auch Donnerstag
+                       ||  ((nWochentag1Jan ==  3) && bIstSchaltjahr)
+                       ||  ((nWochentag1Jan == -4) && bIstSchaltjahr)) {
+                       ; // Das ist korrekt und erlaubt
+               } else
+                       nKalenderWoche = 1; // Korrektur des Wertes
+       }
+
+       return nKalenderWoche;
+}
+
+void getOsterdatum(const unsigned int uJahr, unsigned int *uTag, unsigned int *uMonat)
+{
+       // Berechnet für ein beliebiges Jahr das Osterdatum.
+
+       // Quelle des Gauss - Algorithmus: Stefan Gerth, 
+       // "Die Gauß'sche Osterregel", Nürnberg, Februar 2003. 
+       // http://krapfen.org/content/paper/Schule/Facharbeit/Berechnung_des_Osterfestes.pdf
+
+       unsigned int a = uJahr % 19;
+       unsigned int b = uJahr %  4;
+       unsigned int c = uJahr %  7;
+
+       int k = uJahr / 100;
+       int q = k / 4;
+       int p = ((8 * k) + 13) / 25;
+       unsigned int Egz = (38 - (k - q) + p) % 30; // Die Jahrhundertepakte
+       unsigned int M = (53 - Egz) % 30;
+       unsigned int N = (4 + k - q) % 7;
+
+       unsigned int d = ((19 * a) + M) % 30;
+       unsigned int e = ((2 * b) + (4 * c) + (6 * d) + N) % 7;
+
+       // Ausrechnen des Ostertermins:
+       if ((22 + d + e) <= 31) {
+               *uTag = 22 + d + e;
+               *uMonat = 3;
+       } else {
+               *uTag = d + e - 9;
+               *uMonat = 4;
+
+               // Zwei Ausnahmen berücksichtigen:
+               if (*uTag == 26)
+                       *uTag = 19;
+               else if ((*uTag == 25) && (d == 28) && (a > 10))
+                       *uTag = 18;
+       }
+
+       // Offsets für andere Feiertage:
+
+       // Schwerdonnerstag / Weiberfastnacht -52
+       // Rosenmontag -48
+       // Fastnachtsdienstag -47
+       // Aschermittwoch -46
+       // Gründonnerstag -3
+       // Karfreitag -2
+       // Ostersonntag 0
+       // Ostermontag +1
+       // Christi Himmelfahrt +39
+       // Pfingstsonntag +49
+       // Pfingstmontag +50
+       // Fronleichnam +60
+
+       // Mariä Himmelfahrt ist stets am 15. August (Danke an Michael Plugge!)
+}
+
+void getViertenAdvent(const unsigned int uJahr, unsigned int *uTag, unsigned int *uMonat)
+{
+       // Berechnet für ein beliebiges Jahr das Datum des 4. Advents-Sonntags.
+       // Der 4. Adventssonntag ist stets der Sonntag vor dem 1. Weihnachtsfeiertag,
+       // muß also stets in der Periode [18. - 24.12.] liegen:
+  
+       *uMonat = 12; // Das steht jedes Jahr fest :-)
+  
+       short nWoTag = getWochentag(24, 12, uJahr); // Wochentag des 24.12. ermitteln
+  
+       *uTag = 24 - nWoTag;
+
+       // Offsets: Der Buß- und Bettag liegt stets 32 Tage vor dem  4. Advent
+}
+
+
diff --git a/ui/calendar.h b/ui/calendar.h
new file mode 100644 (file)
index 0000000..636085f
--- /dev/null
@@ -0,0 +1,21 @@
+#ifndef _CALENDAR_H
+#define _CALENDAR_H
+
+unsigned char is_leap(const unsigned int year);
+
+unsigned short days_of_month(const unsigned int uMonat, const unsigned int uJahr);
+
+short getAnzahlTageImJahr(const unsigned int uJahr);
+
+short getWochentag(const unsigned int uTag, const unsigned int uMonat, const unsigned int uJahr);
+
+short getTagDesJahres(const unsigned int uTag, const unsigned int uMonat, const unsigned int uJahr);
+
+short getKalenderwoche(short uTag, short uMonat, short uJahr);
+
+void getOsterdatum(const unsigned int uJahr, unsigned int *uTag, unsigned int *uMonat);
+
+void getViertenAdvent(const unsigned int uJahr, unsigned int *uTag, unsigned int *uMonat);
+
+#endif
+
index ff88ff927396839d972d035ec1cbb60be32ea998..e86f0e1593bc9a930d3bf8aa1be13e3009f01685 100644 (file)
@@ -23,7 +23,7 @@
 
 static oswald_ui *ui_g;
 
-void lcd_set_pixel(gint x, gint y, gboolean state)
+void hal_lcd_set_pixel(gint x, gint y, gboolean state)
 {
        gint ix, iy;
 
@@ -39,12 +39,12 @@ void lcd_set_pixel(gint x, gint y, gboolean state)
 }
 
 /* updates the actual LCD so that drawing becomes visible */
-void lcd_update_display(void)
+void hal_lcd_update_display(void)
 {
        gtk_widget_queue_draw(ui_g->darea);
 }
 
-void lcd_clear_display(void)
+void hal_lcd_clear_display(void)
 {
        gdk_draw_rectangle (ui_g->pixmap,
                ui_g->darea->style->white_gc,
@@ -219,19 +219,19 @@ static void create_mainwin(oswald_ui *ui)
        vb = gtk_vbox_new(FALSE, 5);
        gtk_box_pack_start (GTK_BOX(hb), vb, FALSE, FALSE, 5);
 
-       btn = gtk_button_new_with_label(" D ");
+       btn = gtk_button_new_with_label(" F ");
        gtk_box_pack_start (GTK_BOX(vb), btn, FALSE, FALSE, 10);
-       g_signal_connect(G_OBJECT(btn), "clicked", G_CALLBACK(button_D_clicked), ui);
+       g_signal_connect(G_OBJECT(btn), "clicked", G_CALLBACK(button_F_clicked), ui);
+       g_signal_connect(G_OBJECT(btn), "button-press-event", G_CALLBACK(button_F_pr), ui);
+       g_signal_connect(G_OBJECT(btn), "button-release-event", G_CALLBACK(button_F_pr), ui);
 
        btn = gtk_button_new_with_label(" E ");
        gtk_box_pack_start (GTK_BOX(vb), btn, FALSE, FALSE, 10);
        g_signal_connect(G_OBJECT(btn), "clicked", G_CALLBACK(button_E_clicked), ui);
 
-       btn = gtk_button_new_with_label(" F ");
+       btn = gtk_button_new_with_label(" D ");
        gtk_box_pack_start (GTK_BOX(vb), btn, FALSE, FALSE, 10);
-       g_signal_connect(G_OBJECT(btn), "clicked", G_CALLBACK(button_F_clicked), ui);
-       g_signal_connect(G_OBJECT(btn), "button-press-event", G_CALLBACK(button_F_pr), ui);
-       g_signal_connect(G_OBJECT(btn), "button-release-event", G_CALLBACK(button_F_pr), ui);
+       g_signal_connect(G_OBJECT(btn), "clicked", G_CALLBACK(button_D_clicked), ui);
 
        ui->darea = gtk_drawing_area_new ();
        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)
        return TRUE;
 }
 
-void enable_centisecond_timer(void)
+void hal_enable_centisecond_timer(void)
 {
        ui_g->centisecond_active = TRUE;
        g_timeout_add(10, centisecond_tmo_handler, ui_g);
 }
 
-void disable_centisecond_timer(void)
+void hal_disable_centisecond_timer(void)
 {
        ui_g->centisecond_active = FALSE;
 }
@@ -346,17 +346,67 @@ static gboolean halfsecond_tmo_handler (gpointer userdata)
        return TRUE;
 }
 
-void enable_halfsecond_timer(void)
+void hal_enable_halfsecond_timer(void)
 {
        ui_g->halfsecond_active = TRUE;
        g_timeout_add(500, halfsecond_tmo_handler, ui_g);
 }
 
-void disable_halfsecond_timer(void)
+void hal_disable_halfsecond_timer(void)
 {
        ui_g->halfsecond_active = FALSE;
 }
 
+void hal_get_rtc(clock_state *rtc)
+{
+       time_t mt;
+       struct tm mtime;
+
+       mt = time(NULL);
+       localtime_r(&mt, &mtime);
+
+       rtc->hour = mtime.tm_hour;
+       rtc->minute = mtime.tm_min;
+       rtc->second = mtime.tm_sec;
+       rtc->day = mtime.tm_mday;
+       rtc->month = (mtime.tm_mon + 1);
+       rtc->year = (mtime.tm_year + 1900);
+}
+
+void hal_set_rtc(const clock_state *rtc, boolean set_set)
+{
+}
+
+void hal_get_power_state(power_state *pwr)
+{
+}
+
+static boolean BacklightState = FALSE;
+
+/* sets the backlight on/off, on=TRUE, off=FALSE */
+void hal_lcd_set_backlight(boolean state)
+{
+       g_print("turn LCD backlight %s\n", state ? "on" : "off");
+       BacklightState = state;
+}
+
+boolean hal_lcd_get_backlight(void)
+{
+       return BacklightState;
+}
+
+
+/* sets the vibration motor on/off, on=TRUE, off=FALSE */
+void hal_vibration_set_state(boolean state)
+{
+}
+
+boolean hal_vibration_get_state(void)
+{
+       return FALSE;
+}
+
+
 int main(int argc , char ** argv)
 {
        oswald_ui ui;
index 9a341e38e2d1a9d9dc6a68f0308825bcf3b5bbcf..31ee5cd33a0aa71a3b6e6371d5850ae560022346 100644 (file)
@@ -1,5 +1,6 @@
 #ifndef _OSWALD_H
 #define _OSWALD_H
+#include <stdint.h>
 
 //#define DEBUG 1
 #ifdef DEBUG
@@ -30,20 +31,36 @@ typedef struct {
        u8t     minute;
        u8t     second;
        u8t     day;
+       u8t     wday; // day in week, 0=sunday, 1=monday,...
        u8t     month;
        u16t    year;
        boolean clk24hr;
        boolean day_first;
 } clock_state;
 
+#define WDAY_SUNDAY    (1 << 0)
+#define WDAY_MONDAY    (1 << 1)
+#define WDAY_TUESDAY   (1 << 2)
+#define WDAY_WEDNESDAY (1 << 3)
+#define WDAY_THURSDAY  (1 << 4)
+#define WDAY_FRIDAY    (1 << 5)
+#define WDAY_SATURDAY  (1 << 6)
+typedef struct {
+       u8t     hour;
+       u8t     minute;
+       u8t     wday; // bitfield 0 to 6, 1=sunday, 2=monday, 4=tuesday...
+} alarm_clk;
+
 typedef enum {
        IDLE_SCREEN = 0,
+       ALARM_SETUP_SCREEN,
+       STOP_WATCH_SCREEN,
        ACCEL_DISPLAY_SCREEN,
        MENU_TEST_SCREEN,
-       STOP_WATCH_SCREEN,
 //     APPLICATION_SCREEN,
        LAST_SCREEN,            // a marker for the last (not valid) screen)
        DATETIME_SETTING_SCREEN,
+       ALARM_SCREEN,
        SCREENS_END,
 } screen_number;
 
@@ -66,6 +83,8 @@ typedef enum {
 #define EVENT_AMBIENTLIGHT_UPDATE      (1<<7)          // ambient light sensor updates
 #define EVENT_POWER_CHANGE             (1<<8)          // power source status change
 #define EVENT_COMMS                    (1<<9)          // communication, like Bluetooth I/O
+#define EVENT_POWER_STATE              (1<<10)         // power source changed or similar
+
 
 typedef struct {
        u16t event_mask;                                // the event the screen wants to receive
@@ -85,5 +104,26 @@ typedef struct {
        u8t     z;
 } accel_data_t;
 
-#endif
+#define POWER_SOURCE_BATTERY   0
+#define POWER_SOURCE_EXTERNAL  1
+
+#define POWER_CHARGER_DONE     0
+#define POWER_CHARGER_PRECHARGE        1
+#define POWER_CHARGER_CHARGING 2
+#define POWER_CHARGER_UNK      3
+
+typedef struct {
+       u8t     source;
+       u8t     charge_state;
+       u8t     percent;
+       u16t    level;
+} power_state;
 
+typedef enum {
+       BLUETOOTH_OFF = 0,
+       BLUETOOTH_ON,
+       BLUETOOTH_CONNECTED,
+       BLUETOOTH_ILL
+} bluetooth_state;
+
+#endif
index 36894abeb49a842c8ffb5da326bafe86ef37d6c3..a6eb14f9dfd50191705b71c4c4d0e3198f4a8e55 100644 (file)
@@ -5,7 +5,19 @@
 #include "oswald_graphics.h"
 
 
-void oswald_draw_Line(u8t xstart, u8t ystart, u8t xend, u8t yend)
+void oswald_draw_bitmap(const uint8_t xstart, const uint8_t ystart, const uint8_t width, const uint8_t height, const void *bmp)
+{
+       uint8_t x, y;
+
+       // we only draw set pixel, unset pixel remain as they are
+       for (y=0; y<height; y++) {
+               for (x=0; x<width; x++) {
+                       hal_lcd_set_pixel(x, y, TRUE);
+               }
+       }
+}
+
+void oswald_draw_Line(uint8_t xstart, uint8_t ystart, uint8_t xend, uint8_t yend)
 {
        int x, y, t, dx, dy, incx, incy, pdx, pdy, ddx, ddy, es, el, err;
  
@@ -33,7 +45,7 @@ void oswald_draw_Line(u8t xstart, u8t ystart, u8t xend, u8t yend)
        x = xstart;
        y = ystart;
        err = el/2;
-       lcd_set_pixel(x, y, TRUE);
+       hal_lcd_set_pixel(x, y, TRUE);
  
        for (t = 0; t < el; ++t) {
                err -= es; 
@@ -45,9 +57,9 @@ void oswald_draw_Line(u8t xstart, u8t ystart, u8t xend, u8t yend)
                        x += pdx;
                        y += pdy;
                }
-               lcd_set_pixel(x, y, TRUE);
+               hal_lcd_set_pixel(x, y, TRUE);
        }
-       lcd_update_display();
+       hal_lcd_update_display();
 }
 
 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
        x = xstart;
        y = ystart;
        err = el/2;
-       lcd_set_pixel(x, y, TRUE);
+       hal_lcd_set_pixel(x, y, TRUE);
        for (i=1; i<thickness; i++) {
-               lcd_set_pixel(x-i, y, TRUE);
-               lcd_set_pixel(x+i, y, TRUE);
-               lcd_set_pixel(x, y-i, TRUE);
-               lcd_set_pixel(x, y+i, TRUE);
+               hal_lcd_set_pixel(x-i, y, TRUE);
+               hal_lcd_set_pixel(x+i, y, TRUE);
+               hal_lcd_set_pixel(x, y-i, TRUE);
+               hal_lcd_set_pixel(x, y+i, TRUE);
        }
  
        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
                        x += pdx;
                        y += pdy;
                }
-               lcd_set_pixel(x, y, TRUE);
+               hal_lcd_set_pixel(x, y, TRUE);
                for (i=1; i<thickness; i++) {
-                       lcd_set_pixel(x-i, y, TRUE);
-                       lcd_set_pixel(x+i, y, TRUE);
-                       lcd_set_pixel(x, y-i, TRUE);
-                       lcd_set_pixel(x, y+i, TRUE);
+                       hal_lcd_set_pixel(x-i, y, TRUE);
+                       hal_lcd_set_pixel(x+i, y, TRUE);
+                       hal_lcd_set_pixel(x, y-i, TRUE);
+                       hal_lcd_set_pixel(x, y+i, TRUE);
                }
        }
-       lcd_update_display();
+       hal_lcd_update_display();
 }
 
 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)
        for (ly=0; ly<CharacterHeight; ly++) {
                for (lx=0; lx<CharacterWidth; lx++) {
                        if (bitmap[ly] & (1<<lx)) {
-                               lcd_set_pixel(lx+x, ly+y, TRUE);
+                               hal_lcd_set_pixel(lx+x, ly+y, TRUE);
                                // printf(".");
                        } else {
-                               lcd_set_pixel(lx+x, ly+y, FALSE);
+                               hal_lcd_set_pixel(lx+x, ly+y, FALSE);
                                // printf(" ");
                        }
                }
index 45c9941d3a7db31458e4126e1a57919750d0348c..3d5d6bdc00ed785b29edf3393396388e58972c64 100644 (file)
@@ -8,7 +8,7 @@
 #include "oswald_graphics.h"
 
 
-void oswald_draw_Line(u8t xstart, u8t ystart, u8t xend, u8t yend);
+void oswald_draw_Line(uint8_t xstart, uint8_t ystart, uint8_t xend, uint8_t yend);
 
 void oswald_draw_line_ww(u8t xstart, u8t ystart, u8t xend, u8t yend, u8t thickness);
 
diff --git a/ui/oswald_hal.h b/ui/oswald_hal.h
new file mode 100644 (file)
index 0000000..eddef94
--- /dev/null
@@ -0,0 +1,30 @@
+#ifndef _oswald_hal_h
+#define _oswald_hal_h
+
+/*
+ * these functions must be implemented for a concrete hardware
+ */
+
+void hal_lcd_set_pixel(unsigned int x, unsigned int y, unsigned char state);
+void hal_lcd_clear_display(void);
+void hal_lcd_update_display(void);
+/* sets the backlight on/off, on=TRUE, off=FALSE */
+void hal_lcd_set_backlight(boolean state);
+boolean hal_lcd_get_backlight(void);
+
+void hal_enable_centisecond_timer(void);
+void hal_disable_centisecond_timer(void);
+
+void hal_enable_halfsecond_timer(void);
+void hal_disable_halfsecond_timer(void);
+
+void hal_get_rtc(clock_state *rtc);
+void hal_set_rtc(clock_state *rtc, boolean set_set);
+void hal_get_power_state(power_state *pwr);
+
+/* sets the vibration motor on/off, on=TRUE, off=FALSE */
+void hal_vibration_set_state(boolean state);
+boolean hal_vibration_get_state(void);
+
+#endif
+
index 15091a6e7229d6e95e410ca8cd3c7c216d20682e..e080a7130aee0a0716809031ac66f12ac0ad8d30 100644 (file)
@@ -1,6 +1,7 @@
 #include "oswald.h"
 #include "oswald_watch_faces.h"
 #include "oswald_screens.h"
+#include "oswald_hal.h"
 
 #include "embedvm.h"
 
  * through function calls thus saving stack space
  */
 clock_state OswaldClk;
+alarm_clk OswaldAlarm;
 watch_state OswaldState;
 watch_screen OswaldScreens[SCREENS_END];
-
+power_state OswaldPowerState;
+u8t backlight_safety_off = 0;
 
 void oswald_change_to_screen(screen_number screen_id)
 {
@@ -45,29 +48,33 @@ void oswald_set_date(u8t day, u8t month, u16t year, boolean day_first)
 
 static void update_clock_state (void)
 {
-       OswaldClk.second += 1;
-       if (OswaldClk.second > 59) {
-               OswaldClk.second = 0;
-               OswaldClk.minute += 1;
-       } else
-               return;
-       if (OswaldClk.minute > 59) {
-               OswaldClk.minute = 0;
-               OswaldClk.hour += 1;
-       } else
-               return;
-       if (OswaldClk.hour > 23) {
-               OswaldClk.hour = 0;
-               // day++
-       } else
-               return;
+       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 our 'RTC' */
+       /* 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))
@@ -91,10 +98,20 @@ void oswald_halfsecond_tick(void)
 void oswald_handle_button_press(watch_button button)
 {
        switch (button) {
+               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;
                case BUTTON_A:
                case BUTTON_B:
-               case BUTTON_D:
                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);
@@ -109,9 +126,6 @@ void oswald_handle_button_press(watch_button button)
                        OswaldState.screen = &OswaldScreens[OswaldState.screen_id];
                        OswaldState.screen->event_func(EVENT_SCREEN_VISIBLE, NULL);
                        break;
-               case BUTTON_F:
-                       // backlight on/off
-                       break;
                default:
                        // should never get here
                        break;
@@ -149,16 +163,26 @@ void oswald_init(void)
        OswaldScreens[DATETIME_SETTING_SCREEN].event_mask = EVENT_USER_BUTTONS | EVENT_HALF_SEC_TIMER;
        OswaldScreens[DATETIME_SETTING_SCREEN].event_func = datetime_setup_events;
 
+       OswaldScreens[ALARM_SETUP_SCREEN].event_mask = EVENT_USER_BUTTONS | EVENT_HALF_SEC_TIMER;
+       OswaldScreens[ALARM_SETUP_SCREEN].event_func = alarm_setup_events;
+
        OswaldScreens[MENU_TEST_SCREEN].event_mask = EVENT_USER_BUTTONS;
        OswaldScreens[MENU_TEST_SCREEN].event_func = test_menu_handle_events;
 
        OswaldScreens[STOP_WATCH_SCREEN].event_mask = EVENT_USER_BUTTONS | EVENT_CS_TIMER;
        OswaldScreens[STOP_WATCH_SCREEN].event_func = stop_watch_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;
 }
 
index 28c5691538c23664b0ff84dd08bcac488f6f1dd2..57e8008c7cd8fd20b3278353f76cffb63a9350d1 100644 (file)
@@ -4,6 +4,8 @@
 #include "oswald.h"
 
 extern clock_state OswaldClk;
+extern alarm_clk OswaldAlarm;
+extern power_state OswaldPowerState;
 extern watch_state OswaldState;
 extern watch_screen OswaldScreens[];
 
@@ -24,4 +26,3 @@ void oswald_centisecond_tick(void);
 void oswald_init(void);
 
 #endif
-
index cbe29564a5b439b0e2d6cd4fd3b16702769c2c84..c09958fd2c6635d99f2486f9e3e917dabb326e5e 100644 (file)
@@ -1,8 +1,11 @@
+#include <stdio.h>
+
 #include "oswald.h"
 #include "oswald_main.h"
 #include "oswald_watch_faces.h"
 #include "Fonts.h"
 #include "LcdDisplay.h"
+#include "oswald_hal.h"
 
 #include "oswald_screens.h"
 
@@ -14,7 +17,7 @@ typedef struct {
 } idle_data_t;
 static idle_data_t idle_screen = {
        DrawLcdDigitalClock,
-       FALSE,
+       TRUE,
        FALSE,
 };
  
@@ -36,7 +39,7 @@ void idle_handle_user_buttons(watch_button button)
                                idle_screen.screendraw_func = DrawLcdAnaClock;
                        };
                        break;
-               case BUTTON_D:
+               case BUTTON_F:
                        OswaldState.screen_id = DATETIME_SETTING_SCREEN;
                        OswaldState.screen = &OswaldScreens[OswaldState.screen_id];
                        OswaldState.screen->event_func(EVENT_SCREEN_VISIBLE, NULL);
@@ -74,7 +77,7 @@ static accelscreen_data_t accel_screen = {
 
 void draw_accel_screen(accel_data_t *accel_data)
 {
-       lcd_clear_display();
+       hal_lcd_clear_display();
        SetFont(MetaWatch16);
        WriteLcdString(2, 2, "X:");
        WriteLcdNumber(20, 2, accel_data->x);
@@ -82,7 +85,7 @@ void draw_accel_screen(accel_data_t *accel_data)
        WriteLcdNumber(20, 18, accel_data->y);
        WriteLcdString(2, 34, "Z:");
        WriteLcdNumber(20, 34, accel_data->z);
-       lcd_update_display();
+       hal_lcd_update_display();
 }
 
 void accel_handle_events(u16t event, void *data)
@@ -119,7 +122,7 @@ static datetime_setup_data_t dt_setup_screen = {
 
 void draw_datetime_setup_screen(datetime_setup_data_t *sdata)
 {
-       lcd_clear_display();
+       hal_lcd_clear_display();
        SetFont(MetaWatch16);
        WriteLcdString(2, 2, "Set");
 
@@ -172,7 +175,7 @@ void draw_datetime_setup_screen(datetime_setup_data_t *sdata)
        }
        WriteLcdString(15, 79, "dd.mm.  mm/dd");
 
-       lcd_update_display();
+       hal_lcd_update_display();
 }
 
 void datetime_handle_updown(u8t pos, s8t incr)
@@ -235,6 +238,10 @@ void datetime_handle_updown(u8t pos, s8t incr)
                default:
                        break;
        };
+       if (pos == 2)
+               hal_set_rtc(&OswaldClk, TRUE);
+       else
+               hal_set_rtc(&OswaldClk, FALSE);
 }
 
 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
                case BUTTON_B:
                        datetime_handle_updown(sdata->pos, -1);
                        break;
-               case BUTTON_D:
+               case BUTTON_F:
                        sdata->pos++;
                        sdata->pos %= 8;
                        break;
@@ -260,11 +267,12 @@ void datetime_setup_events(u16t event, void *data)
 {
        switch (event) {
                case EVENT_SCREEN_VISIBLE:
+                       dt_setup_screen.pos = 0;
                        draw_datetime_setup_screen(&dt_setup_screen);
-                       enable_halfsecond_timer();
+                       hal_enable_halfsecond_timer();
                        break;
                case EVENT_SCREEN_DESTROY:
-                       disable_halfsecond_timer();
+                       hal_disable_halfsecond_timer();
                        break;
                case EVENT_USER_BUTTONS:
                        dbg_out("button event %d\n", *(int *)data);
@@ -282,6 +290,172 @@ void datetime_setup_events(u16t event, void *data)
        };
 }
 
+typedef struct {
+       u8t pos;
+       boolean on;
+} alarm_setup_data_t;
+static alarm_setup_data_t alarm_setup_screen = {
+       0,
+       TRUE
+};
+
+void draw_alarm_setup_screen(alarm_setup_data_t *sdata)
+{
+       hal_lcd_clear_display();
+
+       SetFont(MetaWatch16);
+       WriteLcdString(2, 2, "Alarm");
+
+       SetFont(MetaWatchTime);
+       if ((sdata->pos == 0 && sdata->on) || sdata->pos != 0) {
+               WriteLcdCharacter(2, 20, (OswaldAlarm.hour / 10));
+               WriteLcdCharacter(14, 20, (OswaldAlarm.hour % 10));
+       }
+       WriteLcdCharacter(26, 20, TIME_CHARACTER_COLON_INDEX);
+
+       if ((sdata->pos == 1 && sdata->on) || sdata->pos != 1) {
+               WriteLcdCharacter(31, 20, (OswaldAlarm.minute / 10));
+               WriteLcdCharacter(43, 20, (OswaldAlarm.minute % 10));
+       }
+
+       SetFont(MetaWatchMonospaced10);
+       WriteLcdCharacter(3, 45, 'S');
+       WriteLcdCharacter(15, 45, 'M');
+       WriteLcdCharacter(27, 45, 'T');
+       WriteLcdCharacter(39, 45, 'W');
+       WriteLcdCharacter(51, 45, 'T');
+       WriteLcdCharacter(63, 45, 'F');
+       WriteLcdCharacter(75, 45, 'S');
+
+       if ((sdata->pos == 2 && sdata->on) || sdata->pos != 2)
+               WriteLcdCharacter(3, 55, (OswaldAlarm.wday & WDAY_SUNDAY) ? 'x' : '_');
+       if ((sdata->pos == 3 && sdata->on) || sdata->pos != 3)
+               WriteLcdCharacter(15, 55, (OswaldAlarm.wday & WDAY_MONDAY) ? 'x' : '_');
+       if ((sdata->pos == 4 && sdata->on) || sdata->pos != 4)
+               WriteLcdCharacter(27, 55, (OswaldAlarm.wday & WDAY_TUESDAY) ? 'x' : '_');
+       if ((sdata->pos == 5 && sdata->on) || sdata->pos != 5)
+               WriteLcdCharacter(39, 55, (OswaldAlarm.wday & WDAY_WEDNESDAY) ? 'x' : '_');
+       if ((sdata->pos == 6 && sdata->on) || sdata->pos != 6)
+               WriteLcdCharacter(51, 55, (OswaldAlarm.wday & WDAY_THURSDAY) ? 'x' : '_');
+       if ((sdata->pos == 7 && sdata->on) || sdata->pos != 7)
+               WriteLcdCharacter(63, 55, (OswaldAlarm.wday & WDAY_FRIDAY) ? 'x' : '_');
+       if ((sdata->pos == 8 && sdata->on) || sdata->pos != 8)
+               WriteLcdCharacter(75, 55, (OswaldAlarm.wday & WDAY_SATURDAY) ? 'x' : '_');
+
+#if 0
+       SetFont(MetaWatch7);
+       if ((sdata->pos == 6 && sdata->on) || sdata->pos != 6) {
+               if (OswaldClk.clk24hr)
+                       WriteLcdString(2, 66, "x");
+               else
+                       WriteLcdString(2, 66, "_");
+       }
+       WriteLcdString(15, 66, "24hr");
+
+       if ((sdata->pos == 7 && sdata->on) || sdata->pos != 7) {
+               if (OswaldClk.day_first)
+                       WriteLcdString(2, 79, "x");
+               else
+                       WriteLcdString(2, 79, "_");
+       }
+       WriteLcdString(15, 79, "dd.mm.  mm/dd");
+#endif
+       hal_lcd_update_display();
+}
+
+void alarm_handle_updown(u8t pos, s8t incr)
+{
+       switch (pos) {
+               case 0: // hour
+                       if (OswaldAlarm.hour == 0 && incr == -1) {
+                               OswaldAlarm.hour = 23;
+                               break;
+                       };
+                       OswaldAlarm.hour += incr;
+                       if (OswaldAlarm.hour > 23)
+                               OswaldAlarm.hour = 0;
+                       break;
+               case 1: // minute
+                       if (OswaldAlarm.minute == 0 && incr == -1) {
+                               OswaldAlarm.minute = 59;
+                               break;
+                       };
+                       OswaldAlarm.minute += incr;
+                       if (OswaldAlarm.minute > 59)
+                               OswaldAlarm.minute = 0;
+                       break;
+               case 2: // sunday
+                       OswaldAlarm.wday ^= WDAY_SUNDAY;
+                       break;
+               case 3: // monday
+                       OswaldAlarm.wday ^= WDAY_MONDAY;
+                       break;
+               case 4: // tuesday
+                       OswaldAlarm.wday ^= WDAY_TUESDAY;
+                       break;
+               case 5: // wednesday
+                       OswaldAlarm.wday ^= WDAY_WEDNESDAY;
+                       break;
+               case 6: // thursday
+                       OswaldAlarm.wday ^= WDAY_THURSDAY;
+                       break;
+               case 7: // friday
+                       OswaldAlarm.wday ^= WDAY_FRIDAY;
+                       break;
+               case 8: // saturday
+                       OswaldAlarm.wday ^= WDAY_SATURDAY;
+                       break;
+               default:
+                       break;
+       };
+}
+
+void handle_setup_alarm_buttons(watch_button button, alarm_setup_data_t *sdata)
+{
+       switch (button) {
+               case BUTTON_A:
+                       alarm_handle_updown(sdata->pos, 1);
+                       break;
+               case BUTTON_B:
+                       alarm_handle_updown(sdata->pos, -1);
+                       break;
+               case BUTTON_F:
+                       sdata->pos++;
+                       sdata->pos %= 9;
+                       break;
+               default:
+                       break;
+       }
+       draw_alarm_setup_screen(sdata);
+}
+
+void alarm_setup_events(u16t event, void *data)
+{
+       switch (event) {
+               case EVENT_SCREEN_VISIBLE:
+                       alarm_setup_screen.pos = 0;
+                       draw_alarm_setup_screen(&alarm_setup_screen);
+                       hal_enable_halfsecond_timer();
+                       break;
+               case EVENT_SCREEN_DESTROY:
+                       hal_disable_halfsecond_timer();
+                       break;
+               case EVENT_USER_BUTTONS:
+                       dbg_out("button event %d\n", *(int *)data);
+                       handle_setup_alarm_buttons(*(watch_button *)data, &alarm_setup_screen);
+                       break;
+               case EVENT_HALF_SEC_TIMER:
+                       if (alarm_setup_screen.on)
+                               alarm_setup_screen.on = FALSE;
+                       else
+                               alarm_setup_screen.on = TRUE;
+                       draw_alarm_setup_screen(&alarm_setup_screen);
+                       break;
+               default:
+                       break;
+       };
+}
+
 
 typedef struct {
        u8t menu_pos;
@@ -290,7 +464,7 @@ static test_menu_t test_menu = { 0 };
 
 void draw_menu_test_screen(void)
 {
-       lcd_clear_display();
+       hal_lcd_clear_display();
        SetFont(MetaWatch16);
        WriteLcdString(2, 2, "Menu");
        SetFont(MetaWatch7);
@@ -301,7 +475,7 @@ void draw_menu_test_screen(void)
        WriteLcdString(2, 56, "Item 5");
 
        WriteLcdString(50, 20+(9*test_menu.menu_pos), "*");
-       lcd_update_display();
+       hal_lcd_update_display();
 }
 
 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 };
 
 static void update_stop_watch_screen(stopwatch_data_t *sdata)
 {
+       char tstr[16];
        SetFont(MetaWatchMonospaced10);
 
+#if 0
        WriteLcdNumber(0, 30, sdata->hr);
        WriteLcdCharacter(14, 30, ':');
        WriteLcdNumber(19, 30, sdata->min);
@@ -371,8 +547,14 @@ static void update_stop_watch_screen(stopwatch_data_t *sdata)
        WriteLcdNumber(38, 50, sdata->lapse_sec);
        WriteLcdCharacter(52, 50, '.');
        WriteLcdNumber(57, 50, sdata->lapse_csec / 10);
-
-       lcd_update_display();
+#else
+       snprintf(tstr, 16, "%02d:%02d:%02d.%1d", sdata->hr, sdata->min, sdata->sec, sdata->csec / 10);
+       WriteLcdString(0, 30, tstr);
+       snprintf(tstr, 16, "%02d:%02d:%02d.%02d", sdata->lapse_hr, sdata->lapse_min, sdata->lapse_sec, sdata->lapse_csec);
+       WriteLcdString(0, 50, tstr);
+#endif
+
+       hal_lcd_update_display();
 }
 
 static void draw_stop_watch_screen(stopwatch_data_t *sdata)
@@ -388,10 +570,10 @@ static void handle_stop_watch_buttons(watch_button button)
        switch (button) {
                case BUTTON_A: // start/stop
                        if (stopwatch_screen.running) {
-                               disable_centisecond_timer();
+                               hal_disable_centisecond_timer();
                                stopwatch_screen.running = FALSE;
                        } else {
-                               enable_centisecond_timer();
+                               hal_enable_centisecond_timer();
                                stopwatch_screen.running = TRUE;
                        }
                        break;
@@ -401,7 +583,7 @@ static void handle_stop_watch_buttons(watch_button button)
                        stopwatch_screen.lapse_sec = stopwatch_screen.sec;
                        stopwatch_screen.lapse_csec = stopwatch_screen.csec;
                        break;
-               case BUTTON_D: // reset
+               case BUTTON_F: // reset
                        stopwatch_screen.hr = 0;
                        stopwatch_screen.min = 0;
                        stopwatch_screen.sec = 0;
@@ -425,11 +607,11 @@ void stop_watch_handle_events(u16t event, void *data)
                        update_stop_watch_screen(&stopwatch_screen);
                        break;
                case EVENT_SCREEN_VISIBLE:
-                       lcd_clear_display();
+                       hal_lcd_clear_display();
                        draw_stop_watch_screen(&stopwatch_screen);
                        break;
                case EVENT_SCREEN_DESTROY:
-                       disable_centisecond_timer();
+                       hal_disable_centisecond_timer();
                        stopwatch_screen.running = FALSE;
                        break;
                case EVENT_CS_TIMER:
@@ -456,3 +638,42 @@ void stop_watch_handle_events(u16t event, void *data)
                        break;
        };
 }
+
+
+void draw_alarm_screen(void)
+{
+       hal_lcd_clear_display();
+
+       SetFont(MetaWatch16);
+       WriteLcdString(2, 2, "ALARM !");
+
+       hal_lcd_update_display();
+}
+
+void alarm_handle_events(u16t event, void *data)
+{
+       switch (event) {
+               case EVENT_SCREEN_VISIBLE:
+                       draw_alarm_screen();
+                       hal_enable_halfsecond_timer();
+                       hal_vibration_set_state(TRUE);
+                       break;
+               case EVENT_SCREEN_DESTROY:
+                       hal_disable_halfsecond_timer();
+                       hal_lcd_set_backlight(FALSE);
+                       hal_vibration_set_state(FALSE);
+                       break;
+               case EVENT_USER_BUTTONS:
+                       dbg_out("button event %d\n", *(int *)data);
+                       // hal_lcd_set_backlight(FALSE);
+                       break;
+               case EVENT_HALF_SEC_TIMER:
+                       hal_lcd_set_backlight(!hal_lcd_get_backlight());
+                       hal_vibration_set_state(!hal_vibration_get_state());
+                       dbg_out("timer\n");
+                       break;
+               default:
+                       break;
+       };
+}
+
index 0cca47c558c0e3a2b80cdaf0b3e462318c8e1455..005b0bb1c373dff9a52fb734f6ab28ab440aa3b8 100644 (file)
@@ -8,9 +8,13 @@ void accel_handle_events(u16t event, void *data);
 
 void datetime_setup_events(u16t event, void *data);
 
+void alarm_setup_events(u16t event, void *data);
+
 void test_menu_handle_events(u16t event, void *data);
 
 void stop_watch_handle_events(u16t event, void *data);
 
+void alarm_handle_events(u16t event, void *data);
+
 #endif
 
index 548a6bbe8f191fb959ac68469c1f505fa959878a..6db3196abd2d39baba91ff3e415e07866066b96c 100644 (file)
-#include <math.h>
+#include <stdio.h>
+#include <stdint.h>
 
 #include "oswald.h"
 #include "oswald_main.h"
-#include "oswald-ui.h"
 #include "Fonts.h"
 #include "LcdDisplay.h"
+#include "oswald_hal.h"
 
 #include "oswald_watch_faces.h"
 
+int16_t sintab[]={
+           0,   2,   3,   5,   7,   9,  10,  12,  14,  16,
+          17,  19,  21,  22,  24,  26,  28,  29,  31,  33,
+          34,  36,  37,  39,  41,  42,  44,  45,  47,  48,
+          50,  52,  53,  54,  56,  57,  59,  60,  62,  63,
+          64,  66,  67,  68,  69,  71,  72,  73,  74,  75,
+          77,  78,  79,  80,  81,  82,  83,  84,  85,  86,
+          87,  87,  88,  89,  90,  91,  91,  92,  93,  93,
+          94,  95,  95,  96,  96,  97,  97,  97,  98,  98,
+          98,  99,  99,  99,  99, 100, 100, 100, 100, 100,
+         100, 100, 100, 100, 100, 100,  99,  99,  99,  99,
+          98,  98,  98,  97,  97,  97,  96,  96,  95,  95,
+          94,  93,  93,  92,  91,  91,  90,  89,  88,  87,
+          87,  86,  85,  84,  83,  82,  81,  80,  79,  78,
+          77,  75,  74,  73,  72,  71,  69,  68,  67,  66,
+          64,  63,  62,  60,  59,  57,  56,  54,  53,  52,
+          50,  48,  47,  45,  44,  42,  41,  39,  37,  36,
+          34,  33,  31,  29,  28,  26,  24,  22,  21,  19,
+          17,  16,  14,  12,  10,   9,   7,   5,   3,   2,
+           0,  -2,  -3,  -5,  -7,  -9, -10, -12, -14, -16,
+         -17, -19, -21, -22, -24, -26, -28, -29, -31, -33,
+         -34, -36, -37, -39, -41, -42, -44, -45, -47, -48,
+         -50, -52, -53, -54, -56, -57, -59, -60, -62, -63,
+         -64, -66, -67, -68, -69, -71, -72, -73, -74, -75,
+         -77, -78, -79, -80, -81, -82, -83, -84, -85, -86,
+         -87, -87, -88, -89, -90, -91, -91, -92, -93, -93,
+         -94, -95, -95, -96, -96, -97, -97, -97, -98, -98,
+         -98, -99, -99, -99, -99,-100,-100,-100,-100,-100,
+        -100,-100,-100,-100,-100,-100, -99, -99, -99, -99,
+         -98, -98, -98, -97, -97, -97, -96, -96, -95, -95,
+         -94, -93, -93, -92, -91, -91, -90, -89, -88, -87,
+         -87, -86, -85, -84, -83, -82, -81, -80, -79, -78,
+         -77, -75, -74, -73, -72, -71, -69, -68, -67, -66,
+         -64, -63, -62, -60, -59, -57, -56, -54, -53, -52,
+         -50, -48, -47, -45, -44, -42, -41, -39, -37, -36,
+         -34, -33, -31, -29, -28, -26, -24, -22, -21, -19,
+         -17, -16, -14, -12, -10,  -9,  -7,  -5,  -3,  -2
+};
+
+int16_t f_sin(int16_t v)
+{
+       v %= 360;
+       return sintab[v];
+}
+
+int16_t f_cos(int16_t v)
+{
+       v += 90;
+       v %= 360;
+       return sintab[v];
+}
+
 void DrawLcdAnaClock(boolean show_seconds)
 {
-       //unsigned char *bbuf;
-       //char daystr[5];
-       //int len;
-       int i, x, y, x2, y2;
-       double tmp, mf;
-       s8t hour, minute, seconds;
+       int16_t i, x, y, x2, y2;
+       int16_t tmp;
+       int8_t hour, minute, seconds;
+       char tstr[16];
 
        hour = OswaldClk.hour;
        minute = OswaldClk.minute;
        seconds = OswaldClk.second;
 
        hour -= 3;
-       mf = (1. / 59.) * (double)minute;
+       if (hour < 0)
+               hour += 12;
+       // mf = (1. / 59.) * (double)minute;
        minute -= 15;
+       if (minute < 0)
+               minute += 60;
        seconds -= 15;
+       if (seconds < 0)
+               seconds += 60;
 
-       lcd_clear_display();
+       hal_lcd_clear_display();
+
+       SetFont(MetaWatch16);
+       snprintf(tstr, 16, "%02d", OswaldClk.day);
+       WriteLcdString(70, 40, tstr);
 
        // plot(R*cos(360° * i/N), R*sin(360° * i/N))
        for (i=0; i<12; i++) {
-               tmp = 48. + (43. * cos(((2. * M_PI) / 12.) * (double)i));
+               tmp = 48 + ((43 * f_cos((360 / 12) * i)) / 100);
                x =  tmp;
-               tmp = 48 + (43. * sin(((2. * M_PI) / 12.) * (double)i));
+               tmp = 48 + ((43 * f_sin((360 / 12) * i)) / 100);
                y =  tmp;
-               tmp = 48. + (48. * cos(((2. * M_PI) / 12.) * (double)i));
+               tmp = 48 + ((48 * f_cos((360 / 12) * i)) / 100);
                x2 =  tmp;
-               tmp = 48 + (48. * sin(((2. * M_PI) / 12.) * (double)i));
+               tmp = 48 + ((48 * f_sin((360 / 12) * i)) / 100);
                y2 =  tmp;
                DrawLcdLineBresenhamWW(x, y, x2, y2, 2);
        };
+
        // Hour
-       tmp = 48. + (30. * cos(((2. * M_PI) / 12.) * ((double)hour + mf)));
+       tmp = 48 + (30 * f_cos(((360 / 12) * hour) + ((OswaldClk.minute * 360) /12 / 60)) / 100);
        x =  tmp;
-       tmp = 48 + (30. * sin(((2. * M_PI) / 12.) * ((double)hour + mf)));
+       tmp = 48 + (30 * f_sin(((360 / 12) * hour) + ((OswaldClk.minute * 360) /12 / 60)) / 100);
        y =  tmp;
        DrawLcdLineBresenhamWW(48, 48, x, y, 2);
        // Minute
-       tmp = 48. + (40. * cos(((2. * M_PI) / 60.) * (double)minute));
+       tmp = 48 + ((40 * f_cos((360 / 60) * minute)) / 100);
        x =  tmp;
-       tmp = 48 + (40. * sin(((2. * M_PI) / 60.) * (double)minute));
+       tmp = 48 + ((40 * f_sin((360 / 60) * minute)) / 100);
        y =  tmp;
        DrawLcdLineBresenhamWW(48, 48, x, y, 2);
        if (show_seconds) {
                // Seconds
-               tmp = 48. + (40. * cos(((2. * M_PI) / 60.) * (double)seconds));
+               tmp = 48 + ((40 * f_cos((360 / 60) * seconds)) / 100);
                x =  tmp;
-               tmp = 48 + (40. * sin(((2. * M_PI) / 60.) * (double)seconds));
+               tmp = 48 + ((40 * f_sin((360 / 60) * seconds)) / 100);
                y =  tmp;
                DrawLcdLineBresenham(48, 48, x, y);
        };
 
-       //snprintf(daystr, 5, "%d", day);
-       // mw_buf_print(mwbuf, 74, 45, daystr, 0, MW_WHITE, MW_BLACK);
-       lcd_update_display();
+       hal_lcd_update_display();
 }
 
 void DrawLcdDigitalClock(boolean show_seconds)
 {
        int gRow = 3;
-       int gColumn = 4;
+       int gColumn = 3;
+       char tstr[16];
 
        SetFont(MetaWatchTime);
 
-       lcd_clear_display();
+       hal_lcd_clear_display();
        //gRow += WriteLcdCharacter(ui, gRow, gColumn, TIME_CHARACTER_SPACE_INDEX);
-       gRow += WriteLcdCharacter(gRow, gColumn, (OswaldClk.hour / 10));
-       gRow += WriteLcdCharacter(gRow, gColumn, (OswaldClk.hour % 10));
+       if (OswaldClk.clk24hr) {
+               gRow += WriteLcdCharacter(gRow, gColumn, (OswaldClk.hour / 10));
+               gRow += WriteLcdCharacter(gRow, gColumn, (OswaldClk.hour % 10));
+       } else {
+               unsigned char val = OswaldClk.hour;
+               if (val > 12)
+                       val -= 12;
+               gRow += WriteLcdCharacter(gRow, gColumn, (val / 10));
+               gRow += WriteLcdCharacter(gRow, gColumn, (val % 10));
+       }
        gRow += WriteLcdCharacter(gRow, gColumn, TIME_CHARACTER_COLON_INDEX);
        gRow += WriteLcdCharacter(gRow, gColumn, (OswaldClk.minute / 10));
        gRow += WriteLcdCharacter(gRow, gColumn, (OswaldClk.minute % 10));
+
+       gRow += 3;
        if (show_seconds) {
-               gRow += WriteLcdCharacter(gRow, gColumn, TIME_CHARACTER_COLON_INDEX);
-               gRow += WriteLcdCharacter(gRow, gColumn, (OswaldClk.second / 10));
-               gRow += WriteLcdCharacter(gRow, gColumn, (OswaldClk.second % 10));
+               SetFont(MetaWatch16);
+               snprintf(tstr, 16, "%02d", OswaldClk.second);
+               WriteLcdString(gRow, 9, tstr);
        };
-       lcd_update_display();
+
+       SetFont(MetaWatch7);
+
+       if (!OswaldClk.clk24hr) {
+               if (OswaldClk.hour > 12) {
+                       WriteLcdString(gRow, 3, "PM");
+               } else {
+                       WriteLcdString(gRow, 3, "AM");
+               }
+       }
+
+       SetFont(MetaWatch16);
+
+       if (OswaldClk.day_first)
+               snprintf(tstr, 16, "%d.%d.%d", OswaldClk.day, OswaldClk.month, OswaldClk.year);
+       else
+               snprintf(tstr, 16, "%d/%d %d", OswaldClk.month, OswaldClk.day, OswaldClk.year);
+       WriteLcdString(3, 25, tstr);
+
+       snprintf(tstr, 16, "%d%% (%dmV)", OswaldPowerState.percent, OswaldPowerState.level);
+       WriteLcdString(2, 48, tstr);
+       WriteLcdString(2, 64, OswaldPowerState.source ? "ext" : "bat");
+
+       /* this makes only sense when the charger is active */
+       if (OswaldPowerState.source) {
+               switch (OswaldPowerState.charge_state) {
+                       case POWER_CHARGER_DONE:
+                               WriteLcdString(2, 80, "charge done");
+                               break;
+                       case POWER_CHARGER_PRECHARGE:
+                               WriteLcdString(2, 80, "precharging");
+                               break;
+                       case POWER_CHARGER_CHARGING:
+                               WriteLcdString(2, 80, "charging");
+                               break;
+                       case POWER_CHARGER_UNK:
+                               WriteLcdString(2, 80, "charge unkn.");
+                               break;
+                       default:
+                               break;
+               };
+       };
+       hal_lcd_update_display();
 }
+