/*! 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
}
+#if defined(__GNUC__) && (__MSP430X__ > 0)
+__attribute__((__far__))
+#endif
const unsigned char MetaWatch5table[PRINTABLE_CHARACTERS][5] =
{
/* character 0x20 (' '): (width = 2) */
0x00, 0x00, 0x00, 0x00, 0x00,},
};
+#if defined(__GNUC__) && (__MSP430X__ > 0)
+__attribute__((__far__))
+#endif
const unsigned char MetaWatch5width[PRINTABLE_CHARACTERS] =
{
/* width char hexcode */
3, /* } 7D */
};
+#if defined(__GNUC__) && (__MSP430X__ > 0)
+__attribute__((__far__))
+#endif
const unsigned char MetaWatch7table[PRINTABLE_CHARACTERS][7] =
{
};
+#if defined(__GNUC__) && (__MSP430X__ > 0)
+__attribute__((__far__))
+#endif
const unsigned char MetaWatch7width[PRINTABLE_CHARACTERS] = {
/* width char hexcode */
/* ===== ==== ======= */
};
+#if defined(__GNUC__) && (__MSP430X__ > 0)
+__attribute__((__far__))
+#endif
const u16t MetaWatch16table[PRINTABLE_CHARACTERS][16] =
{
/* character 0x20 (' '): (width=4) */
0x0006, 0x0002, 0x0001, 0x0000},
};
+#if defined(__GNUC__) && (__MSP430X__ > 0)
+__attribute__((__far__))
+#endif
const unsigned char MetaWatch16width[PRINTABLE_CHARACTERS] =
{
/* width char hexcode */
};
/******************************************************************************/
+#if defined(__GNUC__) && (__MSP430X__ > 0)
+__attribute__((__far__))
+#endif
const u16t MetaWatchTimeTable[TOTAL_TIME_CHARACTERS][19] =
{
/* character 0x30 ('0'): (width=11, offset=0) */
0x0000, 0x0000, 0x0000},
};
+#if defined(__GNUC__) && (__MSP430X__ > 0)
+__attribute__((__far__))
+#endif
const unsigned char MetaWatchTimeWidth[TOTAL_TIME_CHARACTERS] =
{
/* width char hexcode */
/******************************************************************************/
+#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},
-#include "oswald-ui.h"
+#include "oswald.h"
+#include "oswald_hal.h"
#include "oswald_strings.h"
#include "Fonts.h"
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;
x += pdx;
y += pdy;
}
- lcd_set_pixel(x, y, TRUE);
+ hal_lcd_set_pixel(x, y, TRUE);
}
// lcd_update_display();
}
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) {
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();
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(" ");
}
}
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;
}
#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
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)
--- /dev/null
+#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
+}
+
+
--- /dev/null
+#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
+
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;
}
/* 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,
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);
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;
}
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;
#ifndef _OSWALD_H
#define _OSWALD_H
+#include <stdint.h>
//#define DEBUG 1
#ifdef DEBUG
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;
#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
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
#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;
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;
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)
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) {
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)
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(" ");
}
}
#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);
--- /dev/null
+#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
+
#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)
{
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))
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);
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;
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;
}
#include "oswald.h"
extern clock_state OswaldClk;
+extern alarm_clk OswaldAlarm;
+extern power_state OswaldPowerState;
extern watch_state OswaldState;
extern watch_screen OswaldScreens[];
void oswald_init(void);
#endif
-
+#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"
} idle_data_t;
static idle_data_t idle_screen = {
DrawLcdDigitalClock,
- FALSE,
+ TRUE,
FALSE,
};
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);
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);
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)
void draw_datetime_setup_screen(datetime_setup_data_t *sdata)
{
- lcd_clear_display();
+ hal_lcd_clear_display();
SetFont(MetaWatch16);
WriteLcdString(2, 2, "Set");
}
WriteLcdString(15, 79, "dd.mm. mm/dd");
- lcd_update_display();
+ hal_lcd_update_display();
}
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)
case BUTTON_B:
datetime_handle_updown(sdata->pos, -1);
break;
- case BUTTON_D:
+ case BUTTON_F:
sdata->pos++;
sdata->pos %= 8;
break;
{
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);
};
}
+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;
void draw_menu_test_screen(void)
{
- lcd_clear_display();
+ hal_lcd_clear_display();
SetFont(MetaWatch16);
WriteLcdString(2, 2, "Menu");
SetFont(MetaWatch7);
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)
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);
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)
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;
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;
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:
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;
+ };
+}
+
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
-#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();
}
+