// device liquid crystal display menu // // Date: 2024-01-31 // // Keyboard layout: Four buttons // // Enter - to access current selection // // Up - to select previous item // // Down - to select next item // // Stop - to stop scanning right now #pragma once #include #include #include #include #include #include #include #define MENU_ID_RETURN -1 // ID of menu item that return to parent #define LINK_DEFINE(x, y) x##y #define MEMNU_CMD_HANDLER_PARAM dev_menu* menu, int id #define MENU_CMD_HANDLER_RET bool #define MENU_CMD_CALLBACK std::function class dev_menu : public refer { dev_menu* parent_ = nullptr; typedef struct _menu_item { std::string text; bool leaf; union { int id; // valid on leaf dev_menu *child; // valid on !leaf }; }MITEM; std::vector items_; int cur_ = 0; int sel_ = -1; bool check_item_ = false; bool need_ret_parent_ = true; int find_item(const char* text); public: dev_menu(bool check_item = false, bool need_ret_parent = true); protected: virtual ~dev_menu(); void set_parent(dev_menu* parent); public: bool add_menu(const char* text, int id); bool add_menu(const char* text, dev_menu* submenu); bool remove_menu(const char* text); void set_need_return_parent(bool need); bool move_to(bool next); // true - move to next, false - move to previous. if at end position of move direction, return false bool select(const char* txt); void reset_pos(void); // Function: access current menu // // Parameter: id - to receive ID of current menu item if leaf, fill '-1' if a submenu // // Return: current menu, user should call 'release' after use dev_menu* enter(int* id); // Function: get all menus text // // Parameter: text - to receive the menu text // // sel - to receive current setting index // // Return: current menu index int get_menu_text(std::vector& text, int& sel); }; class KeyMonitor; class Lcd; class ui_mgr : public refer { dev_menu* root_ = nullptr; dev_menu* cur_ = nullptr; volatile bool menu_mode_ = false; // whether LCD is displaying menu volatile bool run_ = true; volatile bool ready_enable_ = true; SIZE font_size_ = {16, 16}; std::map handler_; std::unique_ptr lcd_; std::unique_ptr keyboard_; bool do_menu_command(int cmd); // return whether should hold UI ? void init(void); void clear(void); void refresh_lcd(bool cur_at_top); void move_to(bool next); void enter(void); int get_string_font(const char* text, uint8_t** ptr, uint8_t* rows, uint8_t* cols); typedef struct _disp_data { uint8_t x; uint8_t y; uint8_t rows; uint8_t cols; uint8_t cnt; // 0 to clear uint8_t mask; uint8_t *ptr[16]; }DISPDATA; MUTEX ready_lck_; chronograph ready_watch_; DISPDATA ready_; safe_fifo disp_data_; std::unique_ptr disp_thrd_; void thread_display(void); void display_ready(void); void set_ready_status_enabled(bool enable); void reset_ready_watch(void); int get_ready_watch_ms(void); public: ui_mgr(); protected: virtual ~ui_mgr(); public: void key_event(int key); };