Initial Demo OS
This commit is contained in:
@@ -0,0 +1,12 @@
|
||||
idf_component_register(
|
||||
SRCS
|
||||
"sys_event.c"
|
||||
"sys_status.c"
|
||||
INCLUDE_DIRS
|
||||
"include"
|
||||
REQUIRES
|
||||
freertos
|
||||
esp_timer
|
||||
esp_system
|
||||
log
|
||||
)
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
Reference in New Issue
Block a user