/* * @Author: xxx * @Date: 2023-08-03 17:13:28 * @LastEditors: xxx * @LastEditTime: 2023-08-21 17:01:29 * @Description: 这是一个简单的菜单系统,其中包含一个定时器,当定时器过期时发送消息。菜单系统由多个菜单页面组成,用户可以通过特定键(如“NEXT”和“REFUSH”)导航过各个页面。当定时器过期时,菜单系统将发送消息给下一个页面或刷新当前页面。 The menu_create 函数创建一个新的菜单,通过初始化一个菜单页面列表来完成。The menu_page_add 函数向菜单页面列表中添加一个新的菜单页面。The menu_key_register 函数注册一个特定的键,用于导航菜单。The menu_timer_start 函数开始菜单定时器,指定一个时间并为过期时发送一个消息。The menu_timer_stop 函数关闭菜单定时器。 The get_menu_page 函数根据索引返回指定的菜单页面,如果没有找到则返回 NULL。The menu_detection 函数检查菜单定时器是否正在运行,如果运行,它 decrements 定时器计数器并在定时器过期时发送消息。同时,它检查当前菜单页面并根据接收到的消息执行相应的操作。 * email: * Copyright (c) 2023 by xxx, All Rights Reserved. */ #include "menu.h" #include "sys.h" static menu_t _menu; static volatile uint16_t menu_times = 0; // 菜单定时器时间 static volatile uint64_t next_wm_msg = 0; // 下一个窗体消息 static volatile BOOL menu_times_start_flag = FALSE; // 菜单定时器启动标志 /** * @brief 创建菜单 * @param {uint16_t} menu_ticks - 菜单定时器时间 * @return {menu_t *} - 创建的菜单指针 */ menu_t *menu_create(uint16_t menu_ticks) { if (NULL == _menu.pages) { clist_init(&_menu.pages); } _menu.menu_ticks = menu_ticks; return &_menu; } /** * @brief 设置菜单定时器时间 * @param {uint16_t} menu_ticks * @return {*} * @note */ void menu_set_ticks(uint16_t menu_ticks) { _menu.menu_ticks = menu_ticks; } /** * @brief 获取菜单 * @return {menu_t *} - 菜单指针 */ menu_t *get_menu(void) { return &_menu; } /** * @brief 向菜单页面列表中添加一个菜单页面 * @param {menu_page_t *} page - 要添加的菜单页面指针 */ void menu_page_add(menu_page_t *page) { clist_push_back(&_menu.pages, (cnode)page); } /** * @brief 注册菜单按键 * @param {uint8_t} key - 要注册的菜单按键 */ void menu_key_register(uint64_t key) { if (KEY_IS_LONG(key)) { if (_menu.wm_msg == 0) { _menu.wm_msg = key; } } else { _menu.wm_msg = key; } } /** * @brief 按键长按计时开始 * @return {*} * @note */ void menu_key_long_start(void) { if (_menu.key_long_ticks == 0) { _menu.key_long_ticks = sys_millis(); } } void menu_key_long_stop(void) { _menu.key_long_ticks = 0; } void menu_set_scandir(uint8_t dir) { _menu.dir = dir > 1 ? 1 : dir; } /** * @brief 启动菜单定时器 * @param {uint16_t} time - 菜单定时器时间 * @param {uint64_t} wm_msg - 发送的消息 */ void menu_timer_start(uint16_t time, uint64_t wm_msg) { menu_times = time / _menu.menu_ticks; next_wm_msg = wm_msg; } /** * @brief 关闭菜单定时器 * @return {*} */ void menu_timer_stop(void) { menu_times = 0; } /** * @brief 获取指定索引的菜单页面 * @param {uint8_t} index - 菜单页面的索引 * @return {*} - 找到的菜单页面指针,否则为NULL */ menu_page_t *get_menu_page(uint8_t index) { for (clist_node_t *p = _menu.pages; p != NULL; p = p->Next) { menu_page_t *page = (menu_page_t *)p->data; if (page->Index == index) { return page; } } return NULL; } menu_page_t *get_menu_sub_page(uint8_t index, uint8_t sub_index) { menu_page_t *menu = get_menu_page(index); uint8_t i = 0; for (clist_node_t *p = _menu.pages; p != NULL; p = p->Next) { menu_page_t *page = (menu_page_t *)p->data; if (menu->Index == page->FatherIndex) { i++; if (i == sub_index) { return page; } } } return NULL; } /** * @brief 获取指定索引的菜单页面的子菜单页面个数 * @param {uint8_t} index * @return {*} * @note */ uint8_t get_menu_sub_page_count(uint8_t index, uint8_t sub_index) { uint8_t count = 0; menu_page_t *menu = get_menu_sub_page(index, sub_index); if (menu != NULL) { for (clist_node_t *p = _menu.pages; p != NULL; p = p->Next) { menu_page_t *page = (menu_page_t *)p->data; if (menu->Index == page->FatherIndex) { count++; } } } return count; } /** * @brief 菜单重建 */ void menu_rebuild(void) { _menu.wm_msg = WM_CREATE; } /** * @brief 菜单检测 */ void menu_detection(void) { if (menu_times > 0) // 定时器启动判断 { menu_times--; // 定时器计数 if (menu_times == 0) // 定时器时间到,发送消息 { _menu.wm_msg = next_wm_msg; menu_times_start_flag = TRUE; } } uint32_t count = clist_node_count(_menu.pages); // 获取链表节点个数 if (count == 0) { return; // 没有菜单页面 } for (clist_node_t *p = _menu.pages; p != NULL; p = p->Next) { menu_page_t *page = (menu_page_t *)p->data; if (page->Index == _menu.current_index) { if (menu_times_start_flag == TRUE) { menu_times_start_flag = FALSE; // 定时器启动标志清零 switch (_menu.wm_msg) { case WM_NEXT: _menu.current_index = page->NextItem; // 下一个菜单页面 _menu.wm_msg = WM_CREATE; return; case WM_REFUSH: _menu.current_index = page->Index; // 当前菜单页面 return; default: break; } } else { if (page->CurrentOperate != NULL) { page->CurrentOperate(); // 当前页面操作 _menu.wm_msg = 0; } else { _menu.current_index = page->FatherIndex; // 返回上一级菜单 _menu.wm_msg = 0; } } break; } } }