From f7a095f7b490997e62938e9363824bbefa88deac Mon Sep 17 00:00:00 2001 From: gb <741021719@qq.com> Date: Fri, 2 Feb 2024 16:53:17 +0800 Subject: [PATCH] =?UTF-8?q?=E6=8C=89=E9=94=AE=E5=8A=9F=E8=83=BD=E8=8F=9C?= =?UTF-8?q?=E5=8D=95=E5=8C=96=E6=94=B9=E9=80=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- hardware/hardware.cpp | 4 +- hardware/motor/motorboard.cpp | 2 +- sdk/base/words.h | 43 ++- {hardware => sdk}/uart/PinMonitor.cpp | 0 {hardware => sdk}/uart/PinMonitor.h | 0 ui/DisplayCenter.cpp | 12 +- ui/DisplayCenter.h | 2 + ui/Lcd.cpp | 106 ++++++ ui/Lcd.h | 21 ++ ui/dev_menu.cpp | 461 ++++++++++++++++++++++++++ ui/dev_menu.h | 124 +++++++ ui/font.cpp | 382 +++++++++++++++++++++ ui/font.h | 7 + ui/keymonitor.cpp | 205 ++++++++++++ ui/keymonitor.h | 71 ++++ ui/main.cpp | 28 +- xmake.lua | 4 +- 17 files changed, 1441 insertions(+), 31 deletions(-) rename {hardware => sdk}/uart/PinMonitor.cpp (100%) rename {hardware => sdk}/uart/PinMonitor.h (100%) create mode 100644 ui/dev_menu.cpp create mode 100644 ui/dev_menu.h create mode 100644 ui/font.cpp create mode 100644 ui/font.h create mode 100644 ui/keymonitor.cpp create mode 100644 ui/keymonitor.h diff --git a/hardware/hardware.cpp b/hardware/hardware.cpp index b3b94eb..06d427a 100644 --- a/hardware/hardware.cpp +++ b/hardware/hardware.cpp @@ -7,6 +7,7 @@ #include #include #include +#include ///////////////////////////////////////////////////////////////////////////////////////////////////////// // scanner_hw @@ -355,6 +356,7 @@ void scanner_hw::thread_image_capture(void) err = SCANNER_ERR_OK; chronograph watch; std::pair mbev; + std::function img_callback(img_handler_); auto put_v4l2_mem = [&](BEFORE_DESTROY_PARAM) -> BEFORE_DESTROY_RET { @@ -415,7 +417,7 @@ void scanner_hw::thread_image_capture(void) used_v4l2_mem++; img.pos.paper_ind++; img.pos.status = hg_err_2_image_status(err); - img_handler_(mem, true, &img); + //img_handler_(mem, true, &img); mem->release(); if((!scan_cntless_ && img.pos.paper_ind == scan_count_) || is_scan_fatal()) diff --git a/hardware/motor/motorboard.cpp b/hardware/motor/motorboard.cpp index a688c38..b72dfc6 100644 --- a/hardware/motor/motorboard.cpp +++ b/hardware/motor/motorboard.cpp @@ -1,7 +1,7 @@ #include "motorboard.h" #include -#include "../uart/PinMonitor.h" +#include #include "../uart/uartregsaccess.h" #include // #include "StateControl.h" diff --git a/sdk/base/words.h b/sdk/base/words.h index 5184458..523125f 100644 --- a/sdk/base/words.h +++ b/sdk/base/words.h @@ -3,14 +3,43 @@ // Date: 2024-01-24 #pragma once -#define WORDS_COLOR_COLOR "\345\275\251\350\211\262" -#define WORDS_COLOR_GRAY "\347\201\260\345\272\246" +#define WORDS_COLOR_COLOR "\345\275\251\350\211\262" +#define WORDS_COLOR_GRAY "\347\201\260\345\272\246" -#define WORDS_PAPER_ORIGIN_SIZE "\345\214\271\351\205\215\345\216\237\345\247\213\345\260\272\345\257\270" -#define WORDS_PAPER_MAX_SIZE_CROP "\346\234\200\345\244\247\346\211\253\346\217\217\345\260\272\345\257\270\350\207\252\345\212\250\350\243\201\345\210\207" +#define WORDS_PAPER_ORIGIN_SIZE "\345\214\271\351\205\215\345\216\237\345\247\213\345\260\272\345\257\270" +#define WORDS_PAPER_MAX_SIZE_CROP "\346\234\200\345\244\247\346\211\253\346\217\217\345\260\272\345\257\270\350\207\252\345\212\250\350\243\201\345\210\207" -#define WORDS_FORBIDDEN "\347\246\201\347\224\250" +#define WORDS_FORBIDDEN "\347\246\201\347\224\250" -#define WORDS_SCAN_CONTINUOUS "\350\277\236\347\273\255\346\211\253\346\217\217" +#define WORDS_SCAN_CONTINUOUS "\350\277\236\347\273\255\346\211\253\346\217\217" -#define WORDS_FILLBG_CONVEX "\345\207\270\345\244\232\350\276\271\345\275\242" +#define WORDS_FILLBG_CONVEX "\345\207\270\345\244\232\350\276\271\345\275\242" + + + + +#define WORDS_MENU_RETURN "\350\277\224\345\233\236\344\270\212\344\270\200\347\272\247\350\217\234\345\215\225" +#define WORDS_MENU_SEPARATE_STRENGTH "\345\210\206\347\272\270\345\274\272\345\272\246" +#define WORDS_MENU_LOW "\344\275\216" +#define WORDS_MENU_MID "\344\270\255" +#define WORDS_MENU_HIGH "\351\253\230" +#define WORDS_MENU_POWER "\344\274\221\347\234\240\346\227\266\351\227\264" +#define WORDS_MENU_SLEEP_NONE "\344\270\215\344\274\221\347\234\240" +#define WORDS_MENU_SLEEP_5_MIN "5min" +#define WORDS_MENU_SLEEP_10_MIN "10min" +#define WORDS_MENU_SLEEP_20_MIN "20min" +#define WORDS_MENU_SLEEP_30_MIN "30min" +#define WORDS_MENU_SLEEP_1_HOUR "1h" +#define WORDS_MENU_SLEEP_2_HOUR "2h" +#define WORDS_MENU_SLEEP_4_HOUR "4h" +#define WORDS_MENU_LIFTER_POS "\345\215\207\351\231\215\345\217\260\344\275\215\347\275\256" +#define WORDS_MENU_COUNT_MODE "\350\256\241\346\225\260\346\250\241\345\274\217" +#define WORDS_MENU_MANUAL_MODE "\346\211\213\345\212\250\346\250\241\345\274\217" +#define WORDS_MENU_CLEAR_PASSWAY "\346\270\205\347\220\206\347\272\270\351\201\223" +#define WORDS_MENU_HISTORY_COUNT "\345\216\206\345\217\262\345\274\240\346\225\260" +#define WORDS_MENU_ROLLER_COUNT "\346\273\232\350\275\264\345\274\240\346\225\260" +#define WORDS_MENU_RESET_ROLLOER_CNT "\346\270\205\351\231\244\346\273\232\350\275\264\345\274\240\346\225\260" +#define WORDS_MENU_SLEEP_NOW "\350\277\233\345\205\245\344\274\221\347\234\240" +#define WORDS_MENU_SHUTDOWN "\345\205\263\346\234\272" +#define WORDS_MENU_YES "\347\241\256\345\256\232" +#define WORDS_MENU_NO "\345\217\226\346\266\210" \ No newline at end of file diff --git a/hardware/uart/PinMonitor.cpp b/sdk/uart/PinMonitor.cpp similarity index 100% rename from hardware/uart/PinMonitor.cpp rename to sdk/uart/PinMonitor.cpp diff --git a/hardware/uart/PinMonitor.h b/sdk/uart/PinMonitor.h similarity index 100% rename from hardware/uart/PinMonitor.h rename to sdk/uart/PinMonitor.h diff --git a/ui/DisplayCenter.cpp b/ui/DisplayCenter.cpp index f44e633..e2dff57 100644 --- a/ui/DisplayCenter.cpp +++ b/ui/DisplayCenter.cpp @@ -6,19 +6,20 @@ DisplayCenter::DisplayCenter() : m_lcd(new LCDDisplay()) ,brun(false), m_msgs("DisplayCenter") { m_showthread.reset(new std::thread(&DisplayCenter::runloop,this)); - m_distype = DisType::Dis_Idel; + m_distype = DisType::Dis_Unkown; + PutMsg(DisType::Dis_Init, code_page_, ClearScreen::All); } DisplayCenter::~DisplayCenter() { brun = false; + + m_msgs.trigger(); if(m_showthread.get()&& m_showthread->joinable()) { m_showthread->join(); m_showthread.reset(); } - - m_msgs.trigger(); m_msgs.clear(); m_lcd.reset(); @@ -27,8 +28,6 @@ DisplayCenter::~DisplayCenter() void DisplayCenter::PutMsg(DisType distype,int pagenum,ClearScreen clearscreen) { m_msgs.save({distype,clearscreen,(unsigned int )pagenum,""}, true); - m_distype = distype; - printf("\n ----- distype = %d ",distype); } void DisplayCenter::ResetMsgQueue() @@ -43,7 +42,10 @@ void DisplayCenter::runloop() { MsgPair msg; if(m_msgs.take(msg, true)) + { + m_distype = msg.distype; m_lcd->DisplayState(msg.distype, msg.pagenum, msg.clearscree); + } } } diff --git a/ui/DisplayCenter.h b/ui/DisplayCenter.h index 2db0ff1..0c6512d 100644 --- a/ui/DisplayCenter.h +++ b/ui/DisplayCenter.h @@ -8,6 +8,8 @@ class LCDDisplay; class DisplayCenter { + int code_page_ = 0; + public: DisplayCenter(); ~DisplayCenter(); diff --git a/ui/Lcd.cpp b/ui/Lcd.cpp index 9403adc..9b7a1dd 100644 --- a/ui/Lcd.cpp +++ b/ui/Lcd.cpp @@ -495,6 +495,13 @@ static unsigned char ascii_table_5x8[95][5] = { }; +#define OUT_BIT() \ + shift--; \ + spi_sck.setValue(Gpio::Low); \ + spi_sda.setValue((Gpio::GpioLevel)((val >> shift) & 0x1)); \ + spi_sck.setValue(Gpio::High); + + Lcd::Lcd() : spi_sck(51), spi_sda(72), spi_cs(154), spi_reset(150), spi_rs(156),COM_BOOT0(153) { @@ -779,3 +786,102 @@ void Lcd::Lcd_Clear_Half_Screen(bool top) } spi_cs.setValue(Gpio::High); } + +void Lcd::go_to(uint8_t page, uint8_t col) +{ + write_before(); + set_data_type(false); + + write_char(0xb0 + page); // 设置页地址。每页是8行。一个画面的64行被分成8个页。我们平常所说的第1页,在LCD驱动IC里是第0页,所以在这里减去1*/ + write_char(((col >> 4) & 0x0f) + 0x10); // 设置列地址的高4位 + write_char(col & 0x0f); // 设置列地址的低4位 + + write_end(); +} +void Lcd::write(uint8_t val, bool data, uint8_t mask) +{ + write_before(); + set_data_type(data); + + write_char(val, mask); + + write_end(); +} +void Lcd::clear(int x, int y, int w, int h) +{ + if(x >= LCD_WIDTH || y >= LCD_HEIGHT) + return; + if(x < 0) + x = 0; + if(y < 0) + y = 0; + if(w == -1) + w = LCD_WIDTH; + if(h == -1) + h = LCD_HEIGHT; + w += x; + h += y; + if(w > LCD_WIDTH) + w = LCD_WIDTH; + if(h > LCD_HEIGHT) + h = LCD_HEIGHT; + + for(int r = y / LCD_LINE_PER_PAGE; r <= (h + LCD_LINE_PER_PAGE - 1) / LCD_LINE_PER_PAGE; ++r) + { + go_to(r, x); + write_before(); + set_data_type(true); + for(int c = 0; c < w - x; ++c) + write_char(0); + write_end(); + } +} +void Lcd::write_line(uint8_t rows, uint8_t cols, uint8_t cnt, uint8_t** data, int x, int y, uint8_t mask) +{ + for(int r = 0; r < rows / LCD_LINE_PER_PAGE; ++r) + { + go_to(y / LCD_LINE_PER_PAGE + r, x); + write_before(); + set_data_type(true); + + for(int ind = 0; ind < cnt; ++ind) + { + for(int c = 0; c < cols; ++c) + { + write_char(*data[ind]++, mask); + } + write_char(0, mask); + } + write_end(); + } +} + + +void Lcd::set_data_type(bool data) +{ + spi_rs.setValue((Gpio::GpioLevel)data); +} +void Lcd::write_before(void) +{ + spi_cs.setValue(Gpio::Low); +} +void Lcd::write_char(uint8_t val, uint8_t mask) +{ + uint8_t shift = 8; + + val ^= mask; + + OUT_BIT(); + OUT_BIT(); + OUT_BIT(); + OUT_BIT(); + + OUT_BIT(); + OUT_BIT(); + OUT_BIT(); + OUT_BIT(); +} +void Lcd::write_end(void) +{ + spi_cs.setValue(Gpio::High); +} diff --git a/ui/Lcd.h b/ui/Lcd.h index 5714e5f..33ec46f 100644 --- a/ui/Lcd.h +++ b/ui/Lcd.h @@ -56,6 +56,27 @@ public: void Lcd_Display_String_5x8(unsigned int page, unsigned int column, const char *text); + // New ... + enum + { + LCD_WIDTH = 128, + LCD_HEIGHT = 32, + LCD_LINE_PER_PAGE = 8, + }; + + // 32 lines devide into 4 pages and 8 lines per page + // size: 32lines x 1056px + void go_to(uint8_t page, uint8_t col); + void write(uint8_t val, bool data, uint8_t mask = 0); + void write_line(uint8_t rows, uint8_t cols, uint8_t cnt, uint8_t** data, int x = 0, int y = 0, uint8_t mask = 0); + void clear(int x = 0, int y = 0, int w = -1, int h = -1); + +private: + void set_data_type(bool data); + void write_before(void); + void write_char(uint8_t val, uint8_t mask = 0); + void write_end(void); + }; diff --git a/ui/dev_menu.cpp b/ui/dev_menu.cpp new file mode 100644 index 0000000..19b6840 --- /dev/null +++ b/ui/dev_menu.cpp @@ -0,0 +1,461 @@ +#include "dev_menu.h" + +#include +#include "Displaydef.h" +#include +#include "keymonitor.h" +#include "Lcd.h" +#include "font.h" + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// dev_menu +dev_menu::dev_menu() +{} +dev_menu::~dev_menu() +{ + set_parent(nullptr); + for(auto& v: items_) + { + if(!v.leaf) + { + v.child->set_parent(nullptr); + v.child->release(); + } + } + items_.clear(); +} + +int dev_menu::find_item(const char* text) +{ + int ind = -1; + + for(size_t i = 0; i < items_.size(); ++i) + { + if(items_[i].text == text) + { + ind = i; + break; + } + } + + return ind; +} + +void dev_menu::set_parent(dev_menu* parent) +{ + if(parent_) + { + parent_->release(); + if(items_.size() && items_[0].id == MENU_ID_RETURN) + items_.erase(items_.begin()); + } + parent_ = parent; + if(parent_) + { + parent_->add_ref(); + if(!items_.size() || items_[0].id != MENU_ID_RETURN) + { + MITEM mi; + mi.text = WORDS_MENU_RETURN; + mi.leaf = true; + mi.id = MENU_ID_RETURN; + items_.insert(items_.begin(), mi); + } + } +} + +bool dev_menu::add_menu(const char* text, int id) +{ + int ind = find_item(text); + + if(ind != -1) + return false; + + MITEM mi; + + mi.id = id; + mi.leaf = true; + mi.text = text; + items_.push_back(mi); + + return true; +} +bool dev_menu::add_menu(const char* text, dev_menu* submenu) +{ + int ind = find_item(text); + + if(ind != -1 || !submenu) + return false; + + MITEM mi; + + mi.child = submenu; + mi.leaf = false; + mi.text = text; + items_.push_back(mi); + submenu->add_ref(); + submenu->set_parent(this); + + return true; +} +bool dev_menu::remove_menu(const char* text) +{ + int ind = find_item(text); + + if(ind == -1) + return false; + + if(!items_[ind].leaf) + items_[ind].child->release(); + items_.erase(items_.begin() + ind); + if(cur_ >= items_.size()) + cur_ = items_.size() - 1; + + return true; +} +bool dev_menu::move_to(bool next) +{ + bool ret = false; + + if(next) + { + if(cur_ < (int)items_.size() - 1) + { + cur_++; + ret = true; + } + } + else + { + if(cur_ > 0) + { + cur_--; + ret = true; + } + } + + return ret; +} +bool dev_menu::select(const char* txt) +{ + int ind = find_item(txt); + + if(ind == -1) + return false; + + cur_ = ind; + + return true; +} +void dev_menu::reset_pos(void) +{ + cur_ = 0; +} + +dev_menu* dev_menu::enter(int* id) +{ + dev_menu *menu = this; + + if(id) + *id = -1; + if(cur_ >= 0 && cur_ < items_.size()) + { + if(items_[cur_].leaf) + { + if(items_[cur_].id == MENU_ID_RETURN) + { + if(parent_) + menu = parent_; + } + else if(id) + *id = items_[cur_].id; + } + else + { + menu = items_[cur_].child; + menu->reset_pos(); + } + } + + menu->add_ref(); + + return menu; +} +int dev_menu::get_menu_text(std::vector& text) +{ + for(auto& v: items_) + text.push_back(v.text); + + return cur_; +} + + + + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// ui_mgr +enum +{ + MENU_CMD_ID_GET_ROLLER_COUNT = 0x100, + MENU_CMD_ID_CLEAR_ROLLER_COUNT, + MENU_CMD_ID_SLEEP_NOW, + MENU_CMD_ID_SHUTDOWN, +}; + +ui_mgr::ui_mgr() : disp_data_("lcd-msg") +{ + init(); + + auto ke = [this](int key) -> void + { + key_event(key); + }; + lcd_.reset(new Lcd()); + lcd_->Lcd_Initial_Lcd(false); + lcd_->clear(); + + keyboard_.reset(new KeyMonitor(ke)); + disp_thrd_.reset(new std::thread(&ui_mgr::thread_display, this)); + refresh_lcd(true); +} +ui_mgr::~ui_mgr() +{ + run_ = false; + disp_data_.trigger(); + if(disp_thrd_.get() && disp_thrd_->joinable()) + disp_thrd_->join(); + + clear(); +} + +void ui_mgr::do_menu_command(int cmd) +{ + if(handler_.count(cmd)) + handler_[cmd](cur_, cmd); + + // at last, we return to main menu OR parent ? + cur_->release(); + cur_ = root_; // main menu + cur_->add_ref(); +} +void ui_mgr::init(void) +{ + dev_menu *child = nullptr; + + root_ = new dev_menu(); + + // 分纸强度(低中高) + { + child = new dev_menu(); + child->add_menu(WORDS_MENU_LOW, (int)DisType::Dis_Set_PollPI_Low); + child->add_menu(WORDS_MENU_MID, (int)DisType::Dis_Set_PollPI_Mid); + child->add_menu(WORDS_MENU_HIGH, (int)DisType::Dis_Set_PollPI_High); + root_->add_menu(WORDS_MENU_SEPARATE_STRENGTH, child); + child->release(); + } + // 休眠时间(不休眠,5min, 10min, 20min, 30min, 1h, 2h, 4h) + { + child = new dev_menu(); + child->add_menu(WORDS_MENU_SLEEP_NONE, (int)DisType::Dis_Set_SleepMode_NEVER); + child->add_menu(WORDS_MENU_SLEEP_5_MIN, (int)DisType::Dis_Set_SleepMode_5M); + child->add_menu(WORDS_MENU_SLEEP_10_MIN, (int)DisType::Dis_Set_SleepMode_10M); + child->add_menu(WORDS_MENU_SLEEP_20_MIN, (int)DisType::Dis_Set_SleepMode_20M); + child->add_menu(WORDS_MENU_SLEEP_30_MIN, (int)DisType::Dis_Set_SleepMode_30M); + child->add_menu(WORDS_MENU_SLEEP_1_HOUR, (int)DisType::Dis_Set_SleepMode_1H); + child->add_menu(WORDS_MENU_SLEEP_2_HOUR, (int)DisType::Dis_Set_SleepMode_2H); + child->add_menu(WORDS_MENU_SLEEP_4_HOUR, (int)DisType::Dis_Set_SleepMode_4H); + root_->add_menu(WORDS_MENU_POWER, child); + child->release(); + } + // 升降台位置(低中高) + { + child = new dev_menu(); + child->add_menu(WORDS_MENU_LOW, (int)DisType::Dis_Set_TrayPosition_Low); + child->add_menu(WORDS_MENU_MID, (int)DisType::Dis_Set_TrayPosition_Mid); + child->add_menu(WORDS_MENU_HIGH, (int)DisType::Dis_Set_TrayPosition_High); + root_->add_menu(WORDS_MENU_LIFTER_POS, child); + child->release(); + } + + // 计数模式、手动模式、清理纸道、历史张数、滚轴张数、清除滚轴张数(确定,取消)、进入休眠、关机 + root_->add_menu(WORDS_MENU_COUNT_MODE, (int)DisType::Dis_Count_Page); + root_->add_menu(WORDS_MENU_MANUAL_MODE, (int)DisType::Dis_HandMode); + root_->add_menu(WORDS_MENU_CLEAR_PASSWAY, (int)DisType::Dis_Set_ClearPaperPass); + root_->add_menu(WORDS_MENU_HISTORY_COUNT, (int)DisType::Dis_Set_Get_History_ScanNum); + root_->add_menu(WORDS_MENU_ROLLER_COUNT, MENU_CMD_ID_GET_ROLLER_COUNT); + { + child = new dev_menu(); + child->add_menu(WORDS_MENU_YES, (int)DisType::Dis_Set_YES); + child->add_menu(WORDS_MENU_NO, (int)DisType::Dis_Set_No); + root_->add_menu(WORDS_MENU_RESET_ROLLOER_CNT, child); + child->release(); + } + root_->add_menu(WORDS_MENU_SLEEP_NOW, MENU_CMD_ID_SLEEP_NOW); + root_->add_menu(WORDS_MENU_SHUTDOWN, MENU_CMD_ID_SHUTDOWN); + + cur_ = root_; + cur_->add_ref(); +} +void ui_mgr::clear(void) +{ + if(cur_) + cur_->release(); + cur_ = nullptr; + + if(root_) + root_->release(); + root_ = nullptr; +} +void ui_mgr::refresh_lcd(bool cur_at_top) +{ + std::vector text, disp; + int cur = cur_->get_menu_text(text), sel = 0, + rows = Lcd::LCD_HEIGHT / font_size_.cy; + + if(cur >= 0 && cur < text.size()) + { + disp.push_back(text[cur]); + if(cur_at_top) + { + for(int i = cur + 1; i < text.size() && disp.size() < rows; ++i) + disp.push_back(text[i]); + for(int i = cur - 1; i >= 0 && disp.size() < rows; --i, sel++) + disp.insert(disp.begin(), text[i]); + } + else + { + for(int i = cur - 1; i >= 0 && disp.size() < rows; --i, sel++) + disp.insert(disp.begin(), text[i]); + for(int i = cur + 1; i < text.size() && disp.size() < rows; ++i) + disp.push_back(text[i]); + } + } + + rows = 0; + for(int i = 0; i < disp.size(); ++i) + { + DISPDATA dd; + + memset(&dd, 0, sizeof(dd)); + if(i == 0) + disp_data_.save(dd, true); + dd.mask = i == sel ? 0x0ff : 0; + dd.x = font_size_.cx; + dd.y = rows; + dd.rows = font_size_.cy; + dd.cols = font_size_.cx; + dd.cnt = get_string_font(disp[i].c_str(), dd.ptr); + cur = disp_data_.save(dd, true); + rows += font_size_.cy; + printf("display '%s', queue = %d, mask = %02x\n", disp[i].c_str(), cur, dd.mask); + } +} +void ui_mgr::move_to(bool next) +{ + if(cur_) + { + if(cur_->move_to(next)) + { + // refresh LCD + refresh_lcd(!next); + } + } +} +void ui_mgr::enter(void) +{ + if(!menu_mode_) + { + menu_mode_ = true; + if(cur_) + cur_->release(); + cur_ = root_; + if(cur_) + cur_->add_ref(); + } + + if(cur_) + { + int id = -1; + dev_menu* bef = cur_; + + cur_ = cur_->enter(&id); + bef->release(); + if(id != -1) + { + do_menu_command(id); + } + if(cur_ != bef) + { + // refresh LCD + refresh_lcd(true); + } + } +} +int ui_mgr::get_string_font(const char* text, uint8_t** ptr) +{ + DISPDATA dd; + int cnt = 0, ind = 0; + + for(; text[ind] && cnt < _countof(dd.ptr); ++cnt) + { + // Fixed ME !!! how to count a character width ? here I assume 3-bytes + char utf8[4] = {text[ind], text[ind + 1], text[ind + 2], 0}; + + if(text[ind] >= 0 && text[ind] <= 0x7f) + { + utf8[1] = utf8[2] = 0; + ind++; + } + else + { + ind += 3; + } + ptr[cnt] = get_font_data(utf8) + 2; // skip height and widht data + } + + return cnt; +} + +void ui_mgr::thread_display(void) +{ + DISPDATA dd; + while(run_) + { + if(disp_data_.take(dd, true)) + { + if(dd.cnt) + lcd_->write_line(dd.rows, dd.cols, dd.cnt, dd.ptr, dd.x, dd.y, dd.mask); + else + lcd_->clear(); + } + } +} + +void ui_mgr::key_event(int key) +{ + if(key == (int)KeyMonitor::HGKey::Key_Enter) + enter(); + else if(key == (int)KeyMonitor::HGKey::Key_Left) + move_to(false); + else if(key == (int)KeyMonitor::HGKey::Key_Right) + move_to(true); + else if(key == (int)KeyMonitor::HGKey::Key_Cancle) + { + // stop scanning here ... + } + else if(key == -1) // interrupted by status message, we return to main menu + { + if(cur_) + cur_->release(); + cur_ = root_; + if(cur_) + { + cur_->add_ref(); + cur_->reset_pos(); + } + } + else + { + utils::to_log(LOG_LEVEL_ALL, "Unhandled keyboard event: %02X\n", key); + } +} diff --git a/ui/dev_menu.h b/ui/dev_menu.h new file mode 100644 index 0000000..bb715d8 --- /dev/null +++ b/ui/dev_menu.h @@ -0,0 +1,124 @@ +// 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 void +#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 find_item(const char* text); + +public: + dev_menu(); + +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); + 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 + // + // Return: current menu index + int get_menu_text(std::vector& text); +}; + + +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; + SIZE font_size_ = {16, 16}; + + std::map handler_; + std::unique_ptr lcd_; + std::unique_ptr keyboard_; + + void do_menu_command(int cmd); + 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); + + 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; + safe_fifo disp_data_; + std::unique_ptr disp_thrd_; + void thread_display(void); + +public: + ui_mgr(); +protected: + virtual ~ui_mgr(); + +public: + void key_event(int key); +}; diff --git a/ui/font.cpp b/ui/font.cpp new file mode 100644 index 0000000..e9238c8 --- /dev/null +++ b/ui/font.cpp @@ -0,0 +1,382 @@ +#include "font.h" + + +#include +#include + + + +namespace font_data +{ + static uint8_t question[] = {16, 16 + , 0x00, 0xE0, 0xD0, 0x08, 0x08, 0x08, 0x18, 0xF0, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + , 0x00, 0x00, 0x00, 0x00, 0x6E, 0x62, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }; + +}; + +class font_init +{ + std::map font_map_; + +public: + font_init() + { +static uint8_t fan[] = {16, 16 + , 0x00, 0x40, 0x40, 0x42, 0xCC, 0x48, 0x00, 0xFC, 0xFC, 0x24, 0x24, 0x24, 0x24, 0xA6, 0xE2, 0x00 + , 0x00, 0x00, 0xC0, 0x20, 0x3F, 0x20, 0x58, 0x4F, 0xA1, 0x90, 0x91, 0x8E, 0x86, 0x87, 0x98, 0xB8 + }; +font_map_["\350\277\224"] = fan; + +static uint8_t hui[] = {16, 16 + , 0x00, 0x00, 0x00, 0xFE, 0x02, 0x02, 0xE2, 0x22, 0x22, 0x22, 0x22, 0xE2, 0xE2, 0x02, 0x02, 0xFE + , 0x00, 0x00, 0x00, 0xFF, 0x20, 0x20, 0x27, 0x22, 0x22, 0x22, 0x22, 0x27, 0x27, 0x20, 0x20, 0xFF + }; +font_map_["\345\233\236"] = hui; + +static uint8_t shang[] = {16, 16 + , 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x42, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40 + , 0x00, 0x00, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x7F, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40 + }; +font_map_["\344\270\212"] = shang; + +static uint8_t yi[] = {16, 16 + , 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xC0 + , 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }; +font_map_["\344\270\200"] = yi; + +static uint8_t ji[] = {16, 16 + , 0x00, 0x80, 0xE0, 0xB0, 0x0E, 0x86, 0x60, 0x30, 0x04, 0xFC, 0xFC, 0x04, 0xC4, 0xF4, 0x9C, 0x84 + , 0x00, 0x00, 0xD8, 0x4E, 0x4B, 0x49, 0x84, 0x64, 0x38, 0x9F, 0x83, 0x4C, 0x70, 0x70, 0xCE, 0x83 + }; +font_map_["\347\272\247"] = ji; + +static uint8_t cai[] = {16, 16 + , 0x00, 0x00, 0x04, 0x04, 0x84, 0x04, 0x3F, 0x3F, 0x64, 0xA4, 0x2F, 0x3F, 0x34, 0xF4, 0x74, 0x04 + , 0x00, 0x04, 0x84, 0x84, 0x44, 0x67, 0x34, 0x1C, 0x0C, 0xFF, 0x0C, 0x14, 0x27, 0x45, 0xC4, 0x84 + }; +font_map_["\350\217\234"] = cai; + +static uint8_t dan[] = {16, 16 + , 0x00, 0x00, 0x00, 0x00, 0xF8, 0x48, 0x4B, 0x4E, 0xF8, 0xF8, 0x48, 0x4E, 0x4B, 0xF8, 0xF8, 0x00 + , 0x00, 0x00, 0x10, 0x10, 0x17, 0x12, 0x12, 0x12, 0xFF, 0xFF, 0x12, 0x12, 0x12, 0x17, 0x17, 0x10 + }; +font_map_["\345\215\225"] = dan; + +static uint8_t fen[] = {16, 16 + , 0x00, 0x00, 0x00, 0x80, 0xE0, 0xB8, 0x9E, 0x86, 0x80, 0x80, 0x81, 0x8F, 0x98, 0xE0, 0x40, 0xC0 + , 0x00, 0x00, 0x01, 0x00, 0x80, 0x40, 0x30, 0x1F, 0x03, 0x80, 0x80, 0x80, 0xFF, 0x07, 0x00, 0x00 + }; +font_map_["\345\210\206"] = fen; + +static uint8_t zhi[] = {16, 16 + , 0x00, 0x80, 0xC0, 0xB0, 0x8E, 0xC6, 0x60, 0x20, 0xF8, 0x40, 0x44, 0x44, 0xFC, 0x44, 0x46, 0x46 + , 0x00, 0x40, 0x78, 0x2E, 0x2B, 0x29, 0x14, 0x00, 0xFF, 0x40, 0x20, 0x20, 0x07, 0x1E, 0x30, 0x60 + }; +font_map_["\347\272\270"] = zhi; + +static uint8_t qiang[] = {16, 16 + , 0x00, 0x00, 0xE2, 0xE2, 0x22, 0x22, 0x7E, 0x00, 0x80, 0xBE, 0x92, 0x92, 0xF2, 0x92, 0xBE, 0xBE + , 0x00, 0x00, 0x87, 0x82, 0x82, 0xFE, 0x1E, 0x80, 0x9F, 0x88, 0x88, 0x88, 0xFF, 0x88, 0x88, 0xFF + }; +font_map_["\345\274\272"] = qiang; + +static uint8_t du[] = {16, 16 + , 0x00, 0x00, 0x00, 0xFC, 0x24, 0x24, 0x24, 0xFC, 0xF4, 0x27, 0x26, 0x24, 0xFC, 0xF4, 0x24, 0x24 + , 0x00, 0x80, 0x70, 0x1F, 0x00, 0x00, 0x04, 0x87, 0x9D, 0x65, 0x65, 0x65, 0x9D, 0x8D, 0x84, 0x80 + }; +font_map_["\345\272\246"] = du; + +static uint8_t di[] = {16, 16 + , 0x00, 0x00, 0xC0, 0xF0, 0xFE, 0x07, 0x00, 0xF8, 0x88, 0x88, 0x80, 0xFC, 0x84, 0x86, 0x86, 0x80 + , 0x00, 0x01, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0x60, 0x20, 0xD0, 0x83, 0x1F, 0x38, 0x60, 0xC0 + }; +font_map_["\344\275\216"] = di; + +static uint8_t zhong[] = {16, 16 + , 0x00, 0x00, 0x10, 0xF0, 0x10, 0x10, 0x10, 0x10, 0xFF, 0xFF, 0x10, 0x10, 0x10, 0x10, 0x10, 0xF0 + , 0x00, 0x00, 0x00, 0x07, 0x02, 0x02, 0x02, 0x02, 0xFF, 0xFF, 0x02, 0x02, 0x02, 0x02, 0x02, 0x07 + }; +font_map_["\344\270\255"] = zhong; + +static uint8_t gao[] = {16, 16 + , 0x00, 0x00, 0x04, 0x04, 0x04, 0xF4, 0x54, 0x54, 0x57, 0x56, 0x54, 0x54, 0xF4, 0x14, 0x04, 0x04 + , 0x00, 0x00, 0x00, 0xFF, 0x01, 0x01, 0x7D, 0x25, 0x25, 0x25, 0x25, 0x7D, 0x85, 0x81, 0x81, 0xFF + }; +font_map_["\351\253\230"] = gao; + +static uint8_t xiu[] = {16, 16 + , 0x00, 0x00, 0x80, 0x60, 0xFC, 0x07, 0x12, 0x10, 0x10, 0xD0, 0xFF, 0xFF, 0xF0, 0x10, 0x10, 0x10 + , 0x00, 0x03, 0x01, 0x00, 0xFF, 0x20, 0x10, 0x0C, 0x07, 0x01, 0xFF, 0xFF, 0x00, 0x07, 0x0C, 0x18 + }; +font_map_["\344\274\221"] = xiu; + +static uint8_t mian[] = {16, 16 + , 0x00, 0xFC, 0xFC, 0x44, 0x44, 0xFC, 0x00, 0x02, 0xFE, 0x22, 0x22, 0xE2, 0xE2, 0x22, 0x22, 0x7E + , 0x00, 0x7F, 0x7F, 0x22, 0x22, 0x7F, 0x00, 0x80, 0xFF, 0xC1, 0x21, 0x03, 0x1F, 0x71, 0xC1, 0x81 + }; +font_map_["\347\234\240"] = mian; + +static uint8_t shi[] = {16, 16 + , 0x00, 0x00, 0xFC, 0x84, 0x84, 0x84, 0xFC, 0x10, 0x90, 0x90, 0x10, 0x10, 0x10, 0xFF, 0x10, 0x10 + , 0x00, 0x00, 0x7F, 0x10, 0x10, 0x10, 0x3F, 0x00, 0x00, 0x03, 0x87, 0x80, 0x80, 0xFF, 0x00, 0x00 + }; +font_map_["\346\227\266"] = shi; + +static uint8_t jian[] = {16, 16 + , 0x00, 0x00, 0xFC, 0xFC, 0x03, 0x06, 0xE0, 0xE2, 0x22, 0x22, 0x22, 0xE2, 0x02, 0x02, 0x02, 0xFE + , 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x1F, 0x1F, 0x09, 0x09, 0x09, 0x1F, 0x80, 0x80, 0x80, 0xFF + }; +font_map_["\351\227\264"] = jian; + +static uint8_t bu[] = {16, 16 + , 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x82, 0xE2, 0x7A, 0xFE, 0x06, 0x42, 0xC2, 0x82, 0x02, 0x02 + , 0x00, 0x10, 0x08, 0x08, 0x06, 0x03, 0x01, 0x00, 0x80, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x03, 0x0E + }; +font_map_["\344\270\215"] = bu; + +static uint8_t sheng[] = {16, 16 + , 0x00, 0x00, 0x88, 0x88, 0x88, 0x80, 0xFC, 0xFC, 0x84, 0x86, 0x80, 0x80, 0xFE, 0x82, 0x80, 0x80 + , 0x00, 0x00, 0x00, 0x80, 0x40, 0x30, 0x1F, 0x01, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00 + }; +font_map_["\345\215\207"] = sheng; + +static uint8_t jiang[] = {16, 16 + , 0x00, 0x00, 0xFE, 0xFE, 0x02, 0xFA, 0x8E, 0x20, 0x90, 0x8E, 0x4F, 0x72, 0x32, 0x5A, 0x4E, 0xC2 + , 0x00, 0x00, 0xFF, 0xFF, 0x08, 0x18, 0x0F, 0x16, 0x1E, 0x16, 0x12, 0x12, 0xFF, 0x12, 0x12, 0x12 + }; +font_map_["\351\231\215"] = jiang; + +static uint8_t tai[] = {16, 16 + , 0x00, 0x00, 0x00, 0xC0, 0xE0, 0xB0, 0x98, 0x8E, 0x87, 0x02, 0x40, 0x40, 0x50, 0x70, 0x60, 0xC0 + , 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFE, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0xFE, 0x02, 0x00 + }; +font_map_["\345\217\260"] = tai; + +static uint8_t wei[] = {16, 16 + , 0x00, 0x00, 0x80, 0x70, 0xFE, 0x07, 0x10, 0x10, 0x90, 0x10, 0x17, 0x1E, 0x10, 0xD0, 0xD0, 0x10 + , 0x00, 0x02, 0x01, 0x00, 0xFF, 0x00, 0x80, 0x80, 0x87, 0xBE, 0x80, 0x80, 0xF8, 0x8F, 0x81, 0x80 + }; +font_map_["\344\275\215"] = wei; + +static uint8_t zhi4[] = {16, 16 + , 0x00, 0x00, 0x40, 0x7E, 0xDE, 0xD2, 0xD2, 0xDE, 0xF2, 0xF2, 0xDE, 0xDE, 0xD2, 0xD2, 0x7E, 0x5E + , 0x00, 0x80, 0x80, 0x80, 0xFF, 0xFF, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xFF, 0x80, 0x80 + }; +font_map_["\347\275\256"] = zhi4; + +static uint8_t num5[] = {16, 16 + , 0x00, 0x00, 0xF8, 0x88, 0x88, 0x88, 0x88, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + , 0x00, 0x30, 0x79, 0x41, 0x40, 0x40, 0x61, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }; +font_map_["\065\000\000"] = num5; + +static uint8_t m[] = {16, 16 + , 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + , 0x40, 0x7F, 0x41, 0x40, 0x7F, 0x7F, 0x40, 0x7F, 0x7F, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }; +font_map_["\155\000\000"] = m; + +static uint8_t i[] = {16, 16 + , 0x00, 0x00, 0x80, 0x80, 0x98, 0x98, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + , 0x00, 0x00, 0x40, 0x40, 0x7F, 0x7F, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }; +font_map_["\151\000\000"] = i; + +static uint8_t n[] = {16, 16 + , 0x00, 0x80, 0x80, 0x00, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + , 0x00, 0x41, 0x7F, 0x41, 0x00, 0x00, 0x41, 0x7F, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }; +font_map_["\156\000\000"] = n; + +static uint8_t num0[] = {16, 16 + , 0x00, 0xC0, 0xF0, 0x18, 0x08, 0x08, 0x38, 0xF0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + , 0x00, 0x0F, 0x3F, 0x60, 0x40, 0x40, 0x70, 0x3F, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }; +font_map_["\060\000\000"] = num0; + +static uint8_t num1[] = {16, 16 + , 0x00, 0x00, 0x10, 0x10, 0xF0, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + , 0x00, 0x00, 0x40, 0x40, 0x7F, 0x7F, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }; +font_map_["\061\000\000"] = num1; + +static uint8_t num2[] = {16, 16 + , 0x00, 0x60, 0x70, 0x08, 0x08, 0x08, 0x98, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + , 0x00, 0x60, 0x70, 0x48, 0x44, 0x42, 0x41, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }; +font_map_["\062\000\000"] = num2; + +static uint8_t num3[] = {16, 16 + , 0x00, 0x30, 0x38, 0x08, 0x08, 0x88, 0xF8, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + , 0x00, 0x30, 0x70, 0x40, 0x41, 0x41, 0x62, 0x3E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }; +font_map_["\063\000\000"] = num3; + +static uint8_t num4[] = {16, 16 + , 0x00, 0x00, 0x00, 0x80, 0x60, 0xF8, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + , 0x00, 0x0C, 0x0B, 0x09, 0x48, 0x7F, 0x7F, 0x48, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }; +font_map_["\064\000\000"] = num4; + +static uint8_t h[] = {16, 16 + , 0x00, 0x0C, 0xFC, 0x00, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + , 0x00, 0x40, 0x7F, 0x41, 0x00, 0x00, 0x41, 0x7F, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }; +font_map_["\150\000\000"] = h; + +static uint8_t ji4[] = {16, 16 + , 0x00, 0x40, 0x40, 0x42, 0xC4, 0x4C, 0x00, 0x80, 0x80, 0x80, 0x80, 0xFE, 0x80, 0x80, 0x80, 0x80 + , 0x00, 0x00, 0x00, 0x00, 0xFF, 0x60, 0x30, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00 + }; +font_map_["\350\256\241"] = ji4; + +static uint8_t shu[] = {16, 16 + , 0x00, 0x00, 0x10, 0x9E, 0x5C, 0xFF, 0xFF, 0x58, 0xD6, 0x92, 0x70, 0xFF, 0x13, 0x10, 0xF0, 0x70 + , 0x00, 0x00, 0x05, 0x84, 0x9C, 0x6F, 0x67, 0x34, 0x5C, 0xC1, 0x80, 0x43, 0x3C, 0x3C, 0xCF, 0xC0 + }; +font_map_["\346\225\260"] = shu; + +static uint8_t mo[] = {16, 16 + , 0x00, 0x10, 0x10, 0xD0, 0xFF, 0x90, 0x90, 0x14, 0xE4, 0xFF, 0xAF, 0xA4, 0xA4, 0xBF, 0xE4, 0xE4 + , 0x00, 0x08, 0x06, 0x03, 0xFF, 0x00, 0x0B, 0x08, 0x8F, 0xCB, 0x7A, 0x3E, 0x3A, 0x6A, 0xCF, 0x8F + }; +font_map_["\346\250\241"] = mo; + +static uint8_t shi4[] = {16, 16 + , 0x00, 0x00, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0xFF, 0xFB, 0x10, 0x12, 0x1E, 0x1C + , 0x00, 0x40, 0xC0, 0x40, 0x60, 0x3F, 0x3F, 0x20, 0x00, 0x10, 0x11, 0x0F, 0x38, 0x60, 0xC0, 0x80 + }; +font_map_["\345\274\217"] = shi4; + +static uint8_t shou[] = {16, 16 + , 0x00, 0x00, 0x00, 0x48, 0x48, 0x48, 0x40, 0x44, 0xFC, 0xFC, 0x44, 0x44, 0x44, 0x46, 0x46, 0x40 + , 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x82, 0x82, 0xFF, 0xFF, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02 + }; +font_map_["\346\211\213"] = shou; + +static uint8_t dong[] = {16, 16 + , 0x00, 0x40, 0x44, 0x44, 0xC4, 0xC4, 0x44, 0x44, 0x44, 0x50, 0x10, 0xFF, 0xFF, 0x10, 0x10, 0xF0 + , 0x00, 0x30, 0x38, 0x36, 0x13, 0x11, 0x12, 0x1C, 0xB8, 0x60, 0x38, 0x0F, 0x81, 0x80, 0x80, 0xFF + }; +font_map_["\345\212\250"] = dong; + +static uint8_t qing[] = {16, 16 + , 0x00, 0x20, 0x60, 0xC6, 0x8E, 0x60, 0x40, 0x44, 0x54, 0x54, 0x7F, 0x7F, 0x54, 0x54, 0x54, 0x44 + , 0x00, 0x00, 0xD0, 0xFC, 0x07, 0x00, 0x00, 0xFF, 0x15, 0x15, 0x15, 0x15, 0x95, 0x95, 0xFF, 0xFF + }; +font_map_["\346\270\205"] = qing; + +static uint8_t li3[] = {16, 16 + , 0x00, 0x00, 0x84, 0x84, 0xFC, 0x84, 0x84, 0x84, 0xFE, 0x12, 0x12, 0xFE, 0xFE, 0x12, 0x12, 0xFE + , 0x00, 0x20, 0x60, 0x20, 0x3F, 0x10, 0x90, 0x88, 0x93, 0x91, 0x91, 0xFF, 0xFF, 0x91, 0x91, 0x93 + }; +font_map_["\347\220\206"] = li3; + +static uint8_t dao[] = {16, 16 + , 0x00, 0x40, 0x40, 0x46, 0xCE, 0x00, 0x08, 0x08, 0xEB, 0xAE, 0xBC, 0xB8, 0xAC, 0xAF, 0xEB, 0x28 + , 0x00, 0x40, 0x60, 0x30, 0x1F, 0x20, 0x40, 0x40, 0xFF, 0x92, 0x92, 0x92, 0x92, 0x92, 0xBF, 0x80 + }; +font_map_["\351\201\223"] = dao; + +static uint8_t li4[] = {16, 16 + , 0x00, 0x00, 0x00, 0xFE, 0xFE, 0x02, 0x42, 0x42, 0x42, 0xFA, 0xFA, 0x42, 0x42, 0x42, 0x42, 0xC2 + , 0x00, 0x00, 0xC0, 0x3F, 0x0F, 0x00, 0x80, 0x60, 0x38, 0x1F, 0x01, 0x80, 0x80, 0x80, 0xF8, 0x7F + }; +font_map_["\345\216\206"] = li4; + +static uint8_t shi3[] = {16, 16 + , 0x00, 0x00, 0x00, 0x00, 0xF8, 0x88, 0x88, 0x88, 0x88, 0xFF, 0xFF, 0x88, 0x88, 0x88, 0xF8, 0xF8 + , 0x00, 0x00, 0x00, 0x00, 0x81, 0x82, 0xC4, 0x78, 0x38, 0x3F, 0x60, 0x40, 0xC0, 0xC0, 0x81, 0x81 + }; +font_map_["\345\217\262"] = shi3; + +static uint8_t zhang[] = {16, 16 + , 0x00, 0x00, 0xE2, 0x62, 0x22, 0x22, 0x7E, 0x80, 0x80, 0xFF, 0xFF, 0xA0, 0xB0, 0x98, 0x8C, 0x84 + , 0x00, 0x00, 0x83, 0x81, 0x81, 0xFF, 0x07, 0x00, 0x00, 0xFF, 0xFF, 0x41, 0x2E, 0x18, 0x30, 0x60 + }; +font_map_["\345\274\240"] = zhang; + +static uint8_t gun[] = {16, 16 + , 0x00, 0x20, 0x60, 0x46, 0x84, 0x60, 0x44, 0xA4, 0xB4, 0x54, 0x25, 0xA7, 0x84, 0xD4, 0x94, 0x34 + , 0x00, 0x00, 0xF0, 0xFC, 0x07, 0x20, 0x30, 0x11, 0xF9, 0x8F, 0x47, 0x0E, 0x30, 0x68, 0xCD, 0x86 + }; +font_map_["\346\273\232"] = gun; + +static uint8_t zhou[] = {16, 16 + , 0x00, 0x00, 0xC8, 0xF8, 0x9F, 0xF8, 0x88, 0x88, 0x80, 0xF0, 0x10, 0x10, 0xFF, 0x10, 0x10, 0xF0 + , 0x00, 0x10, 0x10, 0x18, 0x08, 0xFF, 0x00, 0x04, 0x04, 0xFF, 0x42, 0x42, 0x7F, 0x42, 0x42, 0xFF + }; +font_map_["\350\275\264"] = zhou; + +static uint8_t jin[] = {16, 16 + , 0x00, 0x40, 0x40, 0x44, 0xCC, 0x08, 0x10, 0x10, 0x10, 0xFE, 0x10, 0x10, 0x12, 0xFE, 0x10, 0x10 + , 0x00, 0xC0, 0x40, 0x20, 0x3F, 0x20, 0x61, 0xF1, 0x99, 0x87, 0x81, 0x81, 0xE1, 0xBF, 0x81, 0x81 + }; +font_map_["\350\277\233"] = jin; + +static uint8_t ru[] = {16, 16 + , 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x86, 0xFC, 0x78, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00 + , 0x00, 0x80, 0x40, 0x60, 0x30, 0x18, 0x0E, 0x03, 0x00, 0x00, 0x01, 0x07, 0x0C, 0x38, 0x70, 0x60 + }; +font_map_["\345\205\245"] = ru; + +static uint8_t guan[] = {16, 16 + , 0x00, 0x00, 0x00, 0x10, 0x10, 0x11, 0x12, 0x1E, 0xF0, 0xF0, 0x18, 0x1E, 0x13, 0x10, 0x10, 0x10 + , 0x00, 0x00, 0x01, 0x81, 0x81, 0x41, 0x21, 0x19, 0x0F, 0x03, 0x07, 0x19, 0x31, 0x61, 0xC1, 0x81 + }; +font_map_["\345\205\263"] = guan; + +static uint8_t ji1[] = {16, 16 + , 0x00, 0x00, 0x10, 0x90, 0xFF, 0x91, 0x90, 0x10, 0x00, 0xFE, 0x02, 0x02, 0x02, 0xFE, 0x02, 0x00 + , 0x00, 0x10, 0x0C, 0x03, 0xFF, 0x00, 0x81, 0xC3, 0x38, 0x0F, 0x00, 0x00, 0x00, 0xFF, 0x80, 0x80 + }; +font_map_["\346\234\272"] = ji1; + +static uint8_t que[] = {16, 16 + , 0x00, 0x00, 0x84, 0xF4, 0xBC, 0x84, 0x84, 0x04, 0x30, 0xFC, 0x27, 0x27, 0xE4, 0x3C, 0x2C, 0xE0 + , 0x00, 0x04, 0x03, 0x7F, 0x10, 0x10, 0x3F, 0x80, 0x70, 0x3F, 0x09, 0x09, 0xFF, 0x89, 0x89, 0xFF + }; +font_map_["\347\241\256"] = que; + +static uint8_t ding[] = {16, 16 + , 0x00, 0x00, 0x20, 0x78, 0x48, 0x48, 0x48, 0x48, 0x49, 0xCE, 0x48, 0x48, 0x48, 0x48, 0x68, 0x58 + , 0x00, 0x00, 0x80, 0xC0, 0x3E, 0x1E, 0x20, 0x40, 0xC0, 0xFF, 0x84, 0x84, 0x84, 0x84, 0x84, 0x80 + }; +font_map_["\345\256\232"] = ding; + +static uint8_t qu[] = {16, 16 + , 0x00, 0x00, 0x02, 0xFE, 0x22, 0x22, 0x22, 0xFE, 0x02, 0x0A, 0x78, 0x88, 0x08, 0x08, 0xF8, 0x38 + , 0x00, 0x20, 0x30, 0x1F, 0x11, 0x11, 0x09, 0xFF, 0x08, 0x88, 0x40, 0x37, 0x1C, 0x3F, 0x61, 0xC0 + }; +font_map_["\345\217\226"] = qu; + +static uint8_t xiao[] = {16, 16 + , 0x00, 0x00, 0x60, 0xC2, 0x0E, 0x8C, 0x70, 0x02, 0xEE, 0x3C, 0x20, 0x3F, 0x3F, 0x30, 0xEC, 0xE6 + , 0x00, 0x00, 0x00, 0xF0, 0xFC, 0x07, 0x00, 0x00, 0xFF, 0x09, 0x09, 0x09, 0x89, 0x89, 0xFF, 0xFF + }; +font_map_["\346\266\210"] = xiao; + + + + } + ~font_init() + {} + + uint8_t* get_font_data(const char* str) + { + if(font_map_.count(str)) + { + return font_map_[str]; + } + + return font_data::question; + } +}; +static font_init g_fi_; + +uint8_t* get_font_data(const char* str) +{ + return g_fi_.get_font_data(str); +} diff --git a/ui/font.h b/ui/font.h new file mode 100644 index 0000000..a69e546 --- /dev/null +++ b/ui/font.h @@ -0,0 +1,7 @@ +// custom font data +// +// Date: 2024-02-02 +#pragma once +#include + +uint8_t* get_font_data(const char* str); diff --git a/ui/keymonitor.cpp b/ui/keymonitor.cpp new file mode 100644 index 0000000..0ea3b73 --- /dev/null +++ b/ui/keymonitor.cpp @@ -0,0 +1,205 @@ +#include "keymonitor.h" + +#include +#include +#include + +#define STATUS_SUCCESS 0 +#define STATUS_FAILURE -1 + +#define CH455_GET_KEY 0x0700 // 获取按键,返回按键代码 +#define CH455_SYSOFF 0x0400 // 关闭显示、关闭键盘 + +#define CH455_I2C_ADDR 0x40 // CH455的地址 +#define CH455_I2C_MASK 0x3E // CH455的高字节命令掩码 + +#define CH455_BIT_ENABLE 0x01 +//#define CH455_BIT_ENABLE 0x03 // 开启/关闭位 +#define CH455_BIT_SLEEP 0x04 // 睡眠控制位 + + +#define CH455_SYSON ( CH455_SYSOFF | CH455_BIT_ENABLE ) +#define CH455_SLEEPOFF CH455_SYSOFF // 关闭睡眠 +#define CH455_SLEEPON (CH455_SYSOFF|CH455_BIT_SLEEP) // 开启睡眠 + +KeyMonitor::KeyMonitor(std::function keycall) : m_keycall(keycall) +{ + m_gpioi2c_SCL = std::make_shared(44); //I2C_SCL + m_gpioi2c_SCL->setDirection(Gpio::out); + m_gpioi2c_SDA = std::make_shared(43); //I2C_SDA + m_gpioi2c_SDA->setDirection(Gpio::out); + write_cmd(CH455_SYSON); + printf("read_key = %02x\n", read_key()); + setled(HGLed::Led_All_close); + auto pincall=[&](int pin) + { + auto value= read_key(); + printf("Key = %02x pin value = %d \n",value,pin); + if(m_keycall) + m_keycall(value); + }; + m_keymonitor = std::make_shared(52,pincall); +} + +KeyMonitor::~KeyMonitor() +{ + if(m_gpioi2c_SCL.get()) + m_gpioi2c_SCL.reset(); + + if(m_gpioi2c_SDA.get()) + m_gpioi2c_SDA.reset(); + + if(m_keymonitor.get()) + m_keymonitor.reset(); +} + +void KeyMonitor::init() +{ +} + +void KeyMonitor::i2c_start() +{ + m_gpioi2c_SDA->setValue(Gpio::GpioLevel::High); + std::this_thread::sleep_for(std::chrono::microseconds(5)); + m_gpioi2c_SCL->setValue(Gpio::GpioLevel::High); + std::this_thread::sleep_for(std::chrono::microseconds(5)); + m_gpioi2c_SDA->setValue(Gpio::GpioLevel::Low); + std::this_thread::sleep_for(std::chrono::microseconds(5)); + m_gpioi2c_SCL->setValue(Gpio::GpioLevel::Low); + std::this_thread::sleep_for(std::chrono::microseconds(5)); +} + +void KeyMonitor::i2c_write(unsigned char cmd) +{ + unsigned char i; + for(i=0; i<8; i++) + { + //IOWR(I2C_SCL, 0); //钳住I2C总线,准备发送数据 + if(cmd & 0x80) + m_gpioi2c_SDA->setValue(Gpio::GpioLevel::High); + else + m_gpioi2c_SDA->setValue(Gpio::GpioLevel::Low); + + std::this_thread::sleep_for(std::chrono::microseconds(5)); + m_gpioi2c_SCL->setValue(Gpio::GpioLevel::High); + std::this_thread::sleep_for(std::chrono::microseconds(5)); + m_gpioi2c_SCL->setValue(Gpio::GpioLevel::Low); + std::this_thread::sleep_for(std::chrono::microseconds(5)); + cmd<<=1; + } + std::this_thread::sleep_for(std::chrono::microseconds(5)); + m_gpioi2c_SDA->setValue(Gpio::GpioLevel::High); + std::this_thread::sleep_for(std::chrono::microseconds(5)); + m_gpioi2c_SCL->setValue(Gpio::GpioLevel::High); + std::this_thread::sleep_for(std::chrono::microseconds(5)); + m_gpioi2c_SCL->setValue(Gpio::GpioLevel::Low); + std::this_thread::sleep_for(std::chrono::microseconds(5)); +} + +unsigned char KeyMonitor::i2c_read() +{ + unsigned char bytedata = 0; + m_gpioi2c_SDA->setDirection(Gpio::in);//将数据设置为输入模式 + //m_gpioi2c_SDA->setValue(Gpio::GpioLevel::High); + std::this_thread::sleep_for(std::chrono::microseconds(5)); + m_gpioi2c_SCL->setValue(Gpio::GpioLevel::Low); + std::this_thread::sleep_for(std::chrono::microseconds(5)); + for(int i=0; i<8; i++) + { + m_gpioi2c_SCL->setValue(Gpio::GpioLevel::High); + std::this_thread::sleep_for(std::chrono::microseconds(5)); + bytedata <<= 1; + bytedata = bytedata | (m_gpioi2c_SDA->getValue()); + std::this_thread::sleep_for(std::chrono::microseconds(5)); + m_gpioi2c_SCL->setValue(Gpio::GpioLevel::Low); + std::this_thread::sleep_for(std::chrono::microseconds(5)); + } + m_gpioi2c_SDA->setDirection(Gpio::out); + m_gpioi2c_SDA->setValue(Gpio::GpioLevel::High);////数据线设置回输出模式 + std::this_thread::sleep_for(std::chrono::microseconds(5)); + m_gpioi2c_SCL->setValue(Gpio::GpioLevel::High); + std::this_thread::sleep_for(std::chrono::microseconds(5)); + m_gpioi2c_SCL->setValue(Gpio::GpioLevel::Low); + std::this_thread::sleep_for(std::chrono::microseconds(5)); + return bytedata; +} + +void KeyMonitor::i2c_stop() +{ + m_gpioi2c_SCL->setValue(Gpio::GpioLevel::Low); + std::this_thread::sleep_for(std::chrono::microseconds(5)); + m_gpioi2c_SDA->setValue(Gpio::GpioLevel::Low); + std::this_thread::sleep_for(std::chrono::microseconds(5)); + m_gpioi2c_SCL->setValue(Gpio::GpioLevel::High); + std::this_thread::sleep_for(std::chrono::microseconds(5)); + m_gpioi2c_SDA->setValue(Gpio::GpioLevel::High); + std::this_thread::sleep_for(std::chrono::microseconds(5)); +} + +void KeyMonitor::write_cmd(unsigned short cmd) +{ + i2c_start(); + i2c_write(((unsigned char)(cmd>>7)&CH455_I2C_MASK)|CH455_I2C_ADDR); + i2c_write(cmd); + i2c_stop(); +} + +unsigned char KeyMonitor::read_key() +{ + unsigned char key=0; + i2c_start(); + i2c_write((unsigned char)(CH455_GET_KEY>>7)&CH455_I2C_MASK|0x01|CH455_I2C_ADDR); + key = i2c_read(); + i2c_stop(); + return key; +} + +std::uint8_t KeyMonitor::getledstate() +{ + return m_ledstate; +} + +void KeyMonitor::setled(HGLed value) +{ + switch (value) + { + case HGLed::Led_All_close: + m_ledstate = 0; + break; +#ifdef G200 + case HGLed::Led_All_open: + m_ledstate = 0xf8; + break; + case HGLed::Led_Count_close: + m_ledstate = m_ledstate & 0xef; + break; + case HGLed::Led_Count_open: + m_ledstate = m_ledstate | 0x10; + break; + case HGLed::Led_DoubleFeed_close: + m_ledstate = m_ledstate & 0xbf; + break; + case HGLed::Led_DoubleFeed_open: + m_ledstate = m_ledstate | 0x40; + break; + case HGLed::Led_Enter_close: + m_ledstate = m_ledstate & 0xf7; + break; + case HGLed::Led_Enter_open: + m_ledstate = m_ledstate | 0x8; + break; + case HGLed::Led_Handle_close: + m_ledstate = m_ledstate & 0xdf; + break; + case HGLed::Led_Handle_open: + m_ledstate = m_ledstate | 0x20; + break; +#endif + default: + break; + } + i2c_start(); + i2c_write(0x6e); + i2c_write(m_ledstate); + i2c_stop(); +} diff --git a/ui/keymonitor.h b/ui/keymonitor.h new file mode 100644 index 0000000..b1f5f28 --- /dev/null +++ b/ui/keymonitor.h @@ -0,0 +1,71 @@ +#pragma once + +#include +#include + +class PinMonitor; +class Gpio; + +class KeyMonitor +{ +public: +#if VER_FAMILY == 200 + enum class HGKey + { + Key_Enter = 69, + Key_Cancle = 70, + Key_Count = 78, + Key_Handle = 77, + Key_DoubleFeed = 68, + Key_Left = 86, + Key_Menu = 85, + Key_Right = 76, + Key_Clear = 84 + }; +#else + enum class HGKey + { + Key_Enter = 70, + Key_Cancle = 69, + Key_Count = 78, + Key_Menu = 76, + Key_Right = 77, + Key_Clear = 68, + Key_Handle = 3331, + Key_DoubleFeed = 3332, + Key_Left = 3333 + }; +#endif + enum class HGLed + { + Led_Enter_open = 0, + Led_Enter_close, + Led_Count_open, + Led_Count_close, + Led_DoubleFeed_open, + Led_DoubleFeed_close, + Led_Handle_open, + Led_Handle_close, + Led_All_open, + Led_All_close + }; +public: + KeyMonitor(std::function keycall); + void setled(HGLed value); + std::uint8_t getledstate(); + ~KeyMonitor(); +private: + void init(); + void i2c_start(); + void i2c_write(unsigned char cmd); + unsigned char i2c_read(); + void i2c_stop(); + void write_cmd(unsigned short cmd); + unsigned char read_key(); +private: + std::shared_ptr m_keymonitor; + std::shared_ptr m_gpioi2c_SDA; + std::shared_ptr m_gpioi2c_SCL; + std::function m_keycall; + volatile std::uint8_t m_ledstate; +}; \ No newline at end of file diff --git a/ui/main.cpp b/ui/main.cpp index dfed43e..357b2a4 100644 --- a/ui/main.cpp +++ b/ui/main.cpp @@ -10,8 +10,11 @@ #include #include #include +#include #include "DisplayCenter.h" +#include "Lcd.h" +#include "dev_menu.h" #define BUF_LEN_FOR_PID 64 @@ -26,6 +29,10 @@ static void sigHandler(int sig) _exit(0); } +namespace test +{ + +}; int main() { @@ -42,26 +49,17 @@ int main() } int err = 0; - DisplayCenter monitor; - - monitor.PutMsg(DisType::Dis_Welcome, 0, ClearScreen::All); if(err == 0) { + ui_mgr *ui = new ui_mgr(); while(1) { - if(getchar() == 'e') - { - if(getchar() == 'x') - { - if(getchar() == 'i') - { - if(getchar() == 't') - break; - } - } - } + std::string cmd(utils::from_console()); + if(cmd == "exit") + break; } + ui->release(); } return 0; -} \ No newline at end of file +} diff --git a/xmake.lua b/xmake.lua index afd4578..3e90ace 100644 --- a/xmake.lua +++ b/xmake.lua @@ -60,8 +60,8 @@ add_packagedirs("sdk") add_defines("BUILD_AS_DEVICE") add_defines("VER_MAIN=2") add_defines("VER_FAMILY=200") -add_defines("VER_DATE=20240131") -add_defines("VER_BUILD=1") +add_defines("VER_DATE=20240202") +add_defines("VER_BUILD=58") target("conf") set_kind("phony")