Initial Demo OS
This commit is contained in:
@@ -0,0 +1,14 @@
|
||||
idf_component_register(
|
||||
SRCS
|
||||
"sys_app.c"
|
||||
INCLUDE_DIRS
|
||||
"include"
|
||||
REQUIRES
|
||||
sys_core
|
||||
sys_input
|
||||
sys_gfx
|
||||
freertos
|
||||
esp_timer
|
||||
log
|
||||
)
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
#ifndef OS_APP_H
|
||||
#define OS_APP_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "esp_err.h"
|
||||
#include "os_input.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
const char *id;
|
||||
const char *name;
|
||||
void (*init)(void);
|
||||
void (*enter)(void);
|
||||
void (*update)(uint32_t delta_ms);
|
||||
void (*handle_input)(input_action_t action);
|
||||
void (*exit)(void);
|
||||
} sys_app_t;
|
||||
|
||||
esp_err_t sys_app_init(void);
|
||||
esp_err_t sys_app_register(const sys_app_t *app);
|
||||
esp_err_t sys_app_launch_by_id(const char *id);
|
||||
esp_err_t sys_app_launch_by_index(size_t index);
|
||||
void sys_app_launch_launcher(void);
|
||||
const sys_app_t *sys_app_get_current(void);
|
||||
void sys_app_update(uint32_t delta_ms);
|
||||
void sys_app_dispatch_input(input_action_t action);
|
||||
size_t sys_app_get_count(void);
|
||||
const sys_app_t *sys_app_get_by_index(size_t index);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // OS_APP_H
|
||||
@@ -0,0 +1,157 @@
|
||||
#include "os_app.h"
|
||||
#include "os_gfx.h"
|
||||
#include "os_status.h"
|
||||
#include "os_event.h"
|
||||
#include <string.h>
|
||||
#include "esp_log.h"
|
||||
|
||||
static const char *TAG = "SYS_APP";
|
||||
|
||||
#define MAX_APPS 16
|
||||
static const sys_app_t *s_registry[MAX_APPS];
|
||||
static size_t s_app_count = 0;
|
||||
|
||||
static const sys_app_t *s_current_app = NULL;
|
||||
static bool s_in_launcher = true;
|
||||
static size_t s_launcher_selected = 0;
|
||||
|
||||
static void launcher_update(uint32_t delta_ms)
|
||||
{
|
||||
sys_status_t status;
|
||||
sys_status_get(&status);
|
||||
sys_gfx_draw_status_bar(&status);
|
||||
|
||||
sys_gfx_draw_str_3x5(2, 9, "--- APPS ---", COLOR_WHITE);
|
||||
|
||||
const char *names[MAX_APPS];
|
||||
for (size_t i = 0; i < s_app_count; i++) {
|
||||
names[i] = s_registry[i]->name;
|
||||
}
|
||||
sys_gfx_draw_menu(15, names, s_app_count, s_launcher_selected);
|
||||
}
|
||||
|
||||
static void launcher_handle_input(input_action_t action)
|
||||
{
|
||||
if (s_app_count == 0) return;
|
||||
|
||||
if (action == INPUT_ACTION_CLICK) {
|
||||
s_launcher_selected = (s_launcher_selected + 1) % s_app_count;
|
||||
} else if (action == INPUT_ACTION_DOUBLE_CLICK) {
|
||||
if (s_launcher_selected == 0) {
|
||||
s_launcher_selected = s_app_count - 1;
|
||||
} else {
|
||||
s_launcher_selected--;
|
||||
}
|
||||
} else if (action == INPUT_ACTION_LONG_PRESS) {
|
||||
sys_app_launch_by_index(s_launcher_selected);
|
||||
}
|
||||
}
|
||||
|
||||
esp_err_t sys_app_init(void)
|
||||
{
|
||||
s_app_count = 0;
|
||||
s_current_app = NULL;
|
||||
s_in_launcher = true;
|
||||
s_launcher_selected = 0;
|
||||
sys_status_set_active_app_name("Launcher");
|
||||
ESP_LOGI(TAG, "App Manager initialized");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t sys_app_register(const sys_app_t *app)
|
||||
{
|
||||
if (!app || !app->id || !app->name) return ESP_ERR_INVALID_ARG;
|
||||
if (s_app_count >= MAX_APPS) return ESP_ERR_NO_MEM;
|
||||
|
||||
s_registry[s_app_count++] = app;
|
||||
if (app->init) {
|
||||
app->init();
|
||||
}
|
||||
ESP_LOGI(TAG, "Registered app: [%s] '%s'", app->id, app->name);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t sys_app_launch_by_id(const char *id)
|
||||
{
|
||||
if (!id) return ESP_ERR_INVALID_ARG;
|
||||
for (size_t i = 0; i < s_app_count; i++) {
|
||||
if (strcmp(s_registry[i]->id, id) == 0) {
|
||||
return sys_app_launch_by_index(i);
|
||||
}
|
||||
}
|
||||
ESP_LOGW(TAG, "App not found: %s", id);
|
||||
return ESP_ERR_NOT_FOUND;
|
||||
}
|
||||
|
||||
esp_err_t sys_app_launch_by_index(size_t index)
|
||||
{
|
||||
if (index >= s_app_count) return ESP_ERR_INVALID_ARG;
|
||||
|
||||
if (s_current_app && s_current_app->exit) {
|
||||
s_current_app->exit();
|
||||
}
|
||||
|
||||
s_current_app = s_registry[index];
|
||||
s_in_launcher = false;
|
||||
sys_status_set_active_app_name(s_current_app->name);
|
||||
|
||||
if (s_current_app->enter) {
|
||||
s_current_app->enter();
|
||||
}
|
||||
|
||||
sys_event_post(SYS_EVENT_APP_SWITCH, (int32_t)index, (void *)s_current_app->id);
|
||||
sys_gfx_show_toast(s_current_app->name, 800);
|
||||
ESP_LOGI(TAG, "Switched to app: %s", s_current_app->name);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
void sys_app_launch_launcher(void)
|
||||
{
|
||||
if (s_current_app && s_current_app->exit) {
|
||||
s_current_app->exit();
|
||||
}
|
||||
s_current_app = NULL;
|
||||
s_in_launcher = true;
|
||||
sys_status_set_active_app_name("Launcher");
|
||||
sys_gfx_show_toast("Launcher", 600);
|
||||
ESP_LOGI(TAG, "Returned to App Launcher");
|
||||
}
|
||||
|
||||
const sys_app_t *sys_app_get_current(void)
|
||||
{
|
||||
return s_current_app;
|
||||
}
|
||||
|
||||
void sys_app_update(uint32_t delta_ms)
|
||||
{
|
||||
if (s_in_launcher) {
|
||||
launcher_update(delta_ms);
|
||||
} else if (s_current_app && s_current_app->update) {
|
||||
s_current_app->update(delta_ms);
|
||||
}
|
||||
}
|
||||
|
||||
void sys_app_dispatch_input(input_action_t action)
|
||||
{
|
||||
if (action == INPUT_ACTION_HOLD_HOME) {
|
||||
sys_app_launch_launcher();
|
||||
return;
|
||||
}
|
||||
|
||||
if (s_in_launcher) {
|
||||
launcher_handle_input(action);
|
||||
} else if (s_current_app && s_current_app->handle_input) {
|
||||
s_current_app->handle_input(action);
|
||||
}
|
||||
}
|
||||
|
||||
size_t sys_app_get_count(void)
|
||||
{
|
||||
return s_app_count;
|
||||
}
|
||||
|
||||
const sys_app_t *sys_app_get_by_index(size_t index)
|
||||
{
|
||||
if (index >= s_app_count) return NULL;
|
||||
return s_registry[index];
|
||||
}
|
||||
Reference in New Issue
Block a user