Files
menu/src/core/menu_event.c
2025-12-19 17:01:27 +08:00

187 lines
5.1 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
**********************************************************************************************************************
* @file menu_event.c
* @brief 菜单组件事件队列实现
* @author menu_component
* @date 2025-12-19
**********************************************************************************************************************
*/
/* Includes ----------------------------------------------------------------------------------------------------------*/
#include "menu_types.h"
/* 函数实现 ---------------------------------------------------------------------------------------------------------*/
/**
* @brief 初始化事件队列
* @param queue 事件队列指针
*/
void menu_event_queue_init(MenuEventQueue* queue)
{
MENU_ASSERT(queue != NULL);
queue->head = 0;
queue->tail = 0;
queue->count = 0;
queue->reserved = 0;
}
/**
* @brief 检查事件队列是否为空
* @param queue 事件队列指针
* @return true为空false不为空
*/
bool menu_event_queue_is_empty(const MenuEventQueue* queue)
{
MENU_ASSERT(queue != NULL);
return (queue->count == 0);
}
/**
* @brief 检查事件队列是否已满
* @param queue 事件队列指针
* @return true已满false未满
*/
bool menu_event_queue_is_full(const MenuEventQueue* queue)
{
MENU_ASSERT(queue != NULL);
return (queue->count >= MENU_CONFIG_EVENT_QUEUE_LEN);
}
/**
* @brief 获取事件队列中的元素数量
* @param queue 事件队列指针
* @return 元素数量
*/
uint8_t menu_event_queue_get_count(const MenuEventQueue* queue)
{
MENU_ASSERT(queue != NULL);
return queue->count;
}
/**
* @brief 向事件队列添加事件
* @param queue 事件队列指针
* @param event 要添加的事件
* @return 错误码
*/
MenuErrCode menu_event_queue_push(MenuEventQueue* queue, const MenuEvent* event)
{
MENU_ASSERT(queue != NULL);
MENU_ASSERT(event != NULL);
// 检查事件优先级是否合法
if (event->priority >= MENU_CONFIG_EVENT_MAX_PRIORITY) {
return MENU_ERR_INVALID_PARAM;
}
if (menu_event_queue_is_full(queue)) {
// 队列已满,替换低优先级事件
uint8_t lowest_prio = 0;
uint8_t lowest_idx = queue->head;
// 找到最低优先级的事件
for (uint8_t i = 0; i < MENU_CONFIG_EVENT_QUEUE_LEN; i++) {
uint8_t idx = (queue->head + i) % MENU_CONFIG_EVENT_QUEUE_LEN;
if (queue->buffer[idx].priority > lowest_prio) {
lowest_prio = queue->buffer[idx].priority;
lowest_idx = idx;
}
}
// 替换最低优先级事件
queue->buffer[lowest_idx] = *event;
return MENU_ERR_OK;
}
// 队列未满,添加到队尾
queue->buffer[queue->tail] = *event;
queue->tail = (queue->tail + 1) % MENU_CONFIG_EVENT_QUEUE_LEN;
queue->count++;
return MENU_ERR_OK;
}
/**
* @brief 从事件队列获取下一个事件
* @param queue 事件队列指针
* @param event 用于存储获取的事件
* @return 错误码
*/
MenuErrCode menu_event_queue_pop(MenuEventQueue* queue, MenuEvent* event)
{
MENU_ASSERT(queue != NULL);
MENU_ASSERT(event != NULL);
if (menu_event_queue_is_empty(queue)) {
return MENU_ERR_QUEUE_EMPTY;
}
// 寻找最高优先级的事件
uint8_t highest_prio = MENU_CONFIG_EVENT_MAX_PRIORITY;
uint8_t highest_idx = queue->head;
for (uint8_t i = 0; i < queue->count; i++) {
uint8_t idx = (queue->head + i) % MENU_CONFIG_EVENT_QUEUE_LEN;
if (queue->buffer[idx].priority < highest_prio) {
highest_prio = queue->buffer[idx].priority;
highest_idx = idx;
}
}
// 取出最高优先级事件
*event = queue->buffer[highest_idx];
// 移除该事件,将后续事件前移
for (uint8_t i = highest_idx; i != queue->tail; i = (i + 1) % MENU_CONFIG_EVENT_QUEUE_LEN) {
uint8_t next_idx = (i + 1) % MENU_CONFIG_EVENT_QUEUE_LEN;
if (next_idx == queue->tail) {
break;
}
queue->buffer[i] = queue->buffer[next_idx];
}
// 更新队列状态
if (queue->tail > 0) {
queue->tail--;
} else {
queue->tail = MENU_CONFIG_EVENT_QUEUE_LEN - 1;
}
queue->count--;
return MENU_ERR_OK;
}
/**
* @brief 清空事件队列
* @param queue 事件队列指针
*/
void menu_event_queue_clear(MenuEventQueue* queue)
{
MENU_ASSERT(queue != NULL);
queue->head = 0;
queue->tail = 0;
queue->count = 0;
}
/**
* @brief 向事件队列推送一个简单事件
* @param core_ctx 菜单核心上下文
* @param type 事件类型
* @param priority 事件优先级
* @return 错误码
*/
MenuErrCode menu_core_post_event(struct MenuCoreCtx* core_ctx, MenuEventType type, uint8_t priority)
{
MenuEvent event;
event.type = type;
event.priority = priority;
event.target_node_id = core_ctx->current_node_id;
event.data = NULL;
event.timestamp = core_ctx->last_refresh_tick;
return menu_event_queue_push(&core_ctx->event_queue, &event);
}