#include <time.h>
#include <stdio.h>
#include <string.h>
+#include <math.h>
#include "oswald-ui.h"
#include "Fonts.h"
+
#include "LcdDisplay.h"
#define NUM_LCD_ROWS 96
#define MAX_FONT_ROWS ( 19 )
-gint WriteLcdCharacter(oswald_ui *ui, gint x, gint y, unsigned char Character)
+void DrawLcdLineBresenham(u8t xstart, u8t ystart, u8t xend, u8t yend)
+{
+ int x, y, t, dx, dy, incx, incy, pdx, pdy, ddx, ddy, es, el, err;
+
+ dx = xend - xstart;
+ dy = yend - ystart;
+
+ incx = (dx >= 0) ? 1 : -1;
+ incy = (dy >= 0) ? 1 : -1;
+
+ if (dx<0)
+ dx = -dx;
+ if (dy<0)
+ dy = -dy;
+
+ if (dx>dy) {
+ pdx = incx; pdy = 0;
+ ddx=incx; ddy=incy;
+ es =dy; el =dx;
+ } else {
+ pdx=0; pdy=incy;
+ ddx=incx; ddy=incy;
+ es =dx; el =dy;
+ }
+
+ x = xstart;
+ y = ystart;
+ err = el/2;
+ lcd_set_pixel(x, y, TRUE);
+
+ for (t = 0; t < el; ++t) {
+ err -= es;
+ if (err < 0) {
+ err += el;
+ x += ddx;
+ y += ddy;
+ } else {
+ x += pdx;
+ y += pdy;
+ }
+ lcd_set_pixel(x, y, TRUE);
+ }
+}
+
+void DrawLcdLineBresenhamWW(u8t xstart, u8t ystart, u8t xend, u8t yend, u8t thickness)
+{
+ int i, x, y, t, dx, dy, incx, incy, pdx, pdy, ddx, ddy, es, el, err;
+
+ dx = xend - xstart;
+ dy = yend - ystart;
+
+ incx = (dx >= 0) ? 1 : -1;
+ incy = (dy >= 0) ? 1 : -1;
+
+ if (dx<0)
+ dx = -dx;
+ if (dy<0)
+ dy = -dy;
+
+ if (dx>dy) {
+ pdx = incx; pdy = 0;
+ ddx=incx; ddy=incy;
+ es =dy; el =dx;
+ } else {
+ pdx=0; pdy=incy;
+ ddx=incx; ddy=incy;
+ es =dx; el =dy;
+ }
+
+ x = xstart;
+ y = ystart;
+ err = el/2;
+ 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);
+ }
+
+ for (t = 0; t < el; ++t) {
+ err -= es;
+ if (err < 0) {
+ err += el;
+ x += ddx;
+ y += ddy;
+ } else {
+ x += pdx;
+ y += pdy;
+ }
+ 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);
+ }
+ }
+}
+
+
+u8t WriteLcdCharacter(u8t x, u8t y, u8t Character)
{
- gint CharacterHeight = GetCharacterHeight();
- gint CharacterWidth = GetCharacterWidth(Character);
+ u8t CharacterHeight = GetCharacterHeight();
+ u8t CharacterWidth = GetCharacterWidth(Character);
unsigned int bitmap[MAX_FONT_ROWS];
- gint lx, ly;
+ register lx, ly;
GetCharacterBitmap(Character,(unsigned int*)&bitmap);
for (ly=0; ly<CharacterHeight; ly++) {
for (lx=0; lx<CharacterWidth; lx++) {
if (bitmap[ly] & (1<<lx)) {
- set_pixel(ui, lx+x, ly+y, TRUE);
+ lcd_set_pixel(lx+x, ly+y, TRUE);
// printf(".");
} else {
- set_pixel(ui, lx+x, ly+y, FALSE);
+ lcd_set_pixel(lx+x, ly+y, FALSE);
// printf(" ");
}
}
return CharacterWidth + GetFontSpacing();
}
-void WriteLcdString(oswald_ui *ui, gint x, gint y, gchar *str)
+void WriteLcdString(u8t x, u8t y, u8t *str)
{
- gint lx, i;
+ register lx, i;
if (str == NULL || strlen(str)==0)
return;
lx = x;
for (i=0; i<strlen(str); i++) {
- lx += WriteLcdCharacter(ui, lx, y, str[i]);
+ lx += WriteLcdCharacter(lx, y, str[i]);
}
}
-
-void update_idle_time_date(oswald_ui *ui)
-{
- gint gRow = 3;
- gint gColumn = 4;
- static gchar secs = 0;
-
- SetFont(MetaWatchTime);
-
- //gRow += WriteLcdCharacter(ui, gRow, gColumn, TIME_CHARACTER_SPACE_INDEX);
- gRow += WriteLcdCharacter(ui, gRow, gColumn, 2);
- gRow += WriteLcdCharacter(ui, gRow, gColumn, 3);
- gRow += WriteLcdCharacter(ui, gRow, gColumn, TIME_CHARACTER_COLON_INDEX);
- gRow += WriteLcdCharacter(ui, gRow, gColumn, 1);
- gRow += WriteLcdCharacter(ui, gRow, gColumn, 7);
- gRow += WriteLcdCharacter(ui, gRow, gColumn, TIME_CHARACTER_COLON_INDEX);
- gRow += WriteLcdCharacter(ui, gRow, gColumn, (secs / 10));
- gRow += WriteLcdCharacter(ui, gRow, gColumn, (secs % 10));
- secs = ++secs % 60;
-}
-
#include "oswald-ui.h"
-void update_idle_time_date(oswald_ui *ui);
+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, u8t *str);
#endif
bin_PROGRAMS = oswald-gui
-oswald_gui_SOURCES = oswald-ui.c LcdDisplay.c Fonts.c
+oswald_gui_SOURCES = oswald-ui.c LcdDisplay.c Fonts.c oswald_main.c oswald_watch_faces.c
oswald_gui_CFLAGS = -g $(GTK_CFLAGS)
oswald_gui_LDADD = $(GTK_LIBS)
#include <gtk/gtk.h>
-#include "oswald-ui.h"
#include "Fonts.h" // the MetaWatch fonts
+#include "oswald_main.h"
+
+#include "oswald-ui.h"
#define BITMAP_WIDTH 192
#define BITMAP_HEIGHT 192
-void set_pixel(oswald_ui *ui, gint x, gint y, gboolean state)
+static oswald_ui *ui_g;
+
+void lcd_set_pixel(gint x, gint y, gboolean state)
{
- GdkRectangle update_rect;
gint ix, iy;
ix = x*2;
iy = y*2;
- update_rect.x = ix - 5;
- update_rect.y = iy - 5;
- update_rect.width = 10;
- update_rect.height = 10;
-
- gdk_draw_point(GDK_DRAWABLE(ui->pixmap), state ? ui->darea->style->black_gc : ui->darea->style->white_gc, ix, iy);
- gdk_draw_point(GDK_DRAWABLE(ui->pixmap), state ? ui->darea->style->black_gc : ui->darea->style->white_gc, ix+1, iy);
- gdk_draw_point(GDK_DRAWABLE(ui->pixmap), state ? ui->darea->style->black_gc : ui->darea->style->white_gc, ix, iy+1);
- gdk_draw_point(GDK_DRAWABLE(ui->pixmap), state ? ui->darea->style->black_gc : ui->darea->style->white_gc, ix+1, iy+1);
+ gdk_draw_point(GDK_DRAWABLE(ui_g->pixmap), state ? ui_g->darea->style->black_gc : ui_g->darea->style->white_gc, ix, iy);
+ gdk_draw_point(GDK_DRAWABLE(ui_g->pixmap), state ? ui_g->darea->style->black_gc : ui_g->darea->style->white_gc, ix+1, iy);
+ gdk_draw_point(GDK_DRAWABLE(ui_g->pixmap), state ? ui_g->darea->style->black_gc : ui_g->darea->style->white_gc, ix, iy+1);
+ gdk_draw_point(GDK_DRAWABLE(ui_g->pixmap), state ? ui_g->darea->style->black_gc : ui_g->darea->style->white_gc, ix+1, iy+1);
- gtk_widget_draw (GTK_WIDGET(ui->darea), &update_rect);
+ gtk_widget_queue_draw(ui_g->darea);
}
-void clear_display(oswald_ui *ui)
+void lcd_clear_display(void)
{
- GdkRectangle update_rect;
-
- update_rect.x = 0;
- update_rect.y = 0;
- update_rect.width = BITMAP_WIDTH;
- update_rect.height = BITMAP_HEIGHT;
-
- gdk_draw_rectangle (ui->pixmap,
- ui->darea->style->white_gc,
+ gdk_draw_rectangle (ui_g->pixmap,
+ ui_g->darea->style->white_gc,
TRUE,
0, 0,
- ui->darea->allocation.width,
- ui->darea->allocation.height);
+ ui_g->darea->allocation.width,
+ ui_g->darea->allocation.height);
- gtk_widget_draw (GTK_WIDGET(ui->darea), &update_rect);
+ gtk_widget_queue_draw(ui_g->darea);
}
static gint
return FALSE;
}
+void button_A_pressed (GtkButton *button, gpointer user_data)
+{
+ oswald_ui *ui = (oswald_ui *)user_data;
+
+ g_print("Button-A pressed\n");
+ oswald_handle_button_press(BUTTON_A);
+}
+
+void button_B_pressed (GtkButton *button, gpointer user_data)
+{
+ oswald_ui *ui = (oswald_ui *)user_data;
+
+ g_print("Button-B pressed\n");
+}
+
+void button_C_pressed (GtkButton *button, gpointer user_data)
+{
+ oswald_ui *ui = (oswald_ui *)user_data;
+
+ g_print("Button-C pressed\n");
+}
+
+void button_D_pressed (GtkButton *button, gpointer user_data)
+{
+ oswald_ui *ui = (oswald_ui *)user_data;
+
+ g_print("Button-D pressed\n");
+}
+
+void button_E_pressed (GtkButton *button, gpointer user_data)
+{
+ oswald_ui *ui = (oswald_ui *)user_data;
+
+ g_print("Button-E pressed\n");
+}
+
+void button_F_pressed (GtkButton *button, gpointer user_data)
+{
+ oswald_ui *ui = (oswald_ui *)user_data;
+
+ g_print("Button-F pressed\n");
+}
+
static void create_mainwin(oswald_ui *ui)
{
GtkWidget *hb, *vb, *btn;
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_D_pressed), 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_D_pressed), ui);
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_F_pressed), ui);
+
ui->darea = gtk_drawing_area_new ();
gtk_box_pack_start (GTK_BOX(hb), GTK_WIDGET(ui->darea), FALSE, FALSE, 5);
btn = gtk_button_new_with_label(" A ");
gtk_box_pack_start (GTK_BOX(vb), btn, FALSE, FALSE, 10);
+ g_signal_connect(G_OBJECT(btn), "clicked", G_CALLBACK(button_A_pressed), ui);
btn = gtk_button_new_with_label(" B ");
gtk_box_pack_start (GTK_BOX(vb), btn, FALSE, FALSE, 10);
+ g_signal_connect(G_OBJECT(btn), "clicked", G_CALLBACK(button_B_pressed), ui);
btn = gtk_button_new_with_label(" C ");
gtk_box_pack_start (GTK_BOX(vb), btn, FALSE, FALSE, 10);
+ g_signal_connect(G_OBJECT(btn), "clicked", G_CALLBACK(button_C_pressed), ui);
gtk_widget_show_all(ui->mainwin);
}
-gboolean app_tmo_handler (gpointer userdata)
+gboolean one_second_tmo_handler (gpointer userdata)
{
oswald_ui *ui = (oswald_ui *)userdata;
- // fprintf(stderr, "tmo...\n");
+ oswald_one_second_tick();
- if (ui->OnIdleScreen) {
- update_idle_time_date(ui);
-#if 0
- } else {
- // go back to idle screen after IDLE_TIMEOUT seconds
- if ((time(NULL) - ui->idle_tmo) > ui->conf.idle_tmo /*IDLE_TIMEOUT*/)
- create_main_screen(ui);
-#endif
- }
+ return TRUE;
+}
+gboolean app_idle_handler (gpointer user_data)
+{
+ g_print("i");
return TRUE;
}
int main(int argc , char ** argv)
{
oswald_ui ui;
+ time_t mt;
+ struct tm mtime;
+
+ ui_g = &ui;
+
+ mt = time(NULL);
+ localtime_r(&mt, &mtime);
gtk_init (&argc, &argv);
create_mainwin(&ui);
- //set_pixel(&ui, 48, 48, TRUE);
- // demo_time(&ui);
- ui.OnIdleScreen = TRUE;
- g_timeout_add_seconds(1, app_tmo_handler, &ui);
+ oswald_init();
+ oswald_set_time(mtime.tm_hour, mtime.tm_min, mtime.tm_sec);
+
+ g_timeout_add_seconds(1, one_second_tmo_handler, &ui);
+ // g_idle_add(app_idle_handler, &ui);
gtk_main ();
return 0;
#include <gtk/gtk.h>
+#include "oswald.h"
+
typedef struct {
GtkWidget *mainwin;
GtkWidget *darea;
GdkPixmap *pixmap;
- gboolean OnIdleScreen;
} oswald_ui;
-void set_pixel(oswald_ui *ui, gint x, gint y, gboolean state);
+void lcd_set_pixel(gint x, gint y, gboolean state);
+void lcd_clear_display(void);
#endif
--- /dev/null
+#ifndef _OSWALD_H
+#define _OSWALD_H
+
+typedef signed char s8t;
+typedef unsigned char u8t;
+typedef u8t boolean;
+#ifdef TRUE
+#undef TRUE
+#endif
+#define TRUE 1
+#ifdef FALSE
+#undef FALSE
+#endif
+#define FALSE 0
+#ifndef NULL
+#define NULL 0
+#endif
+
+typedef struct {
+ u8t hour;
+ u8t minute;
+ u8t second;
+ u8t day;
+ u8t month;
+ u8t year;
+} clock_state;
+
+typedef enum {
+ IDLE_SCREEN = 0,
+ APPLICATION_SCREEN,
+} screen_number;
+
+typedef enum {
+ BUTTON_A = 0,
+ BUTTON_B,
+ BUTTON_C,
+ BUTTON_D,
+ BUTTON_E,
+ BUTTON_F,
+} watch_button;
+
+typedef struct {
+ screen_number screen;
+ void (*idle_draw_func)(boolean show_seconds);
+ boolean idle_show_seconds;
+} watch_state;
+
+
+#endif
+
--- /dev/null
+#include "oswald.h"
+#include "oswald_watch_faces.h"
+
+#include "oswald_main.h"
+
+/*
+ * some variable defining our curent state
+ * these are globals in order to avoid having to pass pointers
+ * through function calls thus saving stack space
+ */
+clock_state OswaldClk;
+watch_state OswaldState;
+
+void update_screen(void)
+{
+ switch (OswaldState.screen) {
+ case IDLE_SCREEN:
+ if (OswaldState.idle_draw_func != NULL)
+ OswaldState.idle_draw_func(OswaldState.idle_show_seconds);
+ break;
+ case APPLICATION_SCREEN:
+ break;
+ deafault:
+ break;
+ };
+}
+
+void oswald_change_to_screen(screen_number screen)
+{
+ // we spare the update if no change
+ if (OswaldState.screen != screen) {
+ OswaldState.screen = screen;
+ update_screen();
+ }
+}
+
+void oswald_set_time(u8t hour, u8t minute, u8t second)
+{
+ OswaldClk.hour = hour;
+ OswaldClk.minute = minute;
+ OswaldClk.second = second;
+}
+
+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;
+}
+
+void oswald_one_second_tick(void)
+{
+ update_clock_state();
+ update_screen();
+}
+
+void oswald_handle_button_press(watch_button button)
+{
+}
+
+void oswald_init(void)
+{
+ OswaldState.screen = IDLE_SCREEN;
+ OswaldState.idle_draw_func = DrawLcdDigitalClock;
+ OswaldState.idle_show_seconds = FALSE;
+}
+
--- /dev/null
+#ifndef _OSWALD_MAIN_H
+#define _OSWALD_MAIN_H
+
+#include "oswald.h"
+
+extern clock_state OswaldClk;
+extern watch_state OswaldState;
+
+/* gets triggered by OS timer function */
+void oswald_one_second_tick();
+void oswald_set_time(u8t hour, u8t minute, u8t second);
+
+void oswald_handle_button_press(watch_button button);
+void oswald_init(void);
+
+#endif
+
--- /dev/null
+#include <math.h>
+
+#include "oswald.h"
+#include "oswald_main.h"
+#include "oswald-ui.h"
+#include "Fonts.h"
+#include "LcdDisplay.h"
+
+#include "oswald_watch_faces.h"
+
+void DrawLcdAnaClock(boolean show_seconds)
+{
+ unsigned char *bbuf;
+ char daystr[5];
+ int len;
+ register i, x, y, x2, y2;
+ double tmp, mf;
+ s8t hour, minute, seconds;
+
+ hour = OswaldClk.hour;
+ minute = OswaldClk.minute;
+ seconds = OswaldClk.second;
+
+ hour -= 3;
+ mf = (1. / 59.) * (double)minute;
+ minute -= 15;
+ seconds -= 15;
+
+ lcd_clear_display();
+
+ // 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));
+ x = tmp;
+ tmp = 48 + (43. * sin(((2. * M_PI) / 12.) * (double)i));
+ y = tmp;
+ tmp = 48. + (48. * cos(((2. * M_PI) / 12.) * (double)i));
+ x2 = tmp;
+ tmp = 48 + (48. * sin(((2. * M_PI) / 12.) * (double)i));
+ y2 = tmp;
+ DrawLcdLineBresenhamWW(x, y, x2, y2, 2);
+ };
+ // Hour
+ tmp = 48. + (30. * cos(((2. * M_PI) / 12.) * ((double)hour + mf)));
+ x = tmp;
+ tmp = 48 + (30. * sin(((2. * M_PI) / 12.) * ((double)hour + mf)));
+ y = tmp;
+ DrawLcdLineBresenhamWW(48, 48, x, y, 2);
+ // Minute
+ tmp = 48. + (40. * cos(((2. * M_PI) / 60.) * (double)minute));
+ x = tmp;
+ tmp = 48 + (40. * sin(((2. * M_PI) / 60.) * (double)minute));
+ y = tmp;
+ DrawLcdLineBresenhamWW(48, 48, x, y, 2);
+ if (show_seconds) {
+ // Seconds
+ tmp = 48. + (40. * cos(((2. * M_PI) / 60.) * (double)seconds));
+ x = tmp;
+ tmp = 48 + (40. * sin(((2. * M_PI) / 60.) * (double)seconds));
+ y = tmp;
+ DrawLcdLineBresenham(48, 48, x, y);
+ };
+
+ //snprintf(daystr, 5, "%d", day);
+ // mw_buf_print(mwbuf, 74, 45, daystr, 0, MW_WHITE, MW_BLACK);
+}
+
+void DrawLcdDigitalClock(boolean show_seconds)
+{
+ gint gRow = 3;
+ gint gColumn = 4;
+
+ SetFont(MetaWatchTime);
+
+ 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));
+ gRow += WriteLcdCharacter(gRow, gColumn, TIME_CHARACTER_COLON_INDEX);
+ gRow += WriteLcdCharacter(gRow, gColumn, (OswaldClk.minute / 10));
+ gRow += WriteLcdCharacter(gRow, gColumn, (OswaldClk.minute % 10));
+ 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));
+ };
+}
+
--- /dev/null
+#ifndef _OSWALD_WATCH_FACES_H
+#define _OSWALD_WATCH_FACES_H
+
+void DrawLcdAnaClock(boolean show_seconds);
+void DrawLcdDigitalClock(boolean show_seconds);
+
+#endif
+