diff --git a/.cproject b/.cproject
index 2853214..82f1551 100644
--- a/.cproject
+++ b/.cproject
@@ -120,40 +120,34 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -164,6 +158,7 @@
+
diff --git a/Drivers b/Drivers
index e71ddbc..078acc8 160000
--- a/Drivers
+++ b/Drivers
@@ -1 +1 @@
-Subproject commit e71ddbca4e7fc61b82b6b1f03f66b7cfbffb0495
+Subproject commit 078acc813aab2a755e85f89f8d3b1f94174cfd1f
diff --git a/app_protocols/app_protocols.h b/app_protocols/app_protocols.h
index 5b150c5..310e0df 100644
--- a/app_protocols/app_protocols.h
+++ b/app_protocols/app_protocols.h
@@ -3,4 +3,5 @@
#include "appecode/errorcode.h"
//
#include "zscanprotocol/zscanprotocol.h"
-#include "hand_acid_val_protocol/hand_acid_val_protocol.h"
\ No newline at end of file
+#include "hand_acid_val_protocol/hand_acid_val_protocol.h"
+#include "ble_through/ble_proto.h"
\ No newline at end of file
diff --git a/stm32basic b/stm32basic
index 4daae70..774ea10 160000
--- a/stm32basic
+++ b/stm32basic
@@ -1 +1 @@
-Subproject commit 4daae70c942165377837d26b688bab9d6236d453
+Subproject commit 774ea10d163aa3a02c54544cab0074371e56d7d3
diff --git a/stm32halport b/stm32halport
index 6c550d6..36d0c5a 160000
--- a/stm32halport
+++ b/stm32halport
@@ -1 +1 @@
-Subproject commit 6c550d69902d048e8fdd782d11e3feba7120b740
+Subproject commit 36d0c5aed2f2645c4ec97f2900182cfb8f410d8e
diff --git a/uappbase/appcfg/appcfg.hpp b/uappbase/appcfg/appcfg.hpp
index 95a193a..b3b070b 100644
--- a/uappbase/appcfg/appcfg.hpp
+++ b/uappbase/appcfg/appcfg.hpp
@@ -1,4 +1,35 @@
#pragma once
#include "project_configs.h"
-#define MAX_USR_NAME_SIZE 5
\ No newline at end of file
+#define MAX_USR_NAME_SIZE 5
+
+#define MOTO_POWER_EN_IO PC2
+#define MOTO1_CSN_IO PB3
+#define MOTO2_CSN_IO PB4
+#define MOTO3_CSN_IO PB5
+#define MOTO4_CSN_IO PB6
+#define MOTO1_DRV_ENN_IO PD0
+#define MOTO2_DRV_ENN_IO PD1
+#define MOTO3_DRV_ENN_IO PD2
+#define MOTO4_DRV_ENN_IO PD3
+#define ID1_IO PE0
+#define ID2_IO PE1
+#define ID3_IO PD7
+#define ID4_IO PD9
+#define ID5_IO PD8
+#define IO_OUT1_IO PC0
+#define IO_OUT2_IO PC1
+
+#define MOTOR_SPI_INS hspi1
+/***********************************************************************************************************************
+ * MOTOR_CFG *
+ ***********************************************************************************************************************/
+#define MOTOR_SHAFT false
+#define STEPMOTOR_IHOLD 10
+#define STEPMOTOR_IRUN 20
+#define STEPMOTOR_IHOLDDELAY 100
+#define MOTOR_VSTART 200 // 启动速度
+#define MOTOR_A1 100 // 阶段1_加速度
+#define MOTOR_AMAX 300 // 阶段2_加速度
+#define MOTOR_V1 500 // 阶段2_开始速度
+#define MOTOR_TZEROWAIT 100 // 速度零点点切换时间
diff --git a/uappbase/appdep.hpp b/uappbase/appdep.hpp
index 0f54cdd..e3a38b5 100644
--- a/uappbase/appdep.hpp
+++ b/uappbase/appdep.hpp
@@ -1,6 +1,6 @@
#pragma once
#include "stm32basic/stm32basic.hpp"
#include "stm32halport/stm32halport.hpp"
-#include "stm32components/sysmgr/sys_mgr.hpp"
-#include "ucomponents/ucomponents.hpp"
+#include "stm32components/stm32components.hpp"
+//
#include "main.h"
\ No newline at end of file
diff --git a/uappbase/base.hpp b/uappbase/base.hpp
index e2be790..60cc35c 100644
--- a/uappbase/base.hpp
+++ b/uappbase/base.hpp
@@ -5,4 +5,5 @@
//
#include "service/app_core.hpp"
#include "service/app_event_bus.hpp"
-#include "service/gstate_mgr.hpp"
\ No newline at end of file
+#include "service/gstate_mgr.hpp"
+#include "service/config_service.hpp"
\ No newline at end of file
diff --git a/uappbase/service/app_event_bus.hpp b/uappbase/service/app_event_bus.hpp
index 911b617..0ca1340 100644
--- a/uappbase/service/app_event_bus.hpp
+++ b/uappbase/service/app_event_bus.hpp
@@ -1,6 +1,7 @@
#pragma once
-#include "uappbase/appdep.hpp"
+#include "uappbase/appcfg/appcfg.hpp"
#include "uappbase/bean/bean.hpp"
+#include "../appdep.hpp"
//
namespace iflytop {
diff --git a/uappbase/service/config_index.cpp b/uappbase/service/config_index.cpp
new file mode 100644
index 0000000..8f4125a
--- /dev/null
+++ b/uappbase/service/config_index.cpp
@@ -0,0 +1,133 @@
+#include "config_index.hpp"
+namespace iflytop {
+
+#define CFG_ITERM(index, type, initval) \
+ { index, #index, type, initval }
+
+static cfg_iterm_info_t cfg_iterm_infos[] = {
+
+ /***********************************************************************************************************************
+ * 用户管理 *
+ ***********************************************************************************************************************/
+ CFG_ITERM(kusr_name0, kcfgt_str, "管理员"), //
+ CFG_ITERM(kusr_enable0, kcfgt_bool, "true"), // 1:使能,0失能
+ CFG_ITERM(kusr_passwd0, kcfgt_str, "888888"), //
+
+ CFG_ITERM(kusr_name1, kcfgt_str, "用户1"), //
+ CFG_ITERM(kusr_enable1, kcfgt_bool, "true"), //
+ CFG_ITERM(kusr_passwd1, kcfgt_str, "888888"), //
+
+ CFG_ITERM(kusr_name2, kcfgt_str, "用户2"), //
+ CFG_ITERM(kusr_enable2, kcfgt_bool, "true"), //
+ CFG_ITERM(kusr_passwd2, kcfgt_str, "888888"), //
+
+ CFG_ITERM(kusr_name3, kcfgt_str, "用户3"), //
+ CFG_ITERM(kusr_enable3, kcfgt_bool, "true"), //
+ CFG_ITERM(kusr_passwd3, kcfgt_str, "888888"), //
+
+ CFG_ITERM(kusr_name4, kcfgt_str, "用户4"), //
+ CFG_ITERM(kusr_enable4, kcfgt_bool, "true"), //
+ CFG_ITERM(kusr_passwd4, kcfgt_str, "888888"), //
+
+ CFG_ITERM(kusr_name5, kcfgt_str, "用户5"), //
+ CFG_ITERM(kusr_enable5, kcfgt_bool, "true"), //
+ CFG_ITERM(kusr_passwd5, kcfgt_str, "888888"), //
+
+ /***********************************************************************************************************************
+ * 酸液预设名称 *
+ ***********************************************************************************************************************/
+ CFG_ITERM(kcfg_acidName1, kcfgt_str, "预设酸1"), //
+ CFG_ITERM(kcfg_acidName2, kcfgt_str, "预设酸2"), //
+ CFG_ITERM(kcfg_acidName3, kcfgt_str, "预设酸3"), //
+ CFG_ITERM(kcfg_acidName4, kcfgt_str, "预设酸4"), //
+ CFG_ITERM(kcfg_acidName5, kcfgt_str, "预设酸5"), //
+ CFG_ITERM(kcfg_acidName6, kcfgt_str, "预设酸6"), //
+ CFG_ITERM(kcfg_acidName7, kcfgt_str, "预设酸7"), //
+ CFG_ITERM(kcfg_acidName8, kcfgt_str, "预设酸8"), //
+ CFG_ITERM(kcfg_acidName9, kcfgt_str, "预设酸9"), //
+ CFG_ITERM(kcfg_acidName10, kcfgt_str, "预设酸10"), //
+ CFG_ITERM(kcfg_acidName11, kcfgt_str, "预设酸11"), //
+ CFG_ITERM(kcfg_acidName12, kcfgt_str, "预设酸12"), //
+ CFG_ITERM(kcfg_acidName13, kcfgt_str, "预设酸13"), //
+ CFG_ITERM(kcfg_acidName14, kcfgt_str, "预设酸14"), //
+ CFG_ITERM(kcfg_acidName15, kcfgt_str, "预设酸15"), //
+
+ /***********************************************************************************************************************
+ * 酸液通道选择名称 *
+ ***********************************************************************************************************************/
+ CFG_ITERM(kcfg_acidChooseName0, kcfgt_str, "未设置"), //
+ CFG_ITERM(kcfg_acidChooseName1, kcfgt_str, "未设置"), //
+ CFG_ITERM(kcfg_acidChooseName2, kcfgt_str, "未设置"), //
+ CFG_ITERM(kcfg_acidChooseName3, kcfgt_str, "未设置"), //
+
+ /***********************************************************************************************************************
+ * 酸液通道每次分配的数值 *
+ ***********************************************************************************************************************/
+ CFG_ITERM(kcfg_acideval0, kcfgt_float, "10.0"), //
+ CFG_ITERM(kcfg_acideval1, kcfgt_float, "10.0"), //
+ CFG_ITERM(kcfg_acideval2, kcfgt_float, "10.0"), //
+ CFG_ITERM(kcfg_acideval3, kcfgt_float, "10.0"), //
+
+ /***********************************************************************************************************************
+ * 电机默认配置 *
+ ***********************************************************************************************************************/
+ CFG_ITERM(kcfg_1ulTrunsM0, kcfgt_int32, "1000"), //
+ CFG_ITERM(kcfg_1ulTrunsM1, kcfgt_int32, "1000"), //
+ CFG_ITERM(kcfg_1ulTrunsM2, kcfgt_int32, "1000"), //
+ CFG_ITERM(kcfg_1ulTrunsM3, kcfgt_int32, "1000"), //
+
+ /***********************************************************************************************************************
+ * 其他配置 *
+ ***********************************************************************************************************************/
+ CFG_ITERM(kcfg_lockAcidName, kcfgt_bool, "false"), //
+ CFG_ITERM(kcfg_echDitrUpLi, kcfgt_int32, "40"), // 每次分配上限设定值 each distri up-limit
+ CFG_ITERM(kcfg_distrInterval, kcfgt_int32, "50"), // 每次分配间隔时间
+ CFG_ITERM(kcfg_pumpDefVel, kcfgt_int32, "800"), //
+
+ /***********************************************************************************************************************
+ * 回流参数配置 *
+ ***********************************************************************************************************************/
+
+ CFG_ITERM(kcfg_pipeLengthML, kcfgt_float, "1000"), //
+
+};
+
+const char *cfgName(int32_t index) {
+ for (int i = 0; i < CFG_MAX_INDEX; i++) {
+ if (cfg_iterm_infos[i].index == index) {
+ return cfg_iterm_infos[i].itermName;
+ }
+ }
+ ZASSERT(0);
+ return nullptr;
+}
+cfg_iterm_type_t cfgType(int32_t index) {
+ for (int i = 0; i < CFG_MAX_INDEX; i++) {
+ if (cfg_iterm_infos[i].index == index) {
+ return cfg_iterm_infos[i].type;
+ }
+ }
+ return kcfgt_float;
+}
+const char *cfgInitVal(int32_t index) {
+ for (int i = 0; i < CFG_MAX_INDEX; i++) {
+ if (cfg_iterm_infos[i].index == index) {
+ return cfg_iterm_infos[i].initval;
+ }
+ }
+ ZASSERT(0);
+
+ return nullptr;
+}
+
+cfg_iterm_info_t *cfgInfo(int32_t index) {
+ for (int i = 0; i < CFG_MAX_INDEX; i++) {
+ if (cfg_iterm_infos[i].index == index) {
+ return &cfg_iterm_infos[i];
+ }
+ }
+ ZASSERT(0);
+ return nullptr;
+}
+
+} // namespace iflytop
\ No newline at end of file
diff --git a/uappbase/service/config_index.hpp b/uappbase/service/config_index.hpp
new file mode 100644
index 0000000..f5eb5b2
--- /dev/null
+++ b/uappbase/service/config_index.hpp
@@ -0,0 +1,114 @@
+#pragma once
+#include "uappbase/appcfg/appcfg.hpp"
+#include "uappbase/bean/bean.hpp"
+#include "../appdep.hpp"
+
+namespace iflytop {
+typedef enum {
+ kcfgt_float,
+ kcfgt_int32,
+ kcfgt_str,
+ kcfgt_bool,
+} cfg_iterm_type_t;
+
+typedef struct {
+ int32_t index;
+ const char *itermName;
+ cfg_iterm_type_t type;
+ const char *initval;
+} cfg_iterm_info_t;
+
+typedef enum {
+
+ /***********************************************************************************************************************
+ * 用户配置 *
+ ***********************************************************************************************************************/
+ kusr_name0, // 用户0名字(默认为管理员)
+ kusr_enable0, // 用户0是否使能
+ kusr_passwd0, // 用户0密码
+ kusr_name1, // 用户1名字
+ kusr_enable1, // 用户1是否使能
+ kusr_passwd1, // 用户1密码
+ kusr_name2, // 用户2名字
+ kusr_enable2, // 用户2是否使能
+ kusr_passwd2, // 用户2密码
+ kusr_name3, // 用户3名字
+ kusr_enable3, // 用户3是否使能
+ kusr_passwd3, // 用户3密码
+ kusr_name4, // 用户4名字
+ kusr_enable4, // 用户4是否使能
+ kusr_passwd4, // 用户4密码
+ kusr_name5, // 用户5名字
+ kusr_enable5, // 用户5是否使能
+ kusr_passwd5, // 用户5密码
+
+ /***********************************************************************************************************************
+ * 酸液预设名称 *
+ ***********************************************************************************************************************/
+ kcfg_acidName1, // 酸液中预设名字
+ kcfg_acidName2, // 酸液中预设名字
+ kcfg_acidName3, // 酸液中预设名字
+ kcfg_acidName4, // 酸液中预设名字
+ kcfg_acidName5, // 酸液中预设名字
+ kcfg_acidName6, // 酸液中预设名字
+ kcfg_acidName7, // 酸液中预设名字
+ kcfg_acidName8, // 酸液中预设名字
+ kcfg_acidName9, // 酸液中预设名字
+ kcfg_acidName10, // 酸液中预设名字
+ kcfg_acidName11, // 酸液中预设名字
+ kcfg_acidName12, // 酸液中预设名字
+ kcfg_acidName13, // 酸液中预设名字
+ kcfg_acidName14, // 酸液中预设名字
+ kcfg_acidName15, // 酸液中预设名字
+
+ /***********************************************************************************************************************
+ * 酸液通道选择名称 *
+ ***********************************************************************************************************************/
+ kcfg_acidChooseName0, // 酸液0 选择的名字
+ kcfg_acidChooseName1, // 酸液1 选择的名字
+ kcfg_acidChooseName2, // 酸液2 选择的名字
+ kcfg_acidChooseName3, // 酸液3 选择的名字
+
+ /***********************************************************************************************************************
+ * 酸液通道每次分配的数值 *
+ ***********************************************************************************************************************/
+ kcfg_acideval0, // 酸液0 distribution
+ kcfg_acideval1, // 酸液1
+ kcfg_acideval2, // 酸液2
+ kcfg_acideval3, // 酸液3
+
+ /***********************************************************************************************************************
+ * 电机默认配置 *
+ ***********************************************************************************************************************/
+
+ kcfg_1ulTrunsM0, // 电机0 1ul 转数
+ kcfg_1ulTrunsM1, // 电机0 1ul 转数
+ kcfg_1ulTrunsM2, // 电机0 1ul 转数
+ kcfg_1ulTrunsM3, // 电机0 1ul 转数
+
+ /***********************************************************************************************************************
+ * 其他配置 *
+ ***********************************************************************************************************************/
+ kcfg_lockAcidName, // 锁定酸液名称
+ kcfg_echDitrUpLi, // 每次分配上限设定值 each distri up-limit
+ kcfg_pumpDefVel, // 泵机默认速度RPM
+ kcfg_distrInterval, // 每次分配间隔时间
+
+ /***********************************************************************************************************************
+ * 回流参数配置 *
+ ***********************************************************************************************************************/
+ kcfg_pipeLengthML, // 酸液管路长度
+
+ kcfg_max,
+
+} config_index_t;
+
+#define CFG_MAX_INDEX 50
+
+const char *cfgName(int32_t index);
+cfg_iterm_type_t cfgType(int32_t index);
+const char *cfgInitVal(int32_t index);
+
+cfg_iterm_info_t *cfgInfo(int32_t index);
+
+} // namespace iflytop
\ No newline at end of file
diff --git a/uappbase/service/config_service.cpp b/uappbase/service/config_service.cpp
new file mode 100644
index 0000000..c4f1776
--- /dev/null
+++ b/uappbase/service/config_service.cpp
@@ -0,0 +1,196 @@
+#include "config_service.hpp"
+//
+
+#define CFG_HEADER 0x12345678
+/**
+ * @brief CFG内存使用
+ *
+ * 4byte begin
+ *
+ * cfg
+ * cfg
+ * cfg
+ * cfg
+ *
+ * 4byte checksum
+ * 4byte end
+ *
+ */
+
+using namespace iflytop;
+#define TAG "ConfigService"
+
+#pragma pack(1)
+
+typedef struct {
+ union {
+ uint8_t str[CONTENT_MAX_LEN]; // 必须4字节对齐
+ uint32_t u32s[CONTENT_MAX_LEN / 4];
+ };
+} cfg_content_t;
+
+typedef struct {
+ int32_t begin;
+ int32_t checksum;
+ cfg_content_t cfg[CFG_MAX_INDEX];
+} config_data_t;
+
+#pragma pack()
+#define TO_EEPROM_ADD(index) (CONFIG_EEPROM_ADD + 4 + 4 + sizeof(cfg_content_t) * index)
+#define SET_CFG_INT(index, value) cfgcache.cfg[index].int32 = value
+#define SET_CFG_STR(index, value) memcpy(cfgcache.cfg[index].str, value, strlen(value))
+#define CHECKSUM() checksum((uint8_t *)&(cfgcache.cfg[0].str[0]), sizeof(cfgcache) - 8)
+
+static config_data_t cfgcache;
+static M24M02_I2C_EEPROM *eeprom;
+
+static int32_t checksum(uint8_t *data, int32_t n) {
+ int32_t sum = 0;
+ for (int i = 0; i < n; i++) {
+ sum += data[i];
+ }
+ return sum;
+}
+
+bool ConfigService::initialize(M24M02_I2C_EEPROM *_eeprom) {
+ mutex.init();
+
+ eeprom = _eeprom;
+ static_assert(kcfg_max == CFG_MAX_INDEX, "");
+ if (!checkcfg()) {
+ ZLOGI(TAG, "cfg check fail,init cfg");
+
+ cfgcache.begin = CFG_HEADER;
+
+ for (int i = 0; i < kcfg_max; i++) {
+ cfg_iterm_info_t *info = cfgInfo((config_index_t)i);
+ _setcfg(i, info->initval);
+ }
+
+ cfgcache.checksum = CHECKSUM();
+ eeprom->write(CONFIG_EEPROM_ADD, (uint8_t *)&cfgcache, sizeof(cfgcache));
+ flashall();
+ }
+ bool suc = checkcfg();
+ dumpcfgs();
+ ZLOGI(TAG, "cfg init %s", suc ? "ok" : "fail");
+
+ return suc;
+}
+
+void ConfigService::setcfgAndFlush(config_index_t index, const char *val) {
+ zlock_guard lg(mutex);
+ _setcfgAndFlush(index, val);
+}
+void ConfigService::setcfgAndFlush(config_index_t index, int32_t val) {
+ zlock_guard lg(mutex);
+ char buf[CONTENT_MAX_LEN];
+ snprintf(buf, CONTENT_MAX_LEN, "%d", val);
+
+ _setcfgAndFlush(index, buf);
+}
+void ConfigService::setcfgAndFlush(config_index_t index, float val) {
+ zlock_guard lg(mutex);
+ char buf[CONTENT_MAX_LEN];
+ snprintf(buf, CONTENT_MAX_LEN, "%.2f", val);
+
+ _setcfgAndFlush(index, buf);
+}
+void ConfigService::setcfgAndFlush(config_index_t index, bool val) {
+ zlock_guard lg(mutex);
+ _setcfgAndFlush(index, val ? "true" : "false");
+}
+
+void ConfigService::setcfg(config_index_t index, const char *val) {
+ zlock_guard lg(mutex);
+ _setcfg(index, val);
+}
+void ConfigService::setcfg(config_index_t index, int32_t val) {
+ zlock_guard lg(mutex);
+ char buf[CONTENT_MAX_LEN];
+ snprintf(buf, CONTENT_MAX_LEN, "%d", val);
+
+ _setcfg(index, buf);
+}
+void ConfigService::setcfg(config_index_t index, float val) {
+ zlock_guard lg(mutex);
+ char buf[CONTENT_MAX_LEN];
+ snprintf(buf, CONTENT_MAX_LEN, "%.2f", val);
+
+ _setcfg(index, buf);
+}
+void ConfigService::setcfg(config_index_t index, bool val) {
+ zlock_guard lg(mutex);
+ _setcfg(index, val ? "true" : "false");
+}
+
+const char *ConfigService::getStr(config_index_t index, CfgItermCache *cache) {
+ zlock_guard lg(mutex);
+ return _getcfg(index, cache);
+}
+int32_t ConfigService::getInt(config_index_t index) {
+ zlock_guard lg(mutex);
+ return atoi(_getcfg(index, nullptr));
+}
+float ConfigService::getFloat(config_index_t index) {
+ zlock_guard lg(mutex);
+ return atof(_getcfg(index, nullptr));
+}
+bool ConfigService::getBool(config_index_t index) {
+ zlock_guard lg(mutex);
+ return strcmp(_getcfg(index, nullptr), "true") == 0;
+}
+
+/***********************************************************************************************************************
+ * BASIC *
+ ***********************************************************************************************************************/
+void ConfigService::dumpcfgs() {
+ for (int i = 0; i < kcfg_max; i++) {
+ ZLOGI(TAG, "cfg %s:%s", cfgName((config_index_t)i), _getcfg((config_index_t)i, nullptr));
+ }
+}
+
+void ConfigService::_setcfg(int32_t index, const char *value) {
+ ZLOGI(TAG, "setcfg %s:%s", cfgName(index), value);
+
+ memset(cfgcache.cfg[index].str, 0, 32);
+ strncpy((char *)cfgcache.cfg[index].str, value, 31);
+ cfgcache.checksum = CHECKSUM();
+ return;
+}
+void ConfigService::_setcfgAndFlush(int32_t index, const char *value) {
+ _setcfg(index, value);
+ flashIndex(index);
+ return;
+}
+const char *ConfigService::_getcfg(config_index_t index, CfgItermCache *cache) {
+ static CfgItermCache _cache;
+ if (cache == nullptr) {
+ cache = &_cache;
+ }
+ memset(cache->buf, 0, CONTENT_MAX_LEN);
+ strncpy(cache->buf, (const char *)cfgcache.cfg[index].str, CONTENT_MAX_LEN - 1);
+ return cache->buf;
+}
+
+bool ConfigService::checkcfg() {
+ eeprom->read(CONFIG_EEPROM_ADD, (uint8_t *)&cfgcache, sizeof(cfgcache));
+
+ int32_t checksumval = CHECKSUM();
+
+ if (cfgcache.begin != CFG_HEADER || cfgcache.checksum != checksumval) {
+ ZLOGI(TAG, "cfg check fail,b:0x%08x,c:0x%08x!=0x%08x", cfgcache.begin, cfgcache.checksum, checksumval);
+ return false;
+ }
+ return true;
+}
+bool ConfigService::flashIndex(int32_t index) {
+ // for (int i = 0; i < sizeof(cfg_content_t); i += 4) {
+ // uint32_t wdata = cfgcache.cfg[index].u32s[i / 4];
+ // eeprom->write32(TO_EEPROM_ADD(index) + i, wdata);
+ // }
+ eeprom->write(TO_EEPROM_ADD(index), (uint8_t *)&cfgcache.cfg[index], sizeof(cfg_content_t));
+ eeprom->write32(CONFIG_EEPROM_ADD + 4 * 1, (uint32_t)cfgcache.checksum);
+ return true;
+}
+bool ConfigService::flashall() { eeprom->write(CONFIG_EEPROM_ADD, (uint8_t *)&cfgcache, sizeof(cfgcache)); }
diff --git a/uappbase/service/config_service.hpp b/uappbase/service/config_service.hpp
new file mode 100644
index 0000000..504e9bc
--- /dev/null
+++ b/uappbase/service/config_service.hpp
@@ -0,0 +1,63 @@
+#pragma once
+#include "../appdep.hpp"
+#include "uappbase/appcfg/appcfg.hpp"
+#include "uappbase/bean/bean.hpp"
+#include "ucomponents/eeprom/m24m02_i2c_eeprom.hpp"
+#include "config_index.hpp"
+
+namespace iflytop {
+using namespace std;
+#define CS ConfigService::ins()
+
+#define CONFIG_EEPROM_ADD 0
+#define CONTENT_MAX_LEN 32
+
+struct CfgItermCache {
+ char buf[CONTENT_MAX_LEN];
+};
+
+class ConfigService {
+ private:
+ /* data */
+ zmutex mutex;
+
+ public:
+ static ConfigService* ins() {
+ static ConfigService instance;
+ return &instance;
+ }
+
+ bool initialize(M24M02_I2C_EEPROM* _eeprom);
+
+ void setcfgAndFlush(config_index_t index, const char* val);
+ void setcfgAndFlush(config_index_t index, int32_t val);
+ void setcfgAndFlush(config_index_t index, float val);
+ void setcfgAndFlush(config_index_t index, bool val);
+
+ void setcfg(config_index_t index, const char* val);
+ void setcfg(config_index_t index, int32_t val);
+ void setcfg(config_index_t index, float val);
+ void setcfg(config_index_t index, bool val);
+
+ const char* getStr(config_index_t index, CfgItermCache* cache);
+ int32_t getInt(config_index_t index);
+ float getFloat(config_index_t index);
+ bool getBool(config_index_t index);
+
+ private:
+ void _setcfg(int32_t index, const char* value);
+ void _setcfgAndFlush(int32_t index, const char* value);
+ const char* _getcfg(config_index_t index, CfgItermCache* cache);
+
+ bool checkcfg();
+ bool flashIndex(int32_t index);
+ bool flashall();
+ void dumpcfgs();
+};
+
+#define getCfgStr(index) CS->getStr(index, &cfgcache)
+#define getCfgInt(index) CS->getInt(index)
+#define getCfgFloat(index) CS->getFloat(index)
+#define getCfgBool(index) CS->getBool(index)
+
+} // namespace iflytop
\ No newline at end of file
diff --git a/ucomponents/eeprom/m24m02_i2c_eeprom.cpp b/ucomponents/eeprom/m24m02_i2c_eeprom.cpp
new file mode 100644
index 0000000..6c00811
--- /dev/null
+++ b/ucomponents/eeprom/m24m02_i2c_eeprom.cpp
@@ -0,0 +1,139 @@
+#include "m24m02_i2c_eeprom.hpp"
+
+#include
+
+//
+#include "app_protocols/app_protocols.h"
+
+using namespace iflytop;
+#ifdef HAL_I2C_MODULE_ENABLED
+
+// #define DATA_ADD 0x53
+// #define CONFIG_ADD 0x57
+
+#define DATA_ADD 0x50
+
+#define TAG "M24LRXXE"
+
+static int32_t halstatustoerr(HAL_StatusTypeDef status) {
+ if (status == HAL_OK) {
+ return 0;
+ } else if (status == HAL_BUSY) {
+ return kdevice_is_busy;
+ } else if (status == HAL_TIMEOUT) {
+ return kovertime;
+ } else {
+ return kfail;
+ }
+}
+
+void M24M02_I2C_EEPROM::initialize(I2C_HandleTypeDef* i2c_handle) {
+ m_i2c_handle = i2c_handle;
+ m_lock.init();
+}
+
+int32_t M24M02_I2C_EEPROM::write(int32_t add, uint8_t* val, int32_t len) {
+ zlock_guard lg(m_lock);
+
+ ZASSERT(len % 4 == 0);
+ ZASSERT(add % 4 == 0);
+ int32_t ecode = 0;
+ for (int32_t i = 0; i < len; i += 4) {
+ ecode = write32(add + i, *(uint32_t*)&val[i]);
+ if (ecode != 0) return ecode;
+ }
+ return ecode;
+}
+int32_t M24M02_I2C_EEPROM::read(int32_t add, uint8_t* val, int32_t len) {
+ zlock_guard lg(m_lock);
+
+ ZASSERT(len % 4 == 0);
+ ZASSERT(add % 4 == 0);
+ int32_t ecode = 0;
+ for (int32_t i = 0; i < len; i += 4) {
+ ecode = read32(add + i, (uint32_t*)&val[i]);
+ if (ecode != 0) return ecode;
+ }
+ return ecode;
+}
+
+int32_t M24M02_I2C_EEPROM::readCfgReg(int32_t add, uint32_t* val) {
+ // HAL_StatusTypeDef status = HAL_I2C_Mem_Read(m_i2c_handle, CONFIG_ADD << 1, add, I2C_MEMADD_SIZE_16BIT, (uint8_t*)val, 4, 10);
+ // return halstatustoerr(status);
+ return 0;
+}
+uint32_t M24M02_I2C_EEPROM::readCfgReg(int32_t add) {
+ uint32_t val = 0;
+ int32_t ret = readCfgReg(add, &val);
+ if (ret != 0) {
+ return 0;
+ }
+ return val;
+}
+
+bool M24M02_I2C_EEPROM::isOnline() {
+ uint32_t val = 0;
+ int32_t ret = read32(0, &val);
+ if (ret != 0) {
+ return false;
+ }
+ return true;
+}
+
+int32_t M24M02_I2C_EEPROM::write32(uint16_t add, uint32_t val) {
+ zlock_guard lg(m_lock);
+
+ uint16_t deviceadd = DATA_ADD + (add >> 16);
+ uint16_t regadd = add & 0xffff;
+
+ HAL_StatusTypeDef status = HAL_I2C_Mem_Write(m_i2c_handle, deviceadd << 1, regadd, I2C_MEMADD_SIZE_16BIT, (uint8_t*)&val, 4, 10);
+ osDelay(12);
+ return halstatustoerr(status);
+}
+int32_t M24M02_I2C_EEPROM::read32(uint16_t add, uint32_t* val) {
+ zlock_guard lg(m_lock);
+
+ uint16_t deviceadd = DATA_ADD + (add >> 16);
+ uint16_t regadd = add & 0xffff;
+
+ HAL_StatusTypeDef status = HAL_I2C_Mem_Read(m_i2c_handle, deviceadd << 1, regadd, I2C_MEMADD_SIZE_16BIT, (uint8_t*)val, 4, 10);
+ return halstatustoerr(status);
+}
+
+void M24M02_I2C_EEPROM::scan_i2c() {
+ memset(i2c_ping_state, 0, sizeof(i2c_ping_state));
+ for (uint16_t i = 0; i < 255; i++) {
+ HAL_StatusTypeDef status = HAL_I2C_IsDeviceReady(m_i2c_handle, i << 1, 1, 1);
+ if (status == HAL_OK) {
+ i2c_ping_state[i] = true;
+ ZLOGI(TAG, "i2c device found:0x%02x", i);
+ } else {
+ i2c_ping_state[i] = false;
+ }
+ }
+}
+
+void M24M02_I2C_EEPROM::write_test_data_rom() {
+ uint32_t data = 0;
+ uint32_t readdata = 0;
+ //
+
+ for (uint32_t i = 0; i < (0x40000);) {
+ int32_t wlen = 4;
+ write(i, (uint8_t*)&data, wlen);
+ read(i, (uint8_t*)&readdata, wlen);
+
+ ZLOGI(TAG, "off:%x w:%d,r:%d", i, data, readdata);
+ data += 1;
+ i += 4;
+ }
+}
+
+#if 0
+int32_t M24M02_I2C_EEPROM::read_reg(int32_t add, uint32_t* regval) {
+ HAL_StatusTypeDef status = HAL_I2C_Mem_Read(m_i2c_handle, CONFIG_ADD << 1, add, I2C_MEMADD_SIZE_16BIT, (uint8_t*)regval, 4, 10);
+ return halstatustoerr(status);
+}
+#endif
+
+#endif
\ No newline at end of file
diff --git a/ucomponents/eeprom/m24m02_i2c_eeprom.hpp b/ucomponents/eeprom/m24m02_i2c_eeprom.hpp
new file mode 100644
index 0000000..f4d06a2
--- /dev/null
+++ b/ucomponents/eeprom/m24m02_i2c_eeprom.hpp
@@ -0,0 +1,33 @@
+#pragma once
+
+#include "cmsis_os.h"
+#include "stm32basic/stm32basic.hpp"
+
+namespace iflytop {
+using namespace std;
+// ref::https://atta.szlcsc.com/upload/public/pdf/source/20170925/C115042_1506321353695990106.pdf
+// M24M02-DR
+class M24M02_I2C_EEPROM {
+ I2C_HandleTypeDef* m_i2c_handle;
+ bool i2c_ping_state[255] = {0};
+ zmutex m_lock;
+
+ public:
+ M24M02_I2C_EEPROM(){};
+ ~M24M02_I2C_EEPROM(){};
+
+ void initialize(I2C_HandleTypeDef* i2c_handle);
+
+ virtual int32_t write(int32_t add, uint8_t* val, int32_t len); // 5 ms
+ virtual int32_t read(int32_t add, uint8_t* val, int32_t len);
+ virtual bool isOnline();
+
+ int32_t readCfgReg(int32_t add, uint32_t* val);
+ uint32_t readCfgReg(int32_t add);
+ void write_test_data_rom();
+ void scan_i2c();
+
+ int32_t write32(uint16_t add, uint32_t val);
+ int32_t read32(uint16_t add, uint32_t* val);
+};
+} // namespace iflytop
diff --git a/ucomponents/ucomponents.hpp b/ucomponents/ucomponents.hpp
index 7b9637e..17a3880 100644
--- a/ucomponents/ucomponents.hpp
+++ b/ucomponents/ucomponents.hpp
@@ -1 +1,2 @@
-#pragma once
\ No newline at end of file
+#pragma once
+#include "eeprom/m24m02_i2c_eeprom.hpp"
\ No newline at end of file
diff --git a/usrc/apphal/apphal.cpp b/usrc/apphal/apphal.cpp
index 55a887d..23832b5 100644
--- a/usrc/apphal/apphal.cpp
+++ b/usrc/apphal/apphal.cpp
@@ -48,7 +48,7 @@ void AppHal::MX_TIM7_Init(void) {
}
#define EARLY_ASSERT(exptr) \
- if (!(exptr)) { \
+ if (!(exptr)) { \
while (true) { \
} \
}
@@ -60,7 +60,7 @@ void AppHal::DEBUG_UART_INIT(Pin_t tx, Pin_t rx, int32_t baudrate) {
EARLY_ASSERT(PA10 == rx);
/***********************************************************************************************************************
- * IO鍒濆鍖 *
+ * IO鍒濆?嬪寲 *
***********************************************************************************************************************/
__HAL_RCC_USART1_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
@@ -86,7 +86,7 @@ void AppHal::DEBUG_UART_INIT(Pin_t tx, Pin_t rx, int32_t baudrate) {
}
/***********************************************************************************************************************
- * DMA鍒濆鍖 *
+ * DMA鍒濆?嬪寲 *
***********************************************************************************************************************/
HAL_NVIC_SetPriority(DMA2_Stream2_IRQn, 5, 0);
HAL_NVIC_EnableIRQ(DMA2_Stream2_IRQn);
@@ -117,3 +117,212 @@ void AppHal::MX_IWDG_Init(void) {
Error_Handler();
}
}
+
+void AppHal::UART3_Init() {
+ GPIO_InitTypeDef GPIO_InitStruct = {0};
+
+ __HAL_RCC_USART3_CLK_ENABLE();
+ __HAL_RCC_GPIOB_CLK_ENABLE();
+ __HAL_RCC_DMA1_CLK_ENABLE();
+
+ huart3.Instance = USART3;
+ huart3.Init.BaudRate = 115200;
+ huart3.Init.WordLength = UART_WORDLENGTH_8B;
+ huart3.Init.StopBits = UART_STOPBITS_1;
+ huart3.Init.Parity = UART_PARITY_NONE;
+ huart3.Init.Mode = UART_MODE_TX_RX;
+ huart3.Init.HwFlowCtl = UART_HWCONTROL_NONE;
+ huart3.Init.OverSampling = UART_OVERSAMPLING_16;
+ if (HAL_UART_Init(&huart3) != HAL_OK) {
+ Error_Handler();
+ }
+
+ GPIO_InitStruct.Pin = GPIO_PIN_10 | GPIO_PIN_11;
+ GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
+ GPIO_InitStruct.Pull = GPIO_NOPULL;
+ GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
+ GPIO_InitStruct.Alternate = GPIO_AF7_USART3;
+ HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
+
+ hdma1_stream1.Instance = DMA1_Stream1;
+ hdma1_stream1.Init.Channel = DMA_CHANNEL_4;
+ hdma1_stream1.Init.Direction = DMA_PERIPH_TO_MEMORY;
+ hdma1_stream1.Init.PeriphInc = DMA_PINC_DISABLE;
+ hdma1_stream1.Init.MemInc = DMA_MINC_ENABLE;
+ hdma1_stream1.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
+ hdma1_stream1.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
+ hdma1_stream1.Init.Mode = DMA_NORMAL;
+ hdma1_stream1.Init.Priority = DMA_PRIORITY_LOW;
+ hdma1_stream1.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
+ if (HAL_DMA_Init(&hdma1_stream1) != HAL_OK) {
+ Error_Handler();
+ }
+
+ __HAL_LINKDMA(&huart3, hdmarx, hdma1_stream1);
+
+ hdma1_stream3.Instance = DMA1_Stream3;
+ hdma1_stream3.Init.Channel = DMA_CHANNEL_4;
+ hdma1_stream3.Init.Direction = DMA_MEMORY_TO_PERIPH;
+ hdma1_stream3.Init.PeriphInc = DMA_PINC_DISABLE;
+ hdma1_stream3.Init.MemInc = DMA_MINC_ENABLE;
+ hdma1_stream3.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
+ hdma1_stream3.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
+ hdma1_stream3.Init.Mode = DMA_NORMAL;
+ hdma1_stream3.Init.Priority = DMA_PRIORITY_LOW;
+ hdma1_stream3.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
+ if (HAL_DMA_Init(&hdma1_stream3) != HAL_OK) {
+ Error_Handler();
+ }
+
+ __HAL_LINKDMA(&huart3, hdmatx, hdma1_stream3);
+
+ HAL_NVIC_SetPriority(DMA1_Stream1_IRQn, 5, 0);
+ HAL_NVIC_EnableIRQ(DMA1_Stream1_IRQn);
+
+ HAL_NVIC_SetPriority(DMA1_Stream3_IRQn, 5, 0);
+ HAL_NVIC_EnableIRQ(DMA1_Stream3_IRQn);
+
+ HAL_NVIC_SetPriority(USART3_IRQn, 5, 0);
+ HAL_NVIC_EnableIRQ(USART3_IRQn);
+}
+
+/**
+ * @brief
+ */
+void AppHal::UART4_Init() {
+ GPIO_InitTypeDef GPIO_InitStruct = {0};
+
+ __HAL_RCC_UART4_CLK_ENABLE();
+ __HAL_RCC_GPIOC_CLK_ENABLE();
+
+ huart4.Instance = UART4;
+ huart4.Init.BaudRate = 256000;
+ huart4.Init.WordLength = UART_WORDLENGTH_8B;
+ huart4.Init.StopBits = UART_STOPBITS_1;
+ huart4.Init.Parity = UART_PARITY_NONE;
+ huart4.Init.Mode = UART_MODE_TX_RX;
+ huart4.Init.HwFlowCtl = UART_HWCONTROL_NONE;
+ huart4.Init.OverSampling = UART_OVERSAMPLING_16;
+ if (HAL_UART_Init(&huart4) != HAL_OK) {
+ Error_Handler();
+ }
+
+ /**UART4 GPIO Configuration
+ PC10 ------> UART4_TX
+ PC11 ------> UART4_RX
+ */
+ GPIO_InitStruct.Pin = GPIO_PIN_10 | GPIO_PIN_11;
+ GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
+ GPIO_InitStruct.Pull = GPIO_PULLDOWN;
+ GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
+ GPIO_InitStruct.Alternate = GPIO_AF8_UART4;
+ HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
+
+ /* UART4 interrupt Init */
+ HAL_NVIC_SetPriority(UART4_IRQn, 5, 0);
+ HAL_NVIC_EnableIRQ(UART4_IRQn);
+
+ /***********************************************************************************************************************
+ * DMA_INIT *
+ ***********************************************************************************************************************/
+
+ /* UART4 DMA Init */
+ /* UART4_RX Init */
+ hdma1_stream2.Instance = DMA1_Stream2;
+ hdma1_stream2.Init.Channel = DMA_CHANNEL_4;
+ hdma1_stream2.Init.Direction = DMA_PERIPH_TO_MEMORY;
+ hdma1_stream2.Init.PeriphInc = DMA_PINC_DISABLE;
+ hdma1_stream2.Init.MemInc = DMA_MINC_ENABLE;
+ hdma1_stream2.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
+ hdma1_stream2.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
+ hdma1_stream2.Init.Mode = DMA_NORMAL;
+ hdma1_stream2.Init.Priority = DMA_PRIORITY_LOW;
+ hdma1_stream2.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
+ if (HAL_DMA_Init(&hdma1_stream2) != HAL_OK) {
+ Error_Handler();
+ }
+
+ __HAL_LINKDMA(&huart4, hdmarx, hdma1_stream2);
+
+ /* UART4_TX Init */
+ hdma1_stream4.Instance = DMA1_Stream4;
+ hdma1_stream4.Init.Channel = DMA_CHANNEL_4;
+ hdma1_stream4.Init.Direction = DMA_MEMORY_TO_PERIPH;
+ hdma1_stream4.Init.PeriphInc = DMA_PINC_DISABLE;
+ hdma1_stream4.Init.MemInc = DMA_MINC_ENABLE;
+ hdma1_stream4.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
+ hdma1_stream4.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
+ hdma1_stream4.Init.Mode = DMA_NORMAL;
+ hdma1_stream4.Init.Priority = DMA_PRIORITY_LOW;
+ hdma1_stream4.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
+ if (HAL_DMA_Init(&hdma1_stream4) != HAL_OK) {
+ Error_Handler();
+ }
+ __HAL_LINKDMA(&huart4, hdmatx, hdma1_stream4);
+}
+
+void AppHal::MX_I2C1_Init(void) {
+ __HAL_RCC_GPIOB_CLK_ENABLE();
+ __HAL_RCC_I2C1_CLK_ENABLE();
+
+ hi2c1.Instance = I2C1;
+ hi2c1.Init.ClockSpeed = 400000;
+ hi2c1.Init.DutyCycle = I2C_DUTYCYCLE_2;
+ hi2c1.Init.OwnAddress1 = 0;
+ hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
+ hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
+ hi2c1.Init.OwnAddress2 = 0;
+ hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
+ hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
+ if (HAL_I2C_Init(&hi2c1) != HAL_OK) {
+ Error_Handler();
+ }
+
+ GPIO_InitTypeDef GPIO_InitStruct = {0};
+
+ /**I2C1 GPIO Configuration
+ PB8 ------> I2C1_SCL
+ PB9 ------> I2C1_SDA
+ */
+ GPIO_InitStruct.Pin = GPIO_PIN_8 | GPIO_PIN_9;
+ GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
+ GPIO_InitStruct.Pull = GPIO_NOPULL;
+ GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
+ GPIO_InitStruct.Alternate = GPIO_AF4_I2C1;
+ HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
+}
+void AppHal::MX_HSPI1_Init() {
+ __HAL_RCC_SPI1_CLK_ENABLE();
+ __HAL_RCC_GPIOA_CLK_ENABLE();
+
+ // static_assert(MOTOR_SPI == SPI1);
+ // static_assert(&MOTOR_SPI_INS == &hspi1);
+
+ hspi1.Instance = SPI1;
+ hspi1.Init.Mode = SPI_MODE_MASTER;
+ hspi1.Init.Direction = SPI_DIRECTION_2LINES;
+ hspi1.Init.DataSize = SPI_DATASIZE_8BIT;
+ hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;
+ hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;
+ hspi1.Init.NSS = SPI_NSS_SOFT;
+ hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_32;
+ hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
+ hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
+ hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
+ hspi1.Init.CRCPolynomial = 10;
+ if (HAL_SPI_Init(&hspi1) != HAL_OK) {
+ Error_Handler();
+ }
+
+ // static_assert(MOTOR_SPI_SCK == PA5);
+ // static_assert(MOTOR_SPI_SDO == PA6);
+ // static_assert(MOTOR_SPI_SDI == PA7);
+
+ GPIO_InitTypeDef GPIO_InitStruct = {0};
+ GPIO_InitStruct.Pin = GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7;
+ GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
+ GPIO_InitStruct.Pull = GPIO_NOPULL;
+ GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
+ GPIO_InitStruct.Alternate = GPIO_AF5_SPI1;
+ HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
+}
diff --git a/usrc/apphal/apphal.hpp b/usrc/apphal/apphal.hpp
index af30068..8f4e552 100644
--- a/usrc/apphal/apphal.hpp
+++ b/usrc/apphal/apphal.hpp
@@ -9,6 +9,13 @@ class AppHal {
static void MX_TIM7_Init(void);
static void DEBUG_UART_INIT(Pin_t tx, Pin_t rx, int32_t baudrate);
static void MX_IWDG_Init(void);
+
+ static void UART3_Init();
+ static void UART4_Init();
+
+ static void MX_I2C1_Init(void) ;
+ static void MX_HSPI1_Init();
+
};
} // namespace iflytop
diff --git a/usrc/apphal/apphardware.cpp b/usrc/apphal/apphardware.cpp
new file mode 100644
index 0000000..34a00b9
--- /dev/null
+++ b/usrc/apphal/apphardware.cpp
@@ -0,0 +1,79 @@
+#include "apphardware.hpp"
+using namespace iflytop;
+
+#define TAG "AppHardware"
+
+void AppHardware::initialize() {
+ AppHal::UART3_Init();
+ AppHal::UART4_Init();
+ AppHal::MX_I2C1_Init();
+ AppHal::MX_HSPI1_Init();
+
+ tjcUart = &huart4;
+ remoteContolerUart = &huart3;
+
+ MOTO_POWER_EN.initAsOutput(MOTO_POWER_EN_IO, kxs_gpio_nopull, false, true);
+ MOTO1_CSN.initAsOutput(MOTO1_CSN_IO, kxs_gpio_nopull, false, true);
+ MOTO2_CSN.initAsOutput(MOTO2_CSN_IO, kxs_gpio_nopull, false, true);
+ MOTO3_CSN.initAsOutput(MOTO3_CSN_IO, kxs_gpio_nopull, false, true);
+ MOTO4_CSN.initAsOutput(MOTO4_CSN_IO, kxs_gpio_nopull, false, true);
+ MOTO1_DRV_ENN.initAsOutput(MOTO1_DRV_ENN_IO, kxs_gpio_nopull, false, true);
+ MOTO2_DRV_ENN.initAsOutput(MOTO2_DRV_ENN_IO, kxs_gpio_nopull, false, true);
+ MOTO3_DRV_ENN.initAsOutput(MOTO3_DRV_ENN_IO, kxs_gpio_nopull, false, true);
+ MOTO4_DRV_ENN.initAsOutput(MOTO4_DRV_ENN_IO, kxs_gpio_nopull, false, true);
+ ID1.initAsInput(ID1_IO, kxs_gpio_nopull, kxs_gpio_no_irq, false);
+ ID2.initAsInput(ID2_IO, kxs_gpio_nopull, kxs_gpio_no_irq, false);
+ ID3.initAsInput(ID3_IO, kxs_gpio_nopull, kxs_gpio_no_irq, false);
+ ID4.initAsInput(ID4_IO, kxs_gpio_nopull, kxs_gpio_no_irq, false);
+ ID5.initAsInput(ID5_IO, kxs_gpio_nopull, kxs_gpio_no_irq, false);
+ IO_OUT1.initAsOutput(IO_OUT1_IO, kxs_gpio_nopull, true, false);
+ IO_OUT2.initAsOutput(IO_OUT2_IO, kxs_gpio_nopull, true, false);
+
+ BLE_CONNECTED_STATE_IO_PE6.initAsInput(PE6, kxs_gpio_nopull, kxs_gpio_no_irq, false);
+
+
+
+ osDelay(10);
+ MOTO_POWER_EN.setState(false);
+
+ TMC51X0Cfg tmc5130cfg1 = {&MOTOR_SPI_INS, MOTO1_CSN_IO, MOTO1_DRV_ENN_IO};
+ TMC51X0Cfg tmc5130cfg2 = {&MOTOR_SPI_INS, MOTO2_CSN_IO, MOTO2_DRV_ENN_IO};
+ TMC51X0Cfg tmc5130cfg3 = {&MOTOR_SPI_INS, MOTO3_CSN_IO, MOTO3_DRV_ENN_IO};
+ TMC51X0Cfg tmc5130cfg4 = {&MOTOR_SPI_INS, MOTO4_CSN_IO, MOTO4_DRV_ENN_IO};
+
+ MOTO1.initialize(tmc5130cfg1);
+ MOTO2.initialize(tmc5130cfg2);
+ MOTO3.initialize(tmc5130cfg3);
+ MOTO4.initialize(tmc5130cfg4);
+
+ ZLOGI(TAG, "motor1 initialize TMC51X0:%x", MOTO1.readICVersion());
+ ZLOGI(TAG, "motor2 initialize TMC51X0:%x", MOTO2.readICVersion());
+ ZLOGI(TAG, "motor3 initialize TMC51X0:%x", MOTO3.readICVersion());
+ ZLOGI(TAG, "motor4 initialize TMC51X0:%x", MOTO4.readICVersion());
+
+ MOTO1.setIHOLD_IRUN(10, 31, 100);
+ MOTO2.setIHOLD_IRUN(10, 31, 100);
+ MOTO3.setIHOLD_IRUN(10, 31, 100);
+ MOTO4.setIHOLD_IRUN(10, 31, 100);
+
+ MOTO1.setScale(1000);
+ MOTO2.setScale(1000);
+ MOTO3.setScale(1000);
+ MOTO4.setScale(1000);
+
+ MOTO1.enable(1);
+ MOTO2.enable(1);
+ MOTO3.enable(1);
+ MOTO4.enable(1);
+
+ // MOTO1.rotate(1000);
+ // MOTO2.rotate(1000);
+ // MOTO3.rotate(1000);
+ // MOTO4.rotate(1000);
+
+ IO_OUT1.setState(false);
+ IO_OUT2.setState(false);
+
+// ZCAN1::ins()->init();
+ eeprom.initialize(&hi2c1);
+}
\ No newline at end of file
diff --git a/usrc/apphal/apphardware.hpp b/usrc/apphal/apphardware.hpp
new file mode 100644
index 0000000..9dcbd85
--- /dev/null
+++ b/usrc/apphal/apphardware.hpp
@@ -0,0 +1,52 @@
+#pragma once
+#include "apphal.hpp"
+namespace iflytop {
+class AppHardware {
+ private:
+ /* data */
+ public:
+ M24M02_I2C_EEPROM eeprom;
+ TMC51X0 MOTO1;
+ TMC51X0 MOTO2;
+ TMC51X0 MOTO3;
+ TMC51X0 MOTO4;
+
+ ZGPIO MOTO_POWER_EN;
+ ZGPIO MOTO1_CSN;
+ ZGPIO MOTO2_CSN;
+ ZGPIO MOTO3_CSN;
+ ZGPIO MOTO4_CSN;
+ ZGPIO MOTO1_DRV_ENN;
+ ZGPIO MOTO2_DRV_ENN;
+ ZGPIO MOTO3_DRV_ENN;
+ ZGPIO MOTO4_DRV_ENN;
+ ZGPIO ID1;
+ ZGPIO ID2;
+ ZGPIO ID3;
+ ZGPIO ID4;
+ ZGPIO ID5;
+ ZGPIO IO_OUT1;
+ ZGPIO IO_OUT2;
+
+ ZGPIO BLE_CONNECTED_STATE_IO_PE6;
+
+ UART_HandleTypeDef* tjcUart;
+ UART_HandleTypeDef* remoteContolerUart;
+
+ static AppHardware* ins() {
+ static AppHardware instance;
+ return &instance;
+ }
+
+ void initialize();
+ TMC51X0* getPump(int32_t index) {
+ if (index == 0) return &MOTO1;
+ if (index == 1) return &MOTO2;
+ if (index == 2) return &MOTO3;
+ if (index == 3) return &MOTO4;
+ ZASSERT(false);
+ return nullptr;
+ }
+};
+
+} // namespace iflytop
diff --git a/usrc/project_configs.h b/usrc/project_configs.h
index 0783f22..93ef7c3 100644
--- a/usrc/project_configs.h
+++ b/usrc/project_configs.h
@@ -3,20 +3,21 @@
/***********************************************************************************************************************
* SDK_CONFIG *
***********************************************************************************************************************/
-#define SDK_DELAY_US_TIMER htim6 // 寰寤惰繜瀹氭椂鍣紝娉ㄦ剰璇ュ欢鏃跺畾鏃跺櫒闇瑕佹寜鐓т互涓嬫枃妗h繘琛岄厤缃 http://192.168.1.3:3000/zwikipedia/iflytop_wikipedia/src/branch/master/doc/stm32cubemx_us_timer.md
-#define SDK_IRQ_PREEMPTPRIORITY_DEFAULT 5 // IO涓柇榛樿涓柇绛夌骇
-#define SDK_CFG__CFG_FLASH_ADDR 0x080C0000 // flash閰嶇疆鍦板潃
+#define SDK_DELAY_US_TIMER htim6 // 微秒延迟定时器,注意该延时定时器需要按照以下文档进行配置 http://192.168.1.3:3000/zwikipedia/iflytop_wikipedia/src/branch/master/doc/stm32cubemx_us_timer.md
+#define SDK_IRQ_PREEMPTPRIORITY_DEFAULT 5 // IO中断默认中断等级
+#define SDK_CFG__CFG_FLASH_ADDR 0x080C0000 // flash配置地址
#define SDK_CFG__SN_FLASH_ADDR 0x080E0004 //
-#define SDK_MAX_TASK 10 // 鏈澶т换鍔℃暟閲
-#define DEBUG_UART huart1 // 璋冭瘯涓插彛
+#define SDK_MAX_TASK 10 // 最大任务数量
+#define DEBUG_UART huart1 // 调试串口
/***********************************************************************************************************************
- * FLASH鍒嗗尯 *
+ * FLASH分区 *
***********************************************************************************************************************/
-// #define BOARD_TYPE_ID_FLASH_ADD 0x080E0000 // 鏉垮瓙绫诲瀷
-// #define SN_FLASH_ADD 0x080E0004 // 浣跨敤鎵囧尯11瀛樺偍SN缂栫爜
+// #define BOARD_TYPE_ID_FLASH_ADD 0x080E0000 // 板子类型
+// #define SN_FLASH_ADD 0x080E0004 // 使用扇区11存储SN编码
-#define SOFTWARE_VERSION 100 // 杞欢鐗堟湰
-#define HARDWARE_VERSION 1 // 纭欢鐗堟湰
-#define PROJECT "hand_acid_main_board" // 宸ョ▼鍚嶇О
+#define SOFTWARE_VERSION 100 // 软件版本
+#define HARDWARE_VERSION 1 // 硬件版本
+#define PROJECT "hand_acid_main_board" // 工程名称
+#define APP_VERSION "101"
diff --git a/usrc/service/app_core.cpp b/usrc/service/app_core.cpp
index 8f098d6..7aad29b 100644
--- a/usrc/service/app_core.cpp
+++ b/usrc/service/app_core.cpp
@@ -3,9 +3,25 @@
#include
#include
+#include "service/pump_ctrl_service.hpp"
+#include "service/remote_controler.hpp"
+#include "service/remote_controler_event_processer.hpp"
+#include "service/ui_scheduler.hpp"
+//
+#include "service/page/page.hpp"
+
#define TAG "main"
using namespace iflytop;
+static const char* zhex2str(uint8_t* data, size_t len) {
+ static char buf[256];
+ memset(buf, 0, sizeof(buf));
+ for (size_t i = 0; i < len; i++) {
+ sprintf(buf + i * 2, "%02X", data[i]);
+ }
+ return buf;
+}
+
extern "C" {
void umain() { AppCore::ins()->initialize(); }
}
@@ -30,6 +46,39 @@ void AppCore::debugLightLoop() {
}
}
}
+void AppCore::appsetup() {
+ /***********************************************************************************************************************
+ * INIT *
+ ***********************************************************************************************************************/
+ AppHardware::ins()->initialize();
+
+ ConfigService::ins()->initialize(&AppHardware::ins()->eeprom);
+ UIScheduler::ins()->initialize();
+ //
+
+ RCTRL->initialize(); // 遥控器初始化
+ Page_login::ins()->initialize(); //
+ Page_main::ins()->initialize(); //
+ Page_keybAcidCh::ins()->initialize();
+ Page_muAcidType::ins()->initialize();
+ // MenuPageMgrService::ins()->initialize(); //
+
+ /***********************************************************************************************************************
+ * REG_EVENT_HANDLER *
+ ***********************************************************************************************************************/
+ RCTRL->regOnReport([](uint8_t* rx, int32_t len) { //
+ ZLOGI(TAG, "[RCTRL] on event:%s", zhex2str(rx, len));
+ });
+
+ /***********************************************************************************************************************
+ * START *
+ ***********************************************************************************************************************/
+ UIScheduler::ins()->startSchedule();
+ RCTRL->startSchedule();
+
+ // dim
+ UIS->chpage(pg_login);
+}
void AppCore::initialize() {
AppHal::MX_TIM6_Init();
@@ -44,6 +93,8 @@ void AppCore::initialize() {
SysMgr::ins()->initedFinished();
SysMgr::ins()->dumpSysInfo();
+
+ appsetup();
AppHal::MX_IWDG_Init();
while (true) {
diff --git a/usrc/service/app_core.hpp b/usrc/service/app_core.hpp
index 442092f..55d8232 100644
--- a/usrc/service/app_core.hpp
+++ b/usrc/service/app_core.hpp
@@ -15,6 +15,7 @@ class AppCore {
return &ins;
}
void initialize();
+ void appsetup();
void debugLightLoop();
};
diff --git a/usrc/service/page/Page_login.cpp b/usrc/service/page/Page_login.cpp
new file mode 100644
index 0000000..c786fd6
--- /dev/null
+++ b/usrc/service/page/Page_login.cpp
@@ -0,0 +1,99 @@
+#include "Page_login.hpp"
+
+#include
+
+using namespace iflytop;
+
+#define PAGE pg_login
+#define OBJ(name) ob_login_##name
+#define TAG "Page_login"
+static CfgItermCache cfgcache;
+
+#define EN_USR(i, enable) \
+ if (enable) { \
+ UIS->setVal(UI_UUID(login, txtUser##i), usrName[i]); \
+ UIS->setVal(UI_UUID(login, uen##i), 1); \
+ } else { \
+ UIS->setVal(UI_UUID(login, txtUser##i), ""); \
+ UIS->setVal(UI_UUID(login, uen##i), (int32_t)0); \
+ }
+
+int32_t Page_login::getPageNum() { return PAGE; }
+
+void Page_login::OnPageLoad() {
+ if (triggerLoginAction) { // triggerLoginAction为true说明用户刚刚输入完密码
+ UIS->virtualClick(PAGE, OBJ(blogin), 0); // 触发一次登录按钮虚拟点击事件
+ triggerLoginAction = false;
+ return;
+ }
+
+ static int enusrNum;
+ static char usrName[6][20];
+
+ memset(usrName, 0, sizeof(usrName));
+ enusrNum = 0;
+ for (size_t i = 0; i < 6; i++) {
+ bool usrEn = CS->getBool((config_index_t)(kusr_enable0 + 3 * i));
+ if (usrEn) {
+ static_assert((kusr_name1 - kusr_name0) == 3);
+ strncpy(usrName[enusrNum], getCfgStr((config_index_t)(kusr_name0 + 3 * i)), 20);
+ enusrNum++;
+ }
+ }
+
+ /**
+ * @brief 加载用户信息
+ */
+
+ EN_USR(0, enusrNum >= 1);
+ EN_USR(1, enusrNum >= 2);
+ EN_USR(2, enusrNum >= 3);
+ EN_USR(3, enusrNum >= 4);
+ EN_USR(4, enusrNum >= 5);
+ EN_USR(5, enusrNum >= 6);
+
+ UIS->setVal(PAGE, OBJ(chooseUsr), (int32_t)0);
+ UIS->setVal(PAGE, OBJ(cUsrName), getCfgStr((config_index_t)(kusr_name0)));
+}
+void Page_login::OnInputFieldContentChange(uint8_t bid, const char* text) {
+ // 输入框内容变化时,会触发一次页面重新加载的事件,这里的逻辑是为了实现,免按登录登录按键。
+ if (bid == OBJ(txtPasswd)) {
+ triggerLoginAction = true;
+ }
+}
+
+void Page_login::OnLoginButtonClick(uint8_t bid, const char* userName, const char* passwd) {
+ ZLOGI(TAG, "try login %s %s", userName, passwd);
+ bool suc = false;
+ bool isadmin = false;
+ if (strcmp(userName, getCfgStr(kusr_name0)) == 0 && strcmp(passwd, getCfgStr(kusr_passwd0)) == 0) {
+ suc = true;
+ isadmin = true;
+ } else if (strcmp(userName, getCfgStr(kusr_name1)) == 0 && strcmp(passwd, getCfgStr(kusr_passwd1)) == 0) {
+ suc = true;
+ } else if (strcmp(userName, getCfgStr(kusr_name2)) == 0 && strcmp(passwd, getCfgStr(kusr_passwd2)) == 0) {
+ suc = true;
+ } else if (strcmp(userName, getCfgStr(kusr_name3)) == 0 && strcmp(passwd, getCfgStr(kusr_passwd3)) == 0) {
+ suc = true;
+ } else if (strcmp(userName, getCfgStr(kusr_name4)) == 0 && strcmp(passwd, getCfgStr(kusr_passwd4)) == 0) {
+ suc = true;
+ } else if (strcmp(userName, getCfgStr(kusr_name5)) == 0 && strcmp(passwd, getCfgStr(kusr_passwd5)) == 0) {
+ suc = true;
+ }
+ if (suc) {
+ GSM->setLogin(isadmin, userName);
+ UIS->chpage(pg_main);
+ } else {
+ UIS->alert("密码错误");
+ }
+ UIS->setVal(PAGE, OBJ(txtPasswd), "");
+}
+
+#if 0
+void Page_login::unlogin() {
+ ZLOGI(TAG, "unlogin");
+ GSM->setUnLogin();
+ UIS->chpage(PAGE);
+ return;
+}
+#endif
\ No newline at end of file
diff --git a/usrc/service/page/Page_login.hpp b/usrc/service/page/Page_login.hpp
new file mode 100644
index 0000000..e47383a
--- /dev/null
+++ b/usrc/service/page/Page_login.hpp
@@ -0,0 +1,28 @@
+#pragma once
+#include "page_processer.hpp"
+namespace iflytop {
+using namespace std;
+
+class Page_login : public IPageProcesser {
+ private:
+ /* data */
+
+ bool triggerLoginAction = false;
+
+ public:
+ static Page_login* ins() {
+ static Page_login instance;
+ return &instance;
+ }
+
+ private:
+ virtual int32_t getPageNum() override;
+
+ virtual void OnPageLoad() override;
+ virtual void OnLoginButtonClick(uint8_t bid, const char* userName, const char* passwd) override;
+ virtual void OnInputFieldContentChange(uint8_t bid, const char* text) override;
+};
+
+} // namespace iflytop
+
+// kpt_sys_event_page_id
\ No newline at end of file
diff --git a/usrc/service/page/Page_main.cpp b/usrc/service/page/Page_main.cpp
new file mode 100644
index 0000000..570f21f
--- /dev/null
+++ b/usrc/service/page/Page_main.cpp
@@ -0,0 +1,117 @@
+#include "Page_main.hpp"
+using namespace iflytop;
+
+#define PAGE pg_main
+#define OBJ(name) ob_main_##name
+#define TAG "Page_main"
+
+#define ADMIN_MENU_ID pg_menuAdmin2
+#define USR_MENU_ID pg_menuUsr
+
+static CfgItermCache cfgcache;
+
+int32_t Page_main::getPageNum() { return PAGE; }
+
+void Page_main::OnPageLoad() {
+ // 设置酸液种类选择组件是否使能
+ if (CS->getInt(kcfg_lockAcidName) == 1) {
+ UIS->setTouchEnableState(ob_main_acidname0, 0);
+ UIS->setTouchEnableState(ob_main_acidname1, 0);
+ UIS->setTouchEnableState(ob_main_acidname2, 0);
+ UIS->setTouchEnableState(ob_main_acidname3, 0);
+ } else {
+ UIS->setTouchEnableState(ob_main_acidname0, 1);
+ UIS->setTouchEnableState(ob_main_acidname1, 1);
+ UIS->setTouchEnableState(ob_main_acidname2, 1);
+ UIS->setTouchEnableState(ob_main_acidname3, 1);
+ }
+ // 更新酸液种类
+ UIS->setVal(PAGE, OBJ(acidname0), CS->getStr(kcfg_acidChooseName0, &cfgcache));
+ UIS->setVal(PAGE, OBJ(acidname1), CS->getStr(kcfg_acidChooseName1, &cfgcache));
+ UIS->setVal(PAGE, OBJ(acidname2), CS->getStr(kcfg_acidChooseName2, &cfgcache));
+ UIS->setVal(PAGE, OBJ(acidname3), CS->getStr(kcfg_acidChooseName3, &cfgcache));
+ // 更新加液体积
+ UIS->setVal(PAGE, OBJ(acideval0), CS->getStr(kcfg_acideval0, &cfgcache));
+ UIS->setVal(PAGE, OBJ(acideval1), CS->getStr(kcfg_acideval1, &cfgcache));
+ UIS->setVal(PAGE, OBJ(acideval2), CS->getStr(kcfg_acideval2, &cfgcache));
+ UIS->setVal(PAGE, OBJ(acideval3), CS->getStr(kcfg_acideval3, &cfgcache));
+ // 更新状态
+ UIS->setEnumComponentState(PAGE, OBJ(AcidState), GSM->getAcidState()); // 酸液桶是否在线
+ UIS->setEnumComponentState(PAGE, OBJ(RemoterS), GSM->getRemoterS()); // 遥控器是否在线
+ UIS->setEnumComponentState(PAGE, OBJ(RunMode), (int32_t)GSM->getRunMode()); // 运行模式
+
+ UIS->setVal(PAGE, OBJ(acidch0), GSM->getPumpSelectState(0));
+ UIS->setVal(PAGE, OBJ(acidch1), GSM->getPumpSelectState(1));
+ UIS->setVal(PAGE, OBJ(acidch2), GSM->getPumpSelectState(2));
+ UIS->setVal(PAGE, OBJ(acidch3), GSM->getPumpSelectState(3));
+
+ // 时间位置暂时显示版本号
+ UIS->setVal(PAGE, OBJ(clock), "version:%s", APP_VERSION);
+
+ // 根据当前登录用户设置菜单页面
+ if (GStateMgr::ins()->isAdmin()) {
+ UIS->setVal(UI_UUID(gvar, menupageid), ADMIN_MENU_ID);
+ } else {
+ UIS->setVal(UI_UUID(gvar, menupageid), USR_MENU_ID);
+ }
+}
+
+void Page_main::OnInputFieldContentChange(uint8_t bid, const char* text) {
+ // 更新酸液每次分配设定值
+ if (bid == OBJ(acideval0)) {
+ processAcidevalUpdateEvent(bid, text, 0, kcfg_acideval0);
+ } else if (bid == OBJ(acideval1)) {
+ processAcidevalUpdateEvent(bid, text, 1, kcfg_acideval1);
+ } else if (bid == OBJ(acideval2)) {
+ processAcidevalUpdateEvent(bid, text, 2, kcfg_acideval2);
+ } else if (bid == OBJ(acideval3)) {
+ processAcidevalUpdateEvent(bid, text, 3, kcfg_acideval3);
+ }
+
+ // 更新酸液种类
+ else if (bid == OBJ(acidname0)) {
+ ZLOGI(TAG, "acidname0:%s", text);
+ CS->setcfgAndFlush(kcfg_acidChooseName0, text);
+ } else if (bid == OBJ(acidname1)) {
+ ZLOGI(TAG, "acidname1:%s", text);
+ CS->setcfgAndFlush(kcfg_acidChooseName1, text);
+ } else if (bid == OBJ(acidname2)) {
+ ZLOGI(TAG, "acidname2:%s", text);
+ CS->setcfgAndFlush(kcfg_acidChooseName2, text);
+ } else if (bid == OBJ(acidname3)) {
+ ZLOGI(TAG, "acidname3:%s", text);
+ CS->setcfgAndFlush(kcfg_acidChooseName3, text);
+ }
+}
+void Page_main::OnButton(uint8_t bid, uint8_t val) {}
+void Page_main::OnDoubleStateButton(uint8_t bid, uint8_t val) {
+ // 更新泵选择状态
+ if (bid == OBJ(acidch0)) {
+ ZLOGI(TAG, "choose acid ch%d,%d", 0, val);
+ GSM->setPumpSelectState(0, val);
+ } else if (bid == OBJ(acidch1)) {
+ ZLOGI(TAG, "choose acid ch%d,%d", 1, val);
+ GSM->setPumpSelectState(1, val);
+ } else if (bid == OBJ(acidch2)) {
+ ZLOGI(TAG, "choose acid ch%d,%d", 2, val);
+ GSM->setPumpSelectState(2, val);
+ } else if (bid == OBJ(acidch3)) {
+ ZLOGI(TAG, "choose acid ch%d,%d", 3, val);
+ GSM->setPumpSelectState(3, val);
+ }
+}
+
+void Page_main::processAcidevalUpdateEvent(uint8_t bid, const char* text, int ch, config_index_t cfgid) {
+ float add_ml = atof(text);
+ if (add_ml < 0) {
+ UIS->setVal(PAGE, bid, CS->getStr(cfgid, &cfgcache)); // 恢复数值
+ UIS->alert("设定值不能小于0");
+ return;
+ } else if (add_ml > CS->getInt(kcfg_echDitrUpLi)) {
+ UIS->setVal(PAGE, bid, CS->getStr(cfgid, &cfgcache)); // 恢复数值
+ UIS->alert("设定值不能大于%d", CS->getInt(kcfg_echDitrUpLi));
+ return;
+ }
+ ZLOGI(TAG, "set acid ch%d:%s", ch, text);
+ CS->setcfgAndFlush(cfgid, text); //
+}
diff --git a/usrc/service/page/Page_main.hpp b/usrc/service/page/Page_main.hpp
new file mode 100644
index 0000000..a80e9de
--- /dev/null
+++ b/usrc/service/page/Page_main.hpp
@@ -0,0 +1,29 @@
+#pragma once
+#include "page_processer.hpp"
+
+namespace iflytop {
+using namespace std;
+
+class Page_main : public IPageProcesser {
+ private:
+ /* data */
+
+ public:
+ static Page_main* ins() {
+ static Page_main instance;
+ return &instance;
+ }
+
+ private:
+ virtual int32_t getPageNum() override;
+
+ virtual void OnPageLoad() override;
+ virtual void OnInputFieldContentChange(uint8_t bid, const char* text) override;
+ virtual void OnButton(uint8_t bid, uint8_t val) override;
+ virtual void OnDoubleStateButton(uint8_t bid, uint8_t val) override;
+
+ private:
+ void processAcidevalUpdateEvent(uint8_t bid, const char* text, int ch, config_index_t cfgid);
+};
+
+} // namespace iflytop
diff --git a/usrc/service/page/keyboard/Page_keybAcidCh.cpp b/usrc/service/page/keyboard/Page_keybAcidCh.cpp
new file mode 100644
index 0000000..41dadcf
--- /dev/null
+++ b/usrc/service/page/keyboard/Page_keybAcidCh.cpp
@@ -0,0 +1,28 @@
+#include "Page_keybAcidCh.hpp"
+using namespace iflytop;
+
+#define PAGE pg_keybAcidCh
+#define OBJ(name) ob_keybAcidCh_##name
+static CfgItermCache cfgcache;
+
+int32_t Page_keybAcidCh::getPageNum() { return PAGE; }
+
+void Page_keybAcidCh::OnPageLoad() { //
+ UIS->setVal(PAGE, OBJ(b0), getCfgStr(kcfg_acidName1));
+ UIS->setVal(PAGE, OBJ(b1), getCfgStr(kcfg_acidName2));
+ UIS->setVal(PAGE, OBJ(b2), getCfgStr(kcfg_acidName3));
+ UIS->setVal(PAGE, OBJ(b3), getCfgStr(kcfg_acidName4));
+ UIS->setVal(PAGE, OBJ(b4), getCfgStr(kcfg_acidName5));
+ UIS->setVal(PAGE, OBJ(b5), getCfgStr(kcfg_acidName6));
+ UIS->setVal(PAGE, OBJ(b6), getCfgStr(kcfg_acidName7));
+ UIS->setVal(PAGE, OBJ(b7), getCfgStr(kcfg_acidName8));
+ UIS->setVal(PAGE, OBJ(b8), getCfgStr(kcfg_acidName9));
+ UIS->setVal(PAGE, OBJ(b9), getCfgStr(kcfg_acidName10));
+ UIS->setVal(PAGE, OBJ(b10), getCfgStr(kcfg_acidName11));
+ UIS->setVal(PAGE, OBJ(b11), getCfgStr(kcfg_acidName12));
+ UIS->setVal(PAGE, OBJ(b12), getCfgStr(kcfg_acidName13));
+ UIS->setVal(PAGE, OBJ(b13), getCfgStr(kcfg_acidName14));
+ UIS->setVal(PAGE, OBJ(b14), getCfgStr(kcfg_acidName15));
+};
+
+// muAcidType
\ No newline at end of file
diff --git a/usrc/service/page/keyboard/Page_keybAcidCh.hpp b/usrc/service/page/keyboard/Page_keybAcidCh.hpp
new file mode 100644
index 0000000..69c5caa
--- /dev/null
+++ b/usrc/service/page/keyboard/Page_keybAcidCh.hpp
@@ -0,0 +1,20 @@
+#pragma once
+//
+#include "../page_processer.hpp"
+
+namespace iflytop {
+using namespace std;
+// page: keybAcidCh
+class Page_keybAcidCh : public IPageProcesser {
+ public:
+ static Page_keybAcidCh* ins() {
+ static Page_keybAcidCh instance;
+ return &instance;
+ }
+
+ private:
+ virtual int32_t getPageNum() override;
+ virtual void OnPageLoad() override;
+};
+
+} // namespace iflytop
diff --git a/usrc/service/page/page.hpp b/usrc/service/page/page.hpp
new file mode 100644
index 0000000..eb00e70
--- /dev/null
+++ b/usrc/service/page/page.hpp
@@ -0,0 +1,6 @@
+#pragma once
+
+#include "Page_login.hpp"
+#include "Page_main.hpp"
+#include "submenu/Page_muAcidType.hpp"
+#include "keyboard/Page_keybAcidCh.hpp"
\ No newline at end of file
diff --git a/usrc/service/page/page_processer.hpp b/usrc/service/page/page_processer.hpp
new file mode 100644
index 0000000..5082b1d
--- /dev/null
+++ b/usrc/service/page/page_processer.hpp
@@ -0,0 +1,48 @@
+#pragma once
+
+#include "apphal/apphal.hpp"
+#include "service\ui_scheduler.hpp"
+#include "uappbase/base.hpp"
+#include "ui/ui.h"
+namespace iflytop {
+using namespace std;
+
+class IPageProcesser {
+ private:
+ /* data */
+
+ public:
+ virtual void initialize() {
+ UIS->regOnUsrEventCb([this](tjc::tjc_usr_event_t* event) {
+ if (event->pid != getPageNum()) {
+ return;
+ }
+ if (event->eventId == tjc::kpt_sys_event_page_id) {
+ // 页面加载事件
+ OnPageLoad();
+ } else if (event->eventId == tjc::kpt_double_state_button_event) {
+ OnDoubleStateButton(event->bid, event->d.double_state_button.val);
+ } else if (event->eventId == tjc::kpt_button_event) {
+ OnButton(event->bid, event->d.button_event.val);
+ } else if (event->eventId == tjc::kpt_inputfield_content_change_event) {
+ OnInputFieldContentChange(event->bid, event->d.inputfield_content.text);
+ } else if (event->eventId == tjc::kpt_login_request) {
+ OnLoginButtonClick(event->bid, event->d.login_request.usrName, event->d.login_request.passwd);
+ } else if (event->eventId == tjc::kpt_unlogin_request) {
+ OnUnLoginButtonClick(event->bid);
+ }
+ });
+ }
+
+ private:
+ virtual int32_t getPageNum() = 0;
+
+ virtual void OnPageLoad() { return; };
+ virtual void OnInputFieldContentChange(uint8_t bid, const char* text) { return; };
+ virtual void OnButton(uint8_t bid, uint8_t val) { return; };
+ virtual void OnDoubleStateButton(uint8_t bid, uint8_t val) { return; };
+ virtual void OnLoginButtonClick(uint8_t bid, const char* userName, const char* passwd) { return; };
+ virtual void OnUnLoginButtonClick(uint8_t bid) { return; };
+};
+
+} // namespace iflytop
diff --git a/usrc/service/page/submenu/Page_muAcidType.cpp b/usrc/service/page/submenu/Page_muAcidType.cpp
new file mode 100644
index 0000000..e6576ec
--- /dev/null
+++ b/usrc/service/page/submenu/Page_muAcidType.cpp
@@ -0,0 +1,78 @@
+#include "Page_muAcidType.hpp"
+using namespace iflytop;
+
+/**
+ * @brief
+ * 酸类修改页面
+ */
+
+#define PAGE pg_muAcidType
+#define OBJ(name) ob_muAcidType_##name
+#define TAG "Page_muAcidType"
+static CfgItermCache cfgcache;
+int32_t Page_muAcidType::getPageNum() { return PAGE; }
+
+void Page_muAcidType::OnPageLoad() { //
+ UIS->setVal(PAGE, OBJ(t1), getCfgStr(kcfg_acidName1));
+ UIS->setVal(PAGE, OBJ(t2), getCfgStr(kcfg_acidName2));
+ UIS->setVal(PAGE, OBJ(t3), getCfgStr(kcfg_acidName3));
+ UIS->setVal(PAGE, OBJ(t4), getCfgStr(kcfg_acidName4));
+ UIS->setVal(PAGE, OBJ(t5), getCfgStr(kcfg_acidName5));
+ UIS->setVal(PAGE, OBJ(t6), getCfgStr(kcfg_acidName6));
+ UIS->setVal(PAGE, OBJ(t7), getCfgStr(kcfg_acidName7));
+ UIS->setVal(PAGE, OBJ(t8), getCfgStr(kcfg_acidName8));
+ UIS->setVal(PAGE, OBJ(t9), getCfgStr(kcfg_acidName9));
+ UIS->setVal(PAGE, OBJ(t10), getCfgStr(kcfg_acidName10));
+ UIS->setVal(PAGE, OBJ(t11), getCfgStr(kcfg_acidName11));
+ UIS->setVal(PAGE, OBJ(t12), getCfgStr(kcfg_acidName12));
+ UIS->setVal(PAGE, OBJ(t13), getCfgStr(kcfg_acidName13));
+ UIS->setVal(PAGE, OBJ(t14), getCfgStr(kcfg_acidName14));
+ UIS->setVal(PAGE, OBJ(t15), getCfgStr(kcfg_acidName15));
+};
+void Page_muAcidType::updateAcidName(uint8_t bid, config_index_t cindex, const char* txt) {
+ ZLOGI(TAG, "updateAcidName: cindex %d : %s", cindex, txt);
+ CS->setcfgAndFlush(cindex, txt);
+}
+
+void Page_muAcidType::OnInputFieldContentChange(uint8_t bid, const char* text) { //
+ switch (bid) {
+ case OBJ(t1):
+ return updateAcidName(bid, kcfg_acidName1, text);
+ case OBJ(t2):
+ return updateAcidName(bid, kcfg_acidName2, text);
+ case OBJ(t3):
+ return updateAcidName(bid, kcfg_acidName3, text);
+ case OBJ(t4):
+ return updateAcidName(bid, kcfg_acidName4, text);
+ case OBJ(t5):
+ return updateAcidName(bid, kcfg_acidName5, text);
+ case OBJ(t6):
+ return updateAcidName(bid, kcfg_acidName6, text);
+ case OBJ(t7):
+ return updateAcidName(bid, kcfg_acidName7, text);
+ case OBJ(t8):
+ return updateAcidName(bid, kcfg_acidName8, text);
+ case OBJ(t9):
+ return updateAcidName(bid, kcfg_acidName9, text);
+ case OBJ(t10):
+ return updateAcidName(bid, kcfg_acidName10, text);
+ case OBJ(t11):
+ return updateAcidName(bid, kcfg_acidName11, text);
+ case OBJ(t12):
+ return updateAcidName(bid, kcfg_acidName12, text);
+ case OBJ(t13):
+ return updateAcidName(bid, kcfg_acidName13, text);
+ case OBJ(t14):
+ return updateAcidName(bid, kcfg_acidName14, text);
+ case OBJ(t15):
+ return updateAcidName(bid, kcfg_acidName15, text);
+ default:
+ break;
+ }
+};
+void Page_muAcidType::OnButton(uint8_t bid, uint8_t val) { //
+ if (bid == OBJ(bak)) {
+ }
+};
+
+// muAcidType
\ No newline at end of file
diff --git a/usrc/service/page/submenu/Page_muAcidType.hpp b/usrc/service/page/submenu/Page_muAcidType.hpp
new file mode 100644
index 0000000..528b4fd
--- /dev/null
+++ b/usrc/service/page/submenu/Page_muAcidType.hpp
@@ -0,0 +1,26 @@
+#pragma once
+//
+#include "../page_processer.hpp"
+namespace iflytop {
+using namespace std;
+// page: keybAcidCh
+class Page_muAcidType : public IPageProcesser {
+ private:
+ /* data */
+
+ public:
+ static Page_muAcidType* ins() {
+ static Page_muAcidType instance;
+ return &instance;
+ }
+
+ private:
+ virtual int32_t getPageNum() override;
+ virtual void OnPageLoad() override;
+ virtual void OnInputFieldContentChange(uint8_t bid, const char* text) override;
+ virtual void OnButton(uint8_t bid, uint8_t val) override;
+ private:
+ void updateAcidName(uint8_t bid,config_index_t cindex,const char* txt);
+};
+
+} // namespace iflytop
diff --git a/usrc/service/pump_ctrl_service.cpp b/usrc/service/pump_ctrl_service.cpp
new file mode 100644
index 0000000..fb16a75
--- /dev/null
+++ b/usrc/service/pump_ctrl_service.cpp
@@ -0,0 +1,181 @@
+#include "pump_ctrl_service.hpp"
+
+using namespace iflytop;
+#define TAG "PumpCtrlService"
+
+static TMC51X0* m_motors[4];
+#define PUMP_NUM 4
+
+static CfgItermCache cfgcache;
+
+void PumpCtrlService::initialize() {
+ m_motors[0] = AppHardware::ins()->getPump(0);
+ m_motors[1] = AppHardware::ins()->getPump(1);
+ m_motors[2] = AppHardware::ins()->getPump(2);
+ m_motors[3] = AppHardware::ins()->getPump(3);
+
+ for (size_t i = 0; i < PUMP_NUM; i++) {
+ m_motors[i]->enable(false);
+
+ m_motors[i]->setIHOLD_IRUN(STEPMOTOR_IHOLD, STEPMOTOR_IRUN, STEPMOTOR_IHOLDDELAY);
+ m_motors[i]->setScaleDenominator(1);
+ m_motors[i]->setMotorShaft(MOTOR_SHAFT);
+ m_motors[i]->setVstart(MOTOR_VSTART);
+ m_motors[i]->setVstop(MOTOR_VSTART);
+ m_motors[i]->setA1(MOTOR_A1);
+ m_motors[i]->setD1(MOTOR_A1);
+ m_motors[i]->setAmax(MOTOR_AMAX);
+ m_motors[i]->setDmax(MOTOR_AMAX);
+ m_motors[i]->setV1(MOTOR_V1);
+ m_motors[i]->setTzerowait(MOTOR_TZEROWAIT);
+
+ switch (i) {
+ case 0:
+ m_motors[i]->setScale(getCfgInt(kcfg_1ulTrunsM0));
+ break;
+ case 1:
+ m_motors[i]->setScale(getCfgInt(kcfg_1ulTrunsM1));
+ break;
+ case 2:
+ m_motors[i]->setScale(getCfgInt(kcfg_1ulTrunsM2));
+ break;
+ case 3:
+ m_motors[i]->setScale(getCfgInt(kcfg_1ulTrunsM3));
+ break;
+ default:
+ break;
+ }
+ m_motors[i]->enable(true);
+ }
+
+ m_thread.init("PumpCtrlService", 1024);
+}
+
+void PumpCtrlService::stop() {
+ ZLOGI(TAG, "stop");
+ m_thread.stop();
+ stopAll();
+ ZLOGI(TAG, "stop finish");
+}
+
+/***********************************************************************************************************************
+ * EXT *
+ ***********************************************************************************************************************/
+void PumpCtrlService::reflux() {
+ ZLOGI(TAG, "reflux");
+ m_thread.start([this]() {
+ int32_t pipeLenML = getCfgInt(kcfg_pipeLengthML);
+ int32_t vel = getCfgInt(config_index_t(kcfg_pumpDefVel));
+
+ for (size_t i = 0; i < PUMP_NUM; i++) {
+ TMC51X0* cur_motor = m_motors[i];
+ cur_motor->stop();
+ cur_motor->setXACTUAL(0);
+ ZLOGI(TAG, "pump %d move %f ml", i, -pipeLenML);
+ cur_motor->moveBy((int32_t)-pipeLenML * 1000, vel);
+ }
+
+ while (!m_thread.getExitFlag()) {
+ if (isAllReachTarget()) {
+ break;
+ }
+ osDelay(10);
+ }
+
+ stopAll();
+ ZLOGI(TAG, "reflux end");
+ });
+}
+void PumpCtrlService::acidPrefilling() {
+ ZLOGI(TAG, "acidPrefilling");
+ m_thread.start([this]() {
+ int32_t pipeLenML = getCfgInt(kcfg_pipeLengthML);
+ int32_t vel = getCfgInt(config_index_t(kcfg_pumpDefVel));
+
+ for (size_t i = 0; i < PUMP_NUM; i++) {
+ TMC51X0* cur_motor = m_motors[i];
+ cur_motor->stop();
+ cur_motor->setXACTUAL(0);
+ ZLOGI(TAG, "pump %d move %f ml", i, pipeLenML);
+ cur_motor->moveBy((int32_t)pipeLenML * 1000, vel);
+ }
+
+ while (!m_thread.getExitFlag()) {
+ if (isAllReachTarget()) {
+ break;
+ }
+ osDelay(10);
+ }
+
+ stopAll();
+ ZLOGI(TAG, "acidPrefilling end");
+ });
+}
+
+void PumpCtrlService::autoMoveMutiTimes() {
+ // doMoveOnce();
+ ZLOGI(TAG, "autoMoveMutiTimes");
+ m_thread.start([this]() {
+ int32_t delayTime = getCfgInt(kcfg_distrInterval);
+
+ while (!m_thread.getExitFlag()) {
+ doMoveOnce();
+ for (size_t i = 0; i < delayTime * 1000; i++) {
+ osDelay(1);
+ if (m_thread.getExitFlag()) {
+ break;
+ }
+ }
+ }
+
+ stopAll();
+ });
+}
+void PumpCtrlService::moveOnce() {
+ ZLOGI(TAG, "moveOnce");
+ m_thread.start([this]() { doMoveOnce(); });
+}
+
+/***********************************************************************************************************************
+ * BASIC *
+ ***********************************************************************************************************************/
+
+void PumpCtrlService::doMoveOnce() {
+ //
+ ZLOGI(TAG, "do moveOnce ...");
+ for (size_t i = 0; i < PUMP_NUM; i++) {
+ bool pumpselect = GSM->getPumpSelectState(i);
+ float distribut_ml = getCfgFloat(config_index_t(kcfg_acideval0 + i));
+ int32_t vel = getCfgInt(config_index_t(kcfg_pumpDefVel));
+
+ TMC51X0* cur_motor = m_motors[i];
+ cur_motor->stop();
+ cur_motor->setXACTUAL(0);
+ if (pumpselect) {
+ ZLOGI(TAG, "pump %d move %f ml", i, distribut_ml);
+ cur_motor->moveBy((int32_t)distribut_ml * 1000, vel);
+ }
+ }
+
+ while (!isAllReachTarget()) {
+ osDelay(10);
+ }
+ stopAll();
+}
+
+bool PumpCtrlService::isAllReachTarget() {
+ for (size_t i = 0; i < PUMP_NUM; i++) {
+ TMC5130RampStat state = m_motors[i]->getRampStat();
+ if (!m_motors[i]->isReachTarget(&state)) {
+ return false;
+ }
+ }
+ return true;
+}
+
+void PumpCtrlService::stopAll() {
+ for (size_t i = 0; i < PUMP_NUM; i++) {
+ m_motors[i]->stop();
+ }
+ return;
+}
diff --git a/usrc/service/pump_ctrl_service.hpp b/usrc/service/pump_ctrl_service.hpp
new file mode 100644
index 0000000..8657fd5
--- /dev/null
+++ b/usrc/service/pump_ctrl_service.hpp
@@ -0,0 +1,47 @@
+#pragma once
+#include "apphal/apphal.hpp"
+#include "apphal/apphardware.hpp"
+#include "uappbase/base.hpp"
+namespace iflytop {
+using namespace std;
+#define PCS PumpCtrlService::ins()
+
+/**
+ * @brief
+ *
+ */
+
+class PumpCtrlService {
+ ZThread m_thread;
+
+ public:
+ PumpCtrlService() {};
+ ~PumpCtrlService() {};
+
+ static PumpCtrlService* ins() {
+ static PumpCtrlService instance;
+ return &instance;
+ }
+
+ void initialize();
+
+ public:
+ bool isWorking();
+ bool pumpIsWorking();
+
+ public:
+ void moveOnce();
+ void autoMoveMutiTimes();
+
+ void reflux();
+ void acidPrefilling();
+
+ void stop();
+
+ private:
+ bool isAllReachTarget();
+ void stopAll();
+ void doMoveOnce();
+};
+
+} // namespace iflytop
diff --git a/usrc/service/remote_controler.cpp b/usrc/service/remote_controler.cpp
new file mode 100644
index 0000000..ed3447d
--- /dev/null
+++ b/usrc/service/remote_controler.cpp
@@ -0,0 +1,173 @@
+#include "remote_controler.hpp"
+
+using namespace iflytop;
+
+#define UART_RX_OVERTIME 3
+#define TAG "RemoteControler"
+
+
+#define CMD_OVERTIME 500
+
+static ZQueue ackQueue;
+static ZQueue eventQueue;
+static ZThread usartRxThread;
+static ZThread eventProcessThread;
+static bool m_isWaitingForAck;
+static UART_HandleTypeDef* m_uart;
+
+static const char* zhex2str(uint8_t* data, size_t len) {
+ static char buf[256];
+ memset(buf, 0, sizeof(buf));
+ for (size_t i = 0; i < len; i++) {
+ sprintf(buf + i * 2, "%02X", data[i]);
+ }
+ return buf;
+}
+
+void RemoteControler::initialize() {
+ ackQueue.initialize(1, sizeof(RemoteControlerReportPacket_t));
+ eventQueue.initialize(3, sizeof(RemoteControlerReportPacket_t));
+ usartRxThread.init("usartRxThread", 1024);
+ eventProcessThread.init("eventProcessThread", 1024);
+ ZASSERT(AppHardware::ins()->remoteContolerUart);
+
+ m_uart = AppHardware::ins()->remoteContolerUart;
+ m_cmdlock.init();
+}
+void RemoteControler::regOnReport(on_report_cb_t on_report) {
+ m_cb[m_ncb] = on_report;
+ m_ncb++;
+}
+
+bool RemoteControler::isConnected() { return AppHardware::ins()->BLE_CONNECTED_STATE_IO_PE6.getState(); }
+void RemoteControler::callOnReport(uint8_t* rx, int32_t len) {
+ for (int32_t i = 0; i < m_ncb; i++) {
+ m_cb[i](rx, len);
+ }
+}
+
+void RemoteControler::startSchedule() {
+ usartRxThread.start([this]() {
+ static uint8_t rxbuf[128];
+ m_uart->USR_UartITRxing = 1;
+ m_uart->USR_UartITRxBuf = rxbuf;
+ m_uart->USR_UartITRxBufSize = 128;
+ m_uart->USR_UartITRxOff = 0;
+ HAL_UART_Receive_IT(m_uart, &m_uart->USR_UartITRxBufCache, 1);
+ while (1) {
+ // static uint8_t processbuf[128];
+ static RemoteControlerReportPacket_t rxpacket;
+ rxpacket.datalen = 0;
+ if (m_uart->USR_UartITRxOff != 0 && zos_haspassedms(m_uart->USR_UartITLastRxTicket) > UART_RX_OVERTIME) {
+ vPortEnterCritical();
+ if (m_uart->USR_UartITRxOff != 0 && zos_haspassedms(m_uart->USR_UartITLastRxTicket) > UART_RX_OVERTIME) {
+ memset(rxpacket.data, 0, sizeof(rxpacket.data));
+ memcpy(rxpacket.data, m_uart->USR_UartITRxBuf, m_uart->USR_UartITRxOff);
+ rxpacket.datalen = m_uart->USR_UartITRxOff;
+ m_uart->USR_UartITRxOff = 0;
+ }
+ vPortExitCritical();
+ }
+
+ if (rxpacket.datalen != 0) {
+ pre_processrxpacket(&rxpacket);
+ }
+ osDelay(1);
+ }
+ });
+
+ eventProcessThread.start([this]() {
+ while (1) {
+ static RemoteControlerReportPacket_t packet;
+ bool suc = eventQueue.receive(&packet, 10);
+ if (suc) {
+ processRxEventPacket(&packet);
+ }
+ osDelay(1);
+ }
+ });
+}
+extern "C"{
+bool ble_through_proto_check_packet(ble_through_proto_t *packet);
+}
+
+void RemoteControler::pre_processrxpacket(RemoteControlerReportPacket_t* packet) {
+ // 判断包是否合法
+#if DEBUG
+ ZLOGI(TAG, "[rx-thread] : rx :%s(%d)", zhex2str(packet->data, packet->datalen), packet->datalen);
+#endif
+
+ ble_through_proto_t* p_packet = (ble_through_proto_t*)packet->data;
+ if (!ble_through_proto_check_packet(p_packet)) {
+ ZLOGI(TAG, "rx invalid packet %s", zhex2str(packet->data, packet->datalen));
+ return;
+ }
+
+ bool suc = true;
+ if (p_packet->frame_type == kproto_cmd) {
+ // suc = ackQueue.send(packet, 10);
+ } else if (p_packet->frame_type == kproto_report) {
+ suc = eventQueue.send(packet, 10);
+ } else if (p_packet->frame_type == kproto_error_receipt || p_packet->frame_type == kproto_cmd_receipt) {
+ if (m_isWaitingForAck) {
+ suc = ackQueue.send(packet, 10);
+ m_isWaitingForAck = false;
+ }
+ }
+ if (!suc) {
+ ZLOGI(TAG, "eventQueue send failed");
+ }
+}
+
+void RemoteControler::processRxEventPacket(RemoteControlerReportPacket_t* packet) {
+#if DEBUG
+ ZLOGI(TAG, "[process-thread] rx event : %s", zhex2str(packet->data, packet->datalen));
+#endif
+ // if (m_on_report) {
+ // m_on_report(packet->data, packet->datalen);
+ // }
+ callOnReport(packet->data, packet->datalen);
+}
+#if 0
+bool RemoteControler::cmd_set_state(hand_acid_mode_t mode, hand_pump_working_state_t state) {
+ ble_through_proto_t* packet = (ble_through_proto_t*)txbuf;
+ int32_t packetlen = HAND_ACID_BLE_BASE_SIZE + 2 + sizeof(packet->data.set_state);
+
+ packet->h1 = PACKET_H1;
+ packet->h2 = PACKET_H2;
+ packet->packetlen = packetlen;
+ packet->frame_type = kproto_cmd;
+ packet->frame_index = 1;
+ packet->cmd = kproto_cmd_set_state;
+ packet->data.set_state.hand_acid_mode = (uint8_t)mode;
+ packet->data.set_state.hand_pump_working_state = (uint8_t)state;
+ PACKET_SET_CHECKSUM(packet);
+ PACKET_SET_TAIL(packet);
+ return txcmd(txbuf, packetlen);
+}
+#endif
+bool RemoteControler::txcmd(uint8_t* data, uint32_t len) {
+ /**
+ * @brief
+ */
+ zlock_guard lg(m_cmdlock);
+ ackQueue.clear();
+ m_isWaitingForAck = true;
+#if DEBUG
+ ZLOGI(TAG, "txcmd : %s(%d)", zhex2str(data, len), len);
+#endif
+
+ // HAL_UART_Transmit(m_uart, data, len, 100);
+ HAL_UART_Transmit_DMA(m_uart, data, len);
+ bool suc = ackQueue.receive(&ackcache, CMD_OVERTIME);
+ if (!suc) {
+ ZLOGI(TAG, "txcmd failed");
+ HAL_UART_DMAStop(m_uart);
+ return false;
+ }
+#if DEBUG
+ ZLOGI(TAG, "ack : %s", zhex2str(ackcache.data, ackcache.datalen));
+#endif
+ HAL_UART_DMAStop(m_uart);
+ return true;
+}
diff --git a/usrc/service/remote_controler.hpp b/usrc/service/remote_controler.hpp
new file mode 100644
index 0000000..d6e8b19
--- /dev/null
+++ b/usrc/service/remote_controler.hpp
@@ -0,0 +1,50 @@
+#pragma once
+#include "apphal/apphal.hpp"
+#include "apphal/apphardware.hpp"
+#include "uappbase/base.hpp"
+namespace iflytop {
+using namespace std;
+#define RCTRL RemoteControler::ins()
+typedef struct {
+ uint8_t data[255];
+ uint16_t datalen;
+} RemoteControlerReportPacket_t;
+class RemoteControler {
+ public:
+ typedef std::function on_report_cb_t;
+
+ private:
+ on_report_cb_t m_cb[50];
+ int32_t m_ncb = 0;
+
+ zmutex m_cmdlock;
+
+ RemoteControlerReportPacket_t ackcache;
+
+ uint8_t txbuf[255];
+
+ public:
+ RemoteControler(){};
+ ~RemoteControler(){};
+
+ static RemoteControler* ins() {
+ static RemoteControler instance;
+ return &instance;
+ }
+
+ void initialize();
+ void regOnReport(on_report_cb_t on_report);
+ void startSchedule();
+
+ bool isConnected();
+ // bool cmd_set_state(hand_acid_mode_t mode, hand_pump_working_state_t state);
+
+ private:
+ bool txcmd(uint8_t* data, uint32_t len);
+ void pre_processrxpacket(RemoteControlerReportPacket_t* packet);
+
+ void processRxEventPacket(RemoteControlerReportPacket_t* packet);
+ void callOnReport(uint8_t* rx, int32_t len);
+};
+
+} // namespace iflytop
diff --git a/usrc/service/remote_controler_event_processer.cpp b/usrc/service/remote_controler_event_processer.cpp
new file mode 100644
index 0000000..c0ce87b
--- /dev/null
+++ b/usrc/service/remote_controler_event_processer.cpp
@@ -0,0 +1,30 @@
+#include "remote_controler_event_processer.hpp"
+#include "remote_controler.hpp"
+using namespace iflytop;
+void RemoterControlerEventProcesser::initialize() {
+ //
+ RemoteControler::ins()->regOnReport([this](uint8_t* rx, int32_t len) { //
+ onPacket((ble_through_proto_t*)rx);
+ });
+}
+
+void RemoterControlerEventProcesser::onPacket(ble_through_proto_t* packet) {
+ // kproto_report_key_event
+ // kproto_report_connected_event
+
+ // if (packet->cmd == kproto_report_connected_event) {
+ // static AppEvent_t event;
+ // if (packet->data.connected_event.connected) {
+ // /**
+ // * @brief 同步状态到笔端
+ // */
+
+ // event.type = kAppEvent_RemoterControlerConnected;
+ // AppEventBus::ins()->pushEvent(event);
+
+ // } else {
+ // event.type = kAppEvent_RemoterControlerDisConnected;
+ // AppEventBus::ins()->pushEvent(event);
+ // }
+ // }
+}
diff --git a/usrc/service/remote_controler_event_processer.hpp b/usrc/service/remote_controler_event_processer.hpp
new file mode 100644
index 0000000..aafbd0d
--- /dev/null
+++ b/usrc/service/remote_controler_event_processer.hpp
@@ -0,0 +1,21 @@
+#pragma once
+#include "apphal/apphal.hpp"
+#include "apphal/apphardware.hpp"
+#include "uappbase/base.hpp"
+namespace iflytop {
+using namespace std;
+
+class RemoterControlerEventProcesser {
+ public:
+ static RemoterControlerEventProcesser* ins() {
+ static RemoterControlerEventProcesser instance;
+ return &instance;
+ }
+
+ void initialize();
+
+ private:
+ void onPacket(ble_through_proto_t* packet);
+};
+
+} // namespace iflytop
diff --git a/usrc/service/tjc/tjc.hpp b/usrc/service/tjc/tjc.hpp
new file mode 100644
index 0000000..bf31e9e
--- /dev/null
+++ b/usrc/service/tjc/tjc.hpp
@@ -0,0 +1,2 @@
+#pragma once
+#include "tjc_constant.hpp"
\ No newline at end of file
diff --git a/usrc/service/tjc/tjc_constant.cpp b/usrc/service/tjc/tjc_constant.cpp
new file mode 100644
index 0000000..f614eab
--- /dev/null
+++ b/usrc/service/tjc/tjc_constant.cpp
@@ -0,0 +1,486 @@
+#include "tjc_constant.hpp"
+
+#include
+
+namespace tjc {
+typedef struct {
+ uint8_t pid;
+ uint8_t bid;
+ const char* info;
+ const char* pids;
+ const char* bidstr;
+} marco_info_t;
+
+#define _BINFO(_pid, _bid) \
+ { pg_##_pid, ob_##_pid##_##_bid, #_pid "_" #_bid, #_pid, #_bid }
+// 命名规范为驼峰命名
+static marco_info_t infos[] = {
+ _BINFO(gvar, gvar), //
+ _BINFO(gvar, menupageid), //
+
+ _BINFO(pStart, pStart), //
+ _BINFO(pStart, j0), //
+ _BINFO(pStart, tm0), //
+ //
+ _BINFO(login, login), //
+ _BINFO(login, blogin), //
+ _BINFO(login, txtPasswd), //
+ _BINFO(login, uen0), //
+ _BINFO(login, uen1), //
+ _BINFO(login, uen2), //
+ _BINFO(login, uen3), //
+ _BINFO(login, uen4), //
+ _BINFO(login, uen5), //
+ _BINFO(login, txtUser0), //
+ _BINFO(login, txtUser1), //
+ _BINFO(login, txtUser2), //
+ _BINFO(login, txtUser3), //
+ _BINFO(login, txtUser4), //
+ _BINFO(login, txtUser5), //
+ _BINFO(login, m0), //
+ _BINFO(login, chooseUsr), //
+ _BINFO(login, cUsrName), //
+ //
+ _BINFO(main, main), //
+ _BINFO(main, acidch0), //
+ _BINFO(main, MenuButton), //
+ _BINFO(main, acidname0), //
+ _BINFO(main, acideval0), //
+ _BINFO(main, sysInfo), //
+ _BINFO(main, clock), //
+ _BINFO(main, acidname0id), //
+ _BINFO(main, acidname1id), //
+ _BINFO(main, acidname2id), //
+ _BINFO(main, acidname3id), //
+ _BINFO(main, RemoterS), //
+ _BINFO(main, AcidState), //
+ _BINFO(main, RunMode), //
+ _BINFO(main, RunModeVal), //
+ _BINFO(main, acidch1), //
+ _BINFO(main, acidname1), //
+ _BINFO(main, acideval1), //
+ _BINFO(main, acidch2), //
+ _BINFO(main, acidname2), //
+ _BINFO(main, acideval2), //
+ _BINFO(main, acidch3), //
+ _BINFO(main, acidname3), //
+ _BINFO(main, acideval3), //
+ //
+ _BINFO(keybAcidCh, keybAcidCh), //
+ _BINFO(keybAcidCh, bak), //
+ _BINFO(keybAcidCh, b0), //
+ _BINFO(keybAcidCh, b1), //
+ _BINFO(keybAcidCh, b2), //
+ _BINFO(keybAcidCh, b3), //
+ _BINFO(keybAcidCh, b4), //
+ _BINFO(keybAcidCh, b5), //
+ _BINFO(keybAcidCh, b6), //
+ _BINFO(keybAcidCh, b7), //
+ _BINFO(keybAcidCh, b8), //
+ _BINFO(keybAcidCh, b9), //
+ _BINFO(keybAcidCh, b10), //
+ _BINFO(keybAcidCh, b11), //
+ _BINFO(keybAcidCh, b12), //
+ _BINFO(keybAcidCh, b13), //
+ _BINFO(keybAcidCh, b14), //
+ _BINFO(keybAcidCh, loadpageid), //
+ _BINFO(keybAcidCh, loadcmpid), //
+ _BINFO(keybAcidCh, loadcmname), //
+ _BINFO(keybAcidCh, txt), //
+ _BINFO(keybAcidCh, fn0), //
+ //
+ _BINFO(menuAdmin, menuAdmin), //
+ _BINFO(menuAdmin, home), //
+ _BINFO(menuAdmin, muInterval), //
+ _BINFO(menuAdmin, changePasswd), //
+ _BINFO(menuAdmin, muTmrMgr), //
+ _BINFO(menuAdmin, muAcidType), //
+ _BINFO(menuAdmin, muUsrMgr), //
+ _BINFO(menuAdmin, muSettings), //
+ _BINFO(menuAdmin, muAudit), //
+ _BINFO(menuAdmin, muDeviceInfo), //
+ _BINFO(menuAdmin, unlogin), //
+ //
+ _BINFO(menuAdmin2, menuAdmin2), //
+ _BINFO(menuAdmin2, home), //
+ _BINFO(menuAdmin2, muInterval), //
+ _BINFO(menuAdmin2, changePasswd), //
+ _BINFO(menuAdmin2, muAcidType), //
+ _BINFO(menuAdmin2, muUsrMgr), //
+ _BINFO(menuAdmin2, muSettings), //
+ _BINFO(menuAdmin2, muDeviceInfo), //
+ _BINFO(menuAdmin2, unlogin), //
+ //
+ _BINFO(menuUsr, menuUsr), //
+ _BINFO(menuUsr, home), //
+ _BINFO(menuUsr, muInterval), //
+ _BINFO(menuUsr, changePasswd), //
+ _BINFO(menuUsr, muDeviceInfo), //
+ _BINFO(menuUsr, unlogin), //
+ //
+ _BINFO(muInterval, muInterval), //
+ _BINFO(muInterval, t0), //
+ _BINFO(muInterval, t1), //
+ _BINFO(muInterval, bak), //
+ _BINFO(muInterval, frompage), //
+ _BINFO(muInterval, stAcidInte), //
+ _BINFO(muInterval, t2), //
+ //
+ _BINFO(muUsrMgr, muUsrMgr), //
+ _BINFO(muUsrMgr, bak), //
+ _BINFO(muUsrMgr, t0), //
+ _BINFO(muUsrMgr, t2), //
+ _BINFO(muUsrMgr, t3), //
+ _BINFO(muUsrMgr, t4), //
+ _BINFO(muUsrMgr, sw1), //
+ _BINFO(muUsrMgr, t6), //
+ _BINFO(muUsrMgr, sw2), //
+ _BINFO(muUsrMgr, t8), //
+ _BINFO(muUsrMgr, sw3), //
+ _BINFO(muUsrMgr, t10), //
+ _BINFO(muUsrMgr, sw4), //
+ _BINFO(muUsrMgr, t12), //
+ _BINFO(muUsrMgr, b1), //
+ _BINFO(muUsrMgr, b0), //
+ _BINFO(muUsrMgr, b2), //
+ _BINFO(muUsrMgr, b3), //
+ _BINFO(muUsrMgr, frompage), //
+ //
+ _BINFO(muTmrMgr, muTmrMgr), //
+ _BINFO(muTmrMgr, select0), //
+ _BINFO(muTmrMgr, select1), //
+ _BINFO(muTmrMgr, select2), //
+ _BINFO(muTmrMgr, bak), //
+ _BINFO(muTmrMgr, select3), //
+ _BINFO(muTmrMgr, select4), //
+ _BINFO(muTmrMgr, select5), //
+ _BINFO(muTmrMgr, b0), //
+ _BINFO(muTmrMgr, frompage), //
+ //
+ _BINFO(muAcidType, muAcidType), //
+ _BINFO(muAcidType, bak), //
+ _BINFO(muAcidType, t1), //
+ _BINFO(muAcidType, t2), //
+ _BINFO(muAcidType, t3), //
+ _BINFO(muAcidType, t4), //
+ _BINFO(muAcidType, t5), //
+ _BINFO(muAcidType, t6), //
+ _BINFO(muAcidType, t7), //
+ _BINFO(muAcidType, t8), //
+ _BINFO(muAcidType, t9), //
+ _BINFO(muAcidType, t10), //
+ _BINFO(muAcidType, t11), //
+ _BINFO(muAcidType, t12), //
+ _BINFO(muAcidType, t13), //
+ _BINFO(muAcidType, t14), //
+ _BINFO(muAcidType, t15), //
+ _BINFO(muAcidType, frompage), //
+ //
+ _BINFO(muSettings, muSettings), //
+ _BINFO(muSettings, t0), //
+ _BINFO(muSettings, t1), //
+ _BINFO(muSettings, bak), //
+ _BINFO(muSettings, frompage), //
+ _BINFO(muSettings, stAcidInte), //
+ _BINFO(muSettings, t2), //
+ //
+ _BINFO(muDeviceInfo, muDeviceInfo), //
+ _BINFO(muDeviceInfo, bak), //
+ _BINFO(muDeviceInfo, t2), //
+ _BINFO(muDeviceInfo, t3), //
+ _BINFO(muDeviceInfo, t6), //
+ _BINFO(muDeviceInfo, t7), //
+ _BINFO(muDeviceInfo, t10), //
+ _BINFO(muDeviceInfo, t11), //
+ _BINFO(muDeviceInfo, frompage), //
+ //
+ _BINFO(muAudit, muAudit), //
+ _BINFO(muAudit, bak), //
+ _BINFO(muAudit, t0), //
+ _BINFO(muAudit, t1), //
+ _BINFO(muAudit, t2), //
+ _BINFO(muAudit, b0), //
+ _BINFO(muAudit, b1), //
+ _BINFO(muAudit, frompage), //
+ //
+ _BINFO(alert, alert), //
+ _BINFO(alert, t0), //
+ _BINFO(alert, confirmkey), //
+ _BINFO(alert, info), //
+ _BINFO(alert, frompage), //
+ //
+ _BINFO(confirm, confirm), //
+ _BINFO(confirm, t0), //
+ _BINFO(confirm, confirmkey), //
+ _BINFO(confirm, info), //
+ _BINFO(confirm, canclekey), //
+ _BINFO(confirm, frompage), //
+ //
+ _BINFO(changePasswd, changePasswd), //
+ _BINFO(changePasswd, t2), //
+ _BINFO(changePasswd, t3), //
+ _BINFO(changePasswd, t4), //
+ _BINFO(changePasswd, t5), //
+ _BINFO(changePasswd, b0), //
+ _BINFO(changePasswd, b1), //
+ _BINFO(changePasswd, t0), //
+ _BINFO(changePasswd, t1), //
+ _BINFO(changePasswd, frompage), //
+ //
+ _BINFO(keybdB, keybdB), //
+ _BINFO(keybdB, b0), //
+ _BINFO(keybdB, show), //
+ _BINFO(keybdB, b210), //
+ _BINFO(keybdB, b1), //
+ _BINFO(keybdB, b2), //
+ _BINFO(keybdB, b3), //
+ _BINFO(keybdB, b4), //
+ _BINFO(keybdB, b5), //
+ _BINFO(keybdB, b6), //
+ _BINFO(keybdB, b7), //
+ _BINFO(keybdB, b8), //
+ _BINFO(keybdB, b200), //
+ _BINFO(keybdB, b9), //
+ _BINFO(keybdB, loadpageid), //
+ _BINFO(keybdB, tm0), //
+ _BINFO(keybdB, loadcmpid), //
+ _BINFO(keybdB, input), //
+ _BINFO(keybdB, temp), //
+ _BINFO(keybdB, inputlenth), //
+ _BINFO(keybdB, t2), //
+ _BINFO(keybdB, b251), //
+ _BINFO(keybdB, temp2), //
+ _BINFO(keybdB, tempstr), //
+ _BINFO(keybdB, b10), //
+ _BINFO(keybdB, b11), //
+ _BINFO(keybdB, loadcmname), //
+ //
+ _BINFO(keybdAP, keybdAP), //
+ _BINFO(keybdAP, loadpageid), //
+ _BINFO(keybdAP, loadcmpid), //
+ _BINFO(keybdAP, b0), //
+ _BINFO(keybdAP, b251), //
+ _BINFO(keybdAP, b210), //
+ _BINFO(keybdAP, b1), //
+ _BINFO(keybdAP, b2), //
+ _BINFO(keybdAP, b3), //
+ _BINFO(keybdAP, b4), //
+ _BINFO(keybdAP, b5), //
+ _BINFO(keybdAP, b6), //
+ _BINFO(keybdAP, b7), //
+ _BINFO(keybdAP, b8), //
+ _BINFO(keybdAP, b200), //
+ _BINFO(keybdAP, b20), //
+ _BINFO(keybdAP, b21), //
+ _BINFO(keybdAP, b22), //
+ _BINFO(keybdAP, b23), //
+ _BINFO(keybdAP, b24), //
+ _BINFO(keybdAP, b25), //
+ _BINFO(keybdAP, b26), //
+ _BINFO(keybdAP, b27), //
+ _BINFO(keybdAP, b28), //
+ _BINFO(keybdAP, b220), //
+ _BINFO(keybdAP, b40), //
+ _BINFO(keybdAP, b41), //
+ _BINFO(keybdAP, b42), //
+ _BINFO(keybdAP, b43), //
+ _BINFO(keybdAP, b44), //
+ _BINFO(keybdAP, b45), //
+ _BINFO(keybdAP, b46), //
+ _BINFO(keybdAP, b230), //
+ _BINFO(keybdAP, b240), //
+ _BINFO(keybdAP, b242), //
+ _BINFO(keybdAP, b241), //
+ _BINFO(keybdAP, b244), //
+ _BINFO(keybdAP, b231), //
+ _BINFO(keybdAP, b245), //
+ _BINFO(keybdAP, refshowbu), //
+ _BINFO(keybdAP, tm0), //
+ _BINFO(keybdAP, input), //
+ _BINFO(keybdAP, show), //
+ _BINFO(keybdAP, temp), //
+ _BINFO(keybdAP, inputlenth), //
+ _BINFO(keybdAP, b249), //
+ _BINFO(keybdAP, b201), //
+ _BINFO(keybdAP, b9), //
+ _BINFO(keybdAP, b232), //
+ _BINFO(keybdAP, b243), //
+ _BINFO(keybdAP, pa_z), //
+ _BINFO(keybdAP, pa_d), //
+ _BINFO(keybdAP, pastr1), //
+ _BINFO(keybdAP, ii), //
+ _BINFO(keybdAP, loadpa), //
+ _BINFO(keybdAP, pastr0), //
+ _BINFO(keybdAP, bp1), //
+ _BINFO(keybdAP, bp2), //
+ _BINFO(keybdAP, bp3), //
+ _BINFO(keybdAP, bp4), //
+ _BINFO(keybdAP, bp5), //
+ _BINFO(keybdAP, bp6), //
+ _BINFO(keybdAP, bp7), //
+ _BINFO(keybdAP, bp8), //
+ _BINFO(keybdAP, bp9), //
+ _BINFO(keybdAP, bp10), //
+ _BINFO(keybdAP, bp11), //
+ _BINFO(keybdAP, bp12), //
+ _BINFO(keybdAP, bp13), //
+ _BINFO(keybdAP, bp14), //
+ _BINFO(keybdAP, bp15), //
+ _BINFO(keybdAP, bp16), //
+ _BINFO(keybdAP, bp17), //
+ _BINFO(keybdAP, bp18), //
+ _BINFO(keybdAP, b10), //
+ _BINFO(keybdAP, b11), //
+ _BINFO(keybdAP, temp2), //
+ _BINFO(keybdAP, tempstr), //
+ _BINFO(keybdAP, loadcmname), //
+ //
+ _BINFO(keybdA, keybdA), //
+ _BINFO(keybdA, loadpageid), //
+ _BINFO(keybdA, loadcmpid), //
+ _BINFO(keybdA, b0), //
+ _BINFO(keybdA, b251), //
+ _BINFO(keybdA, b210), //
+ _BINFO(keybdA, b1), //
+ _BINFO(keybdA, b2), //
+ _BINFO(keybdA, b3), //
+ _BINFO(keybdA, b4), //
+ _BINFO(keybdA, b5), //
+ _BINFO(keybdA, b6), //
+ _BINFO(keybdA, b7), //
+ _BINFO(keybdA, b8), //
+ _BINFO(keybdA, b200), //
+ _BINFO(keybdA, b20), //
+ _BINFO(keybdA, b21), //
+ _BINFO(keybdA, b22), //
+ _BINFO(keybdA, b23), //
+ _BINFO(keybdA, b24), //
+ _BINFO(keybdA, b25), //
+ _BINFO(keybdA, b26), //
+ _BINFO(keybdA, b27), //
+ _BINFO(keybdA, b28), //
+ _BINFO(keybdA, b220), //
+ _BINFO(keybdA, b40), //
+ _BINFO(keybdA, b41), //
+ _BINFO(keybdA, b42), //
+ _BINFO(keybdA, b43), //
+ _BINFO(keybdA, b44), //
+ _BINFO(keybdA, b45), //
+ _BINFO(keybdA, b46), //
+ _BINFO(keybdA, b230), //
+ _BINFO(keybdA, b240), //
+ _BINFO(keybdA, b242), //
+ _BINFO(keybdA, b241), //
+ _BINFO(keybdA, b243), //
+ _BINFO(keybdA, b231), //
+ _BINFO(keybdA, b244), //
+ _BINFO(keybdA, refshow), //
+ _BINFO(keybdA, tm0), //
+ _BINFO(keybdA, input), //
+ _BINFO(keybdA, show), //
+ _BINFO(keybdA, temp), //
+ _BINFO(keybdA, inputlenth), //
+ _BINFO(keybdA, b249), //
+ _BINFO(keybdA, b201), //
+ _BINFO(keybdA, b9), //
+ _BINFO(keybdA, b232), //
+ _BINFO(keybdA, tempstr), //
+ _BINFO(keybdA, temp2), //
+ _BINFO(keybdA, loadcmname), //
+ //
+ _BINFO(keyPasswd, keyPasswd), //
+ _BINFO(keyPasswd, b0), //
+ _BINFO(keyPasswd, show), //
+ _BINFO(keyPasswd, b210), //
+ _BINFO(keyPasswd, b1), //
+ _BINFO(keyPasswd, b2), //
+ _BINFO(keyPasswd, b3), //
+ _BINFO(keyPasswd, b4), //
+ _BINFO(keyPasswd, b5), //
+ _BINFO(keyPasswd, b6), //
+ _BINFO(keyPasswd, b7), //
+ _BINFO(keyPasswd, b8), //
+ _BINFO(keyPasswd, b200), //
+ _BINFO(keyPasswd, b9), //
+ _BINFO(keyPasswd, loadpageid), //
+ _BINFO(keyPasswd, tm0), //
+ _BINFO(keyPasswd, loadcmpid), //
+ _BINFO(keyPasswd, input), //
+ _BINFO(keyPasswd, temp), //
+ _BINFO(keyPasswd, inputlenth), //
+ _BINFO(keyPasswd, t2), //
+ _BINFO(keyPasswd, b251), //
+ _BINFO(keyPasswd, temp2), //
+ _BINFO(keyPasswd, tempstr), //
+ _BINFO(keyPasswd, b249), //
+ _BINFO(keyPasswd, loadcmname), //
+};
+//
+
+const char* uimarco2str(uint8_t pid, uint8_t bid) {
+ for (int i = 0; i < sizeof(infos) / sizeof(infos[0]); i++) {
+ if (infos[i].pid == pid && infos[i].bid == bid) {
+ return infos[i].info;
+ }
+ }
+ return "unknownUiMarco";
+}
+const char* pageName(uint8_t pid) {
+ for (int i = 0; i < sizeof(infos) / sizeof(infos[0]); i++) {
+ if (infos[i].pid == pid) {
+ return infos[i].pids;
+ }
+ }
+ return "unknownPage";
+}
+
+#define PT_ENUM(key) \
+ case key: \
+ return #key;
+
+const char* pt2str(uint8_t type) {
+ switch (type) {
+ PT_ENUM(kpt_sys_ecode_invalid)
+ PT_ENUM(kpt_sys_ecode_suc)
+ PT_ENUM(kpt_sys_ecode_invalid_control_id)
+ PT_ENUM(kpt_sys_ecode_invalid_page_id)
+ PT_ENUM(kpt_sys_ecode_invalid_image_id)
+ PT_ENUM(kpt_sys_ecode_invalid_font_id)
+ PT_ENUM(kpt_sys_ecode_file_op_failed)
+ PT_ENUM(kpt_sys_ecode_crc_failed)
+ PT_ENUM(kpt_sys_ecode_invalid_baudrate)
+ PT_ENUM(kpt_sys_ecode_invalid_curve_id)
+ PT_ENUM(kpt_sys_ecode_invalid_var_name)
+ PT_ENUM(kpt_sys_ecode_invalid_var_op)
+ PT_ENUM(kpt_sys_ecode_var_op_failed)
+ PT_ENUM(kpt_sys_ecode_flash_op_failed)
+ PT_ENUM(kpt_sys_ecode_invalid_param_num)
+ PT_ENUM(kpt_sys_ecode_io_op_failed)
+ PT_ENUM(kpt_sys_ecode_escape_char_failed)
+ PT_ENUM(kpt_sys_ecode_var_name_too_long)
+ PT_ENUM(kpt_sys_ecode_serial_buf_overflow)
+ PT_ENUM(kpt_button_event)
+ PT_ENUM(kpt_sys_event_page_id)
+ PT_ENUM(kpt_sys_event_touch_data)
+ PT_ENUM(kpt_sys_event_sleep_touch)
+ PT_ENUM(kpt_sys_event_string_var)
+ PT_ENUM(kpt_sys_event_number_var)
+ PT_ENUM(kpt_sys_event_sleep_mode)
+ PT_ENUM(kpt_sys_event_auto_wakeup)
+ PT_ENUM(kpt_sys_event_sys_start)
+ PT_ENUM(kpt_sys_event_sd_upgrade)
+ PT_ENUM(kpt_sys_event_passthrough_finish)
+ PT_ENUM(kpt_sys_event_passthrough_ready)
+ PT_ENUM(kpt_ack)
+ PT_ENUM(kpt_inputfield_content_change_event)
+ PT_ENUM(kpt_double_state_button_event)
+ PT_ENUM(kpt_login_request)
+ PT_ENUM(kpt_unlogin_request)
+
+ default:
+ return "unkown_event";
+ break;
+ }
+}
+
+} // namespace tjc
\ No newline at end of file
diff --git a/usrc/service/tjc/tjc_constant.hpp b/usrc/service/tjc/tjc_constant.hpp
new file mode 100644
index 0000000..e41c7bc
--- /dev/null
+++ b/usrc/service/tjc/tjc_constant.hpp
@@ -0,0 +1,141 @@
+#pragma once
+#include
+
+#include "../ui/ui.h"
+#include "uappbase/appcfg/appcfg.hpp"
+
+namespace tjc {
+
+/**
+ * @brief
+ *
+ * 约定
+ * 1.用户名最大长度为15
+ * 2.组件名称最大长度为14
+ * 3.页面名称最大长度为14
+ * 4.密码为纯数字6位数密码
+ *
+ */
+
+#define MAX_USR_PASSWD_LENGTH (6)
+#define ELEMENT_ID_MAX_SIZE 14
+#define TJC_MAX_PACKET_SIZE 256
+
+typedef enum {
+ /**
+ * @brief 错误码
+ */
+ kpt_sys_ecode_invalid = 0x00,
+ kpt_sys_ecode_suc = 0x01,
+ kpt_sys_ecode_invalid_control_id = 0x02,
+ kpt_sys_ecode_invalid_page_id = 0x03,
+ kpt_sys_ecode_invalid_image_id = 0x04,
+ kpt_sys_ecode_invalid_font_id = 0x05,
+ kpt_sys_ecode_file_op_failed = 0x06,
+ kpt_sys_ecode_crc_failed = 0x09,
+ kpt_sys_ecode_invalid_baudrate = 0x11,
+ kpt_sys_ecode_invalid_curve_id = 0x12,
+ kpt_sys_ecode_invalid_var_name = 0x1A,
+ kpt_sys_ecode_invalid_var_op = 0x1B,
+ kpt_sys_ecode_var_op_failed = 0x1C,
+ kpt_sys_ecode_flash_op_failed = 0x1D,
+ kpt_sys_ecode_invalid_param_num = 0x1E,
+ kpt_sys_ecode_io_op_failed = 0x1F,
+ kpt_sys_ecode_escape_char_failed = 0x20,
+ kpt_sys_ecode_var_name_too_long = 0x23,
+ kpt_sys_ecode_serial_buf_overflow = 0x24,
+ /**
+ * @brief 事件
+ */
+ kpt_button_event = 0x65, //
+ kpt_sys_event_page_id = 0x66,
+ kpt_sys_event_touch_data = 0x67,
+ kpt_sys_event_sleep_touch = 0x68,
+ kpt_sys_event_string_var = 0x70,
+ kpt_sys_event_number_var = 0x71,
+ kpt_sys_event_sleep_mode = 0x86,
+ kpt_sys_event_auto_wakeup = 0x87,
+ kpt_sys_event_sys_start = 0x88,
+ kpt_sys_event_sd_upgrade = 0x89,
+ kpt_sys_event_passthrough_finish = 0xFD,
+ kpt_sys_event_passthrough_ready = 0xFE,
+
+ /**
+ * @brief 用户消息回执
+ */
+ kpt_ack = 0xAA,
+ // kpt_button_event = 0xAB,
+ kpt_inputfield_content_change_event = 0xAC,
+ kpt_double_state_button_event = 0xAD,
+ kpt_login_request = 0xAE,
+ kpt_unlogin_request = 0xAF,
+
+} packet_type_t;
+
+typedef enum {
+ kbutton_release = 0,
+ kbutton_press = 1,
+} button_event_t;
+
+typedef struct {
+ int32_t eventId;
+ uint8_t pid;
+ uint8_t bid;
+ union {
+ // inputfield_content_event
+ struct {
+ char text[TJC_MAX_PACKET_SIZE];
+ } inputfield_content;
+
+ // kpt_usr_login_request
+ struct {
+ char usrName[MAX_USR_NAME_SIZE + 1];
+ char passwd[MAX_USR_PASSWD_LENGTH + 1];
+ } login_request;
+
+ // kpt_double_state_button_event
+ struct {
+ uint8_t val;
+ } double_state_button;
+
+ struct {
+ uint8_t val; // 0 抬起,1按下
+ } button_event;
+
+ } d;
+} tjc_usr_event_t;
+
+typedef enum {
+ k_button_release_event = 1,
+ k_input_confirm_event = 2,
+} usr_event_type_t;
+
+#define GVAR_triET "triET"
+#define GVAR_triBId "triBId"
+#define GVAR_triPageId "triPageId"
+
+const char* pt2str(uint8_t type);
+const char* uimarco2str(uint8_t pid, uint8_t bid);
+const char* pageName(uint8_t page);
+
+#define UI_UUID(pgid, obid) ((pg_##pgid << 8) + ob_##pgid##_##obid)
+
+/***********************************************************************************************************************
+ * PublicPageName *
+ ***********************************************************************************************************************/
+
+/**
+ * @brief
+ *
+ * Page:
+ * "alert"
+ * Var:
+ * alert.frompage
+ * alert.info
+ *
+ *
+ *
+ *
+ */
+
+} // namespace tjc
diff --git a/usrc/service/ui_scheduler.cpp b/usrc/service/ui_scheduler.cpp
new file mode 100644
index 0000000..deb75d1
--- /dev/null
+++ b/usrc/service/ui_scheduler.cpp
@@ -0,0 +1,396 @@
+#include "ui_scheduler.hpp"
+
+#include
+#include
+#include
+#include
+
+#include "tjc/tjc_constant.hpp"
+using namespace iflytop;
+#define CMD_OVERTIME 50
+
+#define DEBUG 1
+static ZThread uart_rx_thread;
+static ZThread rx_processed_thread;
+
+static ZQueue ackQueue;
+static ZQueue eventQueue;
+static ZThread usartRxThread;
+static ZThread eventProcessThread;
+static bool m_isWaitingForAck;
+static UART_HandleTypeDef* tjcUart;
+
+#define TAG "UIScheduler"
+
+static const char* zhex2str(uint8_t* data, size_t len) {
+ static char buf[256];
+ memset(buf, 0, sizeof(buf));
+ for (size_t i = 0; i < len; i++) {
+ sprintf(buf + i * 2, "%02X", data[i]);
+ }
+ return buf;
+}
+
+void UIScheduler::initialize() { //
+ ackQueue.initialize(5, sizeof(tjc_rx_packet_t));
+ eventQueue.initialize(5, sizeof(tjc_rx_packet_t));
+ usartRxThread.init("usartRxThread", 1024);
+ eventProcessThread.init("eventProcessThread", 1024);
+
+ tjcUart = AppHardware::ins()->tjcUart;
+ m_cmdlock.init();
+}
+#define UART_RX_OVERTIME 5
+void UIScheduler::startSchedule() {
+ usartRxThread.start([this]() {
+ static uint8_t rxbuf[128];
+ tjcUart->USR_UartITRxing = 1;
+ tjcUart->USR_UartITRxBuf = rxbuf;
+ tjcUart->USR_UartITRxBufSize = 128;
+ tjcUart->USR_UartITRxOff = 0;
+ HAL_UART_Receive_IT(tjcUart, &tjcUart->USR_UartITRxBufCache, 1);
+ while (1) {
+ static uint8_t processbuf[128];
+ int32_t rxsize = 0;
+ if (tjcUart->USR_UartITRxOff != 0 && zos_haspassedms(tjcUart->USR_UartITLastRxTicket) > UART_RX_OVERTIME) {
+ vPortEnterCritical();
+ if (tjcUart->USR_UartITRxOff != 0 && zos_haspassedms(tjcUart->USR_UartITLastRxTicket) > UART_RX_OVERTIME) {
+ memcpy(processbuf, tjcUart->USR_UartITRxBuf, tjcUart->USR_UartITRxOff);
+ rxsize = tjcUart->USR_UartITRxOff;
+ tjcUart->USR_UartITRxOff = 0;
+ }
+ vPortExitCritical();
+ }
+
+ if (rxsize != 0) {
+ processScreenRxPacket(processbuf, rxsize);
+ }
+ osDelay(1);
+ }
+ });
+
+ eventProcessThread.start([this]() {
+ while (1) {
+ static tjc_rx_packet_t packet;
+ bool suc = eventQueue.receive(&packet, 10);
+ if (suc) {
+ memset(&event_cache, 0, sizeof(event_cache));
+ uint8_t packetType = packet.data[0];
+ if (packetType == tjc::kpt_inputfield_content_change_event) {
+ processUsrKeyboardConfirmEvent(packet.data, packet.datalen);
+ } else if (packetType == tjc::kpt_double_state_button_event) {
+ processUsrDoubleStateButtonEvent(packet.data, packet.datalen);
+ } else if (packetType == tjc::kpt_unlogin_request) {
+ event_cache.eventId = packet.data[0];
+ event_cache.pid = packet.data[1];
+ event_cache.bid = packet.data[2];
+ callUsrEventCb(&event_cache);
+ } else if (packetType == tjc::kpt_login_request) {
+ processLoginRequestEvent(packet.data, packet.datalen);
+ } else if (tjc::kpt_button_event == packetType) {
+ event_cache.eventId = packet.data[0];
+ event_cache.pid = packet.data[1];
+ event_cache.bid = packet.data[2];
+ event_cache.d.button_event.val = packet.data[3];
+ callUsrEventCb(&event_cache);
+ } else if (tjc::kpt_sys_event_page_id == packetType) {
+ event_cache.eventId = packet.data[0];
+ event_cache.pid = packet.data[1];
+ event_cache.bid = 0;
+ callUsrEventCb(&event_cache);
+ } else {
+ event_cache.eventId = packet.data[0];
+ callUsrEventCb(&event_cache);
+ ZLOGI(TAG, "[eventprocess-thread]: rx_event:%s", tjc::pt2str(packetType));
+ }
+ }
+ osDelay(1);
+ }
+ });
+}
+
+// GVAR_triET
+// GVAR_triBId
+// GVAR_triPageId
+
+void UIScheduler::processScreenRxPacket(uint8_t* data, size_t len) {
+ // 判断包是否合法
+#if DEBUG
+ ZLOGI(TAG, "[rx-thread] : rx :%s(%d)", zhex2str(data, len), len);
+#endif
+
+ if (!(data[len - 1] == 0xff && data[len - 2] == 0xff && data[len - 3] == 0xff)) {
+ ZLOGI(TAG, "rx invalid packet %s", zhex2str(data, len));
+ return;
+ }
+ if (TJC_MAX_PACKET_SIZE < len) {
+ ZLOGI(TAG, "rx invalid packet(tool long) %s", zhex2str(data, len));
+ return;
+ }
+
+ uint8_t packetType = data[0];
+
+ static tjc_rx_packet_t packet;
+ packet.datalen = len;
+ memcpy(packet.data, data, len);
+ if (tjc::kpt_ack == packetType) {
+ if (m_isWaitingForAck) {
+ bool suc = ackQueue.send(&packet, 10);
+ if (!suc) {
+ ZLOGI(TAG, "ackQueue send failed");
+ }
+ m_isWaitingForAck = false;
+ }
+
+ } else {
+ bool suc = eventQueue.send(&packet, 10);
+ if (!suc) {
+ ZLOGI(TAG, "eventQueue send failed");
+ }
+ }
+}
+
+void UIScheduler::regOnUsrEventCb(on_usr_event_cb_t cb) {
+ m_cb[m_ncb] = cb;
+ m_ncb++;
+}
+
+static const char* zcpystr(char* cpyto, const char* strbegin, int32_t maxlen) {
+ if (strbegin == NULL) return NULL;
+ int32_t i = 0;
+ for (i = 0; i < maxlen; i++) {
+ cpyto[i] = strbegin[i];
+ if (strbegin[i] == 0) {
+ return &strbegin[i + 1];
+ }
+ }
+ return NULL;
+}
+void UIScheduler::processUsrButtonEvent(uint8_t* data, size_t len) {
+ /**
+ * @brief
+ * 指令格式:
+ * printh 65
+ * prints dp,1
+ * prints '&id&',1
+ * printh FF FF FF
+ *
+ * AB Page cidName/0 FF FF FF
+ *
+ */
+ // ButtonEventContext_t buttonEventCxt;
+
+ // event_cache
+ memset(&event_cache, 0, sizeof(event_cache));
+ event_cache.eventId = data[0];
+ event_cache.pid = data[1];
+ event_cache.bid = data[2];
+
+ callUsrEventCb(&event_cache);
+}
+void UIScheduler::processUsrDoubleStateButtonEvent(uint8_t* data, size_t len) {
+ /**
+ * @brief
+ * 指令格式:
+ * printh AD
+ * prints dp,1
+ * prints '&id&',1
+ * prints '&val&',1
+ * printh FF FF FF
+ *
+ * AB Page cidName/0 FF FF FF
+ *
+ */
+ // ButtonEventContext_t buttonEventCxt;
+
+ // event_cache
+ memset(&event_cache, 0, sizeof(event_cache));
+ event_cache.eventId = data[0];
+ event_cache.pid = data[1];
+ event_cache.bid = data[2];
+ event_cache.d.double_state_button.val = data[3];
+
+ callUsrEventCb(&event_cache);
+}
+void UIScheduler::callUsrEventCb(tjc::tjc_usr_event_t* event) {
+ for (int32_t i = 0; i < m_ncb; i++) {
+ m_cb[i](event);
+ }
+}
+
+void UIScheduler::processUsrKeyboardConfirmEvent(uint8_t* data, size_t len) {
+ /**
+ * @brief
+ *
+ * printh AC
+ * prints loadpageid.val,1
+ * prints loadcmpid.val,1
+ * prints p[loadpageid.val].b[loadcmpid.val].txt,0
+ * printh 00
+ * printh FF FF FF
+ * page loadpageid.val
+ *
+ */
+ // ZLOGI(TAG, "processUsrKeyboardConfirmEvent");
+ memset(&event_cache, 0, sizeof(event_cache));
+ event_cache.eventId = data[0];
+ event_cache.pid = data[1];
+ event_cache.bid = data[2];
+ const char* strbegin = (const char*)&data[3];
+ strbegin = zcpystr(event_cache.d.inputfield_content.text, strbegin, sizeof(event_cache.d.inputfield_content.text));
+ callUsrEventCb(&event_cache);
+}
+
+void UIScheduler::processLoginRequestEvent(uint8_t* data, size_t len) {
+ /*
+ * printh AE
+ * prints dp,1
+ * prints '&id&',1
+ * prints cUsrName.txt,0
+ * printh 00
+ * prints txt_passwd.txt,0
+ * printh 00
+ * printh FF FF FF
+ */
+
+ // ZLOGI(TAG, "processLoginRequestEvent");
+ memset(&event_cache, 0, sizeof(event_cache));
+ event_cache.eventId = data[0];
+ event_cache.pid = data[1];
+ event_cache.bid = data[2];
+ const char* strbegin = (const char*)&data[3];
+ strbegin = zcpystr(event_cache.d.login_request.usrName, strbegin, MAX_USR_NAME_SIZE);
+ strbegin = zcpystr(event_cache.d.login_request.passwd, strbegin, MAX_USR_PASSWD_LENGTH);
+
+ callUsrEventCb(&event_cache);
+}
+
+bool UIScheduler::readTxt(uint8_t pid, uint8_t cId, char* txt, int32_t txtbuflen) {
+ zlock_guard lg(m_cmdlock);
+
+ startReceiveAck();
+ sendcmd("com_stop");
+ sendcmd("printh AA");
+ sendcmd("prints p[%d].b[%d].txt,0", pid, cId);
+ sendcmd("printh 00");
+ sendcmd("printh FF FF FF");
+ sendcmd("com_start");
+
+ bool suc = ackQueue.receive(&ackcache, CMD_OVERTIME);
+ if (!suc) {
+ ZLOGI(TAG, "readTxt failed");
+ return false;
+ }
+ int32_t cpysize = ackcache.datalen - 3;
+ if (cpysize > txtbuflen) {
+ cpysize = txtbuflen - 1;
+ }
+
+ memcpy(txt, &ackcache.data[1], cpysize);
+ return true;
+}
+bool UIScheduler::readInt(uint8_t pid, uint8_t cId, int32_t* val) {
+ zlock_guard lg(m_cmdlock);
+
+ startReceiveAck();
+ sendcmd("com_stop");
+ sendcmd("printh AA");
+ sendcmd("prints p[%d].b[%d].val,4", pid, cId);
+ sendcmd("printh FF FF FF");
+ sendcmd("com_start");
+
+ bool suc = ackQueue.receive(&ackcache, CMD_OVERTIME);
+ if (!suc) {
+ ZLOGI(TAG, "readTxt failed");
+ return false;
+ }
+
+ uint8_t int32val[4] = {0};
+ memcpy(int32val, &ackcache.data[1], 4);
+ *val = *(int32_t*)int32val;
+ return true;
+}
+
+bool UIScheduler::setVal(uint8_t pid, uint8_t bid, const char* txt, ...) {
+ zlock_guard lg(m_cmdlock);
+
+ va_list args;
+ va_start(args, txt);
+ static char buf[128];
+ vsprintf(buf, txt, args);
+ va_end(args);
+
+ sendcmd("p[%d].b[%d].txt=\"%s\"", pid, bid, buf);
+ return true;
+}
+bool UIScheduler::setVal(uint8_t pid, uint8_t cid, int32_t val) {
+ zlock_guard lg(m_cmdlock);
+ sendcmd("p[%d].b[%d].val=%d", pid, cid, val);
+ return true;
+}
+bool UIScheduler::vis(uint16_t buuid, int32_t val) {
+ zlock_guard lg(m_cmdlock);
+ sendcmd("vis %d,%d", buuid & 0xff, val);
+ return true;
+}
+
+void UIScheduler::alert(const char* info, ...) {
+ zlock_guard lg(m_cmdlock);
+
+ va_list args;
+ va_start(args, info);
+ static char buf[128];
+ vsprintf(buf, info, args);
+
+ sendcmd("p[%d].b[%d].val=dp", pg_alert, ob_alert_frompage);
+ sendcmd("p[%d].b[%d].txt=\"%s\"", pg_alert, ob_alert_info, buf);
+ sendcmd("page alert");
+}
+void UIScheduler::chpage(uint8_t page) { sendcmd("page %d", page); }
+
+void UIScheduler::sendcmd(const char* format, ...) {
+ static char buf[128];
+ va_list args;
+ va_start(args, format);
+ vsprintf(buf, format, args);
+ va_end(args);
+
+ uint8_t len = strlen(buf);
+ if (len > (128 - 3)) {
+ ZLOGI(TAG, "sendcmd too long");
+ return;
+ }
+
+ buf[len] = 0xff;
+ buf[len + 1] = 0xff;
+ buf[len + 2] = 0xff;
+
+ HAL_UART_Transmit(tjcUart, (uint8_t*)buf, len + 3, 100);
+ while (true) {
+ osDelay(1);
+ if (tjcUart->gState == HAL_UART_STATE_READY) {
+ return;
+ }
+ }
+}
+
+void UIScheduler::startReceiveAck() {
+ ackQueue.clear();
+ m_isWaitingForAck = true;
+}
+
+void UIScheduler::virtualClick(uint8_t pid, uint8_t bid, uint8_t event) {
+ zlock_guard lg(m_cmdlock);
+ sendcmd("click b[%d],%d", bid, event);
+}
+
+void UIScheduler::setTouchEnableState(uint8_t bid, uint8_t enable) {
+ // tsw obj,state
+ zlock_guard lg(m_cmdlock);
+ sendcmd("tsw b[%d],%d", bid, enable);
+}
+
+void UIScheduler::setEnumComponentState(uint8_t pid, uint8_t bid, int32_t state) {
+ // 枚举类型使用动画组件
+ sendcmd("p[%d].b[%d].tim=%d", pid, bid, state * 50);
+}
diff --git a/usrc/service/ui_scheduler.hpp b/usrc/service/ui_scheduler.hpp
new file mode 100644
index 0000000..6ff82fd
--- /dev/null
+++ b/usrc/service/ui_scheduler.hpp
@@ -0,0 +1,82 @@
+#pragma once
+#include "apphal/apphal.hpp"
+#include "apphal/apphardware.hpp"
+#include "uappbase/base.hpp"
+
+//
+#include "tjc/tjc.hpp"
+
+namespace iflytop {
+using namespace std;
+typedef struct {
+ uint8_t data[TJC_MAX_PACKET_SIZE];
+ uint16_t datalen;
+} tjc_rx_packet_t;
+
+typedef std::function on_usr_event_cb_t;
+
+#define UIS UIScheduler::ins()
+class UIScheduler {
+ ZThread m_thread;
+
+ tjc_rx_packet_t ackcache;
+ zmutex m_cmdlock;
+
+ tjc::tjc_usr_event_t event_cache;
+
+ // on_usr_event_cb_t cb;
+
+ on_usr_event_cb_t m_cb[50];
+ int32_t m_ncb = 0;
+
+ public:
+ UIScheduler() {};
+ ~UIScheduler() {};
+
+ static UIScheduler* ins() {
+ static UIScheduler instance;
+ return &instance;
+ }
+
+ void initialize();
+ void regOnUsrEventCb(on_usr_event_cb_t onclik);
+
+ void startSchedule();
+
+ // cmd list
+ bool readTxt(uint8_t pid, uint8_t bid, char* txt, int32_t txtbuflen);
+ bool readInt(uint8_t pid, uint8_t bid, int32_t* val);
+
+ bool setVal(uint8_t pid, uint8_t bid, const char* txt, ...);
+ bool setVal(uint8_t pid, uint8_t bid, int32_t val);
+
+ bool setVal(uint16_t buuid, const char* txt) { return setVal(buuid >> 8, buuid & 0xff, txt); }
+ bool setVal(uint16_t buuid, int32_t val) { return setVal(buuid >> 8, buuid & 0xff, val); }
+
+ bool vis(uint16_t buuid, int32_t val); // 不支持跨页面隐藏
+ // vis b0,0
+
+ bool readTxt(uint16_t buuid, char* txt, int32_t txtbuflen) { return readTxt(buuid >> 8, buuid & 0xff, txt, txtbuflen); }
+ bool readInt(uint16_t buuid, int32_t* val) { return readInt(buuid >> 8, buuid & 0xff, val); }
+
+ void alert(const char* info, ...);
+ void chpage(uint8_t page);
+ void virtualClick(uint8_t pid, uint8_t bid, uint8_t event);
+ void setTouchEnableState(uint8_t bid, uint8_t enable);
+
+ void setEnumComponentState(uint8_t pid, uint8_t bid, int32_t state);
+ void sendcmd(const char* format, ...);
+
+ private:
+ void processScreenRxPacket(uint8_t* data, size_t len);
+ void processUsrButtonEvent(uint8_t* data, size_t len);
+ void processUsrKeyboardConfirmEvent(uint8_t* data, size_t len);
+ void processUsrDoubleStateButtonEvent(uint8_t* data, size_t len);
+ void processLoginRequestEvent(uint8_t* data, size_t len);
+
+ void startReceiveAck();
+
+ void callUsrEventCb(tjc::tjc_usr_event_t* event);
+};
+
+} // namespace iflytop