Commit d1ff29c0 authored by Federico Vaga's avatar Federico Vaga

AMEND step 1

parent 939f068c
......@@ -40,14 +40,13 @@
xQueueHandle appQueue;
void startMain(application* app) {
appQueue = xQueueCreate(APP_QUEUE_LEN, sizeof(struct event));
if(!appQueue) {
// TODO oops..
}
if(xTaskCreate(app->main, (const signed char*)app->name, APP_STACK_SIZE,
NULL, APP_PRIORITY, NULL) != pdPASS) {
// TODO oops..
}
appQueue = xQueueCreate(APP_QUEUE_LEN, sizeof(struct event));
if(!appQueue) {
// TODO oops..
}
if(xTaskCreate(app->main, (const signed char*)app->name, APP_STACK_SIZE,
NULL, APP_PRIORITY, NULL) != pdPASS) {
// TODO oops..
}
}
......@@ -42,14 +42,14 @@ extern xQueueHandle appQueue;
* @brief An application entry, used by the menu application.
*/
typedef struct {
///> Application name
const char* name;
/**
* @brief Main application routine.
* @params Optional parameters, dependendent on application.
*/
void (*main)(void* params);
///> Application name
const char* name;
/**
* @brief Main application routine.
* @params Optional parameters, dependendent on application.
*/
void (*main)(void* params);
} application;
/**
......
......@@ -38,107 +38,106 @@ static struct rtc_time rtc;
static struct tm cur_time;
static void digital_watch_redraw(struct ui_widget *w) {
char buf[32];
char buf[32];
gfx_clear(&w->dc, 0);
gfx_clear(&w->dc, 0);
strftime(buf, sizeof(buf), "%H:%M", &cur_time);
gfx_text(&w->dc, &font_helv38b, 4, 0, buf, 1);
strftime(buf, sizeof(buf), "%H:%M", &cur_time);
gfx_text(&w->dc, &font_helv38b, 4, 0, buf, 1);
// sprintf must be used, so we can display msecs too
sprintf(buf, "%02d.%01d", cur_time.tm_sec, rtc.msecs / 100);
gfx_text(&w->dc, &font_helv22b, 88, 14, buf, 1);
// sprintf must be used, so we can display msecs too
sprintf(buf, "%02d.%01d", cur_time.tm_sec, rtc.msecs / 100);
gfx_text(&w->dc, &font_helv22b, 88, 14, buf, 1);
strftime(buf, sizeof(buf), "%a %d %b %Y", &cur_time);
gfx_centered_text(&w->dc, &font_helv17, 40, buf, 1);
strftime(buf, sizeof(buf), "%a %d %b %Y", &cur_time);
gfx_centered_text(&w->dc, &font_helv17, 40, buf, 1);
}
static void digital_watch_event(struct ui_widget *w, const struct event *evt) {
// Hour has changed, it is time to redraw the clock
if(evt->type == RTC_TICK) {
rtc = rtc_get_time();
localtime_r((time_t*) &rtc.epoch, &cur_time);
// Hour has changed, it is /* TODO: */ime to redraw the clock
if(evt->type == RTC_TICK) {
rtc = rtc_get_time();
localtime_r((time_t*) &rtc.epoch, &cur_time);
w->flags |= WF_DIRTY;
}
w->flags |= WF_DIRTY;
}
}
struct ui_widget digital_watch = {
digital_watch_redraw,
digital_watch_event,
{ 0, 35, 127, 35 + 58 },
0,
WF_ACTIVE | WF_VISIBLE
digital_watch_redraw,
digital_watch_event,
{ 0, 35, 127, 35 + 58 },
0,
WF_ACTIVE | WF_VISIBLE
};
struct ui_widget clock_screen = {
NULL,
NULL,
{ 0, 0, 127, 127 },
0,
WF_ACTIVE | WF_VISIBLE
NULL,
NULL,
{ 0, 0, 127, 127 },
0,
WF_ACTIVE | WF_VISIBLE
};
void clock_main(void* params) {
(void)(params); // suppress unused parameter warning
struct event evt;
(void)(params); // suppress unused parameter warning
struct event evt;
// Restore clock
rtc = rtc_get_time();
localtime_r((time_t*) &rtc.epoch, &cur_time);
// Restore clock
rtc = rtc_get_time();
localtime_r((time_t*) &rtc.epoch, &cur_time);
// Initialize user interface
ui_clear();
// Initialize user interface
ui_clear();
ui_init_widget(&clock_screen);
ui_init_widget(&digital_watch);
ui_init_widget(&clock_screen);
ui_init_widget(&digital_watch);
ui_add_widget(&digital_watch);
ui_add_child(&clock_screen, &digital_watch);
ui_add_widget(&clock_screen);
ui_add_widget(&digital_watch);
ui_add_child(&clock_screen, &digital_watch);
ui_add_widget(&clock_screen);
ui_init_widget(&status_bar);
ui_add_widget(&status_bar);
ui_init_widget(&status_bar);
ui_add_widget(&status_bar);
// Draw the screen
ui_update(NULL);
// Draw the screen
ui_update(NULL);
// Event loop
while(1) {
if(xQueueReceive(appQueue, &evt, portMAX_DELAY)) {
switch(evt.type) {
case BUTTON_PRESSED:
if (evt.data.button == BUT_TR ||
evt.data.button == BUT_TL)
// Event loop
while(1) {
if(xQueueReceive(appQueue, &evt, portMAX_DELAY)) {
switch(evt.type) {
case BUTTON_PRESSED:
if (evt.data.button == BUT_TR ||
evt.data.button == BUT_TL)
return; // go back to the main menu
// no break; fall through
default: // suppress warnings
ui_update(&evt); // forward event to widgets
break;
}
}
}
// no break; fall through
default: // suppress warnings
ui_update(&evt); // forward event to widgets
break;
}
}
}
}
application clock_app = {
.name = "Clock",
.main = clock_main
.name = "Clock",
.main = clock_main
};
// Settings
struct tm clock_get_time(void) {
rtc = rtc_get_time();
localtime_r((time_t*) &rtc.epoch, &cur_time);
rtc = rtc_get_time();
localtime_r((time_t*) &rtc.epoch, &cur_time);
return cur_time;
return cur_time;
}
void clock_set_time(struct tm *time) {
struct rtc_time r;
r.msecs = 0;
r.epoch = mktime(time);
struct rtc_time r;
r.msecs = 0;
r.epoch = mktime(time);
rtc_set_time(r);
rtc_set_time(r);
}
......@@ -135,8 +135,8 @@ void compass_main(void *params)
if(xQueueReceive(appQueue, &evt, 50 / portTICK_RATE_MS)) {
switch(evt.type) {
case BUTTON_PRESSED:
if (evt.data.button == BUT_TR ||
evt.data.button == BUT_TL)
if (evt.data.button == BUT_TR ||
evt.data.button == BUT_TL)
return;
/*if(evt.data.button == BUT_BR) {
......
......@@ -37,131 +37,130 @@ static char message[32] = "hello world";
static void widget_redraw(struct ui_widget *w)
{
gfx_clear(&w->dc, 0);
gfx_text(&w->dc, &font_helv17b, 0, 0, message, 1);
gfx_clear(&w->dc, 0);
gfx_text(&w->dc, &font_helv17b, 0, 0, message, 1);
}
static void widget_event(struct ui_widget *w, const struct event *evt)
{
// screen needs redrawing
w->flags |= WF_DIRTY;
switch(evt->type) {
case BUTTON_PRESSED:
switch(evt->data.button) {
case BUT_TR: // top right button
backlight_set_level(backlight_get_level() + 10);
sprintf(message, "top right (bl: %d)", backlight_get_level());
break;
case BUT_BR: // bottom right button
backlight_set_level(backlight_get_level() - 10);
sprintf(message, "bot right (bl: %d)", backlight_get_level());
break;
case BUT_BL: // bottom left button
strcpy(message, "bot left");
break;
case BUT_TL: // this should not happen, it is handled
break; // in the main loop
}
// short vibration
vibra_enable();
vTaskDelay(400 / portTICK_RATE_MS);
vibra_disable();
break;
case RTC_TICK:
// tick-tock with a buzzer
buzzer_enable();
vTaskDelay(400 / portTICK_RATE_MS);
buzzer_disable();
// ok, we do not need redrawing
w->flags &= ~WF_DIRTY;
break;
default: // suppress warnings
// ok, we do not need redrawing
w->flags &= ~WF_DIRTY;
break;
}
// screen needs redrawing
w->flags |= WF_DIRTY;
switch(evt->type) {
case BUTTON_PRESSED:
switch(evt->data.button) {
case BUT_TR: // top right button
backlight_set_level(backlight_get_level() + 10);
sprintf(message, "top right (bl: %d)", backlight_get_level());
break;
case BUT_BR: // bottom right button
backlight_set_level(backlight_get_level() - 10);
sprintf(message, "bot right (bl: %d)", backlight_get_level());
break;
case BUT_BL: // bottom left button
strcpy(message, "bot left");
break;
case BUT_TL: // this should not happen, it is handled
break; // in the main loop
}
// short vibration
vibra_enable();
vTaskDelay(400 / portTICK_RATE_MS);
vibra_disable();
break;
case RTC_TICK:
// tick-tock with a buzzer
buzzer_enable();
vTaskDelay(400 / portTICK_RATE_MS);
buzzer_disable();
// ok, we do not need redrawing
w->flags &= ~WF_DIRTY;
break;
default: // suppress warnings
// ok, we do not need redrawing
w->flags &= ~WF_DIRTY;
break;
}
}
struct ui_widget widget = {
widget_redraw, // drawing function, called when widget is marked as dirty
widget_event, // event handler
{ 0, 20, 127, 59 }, // dimensions
0, // surface pointer; do not change
WF_ACTIVE | WF_VISIBLE // flags
widget_redraw, // drawing function, called when widget is marked as dirty
widget_event, // event handler
{ 0, 20, 127, 59 }, // dimensions
0, // surface pointer; do not change
WF_ACTIVE | WF_VISIBLE // flags
};
struct ui_widget example_screen = { // main screen, contains all widgets
NULL,
NULL,
{ 0, 0, 127, 127 },
0,
WF_ACTIVE | WF_VISIBLE
NULL,
NULL,
{ 0, 0, 127, 127 },
0,
WF_ACTIVE | WF_VISIBLE
};
void example_main(void* params) {
(void)(params); // suppress unused parameter warning
struct event evt;
// this is a good place for hardware initialization
// (configure interrupts, backlight settings, etc.)
// initialize user interface
ui_clear();
// initialize widgets before adding them
ui_init_widget(&example_screen);
ui_init_widget(&widget);
ui_add_widget(&widget);
// widget belongs to the main screen
ui_add_child(&example_screen, &widget);
ui_add_widget(&example_screen);
// if you want to have fullscreen just for you
// commenting the lines below will disable the status bar
ui_init_widget(&status_bar);
ui_add_widget(&status_bar);
// draw the screen for the first time
ui_update(NULL);
// event loop
while(1) {
// "0" in the line below, if you set it to a positive value then
// you may have a block of code that is executed when no event arrives
// for details, see below (else block)
if(xQueueReceive(appQueue, &evt, portMAX_DELAY)) {
switch(evt.type) {
// decide which events are relevant and should be handled
// you may save some cycles if you list them here instead of
// lazily handling all of them
case BUTTON_PRESSED:
// current convention is to use the top left button to go back
if(evt.data.button == BUT_TL)
return; // go back to the main menu
// no break; fall through
default: // suppress warnings
// ignore events that were not mentioned above
ui_update(&evt); // forward event to widgets
break;
}
}
else {
// that part is executed if timeout occurs
}
}
(void)(params); // suppress unused parameter warning
struct event evt;
// this is a good place for hardware initialization
// (configure interrupts, backlight settings, etc.)
// initialize user interface
ui_clear();
// initialize widgets before adding them
ui_init_widget(&example_screen);
ui_init_widget(&widget);
ui_add_widget(&widget);
// widget belongs to the main screen
ui_add_child(&example_screen, &widget);
ui_add_widget(&example_screen);
// if you want to have fullscreen just for you
// commenting the lines below will disable the status bar
ui_init_widget(&status_bar);
ui_add_widget(&status_bar);
// draw the screen for the first time
ui_update(NULL);
// event loop
while(1) {
// "0" in the line below, if you set it to a positive value then
// you may have a block of code that is executed when no event arrives
// for details, see below (else block)
if(xQueueReceive(appQueue, &evt, portMAX_DELAY)) {
switch(evt.type) {
// decide which events are relevant and should be handled
// you may save some cycles if you list them here instead of
// lazily handling all of them
case BUTTON_PRESSED:
// current convention is to use the top left button to go back
if(evt.data.button == BUT_TL)
return; // go back to the main menu
// no break; fall through
default: // suppress warnings
// ignore events that were not mentioned above
ui_update(&evt); // forward event to widgets
break;
}
}
else {
// that part is executed if timeout occurs
}
}
}
application example = {
.name = "Example", // this will be shown in menu
.main = example_main
.name = "Example", // this will be shown in menu
.main = example_main
};
......@@ -44,122 +44,122 @@ static int gpsscreen = 0;
static void gps_redraw(struct ui_widget *w)
{
char buf[16];
float latdeg;
float latmin;
float latsec;
float londeg;
float lonmin;
float lonsec;
coord_format = setting_coord_style.val;
if (gps_fixed())
gps_get_coord(&coord, coord_format);
/* Decompose degrees, mins, secs for formats 0 & 1 */
latdeg = coord.lat/100;
latmin = 100 * (latdeg - (int)latdeg);
latsec = coord.lat - (int)coord.lat;
londeg = coord.lon/100;
lonmin = 100 * (londeg - (int)londeg);
lonsec = coord.lon - (int)coord.lon;
gfx_clear(&w->dc, 0);
/* Display latitude and longitude depending on format */
if (gpsscreen == 0) {
if (coord_format == 0) {
/* raw [deg][min].[sec/60] */
sprintf(buf, "L: %d deg", (int)latdeg);
gfx_text(&w->dc, &font_helv22b, 0, 0, buf, 0);
sprintf(buf, "%2.4f'", latmin);
gfx_text(&w->dc, &font_helv22b, 22, 20, buf, 0);
sprintf(buf, "l: %d deg", (int)(londeg));
gfx_text(&w->dc, &font_helv22b, 0, 50, buf, 0);
sprintf(buf, "%2.4f'", lonmin);
gfx_text(&w->dc, &font_helv22b, 15, 70, buf, 0);
} else if (coord_format == 1) {
/* [deg] [min] [sec] */
sprintf(buf, "L: %d deg", (int)latdeg);
gfx_text(&w->dc, &font_helv22b, 0, 0, buf, 0);
sprintf(buf, "%d'%2.2f\"", (int)latmin, 100 * latsec);
gfx_text(&w->dc, &font_helv22b, 5, 20, buf, 0);
sprintf(buf, "l: %d deg", (int)londeg);
gfx_text(&w->dc, &font_helv22b, 0, 50, buf, 0);
sprintf(buf, "%d'%2.2f\"", (int)lonmin, 100 * lonsec);
gfx_text(&w->dc, &font_helv22b, 5, 70, buf, 0);
} else if (coord_format == 2) {
/* [deg].[min/60] */
sprintf(buf, "L: %2.4f", coord.lat);
gfx_text(&w->dc, &font_helv22b, 0, 0, buf, 0);
sprintf(buf, "l: %2.4f", coord.lon);
gfx_text(&w->dc, &font_helv22b, 5, 50, buf, 0);
}
/* Display elevation */
} else {
sprintf(buf, "elev:");
gfx_text(&w->dc, &font_helv22b, 0, 20, buf, 0);
sprintf(buf, "%5.3f", coord.elev);
gfx_text(&w->dc, &font_helv22b, 0, 40, buf, 0);
}
char buf[16];
float latdeg;
float latmin;
float latsec;
float londeg;
float lonmin;
float lonsec;
coord_format = setting_coord_style.val;
if (gps_fixed())
gps_get_coord(&coord, coord_format);
/* Decompose degrees, mins, secs for formats 0 & 1 */
latdeg = coord.lat/100;
latmin = 100 * (latdeg - (int)latdeg);
latsec = coord.lat - (int)coord.lat;
londeg = coord.lon/100;
lonmin = 100 * (londeg - (int)londeg);
lonsec = coord.lon - (int)coord.lon;
gfx_clear(&w->dc, 0);
/* Display latitude and longitude depending on format */
if (gpsscreen == 0) {
if (coord_format == 0) {
/* raw [deg][min].[sec/60] */
sprintf(buf, "L: %d deg", (int)latdeg);
gfx_text(&w->dc, &font_helv22b, 0, 0, buf, 0);
sprintf(buf, "%2.4f'", latmin);
gfx_text(&w->dc, &font_helv22b, 22, 20, buf, 0);
sprintf(buf, "l: %d deg", (int)(londeg));
gfx_text(&w->dc, &font_helv22b, 0, 50, buf, 0);
sprintf(buf, "%2.4f'", lonmin);
gfx_text(&w->dc, &font_helv22b, 15, 70, buf, 0);
} else if (coord_format == 1) {
/* [deg] [min] [sec] */
sprintf(buf, "L: %d deg", (int)latdeg);
gfx_text(&w->dc, &font_helv22b, 0, 0, buf, 0);
sprintf(buf, "%d'%2.2f\"", (int)latmin, 100 * latsec);
gfx_text(&w->dc, &font_helv22b, 5, 20, buf, 0);
sprintf(buf, "l: %d deg", (int)londeg);
gfx_text(&w->dc, &font_helv22b, 0, 50, buf, 0);
sprintf(buf, "%d'%2.2f\"", (int)lonmin, 100 * lonsec);
gfx_text(&w->dc, &font_helv22b, 5, 70, buf, 0);
} else if (coord_format == 2) {
/* [deg].[min/60] */
sprintf(buf, "L: %2.4f", coord.lat);
gfx_text(&w->dc, &font_helv22b, 0, 0, buf, 0);
sprintf(buf, "l: %2.4f", coord.lon);
gfx_text(&w->dc, &font_helv22b, 5, 50, buf, 0);
}
/* Display elevation */
} else {
sprintf(buf, "elev:");
gfx_text(&w->dc, &font_helv22b, 0, 20, buf, 0);
sprintf(buf, "%5.3f", coord.elev);
gfx_text(&w->dc, &font_helv22b, 0, 40, buf, 0);
}
}
static void gps_event(struct ui_widget *w, const struct event *evt)
{
if (evt->type == GPS_TICK || evt->type == BUTTON_PRESSED)
w->flags |= WF_DIRTY;
if (evt->type == GPS_TICK || evt->type == BUTTON_PRESSED)
w->flags |= WF_DIRTY;
}
static struct ui_widget gps_coord_display = {
gps_redraw,
gps_event,
{16, 16, 111, 111},
0,
WF_ACTIVE | WF_VISIBLE
gps_redraw,
gps_event,
{16, 16, 111, 111},
0,
WF_ACTIVE | WF_VISIBLE
};
static struct ui_widget gps_screen = {
NULL,
NULL,
{0, 0, 127, 127},
0,
WF_ACTIVE | WF_VISIBLE
NULL,
NULL,
{0, 0, 127, 127},
0,
WF_ACTIVE | WF_VISIBLE
};
void gpscoord_main(void *params)
{
/* suppress compiler warning */
(void) params;
/* suppress compiler warning */
(void) params;
struct event evt;
struct event evt;
/* Init UI */
ui_clear();
/* Init UI */
ui_clear();
ui_init_widget(&gps_screen);
ui_add_widget(&gps_screen);
ui_init_widget(&gps_screen);
ui_add_widget(&gps_screen);
ui_init_widget(&gps_coord_display);
ui_add_widget(&gps_coord_display);
ui_add_child(&gps_screen, &gps_coord_display);
ui_init_widget(&gps_coord_display);
ui_add_widget(&gps_coord_display);
ui_add_child(&gps_screen, &gps_coord_display);
ui_init_widget(&status_bar);
ui_add_widget(&status_bar);
ui_init_widget(&status_bar);
ui_add_widget(&status_bar);
ui_update(NULL);
ui_update(NULL);
while (1) {
if (xQueueReceive(appQueue, &evt, portMAX_DELAY)) {
switch (evt.type) {
case BUTTON_PRESSED:
if (evt.data.button == BUT_TR ||
evt.data.button == BUT_TL)
return;
while (1) {
if (xQueueReceive(appQueue, &evt, portMAX_DELAY)) {
switch (evt.type) {
case BUTTON_PRESSED:
if (evt.data.button == BUT_TR ||
evt.data.button == BUT_TL)
return;
// else if (evt.data.button == BUT_BR) {
// /*
// * Toggle between coordinate and
......@@ -170,16 +170,16 @@ void gpscoord_main(void *params)
// }
/* fall through */
case GPS_TICK:
ui_update(&evt);
default:
break;
}
}
}
case GPS_TICK:
ui_update(&evt);
default:
break;
}
}
}
}
application gpscoord = {
.name = "uerdefucami",
.main = gpscoord_main
.name = "uerdefucami",
.main = gpscoord_main
};
......@@ -52,174 +52,173 @@ static void menu_ui_init();
static void menu_screen_redraw(struct ui_widget *w)
{
int i;
int menu_limit = (menu_size < MAX_ENTRIES ? menu_size : MAX_ENTRIES);
gfx_clear(&w->dc, 0);
for(i = 0; i < menu_limit; ++i)
{
int pos = offset + i;
// draw a white background for the selected entry
if(pos == selected_item) {
gfx_box(&w->dc, LEFT_MARGIN, i * LINE_HEIGHT,
MENU_SCREEN_WIDTH, (i + 1) * LINE_HEIGHT, 1);
}
menu_entry *ent = &(*current_menu)->entries[pos];
// draw icon
if(ent->icon)
gfx_draw_bitmap(&w->dc, 0, i * LINE_HEIGHT, ent->icon);
// display label (either app or submenu)
if(ent->type == APP) {
application *a = ent->data.app;
gfx_text(&w->dc, &font_helv17, LEFT_MARGIN,
i * LINE_HEIGHT, a->name, i != selected_item);
} else if(ent->type == SUBMENU) {
menu_list *l = ent->data.submenu;
gfx_text(&w->dc, &font_helv17, LEFT_MARGIN,
i * LINE_HEIGHT, l->name, i != selected_item);
} else if (ent->type == SETTING) {
char s[16];
setting_t *set = ent->data.setting;
sprintf(s, "%s: %d", set->name, set->val);
// strcat(s, ": ")
// strcat(s, set->val);
gfx_text(&w->dc, &font_helv17, LEFT_MARGIN,
i * LINE_HEIGHT, s, i != selected_item);
int i;
int menu_limit = (menu_size < MAX_ENTRIES ? menu_size : MAX_ENTRIES);
gfx_clear(&w->dc, 0);
for(i = 0; i < menu_limit; ++i)
{
int pos = offset + i;
// draw a white background for the selected entry
if(pos == selected_item) {
gfx_box(&w->dc, LEFT_MARGIN, i * LINE_HEIGHT,
MENU_SCREEN_WIDTH, (i + 1) * LINE_HEIGHT, 1);
}
menu_entry *ent = &(*current_menu)->entries[pos];
// draw icon
if(ent->icon)
gfx_draw_bitmap(&w->dc, 0, i * LINE_HEIGHT, ent->icon);
// display label (either app or submenu)
if(ent->type == APP) {
application *a = ent->data.app;
gfx_text(&w->dc, &font_helv17, LEFT_MARGIN,
i * LINE_HEIGHT, a->name, i != selected_item);
} else if(ent->type == SUBMENU) {
menu_list *l = ent->data.submenu;
gfx_text(&w->dc, &font_helv17, LEFT_MARGIN,
i * LINE_HEIGHT, l->name, i != selected_item);
} else if (ent->type == SETTING) {
char s[16];
setting_t *set = ent->#define ata.setting;
sprintf(s, "%s: %d", set->name, set->val);
// strcat(s, ": ")
// strcat(s, set->val);
gfx_text(&w->dc, &font_helv17, LEFT_MARGIN,
i * LINE_HEIGHT, s, i != selected_item);
}
}
}
static void menu_screen_event(struct ui_widget *w, const struct event *evt)
{
// scroll through the menu if a button was pressed
if(evt->type == BUTTON_PRESSED) {
if(evt->data.button == BUT_BR) {
if(selected_item < menu_size - 1) {
++selected_item;
if(selected_item >= MAX_ENTRIES)
offset = selected_item - MAX_ENTRIES + 1;
} else {
selected_item = 0;
offset = 0;
}
w->flags |= WF_DIRTY;
} else if(evt->data.button == BUT_BL) {
if(selected_item > 0) {
--selected_item;
if(selected_item < offset)
offset = selected_item;
} else {
selected_item = menu_size - 1;
if (menu_size < MAX_ENTRIES)
offset = selected_item - menu_size + 1;
else
offset = selected_item - MAX_ENTRIES + 1;
}
w->flags |= WF_DIRTY;
}
}
// scroll through the menu if a button was pressed
if(evt->type == BUTTON_PRESSED) {
if(evt->data.button == BUT_BR) {
if(selected_item < menu_size - 1) {
++selected_item;
if(selected_item >= MAX_ENTRIES)
offset = selected_item - MAX_ENTRIES + 1;
} else {
selected_item = 0;
offset = 0;
}
w->flags |= WF_DIRTY;
} else if(evt->data.button == BUT_BL) {
if(selected_item > 0) {
--selected_item;
if(selected_item < offset)
offset = selected_item;
} else {
selected_item = menu_size - 1;
if (menu_size < MAX_ENTRIES)
offset = selected_item - menu_size + 1;
else
offset = selected_item - MAX_ENTRIES + 1;
}
w->flags |= WF_DIRTY;
}
}
}
struct ui_widget menu_screen = {
menu_screen_redraw,
menu_screen_event,
{ 0, STATUS_BAR_HEIGHT,
MENU_SCREEN_WIDTH, STATUS_BAR_HEIGHT + MENU_SCREEN_HEIGHT },
0,
WF_ACTIVE | WF_VISIBLE
menu_screen_redraw,
menu_screen_event,
{ 0, STATUS_BAR_HEIGHT,
MENU_SCREEN_WIDTH, STATUS_BAR_HEIGHT + MENU_SCREEN_HEIGHT },
0,
WF_ACTIVE | WF_VISIBLE
};
static void menu_ui_init() {
ui_clear();
ui_clear();
ui_init_widget(&menu_screen);
ui_add_widget(&menu_screen);
ui_init_widget(&menu_screen);
ui_add_widget(&menu_screen);
ui_init_widget(&status_bar);
ui_add_widget(&status_bar);
ui_init_widget(&status_bar);
ui_add_widget(&status_bar);
ui_update(NULL);
ui_update(NULL);
}
static void run(menu_entry *entry) {
if(entry->type == APP) {
entry->data.app->main(NULL);
} else if(entry->type == SUBMENU) {
selected_item = 0;
offset = 0;
menu_size = 0;
// keep the operation separate to avoid crashes
// when an interrupt goes off between the two following lines
*(current_menu + 1) = entry->data.submenu;
++current_menu;
menu_size = get_menu_size(*current_menu);
} else if (entry->type == SETTING) {
setting_change(entry->data.setting);
}
menu_ui_init();
if(entry->type == APP) {
entry->data.app->main(NULL);
} else if(entry->type == SUBMENU) {
selected_item = 0;
offset = 0;
menu_size = 0;
// keep the operation separate to avoid crashes
// when an interrupt goes off between the two following lines
*(current_menu + 1) = entry->data.submenu;
++current_menu;
menu_size = get_menu_size(*current_menu);
} else if (entry->type == SETTING) {
setting_change(entry->data.setting);
}
menu_ui_init();
}
static void go_back() {
if(current_menu == menu_stack) {
clock_app.main(NULL);
} else {
menu_size = 0;
selected_item = 0;
offset = 0;
--current_menu;
menu_size = get_menu_size(*current_menu);
}
menu_ui_init();
if(current_menu == menu_stack) {
clock_app.main(NULL);
} else {
menu_size = 0;
selected_item = 0;
offset = 0;
--current_menu;
menu_size = get_menu_size(*current_menu);
}
menu_ui_init();
}
void menu_main(void* params) {
(void)(params); // suppress unused parameter warning
struct event evt;
battery_update();
menu_size = get_menu_size(*current_menu);
// run clock as the the initial application
clock_app.main(NULL);
menu_ui_init();
// Once it is deactivated - display the menu
while(1) {
if(xQueueReceive(appQueue, &evt, portMAX_DELAY)) {
switch(evt.type) {
case BUTTON_PRESSED:
if(evt.data.button == BUT_TL) {
go_back();
} else if(evt.data.button == BUT_TR) {
// run the selected application or submenu
run(&(*current_menu)->entries[selected_item]);
} else {
ui_update(&evt);
}
break;
default: // suppress warnings
ui_update(&evt);
break;
}
}
}
(void)(params); // suppress unused parameter warning
struct event evt;
battery_update();
menu_size = get_menu_size(*current_menu);
// run clock as the the initial application
clock_app.main(NULL);
menu_ui_init();
// Once it is deactivated - display the menu
while(1) {
if(xQueueReceive(appQueue, &evt, portMAX_DELAY)) {
switch(evt.type) {
case BUTTON_PRESSED:
if(evt.data.button == BUT_TL) {
go_back();
} else if(evt.data.button == BUT_TR) {
// run the selected application or submenu
run(&(*current_menu)->entries[selected_item]);
} else {
ui_update(&evt);
}
break;
default: // suppress warnings
ui_update(&evt);
break;
}
}
}
}
application menu = {
.name = "Menu",
.main = menu_main
.name = "Menu",
.main = menu_main
};
......@@ -29,51 +29,50 @@
#include "settings/settings.h"
int get_menu_size(const menu_list *menu) {
int len = 0;
const menu_entry* ptr = menu->entries;
int len = 0;
const menu_entry* ptr = menu->entries;
// Look for sentinel
while((*ptr++).type != END) ++len;
// Look for sentinel
while((*ptr++).type != END) ++len;
return len;
return len;
}
menu_list gps_settings_menu = {
"GPS settings",
{
{ SETTING, NULL, { .setting = &setting_gps_on } },
{ SETTING, NULL, { .setting = &setting_coord_style } },
{ SETTING, NULL, { .setting = &setting_gps_sets_time } },
{ SETTING, NULL, { .setting = &setting_tracking } },
{ APP, &clock_icon, { .app = &set_gmt_ofs } },
{ APP, &clock_icon, { .app = &set_time_fr_gps } },
{ END, NULL, { NULL } }
}
"GPS settings",
{
{ SETTING, NULL, { .setting = &setting_gps_on } },
{ SETTING, NULL, { .setting = &setting_coord_style } },
{ SETTING, NULL, { .setting = &setting_gps_sets_time } },
{ SETTING, NULL, { .setting = &setting_tracking } },
{ APP, &clock_icon, { .app = &set_gmt_ofs } },
{ APP, &clock_icon, { .app = &set_time_fr_gps } },
{ END, NULL, { NULL } }
}
};
menu_list settings_menu = {
"Settings",
{
{ APP, &clock_icon, { .app = &set_time } },
{ APP, &date_icon, { .app = &set_date } },
{ SUBMENU, &gps_receiving, { .submenu = &gps_settings_menu } },
{ END, NULL, { NULL } }
}
"Settings",
{
{ APP, &clock_icon, { .app = &set_time } },
{ APP, &date_icon, { .app = &set_date } },
{ SUBMENU, &gps_receiving, { .submenu = &gps_settings_menu } },
{ END, NULL, { NULL } }
}
};
menu_list main_menu = {
"Main menu",
{
{ APP, &example_icon, { .app = &example } },
{ APP, &comp_ico, { .app = &compass } },
{ APP, &game_ico, { .app = &game} },
{ APP, &gps_receiving, { .app = &gpscoord} },
{ SUBMENU, &settings_icon, { .submenu = &settings_menu } },
"Main menu",
{
{ APP, &example_icon, { .app = &example } },
{ APP, &comp_ico, { .app = &compass } },
{ APP, &game_ico, { .app = &game} },
{ APP, &gps_receiving, { .app = &gpscoord} },
{ SUBMENU, &settings_icon, { .submenu = &settings_menu } },
#ifndef DEBUG
{ APP, &usb_ms_icon, { .app = &usb_ms } },
{ APP, &usb_ms_icon, { .app = &usb_ms } },
#endif /* DEBUG */
{ APP, &reset_icon, { .app = &reset} },
{ END, NULL, { NULL } }
{ APP, &reset_icon, { .app = &reset} },
{ END, NULL, { NULL } }
}
};
......@@ -35,10 +35,10 @@
* @brief Type of menu entry.
*/
enum entry_type {
APP,
SUBMENU,
SETTING,
END // sentinel, should be put as the last entry
APP,
SUBMENU,
SETTING,
END // sentinel, should be put as the last entry
};
/**
......@@ -49,15 +49,15 @@ enum entry_type {
* Settings are defined in settings/settings.h
*/
typedef struct menu_entry_t {
enum entry_type type;
enum entry_type type;
const struct rle_bitmap *icon;
const struct rle_bitmap *icon;
union {
application *app;
struct menu_list_t *submenu;
setting_t *setting;
} data;
union {
application *app;
struct menu_list_t *submenu;
setting_t *setting;
} data;
} menu_entry;
/**
......@@ -65,8 +65,8 @@ typedef struct menu_entry_t {
* of menu entries (submenu).
*/
typedef struct menu_list_t {
char name[16];
menu_entry entries[];
char name[16];
menu_entry entries[];
} menu_list;
/**
......
......@@ -35,58 +35,58 @@
static void reset_redraw(struct ui_widget *w)
{
gfx_text(&w->dc, &font_helv22b, 10, 50, "Bottom right", 0);
gfx_text(&w->dc, &font_helv22b, 20, 70, "to reset", 0);
gfx_text(&w->dc, &font_helv22b, 10, 50, "Bottom right", 0);
gfx_text(&w->dc, &font_helv22b, 20, 70, "to reset", 0);
}
static struct ui_widget reset_screen = {
reset_redraw,
NULL,
{0, 0, 127, 127},
0,
WF_ACTIVE | WF_VISIBLE
reset_redraw,
NULL,
{0, 0, 127, 127},
0,
WF_ACTIVE | WF_VISIBLE
};
void reset_main(void *params)
{
(void) params; // suppress warnings
struct event evt;
(void) params; // suppress warnings
struct event evt;
/* Init UI */
ui_clear();
ui_init_widget(&reset_screen);
ui_add_widget(&reset_screen);
ui_init_widget(&status_bar);
ui_add_widget(&status_bar);
ui_update(NULL);
/* Init UI */
ui_clear();
ui_init_widget(&reset_screen);
ui_add_widget(&reset_screen);
ui_init_widget(&status_bar);
ui_add_widget(&status_bar);
ui_update(NULL);
while(1) {
if (xQueueReceive(appQueue, &evt, portMAX_DELAY)) {
switch (evt.type) {
case BUTTON_PRESSED:
if (evt.data.button == BUT_TR ||
evt.data.button == BUT_TL)
return;
/* Reset on bottom right and bottom left buttons
* pressed */
if (evt.data.button == BUT_BR)
SCB->AIRCR = 0x05FA0004;
// Turn GPS off if setting is ON, to prepare it for
// the turn-on pulse on reset
if (setting_get(&setting_gps_on)) {
int i;
gps_on_off_pulse();
for (i = 0; i < 1000000; i++)
;
}
break;
}
}
}
while(1) {
if (xQueueReceive(appQueue, &evt, portMAX_DELAY)) {
switch (evt.type) {
case BUTTON_PRESSED:
if (evt.data.button == BUT_TR ||
evt.data.button == BUT_TL)
return;
/* Reset on bottom right and bottom left buttons
* pressed */
if (evt.data.button == BUT_BR)
SCB->AIRCR = 0x05FA0004;
// Turn GPS off if setting is ON, to prepare it for
// the turn-on pulse on reset
if (setting_get(&setting_gps_on)) {
int i;
gps_on_off_pulse();
for (i = 0; i < 1000000; i++)
;
}
break;
}
}
}
}
application reset = {
.name = "Reset",
.main = reset_main
.name = "Reset",
.main = reset_main
};
......@@ -38,17 +38,17 @@ static const int SIZE_Y = 38;
static void set_date_redraw(struct ui_widget *w)
{
gfx_text(&w->dc, &font_helv38b, 36, POS_Y, "/", 1);
gfx_text(&w->dc, &font_helv38b, 80, POS_Y, "/", 1);
gfx_text(&w->dc, &font_helv38b, 36, POS_Y, "/", 1);
gfx_text(&w->dc, &font_helv38b, 80, POS_Y, "/", 1);
}
static struct ui_widget set_date_screen = {
&set_date_redraw,
NULL,
{ 0, 0, 127, 127 },
0,
WF_ACTIVE | WF_VISIBLE,
NULL
&set_date_redraw,
NULL,
{ 0, 0, 127, 127 },
0,
WF_ACTIVE | WF_VISIBLE,
NULL
};
#define SPINBOX_NUMBER 6
......@@ -59,9 +59,9 @@ static const char const *months1 = "01";
// Character sets for spinboxes
static const char **char_sets[SPINBOX_NUMBER] = {
&days1, &char_digits, // character set for days
&months1, &char_digits, // character set for months
&char_digits, &char_digits // character set for years
&days1, &char_digits, // character set for days
&months1, &char_digits, // character set for months
&char_digits, &char_digits // character set for years
};
// Spinboxes used for setting the hour & minute.
......@@ -72,147 +72,146 @@ static int sb_index;
static inline char sb_digit(int idx)
{
// convert ascii character to a digit by subtracting 0x30 ('0')
return spinbox_get_value(&sb_date[idx]) - '0';
// convert ascii character to a digit by subtracting 0x30 ('0')
return spinbox_get_value(&sb_date[idx]) - '0';
}
static bool is_leap(int year)
{
if(year < 1970) {
if(year < 70)
year += 2000;
else
year += 1900;
}
if (year % 400 == 0)
return true;
else if (year % 100 == 0)
return false;
else if (year % 4 == 0 )
return true;
else
return false;
if(year < 1970) {
if(year < 70)
year += 2000;
else
year += 1900;
}
if (year % 400 == 0)
return true;
else if (year % 100 == 0)
return false;
else if (year % 4 == 0 )
return true;
else
return false;
}
// Checks if spinboxes contain correct values
static bool is_valid(void)
{
const int days_per_month[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
const int days_per_month_leap[] = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
const int days_per_month[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
const int days_per_month_leap[] = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
int day = sb_digit(D1) * 10 + sb_digit(D2);
int month = sb_digit(M1) * 10 + sb_digit(M2);
int year = sb_digit(Y1) * 10 + sb_digit(Y2);
int day = sb_digit(D1) * 10 + sb_digit(D2);
int month = sb_digit(M1) * 10 + sb_digit(M2);
int year = sb_digit(Y1) * 10 + sb_digit(Y2);
int max_day = is_leap(year) ? days_per_month_leap[month - 1] : days_per_month[month - 1];
int max_day = is_leap(year) ? days_per_month_leap[month - 1] : days_per_month[month - 1];
return (day > 0 && day <= max_day && month > 0 && month < 13);
return (day > 0 && day <= max_day && month > 0 && month < 13);
}
// Sets the hour from spinboxes to clock
static void save(void)
{
struct tm time = clock_get_time();
struct tm time = clock_get_time();
time.tm_mday = sb_digit(D1) * 10 + sb_digit(D2);
time.tm_mon = sb_digit(M1) * 10 + sb_digit(M2) - 1;
time.tm_year = sb_digit(Y1) * 10 + sb_digit(Y2);
time.tm_mday = sb_digit(D1) * 10 + sb_digit(D2);
time.tm_mon = sb_digit(M1) * 10 + sb_digit(M2) - 1;
time.tm_year = sb_digit(Y1) * 10 + sb_digit(Y2);
// year ending with a number lower than 70 should be 20xx
if(time.tm_year < 70)
time.tm_year += 100;
// year ending with a number lower than 70 should be 20xx
if(time.tm_year < 70)
time.tm_year += 100;
clock_set_time(&time);
clock_set_time(&time);
}
// Sets the spinboxes to the current hour
static void load(void)
{
struct tm time = clock_get_time();
int year = time.tm_year - 100;
int month = time.tm_mon + 1;
spinbox_set_value(&sb_date[D1], (time.tm_mday / 10) + '0');
spinbox_set_value(&sb_date[D2], (time.tm_mday % 10) + '0');
spinbox_set_value(&sb_date[M1], (month / 10) + '0');
spinbox_set_value(&sb_date[M2], (month % 10) + '0');
spinbox_set_value(&sb_date[Y1], (year / 10) + '0');
spinbox_set_value(&sb_date[Y2], (year % 10) + '0');
struct tm time = clock_get_time();
int year = time.tm_year - 100;
int month = time.tm_mon + 1;
spinbox_set_value(&sb_date[D1], (time.tm_mday / 10) + '0');
spinbox_set_value(&sb_date[D2], (time.tm_mday % 10) + '0');
spinbox_set_value(&sb_date[M1], (month / 10) + '0');
spinbox_set_value(&sb_date[M2], (month % 10) + '0');
spinbox_set_value(&sb_date[Y1], (year / 10) + '0');
spinbox_set_value(&sb_date[Y2], (year % 10) + '0');
}
void set_date_main(void* params) {
(void)(params); // suppress unused parameter warning
struct event evt;
int i;
// initialize user interface
ui_clear();
// initialize widgets before adding them
for(i = 0; i < SPINBOX_NUMBER; ++i) {
struct rect pos = {POS_X + i * DIST_X + (i / 2 * 4), POS_Y,
POS_X + i * DIST_X + (i / 2 * 4) + SIZE_X, POS_Y + SIZE_Y};
spinbox_init_widget(&sb_date[i], pos, *char_sets[i]);
}
sb_index = D1;
spinbox_set_active(&sb_date[D1], true);
ui_init_widget(&set_date_screen);
for(i = 0; i < SPINBOX_NUMBER; ++i) {
ui_add_widget(&sb_date[i].widget);
}
// widget belongs to the main screen
for(i = 0; i < SPINBOX_NUMBER; ++i) {
ui_add_child(&set_date_screen, &sb_date[i].widget);
}
ui_add_widget(&set_date_screen);
ui_init_widget(&status_bar);
ui_add_widget(&status_bar);
load();
ui_update(NULL);
// event loop
while(1) {
if(xQueueReceive(appQueue, &evt, portMAX_DELAY)) {
switch(evt.type) {
case BUTTON_PRESSED:
if(evt.data.button == BUT_TL) {
return; // go back to the main menu
} else if(evt.data.button == BUT_TR) {
if(sb_index < SPINBOX_NUMBER - 1) {
spinbox_set_active(&sb_date[sb_index], false);
spinbox_set_active(&sb_date[++sb_index], true);
} else if(is_valid()) {
save();
return;
} else {
// the set hour is invalid, start from the beginning
spinbox_set_active(&sb_date[sb_index], false);
sb_index = D1;
spinbox_set_active(&sb_date[D1], true);
}
}
ui_update(&evt);
break;
/* Update UI on any event, so the status bar is updated */
default:
ui_update(&evt);
break;
}
}
}
(void)(params); // suppress unused parameter warning
struct event evt;
int i;
// initialize user interface
ui_clear();
// initialize widgets before adding them
for(i = 0; i < SPINBOX_NUMBER; ++i) {
struct rect pos = {POS_X + i * DIST_X + (i / 2 * 4), POS_Y,
POS_X + i * DIST_X + (i / 2 * 4) + SIZE_X, POS_Y + SIZE_Y};
spinbox_init_widget(&sb_date[i], pos, *char_sets[i]);
}
sb_index = D1;
spinbox_set_active(&sb_date[D1], true);
ui_init_widget(&set_date_screen);
for(i = 0; i < SPINBOX_NUMBER; ++i) {
ui_add_widget(&sb_date[i].widget);
}
// widget belongs to the main screen
for(i = 0; i < SPINBOX_NUMBER; ++i) {
ui_add_child(&set_date_screen, &sb_date[i].widget);
}
ui_add_widget(&set_date_screen);
ui_init_widget(&status_bar);
ui_add_widget(&status_bar);
load();
ui_update(NULL);
// event loop
while(1) {
if(xQueueReceive(appQueue, &evt, portMAX_DELAY)) {
switch(evt.type) {
case BUTTON_PRESSED:
if(evt.data.button == BUT_TL) {
return; // go back to the main menu
} else if(evt.data.button == BUT_TR) {
if(sb_index < SPINBOX_NUMBER - 1) {
spinbox_set_active(&sb_date[sb_index], false);
spinbox_set_active(&sb_date[++sb_index], true);
} else if(is_valid()) {
save();
return;
} else {
// the set hour is invalid, start from the beginning
spinbox_set_active(&sb_date[sb_index], false);
sb_index = D1;
spinbox_set_active(&sb_date[D1], true);
}
}
ui_update(&evt);
break;
/* Update UI on any event, so the status bar is updated */
default:
ui_update(&evt);
break;
}
}
}
}
application set_date = {
.name = "Set date", // this will be shown in menu
.main = set_date_main
.name = "Set date", // this will be shown in menu
.main = set_date_main
};
......@@ -38,16 +38,16 @@ static const int SIZE_Y = 38;
static void set_time_redraw(struct ui_widget *w)
{
gfx_text(&w->dc, &font_helv38b, POS_X + 3 * DIST_X - 9, POS_Y, ":", 1);
gfx_text(&w->dc, &font_helv38b, POS_X + 3 * DIST_X - 9, POS_Y, ":", 1);
}
static struct ui_widget set_time_screen = {
&set_time_redraw,
NULL,
{ 0, 0, 127, 127 },
0,
WF_ACTIVE | WF_VISIBLE,
NULL
&set_time_redraw,
NULL,
{ 0, 0, 127, 127 },
0,
WF_ACTIVE | WF_VISIBLE,
NULL
};
#define SPINBOX_NUMBER 5
......@@ -58,9 +58,9 @@ static const char const *hours1 = "01";
static const char const *minutes1 = "012345";
static const char **char_sets[SPINBOX_NUMBER] = {
&sign,
&hours1, &char_digits, // character set for hours
&minutes1, &char_digits // character set for minutes
&sign,
&hours1, &char_digits, // character set for hours
&minutes1, &char_digits // character set for minutes
};
// Spinboxes used for setting the hour & minute.
......@@ -71,134 +71,133 @@ static int sb_index;
static inline char sb_digit(int idx)
{
// convert ascii character to a digit by subtracting 0x30 ('0')
return spinbox_get_value(&sb_time[idx]) - '0';
// convert ascii character to a digit by subtracting 0x30 ('0')
return spinbox_get_value(&sb_time[idx]) - '0';
}
static inline char sb_sign()
{
return spinbox_get_value(&sb_time[S]);
return spinbox_get_value(&sb_time[S]);
}
// Checks if spinboxes contain correct values
static bool is_valid(void)
{
bool r = true;
if (sb_sign() == '-') {
if ((sb_digit(H1) == 1) && (sb_digit(H2) >= 3))
r = false;
} else if (sb_sign() == '+') {
if ((sb_digit(H1) == 1) && (sb_digit(H2) >= 5))
r = false;
}
return r;
bool r = true;
if (sb_sign() == '-') {
if ((sb_digit(H1) == 1) && (sb_digit(H2) >= 3))
r = false;
} else if (sb_sign() == '+') {
if ((sb_digit(H1) == 1) && (sb_digit(H2) >= 5))
r = false;
}
return r;
}
// Sets the hour from spinboxes to GMT offset variable
static void save(void)
{
int hr = setting_get(&setting_gmt_ofs_hr);
int min = setting_get(&setting_gmt_ofs_min);
int hr = setting_get(&setting_gmt_ofs_hr);
int min = setting_get(&setting_gmt_ofs_min);
hr = sb_digit(H1) * 10 + sb_digit(H2);
min = sb_digit(M1) * 10 + sb_digit(M2);
hr = sb_digit(H1) * 10 + sb_digit(H2);
min = sb_digit(M1) * 10 + sb_digit(M2);
if (sb_sign() == '-')
hr *= -1;
if (sb_sign() == '-')
hr *= -1;
/* setting_apply makes sure no interrupts occur while applying */
setting_apply(&setting_gmt_ofs_hr, hr);
setting_apply(&setting_gmt_ofs_min, min);
/* setting_apply makes sure no interrupts occur while applying */
setting_apply(&setting_gmt_ofs_hr, hr);
setting_apply(&setting_gmt_ofs_min, min);
}
// Sets the spinboxes to the current hour
static void load(void)
{
int hr = setting_get(&setting_gmt_ofs_hr);
int min = setting_get(&setting_gmt_ofs_min);
if (hr < 0) {
hr *= -1;
spinbox_set_value(&sb_time[S], '-');
}
spinbox_set_value(&sb_time[H1], (hr / 10) + '0');
spinbox_set_value(&sb_time[H2], (hr % 10) + '0');
spinbox_set_value(&sb_time[M1], (min / 10) + '0');
spinbox_set_value(&sb_time[M2], (min % 10) + '0');
int hr = setting_get(&setting_gmt_ofs_hr);
int min = setting_get(&setting_gmt_ofs_min);
if (hr < 0) {
hr *= -1;
spinbox_set_value(&sb_time[S], '-');
}
spinbox_set_value(&sb_time[H1], (hr / 10) + '0');
spinbox_set_value(&sb_time[H2], (hr % 10) + '0');
spinbox_set_value(&sb_time[M1], (min / 10) + '0');
spinbox_set_value(&sb_time[M2], (min % 10) + '0');
}
void set_gmt_ofs_main(void* params) {
(void)(params); // suppress unused parameter warning
struct event evt;
int i;
// initialize user interface
ui_clear();
// initialize widgets before adding them
for(i = 0; i < SPINBOX_NUMBER; ++i) {
struct rect pos = {POS_X + i * DIST_X, POS_Y,
POS_X + i * DIST_X + SIZE_X, POS_Y + SIZE_Y};
spinbox_init_widget(&sb_time[i], pos, *char_sets[i]);
}
sb_index = S;
spinbox_set_active(&sb_time[S], true);
ui_init_widget(&set_time_screen);
for(i = 0; i < SPINBOX_NUMBER; ++i) {
ui_add_widget(&sb_time[i].widget);
}
// widget belongs to the main screen
for(i = 0; i < SPINBOX_NUMBER; ++i) {
ui_add_child(&set_time_screen, &sb_time[i].widget);
}
ui_add_widget(&set_time_screen);
ui_init_widget(&status_bar);
ui_add_widget(&status_bar);
load();
ui_update(NULL);
// event loop
while(1) {
if(xQueueReceive(appQueue, &evt, portMAX_DELAY)) {
switch(evt.type) {
case BUTTON_PRESSED:
if(evt.data.button == BUT_TL) {
return; // go back to the main menu
} else if(evt.data.button == BUT_TR) {
if(sb_index < SPINBOX_NUMBER - 1) {
spinbox_set_active(&sb_time[sb_index], false);
spinbox_set_active(&sb_time[++sb_index], true);
} else if(is_valid()) {
save();
return;
} else {
// the set hour is invalid, start from the beginning
spinbox_set_active(&sb_time[sb_index], false);
sb_index = S;
spinbox_set_active(&sb_time[S], true);
}
}
ui_update(&evt);
break;
/* Update UI on any event, so the status bar is updated */
default:
ui_update(&evt);
break;
}
}
}
(void)(params); // suppress unused parameter warning
struct event evt;
int i;
// initialize user interface
ui_clear();
// initialize widgets before adding them
for(i = 0; i < SPINBOX_NUMBER; ++i) {
struct rect pos = {POS_X + i * DIST_X, POS_Y,
POS_X + i * DIST_X + SIZE_X, POS_Y + SIZE_Y};
spinbox_init_widget(&sb_time[i], pos, *char_sets[i]);
}
sb_index = S;
spinbox_set_active(&sb_time[S], true);
ui_init_widget(&set_time_screen);
for(i = 0; i < SPINBOX_NUMBER; ++i) {
ui_add_widget(&sb_time[i].widget);
}
// widget belongs to the main screen
for(i = 0; i < SPINBOX_NUMBER; ++i) {
ui_add_child(&set_time_screen, &sb_time[i].widget);
}
ui_add_widget(&set_time_screen);
ui_init_widget(&status_bar);
ui_add_widget(&status_bar);
load();
ui_update(NULL);
// event loop
while(1) {
if(xQueueReceive(appQueue, &evt, portMAX_DELAY)) {
switch(evt.type) {
case BUTTON_PRESSED:
if(evt.data.button == BUT_TL) {
return; // go back to the main menu
} else if(evt.data.button == BUT_TR) {
if(sb_index < SPINBOX_NUMBER - 1) {
spinbox_set_active(&sb_time[sb_index], false);
spinbox_set_active(&sb_time[++sb_index], true);
} else if(is_valid()) {
save();
return;
} else {
// the set hour is invalid, start from the beginning
spinbox_set_active(&sb_time[sb_index], false);
sb_index = S;
spinbox_set_active(&sb_time[S], true);
}
}
ui_update(&evt);
break;
/* Update UI on any event, so the status bar is updated */
default:
ui_update(&evt);
break;
}
}
}
}
application set_gmt_ofs = {
.name = "Set GMT offset", // this will be shown in menu
.main = set_gmt_ofs_main
.name = "Set GMT offset", // this will be shown in menu
.main = set_gmt_ofs_main
};
......@@ -38,16 +38,16 @@ static const int SIZE_Y = 38;
static void set_time_redraw(struct ui_widget *w)
{
gfx_centered_text(&w->dc, &font_helv38b, POS_Y, ":", 1);
gfx_centered_text(&w->dc, &font_helv38b, POS_Y, ":", 1);
}
static struct ui_widget set_time_screen = {
&set_time_redraw,
NULL,
{ 0, 0, 127, 127 },
0,
WF_ACTIVE | WF_VISIBLE,
NULL
&set_time_redraw,
NULL,
{ 0, 0, 127, 127 },
0,
WF_ACTIVE | WF_VISIBLE,
NULL
};
#define SPINBOX_NUMBER 4
......@@ -57,8 +57,8 @@ static const char const *hours1 = "012";
static const char const *minutes1 = "012345";
static const char **char_sets[SPINBOX_NUMBER] = {
&hours1, &char_digits, // character set for hours
&minutes1, &char_digits // character set for minutes
&hours1, &char_digits, // character set for hours
&minutes1, &char_digits // character set for minutes
};
// Spinboxes used for setting the hour & minute.
......@@ -69,113 +69,112 @@ static int sb_index;
static inline char sb_digit(int idx)
{
// convert ascii character to a digit by subtracting 0x30 ('0')
return spinbox_get_value(&sb_time[idx]) - '0';
// convert ascii character to a digit by subtracting 0x30 ('0')
return spinbox_get_value(&sb_time[idx]) - '0';
}
// Checks if spinboxes contain correct values
static bool is_valid(void)
{
int hour = sb_digit(H1) * 10 + sb_digit(H2);
int min = sb_digit(M1) * 10 + sb_digit(M2);
return (hour >= 0 && hour <= 23 && min >= 0 && min <= 59);
int hour = sb_digit(H1) * 10 + sb_digit(H2);
int min = sb_digit(M1) * 10 + sb_digit(M2);
return (hour >= 0 && hour <= 23 && min >= 0 && min <= 59);
}
// Sets the hour from spinboxes to clock
static void save(void)
{
struct tm time = clock_get_time();
struct tm time = clock_get_time();
time.tm_hour = sb_digit(H1) * 10 + sb_digit(H2);
time.tm_min = sb_digit(M1) * 10 + sb_digit(M2);
time.tm_sec = 0;
time.tm_hour = sb_digit(H1) * 10 + sb_digit(H2);
time.tm_min = sb_digit(M1) * 10 + sb_digit(M2);
time.tm_sec = 0;
clock_set_time(&time);
clock_set_time(&time);
}
// Sets the spinboxes to the current hour
static void load(void)
{
struct tm time = clock_get_time();
struct tm time = clock_get_time();
spinbox_set_value(&sb_time[H1], (time.tm_hour / 10) + '0');
spinbox_set_value(&sb_time[H2], (time.tm_hour % 10) + '0');
spinbox_set_value(&sb_time[M1], (time.tm_min / 10) + '0');
spinbox_set_value(&sb_time[M2], (time.tm_min % 10) + '0');
spinbox_set_value(&sb_time[H1], (time.tm_hour / 10) + '0');
spinbox_set_value(&sb_time[H2], (time.tm_hour % 10) + '0');
spinbox_set_value(&sb_time[M1], (time.tm_min / 10) + '0');
spinbox_set_value(&sb_time[M2], (time.tm_min % 10) + '0');
}
void set_time_main(void* params) {
(void)(params); // suppress unused parameter warning
struct event evt;
int i;
// initialize user interface
ui_clear();
// initialize widgets before adding them
for(i = 0; i < SPINBOX_NUMBER; ++i) {
struct rect pos = {POS_X + i * DIST_X, POS_Y,
POS_X + i * DIST_X + SIZE_X, POS_Y + SIZE_Y};
spinbox_init_widget(&sb_time[i], pos, *char_sets[i]);
}
sb_index = H1;
spinbox_set_active(&sb_time[H1], true);
ui_init_widget(&set_time_screen);
for(i = 0; i < SPINBOX_NUMBER; ++i) {
ui_add_widget(&sb_time[i].widget);
}
// widget belongs to the main screen
for(i = 0; i < SPINBOX_NUMBER; ++i) {
ui_add_child(&set_time_screen, &sb_time[i].widget);
}
ui_add_widget(&set_time_screen);
ui_init_widget(&status_bar);
ui_add_widget(&status_bar);
load();
ui_update(NULL);
// event loop
while(1) {
if(xQueueReceive(appQueue, &evt, portMAX_DELAY)) {
switch(evt.type) {
case BUTTON_PRESSED:
if(evt.data.button == BUT_TL) {
return; // go back to the main menu
} else if(evt.data.button == BUT_TR) {
if(sb_index < SPINBOX_NUMBER - 1) {
spinbox_set_active(&sb_time[sb_index], false);
spinbox_set_active(&sb_time[++sb_index], true);
} else if(is_valid()) {
save();
return;
} else {
// the set hour is invalid, start from the beginning
spinbox_set_active(&sb_time[sb_index], false);
sb_index = H1;
spinbox_set_active(&sb_time[H1], true);
}
}
ui_update(&evt);
break;
/* Update UI on any event, so the status bar is updated */
default:
ui_update(&evt);
break;
}
}
}
(void)(params); // suppress unused parameter warning
struct event evt;
int i;
// initialize user interface
ui_clear();
// initialize widgets before adding them
for(i = 0; i < SPINBOX_NUMBER; ++i) {
struct rect pos = {POS_X + i * DIST_X, POS_Y,
POS_X + i * DIST_X + SIZE_X, POS_Y + SIZE_Y};
spinbox_init_widget(&sb_time[i], pos, *char_sets[i]);
}
sb_index = H1;
spinbox_set_active(&sb_time[H1], true);
ui_init_widget(&set_time_screen);
for(i = 0; i < SPINBOX_NUMBER; ++i) {
ui_add_widget(&sb_time[i].widget);
}
// widget belongs to the main screen
for(i = 0; i < SPINBOX_NUMBER; ++i) {
ui_add_child(&set_time_screen, &sb_time[i].widget);
}
ui_add_widget(&set_time_screen);
ui_init_widget(&status_bar);
ui_add_widget(&status_bar);
load();
ui_update(NULL);
// event loop
while(1) {
if(xQueueReceive(appQueue, &evt, portMAX_DELAY)) {
switch(evt.type) {
case BUTTON_PRESSED:
if(evt.data.button == BUT_TL) {
return; // go back to the main menu
} else if(evt.data.button == BUT_TR) {
if(sb_index < SPINBOX_NUMBER - 1) {
spinbox_set_active(&sb_time[sb_index], false);
spinbox_set_active(&sb_time[++sb_index], true);
} else if(is_valid()) {
save();
return;
} else {
// the set hour is invalid, start from the beginning
spinbox_set_active(&sb_time[sb_index], false);
sb_index = H1;
spinbox_set_active(&sb_time[H1], true);
}
}
ui_update(&evt);
break;
/* Update UI on any event, so the status bar is updated */
default:
ui_update(&evt);
break;
}
}
}
}
application set_time = {
.name = "Set time", // this will be shown in menu
.main = set_time_main
.name = "Set time", // this will be shown in menu
.main = set_time_main
};
......@@ -30,28 +30,28 @@
void set_time_fr_gps_main(void *params)
{
/* Avoid compiler warning */
(void) params;
/* Avoid compiler warning */
(void) params;
struct tm time;
struct gps_utc gpstime;
struct tm time;
struct gps_utc gpstime;
if (gps_fixed()) {
gps_get_utc(&gpstime);
if (gps_fixed()) {
gps_get_utc(&gpstime);
time.tm_year = gpstime.yr;
time.tm_mon = gpstime.mon;
time.tm_mday = gpstime.day;
time.tm_hour = gpstime.hr + setting_get(&setting_gmt_ofs_hr);
time.tm_min = gpstime.min + setting_get(&setting_gmt_ofs_min);
time.tm_sec = gpstime.sec;
time.tm_isdst = 0;
time.tm_year = gpstime.yr;
time.tm_mon = gpstime.mon;
time.tm_mday = gpstime.day;
time.tm_hour = gpstime.hr + setting_get(&setting_gmt_ofs_hr);
time.tm_min = gpstime.min + setting_get(&setting_gmt_ofs_min);
time.tm_sec = gpstime.sec;
time.tm_isdst = 0;
clock_set_time(&time);
}
clock_set_time(&time);
}
}
application set_time_fr_gps = {
.name = "Set time fr GPS", // this will be shown in menu
.main = set_time_fr_gps_main
.name = "Set time fr GPS", // this will be shown in menu
.main = set_time_fr_gps_main
};
......@@ -43,70 +43,70 @@ static EE_Variable_TypeDef gps_on, coord_style, gps_sets_time,
void setting_init()
{
/* Start adding virtual addresses to allocated variables */
EE_DeclareVariable(&gps_on);
EE_DeclareVariable(&coord_style);
EE_DeclareVariable(&gps_sets_time);
EE_DeclareVariable(&gmt_ofs_hr);
EE_DeclareVariable(&gmt_ofs_min);
EE_DeclareVariable(&tracking);
/*
* Place these virtual addresses to the RAM-stored structs, so we can pass
* them to setting_apply() when called
*/
setting_gps_on.fladdr = gps_on.virtualAddress;
setting_coord_style.fladdr = coord_style.virtualAddress;
setting_gps_sets_time.fladdr = gps_sets_time.virtualAddress;
setting_gmt_ofs_hr.fladdr = gmt_ofs_hr.virtualAddress;
setting_gmt_ofs_min.fladdr = gmt_ofs_min.virtualAddress;
setting_tracking.fladdr = tracking.virtualAddress;
/*
* EE_Init() fails if the virtual addresses are not found in the flash. If
* it fails, we write the default setting values. Otherwise, we apply the
* settings in the flash to the setting values in RAM
*/
if (!EE_Init(2)) {
EE_Format(2);
EE_Write(&gps_on, setting_gps_on.val);
EE_Write(&coord_style, setting_coord_style.val);
EE_Write(&gps_sets_time, setting_gps_sets_time.val);
EE_Write(&gmt_ofs_hr, setting_gmt_ofs_hr.val);
EE_Write(&gmt_ofs_min, setting_gmt_ofs_min.val);
EE_Write(&tracking, setting_tracking.val);
} else {
EE_Read(&gps_on, &setting_gps_on.val);
EE_Read(&coord_style, &setting_coord_style.val);
EE_Read(&gps_sets_time, &setting_gps_sets_time.val);
EE_Read(&gmt_ofs_hr, &setting_gmt_ofs_hr.val);
EE_Read(&gmt_ofs_min, &setting_gmt_ofs_min.val);
EE_Read(&tracking, &setting_tracking.val);
}
/* Start adding virtual addresses to allocated variables */
EE_DeclareVariable(&gps_on);
EE_DeclareVariable(&coord_style);
EE_DeclareVariable(&gps_sets_time);
EE_DeclareVariable(&gmt_ofs_hr);
EE_DeclareVariable(&gmt_ofs_min);
EE_DeclareVariable(&tracking);
/*
* Place these virtual addresses to the RAM-stored structs, so we can pass
* them to setting_apply() when called
*/
setting_gps_on.fladdr = gps_on.virtualAddress;
setting_coord_style.fladdr = coord_style.virtualAddress;
setting_gps_sets_time.fladdr = gps_sets_time.virtualAddress;
setting_gmt_ofs_hr.fladdr = gmt_ofs_hr.virtualAddress;
setting_gmt_ofs_min.fladdr = gmt_ofs_min.virtualAddress;
setting_tracking.fladdr = tracking.virtualAddress;
/*
* EE_Init() fails if the virtual addresses are not found in the flash. If
* it fails, we write the default setting values. Otherwise, we apply the
* settings in the flash to the setting values in RAM
*/
if (!EE_Init(2)) {
EE_Format(2);
EE_Write(&gps_on, setting_gps_on.val);
EE_Write(&coord_style, setting_coord_style.val);
EE_Write(&gps_sets_time, setting_gps_sets_time.val);
EE_Write(&gmt_ofs_hr, setting_gmt_ofs_hr.val);
EE_Write(&gmt_ofs_min, setting_gmt_ofs_min.val);
EE_Write(&tracking, setting_tracking.val);
} else {
EE_Read(&gps_on, &setting_gps_on.val);
EE_Read(&coord_style, &setting_coord_style.val);
EE_Read(&gps_sets_time, &setting_gps_sets_time.val);
EE_Read(&gmt_ofs_hr, &setting_gmt_ofs_hr.val);
EE_Read(&gmt_ofs_min, &setting_gmt_ofs_min.val);
EE_Read(&tracking, &setting_tracking.val);
}
}
void setting_change(setting_t *setting)
{
int v = setting->val;
int v = setting->val;
v++;
v %= setting->nrvals;
v++;
v %= setting->nrvals;
setting_apply(setting, v);
setting_apply(setting, v);
}
void setting_apply(setting_t *setting, int val)
{
EE_Variable_TypeDef eevar;
eevar.virtualAddress = setting->fladdr;
EE_Variable_TypeDef eevar;
eevar.virtualAddress = setting->fladdr;
taskENTER_CRITICAL();
setting->val = val;
EE_Write(&eevar, val);
taskEXIT_CRITICAL();
taskENTER_CRITICAL();
setting->val = val;
EE_Write(&eevar, val);
taskEXIT_CRITICAL();
}
int setting_get(setting_t *setting)
{
return setting->val;
return setting->val;
}
......@@ -33,9 +33,9 @@
#include <stdint.h>
typedef struct setting {
char name[16];
uint16_t val; // uint16_t to comply to eeprom_emulation code
uint16_t nrvals;
char name[16];
uint16_t val; // uint16_t to comply to eeprom_emulation code
uint16_t nrvals;
uint16_t fladdr;
} setting_t;
......@@ -57,5 +57,3 @@ void setting_apply(setting_t *setting, int val);
int setting_get(setting_t *setting);
#endif /* SETTINGS_H */
......@@ -41,82 +41,81 @@ extern xSemaphoreHandle mutexSdCardAccess;
static void usb_ms_redraw(struct ui_widget *w)
{
gfx_clear(&w->dc, 0);
gfx_clear(&w->dc, 0);
gfx_centered_text(&w->dc, &font_helv17b, 30, "USB mass storage", 1);
gfx_centered_text(&w->dc, &font_helv17b, 30, "USB mass storage", 1);
if (mutexours && init_ok) {
gfx_centered_text(&w->dc, &font_helv17b, 30 + 18, "enabled", 1);
if (mutexours && init_ok) {
gfx_centered_text(&w->dc, &font_helv17b, 30 + 18, "enabled", 1);
gfx_centered_text(&w->dc, &font_helv11, 80, "unmount the device", 1);
gfx_centered_text(&w->dc, &font_helv11, 80 + 12, "before unplugging", 1);
} else if (!mutexours) {
gfx_centered_text(&w->dc, &font_helv17b, 80, "media in use", 1);
} else {
gfx_centered_text(&w->dc, &font_helv17b, 80, "media error", 1);
}
gfx_centered_text(&w->dc, &font_helv11, 80, "unmount the device", 1);
gfx_centered_text(&w->dc, &font_helv11, 80 + 12, "before unplugging", 1);
} else if (!mutexours) {
gfx_centered_text(&w->dc, &font_helv17b, 80, "media in use", 1);
} else {
gfx_centered_text(&w->dc, &font_helv17b, 80, "media error", 1);
}
}
struct ui_widget usb_ms_screen = {
usb_ms_redraw,
NULL,
{ 0, 0, 127, 127 },
0,
WF_ACTIVE | WF_VISIBLE,
NULL
usb_ms_redraw,
NULL,
{ 0, 0, 127, 127 },
0,
WF_ACTIVE | WF_VISIBLE,
NULL
};
void usb_ms_main(void* params) {
(void)(params); // suppress unused parameter warning
struct event evt;
ui_clear();
ui_init_widget(&usb_ms_screen);
ui_add_widget(&usb_ms_screen);
ui_init_widget(&status_bar);
ui_add_widget(&status_bar);
if (xSemaphoreTake(mutexSdCardAccess, 0)) {
mutexours = 1;
init_ok = MSDDMEDIA_Init();
if(init_ok) {
MSDD_Init(-1, -1);
}
}
ui_update(NULL);
while(1) {
if(xQueueReceive(appQueue, &evt, 0)) {
switch(evt.type) {
case BUTTON_PRESSED:
if (evt.data.button == BUT_TR ||
evt.data.button == BUT_TL) {
if (mutexours) {
mutexours = 0;
USBD_Stop();
xSemaphoreGive(mutexSdCardAccess);
}
return; // go back to the main menu
}
break;
default: // suppress warnings
// ignore events that were not mentioned above
ui_update(&evt);
break;
}
} else if (mutexours) {
MSDD_Handler();
}
}
(void)(params); // suppress unused parameter warning
struct event evt;
ui_clear();
ui_init_widget(&usb_ms_screen);
ui_add_widget(&usb_ms_screen);
ui_init_widget(&status_bar);
ui_add_widget(&status_bar);
if (xSemaphoreTake(mutexSdCardAccess, 0)) {
mutexours = 1;
init_ok = MSDDMEDIA_Init();
if(init_ok) {
MSDD_Init(-1, -1);
}
}
ui_update(NULL);
while(1) {
if(xQueueReceive(appQueue, &evt, 0)) {
switch(evt.type) {
case BUTTON_PRESSED:
if (evt.data.button == BUT_TR ||
evt.data.button == BUT_TL) {
if (mutexours) {
mutexours = 0;
USBD_Stop();
xSemaphoreGive(mutexSdCardAccess);
}
return; // go back to the main menu
}
break;
default: // suppress warnings
// ignore events that were not mentioned above
ui_update(&evt);
break;
}
} else if (mutexours) {
MSDD_Handler();
}
}
}
application usb_ms = {
.name = "USB drive",
.main = usb_ms_main
.name = "USB drive",
.main = usb_ms_main
};
......@@ -34,76 +34,75 @@ const char *char_letters = "abcdefghijklmnopqrstuvwxyz";
static void spinbox_event(struct ui_widget *w, const struct event *evt)
{
struct spinbox *s = (struct spinbox*) w->data;
struct spinbox *s = (struct spinbox*) w->data;
if(s->active && evt->type == BUTTON_PRESSED) {
if(evt->data.button == BUT_BR) {
if(s->chars[s->value_idx + 1] != 0) {
++s->value_idx;
} else {
s->value_idx = 0;
}
w->flags |= WF_DIRTY;
} else if(evt->data.button == BUT_BL) {
if(s->value_idx > 0) {
--s->value_idx;
} else {
s->value_idx = strlen(s->chars) - 1;
}
w->flags |= WF_DIRTY;
}
}
if(s->active && evt->type == BUTTON_PRESSED) {
if(evt->data.button == BUT_BR) {
if(s->chars[s->value_idx + 1] != 0) {
++s->value_idx;
} else {
s->value_idx = 0;
}
w->flags |= WF_DIRTY;
} else if(evt->data.button == BUT_BL) {
if(s->value_idx > 0) {
--s->value_idx;
} else {
s->value_idx = strlen(s->chars) - 1;
}
w->flags |= WF_DIRTY;
}
}
}
static void spinbox_redraw(struct ui_widget *w)
{
struct spinbox *s = (struct spinbox*) w->data;
const char buf[] = { spinbox_get_value(s), 0 }; // add the string terminator
int width = gfx_text_width(s->font, buf);
struct spinbox *s = (struct spinbox*) w->data;
const char buf[] = { spinbox_get_value(s), 0 }; // add the string terminator
int width = gfx_text_width(s->font, buf);
gfx_clear(&w->dc, 0);
gfx_text(&w->dc, s->font, 0, 0, buf, 1);
gfx_clear(&w->dc, 0);
gfx_text(&w->dc, s->font, 0, 0, buf, 1);
// underline
if(s->active) {
gfx_line(&w->dc, 0, s->font->height,
// underline
if(s->active) {
gfx_line(&w->dc, 0, s->font->height,
0 + width, s->font->height, 1);
gfx_line(&w->dc, 0, s->font->height - 1,
gfx_line(&w->dc, 0, s->font->height - 1,
0 + width, s->font->height - 1, 1);
}
}
}
void spinbox_init_widget(struct spinbox *s, struct rect pos, const char *character_set)
{
s->chars = character_set;
s->value_idx = 0;
s->active = false;
s->chars = character_set;
s->value_idx = 0;
s->active = false;
s->widget.redraw = &spinbox_redraw;
s->widget.event = &spinbox_event;
s->widget.pos = pos;
s->widget.order = 0;
s->widget.flags = WF_ACTIVE | WF_VISIBLE;
s->widget.data = (void*)s;
spinbox_set_font(s, &font_helv38b);
ui_init_widget(&s->widget);
s->widget.redraw = &spinbox_redraw;
s->widget.event = &spinbox_event;
s->widget.pos = pos;
s->widget.order = 0;
s->widget.flags = WF_ACTIVE | WF_VISIBLE;
s->widget.data = (void*)s;
spinbox_set_font(s, &font_helv38b);
ui_init_widget(&s->widget);
}
void spinbox_set_font(struct spinbox *s, const struct font *f)
{
s->font = f;
s->font = f;
}
void spinbox_set_value(struct spinbox *s, char val)
{
int idx = 0;
int idx = 0;
while(s->chars[idx]) {
if(s->chars[idx] == val) {
s->value_idx = idx;
break;
}
++idx;
}
while(s->chars[idx]) {
if(s->chars[idx] == val) {
s->value_idx = idx;
break;
}
++idx;
}
}
......@@ -37,20 +37,20 @@ extern const char *char_digits;
extern const char *char_letters;
struct spinbox {
///> UI widget that represents the spinbox.
struct ui_widget widget;
///> UI widget that represents the spinbox.
struct ui_widget widget;
///> Possible values to choose from.
const char *chars;
///> Possible values to choose from.
const char *chars;
///> Font used to display the value.
const struct font *font;
///> Font used to display the value.
const struct font *font;
///> Current index in the chars[] array.
int value_idx;
///> Current index in the chars[] array.
int value_idx;
///> Is it active spinbox?
bool active;
///> Is it active spinbox?
bool active;
};
/**
......@@ -78,7 +78,7 @@ void spinbox_set_font(struct spinbox *s, const struct font *f);
*/
inline static char spinbox_get_value(const struct spinbox *s)
{
return s->chars[s->value_idx];
return s->chars[s->value_idx];
}
/**
......@@ -99,8 +99,8 @@ void spinbox_set_value(struct spinbox *s, char val);
*/
inline static void spinbox_set_active(struct spinbox *s, bool active)
{
s->active = active;
s->widget.flags |= WF_DIRTY;
s->active = active;
s->widget.flags |= WF_DIRTY;
}
#endif /* SPINBOX_H */
......@@ -52,79 +52,78 @@ static struct rle_bitmap track_ico;
static void status_bar_event(struct ui_widget *w, const struct event *evt)
{
switch(evt->type) {
case GPS_TICK:
if (gps_on()) {
if (gps_fixed()) {
memcpy(&gps_ico, &gps_receiving,
sizeof(struct rle_bitmap));
} else {
gps_ico_blink ^= 1;
if (gps_ico_blink) {
memcpy(&gps_ico, &gps_searching,
sizeof(struct rle_bitmap));
} else {
memset(&gps_ico, 0, sizeof(struct rle_bitmap));
}
}
} else {
memcpy(&gps_ico, 0, sizeof(struct rle_bitmap));
}
if (setting_get(&setting_tracking))
memcpy(&track_ico, &tracking, sizeof(struct rle_bitmap));
else
memset(&track_ico, 0, sizeof(struct rle_bitmap));
w->flags |= WF_DIRTY;
break;
case BATTERY_STATUS:
if(abs(percentage - evt->data.battery.percentage) > 5 ||
charging != evt->data.battery.charging) {
percentage = evt->data.battery.percentage;
charging = evt->data.battery.charging;
w->flags |= WF_DIRTY;
}
break;
}
switch(evt->type) {
case GPS_TICK:
if (gps_on()) {
if (gps_fixed()) {
memcpy(&gps_ico, &gps_receiving,
sizeof(struct rle_bitmap));
} else {
gps_ico_blink ^= 1;
if (gps_ico_blink) {
memcpy(&gps_ico, &gps_searching,
sizeof(struct rle_bitmap));
} else {
memset(&gps_ico, 0, sizeof(struct rle_bitmap));
}
}
} else {
memcpy(&gps_ico, 0, sizeof(struct rle_bitmap));
}
if (setting_get(&setting_tracking))
memcpy(&track_ico, &tracking, sizeof(struct rle_bitmap));
else
memset(&track_ico, 0, sizeof(struct rle_bitmap));
w->flags |= WF_DIRTY;
break;
case BATTERY_STATUS:
if(abs(percentage - evt->data.battery.percentage) > 5 ||
charging != evt->data.battery.charging) {
percentage = evt->data.battery.percentage;
charging = evt->data.battery.charging;
w->flags |= WF_DIRTY;
}
break;
}
}
static void status_bar_redraw(struct ui_widget *w)
{
unsigned i;
gfx_clear(&w->dc, 0);
/*gfx_round_box(&w->dc, 30, -10, 127 - 30, 10, 9, COLOR_BLACK);*/
/*gfx_centered_text(&w->dc, &font_helv11, 0, "Home", 1);*/
gfx_draw_bitmap(&w->dc, GPS_POS, 0, &gps_ico);
gfx_draw_bitmap(&w->dc, TRACK_POS, 0, &track_ico);
if(charging) {
gfx_draw_bitmap(&w->dc, BATTERY_POS, 0, &battery_charging);
} else {
gfx_draw_bitmap(&w->dc, BATTERY_POS, 0, &battery);
if(percentage > 100) {
// Indicate wrong reading (draw the exclamation mark)
gfx_line(&w->dc, BATTERY_POS + 6, 2, BATTERY_POS + 6, 7, 1);
gfx_set_pixel(&w->dc, BATTERY_POS + 6, 9, 1);
} else {
// Draw bars
for(i = 0; i < percentage / BATTERY_BARS; ++i)
gfx_line(&w->dc, BATTERY_POS + 2 + i, 2, BATTERY_POS + 2 + i, 9, 1);
}
}
unsigned i;
gfx_clear(&w->dc, 0);
/*gfx_round_box(&w->dc, 30, -10, 127 - 30, 10, 9, COLOR_BLACK);*/
/*gfx_centered_text(&w->dc, &font_helv11, 0, "Home", 1);*/
gfx_draw_bitmap(&w->dc, GPS_POS, 0, &gps_ico);
gfx_draw_bitmap(&w->dc, TRACK_POS, 0, &track_ico);
if(charging) {
gfx_draw_bitmap(&w->dc, BATTERY_POS, 0, &battery_charging);
} else {
gfx_draw_bitmap(&w->dc, BATTERY_POS, 0, &battery);
if(percentage > 100) {
// Indicate wrong reading (draw the exclamation mark)
gfx_line(&w->dc, BATTERY_POS + 6, 2, BATTERY_POS + 6, 7, 1);
gfx_set_pixel(&w->dc, BATTERY_POS + 6, 9, 1);
} else {
// Draw bars
for(i = 0; i < percentage / BATTERY_BARS; ++i)
gfx_line(&w->dc, BATTERY_POS + 2 + i, 2, BATTERY_POS + 2 + i, 9, 1);
}
}
}
struct ui_widget status_bar = {
status_bar_redraw,
status_bar_event,
{ 0, 0, 127, 15 },
0,
WF_ACTIVE | WF_VISIBLE
status_bar_redraw,
status_bar_event,
{ 0, 0, 127, 15 },
0,
WF_ACTIVE | WF_VISIBLE
};
......@@ -31,4 +31,3 @@
#define STATUS_BAR_HEIGHT 20
struct ui_widget status_bar;
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment