summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--apps/home_menu.cpp119
-rw-r--r--apps/home_menu.hpp29
-rw-r--r--base_app.hpp10
-rw-r--r--pico-watch.cpp58
4 files changed, 119 insertions, 97 deletions
diff --git a/apps/home_menu.cpp b/apps/home_menu.cpp
index 239ffda..a450c8f 100644
--- a/apps/home_menu.cpp
+++ b/apps/home_menu.cpp
@@ -8,80 +8,65 @@
extern void app_switch(int old_appid, int new_appid);
extern bool rtc_get_datetime(datetime_t *t);
-#define NUMBER_OF_APPS 3
-#define SIZE_APP_NAME 12
+void app_home_menu::title_str(char *buf, uint buf_size, const datetime_t *t) {
+ snprintf(buf,
+ buf_size,
+ "%d:%02d Home Menu",
+ t->hour,
+ t->min,
+ t->sec);
+};
-namespace app_home_menu {
- const char *APPS_NAME[NUMBER_OF_APPS] = {"Home", "Clock", "Settings"};
- int selected_app = 0;
- char display_app_name[SIZE_APP_NAME];
+void app_home_menu::show_title(Api *app_api) {
+ char datetime_buf[256];
+ char *datetime_str = &datetime_buf[0];
+ datetime_t t;
+ app_api->datetime_get(&t);
- void title_str(char *buf, uint buf_size, const datetime_t *t) {
- snprintf(buf,
- buf_size,
- "%d:%02d Home Menu",
- t->hour,
- t->min,
- t->sec);
- };
-
- void show_title(Api *app_api) {
- char datetime_buf[256];
- char *datetime_str = &datetime_buf[0];
- datetime_t t;
- app_api->datetime_get(&t);
-
- // title with time
- title_str(datetime_str, sizeof(datetime_buf), &t);
- app_api->gui_header_text((std::string)datetime_str);
- }
+ // title with time
+ title_str(datetime_str, sizeof(datetime_buf), &t);
+ app_api->gui_header_text((std::string)datetime_str);
+}
- // Rendering of app
- int render(Api *app_api) {
- show_title(app_api);
- app_api->display_write_string(0,5,3, display_app_name, FONT_12x16, 0, 1);
- return 0;
- }
+// Rendering of app
+int app_home_menu::render(Api *app_api) {
+ show_title(app_api);
+ app_api->display_write_string(0,5,3, display_app_name, FONT_12x16, 0, 1);
+ return 0;
+}
- // Example of how button inputs could be interpreted.
- // Drawing on screen should be done in the render function.
- int btnpressed(Api *app_api, uint gpio, unsigned long delta) {
- switch (gpio) {
- case BUTTON_SELECT:
- app_switch(0, selected_app);
- return 0;
- case BUTTON_DOWN:
- selected_app--;
- break;
- case BUTTON_UP:
- selected_app++;
- break;
- }
- if (selected_app > NUMBER_OF_APPS-1) {
- selected_app = NUMBER_OF_APPS-1;
- } else if (selected_app < 0) {
- selected_app = 0;
- }
- // Add spaces to avoid "ghost" characters from app names displayed before
- snprintf(display_app_name, SIZE_APP_NAME, "%s ", APPS_NAME[selected_app]);
- return 0;
+// Example of how button inputs could be interpreted.
+// Drawing on screen should be done in the render function.
+int app_home_menu::btnpressed(Api *app_api, uint gpio, unsigned long delta) {
+ switch (gpio) {
+ case BUTTON_SELECT:
+ app_switch(0, selected_app);
+ return 0;
+ case BUTTON_DOWN:
+ selected_app--;
+ break;
+ case BUTTON_UP:
+ selected_app++;
+ break;
}
-
- // Initlisation of the app.
- int init(Api *app_api) {
- app_api->performance_set(Api::perf_modes::LOW_POWER);
+ if (selected_app > NUMBER_OF_APPS-1) {
+ selected_app = NUMBER_OF_APPS-1;
+ } else if (selected_app < 0) {
selected_app = 0;
- snprintf(display_app_name, SIZE_APP_NAME, "%s", APPS_NAME[0]);
- return Api::app_init_return_status::OK;
}
+ // Add spaces to avoid "ghost" characters from app names displayed before
+ snprintf(display_app_name, SIZE_APP_NAME, "%s ", APPS_NAME[selected_app]);
+ return 0;
+}
- // Processor intensive operations and functions related to drawing to the screen should only be done when the app is in_foreground(=1). This function is only called when the app is init.
- int bgrefresh(Api *app_api, bool in_foreground) {
- return 1;
- }
+// Initlisation of the app.
+app_home_menu::app_home_menu(Api *app_api) {
+ app_api->performance_set(Api::perf_modes::LOW_POWER);
+ selected_app = 0;
+ snprintf(display_app_name, SIZE_APP_NAME, "%s", APPS_NAME[0]);
+}
- // Destruction of app, deinitlisation should be done here. This is only called if the app's APPS_DESTROY_ON_EXIT is set to 1. When it is not a "service" app.
- int destroy(Api *app_api) {
- return 0;
- }
+// Processor intensive operations and functions related to drawing to the screen should only be done when the app is in_foreground(=1). This function is only called when the app is init.
+int app_home_menu::bgrefresh(Api *app_api, bool in_foreground) {
+ return 1;
}
diff --git a/apps/home_menu.hpp b/apps/home_menu.hpp
index 78aed40..dce83e4 100644
--- a/apps/home_menu.hpp
+++ b/apps/home_menu.hpp
@@ -1,17 +1,26 @@
-#ifndef __HOME_MENU_H__
-#define __HOME_MENU_H__
+#pragma once
#include "pico/util/datetime.h"
#include "../oled/ss_oled.h"
#include "../api.hpp"
+#include "../base_app.hpp"
-namespace app_home_menu {
- int init(Api *app_api);
- int render(Api *app_api);
- int btnpressed(Api *app_api, uint gpio, unsigned long delta);
- int bgrefresh(Api *app_api, bool in_foreground);
- int destroy(Api *app_api);
-}
+#define NUMBER_OF_APPS 3
+#define SIZE_APP_NAME 12
-#endif
+class app_home_menu : public BaseApp {
+ private:
+ const char *APPS_NAME[NUMBER_OF_APPS] = {"Home", "Clock", "Settings"};
+ int selected_app = 0;
+ char display_app_name[SIZE_APP_NAME];
+ void title_str(char *buf, uint buf_size, const datetime_t *t);
+ void show_title(Api *app_api);
+ public:
+ uint app_id = 0;
+ app_home_menu(Api *app_api);
+ int render(Api *app_api);
+ int btnpressed(Api *app_api, uint gpio, unsigned long delta);
+ int bgrefresh(Api *app_api, bool in_foreground);
+ ~app_home_menu();
+};
diff --git a/base_app.hpp b/base_app.hpp
new file mode 100644
index 0000000..0950a01
--- /dev/null
+++ b/base_app.hpp
@@ -0,0 +1,10 @@
+#pragma once
+
+// Base app
+class BaseApp {
+ public:
+ uint app_id = 0; // CHECK: This has to be overwritten by derived classes
+ virtual int render(Api *app_api) = 0; // Has to be implemented
+ virtual int btnpressed(Api *app_api, uint gpio, unsigned long delta) {};
+ virtual int bgrefresh(Api *app_api, bool in_foreground) {};
+};
diff --git a/pico-watch.cpp b/pico-watch.cpp
index f75317e..7ce2f98 100644
--- a/pico-watch.cpp
+++ b/pico-watch.cpp
@@ -1,4 +1,5 @@
#include <stdio.h>
+#include <vector>
#include "pico/stdlib.h"
#include "hardware/i2c.h"
#include "hardware/sync.h"
@@ -8,6 +9,7 @@
#include "init.hpp"
#include "api.hpp"
#include "buttons.hpp"
+#include "base_app.hpp"
#include "apps/main_clock.hpp"
#include "apps/home_menu.hpp"
#include "apps/settings/main.hpp"
@@ -17,15 +19,19 @@ user_settings g_user;
Api app_api;
#define NUMBER_OF_APPS 3
-#define APP_DATA_BUFFER_LEN 256
-int (*APPS_FUNC_INIT[NUMBER_OF_APPS])(Api *app_api) = {app_home_menu::init, app_main_clock::init, app_settings::init};
-int (*APPS_FUNC_RENDER[NUMBER_OF_APPS])(Api *app_api) = {app_home_menu::render, app_main_clock::render, app_settings::render};
-int (*APPS_FUNC_BTNPRESS[NUMBER_OF_APPS])(Api *app_api, uint gpio, unsigned long delta) = {app_home_menu::btnpressed, app_main_clock::btnpressed, app_settings::btnpressed};
-int (*APPS_FUNC_BGREFRESH[NUMBER_OF_APPS])(Api *app_api, bool in_foreground) = {app_home_menu::bgrefresh, app_main_clock::bgrefresh, app_settings::bgrefresh};
-int (*APPS_FUNC_DESTROY[NUMBER_OF_APPS])(Api *app_api) = {app_home_menu::destroy, app_main_clock::destroy, app_settings::destroy};
+
+std::vector<BaseApp*> open_apps;
+
int APPS_DESTROY_ON_EXIT[NUMBER_OF_APPS] = {0, 1, 1};
int APPS_IS_INIT[NUMBER_OF_APPS] = {0}; // Only run in background if init
+int app_create(int app_id) {
+ switch (app_id) {
+ case 0: open_apps.push_back(new app_home_menu(&app_api)); break;
+ default: __breakpoint();
+ }
+}
+
int app_init(int app_id) {
app_api.display_fill(0,1); // Clear OLED
app_api.performance_render_interval_set(500); // Reset interval
@@ -36,7 +42,8 @@ int app_init(int app_id) {
}
if (!APPS_IS_INIT[app_id]) {
- int status = (*APPS_FUNC_INIT[app_id])(&app_api);
+ app_create(app_id);
+ /* int status = (*APPS_FUNC_INIT[app_id])(&app_api);
switch (status) {
case Api::app_init_return_status::MALLOC_FAILED:
@@ -55,31 +62,40 @@ int app_init(int app_id) {
default: // OK and unhandled status codes
printf("App init, status: %d\n", status);
break;
- }
+ } */
APPS_IS_INIT[app_id] = 1;
}
return app_id;
}
int app_render(int app_id) {
- return (*APPS_FUNC_RENDER[app_id])(&app_api);
+ for (auto app : open_apps) {
+ if (app_id == app->app_id)
+ return app->render(&app_api);
+ }
}
// Delta is in ms, from time_since_button_press()
int app_btnpressed(int app_id, uint gpio, unsigned long delta) {
- return (*APPS_FUNC_BTNPRESS[app_id])(&app_api, gpio, delta);
+ for (auto app : open_apps) {
+ if (app_id == app->app_id)
+ return app->btnpressed(&app_api, gpio, delta);
+ }
}
int app_destroy(int app_id) {
- if (APPS_IS_INIT[app_id]) {
- APPS_IS_INIT[app_id] = 0;
- return (*APPS_FUNC_DESTROY[app_id])(&app_api);
+ BaseApp* to_destroy;
+
+ for (auto app : open_apps) {
+ if (app_id == app->app_id)
+ to_destroy = app;
}
-}
+ delete to_destroy;
+ // FIXME: Remove app from list
+ //open_apps.erase(std::remove(open_apps.begin(), open_apps.end(), to_destroy), open_apps.end()); // See https://stackoverflow.com/a/27306171/15578170
-int app_bgrefresh(int app_id) {
- if (APPS_IS_INIT[app_id])
- return (*APPS_FUNC_BGREFRESH[app_id])(&app_api, app_id==g_s.current_app);
+ APPS_IS_INIT[app_id] = 0;
+ return 0;
}
bool repeating_callback(struct repeating_timer *t) {
@@ -94,9 +110,11 @@ bool repeating_callback(struct repeating_timer *t) {
app_api.performance_set(Api::perf_modes::EXIT_SHALLOW_SLEEP);
app_api.display_power(true);
}
- // Refresh each app, but should it be done when sleeping?
- for (int i=0; i < NUMBER_OF_APPS; i++) {
- app_bgrefresh(i);
+
+ // Refresh each app
+ // should it be done when sleeping?
+ for (auto app : open_apps) {
+ app->bgrefresh(&app_api, g_s.current_app == app->app_id);
}
return true;
}