Initial Demo OS

This commit is contained in:
dark98
2026-09-03 00:46:04 +01:00
commit 1491821e96
45 changed files with 2908 additions and 0 deletions
+12
View File
@@ -0,0 +1,12 @@
idf_component_register(
SRCS
"sys_event.c"
"sys_status.c"
INCLUDE_DIRS
"include"
REQUIRES
freertos
esp_timer
esp_system
log
)
+52
View File
@@ -0,0 +1,52 @@
#ifndef OS_EVENT_H
#define OS_EVENT_H
#include <stdint.h>
#include <stdbool.h>
#include "esp_err.h"
#ifdef __cplusplus
extern "C" {
#endif
/* System Event IDs */
typedef enum {
SYS_EVENT_INPUT_SHORT_PRESS = 1, /* Single click (e.g. Next / Increment) */
SYS_EVENT_INPUT_DOUBLE_CLICK, /* Double click (e.g. Back / Cancel) */
SYS_EVENT_INPUT_LONG_PRESS, /* Hold 400ms (e.g. Select / Confirm) */
SYS_EVENT_INPUT_EXTRA_LONG_PRESS, /* Hold 1500ms (e.g. Global Home / Launcher) */
SYS_EVENT_APP_SWITCH, /* Switched to a new app */
SYS_EVENT_TICK_1S, /* 1 Hz system heartbeat */
SYS_EVENT_WIFI_STATUS_CHANGED, /* WiFi connection state changed */
SYS_EVENT_BATTERY_STATUS_CHANGED, /* Battery level / charging changed */
SYS_EVENT_CUSTOM
} sys_event_id_t;
typedef struct {
sys_event_id_t id;
int32_t data;
void *ptr_data;
} sys_event_t;
typedef void (*sys_event_cb_t)(const sys_event_t *event, void *user_arg);
/**
* @brief Initialize the global system event bus.
*/
esp_err_t sys_event_init(void);
/**
* @brief Post an event to the global event bus.
*/
esp_err_t sys_event_post(sys_event_id_t id, int32_t data, void *ptr_data);
/**
* @brief Subscribe to system events.
*/
esp_err_t sys_event_subscribe(sys_event_cb_t callback, void *user_arg);
#ifdef __cplusplus
}
#endif
#endif // OS_EVENT_H
+51
View File
@@ -0,0 +1,51 @@
#ifndef OS_STATUS_H
#define OS_STATUS_H
#include <stdint.h>
#include <stdbool.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef enum {
WIFI_STATE_OFF = 0,
WIFI_STATE_CONNECTING,
WIFI_STATE_CONNECTED,
WIFI_STATE_AP_MODE,
} wifi_state_t;
typedef enum {
BLE_STATE_OFF = 0,
BLE_STATE_ADVERTISING,
BLE_STATE_CONNECTED,
} ble_state_t;
typedef struct {
uint32_t uptime_sec;
uint32_t free_heap;
uint32_t min_free_heap;
uint8_t cpu_usage_pct;
wifi_state_t wifi_state;
int8_t wifi_rssi;
ble_state_t ble_state;
bool is_charging;
uint8_t battery_pct;
bool status_bar_visible;
const char *active_app_name;
} sys_status_t;
void sys_status_init(void);
void sys_status_get(sys_status_t *out_status);
void sys_status_update(void);
void sys_status_set_wifi(wifi_state_t state, int8_t rssi);
void sys_status_set_ble(ble_state_t state);
void sys_status_set_status_bar_visible(bool visible);
bool sys_status_is_status_bar_visible(void);
void sys_status_set_active_app_name(const char *name);
#ifdef __cplusplus
}
#endif
#endif // OS_STATUS_H
+84
View File
@@ -0,0 +1,84 @@
#include "os_event.h"
#include "freertos/FreeRTOS.h"
#include "freertos/queue.h"
#include "freertos/task.h"
#include "esp_log.h"
static const char *TAG = "SYS_EVENT";
#define MAX_SUBSCRIBERS 16
#define EVENT_QUEUE_LEN 32
typedef struct {
sys_event_cb_t callback;
void *user_arg;
} subscriber_entry_t;
static subscriber_entry_t s_subscribers[MAX_SUBSCRIBERS];
static size_t s_subscriber_count = 0;
static QueueHandle_t s_event_queue = NULL;
static void sys_event_dispatch_task(void *pvParameters)
{
sys_event_t event;
while (1) {
if (xQueueReceive(s_event_queue, &event, portMAX_DELAY) == pdTRUE) {
for (size_t i = 0; i < s_subscriber_count; i++) {
if (s_subscribers[i].callback) {
s_subscribers[i].callback(&event, s_subscribers[i].user_arg);
}
}
}
}
}
esp_err_t sys_event_init(void)
{
if (s_event_queue != NULL) {
return ESP_OK;
}
s_event_queue = xQueueCreate(EVENT_QUEUE_LEN, sizeof(sys_event_t));
if (!s_event_queue) {
ESP_LOGE(TAG, "Failed to create event queue");
return ESP_ERR_NO_MEM;
}
BaseType_t ret = xTaskCreate(sys_event_dispatch_task, "sys_event_task", 3072, NULL, 10, NULL);
if (ret != pdPASS) {
ESP_LOGE(TAG, "Failed to create event dispatcher task");
return ESP_FAIL;
}
ESP_LOGI(TAG, "System Event Bus initialized");
return ESP_OK;
}
esp_err_t sys_event_post(sys_event_id_t id, int32_t data, void *ptr_data)
{
if (!s_event_queue) {
return ESP_ERR_INVALID_STATE;
}
sys_event_t event = {
.id = id,
.data = data,
.ptr_data = ptr_data
};
if (xQueueSend(s_event_queue, &event, 0) != pdTRUE) {
ESP_LOGW(TAG, "Event queue full, dropped event %d", (int)id);
return ESP_ERR_NO_MEM;
}
return ESP_OK;
}
esp_err_t sys_event_subscribe(sys_event_cb_t callback, void *user_arg)
{
if (!callback) return ESP_ERR_INVALID_ARG;
if (s_subscriber_count >= MAX_SUBSCRIBERS) {
ESP_LOGE(TAG, "Max subscribers reached");
return ESP_ERR_NO_MEM;
}
s_subscribers[s_subscriber_count].callback = callback;
s_subscribers[s_subscriber_count].user_arg = user_arg;
s_subscriber_count++;
return ESP_OK;
}
+87
View File
@@ -0,0 +1,87 @@
#include "os_status.h"
#include <string.h>
#include "esp_system.h"
#include "esp_timer.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
static sys_status_t s_status = {
.uptime_sec = 0,
.free_heap = 0,
.min_free_heap = 0,
.cpu_usage_pct = 0,
.wifi_state = WIFI_STATE_OFF,
.wifi_rssi = 0,
.ble_state = BLE_STATE_OFF,
.is_charging = true,
.battery_pct = 100,
.status_bar_visible = true,
.active_app_name = "Clock"
};
static portMUX_TYPE s_status_mux = portMUX_INITIALIZER_UNLOCKED;
void sys_status_init(void)
{
portENTER_CRITICAL(&s_status_mux);
s_status.uptime_sec = 0;
s_status.free_heap = esp_get_free_heap_size();
s_status.min_free_heap = esp_get_minimum_free_heap_size();
s_status.status_bar_visible = true;
portEXIT_CRITICAL(&s_status_mux);
}
void sys_status_get(sys_status_t *out_status)
{
if (!out_status) return;
portENTER_CRITICAL(&s_status_mux);
memcpy(out_status, &s_status, sizeof(sys_status_t));
portEXIT_CRITICAL(&s_status_mux);
}
void sys_status_update(void)
{
portENTER_CRITICAL(&s_status_mux);
s_status.uptime_sec = (uint32_t)(esp_timer_get_time() / 1000000ULL);
s_status.free_heap = esp_get_free_heap_size();
s_status.min_free_heap = esp_get_minimum_free_heap_size();
portEXIT_CRITICAL(&s_status_mux);
}
void sys_status_set_wifi(wifi_state_t state, int8_t rssi)
{
portENTER_CRITICAL(&s_status_mux);
s_status.wifi_state = state;
s_status.wifi_rssi = rssi;
portEXIT_CRITICAL(&s_status_mux);
}
void sys_status_set_ble(ble_state_t state)
{
portENTER_CRITICAL(&s_status_mux);
s_status.ble_state = state;
portEXIT_CRITICAL(&s_status_mux);
}
void sys_status_set_status_bar_visible(bool visible)
{
portENTER_CRITICAL(&s_status_mux);
s_status.status_bar_visible = visible;
portEXIT_CRITICAL(&s_status_mux);
}
bool sys_status_is_status_bar_visible(void)
{
bool visible;
portENTER_CRITICAL(&s_status_mux);
visible = s_status.status_bar_visible;
portEXIT_CRITICAL(&s_status_mux);
return visible;
}
void sys_status_set_active_app_name(const char *name)
{
portENTER_CRITICAL(&s_status_mux);
s_status.active_app_name = name;
portEXIT_CRITICAL(&s_status_mux);
}