From bacd56f7a0da1be74275d90a18b6403e9d88b763 Mon Sep 17 00:00:00 2001 From: zhaohe Date: Sun, 4 Feb 2024 23:58:49 +0800 Subject: [PATCH] update --- .vscode/settings.json | 3 +- app/app.uvoptx | 180 +++---- app/app.uvprojx | 46 +- app/src/app_event.h | 1 + app/src/app_event_distribute.c | 23 + app/src/app_event_distribute.h | 15 + app/src/ble_cmd_process_service.c | 467 ++++++++++++++++++ app/src/ble_cmd_process_service.h | 15 + app/src/board/board.h | 6 +- app/src/config.h | 3 + app/src/device_controler.c | 0 app/src/device_controler.h | 0 app/src/device_state.c | 27 + app/src/device_state.h | 92 ++++ app/src/display_manager.c | 442 +++++++++++++++++ app/src/display_manager.h | 81 +++ app/src/display_manager_res.h | 5 + app/src/font.h | 275 +++++++++++ app/src/heart_wave_sample_service.c | 183 +++++++ app/src/heart_wave_sample_service.h | 15 + app/src/one_conduction/app_event.h | 1 - app/src/one_conduction/ble_cmd_process_service.c | 461 ----------------- app/src/one_conduction/ble_cmd_process_service.h | 15 - app/src/one_conduction/config.h | 3 - app/src/one_conduction/device_controler.c | 0 app/src/one_conduction/device_controler.h | 0 app/src/one_conduction/device_state.c | 27 - app/src/one_conduction/device_state.h | 87 ---- app/src/one_conduction/display_manager.c | 442 ----------------- app/src/one_conduction/display_manager.h | 81 --- app/src/one_conduction/display_manager_res.h | 5 - app/src/one_conduction/font.h | 275 ----------- app/src/one_conduction/heart_wave_sample_service.c | 156 ------ app/src/one_conduction/heart_wave_sample_service.h | 15 - app/src/one_conduction/one_conduction_board.c | 401 --------------- app/src/one_conduction/one_conduction_board.h | 77 --- app/src/one_conduction/one_conduction_main.c | 449 ----------------- app/src/one_conduction/one_conduction_main.h | 4 - app/src/one_conduction/sample_data_manager.c | 83 ---- app/src/one_conduction/sample_data_manager.h | 47 -- app/src/one_conduction/zeeprom_fs.c | 543 --------------------- app/src/one_conduction/zeeprom_fs.h | 66 --- app/src/one_conduction_board.c | 401 +++++++++++++++ app/src/one_conduction_board.h | 77 +++ app/src/one_conduction_main.c | 458 +++++++++++++++++ app/src/one_conduction_main.h | 4 + app/src/sample_data_manager.c | 83 ++++ app/src/sample_data_manager.h | 47 ++ app/src/zeeprom_fs.c | 543 +++++++++++++++++++++ app/src/zeeprom_fs.h | 66 +++ 50 files changed, 3453 insertions(+), 3343 deletions(-) create mode 100644 app/src/app_event.h create mode 100644 app/src/app_event_distribute.c create mode 100644 app/src/app_event_distribute.h create mode 100644 app/src/ble_cmd_process_service.c create mode 100644 app/src/ble_cmd_process_service.h create mode 100644 app/src/config.h create mode 100644 app/src/device_controler.c create mode 100644 app/src/device_controler.h create mode 100644 app/src/device_state.c create mode 100644 app/src/device_state.h create mode 100644 app/src/display_manager.c create mode 100644 app/src/display_manager.h create mode 100644 app/src/display_manager_res.h create mode 100644 app/src/font.h create mode 100644 app/src/heart_wave_sample_service.c create mode 100644 app/src/heart_wave_sample_service.h delete mode 100644 app/src/one_conduction/app_event.h delete mode 100644 app/src/one_conduction/ble_cmd_process_service.c delete mode 100644 app/src/one_conduction/ble_cmd_process_service.h delete mode 100644 app/src/one_conduction/config.h delete mode 100644 app/src/one_conduction/device_controler.c delete mode 100644 app/src/one_conduction/device_controler.h delete mode 100644 app/src/one_conduction/device_state.c delete mode 100644 app/src/one_conduction/device_state.h delete mode 100644 app/src/one_conduction/display_manager.c delete mode 100644 app/src/one_conduction/display_manager.h delete mode 100644 app/src/one_conduction/display_manager_res.h delete mode 100644 app/src/one_conduction/font.h delete mode 100644 app/src/one_conduction/heart_wave_sample_service.c delete mode 100644 app/src/one_conduction/heart_wave_sample_service.h delete mode 100644 app/src/one_conduction/one_conduction_board.c delete mode 100644 app/src/one_conduction/one_conduction_board.h delete mode 100644 app/src/one_conduction/one_conduction_main.c delete mode 100644 app/src/one_conduction/one_conduction_main.h delete mode 100644 app/src/one_conduction/sample_data_manager.c delete mode 100644 app/src/one_conduction/sample_data_manager.h delete mode 100644 app/src/one_conduction/zeeprom_fs.c delete mode 100644 app/src/one_conduction/zeeprom_fs.h create mode 100644 app/src/one_conduction_board.c create mode 100644 app/src/one_conduction_board.h create mode 100644 app/src/one_conduction_main.c create mode 100644 app/src/one_conduction_main.h create mode 100644 app/src/sample_data_manager.c create mode 100644 app/src/sample_data_manager.h create mode 100644 app/src/zeeprom_fs.c create mode 100644 app/src/zeeprom_fs.h diff --git a/.vscode/settings.json b/.vscode/settings.json index 84890fb..d13aefa 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -92,7 +92,8 @@ "ble_cmd_process_service.h": "c", "heart_wave_sample_service.h": "c", "device_info_mgr.h": "c", - "znordic_device_info_mgr.h": "c" + "znordic_device_info_mgr.h": "c", + "device_state.h": "c" }, "files.encoding": "gbk" } \ No newline at end of file diff --git a/app/app.uvoptx b/app/app.uvoptx index c05a827..2b6d11b 100644 --- a/app/app.uvoptx +++ b/app/app.uvoptx @@ -398,7 +398,7 @@ 0 0 0 - .\src\one_conduction\one_conduction_board.c + .\src\one_conduction_board.c one_conduction_board.c 0 0 @@ -410,7 +410,7 @@ 0 0 0 - .\src\one_conduction\one_conduction_main.c + .\src\one_conduction_main.c one_conduction_main.c 0 0 @@ -458,7 +458,7 @@ 0 0 0 - .\src\one_conduction\device_controler.c + .\src\device_controler.c device_controler.c 0 0 @@ -470,7 +470,7 @@ 0 0 0 - .\src\one_conduction\display_manager.c + .\src\display_manager.c display_manager.c 0 0 @@ -506,7 +506,7 @@ 0 0 0 - .\src\one_conduction\sample_data_manager.c + .\src\sample_data_manager.c sample_data_manager.c 0 0 @@ -518,7 +518,7 @@ 0 0 0 - .\src\one_conduction\zeeprom_fs.c + .\src\zeeprom_fs.c zeeprom_fs.c 0 0 @@ -530,7 +530,7 @@ 0 0 0 - .\src\one_conduction\heart_wave_sample_service.c + .\src\heart_wave_sample_service.c heart_wave_sample_service.c 0 0 @@ -542,7 +542,7 @@ 0 0 0 - .\src\one_conduction\device_state.c + .\src\device_state.c device_state.c 0 0 @@ -554,7 +554,7 @@ 0 0 0 - .\src\one_conduction\ble_cmd_process_service.c + .\src\ble_cmd_process_service.c ble_cmd_process_service.c 0 0 @@ -595,6 +595,18 @@ 0 0 + + 1 + 20 + 1 + 0 + 0 + 0 + .\src\app_event_distribute.c + app_event_distribute.c + 0 + 0 + @@ -605,7 +617,7 @@ 0 2 - 20 + 21 1 0 0 @@ -625,7 +637,7 @@ 0 3 - 21 + 22 1 0 0 @@ -637,7 +649,7 @@ 3 - 22 + 23 1 0 0 @@ -657,7 +669,7 @@ 0 4 - 23 + 24 1 0 0 @@ -677,7 +689,7 @@ 0 5 - 24 + 25 1 0 0 @@ -689,7 +701,7 @@ 5 - 25 + 26 1 0 0 @@ -701,7 +713,7 @@ 5 - 26 + 27 1 0 0 @@ -713,7 +725,7 @@ 5 - 27 + 28 1 0 0 @@ -725,7 +737,7 @@ 5 - 28 + 29 1 0 0 @@ -737,7 +749,7 @@ 5 - 29 + 30 1 0 0 @@ -749,7 +761,7 @@ 5 - 30 + 31 1 0 0 @@ -761,7 +773,7 @@ 5 - 31 + 32 1 0 0 @@ -781,7 +793,7 @@ 0 6 - 32 + 33 1 0 0 @@ -801,7 +813,7 @@ 0 7 - 33 + 34 1 0 0 @@ -813,7 +825,7 @@ 7 - 34 + 35 1 0 0 @@ -825,7 +837,7 @@ 7 - 35 + 36 1 0 0 @@ -837,7 +849,7 @@ 7 - 36 + 37 1 0 0 @@ -849,7 +861,7 @@ 7 - 37 + 38 1 0 0 @@ -861,7 +873,7 @@ 7 - 38 + 39 1 0 0 @@ -873,7 +885,7 @@ 7 - 39 + 40 1 0 0 @@ -885,7 +897,7 @@ 7 - 40 + 41 1 0 0 @@ -897,7 +909,7 @@ 7 - 41 + 42 1 0 0 @@ -909,7 +921,7 @@ 7 - 42 + 43 1 0 0 @@ -921,7 +933,7 @@ 7 - 43 + 44 1 0 0 @@ -933,7 +945,7 @@ 7 - 44 + 45 1 0 0 @@ -945,7 +957,7 @@ 7 - 45 + 46 1 0 0 @@ -957,7 +969,7 @@ 7 - 46 + 47 1 0 0 @@ -969,7 +981,7 @@ 7 - 47 + 48 1 0 0 @@ -981,7 +993,7 @@ 7 - 48 + 49 1 0 0 @@ -993,7 +1005,7 @@ 7 - 49 + 50 1 0 0 @@ -1005,7 +1017,7 @@ 7 - 50 + 51 1 0 0 @@ -1017,7 +1029,7 @@ 7 - 51 + 52 1 0 0 @@ -1029,7 +1041,7 @@ 7 - 52 + 53 1 0 0 @@ -1049,7 +1061,7 @@ 0 8 - 53 + 54 1 0 0 @@ -1061,7 +1073,7 @@ 8 - 54 + 55 1 0 0 @@ -1073,7 +1085,7 @@ 8 - 55 + 56 1 0 0 @@ -1085,7 +1097,7 @@ 8 - 56 + 57 1 0 0 @@ -1097,7 +1109,7 @@ 8 - 57 + 58 1 0 0 @@ -1109,7 +1121,7 @@ 8 - 58 + 59 1 0 0 @@ -1121,7 +1133,7 @@ 8 - 59 + 60 1 0 0 @@ -1133,7 +1145,7 @@ 8 - 60 + 61 1 0 0 @@ -1145,7 +1157,7 @@ 8 - 61 + 62 1 0 0 @@ -1157,7 +1169,7 @@ 8 - 62 + 63 1 0 0 @@ -1169,7 +1181,7 @@ 8 - 63 + 64 1 0 0 @@ -1181,7 +1193,7 @@ 8 - 64 + 65 1 0 0 @@ -1193,7 +1205,7 @@ 8 - 65 + 66 1 0 0 @@ -1205,7 +1217,7 @@ 8 - 66 + 67 1 0 0 @@ -1217,7 +1229,7 @@ 8 - 67 + 68 1 0 0 @@ -1229,7 +1241,7 @@ 8 - 68 + 69 1 0 0 @@ -1241,7 +1253,7 @@ 8 - 69 + 70 1 0 0 @@ -1253,7 +1265,7 @@ 8 - 70 + 71 1 0 0 @@ -1265,7 +1277,7 @@ 8 - 71 + 72 1 0 0 @@ -1277,7 +1289,7 @@ 8 - 72 + 73 1 0 0 @@ -1289,7 +1301,7 @@ 8 - 73 + 74 1 0 0 @@ -1301,7 +1313,7 @@ 8 - 74 + 75 1 0 0 @@ -1313,7 +1325,7 @@ 8 - 75 + 76 1 0 0 @@ -1325,7 +1337,7 @@ 8 - 76 + 77 1 0 0 @@ -1337,7 +1349,7 @@ 8 - 77 + 78 1 0 0 @@ -1349,7 +1361,7 @@ 8 - 78 + 79 1 0 0 @@ -1361,7 +1373,7 @@ 8 - 79 + 80 1 0 0 @@ -1381,7 +1393,7 @@ 0 9 - 80 + 81 1 0 0 @@ -1393,7 +1405,7 @@ 9 - 81 + 82 1 0 0 @@ -1405,7 +1417,7 @@ 9 - 82 + 83 1 0 0 @@ -1417,7 +1429,7 @@ 9 - 83 + 84 1 0 0 @@ -1429,7 +1441,7 @@ 9 - 84 + 85 1 0 0 @@ -1441,7 +1453,7 @@ 9 - 85 + 86 1 0 0 @@ -1461,7 +1473,7 @@ 0 10 - 86 + 87 1 0 0 @@ -1473,7 +1485,7 @@ 10 - 87 + 88 1 0 0 @@ -1485,7 +1497,7 @@ 10 - 88 + 89 1 0 0 @@ -1505,7 +1517,7 @@ 0 11 - 89 + 90 1 0 0 @@ -1517,7 +1529,7 @@ 11 - 90 + 91 1 0 0 @@ -1529,7 +1541,7 @@ 11 - 91 + 92 1 0 0 @@ -1549,7 +1561,7 @@ 0 12 - 92 + 93 1 0 0 @@ -1569,7 +1581,7 @@ 0 13 - 93 + 94 1 0 0 @@ -1581,7 +1593,7 @@ 13 - 94 + 95 1 0 0 diff --git a/app/app.uvprojx b/app/app.uvprojx index d45fdb1..dbb6b38 100644 --- a/app/app.uvprojx +++ b/app/app.uvprojx @@ -396,12 +396,12 @@ one_conduction_board.c 1 - .\src\one_conduction\one_conduction_board.c + .\src\one_conduction_board.c one_conduction_main.c 1 - .\src\one_conduction\one_conduction_main.c + .\src\one_conduction_main.c driver_ssd1306.c @@ -421,12 +421,12 @@ device_controler.c 1 - .\src\one_conduction\device_controler.c + .\src\device_controler.c display_manager.c 1 - .\src\one_conduction\display_manager.c + .\src\display_manager.c fontlib.c @@ -441,27 +441,27 @@ sample_data_manager.c 1 - .\src\one_conduction\sample_data_manager.c + .\src\sample_data_manager.c zeeprom_fs.c 1 - .\src\one_conduction\zeeprom_fs.c + .\src\zeeprom_fs.c heart_wave_sample_service.c 1 - .\src\one_conduction\heart_wave_sample_service.c + .\src\heart_wave_sample_service.c device_state.c 1 - .\src\one_conduction\device_state.c + .\src\device_state.c ble_cmd_process_service.c 1 - .\src\one_conduction\ble_cmd_process_service.c + .\src\ble_cmd_process_service.c zble_module.c @@ -478,6 +478,11 @@ 1 ..\libznordic\src\znordic_device_info_mgr.c + + app_event_distribute.c + 1 + .\src\app_event_distribute.c + @@ -4220,12 +4225,12 @@ one_conduction_board.c 1 - .\src\one_conduction\one_conduction_board.c + .\src\one_conduction_board.c one_conduction_main.c 1 - .\src\one_conduction\one_conduction_main.c + .\src\one_conduction_main.c driver_ssd1306.c @@ -4245,12 +4250,12 @@ device_controler.c 1 - .\src\one_conduction\device_controler.c + .\src\device_controler.c display_manager.c 1 - .\src\one_conduction\display_manager.c + .\src\display_manager.c fontlib.c @@ -4265,27 +4270,27 @@ sample_data_manager.c 1 - .\src\one_conduction\sample_data_manager.c + .\src\sample_data_manager.c zeeprom_fs.c 1 - .\src\one_conduction\zeeprom_fs.c + .\src\zeeprom_fs.c heart_wave_sample_service.c 1 - .\src\one_conduction\heart_wave_sample_service.c + .\src\heart_wave_sample_service.c device_state.c 1 - .\src\one_conduction\device_state.c + .\src\device_state.c ble_cmd_process_service.c 1 - .\src\one_conduction\ble_cmd_process_service.c + .\src\ble_cmd_process_service.c zble_module.c @@ -4302,6 +4307,11 @@ 1 ..\libznordic\src\znordic_device_info_mgr.c + + app_event_distribute.c + 1 + .\src\app_event_distribute.c + diff --git a/app/src/app_event.h b/app/src/app_event.h new file mode 100644 index 0000000..cc128f6 --- /dev/null +++ b/app/src/app_event.h @@ -0,0 +1 @@ +#include "device_state.h" \ No newline at end of file diff --git a/app/src/app_event_distribute.c b/app/src/app_event_distribute.c new file mode 100644 index 0000000..07a00a6 --- /dev/null +++ b/app/src/app_event_distribute.c @@ -0,0 +1,23 @@ +#include "app_event_distribute.h" + +#include "app_event.h" +#include "app_scheduler.h" + +static AppEventListener m_listener[10]; +static int m_listener_num = 0; + +static void app_event_process_cb(void* p_event_data, uint16_t event_size) { + for (int i = 0; i < m_listener_num; i++) { + if (m_listener[i].cbfunc) { + m_listener[i].cbfunc(p_event_data, event_size); + } + } +} + +void AppEvent_regListener(app_event_listener_t listener) { // + m_listener[m_listener_num++].cbfunc = listener; +} + +void AppEvent_pushEvent(app_event_t* event) { // + app_sched_event_put(event, sizeof(app_event_t), app_event_process_cb); +} diff --git a/app/src/app_event_distribute.h b/app/src/app_event_distribute.h new file mode 100644 index 0000000..7f22132 --- /dev/null +++ b/app/src/app_event_distribute.h @@ -0,0 +1,15 @@ +#pragma once +#include +#include + +#include "app_event.h" + + +typedef void (*app_event_listener_t)(void* p_event_data, uint16_t event_size); + +typedef struct { + app_event_listener_t cbfunc; +} AppEventListener; + +void AppEvent_regListener(app_event_listener_t listener); +void AppEvent_pushEvent(app_event_t* event); diff --git a/app/src/ble_cmd_process_service.c b/app/src/ble_cmd_process_service.c new file mode 100644 index 0000000..34265c5 --- /dev/null +++ b/app/src/ble_cmd_process_service.c @@ -0,0 +1,467 @@ +#include "ble_cmd_process_service.h" + +#include "../../ify_hrs_protocol/heart_rate_sensor_protocol.h" +#include "board/board.h" +#include "config.h" +#include "one_conduction_board.h" +#include "sample_data_manager.h" +#include "zble_module.h" +#include "zdatachannel_service.h" +#include "znordic_device_info_mgr.h" + +APP_TIMER_DEF(m_record_upload_tmr); // 数据上报定时器 +APP_TIMER_DEF(m_record_upload_finish_packet_report_tmr); // 数据上报完成上报定时器 +static uint8_t txbuf[128]; +static uint8_t reportbuf[128]; +static bool m_realtime_report_state = false; +static bool m_isupload_data_state = false; +static bool m_ble_cmder_is_inited = false; +static uint32_t m_report_data_sumcheckcode = 0; + +static void record_upload_tmr_cb(void* p_context); +static void record_upload_finish_packet_report_tmr_cb(void* p_context); +int ble_stop_upload_record(); +/******************************************************************************* + * 广播控制 * + *******************************************************************************/ +void ble_cmder_start_adv() { + m_realtime_report_state = false; + zble_module_start_adv(); +} +void ble_cmder_stop_adv() { + zble_module_stop_adv(); + m_realtime_report_state = false; +} + +/******************************************************************************* + * 模块初始化 * + *******************************************************************************/ +void ble_cmder_init() { + if (!m_ble_cmder_is_inited) { + ZERROR_CHECK(app_timer_create(&m_record_upload_tmr, APP_TIMER_MODE_REPEATED, record_upload_tmr_cb)); + ZERROR_CHECK(app_timer_create(&m_record_upload_finish_packet_report_tmr, APP_TIMER_MODE_SINGLE_SHOT, record_upload_finish_packet_report_tmr_cb)); + } + m_ble_cmder_is_inited = true; +} +void ble_cmder_uninit() {} + +/******************************************************************************* + * 实时上报控制 * + *******************************************************************************/ +int ble_start_realtime_report() { + m_realtime_report_state = true; + return 0; +} +int ble_stop_realtime_report() { + m_realtime_report_state = false; + return 0; +} +void ble_cmder_try_report_one_sample_data(uint32_t frameIndex, uint16_t data0, uint16_t data1, uint16_t data2, uint16_t data3) { + if (!m_realtime_report_state) { + return; + } + + heartrate_report_packet_t* reportpacket = (heartrate_report_packet_t*)reportbuf; + reportpacket->cmd = ify_hrs_report_heartrate_data; + reportpacket->frame_index = 0; + reportpacket->frame_type = kifyhrs_pt_report; + reportpacket->sample_data_index = frameIndex; + + reportpacket->data[0] = (data0 >> 0) & 0xFF; // 第一帧数据 + reportpacket->data[1] = (data0 >> 8) & 0xFF; // 第一帧数据 + reportpacket->data[2] = (data1 >> 0) & 0xFF; // 第二帧数据 + reportpacket->data[3] = (data1 >> 8) & 0xFF; // 第二帧数据 + reportpacket->data[4] = (data2 >> 0) & 0xFF; // 第三帧数据 + reportpacket->data[5] = (data2 >> 8) & 0xFF; // 第三帧数据 + reportpacket->data[6] = (data3 >> 0) & 0xFF; // 第四帧数据 + reportpacket->data[7] = (data3 >> 8) & 0xFF; // 第四帧数据 + + uint16_t sendlen = sizeof(heartrate_report_packet_t) + 8; + zdatachannel_data_send2(reportbuf, sendlen); + return; +} + +void ble_cmder_try_report_sensor_drop_event(uint8_t dropstate0, uint8_t dropstate1) { + sensor_drop_event_report_packet_t* reportpacket = (sensor_drop_event_report_packet_t*)reportbuf; + reportpacket->cmd = ify_hrs_report_sensor_drop_detect; + reportpacket->frame_index = 0; + reportpacket->frame_type = kifyhrs_pt_report; + reportpacket->drop_state0 = dropstate0; + reportpacket->drop_state1 = dropstate1; + + uint16_t sendlen = sizeof(sensor_drop_event_report_packet_t); + zdatachannel_data_send2(reportbuf, sendlen); + return; +} +void ble_cmder_report_upload_finish_event(uint32_t sumcheckcode) { + ify_hrs_packet_t* txheader = (ify_hrs_packet_t*)txbuf; + uint16_t sendlen = sizeof(ify_hrs_packet_t) + 4; + + txheader->cmd = ify_hrs_report_record_upload_end; // 6A + txheader->frame_index = 0; + txheader->frame_type = kifyhrs_pt_report; + + // txheader->data[0] = errorcode; + *(uint32_t*)txheader->data = sumcheckcode; + + zdatachannel_data_send2(txbuf, sendlen); + return; +} + +void ble_cmder_report_sample_finish_event() { + ify_hrs_packet_t* txheader = (ify_hrs_packet_t*)txbuf; + uint16_t sendlen = sizeof(ify_hrs_packet_t); + + txheader->cmd = ify_hrs_report_sample_finish_end; + txheader->frame_index = 0; + txheader->frame_type = kifyhrs_pt_report; + + zdatachannel_data_send2(txbuf, sendlen); + return; +} + +/******************************************************************************* + * 上传数据控制 * + *******************************************************************************/ +static int m_upload_fd; +static uint8_t datacache[256]; +static int m_remaindatalen = 0; +/** + * @brief 数据上报定时器回调 + * + * @param p_context + */ +static void record_upload_finish_packet_report_tmr_cb(void* p_context) { // + ble_cmder_report_upload_finish_event(m_report_data_sumcheckcode); +} + +static void record_upload_tmr_cb(void* p_context) { // + + if (!m_isupload_data_state) return; + + // sample_data_mgr_read + if (m_remaindatalen == 0) { + memset(datacache, 0, sizeof(datacache)); + int32_t rdsize = sample_data_mgr_read(m_upload_fd, datacache, sizeof(datacache)); + if (rdsize <= 0) { + ZLOGI("read file end,stop upload"); + ZERROR_CHECK(app_timer_start(m_record_upload_finish_packet_report_tmr, APP_TIMER_TICKS(30), (void*)m_report_data_sumcheckcode)); + ble_stop_upload_record(); + return; + } + m_remaindatalen = rdsize; + } + if (m_remaindatalen == 0) { + return; + } + + int32_t mtusize = zble_module_get_mtu_size(); + mtusize = mtusize < 128 ? mtusize : 128; + + uint8_t* data = datacache + (sizeof(datacache) - m_remaindatalen); + int len = m_remaindatalen > mtusize ? mtusize : m_remaindatalen; + + ZLOGI("upload %d %d %d", len, m_remaindatalen, mtusize); + if (!zdatachannel_is_connected()) { + ZLOGI("ble is disconnected,stop upload"); + ble_stop_upload_record(); + return; + } + + uint32_t suc = zdatachannel_block_data_send2(data, len); + if (suc != NRF_SUCCESS) { + if (suc == NRF_ERROR_INVALID_STATE) { + // 未使能notify + ZLOGI("ble unenable notify,stop upload"); + ble_stop_upload_record(); + return; + } else if (suc == NRF_ERROR_BUSY || suc == NRF_ERROR_RESOURCES) { + // 等待下次发送 + return; + } else { + ZLOGI("ble send error,stop upload %x", suc); + ble_stop_upload_record(); + return; + } + } + for (uint32_t i = 0; i < len; i++) { + m_report_data_sumcheckcode += data[i]; + } + m_remaindatalen -= len; +} + +int ble_start_upload_record(sample_data_filename_t* recordid) { + // + // 启动 + // + if (ds_now_state() != kdevice_state_home) { + return kifyhrs_ecode_device_busy; + } + + m_upload_fd = sample_data_mgr_open(recordid, kwrflag_read_only); + if (m_upload_fd <= 0) { + return kifyhrs_ecode_no_record_find; + } + + ZERROR_CHECK(app_timer_start(m_record_upload_tmr, APP_TIMER_TICKS(2), NULL)); + m_isupload_data_state = true; + m_remaindatalen = 0; + m_report_data_sumcheckcode = 0; + return 0; +} +int ble_stop_upload_record() { + m_isupload_data_state = false; + app_timer_stop(m_record_upload_tmr); + return 0; +} +bool ble_is_upload_record() { return m_isupload_data_state; } + +/******************************************************************************* + * UTILS * + *******************************************************************************/ +static void send_error_receipt(ify_hrs_packet_t* rxpacket, int32_t errorcode) { + ify_hrs_packet_t* txheader = (ify_hrs_packet_t*)txbuf; + error_receipt_t* receipt = (error_receipt_t*)txheader->data; + uint16_t sendlen = sizeof(ify_hrs_packet_t) + sizeof(error_receipt_t); + + txheader->cmd = rxpacket->cmd; + txheader->frame_index = rxpacket->frame_index; + txheader->frame_type = kifyhrs_pt_error_receipt; + + txheader->frame_type = kifyhrs_pt_error_receipt; + receipt->errorcode = kifyhrs_ecode_cmd_not_support; + zdatachannel_data_send2(txbuf, sendlen); +} + +static void send_success_receipt(ify_hrs_packet_t* rxpacket, int32_t emptydatasize) { + ify_hrs_packet_t* txheader = (ify_hrs_packet_t*)txbuf; + uint16_t sendlen = sizeof(ify_hrs_packet_t) + emptydatasize; + + txheader->cmd = rxpacket->cmd; + txheader->frame_index = rxpacket->frame_index; + txheader->frame_type = kifyhrs_pt_cmd_receipt; + + zdatachannel_data_send2(txbuf, sendlen); +} + +/******************************************************************************* + * 下发消息处理 * + *******************************************************************************/ +void ble_cmder_process_rx(uint8_t* rx, int len) { + if (len < sizeof(ify_hrs_packet_t)) { + ZLOGI("rx len error:%d", len); + return; + } + + ify_hrs_packet_t* rxheader = (ify_hrs_packet_t*)rx; + ify_hrs_packet_t* txheader = (ify_hrs_packet_t*)txbuf; + ify_hrs_cmd_t cmd = (ify_hrs_cmd_t)rxheader->cmd; + memset(txbuf, 0, sizeof(txbuf)); + + txheader->cmd = rxheader->cmd; + txheader->frame_index = rxheader->frame_index; + txheader->frame_type = kifyhrs_pt_cmd_receipt; + + ZLOGI("rx cmd:%d index:%d datalen:%d", cmd, rxheader->frame_index, len - sizeof(ify_hrs_packet_t)); + NRF_LOG_HEXDUMP_INFO(rx, len); + + if (cmd == ify_hrs_cmd_read_device_version) { + device_version_info_receipt_t* receipt = (device_version_info_receipt_t*)txheader->data; + uint16_t sendlen = sizeof(ify_hrs_packet_t) + sizeof(device_version_info_receipt_t); + + receipt->blestack_version = device_info_read_blestack_version(); + receipt->bootloader_version = device_info_read_bootloader_version(); + receipt->firmware_version = device_info_read_firmware_version(); + receipt->hardware_version = device_info_read_hardware_version(); + zdatachannel_data_send2(txbuf, sendlen); + } + + else if (cmd == ify_hrs_cmd_read_sensor_info) { + sensor_info_receipt_t* receipt = (sensor_info_receipt_t*)txheader->data; + uint16_t sendlen = sizeof(ify_hrs_packet_t) + sizeof(sensor_info_receipt_t); + + receipt->sensor_num = 1; + receipt->sensor_precision = SAMPLE_PRECISION; + receipt->sensor_sample_rate = SAMPLE_RATE / 10; + receipt->sensor0_pos = kifyhrs_sensor_pos_none; + receipt->sensor1_pos = kifyhrs_sensor_pos_none; + receipt->sensor2_pos = kifyhrs_sensor_pos_none; + + zdatachannel_data_send2(txbuf, sendlen); + } + + else if (cmd == ify_hrs_cmd_read_device_state) { + device_state_receipt_t* receipt = (device_state_receipt_t*)txheader->data; + uint16_t sendlen = sizeof(ify_hrs_packet_t) + sizeof(device_state_receipt_t); + + receipt->drop_state0 = (!SingleLeadECG_ecg_plod_get_connected_state()); + receipt->drop_state1 = 0x00; + receipt->device_state0.sampling_state = (ds_now_state() == kdevice_state_sampling); + receipt->device_state0.report_state = m_realtime_report_state; + receipt->device_state0.low_battery = (SingleLeadECG_battery_val() < 20); + receipt->device_state0.full_storge = (sample_data_mgr_storage_is_full()); + + receipt->device_state1 = 0; + receipt->powerlevel = SingleLeadECG_battery_val(); + receipt->storage_item_num = sample_data_mgr_get_file_num(); + + zdatachannel_data_send2(txbuf, sendlen); + } + + else if (cmd == ify_hrs_cmd_read_time) { + read_time_receipt_t* receipt = (read_time_receipt_t*)txheader->data; + uint16_t sendlen = sizeof(ify_hrs_packet_t) + sizeof(read_time_receipt_t); + static ztm_t ztm; + znordic_rtc_gettime(&ztm); + + receipt->year = (ztm.tm_year + 1900 - 2000); + receipt->month = ztm.tm_mon + 1; + receipt->day = ztm.tm_mday; + receipt->hour = ztm.tm_hour; + receipt->minute = ztm.tm_min; + receipt->second = ztm.tm_sec; + zdatachannel_data_send2(txbuf, sendlen); + } + + else if (cmd == ify_hrs_cmd_sync_time) { + sync_time_cmd_t* cmd = (sync_time_cmd_t*)rxheader->data; + uint16_t sendlen = sizeof(ify_hrs_packet_t); + + znordic_rtc_settime(cmd->year + 2000, cmd->month, cmd->day, cmd->hour, cmd->minute, cmd->second); + zdatachannel_data_send2(txbuf, sendlen); + } + + else if (cmd == ify_hrs_cmd_start_capture) { + send_error_receipt(rxheader, kifyhrs_ecode_cmd_not_support); + } + + else if (cmd == ify_hrs_cmd_stop_capture) { + send_error_receipt(rxheader, kifyhrs_ecode_cmd_not_support); + } + + else if (cmd == ify_hrs_cmd_start_realtime_report) { + // unsupport cmd + int ecode = ble_start_realtime_report(); + if (ecode == 0) { + send_success_receipt(rxheader, 8); // 凑8个字节,使这个回执的字节长度同上报包长度一致,方便调试 + } else { + send_error_receipt(rxheader, ecode); + } + } + + else if (cmd == ify_hrs_cmd_stop_realtime_report) { + int ecode = ble_stop_realtime_report(); + if (ecode == 0) { + send_success_receipt(rxheader, 0); + } else { + send_error_receipt(rxheader, ecode); + } + } + + else if (cmd == ify_hrs_cmd_read_records_info) { + // 指令 10-读取采样记录头部信息 + read_record_info_cmd_t* cmd = (read_record_info_cmd_t*)rxheader->data; + read_record_info_receipt_t* receipt = (read_record_info_receipt_t*)txheader->data; + uint16_t sendlen = sizeof(ify_hrs_packet_t) + sizeof(read_record_info_receipt_t); + + uint8_t recordoff = cmd->record_index; + + // 采样时不支持 + if (ds_now_state() != kdevice_state_home) { + send_error_receipt(rxheader, kifyhrs_ecode_device_busy); + return; + } + + sample_data_fileinfo_list_t* recordlist = sample_data_mgr_get_fileinfo_list(); + if (recordoff >= recordlist->count) { + send_error_receipt(rxheader, kifyhrs_ecode_no_record_find); + return; + } + + sample_data_fileinfo_t* fileinfo = recordlist->fileinfo[recordoff]; + memcpy(receipt->record_id, fileinfo->filename, 6); + receipt->frameNum = fileinfo->size / 2; // 2byte per frame + receipt->dataSize = fileinfo->size; + receipt->sensorNum = 1; + receipt->captureRate = SAMPLE_RATE / 10; + receipt->capturePrecision = SAMPLE_PRECISION; + receipt->compressAlgorithm = 0; + + zdatachannel_data_send2(txbuf, sendlen); + + } + + else if (cmd == ify_hrs_cmd_del_record) { + // 指令 11-删除采样记录 + del_record_cmd_t* cmd = (del_record_cmd_t*)rxheader->data; + + static sample_data_filename_t filename; + memset(&filename, 0, sizeof(filename)); + memcpy(&filename, cmd->record_id, sizeof(cmd->record_id)); + + // 采样时不支持 + if (ds_now_state() != kdevice_state_home) { + send_error_receipt(rxheader, kifyhrs_ecode_device_busy); + return; + } + + int ecode = sample_data_mgr_delete_file(&filename); + if (ecode == 0) { + send_success_receipt(rxheader, 0); + } else { + send_error_receipt(rxheader, kifyhrs_ecode_unkown_error); + } + } + + else if (cmd == ify_hrs_cmd_start_upload_record) { + // 指令 12-上传采集记录 + start_upload_record_cmd_t* cmd = (start_upload_record_cmd_t*)rxheader->data; + + static sample_data_filename_t filename; + memset(&filename, 0, sizeof(filename)); + memcpy(&filename, cmd->record_id, sizeof(cmd->record_id)); + + // 采样时不支持 + if (ds_now_state() != kdevice_state_home) { + send_error_receipt(rxheader, kifyhrs_ecode_device_busy); + return; + } + + int ecode = ble_start_upload_record(&filename); + if (ecode == 0) { + ify_hrs_packet_t* txheader = (ify_hrs_packet_t*)txbuf; + uint16_t sendlen = sizeof(ify_hrs_packet_t) + 1; // 凑齐4BYTE,方便调试 + txheader->cmd = rxheader->cmd; + txheader->frame_index = rxheader->frame_index; + txheader->frame_type = kifyhrs_pt_cmd_receipt; + + zdatachannel_data_send2(txbuf, sendlen); + } else { + send_error_receipt(rxheader, ecode); + } + } + + else if (cmd == ify_hrs_cmd_stop_upload_record) { + ble_stop_upload_record(); + send_success_receipt(rxheader, 0); + } + + else if (cmd == ify_hrs_cmd_enter_ota) { + send_error_receipt(rxheader, kifyhrs_ecode_cmd_not_support); + } + + else if (cmd == ify_hrs_cmd_read_sn) { + read_sn_receipt_t* receipt = (read_sn_receipt_t*)txheader->data; + uint16_t sendlen = sizeof(ify_hrs_packet_t) + sizeof(read_sn_receipt_t); + device_info_read_sn((sn_t*)&receipt->sn); + zdatachannel_data_send2(txbuf, sendlen); + } + + else if (cmd == ify_hrs_cmd_reset) { + NVIC_SystemReset(); + } + // + else { + send_error_receipt(rxheader, kifyhrs_ecode_cmd_not_support); + } +} diff --git a/app/src/ble_cmd_process_service.h b/app/src/ble_cmd_process_service.h new file mode 100644 index 0000000..412bb58 --- /dev/null +++ b/app/src/ble_cmd_process_service.h @@ -0,0 +1,15 @@ +#pragma once + +#include "device_state.h" + +void ble_cmder_init(); +void ble_cmder_uninit(); + +void ble_cmder_process_rx(uint8_t* rx, int len); +void ble_cmder_start_adv(); +void ble_cmder_stop_adv(); + +void ble_cmder_try_report_one_sample_data(uint32_t frameIndex, uint16_t data0, uint16_t data1, uint16_t data2, uint16_t data3); +void ble_cmder_try_report_sensor_drop_event(uint8_t dropstate0, uint8_t dropstate1); +void ble_cmder_report_upload_finish_event(uint32_t sumcheckcode); +void ble_cmder_report_sample_finish_event(); diff --git a/app/src/board/board.h b/app/src/board/board.h index 91b2f2f..59baa7e 100644 --- a/app/src/board/board.h +++ b/app/src/board/board.h @@ -19,6 +19,8 @@ #define SAMPLE_PRECISION 12 #define AUTOMATIC_SLEEP_TIME 15000 -#define SAMPLE_MIN_TIME_S (30.0) +#define SAMPLE_MIN_TIME_S (30.0) -#define ENABLE_SLEEP \ No newline at end of file +#define ENABLE_SLEEP + +#define LITTLE_DATA_BLOCK_FRAME_NUM 4 // 每次多少帧上报一次 diff --git a/app/src/config.h b/app/src/config.h new file mode 100644 index 0000000..3977535 --- /dev/null +++ b/app/src/config.h @@ -0,0 +1,3 @@ +#pragma once + +#include "board/board.h" \ No newline at end of file diff --git a/app/src/device_controler.c b/app/src/device_controler.c new file mode 100644 index 0000000..e69de29 diff --git a/app/src/device_controler.h b/app/src/device_controler.h new file mode 100644 index 0000000..e69de29 diff --git a/app/src/device_state.c b/app/src/device_state.c new file mode 100644 index 0000000..243c1b5 --- /dev/null +++ b/app/src/device_state.c @@ -0,0 +1,27 @@ + +#include "device_state.h" + +#include "znordic.h" +static device_state_t m_device_state = kdevice_state_standby; // 设备状态 +static uint32_t m_change_to_cur_state_tp = 0; // 切换到当前状态的时间戳 + +void ds_change_to_state(device_state_t state) { + ZLOGI("change state from %s to %s", device_state_to_str(m_device_state), device_state_to_str(state)); + m_device_state = state; + m_change_to_cur_state_tp = znordic_getpower_on_ms(); +} + +uint32_t ds_cur_state_haspassed_ms() { return znordic_haspassed_ms(m_change_to_cur_state_tp); } +device_state_t ds_now_state() { return m_device_state; } + +static sample_capture_state_t m_sample_capture_state; + +sample_capture_state_t* sample_capture_state_get() { // + return &m_sample_capture_state; +} +void sample_capture_state_reset() { // + m_sample_capture_state.is_over30s = false; +}; +void sample_capture_state_set_is_over30s(bool over30s) { // + m_sample_capture_state.is_over30s = over30s; +} diff --git a/app/src/device_state.h b/app/src/device_state.h new file mode 100644 index 0000000..469a34c --- /dev/null +++ b/app/src/device_state.h @@ -0,0 +1,92 @@ +#pragma once +#include +#include + +#include "board/board.h" +typedef enum { + kplod_connected_event = 0, // 导联连接事件 + kplod_disconnected_event, // 导联断开事件 + kplod_connecting_event, // 导联连接中事件 + + kplod_start_charge_event, // 充电事件 + kplod_charging_event, // 充电中 + kplod_end_charge_event, // 充电结束事件 + + kevent_tmr_scheduler_event, // 定时器调度事件 + + kevent_capture_256data_event, // 采样数据回调 + kevent_capture_little_data_block_event, // 单次采样数据回调 +} app_event_type_t; + +typedef struct { + uint16_t data; +} one_frame_data_t; + +typedef struct { + app_event_type_t eventType; + union { + uint32_t plod_connected_accumulation_time; // 导联连接累计时间 + uint8_t* capture_data_cache; // 实时采样数据,数据长度为256字节 + struct { + uint32_t frameIndex; + one_frame_data_t data[LITTLE_DATA_BLOCK_FRAME_NUM]; + } little_data_block; + } val; +} app_event_t; + +typedef enum { + // 待机 + kdevice_state_standby = 0, + // 开机 + kdevice_state_poweron, + // 首页 + kdevice_state_home, + // 提示用户保持静止 + kdevice_state_keep_still, + // 采集中 + kdevice_state_sampling, + // 采集完成 + kdevice_state_sampling_complete, + // 采集异常 + kdevice_state_sampling_error, + // 充电中 + kdevice_state_charging, +} device_state_t; + +static const char* device_state_to_str(device_state_t ds) { + switch (ds) { + case kdevice_state_standby: + return "standby"; + case kdevice_state_poweron: + return "poweron"; + case kdevice_state_home: + return "home"; + case kdevice_state_keep_still: + return "keep_still"; + case kdevice_state_sampling: + return "sampling"; + case kdevice_state_sampling_complete: + return "sampling_complete"; + case kdevice_state_sampling_error: + return "sampling_error"; + case kdevice_state_charging: + return "charging"; + default: + return "unknow"; + } +} + +void app_event_process_cb(void* p_event_data, uint16_t event_size); + +void ds_change_to_state(device_state_t state); +uint32_t ds_cur_state_haspassed_ms(); +device_state_t ds_now_state(); + +typedef struct { + bool is_over30s; +} sample_capture_state_t; + +sample_capture_state_t* sample_capture_state_get(); + +void sample_capture_state_reset(); +void sample_capture_state_set_is_over30s(bool over30s); diff --git a/app/src/display_manager.c b/app/src/display_manager.c new file mode 100644 index 0000000..615c324 --- /dev/null +++ b/app/src/display_manager.c @@ -0,0 +1,442 @@ +#include "display_manager.h" + +#include "../../../res/logo_mono.c" +// +#include + +#include "basic/ssd1306/driver_ssd1306.h" +#include "basic/ssd1306/driver_ssd1306_basic.h" +#include "basic/ssd1306/wave_drawer.h" +#include "config.h" +#include "font.h" +#include "heart_wave_sample_service.h" +#include "one_conduction_board.h" +PageState_t g_pageState; + +void dsp_mgr_change_to_page(page_t page) { // + g_pageState.page = page; + g_pageState.last_page = page; + g_pageState.page_change_to_page_time = znordic_getpower_on_s(); + + g_pageState.in_prompt = false; + memset(g_pageState.prompt, 0, sizeof(g_pageState.prompt)); +} + +uint32_t dsp_mgr_get_page_elapsed_time_s(void) { // + return znordic_getpower_on_s() - g_pageState.page_change_to_page_time; +} + +void dsp_mgr_schedule(void) {} + +PageState_t* dsp_mgr_get_state(void) { return NULL; } + +int compute_x_pos_by_center(int16_t x, int16_t width) { return x - width / 2; } +int compute_y_pos_by_center(int16_t y, int16_t height) { return y - height / 2; } + +#define SCREEN_CENTER_X 64 +#define SCREEN_CENTER_Y 32 + +#define CHARGE_BATTERY_WIDTH (12 * 1.2) +#define CHARGE_BATTERY_HEIGHT (22 * 1.2) + +#define MAIN_PAGE_BATTERY_WIDTH (12) // 首页电池宽度 +#define MAIN_PAGE_BATTERY_HEIGHT (22) // 首页电池高度 + +/******************************************************************************* + * 充电页面 * + *******************************************************************************/ +/** + * 显示元素: + * 1.电池电量 + * --------------- + * | _ | + * | | | | + * | | + * --------------- + * + * 动画效果: + * 1. 电池电量变化 + * + */ +static uint32_t m_nowshowbatterylevel; // 当前显示的电池电量 + +void dsp_mgr_change_to_chargingPage() { + ssd1306_basic_clear(); + uint8_t x = compute_x_pos_by_center(SCREEN_CENTER_X, CHARGE_BATTERY_WIDTH); + uint8_t y = compute_y_pos_by_center(SCREEN_CENTER_Y, CHARGE_BATTERY_HEIGHT); + uint8_t xchange, ychange; + ssd1306_basic_draw_battery_level(x, y, &xchange, &ychange, SingleLeadECG_battery_val(), CHARGE_BATTERY_WIDTH, CHARGE_BATTERY_HEIGHT); + m_nowshowbatterylevel = SingleLeadECG_battery_val(); + ssd1306_basic_gram_update(); + dsp_mgr_change_to_page(kPage_chargingPage); +} + +void chargingPage_set_batteryLevel(int batteryLevel) { + uint8_t x = compute_x_pos_by_center(SCREEN_CENTER_X, CHARGE_BATTERY_WIDTH); + uint8_t y = compute_y_pos_by_center(SCREEN_CENTER_Y, CHARGE_BATTERY_HEIGHT); + uint8_t xchange, ychange; + ssd1306_basic_draw_battery_level(x, y, &xchange, &ychange, batteryLevel, CHARGE_BATTERY_WIDTH, CHARGE_BATTERY_HEIGHT); + ssd1306_basic_gram_update(); +} + +void chargingPage_schedule() { // + static uint32_t last_update_time = 0; + if (znordic_haspassed_ms(last_update_time) < 300) { + return; + } + + last_update_time = znordic_getpower_on_ms(); + m_nowshowbatterylevel += 5; + if (m_nowshowbatterylevel > 100) { + m_nowshowbatterylevel = SingleLeadECG_battery_val(); + } + chargingPage_set_batteryLevel(m_nowshowbatterylevel); +} + +/******************************************************************************* + * 欢迎页面 * + *******************************************************************************/ +void dsp_mgr_change_to_welcome() { + /** + * @brief 切换到欢迎界面 + * 1. 加载屏幕外设 + * 2. 打开屏幕电源 + * 3. 初始化开机页面 + */ + + // ssd1306_basic_string(0, 0, "123456789123456789123", 21, 0, SSD1306_FONT_12); + ssd1306_basic_draw_screen((const char*)gImage_logo_mono); + ssd1306_basic_gram_update(); + dsp_mgr_change_to_page(kPage_welcome); +} + +void welcomePage_schedule() {} + +/******************************************************************************* + * 首页 * + *******************************************************************************/ +static bool m_main_page_colon_state = false; + +void mainPage_show(bool colon_state) { + static ztm_t now; + int16_t batterylevel; + uint8_t xchange, ychange; + uint8_t x, y; + x = compute_x_pos_by_center(SCREEN_CENTER_X, fontclocklib.widthPixel * 5 + MAIN_PAGE_BATTERY_WIDTH); + y = compute_y_pos_by_center(SCREEN_CENTER_Y, fontclocklib.heightPixel + 1); + znordic_rtc_gettime(&now); + batterylevel = SingleLeadECG_battery_val(); + + ssd1306_basic_clear_gram(); + + // ZLOGI("mainPage_show %d %d", colon_state, x, y); + + ssd1306_basic_draw_str(x, y, &xchange, &ychange, fmt("%02d:%02d", now.tm_hour, now.tm_min), &fontclocklib); + x = x + 2 + xchange; + ssd1306_basic_draw_battery_level(x, y, &xchange, &ychange, batterylevel, MAIN_PAGE_BATTERY_WIDTH, MAIN_PAGE_BATTERY_HEIGHT); + ssd1306_basic_gram_update(); + m_main_page_colon_state = colon_state; + dsp_mgr_change_to_page(kPage_main); +} + +void dsp_mgr_change_to_main() { mainPage_show(true); } +void mainPage_updateState() { mainPage_show(!m_main_page_colon_state); } +void mainPage_schedule() { + static uint32_t last_update_time = 0; + if (znordic_haspassed_ms(last_update_time) < 300) { + return; + } + last_update_time = znordic_getpower_on_ms(); + mainPage_updateState(); +} + +/******************************************************************************* + * 保持静止页面 * + *******************************************************************************/ +static int m_prepare_page_progress = 0; +void PreparePage_show(int progress) { + m_prepare_page_progress = progress; + ssd1306_basic_clear_gram(); + uint8_t x = 0; + uint8_t y = 0; + uint8_t xchange, ychange; + + x = compute_x_pos_by_center(SCREEN_CENTER_X, font24x24_zh_lib.widthPixel * 4); + y = compute_y_pos_by_center(SCREEN_CENTER_Y, font24x24_zh_lib.heightPixel); + + ssd1306_basic_draw_str(x, y, &xchange, &ychange, "保持静止", &font24x24_zh_lib); + + if (progress == 0) { + ssd1306_basic_draw_str(x - font8x8_xo_lib.widthPixel, y - font8x8_xo_lib.heightPixel, &xchange, &ychange, "xxxx", &font8x8_xo_lib); + } else if (progress == 1) { + ssd1306_basic_draw_str(x - font8x8_xo_lib.widthPixel, y - font8x8_xo_lib.heightPixel, &xchange, &ychange, "oxxx", &font8x8_xo_lib); + } else if (progress == 2) { + ssd1306_basic_draw_str(x - font8x8_xo_lib.widthPixel, y - font8x8_xo_lib.heightPixel, &xchange, &ychange, "ooxx", &font8x8_xo_lib); + } else if (progress == 3) { + ssd1306_basic_draw_str(x - font8x8_xo_lib.widthPixel, y - font8x8_xo_lib.heightPixel, &xchange, &ychange, "ooox", &font8x8_xo_lib); + } else if (progress == 4) { + ssd1306_basic_draw_str(x - font8x8_xo_lib.widthPixel, y - font8x8_xo_lib.heightPixel, &xchange, &ychange, "oooo", &font8x8_xo_lib); + } + + ssd1306_basic_gram_update(); +} + +void dsp_mgr_change_to_preparePage() { + PreparePage_show(0); + dsp_mgr_change_to_page(kPage_preparePage); +} +void dsp_mgr_preparePage_set_progress(int progress) { PreparePage_show(progress); } +int dsp_mgr_preparePage_get_progress() { return m_prepare_page_progress; } + +void PreparePage_schedule() {} + +/******************************************************************************* + * 采样页面 * + *******************************************************************************/ + +#define SMAPLE_PAGE_START_X 1 +#define SMAPLE_PAGE_START_Y 1 + +typedef struct { + wave_drawer_t wave_drawer; + + int wave_drawser_x; + int wave_drawser_y; + int wave_drawser_hight; + int wave_drawser_width; + + int progress_x; + int progress_y; + + int progress_width; + int progress_hight; + + int heartrate_x; + int heartrate_y; +} sample_page_state_t; +sample_page_state_t m_sample_page_state; +#if 0 +void dsp_mgr_change_to_sampling(int progress_s, int heartrate) { // + sample_page_state_t* sps = &m_sample_page_state; + + sps->wave_drawser_x = SMAPLE_PAGE_START_X; + sps->wave_drawser_y = SMAPLE_PAGE_START_Y; + sps->wave_drawser_hight = 40; + sps->wave_drawser_width = 120; + + sps->progress_x = SMAPLE_PAGE_START_X + 1; + sps->progress_y = SMAPLE_PAGE_START_Y + sps->wave_drawser_hight + 3 + 4; + sps->progress_width = 80; + sps->progress_hight = 8; + + sps->heartrate_x = sps->progress_x + sps->progress_width + 2; + sps->heartrate_y = sps->progress_y - 4; + + int progress = progress_s / SAMPLE_MIN_TIME_S * 25; + + ssd1306_basic_clear_gram(); + + wave_drawer_init(&sps->wave_drawer, sps->wave_drawser_x, sps->wave_drawser_y, sps->wave_drawser_width, sps->wave_drawser_hight); + wave_drawer_draw_border(&sps->wave_drawer); + uint8_t xchange, ychange; + ssd1306_basic_draw_progress(sps->progress_x, sps->progress_y, sps->progress_width, sps->progress_hight, 25, progress); + if (heartrate <= 0) { + ssd1306_basic_draw_str(sps->heartrate_x, sps->heartrate_y, &xchange, &ychange, "<>-- ", &font_asicc16x8_lib); + } else { + ssd1306_basic_draw_str(sps->heartrate_x, sps->heartrate_y, &xchange, &ychange, fmt("<>%3d", heartrate), &font_asicc16x8_lib); + } + ssd1306_basic_gram_update(); + dsp_mgr_change_to_page(kPage_sampling); +} + +void samplePage_update_state(int progress_s, int wave_y, int heartrate, bool update_screen) { // + + sample_page_state_t* sps = &m_sample_page_state; + uint8_t xchange, ychange; + + int progress = progress_s / SAMPLE_MIN_TIME_S * 25; + + if (progress_s / 10 == 0) { + ssd1306_basic_draw_str(sps->progress_x, sps->progress_y - 8, &xchange, &ychange, "xxx", &font8x8_xo_lib); + } else if (progress_s / 10 == 1) { + ssd1306_basic_draw_str(sps->progress_x, sps->progress_y - 8, &xchange, &ychange, "oxx", &font8x8_xo_lib); + } else if (progress_s / 10 == 2) { + ssd1306_basic_draw_str(sps->progress_x, sps->progress_y - 8, &xchange, &ychange, "oox", &font8x8_xo_lib); + } else if (progress_s / 10 == 3) { + ssd1306_basic_draw_str(sps->progress_x, sps->progress_y - 8, &xchange, &ychange, "ooo", &font8x8_xo_lib); + } + + wave_drawer_draw_next_point(&sps->wave_drawer, wave_y); + ssd1306_basic_draw_progress(sps->progress_x, sps->progress_y, sps->progress_width, sps->progress_hight, 25, progress); + if (heartrate <= 0) { + ssd1306_basic_draw_str(sps->heartrate_x, sps->heartrate_y, &xchange, &ychange, "<>-- ", &font_asicc16x8_lib); + } else { + ssd1306_basic_draw_str(sps->heartrate_x, sps->heartrate_y, &xchange, &ychange, fmt("<>%3d", heartrate), &font_asicc16x8_lib); + } + if (update_screen) ssd1306_basic_gram_update(); +} +#endif +void dsp_mgr_change_to_sampling(int progress_s, int heartrate) { // + sample_page_state_t* sps = &m_sample_page_state; + + sps->progress_x = SMAPLE_PAGE_START_X + 10; + sps->progress_y = SMAPLE_PAGE_START_Y + 2; + sps->progress_width = 100; + sps->progress_hight = 8; + + sps->wave_drawser_x = SMAPLE_PAGE_START_X + 5; + sps->wave_drawser_y = SMAPLE_PAGE_START_Y + sps->progress_hight + 5; + sps->wave_drawser_hight = 45; + sps->wave_drawser_width = 90; + + sps->heartrate_x = sps->wave_drawser_x + sps->wave_drawser_width + 5; + sps->heartrate_y = sps->wave_drawser_y + 5; + + int progress = progress_s / SAMPLE_MIN_TIME_S * 25; + uint8_t xchange, ychange; + + ssd1306_basic_clear_gram(); + /** + * @brief + * ================= + * | | 心 + * | wave | + * | | 心率 + */ + ssd1306_basic_draw_progress(sps->progress_x, sps->progress_y, sps->progress_width, sps->progress_hight, 25, progress); + // ssd1306_basic_draw_str(sps->progress_x + sps->progress_width + 2, sps->progress_y, &xchange, &ychange, "x", &font8x8_xo_lib); + + wave_drawer_init(&sps->wave_drawer, sps->wave_drawser_x, sps->wave_drawser_y, sps->wave_drawser_width, sps->wave_drawser_hight); + // wave_drawer_draw_border(&sps->wave_drawer); + + ssd1306_basic_draw_str(sps->heartrate_x + 2, sps->heartrate_y, &xchange, &ychange, "<>", &font_asicc16x8_lib); + if (heartrate <= 0) { + ssd1306_basic_draw_str(sps->heartrate_x, sps->heartrate_y + 20, &xchange, &ychange, "-- ", &font_asicc16x8_lib); + } else { + ssd1306_basic_draw_str(sps->heartrate_x, sps->heartrate_y + 20, &xchange, &ychange, fmt("%3d", heartrate), &font_asicc16x8_lib); + } + ssd1306_basic_gram_update(); + dsp_mgr_change_to_page(kPage_sampling); +} + +void samplePage_update_state(int progress_s, int wave_y, int heartrate, bool updateHeart, bool update_screen) { // + + sample_page_state_t* sps = &m_sample_page_state; + uint8_t xchange, ychange; + static bool heart_logo_state = false; + + int progress = progress_s / SAMPLE_MIN_TIME_S * 25; + + ssd1306_basic_draw_progress(sps->progress_x, sps->progress_y, sps->progress_width, sps->progress_hight, 25, progress); + // if (progress_s / 10 >= 3) { + // ssd1306_basic_draw_str(sps->progress_x + sps->progress_width + 2, sps->progress_y, &xchange, &ychange, "o", &font8x8_xo_lib); + // } else { + // ssd1306_basic_draw_str(sps->progress_x + sps->progress_width + 2, sps->progress_y, &xchange, &ychange, "x", &font8x8_xo_lib); + // } + if (update_screen && updateHeart) { + if (heart_logo_state) { + ssd1306_basic_draw_str(sps->heartrate_x + 2, sps->heartrate_y, &xchange, &ychange, "<>", &font_asicc16x8_lib); + } else { + ssd1306_basic_draw_str(sps->heartrate_x + 2, sps->heartrate_y, &xchange, &ychange, " ", &font_asicc16x8_lib); + } + heart_logo_state = !heart_logo_state; + } + + if (heartrate <= 0) { + ssd1306_basic_draw_str(sps->heartrate_x, sps->heartrate_y + 20, &xchange, &ychange, "-- ", &font_asicc16x8_lib); + } else { + ssd1306_basic_draw_str(sps->heartrate_x, sps->heartrate_y + 20, &xchange, &ychange, fmt("%3d", heartrate), &font_asicc16x8_lib); + } + wave_drawer_draw_next_point(&sps->wave_drawer, wave_y); + if (update_screen) ssd1306_basic_gram_update(); +} + +void samplePage_schedule() { + static int count = 0; + count++; + int capturetime = hwss_has_captured_time_ms(); + int wave_y = (int)hwss_read_val(); + int heartrate = (int)hwss_read_heart_rate(); + // ZLOGI("samplePage_schedule %d %d %d", capturetime, wave_y, heartrate); + samplePage_update_state(capturetime / 1000, wave_y, 123, count % 10 == 0, count % 5 == 0); +} + +/******************************************************************************* + * samplingError * + *******************************************************************************/ +void dsp_mgr_change_to_samplingError() { + /** + * @brief + * 不足30秒[X] + */ + ssd1306_basic_clear_gram(); + + uint8_t x; + uint8_t y; + + x = compute_x_pos_by_center(SCREEN_CENTER_X, font24x24_zh_lib.widthPixel * 3 + font12x24_asiic_lib.widthPixel * 2); + y = compute_y_pos_by_center(SCREEN_CENTER_Y, font24x24_zh_lib.heightPixel); + + uint8_t xchange, ychange; + ssd1306_basic_draw_str(x, y, &xchange, &ychange, "不足", &font24x24_zh_lib); + x = x + xchange; + ssd1306_basic_draw_str(x, y, &xchange, &ychange, "30", &font12x24_asiic_lib); + x = x + xchange; + ssd1306_basic_draw_str(x, y, &xchange, &ychange, "秒", &font24x24_zh_lib); + x = x + xchange; + ssd1306_basic_gram_update(); + dsp_mgr_change_to_page(kPage_samplingError); +} + +void dsp_mgr_change_to_sampleSuc() { + /** + * @brief + * 1.进度条 + * 2.提示信息 + */ + ssd1306_basic_clear(); + uint8_t x = 0; + uint8_t y = 0; + + uint8_t xchange, ychange; + x = compute_x_pos_by_center(SCREEN_CENTER_X, font24x24_zh_lib.widthPixel * 4); + y = compute_y_pos_by_center(SCREEN_CENTER_Y, font24x24_zh_lib.heightPixel); + + ssd1306_basic_draw_str(x, y, &xchange, &ychange, "采集完成", &font24x24_zh_lib); + ssd1306_basic_gram_update(); + dsp_mgr_change_to_page(kPage_storagingSuc); +} + +/******************************************************************************* + * SCHEDULE * + *******************************************************************************/ + +APP_TIMER_DEF(m_dsp_mgr_schedule_tmr); +static void dsp_mgr_schedule_tmr_cb(void* p_context) { // + if (g_pageState.page == kPage_chargingPage) { + chargingPage_schedule(); + } else if (g_pageState.page == kPage_welcome) { + welcomePage_schedule(); + } else if (g_pageState.page == kPage_main) { + mainPage_schedule(); + } else if (g_pageState.page == kPage_preparePage) { + PreparePage_schedule(); + } else if (g_pageState.page == kPage_sampling) { + samplePage_schedule(); + } +} + +void dsp_mgr_init(void) { + static bool timer_inited = false; + SingleLeadECG_screen_init(); + if (!timer_inited) { + ZERROR_CHECK(app_timer_create(&m_dsp_mgr_schedule_tmr, APP_TIMER_MODE_REPEATED, dsp_mgr_schedule_tmr_cb)); + } + // 此处周期决定采样一个页面显示的宽度 + ZERROR_CHECK(app_timer_start(m_dsp_mgr_schedule_tmr, APP_TIMER_TICKS(25), NULL)); + timer_inited = true; +} +void dsp_mgr_uninit(void) { + app_timer_stop(m_dsp_mgr_schedule_tmr); + SingleLeadECG_screen_deinit(); +} diff --git a/app/src/display_manager.h b/app/src/display_manager.h new file mode 100644 index 0000000..0553b77 --- /dev/null +++ b/app/src/display_manager.h @@ -0,0 +1,81 @@ +#pragma once + +#include "znordic.h" +// +#include "app_timer.h" +#include "diskio_blkdev.h" +#include "ff.h" +#include "nrf_block_dev_sdc.h" +#include "nrf_delay.h" +#include "nrf_drv_pwm.h" +#include "nrf_drv_saadc.h" +#include "nrf_drv_twi.h" +#include "nrf_drv_wdt.h" +#include "nrf_gpio.h" + +/** + * @brief + * 页面流转 + * + * close <--------------------- + * | + * button ---> welcome ---> main ---> preparePage ---> sampling ---> storaging ---> storagingSuc + * ^ ---> samplingError | + * |-------------------------------------------| | + * |-----------------------------------------------------------| + * + */ + +typedef enum { + kPage_poweroff, + kPage_welcome, + kPage_main, + kPage_preparePage, + kPage_sampling, + kPage_samplingError, + kPage_storaging, + kPage_storagingSuc, + kPage_chargingPage, +} page_t; + +typedef struct { + /** + * @brief 页面状态 + */ + page_t page; // 当前页面 + page_t last_page; // 上一个页面 + uint32_t page_change_to_page_time; // 当前页面持续的时间 + + bool in_prompt; // 是否在提示状态 + char prompt[32]; // 提示内容 + + /** + * @brief + */ + +} PageState_t; + +void dsp_mgr_init(void); +void dsp_mgr_uninit(void); +void dsp_mgr_schedule(void); + +PageState_t* dsp_mgr_get_state(void); +uint32_t dsp_mgr_get_page_elapsed_time_s(void); + +void dsp_mgr_change_to_poweroff(); +void dsp_mgr_change_to_welcome(); +void dsp_mgr_change_to_main(); +void dsp_mgr_change_to_chargingPage(); + +// 保持静止页面 +void dsp_mgr_change_to_preparePage(); +void dsp_mgr_preparePage_set_progress(int progress); +int dsp_mgr_preparePage_get_progress(); + +// 采样中页面 +void dsp_mgr_change_to_sampling(int progress_s, int heartrate); + +// 采样出错页面 +void dsp_mgr_change_to_samplingError(); +// 采样成功页面 +void dsp_mgr_change_to_sampleSuc(); \ No newline at end of file diff --git a/app/src/display_manager_res.h b/app/src/display_manager_res.h new file mode 100644 index 0000000..15109eb --- /dev/null +++ b/app/src/display_manager_res.h @@ -0,0 +1,5 @@ +#pragma once + +#include + + diff --git a/app/src/font.h b/app/src/font.h new file mode 100644 index 0000000..179ea34 --- /dev/null +++ b/app/src/font.h @@ -0,0 +1,275 @@ +// https://www.23bei.com/tool-965.html + +#include +#if 0 +const uint8_t fontclocklib_code[] = { + 0x00, 0x00, 0x00, 0x00, 0x7F, 0x80, 0x01, 0xFF, 0xE0, 0x03, 0xFF, 0xF0, 0x07, 0x80, 0x78, 0x06, // + 0x00, 0x18, 0x04, 0x00, 0x08, 0x06, 0x00, 0x18, 0x07, 0x80, 0x78, 0x03, 0xFF, 0xF0, 0x01, 0xFF, // + 0xE0, 0x00, 0x7F, 0x80, // + 0x00, 0x00, 0x00, 0x02, 0x00, 0x10, 0x02, 0x00, 0x10, 0x02, 0x00, 0x10, 0x07, 0xFF, 0xF0, 0x0F, // + 0xFF, 0xF0, 0x0F, 0xFF, 0xF0, 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, // + 0x00, 0x00, 0x00, 0x00, // + 0x03, 0x80, 0x70, 0x07, 0x80, 0xF0, 0x0D, 0x81, 0xB0, 0x08, 0x03, 0x30, 0x08, 0x06, 0x30, 0x08, // + 0x0C, 0x30, 0x0C, 0x38, 0x30, 0x0F, 0xF8, 0x30, 0x07, 0xF1, 0xF0, 0x03, 0xC1, 0xF0, 0x00, 0x00, // + 0x00, 0x00, 0x00, 0x00, // + 0x03, 0x81, 0xC0, 0x07, 0x81, 0xE0, 0x0F, 0x81, 0xF0, 0x08, 0x10, 0x10, 0x08, 0x10, 0x10, 0x0C, // + 0x30, 0x10, 0x0F, 0xF8, 0x30, 0x07, 0xEF, 0xF0, 0x03, 0xCF, 0xE0, 0x00, 0x03, 0xC0, 0x00, 0x00, // + 0x00, 0x00, 0x00, 0x00, // + 0x00, 0x06, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x3A, 0x00, 0x00, 0xE2, 0x00, 0x01, 0xC2, 0x10, 0x07, // + 0x02, 0x10, 0x0F, 0xFF, 0xF0, 0x1F, 0xFF, 0xF0, 0x1F, 0xFF, 0xF0, 0x00, 0x02, 0x10, 0x00, 0x02, // + 0x10, 0x00, 0x00, 0x00, // + 0x00, 0x01, 0xC0, 0x0F, 0xF9, 0xE0, 0x0F, 0xF9, 0xB0, 0x0C, 0x30, 0x10, 0x0C, 0x20, 0x10, 0x0C, // + 0x20, 0x10, 0x0C, 0x30, 0x70, 0x0C, 0x3F, 0xF0, 0x0C, 0x1F, 0xE0, 0x0C, 0x0F, 0x80, 0x00, 0x00, // + 0x00, 0x00, 0x00, 0x00, // + 0x00, 0x7F, 0x00, 0x03, 0xFF, 0xC0, 0x07, 0xFF, 0xE0, 0x07, 0x18, 0x70, 0x0C, 0x30, 0x30, 0x08, // + 0x20, 0x10, 0x08, 0x20, 0x10, 0x0E, 0x30, 0x30, 0x0E, 0x3F, 0xE0, 0x06, 0x1F, 0xE0, 0x00, 0x0F, // + 0x80, 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, 0x07, 0x80, 0x00, 0x0F, 0x80, 0x00, 0x0E, 0x00, 0x00, 0x0C, 0x01, 0xF0, 0x0C, // + 0x0F, 0xF0, 0x0C, 0x3F, 0xF0, 0x0D, 0xF0, 0x00, 0x0F, 0xC0, 0x00, 0x0E, 0x00, 0x00, 0x0C, 0x00, // + 0x00, 0x00, 0x00, 0x00, // + 0x03, 0xC3, 0xC0, 0x07, 0xEF, 0xE0, 0x0F, 0xEF, 0xE0, 0x0C, 0x78, 0x30, 0x08, 0x30, 0x10, 0x08, // + 0x38, 0x10, 0x08, 0x18, 0x10, 0x0C, 0x3C, 0x30, 0x0F, 0xEF, 0xF0, 0x07, 0xE7, 0xE0, 0x03, 0x83, // + 0xC0, 0x00, 0x00, 0x00, // + 0x01, 0xF0, 0x00, 0x07, 0xF8, 0x60, 0x07, 0xFC, 0x70, 0x0E, 0x0C, 0x70, 0x08, 0x04, 0x10, 0x08, // + 0x04, 0x10, 0x08, 0x0C, 0x30, 0x0E, 0x19, 0xE0, 0x07, 0xFF, 0xE0, 0x03, 0xFF, 0x80, 0x00, 0xFE, // + 0x00, 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x70, 0x00, // + 0xE0, 0x70, 0x00, 0xE0, 0x70, 0x00, 0xE0, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // + 0x00, 0x00, 0x00, 0x00, // +}; + +static FontLibrary_t fontclocklib = { + .font = fontclocklib_code, + .fontIndex = "0123456789:", + .fontIndexLen = 12, + .fontCode = kgbk, + .isAscii = true, + .widthPixel = 24, + .heightPixel = 24, +}; +#endif + +// DB 00H 00H 07H F0H 0FH F8H 18H 0CH 10H 04H 18H 0CH 0FH F8H 07H F0H;"0",0 +// DB 10H 08H 10H 08H 3FH F8H 3FH F8H 00H 08H 00H 08H 00H 00H 00H 00H;"1",1 +// DB 1CH 18H 3CH 38H 20H 68H 20H C8H 23H 88H 3FH 18H 1CH 18H 00H 00H;"2",2 +// DB 18H 30H 38H 38H 22H 08H 22H 08H 27H 18H 3DH F0H 18H E0H 00H 00H;"3",3 +// DB 01H C0H 07H C0H 0EH 48H 18H 48H 3FH F8H 3FH F8H 00H 48H 00H 00H;"4",4 +// DB 3FH 30H 3FH 38H 23H 08H 22H 08H 23H 18H 21H F0H 20H E0H 00H 00H;"5",5 +// DB 0FH E0H 1FH F0H 33H 18H 22H 08H 33H 18H 31H F0H 00H E0H 00H 00H;"6",6 +// DB 38H 00H 38H 00H 21H F8H 27H F8H 3EH 00H 38H 00H 20H 00H 00H 00H;"7",7 +// DB 1CH 70H 3EH F8H 23H 88H 21H 08H 23H 88H 3EH F8H 1CH 70H 00H 00H;"8",8 +// DB 0EH 00H 1FH 18H 31H 98H 20H 88H 31H 98H 1FH F0H 0FH E0H 00H 00H;"9",9 +// DB 00H 00H 00H 00H 06H 18H 06H 18H 06H 18H 00H 00H 00H 00H 00H 00H;":",10 + +#if 0 +//32*32 +const uint8_t fontclocklib_code[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xC0, 0xC0, 0x40, 0x40, 0xC0, 0xC0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xFE, 0xFF, 0x0F, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x07, 0xFF, 0xFE, 0xF0, + 0x00, 0x00, 0x1F, 0xFF, 0xFF, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x07, 0x06, 0x04, 0x04, 0x06, 0x07, 0x03, 0x01, 0x00, 0x00, /*"0",0*/ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xC0, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x04, 0x04, 0x06, 0x07, 0x07, 0x07, 0x06, 0x04, 0x04, 0x04, 0x00, 0x00, /*"1",1*/ + 0x00, 0x00, 0x00, 0x00, 0x80, 0xC0, 0x40, 0x40, 0x40, 0x40, 0xC0, 0xC0, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x1E, 0x1F, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC1, 0xFF, 0x7F, 0x3E, 0x00, + 0x00, 0x00, 0x00, 0x80, 0xC0, 0x60, 0x30, 0x18, 0x0C, 0x06, 0x03, 0x01, 0x00, 0xE0, 0xE0, 0x00, 0x00, 0x00, 0x07, 0x07, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x07, 0x07, 0x01, 0x00, /*"2",2*/ + 0x00, 0x00, 0x00, 0x80, 0x80, 0xC0, 0x40, 0x40, 0x40, 0xC0, 0xC0, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x0F, 0x00, 0x80, 0x80, 0x80, 0xC0, 0xE1, 0x7F, 0x3F, 0x1E, 0x00, 0x00, + 0x00, 0x00, 0xE0, 0xE0, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x03, 0xFF, 0xFE, 0x78, 0x00, 0x00, 0x00, 0x01, 0x03, 0x03, 0x06, 0x04, 0x04, 0x04, 0x04, 0x06, 0x03, 0x03, 0x01, 0x00, 0x00, /*"3",3*/ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xC0, 0xC0, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xE0, 0x70, 0x3C, 0x0E, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x1C, 0x1E, 0x13, 0x11, 0x10, 0x10, 0x10, 0xFF, 0xFF, 0xFF, 0xFF, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x0F, 0x0F, 0x0F, 0x0F, 0x08, 0x08, 0x08, /*"4",4*/ + 0x00, 0x00, 0x00, 0x00, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0xC7, 0x60, 0x20, 0x20, 0x20, 0x60, 0xE0, 0xC0, 0x80, 0x00, 0x00, + 0x00, 0x00, 0xE0, 0xE1, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xFF, 0xFF, 0x7E, 0x00, 0x00, 0x00, 0x01, 0x03, 0x06, 0x04, 0x04, 0x04, 0x04, 0x04, 0x06, 0x03, 0x03, 0x01, 0x00, 0x00, /*"5",5*/ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xC0, 0xC0, 0x40, 0x40, 0x40, 0xC0, 0x80, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xFC, 0xFE, 0x8F, 0x81, 0xC0, 0x40, 0x40, 0x40, 0xC0, 0xC3, 0x83, 0x03, 0x00, + 0x00, 0x00, 0x3F, 0xFF, 0xFF, 0xC3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xFF, 0xFF, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x07, 0x06, 0x04, 0x04, 0x04, 0x06, 0x03, 0x03, 0x01, 0x00, /*"6",6*/ + 0x00, 0x00, 0x00, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x03, 0x01, 0x00, 0x00, 0x80, 0xE0, 0x78, 0x1E, 0x07, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xFC, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x07, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"7",7*/ + 0x00, 0x00, 0x00, 0x00, 0x80, 0xC0, 0xC0, 0x40, 0x40, 0x40, 0xC0, 0xC0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1E, 0x3F, 0x7F, 0xF1, 0xE0, 0xC0, 0x80, 0x80, 0x80, 0xE1, 0x7F, 0x3F, 0x1E, 0x00, + 0x00, 0xF8, 0xFC, 0xFE, 0x07, 0x03, 0x01, 0x01, 0x01, 0x03, 0x07, 0x0F, 0xFE, 0xFC, 0xF8, 0x00, 0x00, 0x00, 0x01, 0x03, 0x03, 0x06, 0x04, 0x04, 0x04, 0x04, 0x06, 0x03, 0x03, 0x01, 0x00, 0x00, /*"8",8*/ + 0x00, 0x00, 0x00, 0x80, 0x80, 0xC0, 0x40, 0x40, 0x40, 0x40, 0xC0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x83, 0xFF, 0xFE, 0xF8, 0x00, + 0x00, 0x00, 0x81, 0x83, 0x87, 0x06, 0x04, 0x04, 0x04, 0x06, 0x83, 0xF3, 0xFF, 0x7F, 0x0F, 0x00, 0x00, 0x00, 0x03, 0x03, 0x07, 0x04, 0x04, 0x04, 0x06, 0x07, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, /*"9",9*/ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xE0, 0xE0, 0xE0, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x81, 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x07, 0x07, 0x07, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, /*":",10*/ +}; +static FontLibrary_t fontclocklib = { + .font = fontclocklib_code, + .fontIndex = "0123456789:", + .fontIndexLen = 12, + .fontCode = kgbk, + .isAscii = true, + .widthPixel = 16, + .heightPixel = 32, +}; +#endif + +// 24*24 +const uint8_t fontclocklib_code[] = { + + 0x00, 0x00, 0x80, 0xC0, 0xE0, 0x60, 0x20, 0x60, 0xE0, 0xC0, 0x80, 0x00, 0x00, 0xFE, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x01, 0xFF, 0xFF, 0xFE, 0x00, 0x01, 0x07, 0x0F, 0x1E, 0x18, 0x10, 0x18, 0x1E, 0x0F, 0x07, 0x01, /*"0",0*/ + 0x00, 0x00, 0x80, 0x80, 0x80, 0xC0, 0xE0, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x1F, 0x1F, 0x1F, 0x10, 0x10, 0x10, 0x00, /*"1",1*/ + 0x00, 0x80, 0xC0, 0x60, 0x20, 0x20, 0x20, 0x60, 0xE0, 0xC0, 0x80, 0x00, 0x00, 0x03, 0x03, 0x03, 0x80, 0xC0, 0x60, 0x38, 0x3F, 0x1F, 0x07, 0x00, 0x00, 0x1C, 0x1E, 0x1B, 0x19, 0x18, 0x18, 0x18, 0x18, 0x1F, 0x1F, 0x00, /*"2",2*/ + 0x00, 0x80, 0xC0, 0xE0, 0x20, 0x20, 0x60, 0xE0, 0xC0, 0x80, 0x00, 0x00, 0x00, 0x03, 0x03, 0x03, 0x10, 0x10, 0x18, 0x3F, 0xEF, 0xE7, 0x80, 0x00, 0x00, 0x07, 0x0F, 0x1F, 0x10, 0x10, 0x10, 0x18, 0x1F, 0x0F, 0x07, 0x00, /*"3",3*/ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF0, 0x00, 0x00, 0x00, 0xC0, 0xF0, 0xB8, 0x8E, 0x87, 0x81, 0xFF, 0xFF, 0xFF, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x1F, 0x1F, 0x1F, 0x10, 0x10, /*"4",4*/ + 0x00, 0x00, 0xE0, 0xE0, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x00, 0x00, 0x00, 0x3F, 0x3F, 0x18, 0x08, 0x08, 0x18, 0xF8, 0xF0, 0xE0, 0x00, 0x00, 0x07, 0x0F, 0x1B, 0x10, 0x10, 0x10, 0x1C, 0x1F, 0x0F, 0x03, 0x00, /*"5",5*/ + 0x00, 0x00, 0x80, 0xC0, 0xC0, 0x60, 0x20, 0x20, 0xE0, 0xE0, 0xC0, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0x31, 0x18, 0x08, 0x08, 0x18, 0xF8, 0xF0, 0xE0, 0x00, 0x01, 0x07, 0x0F, 0x1C, 0x18, 0x10, 0x10, 0x18, 0x0F, 0x0F, 0x03, /*"6",6*/ + 0x00, 0x00, 0xC0, 0xE0, 0xE0, 0x60, 0x60, 0x60, 0x60, 0xE0, 0xE0, 0x60, 0x00, 0x00, 0x03, 0x03, 0x00, 0x00, 0xE0, 0xF8, 0x1F, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x1F, 0x1F, 0x00, 0x00, 0x00, 0x00, /*"7",7*/ + 0x00, 0x80, 0xC0, 0xE0, 0x60, 0x20, 0x20, 0x20, 0x60, 0xE0, 0xC0, 0x80, 0x00, 0x87, 0xEF, 0xEF, 0x3C, 0x18, 0x38, 0x30, 0x78, 0xEF, 0xCF, 0x83, 0x00, 0x07, 0x0F, 0x0F, 0x18, 0x10, 0x10, 0x10, 0x18, 0x1F, 0x0F, 0x07, /*"8",8*/ + 0x00, 0x00, 0xC0, 0xC0, 0xE0, 0x20, 0x20, 0x20, 0xE0, 0xC0, 0x80, 0x00, 0x00, 0x1F, 0x3F, 0x7F, 0x60, 0x40, 0x40, 0x60, 0x30, 0xFF, 0xFF, 0xFE, 0x00, 0x00, 0x0C, 0x1C, 0x1C, 0x10, 0x10, 0x18, 0x0F, 0x0F, 0x03, 0x00, /*"9",9*/ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x0E, 0x0E, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x1C, 0x1C, 0x1C, 0x00, 0x00, 0x00, /*":",10*/ + +}; +static FontLibrary_t fontclocklib = { + .font = fontclocklib_code, + .fontIndex = "0123456789:", + .fontIndexLen = 12, + .fontCode = kgbk, + .isAscii = true, + .widthPixel = 12, + .heightPixel = 24, +}; + +const uint8_t font8x8_xo_code[] = { + 0x00, 0x3C, 0x7E, 0x7E, 0x7E, 0x7E, 0x3C, 0x00, /*实心圆,代表完成*/ + 0x00, 0x3C, 0x42, 0x42, 0x42, 0x42, 0x3C, 0x00, /*空心圆,代表未完成*/ + +}; + +static FontLibrary_t font8x8_xo_lib = { + .font = font8x8_xo_code, + .fontIndex = "ox", + .fontIndexLen = 2, + .fontCode = kgbk, + .isAscii = true, + .widthPixel = 8, + .heightPixel = 8, +}; + +const uint8_t font12x24_asiic_code[] = { + + 0x00, 0x00, 0xC0, 0xE0, 0x70, 0x30, 0x30, 0x60, 0xE0, 0xC0, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xFF, 0xFE, 0x00, 0x00, 0x01, 0x07, 0x0E, 0x0C, 0x18, 0x18, 0x0C, 0x0F, 0x07, 0x00, 0x00, /*"0",0*/ + 0x00, 0x00, 0x00, 0x80, 0xC0, 0xE0, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x01, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, /*"1",1*/ + 0x00, 0x80, 0xE0, 0x60, 0x30, 0x30, 0x30, 0x70, 0xE0, 0xC0, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x80, 0xC0, 0xE0, 0x38, 0x1F, 0x07, 0x00, 0x00, 0x00, 0x08, 0x0E, 0x0F, 0x0B, 0x09, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, /*"2",2*/ + 0x00, 0x80, 0xC0, 0x60, 0x30, 0x30, 0x30, 0x30, 0xE0, 0xC0, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x18, 0x18, 0x38, 0x7F, 0xE7, 0x80, 0x00, 0x00, 0x03, 0x07, 0x0C, 0x18, 0x18, 0x18, 0x0C, 0x0E, 0x07, 0x01, 0x00, /*"3",3*/ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0x00, 0x00, 0x00, 0x80, 0xC0, 0xF0, 0xB8, 0x8E, 0x87, 0x81, 0xFF, 0xFF, 0x80, 0x80, 0x80, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x0F, 0x0F, 0x01, 0x01, 0x01, /*"4",4*/ + 0x00, 0x00, 0xE0, 0xE0, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0x1C, 0x1F, 0x0D, 0x04, 0x04, 0x0C, 0x0C, 0x3C, 0xF8, 0xC0, 0x00, 0x01, 0x07, 0x0E, 0x08, 0x18, 0x18, 0x18, 0x0C, 0x0F, 0x07, 0x00, 0x00, /*"5",5*/ + 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xF0, 0x30, 0x10, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xF8, 0x1E, 0x0F, 0x0D, 0x0C, 0x0C, 0x18, 0xF8, 0xF0, 0x00, 0x00, 0x03, 0x07, 0x0C, 0x18, 0x18, 0x18, 0x18, 0x0C, 0x0F, 0x03, 0x00, /*"6",6*/ + 0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0xA0, 0xE0, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xF8, 0x1E, 0x07, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x0F, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"7",7*/ + 0x00, 0x80, 0xE0, 0x60, 0x30, 0x30, 0x30, 0x20, 0xE0, 0xC0, 0x00, 0x00, 0x00, 0xE3, 0xFF, 0x3C, 0x18, 0x18, 0x18, 0x3C, 0x3F, 0xE7, 0xC0, 0x00, 0x00, 0x07, 0x0F, 0x0C, 0x18, 0x18, 0x18, 0x18, 0x0C, 0x07, 0x03, 0x00, /*"8",8*/ + 0x00, 0xC0, 0xE0, 0x60, 0x30, 0x30, 0x30, 0x60, 0xE0, 0xC0, 0x00, 0x00, 0x02, 0x1F, 0x3D, 0x30, 0x60, 0x60, 0xE0, 0xF0, 0x7F, 0x1F, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10, 0x1C, 0x0F, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, /*"9",9*/ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x0C, 0x1C, 0xF0, 0xE0, 0xE0, 0x38, 0x1C, 0x04, 0x00, 0x00, 0x00, 0x10, 0x1C, 0x0E, 0x03, 0x01, 0x03, 0x07, 0x0E, 0x18, 0x10, 0x00, /*"x",10*/ + 0x00, 0x30, 0xF0, 0xE0, 0x00, 0x00, 0x00, 0x80, 0xE0, 0x70, 0x10, 0x00, 0x00, 0x00, 0x00, 0x83, 0xEF, 0x7C, 0x7E, 0xE7, 0x81, 0x00, 0x00, 0x00, 0x10, 0x1C, 0x1F, 0x07, 0x01, 0x00, 0x00, 0x01, 0x0F, 0x1E, 0x18, 0x00, /*"X",11*/ + 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x60, 0x60, 0x60, 0x60, 0x60, 0x00, /*"[",12*/ + 0x00, 0x0C, 0x0C, 0x0C, 0x0C, 0xFC, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x60, 0x60, 0x60, 0x7F, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, + /*"]",13*/}; + +static FontLibrary_t font12x24_asiic_lib = { + .font = font12x24_asiic_code, + .fontIndex = "0123456789xX[]", + .fontIndexLen = 15, + .fontCode = kgbk, + .isAscii = true, + .widthPixel = 12, + .heightPixel = 24, +}; + +const uint8_t font24x24_zh_code[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xF8, 0x38, 0x10, 0x10, 0xF0, 0x90, 0x10, 0x10, 0x10, 0x88, 0xF8, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x10, 0x0C, 0x06, 0xE7, 0x1C, 0x10, 0x10, 0x10, 0x10, 0x93, + 0x71, 0xFF, 0x39, 0x49, 0x89, 0x08, 0x08, 0x0C, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x04, 0x02, 0x01, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x03, 0x07, 0x06, 0x06, 0x04, 0x04, 0x00, /*"保",0*/ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xFC, 0xFC, 0xC0, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xC2, 0x63, 0x33, 0xFF, 0x0D, 0x09, 0x08, 0x48, + 0x48, 0x49, 0x48, 0x47, 0x4F, 0xFC, 0x24, 0x24, 0x26, 0x06, 0x04, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x08, 0x38, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x02, 0x20, 0x60, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"持",1*/ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x40, 0xFC, 0x20, 0xA0, 0x20, 0x00, 0x80, 0x60, 0x3C, 0x2C, 0xA0, 0x70, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x0C, 0x94, 0x75, 0x55, 0x57, 0x15, 0xF4, 0x02, 0x90, + 0x92, 0x92, 0x92, 0xFF, 0x92, 0x8A, 0x49, 0x3F, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x18, 0x0F, 0x02, 0x01, 0x09, 0x18, 0x0F, 0x00, 0x00, 0x00, 0x20, 0x60, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"静",2*/ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0xF8, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xF8, 0x00, 0x00, 0x00, + 0xFF, 0x0F, 0x08, 0x08, 0x08, 0x0C, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x18, 0x08, 0x08, 0x08, 0x0F, 0x08, 0x08, 0x0C, 0x0F, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x00, 0x00, /*"止",3*/ + 0x00, 0x00, 0x00, 0x00, 0x40, 0x60, 0x60, 0x60, 0x20, 0x20, 0x20, 0x20, 0xA0, 0xE0, 0x30, 0x30, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xC0, 0x60, 0x30, 0x0D, 0xFF, + 0x03, 0x00, 0x00, 0x10, 0x20, 0x60, 0xE0, 0xC0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x04, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x00, 0x00, 0x00, /*"不",4*/ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0xE0, 0x20, 0x20, 0x10, 0x10, 0x10, 0xF8, 0xF8, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x70, 0x61, 0x87, 0x82, 0x06, 0xFE, + 0x12, 0x11, 0x11, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x04, 0x03, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x03, 0x02, 0x06, 0x0C, 0x0C, 0x18, 0x18, 0x18, 0x18, 0x18, 0x10, 0x00, 0x00, /*"足",5*/ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x40, 0xE0, 0x30, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x04, 0xC4, 0x64, 0x1A, 0xFF, 0x12, 0x32, 0x00, 0x18, + 0x0F, 0x00, 0x00, 0x1F, 0x80, 0xE0, 0x3C, 0x08, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x40, 0x20, 0x30, 0x18, 0x0C, 0x06, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"秒",6*/ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x20, 0x20, 0x38, 0xF8, 0x20, 0x20, 0x20, 0x60, 0x9C, 0x24, 0x10, 0x10, 0x10, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x67, 0x7E, 0x00, + 0x10, 0x8C, 0x9B, 0xB9, 0xE4, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x20, 0x20, 0x20, 0x23, 0x3F, 0x11, 0x13, 0x1D, 0x11, 0x1D, 0x17, 0x10, 0x18, 0x1F, 0x11, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, /*"蓝",7*/ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x10, 0x10, 0x10, 0x10, 0x10, 0xF0, 0x18, 0x18, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x0F, 0x04, 0x84, 0x64, 0x34, 0x1E, + 0x06, 0xFF, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x04, 0x02, 0x01, 0x00, 0x00, 0x10, 0x20, 0x70, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"牙",8*/ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x10, 0xF0, 0x70, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x0E, 0x08, 0x08, 0x08, 0x04, 0x04, 0x07, + 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x06, 0x08, 0x08, 0x18, 0x18, 0x18, 0x10, 0x18, 0x18, 0x18, 0x18, 0x08, 0x08, 0x0C, 0x0E, 0x07, 0x00, 0x00, 0x00, /*"已",9*/ + 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x30, 0x10, 0xC0, 0xC0, 0x00, 0x00, 0x40, 0x20, 0x20, 0xA0, 0xF0, 0x30, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x67, 0x74, 0x2C, 0x26, 0x01, 0x00, 0x10, 0x50, + 0x48, 0x44, 0xC3, 0xC3, 0x62, 0x24, 0x2C, 0x0C, 0x18, 0x10, 0x00, 0x00, 0x00, 0x00, 0x04, 0x04, 0x04, 0x06, 0x02, 0x02, 0x01, 0x10, 0x18, 0x08, 0x08, 0x08, 0x0F, 0x0B, 0x08, 0x08, 0x08, 0x0C, 0x0C, 0x08, 0x00, 0x00, /*"经",10*/ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0xC0, 0x00, 0x00, 0x40, 0x40, 0xC0, 0xE0, 0x5C, 0x2C, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x08, 0xF8, 0x08, 0x00, 0x40, 0x48, 0x4E, 0x4B, + 0x44, 0x45, 0xFF, 0x24, 0x24, 0x24, 0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x08, 0x0C, 0x04, 0x07, 0x04, 0x04, 0x08, 0x08, 0x08, 0x08, 0x10, 0x10, 0x17, 0x30, 0x30, 0x30, 0x30, 0x30, 0x10, 0x10, 0x00, 0x00, /*"连",11*/ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x88, 0x98, 0xD0, 0xC0, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x82, 0xC2, 0x62, 0xFF, 0x11, 0x91, 0x80, 0x80, 0x90, + 0x92, 0xF4, 0xB0, 0x98, 0x97, 0x89, 0x48, 0x48, 0x48, 0x40, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x18, 0x3F, 0x0F, 0x00, 0x00, 0x20, 0x20, 0x13, 0x12, 0x0C, 0x06, 0x0F, 0x08, 0x18, 0x30, 0x20, 0x00, 0x00, 0x00, /*"接",12*/ + 0x00, 0x00, 0x00, 0xE0, 0x40, 0x40, 0x80, 0x00, 0xF8, 0x88, 0x40, 0x20, 0x00, 0x80, 0x80, 0x40, 0x40, 0x20, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x80, 0x40, 0x25, 0x1A, 0xFF, 0x12, 0x12, 0x12, + 0x00, 0xE0, 0x3F, 0x08, 0x04, 0xFC, 0xFC, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x04, 0x02, 0x02, 0x02, 0x03, 0x02, 0x12, 0x08, 0x06, 0x01, 0x00, 0x00, 0x00, 0x7F, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, /*"断",13*/ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x60, 0x60, 0xE0, 0x20, 0x20, 0x20, 0x20, 0xF0, 0x30, 0x30, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0xE8, 0x3F, 0x08, 0x08, + 0x04, 0x04, 0xFF, 0x04, 0x04, 0x04, 0x04, 0x04, 0x06, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x08, 0x04, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"开",14*/ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9C, 0xF8, 0x80, 0x80, 0x80, 0x80, 0xC0, 0xC0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x7F, 0x81, 0x89, 0x49, 0xC8, 0xFF, 0x4C, + 0x44, 0x44, 0x40, 0x3C, 0x0F, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x0F, 0x18, 0x10, 0x10, 0x30, 0x30, 0x30, 0x10, 0x10, 0x1A, 0x1C, 0x00, 0x00, 0x00, /*"电",15*/ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x78, 0xA8, 0xA8, 0xA8, 0xA8, 0x88, 0xE4, 0x7C, 0x18, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x04, 0x04, 0x04, 0x04, 0x14, 0xF4, 0x94, 0x14, 0x52, 0xF2, + 0xAA, 0xAA, 0x8A, 0xFA, 0x3A, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x20, 0x20, 0x24, 0x25, 0x25, 0x25, 0x3F, 0x24, 0x24, 0x27, 0x30, 0x30, 0x30, 0x30, 0x20, 0x00, 0x00, 0x00, 0x00, /*"量",16*/ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x40, 0x40, 0x40, 0xC0, 0xC6, 0xFC, 0xA0, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x10, 0x08, 0x24, 0xE6, 0xA3, 0xA1, 0x94, 0xAF, + 0x10, 0x11, 0xF3, 0xF6, 0x2C, 0x0C, 0x18, 0x18, 0x18, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x20, 0x20, 0x20, 0x21, 0x27, 0x24, 0x24, 0x34, 0x12, 0x16, 0x13, 0x10, 0x10, 0x10, 0x10, 0x30, 0x00, 0x00, 0x00, 0x00, /*"查",17*/ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA0, 0x90, 0x90, 0xF0, 0xB8, 0x88, 0x8C, 0xCC, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0xC8, 0x78, 0xFC, 0xA7, 0xA4, + 0xA4, 0xA4, 0x14, 0x14, 0xF2, 0x22, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x10, 0x10, 0x08, 0x04, 0x02, 0x01, 0x00, 0x00, 0x3F, 0x14, 0x14, 0x14, 0x12, 0x10, 0x30, 0x7F, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"看",18*/ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x60, 0x38, 0x10, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x38, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0xC6, 0x65, 0x3C, 0x2C, 0x23, 0x01, 0x80, 0x02, + 0x22, 0x22, 0x22, 0x22, 0x3F, 0x91, 0x91, 0x91, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x04, 0x0C, 0x04, 0x06, 0x02, 0x02, 0x01, 0x01, 0x00, 0x00, 0x03, 0x1F, 0x09, 0x09, 0x09, 0x08, 0x08, 0x0F, 0x01, 0x00, 0x00, 0x00, /*"结",19*/ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x30, 0xF0, 0x10, 0x90, 0x90, 0xF0, 0xF0, 0xD0, 0x10, 0x88, 0xF8, 0x78, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x60, 0x21, 0x27, 0xA4, 0x64, 0xFF, + 0x52, 0x92, 0x12, 0x13, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x20, 0x10, 0x08, 0x04, 0x06, 0x03, 0x01, 0x00, 0x7F, 0x00, 0x00, 0x01, 0x02, 0x06, 0x0C, 0x18, 0x18, 0x18, 0x10, 0x00, 0x00, /*"果",20*/ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x20, 0x20, 0xD0, 0x90, 0x18, 0x0C, 0x88, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x20, 0x60, 0x20, 0x20, 0x20, 0x22, 0x22, 0x33, 0x11, + 0xFF, 0x11, 0x11, 0x11, 0x11, 0x10, 0x18, 0x18, 0x18, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x20, 0x60, 0x78, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"手",21*/ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xC0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x86, 0xC2, 0x32, 0x0F, 0xFF, 0x21, 0x61, 0x01, 0x01, + 0xFF, 0x01, 0x01, 0x00, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x04, 0x02, 0x01, 0x00, 0x00, 0x3F, 0x0F, 0x00, 0x08, 0x04, 0x03, 0x01, 0x00, 0x00, 0x00, 0x07, 0x06, 0x0C, 0x0C, 0x0C, 0x0F, 0x06, 0x00, /*"机",22*/ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x20, 0x20, 0x50, 0xD0, 0x88, 0x0C, 0x8C, 0x40, 0x70, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x11, 0xD0, 0x70, 0x32, 0xFC, 0x30, + 0x48, 0x88, 0x88, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x04, 0x02, 0x01, 0x00, 0x00, 0x30, 0x7F, 0x00, 0x00, 0x00, 0x01, 0x03, 0x06, 0x06, 0x0C, 0x0C, 0x04, 0x08, 0x00, 0x00, /*"采",23*/ + 0x00, 0x00, 0x00, 0x00, 0x80, 0x40, 0x20, 0xF0, 0x0C, 0x24, 0xA0, 0xA4, 0xEC, 0xE8, 0x90, 0x50, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0xBF, 0x90, 0x90, 0xD2, 0xF2, + 0xCF, 0x4B, 0x4A, 0x49, 0x48, 0x48, 0x60, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x10, 0x10, 0x08, 0x04, 0x06, 0x03, 0x01, 0x7F, 0x00, 0x01, 0x02, 0x04, 0x0C, 0x18, 0x18, 0x18, 0x10, 0x10, 0x00, 0x00, /*"集",24*/ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x7C, 0xC0, 0x80, 0x80, 0x88, 0x98, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xFE, 0x42, 0x42, 0x22, 0x22, 0xE1, 0x21, + 0x03, 0x1F, 0x70, 0x80, 0xE0, 0x3C, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x08, 0x06, 0x03, 0x00, 0x04, 0x08, 0x1C, 0x07, 0x00, 0x08, 0x04, 0x02, 0x01, 0x07, 0x0C, 0x18, 0x30, 0x70, 0x78, 0x00, 0x00, /*"成",25*/ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x81, 0x81, 0xC1, 0x7F, 0x20, 0x20, 0x20, 0x12, + 0x82, 0xE2, 0x3E, 0x07, 0x02, 0x01, 0x01, 0xFF, 0x0F, 0x02, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x10, 0x10, 0x08, 0x04, 0x03, 0x01, 0x00, 0x04, 0x08, 0x38, 0x1C, 0x0F, 0x01, 0x00, 0x00, 0x00, 0x00, /*"功",26*/ + 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x80, 0x80, 0x80, 0x40, 0x48, 0x58, 0x50, 0x40, 0x20, 0x20, 0xA0, 0xE0, 0xC0, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x01, 0x40, 0x60, 0x24, 0xE4, 0x26, 0x22, + 0xF2, 0x12, 0x10, 0x10, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x08, 0x04, 0x06, 0x03, 0x00, 0x00, 0x00, 0x1F, 0x30, 0x20, 0x20, 0x20, 0x20, 0x20, 0x30, 0x3E, 0x10, 0x00, 0x00, /*"完",27*/ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x78, 0x10, 0x00, 0x80, 0x80, 0x40, 0x40, 0xA0, 0x38, 0x18, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x18, 0x0C, 0x03, 0xFD, 0x00, 0x00, 0x00, 0xE1, 0xFF, + 0x10, 0x88, 0x0F, 0x3C, 0xE4, 0x84, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x1F, 0x00, 0x00, 0x04, 0x0F, 0x03, 0x01, 0x00, 0x04, 0x0C, 0x00, 0x01, 0x06, 0x0C, 0x18, 0x3E, 0x30, 0x00, /*"低",28*/ +}; +static FontLibrary_t font24x24_zh_lib = { + .font = font24x24_zh_code, + .fontIndex = "保持静止不足秒蓝牙已经连接断开电量查看结果手机采集成功完低", + .fontIndexLen = 88, + .fontCode = kgbk, + .isAscii = false, + .widthPixel = 24, + .heightPixel = 24, +}; + +#if 0 +// const unsigned char gImage_heart_16x16[] = { +// /* 0X22,0X01,0X10,0X00,0X10,0X00, */ +// 0X00, 0XF8, 0XFC, 0XFE, 0XFE, 0XFE, 0XFE, 0XFC, 0XFC, 0XFE, 0XFE, 0XFE, 0XFE, 0XFC, 0XF8, 0X00, 0X00, 0X00, 0X03, 0X07, 0X0F, 0X1F, 0X3F, 0X7F, 0X7F, 0X3F, 0X1F, 0X0F, 0X07, 0X03, 0X00, 0X00, +// }; +#endif + +const unsigned char font_asicc_code_16x8[] = { + 0x00, 0xF0, 0x18, 0x08, 0x08, 0x18, 0xE0, 0x00, 0x00, 0x0F, 0x10, 0x20, 0x30, 0x18, 0x0F, 0x00, /*"0",0*/ + 0x00, 0x60, 0x20, 0xF0, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x3F, 0x00, 0x00, 0x00, /*"1",1*/ + 0x00, 0x30, 0x18, 0x08, 0x08, 0xD8, 0x70, 0x00, 0x00, 0x30, 0x38, 0x34, 0x33, 0x31, 0x30, 0x00, /*"2",2*/ + 0x00, 0x30, 0x18, 0x08, 0x88, 0xD8, 0x70, 0x00, 0x00, 0x18, 0x10, 0x20, 0x21, 0x13, 0x0E, 0x00, /*"3",3*/ + 0x00, 0x00, 0x80, 0x60, 0x30, 0xF8, 0x00, 0x00, 0x04, 0x07, 0x05, 0x04, 0x04, 0x3F, 0x04, 0x04, /*"4",4*/ + 0x00, 0xF0, 0x98, 0xC8, 0x88, 0x88, 0x08, 0x00, 0x08, 0x19, 0x30, 0x20, 0x30, 0x19, 0x0F, 0x00, /*"5",5*/ + 0x00, 0x80, 0xC0, 0xF0, 0x98, 0x80, 0x00, 0x00, 0x00, 0x1F, 0x31, 0x20, 0x20, 0x30, 0x1F, 0x06, /*"6",6*/ + 0x00, 0x08, 0x08, 0x08, 0x88, 0xE8, 0x38, 0x00, 0x00, 0x00, 0x30, 0x3E, 0x03, 0x00, 0x00, 0x00, /*"7",7*/ + 0x00, 0xF0, 0x88, 0x88, 0x88, 0xD8, 0x70, 0x00, 0x04, 0x1F, 0x31, 0x21, 0x21, 0x31, 0x1E, 0x00, /*"8",8*/ + 0xE0, 0xF0, 0x08, 0x08, 0x08, 0x98, 0xF0, 0x00, 0x00, 0x01, 0x23, 0x3A, 0x0F, 0x03, 0x00, 0x00, /*"9",9*/ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, /*"-",10*/ + 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x11, 0x00, 0x00, 0x00, /*":",10*/ + + 0X00, 0XF8, 0XFC, 0XFE, 0XFE, 0XFE, 0XFE, 0XFC, 0X00, 0X00, 0X03, 0X07, 0X0F, 0X1F, 0X3F, 0X7F, /*?右半*/ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*" "*/ +}; + +static FontLibrary_t font_asicc16x8_lib = { + .font = font_asicc_code_16x8, + .fontIndex = "0123456789-:<> ", // <> 这两个符号是心形的左右半边 + .fontIndexLen = 16, + .fontCode = kgbk, + .isAscii = true, + .widthPixel = 8, + .heightPixel = 16, +}; diff --git a/app/src/heart_wave_sample_service.c b/app/src/heart_wave_sample_service.c new file mode 100644 index 0000000..0a40ecf --- /dev/null +++ b/app/src/heart_wave_sample_service.c @@ -0,0 +1,183 @@ +#include "heart_wave_sample_service.h" + +#include "app_event.h" +#include "app_event_distribute.h" +#include "nrfx_timer.h" +#include "one_conduction_board.h" +static const nrfx_timer_t m_timer = NRFX_TIMER_INSTANCE(1); /**< Timer used for channel sweeps and tx with duty cycle. */ +static bool m_timer_started = false; /**< True if timer is running. */ + +static uint16_t m_capture_buffer_a[128]; +static uint16_t m_capture_buffer_b[128]; + +static uint16_t* m_capture_buffer; +static uint16_t m_capture_buffer_index = 0; + +volatile static float m_sensor_display_data = 0; // 0->100 +static uint32_t m_start_capture_tp; +static uint32_t m_frame_index = 0; + +static one_frame_data_t m_sensor_little_frame_cache[LITTLE_DATA_BLOCK_FRAME_NUM]; +static uint32_t m_little_frame_index; + +static void swap_buffer() { + if (m_capture_buffer == NULL) { + m_capture_buffer = m_capture_buffer_a; + m_capture_buffer_index = 0; + return; + } + + if (m_capture_buffer == m_capture_buffer_a) { + m_capture_buffer = m_capture_buffer_b; + } else { + m_capture_buffer = m_capture_buffer_a; + } + m_capture_buffer_index = 0; + return; +} +static float amp_val(uint16_t val, uint16_t valcener, float amp) { + float valf = (float)val - valcener; + valf = valf * amp; + valf += valcener; + + if (valf >= 100) { + valf = 100; + } + + if (valf <= 0) { + valf = 0; + } + return valf; +} + +typedef struct { + float value; + float efectiveFactor; +} filter_t; + +filter_t m_filter = {0, 0.8}; + +static float Filter(filter_t* filter, float newInput) { + float newv = ((float)filter->value * (1.0f - filter->efectiveFactor)) + ((float)newInput * filter->efectiveFactor); + filter->value = newv; + return newv; +} + +/******************************************************************************* + * 小包数据上报 * + *******************************************************************************/ +static inline void prvf_little_block_cache_push_one_frame(uint16_t data) { + if (m_little_frame_index >= LITTLE_DATA_BLOCK_FRAME_NUM) { + return; + } + m_sensor_little_frame_cache[m_little_frame_index].data = data; + m_little_frame_index++; +} + +static inline bool prvf_light_block_cache_is_full(void) { + if (m_little_frame_index >= LITTLE_DATA_BLOCK_FRAME_NUM) { + return true; + } + return false; +} +static inline void prvf_light_block_cache_clear(void) { m_little_frame_index = 0; } +static inline void prvf_light_block_trigger_event() { + static app_event_t event; + event.eventType = kevent_capture_little_data_block_event; + for (uint32_t i = 0; i < LITTLE_DATA_BLOCK_FRAME_NUM; i++) { + event.val.little_data_block.data[i].data = m_sensor_little_frame_cache[i].data; + } + event.val.little_data_block.frameIndex = m_frame_index - LITTLE_DATA_BLOCK_FRAME_NUM; + AppEvent_pushEvent(&event); +} + +void nrfx_timer_event_handler(nrf_timer_event_t event_type, void* p_context) { // + uint16_t val = SingleLeadECG_ecg_plod_get_ecg_val(); // 12bit + m_frame_index++; + + /******************************************************************************* + * 显示数据计算并赋值 * + *******************************************************************************/ + float val_af100 = (float)val / 4096.0f * 100; + val_af100 = amp_val(val_af100, 50, 1.8f); + val_af100 = Filter(&m_filter, val_af100); + m_sensor_display_data = val_af100; + + /******************************************************************************* + * 采样数据缓存 * + *******************************************************************************/ + if (m_capture_buffer == NULL) { + swap_buffer(); + } + + if (m_capture_buffer_index < 128) { + m_capture_buffer[m_capture_buffer_index++] = val; + } + + if (m_capture_buffer_index == 128) { + app_event_t evt; + evt.eventType = kevent_capture_256data_event; + evt.val.capture_data_cache = (uint8_t*)m_capture_buffer; + swap_buffer(); + AppEvent_pushEvent(&evt); + } + + /******************************************************************************* + * 实时采样数据事件上报 * + *******************************************************************************/ + /** + * @brief 缓存数据,并触发小数据块事件 + */ + prvf_little_block_cache_push_one_frame(val); + if (prvf_light_block_cache_is_full()) { + prvf_light_block_trigger_event(); + prvf_light_block_cache_clear(); + } +} + +void hwss_init(void) { + if (m_timer_started) { + return; + } + /** + * @brief 初始化定时器 + */ + nrfx_err_t err; + nrfx_timer_config_t timer_cfg = { + .frequency = NRF_TIMER_FREQ_125kHz, + .mode = NRF_TIMER_MODE_TIMER, + .bit_width = NRF_TIMER_BIT_WIDTH_24, + .p_context = NULL, + .interrupt_priority = NRFX_TIMER_DEFAULT_CONFIG_IRQ_PRIORITY, + }; + + err = nrfx_timer_init(&m_timer, &timer_cfg, nrfx_timer_event_handler); + if (err != NRFX_SUCCESS) { + NRF_LOG_ERROR("nrfx_timer_init failed with: %d\n", err); + } + uint32_t timer_ticks = nrfx_timer_ms_to_ticks(&m_timer, 5); // 200HZ + nrfx_timer_extended_compare(&m_timer, NRF_TIMER_CC_CHANNEL0, timer_ticks, NRF_TIMER_SHORT_COMPARE0_CLEAR_MASK, true); + m_timer_started = true; +} +void hwss_uninit(void) { nrfx_timer_disable(&m_timer); } + +void hwss_start_capture(void) { + m_start_capture_tp = znordic_getpower_on_s(); + swap_buffer(); + m_frame_index = 0; + nrfx_timer_enable(&m_timer); +} +void hwss_stop_capture(void) { + nrfx_timer_disable(&m_timer); + m_frame_index = 0; +} + +float hwss_read_val(void) { + __disable_irq(); + float val = m_sensor_display_data; + __enable_irq(); + return val; +} +float hwss_read_heart_rate(void) { return 0; } + +int hwss_has_captured_time_ms() { return (znordic_getpower_on_s() - m_start_capture_tp) * 1000; } diff --git a/app/src/heart_wave_sample_service.h b/app/src/heart_wave_sample_service.h new file mode 100644 index 0000000..65e18dc --- /dev/null +++ b/app/src/heart_wave_sample_service.h @@ -0,0 +1,15 @@ +#pragma once +#include "one_conduction_board.h" + +// 每256个字节触发一次回调 +typedef void (*heart_wave_sample_service_callback_t)(uint16_t *p_data, uint16_t length); + +void hwss_init(void); +void hwss_uninit(void); + +void hwss_start_capture(void); +void hwss_stop_capture(void); + +float hwss_read_val(void); +float hwss_read_heart_rate(void); +int hwss_has_captured_time_ms(); diff --git a/app/src/one_conduction/app_event.h b/app/src/one_conduction/app_event.h deleted file mode 100644 index cc128f6..0000000 --- a/app/src/one_conduction/app_event.h +++ /dev/null @@ -1 +0,0 @@ -#include "device_state.h" \ No newline at end of file diff --git a/app/src/one_conduction/ble_cmd_process_service.c b/app/src/one_conduction/ble_cmd_process_service.c deleted file mode 100644 index f5d567b..0000000 --- a/app/src/one_conduction/ble_cmd_process_service.c +++ /dev/null @@ -1,461 +0,0 @@ -#include "ble_cmd_process_service.h" - -#include "../../ify_hrs_protocol/heart_rate_sensor_protocol.h" -#include "board/board.h" -#include "config.h" -#include "one_conduction_board.h" -#include "sample_data_manager.h" -#include "zble_module.h" -#include "zdatachannel_service.h" -#include "znordic_device_info_mgr.h" - -APP_TIMER_DEF(m_record_upload_tmr); // 数据上报定时器 -APP_TIMER_DEF(m_record_upload_finish_packet_report_tmr); // 数据上报完成上报定时器 -static uint8_t txbuf[128]; -static uint8_t reportbuf[128]; -static bool m_realtime_report_state = false; -static bool m_isupload_data_state = false; -static bool m_ble_cmder_is_inited = false; -static uint32_t m_report_data_sumcheckcode = 0; - -static void record_upload_tmr_cb(void* p_context); -static void record_upload_finish_packet_report_tmr_cb(void* p_context); -int ble_stop_upload_record(); -/******************************************************************************* - * 广播控制 * - *******************************************************************************/ -void ble_cmder_start_adv() { - m_realtime_report_state = false; - zble_module_start_adv(); -} -void ble_cmder_stop_adv() { - zble_module_stop_adv(); - m_realtime_report_state = false; -} - -/******************************************************************************* - * 模块初始化 * - *******************************************************************************/ -void ble_cmder_init() { - if (!m_ble_cmder_is_inited) { - ZERROR_CHECK(app_timer_create(&m_record_upload_tmr, APP_TIMER_MODE_REPEATED, record_upload_tmr_cb)); - ZERROR_CHECK(app_timer_create(&m_record_upload_finish_packet_report_tmr, APP_TIMER_MODE_SINGLE_SHOT, record_upload_finish_packet_report_tmr_cb)); - } - m_ble_cmder_is_inited = true; -} -void ble_cmder_uninit() {} - -/******************************************************************************* - * 实时上报控制 * - *******************************************************************************/ -int ble_start_realtime_report() { - m_realtime_report_state = true; - return 0; -} -int ble_stop_realtime_report() { - m_realtime_report_state = false; - return 0; -} -void ble_cmder_try_report_one_sample_data(uint32_t frameIndex, uint16_t data) { - if (!m_realtime_report_state) { - return; - } - - heartrate_report_packet_t* reportpacket = (heartrate_report_packet_t*)reportbuf; - reportpacket->cmd = ify_hrs_report_heartrate_data; - reportpacket->frame_index = 0; - reportpacket->frame_type = kifyhrs_pt_report; - reportpacket->sample_data_index = frameIndex; - - /** - * @brief 第一导联数据 - */ - reportpacket->data[0] = (data >> 0) & 0xFF; - reportpacket->data[1] = (data >> 8) & 0xFF; - reportpacket->data[2] = 0; - reportpacket->data[3] = 0; - - uint16_t sendlen = sizeof(heartrate_report_packet_t) + 4; - zdatachannel_data_send2(reportbuf, sendlen); - return; -} - -void ble_cmder_try_report_sensor_drop_event(uint8_t dropstate0, uint8_t dropstate1) { - sensor_drop_event_report_packet_t* reportpacket = (sensor_drop_event_report_packet_t*)reportbuf; - reportpacket->cmd = ify_hrs_report_sensor_drop_detect; - reportpacket->frame_index = 0; - reportpacket->frame_type = kifyhrs_pt_report; - reportpacket->drop_state0 = dropstate0; - reportpacket->drop_state1 = dropstate1; - - uint16_t sendlen = sizeof(sensor_drop_event_report_packet_t); - zdatachannel_data_send2(reportbuf, sendlen); - return; -} -void ble_cmder_report_upload_finish_event(uint32_t sumcheckcode) { - ify_hrs_packet_t* txheader = (ify_hrs_packet_t*)txbuf; - uint16_t sendlen = sizeof(ify_hrs_packet_t) + 4; - - txheader->cmd = ify_hrs_report_record_upload_end; // 6A - txheader->frame_index = 0; - txheader->frame_type = kifyhrs_pt_report; - - // txheader->data[0] = errorcode; - *(uint32_t*)txheader->data = sumcheckcode; - - zdatachannel_data_send2(txbuf, sendlen); - return; -} - -void ble_cmder_report_sample_finish_event() { - ify_hrs_packet_t* txheader = (ify_hrs_packet_t*)txbuf; - uint16_t sendlen = sizeof(ify_hrs_packet_t); - - txheader->cmd = ify_hrs_report_sample_finish_end; - txheader->frame_index = 0; - txheader->frame_type = kifyhrs_pt_report; - - zdatachannel_data_send2(txbuf, sendlen); - return; -} - -/******************************************************************************* - * 上传数据控制 * - *******************************************************************************/ -static int m_upload_fd; -static uint8_t datacache[256]; -static int m_remaindatalen = 0; -/** - * @brief 数据上报定时器回调 - * - * @param p_context - */ -static void record_upload_finish_packet_report_tmr_cb(void* p_context) { // - ble_cmder_report_upload_finish_event(m_report_data_sumcheckcode); -} - -static void record_upload_tmr_cb(void* p_context) { // - - if (!m_isupload_data_state) return; - - // sample_data_mgr_read - if (m_remaindatalen == 0) { - memset(datacache, 0, sizeof(datacache)); - int32_t rdsize = sample_data_mgr_read(m_upload_fd, datacache, sizeof(datacache)); - if (rdsize <= 0) { - ZLOGI("read file end,stop upload"); - ZERROR_CHECK(app_timer_start(m_record_upload_finish_packet_report_tmr, APP_TIMER_TICKS(30), (void*)m_report_data_sumcheckcode)); - ble_stop_upload_record(); - return; - } - m_remaindatalen = rdsize; - } - if (m_remaindatalen == 0) { - return; - } - - int32_t mtusize = zble_module_get_mtu_size(); - mtusize = mtusize < 128 ? mtusize : 128; - - uint8_t* data = datacache + (sizeof(datacache) - m_remaindatalen); - int len = m_remaindatalen > mtusize ? mtusize : m_remaindatalen; - - ZLOGI("upload %d %d %d", len, m_remaindatalen, mtusize); - if (!zdatachannel_is_connected()) { - ZLOGI("ble is disconnected,stop upload"); - ble_stop_upload_record(); - return; - } - - uint32_t suc = zdatachannel_block_data_send2(data, len); - if (suc != NRF_SUCCESS) { - if (suc == NRF_ERROR_INVALID_STATE) { - // 未使能notify - ZLOGI("ble unenable notify,stop upload"); - ble_stop_upload_record(); - return; - } else if (suc == NRF_ERROR_BUSY || suc == NRF_ERROR_RESOURCES) { - // 等待下次发送 - return; - } else { - ZLOGI("ble send error,stop upload %x", suc); - ble_stop_upload_record(); - return; - } - } - for (uint32_t i = 0; i < len; i++) { - m_report_data_sumcheckcode += data[i]; - } - m_remaindatalen -= len; -} - -int ble_start_upload_record(sample_data_filename_t* recordid) { - // - // 启动 - // - if (ds_now_state() != kdevice_state_home) { - return kifyhrs_ecode_device_busy; - } - - m_upload_fd = sample_data_mgr_open(recordid, kwrflag_read_only); - if (m_upload_fd <= 0) { - return kifyhrs_ecode_no_record_find; - } - - ZERROR_CHECK(app_timer_start(m_record_upload_tmr, APP_TIMER_TICKS(2), NULL)); - m_isupload_data_state = true; - m_remaindatalen = 0; - m_report_data_sumcheckcode = 0; - return 0; -} -int ble_stop_upload_record() { - m_isupload_data_state = false; - app_timer_stop(m_record_upload_tmr); - return 0; -} -bool ble_is_upload_record() { return m_isupload_data_state; } - -/******************************************************************************* - * UTILS * - *******************************************************************************/ -static void send_error_receipt(ify_hrs_packet_t* rxpacket, int32_t errorcode) { - ify_hrs_packet_t* txheader = (ify_hrs_packet_t*)txbuf; - error_receipt_t* receipt = (error_receipt_t*)txheader->data; - uint16_t sendlen = sizeof(ify_hrs_packet_t) + sizeof(error_receipt_t); - - txheader->cmd = rxpacket->cmd; - txheader->frame_index = rxpacket->frame_index; - txheader->frame_type = kifyhrs_pt_error_receipt; - - txheader->frame_type = kifyhrs_pt_error_receipt; - receipt->errorcode = kifyhrs_ecode_cmd_not_support; - zdatachannel_data_send2(txbuf, sendlen); -} - -static void send_success_receipt(ify_hrs_packet_t* rxpacket, int32_t emptydatasize) { - ify_hrs_packet_t* txheader = (ify_hrs_packet_t*)txbuf; - uint16_t sendlen = sizeof(ify_hrs_packet_t) + emptydatasize; - - txheader->cmd = rxpacket->cmd; - txheader->frame_index = rxpacket->frame_index; - txheader->frame_type = kifyhrs_pt_cmd_receipt; - - zdatachannel_data_send2(txbuf, sendlen); -} - -/******************************************************************************* - * 下发消息处理 * - *******************************************************************************/ -void ble_cmder_process_rx(uint8_t* rx, int len) { - if (len < sizeof(ify_hrs_packet_t)) { - ZLOGI("rx len error:%d", len); - return; - } - - ify_hrs_packet_t* rxheader = (ify_hrs_packet_t*)rx; - ify_hrs_packet_t* txheader = (ify_hrs_packet_t*)txbuf; - ify_hrs_cmd_t cmd = (ify_hrs_cmd_t)rxheader->cmd; - memset(txbuf, 0, sizeof(txbuf)); - - txheader->cmd = rxheader->cmd; - txheader->frame_index = rxheader->frame_index; - txheader->frame_type = kifyhrs_pt_cmd_receipt; - - ZLOGI("rx cmd:%d index:%d datalen:%d", cmd, rxheader->frame_index, len - sizeof(ify_hrs_packet_t)); - NRF_LOG_HEXDUMP_INFO(rx, len); - - if (cmd == ify_hrs_cmd_read_device_version) { - device_version_info_receipt_t* receipt = (device_version_info_receipt_t*)txheader->data; - uint16_t sendlen = sizeof(ify_hrs_packet_t) + sizeof(device_version_info_receipt_t); - - receipt->blestack_version = device_info_read_blestack_version(); - receipt->bootloader_version = device_info_read_bootloader_version(); - receipt->firmware_version = device_info_read_firmware_version(); - receipt->hardware_version = device_info_read_hardware_version(); - zdatachannel_data_send2(txbuf, sendlen); - } - - else if (cmd == ify_hrs_cmd_read_sensor_info) { - sensor_info_receipt_t* receipt = (sensor_info_receipt_t*)txheader->data; - uint16_t sendlen = sizeof(ify_hrs_packet_t) + sizeof(sensor_info_receipt_t); - - receipt->sensor_num = 1; - receipt->sensor_precision = SAMPLE_PRECISION; - receipt->sensor_sample_rate = SAMPLE_RATE / 10; - receipt->sensor0_pos = kifyhrs_sensor_pos_none; - receipt->sensor1_pos = kifyhrs_sensor_pos_none; - receipt->sensor2_pos = kifyhrs_sensor_pos_none; - - zdatachannel_data_send2(txbuf, sendlen); - } - - else if (cmd == ify_hrs_cmd_read_device_state) { - device_state_receipt_t* receipt = (device_state_receipt_t*)txheader->data; - uint16_t sendlen = sizeof(ify_hrs_packet_t) + sizeof(device_state_receipt_t); - - receipt->drop_state0 = (!SingleLeadECG_ecg_plod_get_connected_state()); - receipt->drop_state1 = 0x00; - receipt->device_state0.sampling_state = (ds_now_state() == kdevice_state_sampling); - receipt->device_state0.report_state = m_realtime_report_state; - receipt->device_state0.low_battery = (SingleLeadECG_battery_val() < 20); - receipt->device_state0.full_storge = (sample_data_mgr_storage_is_full()); - - receipt->device_state1 = 0; - receipt->powerlevel = SingleLeadECG_battery_val(); - receipt->storage_item_num = sample_data_mgr_get_file_num(); - - zdatachannel_data_send2(txbuf, sendlen); - } - - else if (cmd == ify_hrs_cmd_read_time) { - read_time_receipt_t* receipt = (read_time_receipt_t*)txheader->data; - uint16_t sendlen = sizeof(ify_hrs_packet_t) + sizeof(read_time_receipt_t); - static ztm_t ztm; - znordic_rtc_gettime(&ztm); - - receipt->year = (ztm.tm_year + 1900 - 2000); - receipt->month = ztm.tm_mon + 1; - receipt->day = ztm.tm_mday; - receipt->hour = ztm.tm_hour; - receipt->minute = ztm.tm_min; - receipt->second = ztm.tm_sec; - zdatachannel_data_send2(txbuf, sendlen); - } - - else if (cmd == ify_hrs_cmd_sync_time) { - sync_time_cmd_t* cmd = (sync_time_cmd_t*)rxheader->data; - uint16_t sendlen = sizeof(ify_hrs_packet_t); - - znordic_rtc_settime(cmd->year + 2000, cmd->month, cmd->day, cmd->hour, cmd->minute, cmd->second); - zdatachannel_data_send2(txbuf, sendlen); - } - - else if (cmd == ify_hrs_cmd_start_capture) { - send_error_receipt(rxheader, kifyhrs_ecode_cmd_not_support); - } - - else if (cmd == ify_hrs_cmd_stop_capture) { - send_error_receipt(rxheader, kifyhrs_ecode_cmd_not_support); - } - - else if (cmd == ify_hrs_cmd_start_realtime_report) { - // unsupport cmd - int ecode = ble_start_realtime_report(); - if (ecode == 0) { - send_success_receipt(rxheader, 8); // 凑8个字节,使这个回执的字节长度同上报包长度一致,方便调试 - } else { - send_error_receipt(rxheader, ecode); - } - } - - else if (cmd == ify_hrs_cmd_stop_realtime_report) { - int ecode = ble_stop_realtime_report(); - if (ecode == 0) { - send_success_receipt(rxheader, 0); - } else { - send_error_receipt(rxheader, ecode); - } - } - - else if (cmd == ify_hrs_cmd_read_records_info) { - // 指令 10-读取采样记录头部信息 - read_record_info_cmd_t* cmd = (read_record_info_cmd_t*)rxheader->data; - read_record_info_receipt_t* receipt = (read_record_info_receipt_t*)txheader->data; - uint16_t sendlen = sizeof(ify_hrs_packet_t) + sizeof(read_record_info_receipt_t); - - uint8_t recordoff = cmd->record_index; - - // 采样时不支持 - if (ds_now_state() != kdevice_state_home) { - send_error_receipt(rxheader, kifyhrs_ecode_device_busy); - return; - } - - sample_data_fileinfo_list_t* recordlist = sample_data_mgr_get_fileinfo_list(); - if (recordoff >= recordlist->count) { - send_error_receipt(rxheader, kifyhrs_ecode_no_record_find); - return; - } - - sample_data_fileinfo_t* fileinfo = recordlist->fileinfo[recordoff]; - memcpy(receipt->record_id, fileinfo->filename, 6); - receipt->frameNum = fileinfo->size / 2; // 2byte per frame - receipt->dataSize = fileinfo->size; - receipt->sensorNum = 1; - receipt->captureRate = SAMPLE_RATE / 10; - receipt->capturePrecision = SAMPLE_PRECISION; - receipt->compressAlgorithm = 0; - - zdatachannel_data_send2(txbuf, sendlen); - - } - - else if (cmd == ify_hrs_cmd_del_record) { - // 指令 11-删除采样记录 - del_record_cmd_t* cmd = (del_record_cmd_t*)rxheader->data; - - static sample_data_filename_t filename; - memset(&filename, 0, sizeof(filename)); - memcpy(&filename, cmd->record_id, sizeof(cmd->record_id)); - - // 采样时不支持 - if (ds_now_state() != kdevice_state_home) { - send_error_receipt(rxheader, kifyhrs_ecode_device_busy); - return; - } - - int ecode = sample_data_mgr_delete_file(&filename); - if (ecode == 0) { - send_success_receipt(rxheader, 0); - } else { - send_error_receipt(rxheader, kifyhrs_ecode_unkown_error); - } - } - - else if (cmd == ify_hrs_cmd_start_upload_record) { - // 指令 12-上传采集记录 - start_upload_record_cmd_t* cmd = (start_upload_record_cmd_t*)rxheader->data; - - static sample_data_filename_t filename; - memset(&filename, 0, sizeof(filename)); - memcpy(&filename, cmd->record_id, sizeof(cmd->record_id)); - - // 采样时不支持 - if (ds_now_state() != kdevice_state_home) { - send_error_receipt(rxheader, kifyhrs_ecode_device_busy); - return; - } - - int ecode = ble_start_upload_record(&filename); - if (ecode == 0) { - ify_hrs_packet_t* txheader = (ify_hrs_packet_t*)txbuf; - uint16_t sendlen = sizeof(ify_hrs_packet_t) + 1; // 凑齐4BYTE,方便调试 - txheader->cmd = rxheader->cmd; - txheader->frame_index = rxheader->frame_index; - txheader->frame_type = kifyhrs_pt_cmd_receipt; - - zdatachannel_data_send2(txbuf, sendlen); - } else { - send_error_receipt(rxheader, ecode); - } - } - - else if (cmd == ify_hrs_cmd_enter_ota) { - send_error_receipt(rxheader, kifyhrs_ecode_cmd_not_support); - } - - else if (cmd == ify_hrs_cmd_read_sn) { - read_sn_receipt_t* receipt = (read_sn_receipt_t*)txheader->data; - uint16_t sendlen = sizeof(ify_hrs_packet_t) + sizeof(read_sn_receipt_t); - device_info_read_sn((sn_t*)&receipt->sn); - zdatachannel_data_send2(txbuf, sendlen); - } - - else if (cmd == ify_hrs_cmd_reset) { - NVIC_SystemReset(); - } - // - else { - send_error_receipt(rxheader, kifyhrs_ecode_cmd_not_support); - } -} diff --git a/app/src/one_conduction/ble_cmd_process_service.h b/app/src/one_conduction/ble_cmd_process_service.h deleted file mode 100644 index a9828f6..0000000 --- a/app/src/one_conduction/ble_cmd_process_service.h +++ /dev/null @@ -1,15 +0,0 @@ -#pragma once - -#include "device_state.h" - -void ble_cmder_init(); -void ble_cmder_uninit(); - -void ble_cmder_process_rx(uint8_t* rx, int len); -void ble_cmder_start_adv(); -void ble_cmder_stop_adv(); - -void ble_cmder_try_report_one_sample_data(uint32_t frameIndex, uint16_t data); -void ble_cmder_try_report_sensor_drop_event(uint8_t dropstate0, uint8_t dropstate1); -void ble_cmder_report_upload_finish_event(uint32_t sumcheckcode); -void ble_cmder_report_sample_finish_event(); diff --git a/app/src/one_conduction/config.h b/app/src/one_conduction/config.h deleted file mode 100644 index 3977535..0000000 --- a/app/src/one_conduction/config.h +++ /dev/null @@ -1,3 +0,0 @@ -#pragma once - -#include "board/board.h" \ No newline at end of file diff --git a/app/src/one_conduction/device_controler.c b/app/src/one_conduction/device_controler.c deleted file mode 100644 index e69de29..0000000 diff --git a/app/src/one_conduction/device_controler.h b/app/src/one_conduction/device_controler.h deleted file mode 100644 index e69de29..0000000 diff --git a/app/src/one_conduction/device_state.c b/app/src/one_conduction/device_state.c deleted file mode 100644 index 243c1b5..0000000 --- a/app/src/one_conduction/device_state.c +++ /dev/null @@ -1,27 +0,0 @@ - -#include "device_state.h" - -#include "znordic.h" -static device_state_t m_device_state = kdevice_state_standby; // 设备状态 -static uint32_t m_change_to_cur_state_tp = 0; // 切换到当前状态的时间戳 - -void ds_change_to_state(device_state_t state) { - ZLOGI("change state from %s to %s", device_state_to_str(m_device_state), device_state_to_str(state)); - m_device_state = state; - m_change_to_cur_state_tp = znordic_getpower_on_ms(); -} - -uint32_t ds_cur_state_haspassed_ms() { return znordic_haspassed_ms(m_change_to_cur_state_tp); } -device_state_t ds_now_state() { return m_device_state; } - -static sample_capture_state_t m_sample_capture_state; - -sample_capture_state_t* sample_capture_state_get() { // - return &m_sample_capture_state; -} -void sample_capture_state_reset() { // - m_sample_capture_state.is_over30s = false; -}; -void sample_capture_state_set_is_over30s(bool over30s) { // - m_sample_capture_state.is_over30s = over30s; -} diff --git a/app/src/one_conduction/device_state.h b/app/src/one_conduction/device_state.h deleted file mode 100644 index 9a6f645..0000000 --- a/app/src/one_conduction/device_state.h +++ /dev/null @@ -1,87 +0,0 @@ -#pragma once -#include -#include - -typedef enum { - kplod_connected_event = 0, // 导联连接事件 - kplod_disconnected_event, // 导联断开事件 - kplod_connecting_event, // 导联连接中事件 - - kplod_start_charge_event, // 充电事件 - kplod_charging_event, // 充电中 - kplod_end_charge_event, // 充电结束事件 - - kevent_tmr_scheduler_event, // 定时器调度事件 - - kevent_capture_256data_event, // 采样数据回调 - kevent_capture_1data_event, // 单次采样数据回调 -} app_event_type_t; - -typedef struct { - app_event_type_t eventType; - union { - uint32_t plod_connected_accumulation_time; // 导联连接累计时间 - uint8_t* capture_data_cache; // 实时采样数据,数据长度为256字节 - struct { - uint32_t frameIndex; - uint16_t data; - } frame_data; - } val; -} app_event_t; - -typedef enum { - // 待机 - kdevice_state_standby = 0, - // 开机 - kdevice_state_poweron, - // 首页 - kdevice_state_home, - // 提示用户保持静止 - kdevice_state_keep_still, - // 采集中 - kdevice_state_sampling, - // 采集完成 - kdevice_state_sampling_complete, - // 采集异常 - kdevice_state_sampling_error, - // 充电中 - kdevice_state_charging, -} device_state_t; - -static const char* device_state_to_str(device_state_t ds) { - switch (ds) { - case kdevice_state_standby: - return "standby"; - case kdevice_state_poweron: - return "poweron"; - case kdevice_state_home: - return "home"; - case kdevice_state_keep_still: - return "keep_still"; - case kdevice_state_sampling: - return "sampling"; - case kdevice_state_sampling_complete: - return "sampling_complete"; - case kdevice_state_sampling_error: - return "sampling_error"; - case kdevice_state_charging: - return "charging"; - default: - return "unknow"; - } -} - -void app_event_process_cb(void* p_event_data, uint16_t event_size); - -void ds_change_to_state(device_state_t state); -uint32_t ds_cur_state_haspassed_ms(); -device_state_t ds_now_state(); - -typedef struct { - bool is_over30s; -} sample_capture_state_t; - -sample_capture_state_t* sample_capture_state_get(); - -void sample_capture_state_reset(); -void sample_capture_state_set_is_over30s(bool over30s); diff --git a/app/src/one_conduction/display_manager.c b/app/src/one_conduction/display_manager.c deleted file mode 100644 index 615c324..0000000 --- a/app/src/one_conduction/display_manager.c +++ /dev/null @@ -1,442 +0,0 @@ -#include "display_manager.h" - -#include "../../../res/logo_mono.c" -// -#include - -#include "basic/ssd1306/driver_ssd1306.h" -#include "basic/ssd1306/driver_ssd1306_basic.h" -#include "basic/ssd1306/wave_drawer.h" -#include "config.h" -#include "font.h" -#include "heart_wave_sample_service.h" -#include "one_conduction_board.h" -PageState_t g_pageState; - -void dsp_mgr_change_to_page(page_t page) { // - g_pageState.page = page; - g_pageState.last_page = page; - g_pageState.page_change_to_page_time = znordic_getpower_on_s(); - - g_pageState.in_prompt = false; - memset(g_pageState.prompt, 0, sizeof(g_pageState.prompt)); -} - -uint32_t dsp_mgr_get_page_elapsed_time_s(void) { // - return znordic_getpower_on_s() - g_pageState.page_change_to_page_time; -} - -void dsp_mgr_schedule(void) {} - -PageState_t* dsp_mgr_get_state(void) { return NULL; } - -int compute_x_pos_by_center(int16_t x, int16_t width) { return x - width / 2; } -int compute_y_pos_by_center(int16_t y, int16_t height) { return y - height / 2; } - -#define SCREEN_CENTER_X 64 -#define SCREEN_CENTER_Y 32 - -#define CHARGE_BATTERY_WIDTH (12 * 1.2) -#define CHARGE_BATTERY_HEIGHT (22 * 1.2) - -#define MAIN_PAGE_BATTERY_WIDTH (12) // 首页电池宽度 -#define MAIN_PAGE_BATTERY_HEIGHT (22) // 首页电池高度 - -/******************************************************************************* - * 充电页面 * - *******************************************************************************/ -/** - * 显示元素: - * 1.电池电量 - * --------------- - * | _ | - * | | | | - * | | - * --------------- - * - * 动画效果: - * 1. 电池电量变化 - * - */ -static uint32_t m_nowshowbatterylevel; // 当前显示的电池电量 - -void dsp_mgr_change_to_chargingPage() { - ssd1306_basic_clear(); - uint8_t x = compute_x_pos_by_center(SCREEN_CENTER_X, CHARGE_BATTERY_WIDTH); - uint8_t y = compute_y_pos_by_center(SCREEN_CENTER_Y, CHARGE_BATTERY_HEIGHT); - uint8_t xchange, ychange; - ssd1306_basic_draw_battery_level(x, y, &xchange, &ychange, SingleLeadECG_battery_val(), CHARGE_BATTERY_WIDTH, CHARGE_BATTERY_HEIGHT); - m_nowshowbatterylevel = SingleLeadECG_battery_val(); - ssd1306_basic_gram_update(); - dsp_mgr_change_to_page(kPage_chargingPage); -} - -void chargingPage_set_batteryLevel(int batteryLevel) { - uint8_t x = compute_x_pos_by_center(SCREEN_CENTER_X, CHARGE_BATTERY_WIDTH); - uint8_t y = compute_y_pos_by_center(SCREEN_CENTER_Y, CHARGE_BATTERY_HEIGHT); - uint8_t xchange, ychange; - ssd1306_basic_draw_battery_level(x, y, &xchange, &ychange, batteryLevel, CHARGE_BATTERY_WIDTH, CHARGE_BATTERY_HEIGHT); - ssd1306_basic_gram_update(); -} - -void chargingPage_schedule() { // - static uint32_t last_update_time = 0; - if (znordic_haspassed_ms(last_update_time) < 300) { - return; - } - - last_update_time = znordic_getpower_on_ms(); - m_nowshowbatterylevel += 5; - if (m_nowshowbatterylevel > 100) { - m_nowshowbatterylevel = SingleLeadECG_battery_val(); - } - chargingPage_set_batteryLevel(m_nowshowbatterylevel); -} - -/******************************************************************************* - * 欢迎页面 * - *******************************************************************************/ -void dsp_mgr_change_to_welcome() { - /** - * @brief 切换到欢迎界面 - * 1. 加载屏幕外设 - * 2. 打开屏幕电源 - * 3. 初始化开机页面 - */ - - // ssd1306_basic_string(0, 0, "123456789123456789123", 21, 0, SSD1306_FONT_12); - ssd1306_basic_draw_screen((const char*)gImage_logo_mono); - ssd1306_basic_gram_update(); - dsp_mgr_change_to_page(kPage_welcome); -} - -void welcomePage_schedule() {} - -/******************************************************************************* - * 首页 * - *******************************************************************************/ -static bool m_main_page_colon_state = false; - -void mainPage_show(bool colon_state) { - static ztm_t now; - int16_t batterylevel; - uint8_t xchange, ychange; - uint8_t x, y; - x = compute_x_pos_by_center(SCREEN_CENTER_X, fontclocklib.widthPixel * 5 + MAIN_PAGE_BATTERY_WIDTH); - y = compute_y_pos_by_center(SCREEN_CENTER_Y, fontclocklib.heightPixel + 1); - znordic_rtc_gettime(&now); - batterylevel = SingleLeadECG_battery_val(); - - ssd1306_basic_clear_gram(); - - // ZLOGI("mainPage_show %d %d", colon_state, x, y); - - ssd1306_basic_draw_str(x, y, &xchange, &ychange, fmt("%02d:%02d", now.tm_hour, now.tm_min), &fontclocklib); - x = x + 2 + xchange; - ssd1306_basic_draw_battery_level(x, y, &xchange, &ychange, batterylevel, MAIN_PAGE_BATTERY_WIDTH, MAIN_PAGE_BATTERY_HEIGHT); - ssd1306_basic_gram_update(); - m_main_page_colon_state = colon_state; - dsp_mgr_change_to_page(kPage_main); -} - -void dsp_mgr_change_to_main() { mainPage_show(true); } -void mainPage_updateState() { mainPage_show(!m_main_page_colon_state); } -void mainPage_schedule() { - static uint32_t last_update_time = 0; - if (znordic_haspassed_ms(last_update_time) < 300) { - return; - } - last_update_time = znordic_getpower_on_ms(); - mainPage_updateState(); -} - -/******************************************************************************* - * 保持静止页面 * - *******************************************************************************/ -static int m_prepare_page_progress = 0; -void PreparePage_show(int progress) { - m_prepare_page_progress = progress; - ssd1306_basic_clear_gram(); - uint8_t x = 0; - uint8_t y = 0; - uint8_t xchange, ychange; - - x = compute_x_pos_by_center(SCREEN_CENTER_X, font24x24_zh_lib.widthPixel * 4); - y = compute_y_pos_by_center(SCREEN_CENTER_Y, font24x24_zh_lib.heightPixel); - - ssd1306_basic_draw_str(x, y, &xchange, &ychange, "保持静止", &font24x24_zh_lib); - - if (progress == 0) { - ssd1306_basic_draw_str(x - font8x8_xo_lib.widthPixel, y - font8x8_xo_lib.heightPixel, &xchange, &ychange, "xxxx", &font8x8_xo_lib); - } else if (progress == 1) { - ssd1306_basic_draw_str(x - font8x8_xo_lib.widthPixel, y - font8x8_xo_lib.heightPixel, &xchange, &ychange, "oxxx", &font8x8_xo_lib); - } else if (progress == 2) { - ssd1306_basic_draw_str(x - font8x8_xo_lib.widthPixel, y - font8x8_xo_lib.heightPixel, &xchange, &ychange, "ooxx", &font8x8_xo_lib); - } else if (progress == 3) { - ssd1306_basic_draw_str(x - font8x8_xo_lib.widthPixel, y - font8x8_xo_lib.heightPixel, &xchange, &ychange, "ooox", &font8x8_xo_lib); - } else if (progress == 4) { - ssd1306_basic_draw_str(x - font8x8_xo_lib.widthPixel, y - font8x8_xo_lib.heightPixel, &xchange, &ychange, "oooo", &font8x8_xo_lib); - } - - ssd1306_basic_gram_update(); -} - -void dsp_mgr_change_to_preparePage() { - PreparePage_show(0); - dsp_mgr_change_to_page(kPage_preparePage); -} -void dsp_mgr_preparePage_set_progress(int progress) { PreparePage_show(progress); } -int dsp_mgr_preparePage_get_progress() { return m_prepare_page_progress; } - -void PreparePage_schedule() {} - -/******************************************************************************* - * 采样页面 * - *******************************************************************************/ - -#define SMAPLE_PAGE_START_X 1 -#define SMAPLE_PAGE_START_Y 1 - -typedef struct { - wave_drawer_t wave_drawer; - - int wave_drawser_x; - int wave_drawser_y; - int wave_drawser_hight; - int wave_drawser_width; - - int progress_x; - int progress_y; - - int progress_width; - int progress_hight; - - int heartrate_x; - int heartrate_y; -} sample_page_state_t; -sample_page_state_t m_sample_page_state; -#if 0 -void dsp_mgr_change_to_sampling(int progress_s, int heartrate) { // - sample_page_state_t* sps = &m_sample_page_state; - - sps->wave_drawser_x = SMAPLE_PAGE_START_X; - sps->wave_drawser_y = SMAPLE_PAGE_START_Y; - sps->wave_drawser_hight = 40; - sps->wave_drawser_width = 120; - - sps->progress_x = SMAPLE_PAGE_START_X + 1; - sps->progress_y = SMAPLE_PAGE_START_Y + sps->wave_drawser_hight + 3 + 4; - sps->progress_width = 80; - sps->progress_hight = 8; - - sps->heartrate_x = sps->progress_x + sps->progress_width + 2; - sps->heartrate_y = sps->progress_y - 4; - - int progress = progress_s / SAMPLE_MIN_TIME_S * 25; - - ssd1306_basic_clear_gram(); - - wave_drawer_init(&sps->wave_drawer, sps->wave_drawser_x, sps->wave_drawser_y, sps->wave_drawser_width, sps->wave_drawser_hight); - wave_drawer_draw_border(&sps->wave_drawer); - uint8_t xchange, ychange; - ssd1306_basic_draw_progress(sps->progress_x, sps->progress_y, sps->progress_width, sps->progress_hight, 25, progress); - if (heartrate <= 0) { - ssd1306_basic_draw_str(sps->heartrate_x, sps->heartrate_y, &xchange, &ychange, "<>-- ", &font_asicc16x8_lib); - } else { - ssd1306_basic_draw_str(sps->heartrate_x, sps->heartrate_y, &xchange, &ychange, fmt("<>%3d", heartrate), &font_asicc16x8_lib); - } - ssd1306_basic_gram_update(); - dsp_mgr_change_to_page(kPage_sampling); -} - -void samplePage_update_state(int progress_s, int wave_y, int heartrate, bool update_screen) { // - - sample_page_state_t* sps = &m_sample_page_state; - uint8_t xchange, ychange; - - int progress = progress_s / SAMPLE_MIN_TIME_S * 25; - - if (progress_s / 10 == 0) { - ssd1306_basic_draw_str(sps->progress_x, sps->progress_y - 8, &xchange, &ychange, "xxx", &font8x8_xo_lib); - } else if (progress_s / 10 == 1) { - ssd1306_basic_draw_str(sps->progress_x, sps->progress_y - 8, &xchange, &ychange, "oxx", &font8x8_xo_lib); - } else if (progress_s / 10 == 2) { - ssd1306_basic_draw_str(sps->progress_x, sps->progress_y - 8, &xchange, &ychange, "oox", &font8x8_xo_lib); - } else if (progress_s / 10 == 3) { - ssd1306_basic_draw_str(sps->progress_x, sps->progress_y - 8, &xchange, &ychange, "ooo", &font8x8_xo_lib); - } - - wave_drawer_draw_next_point(&sps->wave_drawer, wave_y); - ssd1306_basic_draw_progress(sps->progress_x, sps->progress_y, sps->progress_width, sps->progress_hight, 25, progress); - if (heartrate <= 0) { - ssd1306_basic_draw_str(sps->heartrate_x, sps->heartrate_y, &xchange, &ychange, "<>-- ", &font_asicc16x8_lib); - } else { - ssd1306_basic_draw_str(sps->heartrate_x, sps->heartrate_y, &xchange, &ychange, fmt("<>%3d", heartrate), &font_asicc16x8_lib); - } - if (update_screen) ssd1306_basic_gram_update(); -} -#endif -void dsp_mgr_change_to_sampling(int progress_s, int heartrate) { // - sample_page_state_t* sps = &m_sample_page_state; - - sps->progress_x = SMAPLE_PAGE_START_X + 10; - sps->progress_y = SMAPLE_PAGE_START_Y + 2; - sps->progress_width = 100; - sps->progress_hight = 8; - - sps->wave_drawser_x = SMAPLE_PAGE_START_X + 5; - sps->wave_drawser_y = SMAPLE_PAGE_START_Y + sps->progress_hight + 5; - sps->wave_drawser_hight = 45; - sps->wave_drawser_width = 90; - - sps->heartrate_x = sps->wave_drawser_x + sps->wave_drawser_width + 5; - sps->heartrate_y = sps->wave_drawser_y + 5; - - int progress = progress_s / SAMPLE_MIN_TIME_S * 25; - uint8_t xchange, ychange; - - ssd1306_basic_clear_gram(); - /** - * @brief - * ================= - * | | 心 - * | wave | - * | | 心率 - */ - ssd1306_basic_draw_progress(sps->progress_x, sps->progress_y, sps->progress_width, sps->progress_hight, 25, progress); - // ssd1306_basic_draw_str(sps->progress_x + sps->progress_width + 2, sps->progress_y, &xchange, &ychange, "x", &font8x8_xo_lib); - - wave_drawer_init(&sps->wave_drawer, sps->wave_drawser_x, sps->wave_drawser_y, sps->wave_drawser_width, sps->wave_drawser_hight); - // wave_drawer_draw_border(&sps->wave_drawer); - - ssd1306_basic_draw_str(sps->heartrate_x + 2, sps->heartrate_y, &xchange, &ychange, "<>", &font_asicc16x8_lib); - if (heartrate <= 0) { - ssd1306_basic_draw_str(sps->heartrate_x, sps->heartrate_y + 20, &xchange, &ychange, "-- ", &font_asicc16x8_lib); - } else { - ssd1306_basic_draw_str(sps->heartrate_x, sps->heartrate_y + 20, &xchange, &ychange, fmt("%3d", heartrate), &font_asicc16x8_lib); - } - ssd1306_basic_gram_update(); - dsp_mgr_change_to_page(kPage_sampling); -} - -void samplePage_update_state(int progress_s, int wave_y, int heartrate, bool updateHeart, bool update_screen) { // - - sample_page_state_t* sps = &m_sample_page_state; - uint8_t xchange, ychange; - static bool heart_logo_state = false; - - int progress = progress_s / SAMPLE_MIN_TIME_S * 25; - - ssd1306_basic_draw_progress(sps->progress_x, sps->progress_y, sps->progress_width, sps->progress_hight, 25, progress); - // if (progress_s / 10 >= 3) { - // ssd1306_basic_draw_str(sps->progress_x + sps->progress_width + 2, sps->progress_y, &xchange, &ychange, "o", &font8x8_xo_lib); - // } else { - // ssd1306_basic_draw_str(sps->progress_x + sps->progress_width + 2, sps->progress_y, &xchange, &ychange, "x", &font8x8_xo_lib); - // } - if (update_screen && updateHeart) { - if (heart_logo_state) { - ssd1306_basic_draw_str(sps->heartrate_x + 2, sps->heartrate_y, &xchange, &ychange, "<>", &font_asicc16x8_lib); - } else { - ssd1306_basic_draw_str(sps->heartrate_x + 2, sps->heartrate_y, &xchange, &ychange, " ", &font_asicc16x8_lib); - } - heart_logo_state = !heart_logo_state; - } - - if (heartrate <= 0) { - ssd1306_basic_draw_str(sps->heartrate_x, sps->heartrate_y + 20, &xchange, &ychange, "-- ", &font_asicc16x8_lib); - } else { - ssd1306_basic_draw_str(sps->heartrate_x, sps->heartrate_y + 20, &xchange, &ychange, fmt("%3d", heartrate), &font_asicc16x8_lib); - } - wave_drawer_draw_next_point(&sps->wave_drawer, wave_y); - if (update_screen) ssd1306_basic_gram_update(); -} - -void samplePage_schedule() { - static int count = 0; - count++; - int capturetime = hwss_has_captured_time_ms(); - int wave_y = (int)hwss_read_val(); - int heartrate = (int)hwss_read_heart_rate(); - // ZLOGI("samplePage_schedule %d %d %d", capturetime, wave_y, heartrate); - samplePage_update_state(capturetime / 1000, wave_y, 123, count % 10 == 0, count % 5 == 0); -} - -/******************************************************************************* - * samplingError * - *******************************************************************************/ -void dsp_mgr_change_to_samplingError() { - /** - * @brief - * 不足30秒[X] - */ - ssd1306_basic_clear_gram(); - - uint8_t x; - uint8_t y; - - x = compute_x_pos_by_center(SCREEN_CENTER_X, font24x24_zh_lib.widthPixel * 3 + font12x24_asiic_lib.widthPixel * 2); - y = compute_y_pos_by_center(SCREEN_CENTER_Y, font24x24_zh_lib.heightPixel); - - uint8_t xchange, ychange; - ssd1306_basic_draw_str(x, y, &xchange, &ychange, "不足", &font24x24_zh_lib); - x = x + xchange; - ssd1306_basic_draw_str(x, y, &xchange, &ychange, "30", &font12x24_asiic_lib); - x = x + xchange; - ssd1306_basic_draw_str(x, y, &xchange, &ychange, "秒", &font24x24_zh_lib); - x = x + xchange; - ssd1306_basic_gram_update(); - dsp_mgr_change_to_page(kPage_samplingError); -} - -void dsp_mgr_change_to_sampleSuc() { - /** - * @brief - * 1.进度条 - * 2.提示信息 - */ - ssd1306_basic_clear(); - uint8_t x = 0; - uint8_t y = 0; - - uint8_t xchange, ychange; - x = compute_x_pos_by_center(SCREEN_CENTER_X, font24x24_zh_lib.widthPixel * 4); - y = compute_y_pos_by_center(SCREEN_CENTER_Y, font24x24_zh_lib.heightPixel); - - ssd1306_basic_draw_str(x, y, &xchange, &ychange, "采集完成", &font24x24_zh_lib); - ssd1306_basic_gram_update(); - dsp_mgr_change_to_page(kPage_storagingSuc); -} - -/******************************************************************************* - * SCHEDULE * - *******************************************************************************/ - -APP_TIMER_DEF(m_dsp_mgr_schedule_tmr); -static void dsp_mgr_schedule_tmr_cb(void* p_context) { // - if (g_pageState.page == kPage_chargingPage) { - chargingPage_schedule(); - } else if (g_pageState.page == kPage_welcome) { - welcomePage_schedule(); - } else if (g_pageState.page == kPage_main) { - mainPage_schedule(); - } else if (g_pageState.page == kPage_preparePage) { - PreparePage_schedule(); - } else if (g_pageState.page == kPage_sampling) { - samplePage_schedule(); - } -} - -void dsp_mgr_init(void) { - static bool timer_inited = false; - SingleLeadECG_screen_init(); - if (!timer_inited) { - ZERROR_CHECK(app_timer_create(&m_dsp_mgr_schedule_tmr, APP_TIMER_MODE_REPEATED, dsp_mgr_schedule_tmr_cb)); - } - // 此处周期决定采样一个页面显示的宽度 - ZERROR_CHECK(app_timer_start(m_dsp_mgr_schedule_tmr, APP_TIMER_TICKS(25), NULL)); - timer_inited = true; -} -void dsp_mgr_uninit(void) { - app_timer_stop(m_dsp_mgr_schedule_tmr); - SingleLeadECG_screen_deinit(); -} diff --git a/app/src/one_conduction/display_manager.h b/app/src/one_conduction/display_manager.h deleted file mode 100644 index 0553b77..0000000 --- a/app/src/one_conduction/display_manager.h +++ /dev/null @@ -1,81 +0,0 @@ -#pragma once - -#include "znordic.h" -// -#include "app_timer.h" -#include "diskio_blkdev.h" -#include "ff.h" -#include "nrf_block_dev_sdc.h" -#include "nrf_delay.h" -#include "nrf_drv_pwm.h" -#include "nrf_drv_saadc.h" -#include "nrf_drv_twi.h" -#include "nrf_drv_wdt.h" -#include "nrf_gpio.h" - -/** - * @brief - * 页面流转 - * - * close <--------------------- - * | - * button ---> welcome ---> main ---> preparePage ---> sampling ---> storaging ---> storagingSuc - * ^ ---> samplingError | - * |-------------------------------------------| | - * |-----------------------------------------------------------| - * - */ - -typedef enum { - kPage_poweroff, - kPage_welcome, - kPage_main, - kPage_preparePage, - kPage_sampling, - kPage_samplingError, - kPage_storaging, - kPage_storagingSuc, - kPage_chargingPage, -} page_t; - -typedef struct { - /** - * @brief 页面状态 - */ - page_t page; // 当前页面 - page_t last_page; // 上一个页面 - uint32_t page_change_to_page_time; // 当前页面持续的时间 - - bool in_prompt; // 是否在提示状态 - char prompt[32]; // 提示内容 - - /** - * @brief - */ - -} PageState_t; - -void dsp_mgr_init(void); -void dsp_mgr_uninit(void); -void dsp_mgr_schedule(void); - -PageState_t* dsp_mgr_get_state(void); -uint32_t dsp_mgr_get_page_elapsed_time_s(void); - -void dsp_mgr_change_to_poweroff(); -void dsp_mgr_change_to_welcome(); -void dsp_mgr_change_to_main(); -void dsp_mgr_change_to_chargingPage(); - -// 保持静止页面 -void dsp_mgr_change_to_preparePage(); -void dsp_mgr_preparePage_set_progress(int progress); -int dsp_mgr_preparePage_get_progress(); - -// 采样中页面 -void dsp_mgr_change_to_sampling(int progress_s, int heartrate); - -// 采样出错页面 -void dsp_mgr_change_to_samplingError(); -// 采样成功页面 -void dsp_mgr_change_to_sampleSuc(); \ No newline at end of file diff --git a/app/src/one_conduction/display_manager_res.h b/app/src/one_conduction/display_manager_res.h deleted file mode 100644 index 15109eb..0000000 --- a/app/src/one_conduction/display_manager_res.h +++ /dev/null @@ -1,5 +0,0 @@ -#pragma once - -#include - - diff --git a/app/src/one_conduction/font.h b/app/src/one_conduction/font.h deleted file mode 100644 index 179ea34..0000000 --- a/app/src/one_conduction/font.h +++ /dev/null @@ -1,275 +0,0 @@ -// https://www.23bei.com/tool-965.html - -#include -#if 0 -const uint8_t fontclocklib_code[] = { - 0x00, 0x00, 0x00, 0x00, 0x7F, 0x80, 0x01, 0xFF, 0xE0, 0x03, 0xFF, 0xF0, 0x07, 0x80, 0x78, 0x06, // - 0x00, 0x18, 0x04, 0x00, 0x08, 0x06, 0x00, 0x18, 0x07, 0x80, 0x78, 0x03, 0xFF, 0xF0, 0x01, 0xFF, // - 0xE0, 0x00, 0x7F, 0x80, // - 0x00, 0x00, 0x00, 0x02, 0x00, 0x10, 0x02, 0x00, 0x10, 0x02, 0x00, 0x10, 0x07, 0xFF, 0xF0, 0x0F, // - 0xFF, 0xF0, 0x0F, 0xFF, 0xF0, 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, // - 0x00, 0x00, 0x00, 0x00, // - 0x03, 0x80, 0x70, 0x07, 0x80, 0xF0, 0x0D, 0x81, 0xB0, 0x08, 0x03, 0x30, 0x08, 0x06, 0x30, 0x08, // - 0x0C, 0x30, 0x0C, 0x38, 0x30, 0x0F, 0xF8, 0x30, 0x07, 0xF1, 0xF0, 0x03, 0xC1, 0xF0, 0x00, 0x00, // - 0x00, 0x00, 0x00, 0x00, // - 0x03, 0x81, 0xC0, 0x07, 0x81, 0xE0, 0x0F, 0x81, 0xF0, 0x08, 0x10, 0x10, 0x08, 0x10, 0x10, 0x0C, // - 0x30, 0x10, 0x0F, 0xF8, 0x30, 0x07, 0xEF, 0xF0, 0x03, 0xCF, 0xE0, 0x00, 0x03, 0xC0, 0x00, 0x00, // - 0x00, 0x00, 0x00, 0x00, // - 0x00, 0x06, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x3A, 0x00, 0x00, 0xE2, 0x00, 0x01, 0xC2, 0x10, 0x07, // - 0x02, 0x10, 0x0F, 0xFF, 0xF0, 0x1F, 0xFF, 0xF0, 0x1F, 0xFF, 0xF0, 0x00, 0x02, 0x10, 0x00, 0x02, // - 0x10, 0x00, 0x00, 0x00, // - 0x00, 0x01, 0xC0, 0x0F, 0xF9, 0xE0, 0x0F, 0xF9, 0xB0, 0x0C, 0x30, 0x10, 0x0C, 0x20, 0x10, 0x0C, // - 0x20, 0x10, 0x0C, 0x30, 0x70, 0x0C, 0x3F, 0xF0, 0x0C, 0x1F, 0xE0, 0x0C, 0x0F, 0x80, 0x00, 0x00, // - 0x00, 0x00, 0x00, 0x00, // - 0x00, 0x7F, 0x00, 0x03, 0xFF, 0xC0, 0x07, 0xFF, 0xE0, 0x07, 0x18, 0x70, 0x0C, 0x30, 0x30, 0x08, // - 0x20, 0x10, 0x08, 0x20, 0x10, 0x0E, 0x30, 0x30, 0x0E, 0x3F, 0xE0, 0x06, 0x1F, 0xE0, 0x00, 0x0F, // - 0x80, 0x00, 0x00, 0x00, // - 0x00, 0x00, 0x00, 0x07, 0x80, 0x00, 0x0F, 0x80, 0x00, 0x0E, 0x00, 0x00, 0x0C, 0x01, 0xF0, 0x0C, // - 0x0F, 0xF0, 0x0C, 0x3F, 0xF0, 0x0D, 0xF0, 0x00, 0x0F, 0xC0, 0x00, 0x0E, 0x00, 0x00, 0x0C, 0x00, // - 0x00, 0x00, 0x00, 0x00, // - 0x03, 0xC3, 0xC0, 0x07, 0xEF, 0xE0, 0x0F, 0xEF, 0xE0, 0x0C, 0x78, 0x30, 0x08, 0x30, 0x10, 0x08, // - 0x38, 0x10, 0x08, 0x18, 0x10, 0x0C, 0x3C, 0x30, 0x0F, 0xEF, 0xF0, 0x07, 0xE7, 0xE0, 0x03, 0x83, // - 0xC0, 0x00, 0x00, 0x00, // - 0x01, 0xF0, 0x00, 0x07, 0xF8, 0x60, 0x07, 0xFC, 0x70, 0x0E, 0x0C, 0x70, 0x08, 0x04, 0x10, 0x08, // - 0x04, 0x10, 0x08, 0x0C, 0x30, 0x0E, 0x19, 0xE0, 0x07, 0xFF, 0xE0, 0x03, 0xFF, 0x80, 0x00, 0xFE, // - 0x00, 0x00, 0x00, 0x00, // - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x70, 0x00, // - 0xE0, 0x70, 0x00, 0xE0, 0x70, 0x00, 0xE0, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // - 0x00, 0x00, 0x00, 0x00, // -}; - -static FontLibrary_t fontclocklib = { - .font = fontclocklib_code, - .fontIndex = "0123456789:", - .fontIndexLen = 12, - .fontCode = kgbk, - .isAscii = true, - .widthPixel = 24, - .heightPixel = 24, -}; -#endif - -// DB 00H 00H 07H F0H 0FH F8H 18H 0CH 10H 04H 18H 0CH 0FH F8H 07H F0H;"0",0 -// DB 10H 08H 10H 08H 3FH F8H 3FH F8H 00H 08H 00H 08H 00H 00H 00H 00H;"1",1 -// DB 1CH 18H 3CH 38H 20H 68H 20H C8H 23H 88H 3FH 18H 1CH 18H 00H 00H;"2",2 -// DB 18H 30H 38H 38H 22H 08H 22H 08H 27H 18H 3DH F0H 18H E0H 00H 00H;"3",3 -// DB 01H C0H 07H C0H 0EH 48H 18H 48H 3FH F8H 3FH F8H 00H 48H 00H 00H;"4",4 -// DB 3FH 30H 3FH 38H 23H 08H 22H 08H 23H 18H 21H F0H 20H E0H 00H 00H;"5",5 -// DB 0FH E0H 1FH F0H 33H 18H 22H 08H 33H 18H 31H F0H 00H E0H 00H 00H;"6",6 -// DB 38H 00H 38H 00H 21H F8H 27H F8H 3EH 00H 38H 00H 20H 00H 00H 00H;"7",7 -// DB 1CH 70H 3EH F8H 23H 88H 21H 08H 23H 88H 3EH F8H 1CH 70H 00H 00H;"8",8 -// DB 0EH 00H 1FH 18H 31H 98H 20H 88H 31H 98H 1FH F0H 0FH E0H 00H 00H;"9",9 -// DB 00H 00H 00H 00H 06H 18H 06H 18H 06H 18H 00H 00H 00H 00H 00H 00H;":",10 - -#if 0 -//32*32 -const uint8_t fontclocklib_code[] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xC0, 0xC0, 0x40, 0x40, 0xC0, 0xC0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xFE, 0xFF, 0x0F, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x07, 0xFF, 0xFE, 0xF0, - 0x00, 0x00, 0x1F, 0xFF, 0xFF, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x07, 0x06, 0x04, 0x04, 0x06, 0x07, 0x03, 0x01, 0x00, 0x00, /*"0",0*/ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xC0, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x04, 0x04, 0x06, 0x07, 0x07, 0x07, 0x06, 0x04, 0x04, 0x04, 0x00, 0x00, /*"1",1*/ - 0x00, 0x00, 0x00, 0x00, 0x80, 0xC0, 0x40, 0x40, 0x40, 0x40, 0xC0, 0xC0, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x1E, 0x1F, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC1, 0xFF, 0x7F, 0x3E, 0x00, - 0x00, 0x00, 0x00, 0x80, 0xC0, 0x60, 0x30, 0x18, 0x0C, 0x06, 0x03, 0x01, 0x00, 0xE0, 0xE0, 0x00, 0x00, 0x00, 0x07, 0x07, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x07, 0x07, 0x01, 0x00, /*"2",2*/ - 0x00, 0x00, 0x00, 0x80, 0x80, 0xC0, 0x40, 0x40, 0x40, 0xC0, 0xC0, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x0F, 0x00, 0x80, 0x80, 0x80, 0xC0, 0xE1, 0x7F, 0x3F, 0x1E, 0x00, 0x00, - 0x00, 0x00, 0xE0, 0xE0, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x03, 0xFF, 0xFE, 0x78, 0x00, 0x00, 0x00, 0x01, 0x03, 0x03, 0x06, 0x04, 0x04, 0x04, 0x04, 0x06, 0x03, 0x03, 0x01, 0x00, 0x00, /*"3",3*/ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xC0, 0xC0, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xE0, 0x70, 0x3C, 0x0E, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, - 0x00, 0x10, 0x1C, 0x1E, 0x13, 0x11, 0x10, 0x10, 0x10, 0xFF, 0xFF, 0xFF, 0xFF, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x0F, 0x0F, 0x0F, 0x0F, 0x08, 0x08, 0x08, /*"4",4*/ - 0x00, 0x00, 0x00, 0x00, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0xC7, 0x60, 0x20, 0x20, 0x20, 0x60, 0xE0, 0xC0, 0x80, 0x00, 0x00, - 0x00, 0x00, 0xE0, 0xE1, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xFF, 0xFF, 0x7E, 0x00, 0x00, 0x00, 0x01, 0x03, 0x06, 0x04, 0x04, 0x04, 0x04, 0x04, 0x06, 0x03, 0x03, 0x01, 0x00, 0x00, /*"5",5*/ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xC0, 0xC0, 0x40, 0x40, 0x40, 0xC0, 0x80, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xFC, 0xFE, 0x8F, 0x81, 0xC0, 0x40, 0x40, 0x40, 0xC0, 0xC3, 0x83, 0x03, 0x00, - 0x00, 0x00, 0x3F, 0xFF, 0xFF, 0xC3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xFF, 0xFF, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x07, 0x06, 0x04, 0x04, 0x04, 0x06, 0x03, 0x03, 0x01, 0x00, /*"6",6*/ - 0x00, 0x00, 0x00, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x03, 0x01, 0x00, 0x00, 0x80, 0xE0, 0x78, 0x1E, 0x07, 0x01, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xFC, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x07, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"7",7*/ - 0x00, 0x00, 0x00, 0x00, 0x80, 0xC0, 0xC0, 0x40, 0x40, 0x40, 0xC0, 0xC0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1E, 0x3F, 0x7F, 0xF1, 0xE0, 0xC0, 0x80, 0x80, 0x80, 0xE1, 0x7F, 0x3F, 0x1E, 0x00, - 0x00, 0xF8, 0xFC, 0xFE, 0x07, 0x03, 0x01, 0x01, 0x01, 0x03, 0x07, 0x0F, 0xFE, 0xFC, 0xF8, 0x00, 0x00, 0x00, 0x01, 0x03, 0x03, 0x06, 0x04, 0x04, 0x04, 0x04, 0x06, 0x03, 0x03, 0x01, 0x00, 0x00, /*"8",8*/ - 0x00, 0x00, 0x00, 0x80, 0x80, 0xC0, 0x40, 0x40, 0x40, 0x40, 0xC0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x83, 0xFF, 0xFE, 0xF8, 0x00, - 0x00, 0x00, 0x81, 0x83, 0x87, 0x06, 0x04, 0x04, 0x04, 0x06, 0x83, 0xF3, 0xFF, 0x7F, 0x0F, 0x00, 0x00, 0x00, 0x03, 0x03, 0x07, 0x04, 0x04, 0x04, 0x06, 0x07, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, /*"9",9*/ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xE0, 0xE0, 0xE0, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x81, 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x07, 0x07, 0x07, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, /*":",10*/ -}; -static FontLibrary_t fontclocklib = { - .font = fontclocklib_code, - .fontIndex = "0123456789:", - .fontIndexLen = 12, - .fontCode = kgbk, - .isAscii = true, - .widthPixel = 16, - .heightPixel = 32, -}; -#endif - -// 24*24 -const uint8_t fontclocklib_code[] = { - - 0x00, 0x00, 0x80, 0xC0, 0xE0, 0x60, 0x20, 0x60, 0xE0, 0xC0, 0x80, 0x00, 0x00, 0xFE, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x01, 0xFF, 0xFF, 0xFE, 0x00, 0x01, 0x07, 0x0F, 0x1E, 0x18, 0x10, 0x18, 0x1E, 0x0F, 0x07, 0x01, /*"0",0*/ - 0x00, 0x00, 0x80, 0x80, 0x80, 0xC0, 0xE0, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x1F, 0x1F, 0x1F, 0x10, 0x10, 0x10, 0x00, /*"1",1*/ - 0x00, 0x80, 0xC0, 0x60, 0x20, 0x20, 0x20, 0x60, 0xE0, 0xC0, 0x80, 0x00, 0x00, 0x03, 0x03, 0x03, 0x80, 0xC0, 0x60, 0x38, 0x3F, 0x1F, 0x07, 0x00, 0x00, 0x1C, 0x1E, 0x1B, 0x19, 0x18, 0x18, 0x18, 0x18, 0x1F, 0x1F, 0x00, /*"2",2*/ - 0x00, 0x80, 0xC0, 0xE0, 0x20, 0x20, 0x60, 0xE0, 0xC0, 0x80, 0x00, 0x00, 0x00, 0x03, 0x03, 0x03, 0x10, 0x10, 0x18, 0x3F, 0xEF, 0xE7, 0x80, 0x00, 0x00, 0x07, 0x0F, 0x1F, 0x10, 0x10, 0x10, 0x18, 0x1F, 0x0F, 0x07, 0x00, /*"3",3*/ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF0, 0x00, 0x00, 0x00, 0xC0, 0xF0, 0xB8, 0x8E, 0x87, 0x81, 0xFF, 0xFF, 0xFF, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x1F, 0x1F, 0x1F, 0x10, 0x10, /*"4",4*/ - 0x00, 0x00, 0xE0, 0xE0, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x00, 0x00, 0x00, 0x3F, 0x3F, 0x18, 0x08, 0x08, 0x18, 0xF8, 0xF0, 0xE0, 0x00, 0x00, 0x07, 0x0F, 0x1B, 0x10, 0x10, 0x10, 0x1C, 0x1F, 0x0F, 0x03, 0x00, /*"5",5*/ - 0x00, 0x00, 0x80, 0xC0, 0xC0, 0x60, 0x20, 0x20, 0xE0, 0xE0, 0xC0, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0x31, 0x18, 0x08, 0x08, 0x18, 0xF8, 0xF0, 0xE0, 0x00, 0x01, 0x07, 0x0F, 0x1C, 0x18, 0x10, 0x10, 0x18, 0x0F, 0x0F, 0x03, /*"6",6*/ - 0x00, 0x00, 0xC0, 0xE0, 0xE0, 0x60, 0x60, 0x60, 0x60, 0xE0, 0xE0, 0x60, 0x00, 0x00, 0x03, 0x03, 0x00, 0x00, 0xE0, 0xF8, 0x1F, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x1F, 0x1F, 0x00, 0x00, 0x00, 0x00, /*"7",7*/ - 0x00, 0x80, 0xC0, 0xE0, 0x60, 0x20, 0x20, 0x20, 0x60, 0xE0, 0xC0, 0x80, 0x00, 0x87, 0xEF, 0xEF, 0x3C, 0x18, 0x38, 0x30, 0x78, 0xEF, 0xCF, 0x83, 0x00, 0x07, 0x0F, 0x0F, 0x18, 0x10, 0x10, 0x10, 0x18, 0x1F, 0x0F, 0x07, /*"8",8*/ - 0x00, 0x00, 0xC0, 0xC0, 0xE0, 0x20, 0x20, 0x20, 0xE0, 0xC0, 0x80, 0x00, 0x00, 0x1F, 0x3F, 0x7F, 0x60, 0x40, 0x40, 0x60, 0x30, 0xFF, 0xFF, 0xFE, 0x00, 0x00, 0x0C, 0x1C, 0x1C, 0x10, 0x10, 0x18, 0x0F, 0x0F, 0x03, 0x00, /*"9",9*/ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x0E, 0x0E, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x1C, 0x1C, 0x1C, 0x00, 0x00, 0x00, /*":",10*/ - -}; -static FontLibrary_t fontclocklib = { - .font = fontclocklib_code, - .fontIndex = "0123456789:", - .fontIndexLen = 12, - .fontCode = kgbk, - .isAscii = true, - .widthPixel = 12, - .heightPixel = 24, -}; - -const uint8_t font8x8_xo_code[] = { - 0x00, 0x3C, 0x7E, 0x7E, 0x7E, 0x7E, 0x3C, 0x00, /*实心圆,代表完成*/ - 0x00, 0x3C, 0x42, 0x42, 0x42, 0x42, 0x3C, 0x00, /*空心圆,代表未完成*/ - -}; - -static FontLibrary_t font8x8_xo_lib = { - .font = font8x8_xo_code, - .fontIndex = "ox", - .fontIndexLen = 2, - .fontCode = kgbk, - .isAscii = true, - .widthPixel = 8, - .heightPixel = 8, -}; - -const uint8_t font12x24_asiic_code[] = { - - 0x00, 0x00, 0xC0, 0xE0, 0x70, 0x30, 0x30, 0x60, 0xE0, 0xC0, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xFF, 0xFE, 0x00, 0x00, 0x01, 0x07, 0x0E, 0x0C, 0x18, 0x18, 0x0C, 0x0F, 0x07, 0x00, 0x00, /*"0",0*/ - 0x00, 0x00, 0x00, 0x80, 0xC0, 0xE0, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x01, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, /*"1",1*/ - 0x00, 0x80, 0xE0, 0x60, 0x30, 0x30, 0x30, 0x70, 0xE0, 0xC0, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x80, 0xC0, 0xE0, 0x38, 0x1F, 0x07, 0x00, 0x00, 0x00, 0x08, 0x0E, 0x0F, 0x0B, 0x09, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, /*"2",2*/ - 0x00, 0x80, 0xC0, 0x60, 0x30, 0x30, 0x30, 0x30, 0xE0, 0xC0, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x18, 0x18, 0x38, 0x7F, 0xE7, 0x80, 0x00, 0x00, 0x03, 0x07, 0x0C, 0x18, 0x18, 0x18, 0x0C, 0x0E, 0x07, 0x01, 0x00, /*"3",3*/ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0x00, 0x00, 0x00, 0x80, 0xC0, 0xF0, 0xB8, 0x8E, 0x87, 0x81, 0xFF, 0xFF, 0x80, 0x80, 0x80, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x0F, 0x0F, 0x01, 0x01, 0x01, /*"4",4*/ - 0x00, 0x00, 0xE0, 0xE0, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0x1C, 0x1F, 0x0D, 0x04, 0x04, 0x0C, 0x0C, 0x3C, 0xF8, 0xC0, 0x00, 0x01, 0x07, 0x0E, 0x08, 0x18, 0x18, 0x18, 0x0C, 0x0F, 0x07, 0x00, 0x00, /*"5",5*/ - 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xF0, 0x30, 0x10, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xF8, 0x1E, 0x0F, 0x0D, 0x0C, 0x0C, 0x18, 0xF8, 0xF0, 0x00, 0x00, 0x03, 0x07, 0x0C, 0x18, 0x18, 0x18, 0x18, 0x0C, 0x0F, 0x03, 0x00, /*"6",6*/ - 0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0xA0, 0xE0, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xF8, 0x1E, 0x07, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x0F, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"7",7*/ - 0x00, 0x80, 0xE0, 0x60, 0x30, 0x30, 0x30, 0x20, 0xE0, 0xC0, 0x00, 0x00, 0x00, 0xE3, 0xFF, 0x3C, 0x18, 0x18, 0x18, 0x3C, 0x3F, 0xE7, 0xC0, 0x00, 0x00, 0x07, 0x0F, 0x0C, 0x18, 0x18, 0x18, 0x18, 0x0C, 0x07, 0x03, 0x00, /*"8",8*/ - 0x00, 0xC0, 0xE0, 0x60, 0x30, 0x30, 0x30, 0x60, 0xE0, 0xC0, 0x00, 0x00, 0x02, 0x1F, 0x3D, 0x30, 0x60, 0x60, 0xE0, 0xF0, 0x7F, 0x1F, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10, 0x1C, 0x0F, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, /*"9",9*/ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x0C, 0x1C, 0xF0, 0xE0, 0xE0, 0x38, 0x1C, 0x04, 0x00, 0x00, 0x00, 0x10, 0x1C, 0x0E, 0x03, 0x01, 0x03, 0x07, 0x0E, 0x18, 0x10, 0x00, /*"x",10*/ - 0x00, 0x30, 0xF0, 0xE0, 0x00, 0x00, 0x00, 0x80, 0xE0, 0x70, 0x10, 0x00, 0x00, 0x00, 0x00, 0x83, 0xEF, 0x7C, 0x7E, 0xE7, 0x81, 0x00, 0x00, 0x00, 0x10, 0x1C, 0x1F, 0x07, 0x01, 0x00, 0x00, 0x01, 0x0F, 0x1E, 0x18, 0x00, /*"X",11*/ - 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x60, 0x60, 0x60, 0x60, 0x60, 0x00, /*"[",12*/ - 0x00, 0x0C, 0x0C, 0x0C, 0x0C, 0xFC, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x60, 0x60, 0x60, 0x7F, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, - /*"]",13*/}; - -static FontLibrary_t font12x24_asiic_lib = { - .font = font12x24_asiic_code, - .fontIndex = "0123456789xX[]", - .fontIndexLen = 15, - .fontCode = kgbk, - .isAscii = true, - .widthPixel = 12, - .heightPixel = 24, -}; - -const uint8_t font24x24_zh_code[] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xF8, 0x38, 0x10, 0x10, 0xF0, 0x90, 0x10, 0x10, 0x10, 0x88, 0xF8, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x10, 0x0C, 0x06, 0xE7, 0x1C, 0x10, 0x10, 0x10, 0x10, 0x93, - 0x71, 0xFF, 0x39, 0x49, 0x89, 0x08, 0x08, 0x0C, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x04, 0x02, 0x01, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x03, 0x07, 0x06, 0x06, 0x04, 0x04, 0x00, /*"保",0*/ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xFC, 0xFC, 0xC0, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xC2, 0x63, 0x33, 0xFF, 0x0D, 0x09, 0x08, 0x48, - 0x48, 0x49, 0x48, 0x47, 0x4F, 0xFC, 0x24, 0x24, 0x26, 0x06, 0x04, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x08, 0x38, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x02, 0x20, 0x60, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"持",1*/ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x40, 0xFC, 0x20, 0xA0, 0x20, 0x00, 0x80, 0x60, 0x3C, 0x2C, 0xA0, 0x70, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x0C, 0x94, 0x75, 0x55, 0x57, 0x15, 0xF4, 0x02, 0x90, - 0x92, 0x92, 0x92, 0xFF, 0x92, 0x8A, 0x49, 0x3F, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x18, 0x0F, 0x02, 0x01, 0x09, 0x18, 0x0F, 0x00, 0x00, 0x00, 0x20, 0x60, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"静",2*/ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0xF8, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xF8, 0x00, 0x00, 0x00, - 0xFF, 0x0F, 0x08, 0x08, 0x08, 0x0C, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x18, 0x08, 0x08, 0x08, 0x0F, 0x08, 0x08, 0x0C, 0x0F, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x00, 0x00, /*"止",3*/ - 0x00, 0x00, 0x00, 0x00, 0x40, 0x60, 0x60, 0x60, 0x20, 0x20, 0x20, 0x20, 0xA0, 0xE0, 0x30, 0x30, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xC0, 0x60, 0x30, 0x0D, 0xFF, - 0x03, 0x00, 0x00, 0x10, 0x20, 0x60, 0xE0, 0xC0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x04, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x00, 0x00, 0x00, /*"不",4*/ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0xE0, 0x20, 0x20, 0x10, 0x10, 0x10, 0xF8, 0xF8, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x70, 0x61, 0x87, 0x82, 0x06, 0xFE, - 0x12, 0x11, 0x11, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x04, 0x03, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x03, 0x02, 0x06, 0x0C, 0x0C, 0x18, 0x18, 0x18, 0x18, 0x18, 0x10, 0x00, 0x00, /*"足",5*/ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x40, 0xE0, 0x30, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x04, 0xC4, 0x64, 0x1A, 0xFF, 0x12, 0x32, 0x00, 0x18, - 0x0F, 0x00, 0x00, 0x1F, 0x80, 0xE0, 0x3C, 0x08, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x40, 0x20, 0x30, 0x18, 0x0C, 0x06, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"秒",6*/ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x20, 0x20, 0x38, 0xF8, 0x20, 0x20, 0x20, 0x60, 0x9C, 0x24, 0x10, 0x10, 0x10, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x67, 0x7E, 0x00, - 0x10, 0x8C, 0x9B, 0xB9, 0xE4, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x20, 0x20, 0x20, 0x23, 0x3F, 0x11, 0x13, 0x1D, 0x11, 0x1D, 0x17, 0x10, 0x18, 0x1F, 0x11, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, /*"蓝",7*/ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x10, 0x10, 0x10, 0x10, 0x10, 0xF0, 0x18, 0x18, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x0F, 0x04, 0x84, 0x64, 0x34, 0x1E, - 0x06, 0xFF, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x04, 0x02, 0x01, 0x00, 0x00, 0x10, 0x20, 0x70, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"牙",8*/ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x10, 0xF0, 0x70, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x0E, 0x08, 0x08, 0x08, 0x04, 0x04, 0x07, - 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x06, 0x08, 0x08, 0x18, 0x18, 0x18, 0x10, 0x18, 0x18, 0x18, 0x18, 0x08, 0x08, 0x0C, 0x0E, 0x07, 0x00, 0x00, 0x00, /*"已",9*/ - 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x30, 0x10, 0xC0, 0xC0, 0x00, 0x00, 0x40, 0x20, 0x20, 0xA0, 0xF0, 0x30, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x67, 0x74, 0x2C, 0x26, 0x01, 0x00, 0x10, 0x50, - 0x48, 0x44, 0xC3, 0xC3, 0x62, 0x24, 0x2C, 0x0C, 0x18, 0x10, 0x00, 0x00, 0x00, 0x00, 0x04, 0x04, 0x04, 0x06, 0x02, 0x02, 0x01, 0x10, 0x18, 0x08, 0x08, 0x08, 0x0F, 0x0B, 0x08, 0x08, 0x08, 0x0C, 0x0C, 0x08, 0x00, 0x00, /*"经",10*/ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0xC0, 0x00, 0x00, 0x40, 0x40, 0xC0, 0xE0, 0x5C, 0x2C, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x08, 0xF8, 0x08, 0x00, 0x40, 0x48, 0x4E, 0x4B, - 0x44, 0x45, 0xFF, 0x24, 0x24, 0x24, 0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x08, 0x0C, 0x04, 0x07, 0x04, 0x04, 0x08, 0x08, 0x08, 0x08, 0x10, 0x10, 0x17, 0x30, 0x30, 0x30, 0x30, 0x30, 0x10, 0x10, 0x00, 0x00, /*"连",11*/ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x88, 0x98, 0xD0, 0xC0, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x82, 0xC2, 0x62, 0xFF, 0x11, 0x91, 0x80, 0x80, 0x90, - 0x92, 0xF4, 0xB0, 0x98, 0x97, 0x89, 0x48, 0x48, 0x48, 0x40, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x18, 0x3F, 0x0F, 0x00, 0x00, 0x20, 0x20, 0x13, 0x12, 0x0C, 0x06, 0x0F, 0x08, 0x18, 0x30, 0x20, 0x00, 0x00, 0x00, /*"接",12*/ - 0x00, 0x00, 0x00, 0xE0, 0x40, 0x40, 0x80, 0x00, 0xF8, 0x88, 0x40, 0x20, 0x00, 0x80, 0x80, 0x40, 0x40, 0x20, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x80, 0x40, 0x25, 0x1A, 0xFF, 0x12, 0x12, 0x12, - 0x00, 0xE0, 0x3F, 0x08, 0x04, 0xFC, 0xFC, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x04, 0x02, 0x02, 0x02, 0x03, 0x02, 0x12, 0x08, 0x06, 0x01, 0x00, 0x00, 0x00, 0x7F, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, /*"断",13*/ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x60, 0x60, 0xE0, 0x20, 0x20, 0x20, 0x20, 0xF0, 0x30, 0x30, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0xE8, 0x3F, 0x08, 0x08, - 0x04, 0x04, 0xFF, 0x04, 0x04, 0x04, 0x04, 0x04, 0x06, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x08, 0x04, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"开",14*/ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9C, 0xF8, 0x80, 0x80, 0x80, 0x80, 0xC0, 0xC0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x7F, 0x81, 0x89, 0x49, 0xC8, 0xFF, 0x4C, - 0x44, 0x44, 0x40, 0x3C, 0x0F, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x0F, 0x18, 0x10, 0x10, 0x30, 0x30, 0x30, 0x10, 0x10, 0x1A, 0x1C, 0x00, 0x00, 0x00, /*"电",15*/ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x78, 0xA8, 0xA8, 0xA8, 0xA8, 0x88, 0xE4, 0x7C, 0x18, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x04, 0x04, 0x04, 0x04, 0x14, 0xF4, 0x94, 0x14, 0x52, 0xF2, - 0xAA, 0xAA, 0x8A, 0xFA, 0x3A, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x20, 0x20, 0x24, 0x25, 0x25, 0x25, 0x3F, 0x24, 0x24, 0x27, 0x30, 0x30, 0x30, 0x30, 0x20, 0x00, 0x00, 0x00, 0x00, /*"量",16*/ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x40, 0x40, 0x40, 0xC0, 0xC6, 0xFC, 0xA0, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x10, 0x08, 0x24, 0xE6, 0xA3, 0xA1, 0x94, 0xAF, - 0x10, 0x11, 0xF3, 0xF6, 0x2C, 0x0C, 0x18, 0x18, 0x18, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x20, 0x20, 0x20, 0x21, 0x27, 0x24, 0x24, 0x34, 0x12, 0x16, 0x13, 0x10, 0x10, 0x10, 0x10, 0x30, 0x00, 0x00, 0x00, 0x00, /*"查",17*/ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA0, 0x90, 0x90, 0xF0, 0xB8, 0x88, 0x8C, 0xCC, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0xC8, 0x78, 0xFC, 0xA7, 0xA4, - 0xA4, 0xA4, 0x14, 0x14, 0xF2, 0x22, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x10, 0x10, 0x08, 0x04, 0x02, 0x01, 0x00, 0x00, 0x3F, 0x14, 0x14, 0x14, 0x12, 0x10, 0x30, 0x7F, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"看",18*/ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x60, 0x38, 0x10, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x38, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0xC6, 0x65, 0x3C, 0x2C, 0x23, 0x01, 0x80, 0x02, - 0x22, 0x22, 0x22, 0x22, 0x3F, 0x91, 0x91, 0x91, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x04, 0x0C, 0x04, 0x06, 0x02, 0x02, 0x01, 0x01, 0x00, 0x00, 0x03, 0x1F, 0x09, 0x09, 0x09, 0x08, 0x08, 0x0F, 0x01, 0x00, 0x00, 0x00, /*"结",19*/ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x30, 0xF0, 0x10, 0x90, 0x90, 0xF0, 0xF0, 0xD0, 0x10, 0x88, 0xF8, 0x78, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x60, 0x21, 0x27, 0xA4, 0x64, 0xFF, - 0x52, 0x92, 0x12, 0x13, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x20, 0x10, 0x08, 0x04, 0x06, 0x03, 0x01, 0x00, 0x7F, 0x00, 0x00, 0x01, 0x02, 0x06, 0x0C, 0x18, 0x18, 0x18, 0x10, 0x00, 0x00, /*"果",20*/ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x20, 0x20, 0xD0, 0x90, 0x18, 0x0C, 0x88, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x20, 0x60, 0x20, 0x20, 0x20, 0x22, 0x22, 0x33, 0x11, - 0xFF, 0x11, 0x11, 0x11, 0x11, 0x10, 0x18, 0x18, 0x18, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x20, 0x60, 0x78, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*"手",21*/ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xC0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x86, 0xC2, 0x32, 0x0F, 0xFF, 0x21, 0x61, 0x01, 0x01, - 0xFF, 0x01, 0x01, 0x00, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x04, 0x02, 0x01, 0x00, 0x00, 0x3F, 0x0F, 0x00, 0x08, 0x04, 0x03, 0x01, 0x00, 0x00, 0x00, 0x07, 0x06, 0x0C, 0x0C, 0x0C, 0x0F, 0x06, 0x00, /*"机",22*/ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x20, 0x20, 0x50, 0xD0, 0x88, 0x0C, 0x8C, 0x40, 0x70, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x11, 0xD0, 0x70, 0x32, 0xFC, 0x30, - 0x48, 0x88, 0x88, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x04, 0x02, 0x01, 0x00, 0x00, 0x30, 0x7F, 0x00, 0x00, 0x00, 0x01, 0x03, 0x06, 0x06, 0x0C, 0x0C, 0x04, 0x08, 0x00, 0x00, /*"采",23*/ - 0x00, 0x00, 0x00, 0x00, 0x80, 0x40, 0x20, 0xF0, 0x0C, 0x24, 0xA0, 0xA4, 0xEC, 0xE8, 0x90, 0x50, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0xBF, 0x90, 0x90, 0xD2, 0xF2, - 0xCF, 0x4B, 0x4A, 0x49, 0x48, 0x48, 0x60, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x10, 0x10, 0x08, 0x04, 0x06, 0x03, 0x01, 0x7F, 0x00, 0x01, 0x02, 0x04, 0x0C, 0x18, 0x18, 0x18, 0x10, 0x10, 0x00, 0x00, /*"集",24*/ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x7C, 0xC0, 0x80, 0x80, 0x88, 0x98, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xFE, 0x42, 0x42, 0x22, 0x22, 0xE1, 0x21, - 0x03, 0x1F, 0x70, 0x80, 0xE0, 0x3C, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x08, 0x06, 0x03, 0x00, 0x04, 0x08, 0x1C, 0x07, 0x00, 0x08, 0x04, 0x02, 0x01, 0x07, 0x0C, 0x18, 0x30, 0x70, 0x78, 0x00, 0x00, /*"成",25*/ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x81, 0x81, 0xC1, 0x7F, 0x20, 0x20, 0x20, 0x12, - 0x82, 0xE2, 0x3E, 0x07, 0x02, 0x01, 0x01, 0xFF, 0x0F, 0x02, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x10, 0x10, 0x08, 0x04, 0x03, 0x01, 0x00, 0x04, 0x08, 0x38, 0x1C, 0x0F, 0x01, 0x00, 0x00, 0x00, 0x00, /*"功",26*/ - 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x80, 0x80, 0x80, 0x40, 0x48, 0x58, 0x50, 0x40, 0x20, 0x20, 0xA0, 0xE0, 0xC0, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x01, 0x40, 0x60, 0x24, 0xE4, 0x26, 0x22, - 0xF2, 0x12, 0x10, 0x10, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x08, 0x04, 0x06, 0x03, 0x00, 0x00, 0x00, 0x1F, 0x30, 0x20, 0x20, 0x20, 0x20, 0x20, 0x30, 0x3E, 0x10, 0x00, 0x00, /*"完",27*/ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x78, 0x10, 0x00, 0x80, 0x80, 0x40, 0x40, 0xA0, 0x38, 0x18, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x18, 0x0C, 0x03, 0xFD, 0x00, 0x00, 0x00, 0xE1, 0xFF, - 0x10, 0x88, 0x0F, 0x3C, 0xE4, 0x84, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x1F, 0x00, 0x00, 0x04, 0x0F, 0x03, 0x01, 0x00, 0x04, 0x0C, 0x00, 0x01, 0x06, 0x0C, 0x18, 0x3E, 0x30, 0x00, /*"低",28*/ -}; -static FontLibrary_t font24x24_zh_lib = { - .font = font24x24_zh_code, - .fontIndex = "保持静止不足秒蓝牙已经连接断开电量查看结果手机采集成功完低", - .fontIndexLen = 88, - .fontCode = kgbk, - .isAscii = false, - .widthPixel = 24, - .heightPixel = 24, -}; - -#if 0 -// const unsigned char gImage_heart_16x16[] = { -// /* 0X22,0X01,0X10,0X00,0X10,0X00, */ -// 0X00, 0XF8, 0XFC, 0XFE, 0XFE, 0XFE, 0XFE, 0XFC, 0XFC, 0XFE, 0XFE, 0XFE, 0XFE, 0XFC, 0XF8, 0X00, 0X00, 0X00, 0X03, 0X07, 0X0F, 0X1F, 0X3F, 0X7F, 0X7F, 0X3F, 0X1F, 0X0F, 0X07, 0X03, 0X00, 0X00, -// }; -#endif - -const unsigned char font_asicc_code_16x8[] = { - 0x00, 0xF0, 0x18, 0x08, 0x08, 0x18, 0xE0, 0x00, 0x00, 0x0F, 0x10, 0x20, 0x30, 0x18, 0x0F, 0x00, /*"0",0*/ - 0x00, 0x60, 0x20, 0xF0, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x3F, 0x00, 0x00, 0x00, /*"1",1*/ - 0x00, 0x30, 0x18, 0x08, 0x08, 0xD8, 0x70, 0x00, 0x00, 0x30, 0x38, 0x34, 0x33, 0x31, 0x30, 0x00, /*"2",2*/ - 0x00, 0x30, 0x18, 0x08, 0x88, 0xD8, 0x70, 0x00, 0x00, 0x18, 0x10, 0x20, 0x21, 0x13, 0x0E, 0x00, /*"3",3*/ - 0x00, 0x00, 0x80, 0x60, 0x30, 0xF8, 0x00, 0x00, 0x04, 0x07, 0x05, 0x04, 0x04, 0x3F, 0x04, 0x04, /*"4",4*/ - 0x00, 0xF0, 0x98, 0xC8, 0x88, 0x88, 0x08, 0x00, 0x08, 0x19, 0x30, 0x20, 0x30, 0x19, 0x0F, 0x00, /*"5",5*/ - 0x00, 0x80, 0xC0, 0xF0, 0x98, 0x80, 0x00, 0x00, 0x00, 0x1F, 0x31, 0x20, 0x20, 0x30, 0x1F, 0x06, /*"6",6*/ - 0x00, 0x08, 0x08, 0x08, 0x88, 0xE8, 0x38, 0x00, 0x00, 0x00, 0x30, 0x3E, 0x03, 0x00, 0x00, 0x00, /*"7",7*/ - 0x00, 0xF0, 0x88, 0x88, 0x88, 0xD8, 0x70, 0x00, 0x04, 0x1F, 0x31, 0x21, 0x21, 0x31, 0x1E, 0x00, /*"8",8*/ - 0xE0, 0xF0, 0x08, 0x08, 0x08, 0x98, 0xF0, 0x00, 0x00, 0x01, 0x23, 0x3A, 0x0F, 0x03, 0x00, 0x00, /*"9",9*/ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, /*"-",10*/ - 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x11, 0x00, 0x00, 0x00, /*":",10*/ - - 0X00, 0XF8, 0XFC, 0XFE, 0XFE, 0XFE, 0XFE, 0XFC, 0X00, 0X00, 0X03, 0X07, 0X0F, 0X1F, 0X3F, 0X7F, /*?右半*/ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*" "*/ -}; - -static FontLibrary_t font_asicc16x8_lib = { - .font = font_asicc_code_16x8, - .fontIndex = "0123456789-:<> ", // <> 这两个符号是心形的左右半边 - .fontIndexLen = 16, - .fontCode = kgbk, - .isAscii = true, - .widthPixel = 8, - .heightPixel = 16, -}; diff --git a/app/src/one_conduction/heart_wave_sample_service.c b/app/src/one_conduction/heart_wave_sample_service.c deleted file mode 100644 index 3fe2789..0000000 --- a/app/src/one_conduction/heart_wave_sample_service.c +++ /dev/null @@ -1,156 +0,0 @@ -#include "heart_wave_sample_service.h" - -#include "app_event.h" -#include "nrfx_timer.h" -#include "one_conduction_board.h" - -static const nrfx_timer_t m_timer = NRFX_TIMER_INSTANCE(1); /**< Timer used for channel sweeps and tx with duty cycle. */ -static bool m_timer_started = false; /**< True if timer is running. */ - -static uint16_t m_capture_buffer_a[128]; -static uint16_t m_capture_buffer_b[128]; - -static uint16_t* m_capture_buffer; -static uint16_t m_capture_buffer_index = 0; - -volatile static float m_sensor_display_data = 0; // 0->100 -static uint32_t m_start_capture_tp; -static uint32_t m_frameindex = 0; - -static void swap_buffer() { - if (m_capture_buffer == NULL) { - m_capture_buffer = m_capture_buffer_a; - m_capture_buffer_index = 0; - return; - } - - if (m_capture_buffer == m_capture_buffer_a) { - m_capture_buffer = m_capture_buffer_b; - } else { - m_capture_buffer = m_capture_buffer_a; - } - m_capture_buffer_index = 0; - return; -} -static float amp_val(uint16_t val, uint16_t valcener, float amp) { - float valf = (float)val - valcener; - valf = valf * amp; - valf += valcener; - - if (valf >= 100) { - valf = 100; - } - - if (valf <= 0) { - valf = 0; - } - return valf; -} - -typedef struct { - float value; - float efectiveFactor; -} filter_t; - -filter_t m_filter = {0, 0.8}; - -static float Filter(filter_t* filter, float newInput) { - float newv = ((float)filter->value * (1.0f - filter->efectiveFactor)) + ((float)newInput * filter->efectiveFactor); - filter->value = newv; - return newv; -} - -void nrfx_timer_event_handler(nrf_timer_event_t event_type, void* p_context) { // - uint16_t val = SingleLeadECG_ecg_plod_get_ecg_val(); // 12bit - m_frameindex++; - - /******************************************************************************* - * 显示数据计算并赋值 * - *******************************************************************************/ - float val_af100 = (float)val / 4096.0f * 100; - val_af100 = amp_val(val_af100, 50, 1.8f); - val_af100 = Filter(&m_filter, val_af100); - m_sensor_display_data = val_af100; - - /******************************************************************************* - * 采样数据缓存 * - *******************************************************************************/ - if (m_capture_buffer == NULL) { - swap_buffer(); - } - - if (m_capture_buffer_index < 128) { - m_capture_buffer[m_capture_buffer_index++] = val; - } - - if (m_capture_buffer_index == 128) { - app_event_t evt; - evt.eventType = kevent_capture_256data_event; - evt.val.capture_data_cache = (uint8_t*)m_capture_buffer; - swap_buffer(); - app_sched_event_put(&evt, sizeof(evt), app_event_process_cb); - } - - /******************************************************************************* - * 实时采样数据事件上报 * - *******************************************************************************/ - { - static int index = 0; - if (index % 2 == 0) { - app_event_t evt; - evt.eventType = kevent_capture_1data_event; - evt.val.frame_data.frameIndex = m_frameindex; - evt.val.frame_data.data = val; - swap_buffer(); - app_sched_event_put(&evt, sizeof(evt), app_event_process_cb); - } - index++; - } -} - -void hwss_init(void) { - if (m_timer_started) { - return; - } - /** - * @brief 初始化定时器 - */ - nrfx_err_t err; - nrfx_timer_config_t timer_cfg = { - .frequency = NRF_TIMER_FREQ_125kHz, - .mode = NRF_TIMER_MODE_TIMER, - .bit_width = NRF_TIMER_BIT_WIDTH_24, - .p_context = NULL, - .interrupt_priority = NRFX_TIMER_DEFAULT_CONFIG_IRQ_PRIORITY, - }; - - err = nrfx_timer_init(&m_timer, &timer_cfg, nrfx_timer_event_handler); - if (err != NRFX_SUCCESS) { - NRF_LOG_ERROR("nrfx_timer_init failed with: %d\n", err); - } - uint32_t timer_ticks = nrfx_timer_ms_to_ticks(&m_timer, 5); // 200HZ - nrfx_timer_extended_compare(&m_timer, NRF_TIMER_CC_CHANNEL0, timer_ticks, NRF_TIMER_SHORT_COMPARE0_CLEAR_MASK, true); - m_timer_started = true; -} -void hwss_uninit(void) { nrfx_timer_disable(&m_timer); } - -void hwss_start_capture(void) { - m_start_capture_tp = znordic_getpower_on_s(); - swap_buffer(); - m_frameindex = 0; - nrfx_timer_enable(&m_timer); -} -void hwss_stop_capture(void) { - nrfx_timer_disable(&m_timer); - m_frameindex = 0; -} - -float hwss_read_val(void) { - __disable_irq(); - float val = m_sensor_display_data; - __enable_irq(); - return val; -} -float hwss_read_heart_rate(void) { return 0; } - -int hwss_has_captured_time_ms() { return (znordic_getpower_on_s() - m_start_capture_tp) * 1000; } diff --git a/app/src/one_conduction/heart_wave_sample_service.h b/app/src/one_conduction/heart_wave_sample_service.h deleted file mode 100644 index 65e18dc..0000000 --- a/app/src/one_conduction/heart_wave_sample_service.h +++ /dev/null @@ -1,15 +0,0 @@ -#pragma once -#include "one_conduction_board.h" - -// 每256个字节触发一次回调 -typedef void (*heart_wave_sample_service_callback_t)(uint16_t *p_data, uint16_t length); - -void hwss_init(void); -void hwss_uninit(void); - -void hwss_start_capture(void); -void hwss_stop_capture(void); - -float hwss_read_val(void); -float hwss_read_heart_rate(void); -int hwss_has_captured_time_ms(); diff --git a/app/src/one_conduction/one_conduction_board.c b/app/src/one_conduction/one_conduction_board.c deleted file mode 100644 index 8eab403..0000000 --- a/app/src/one_conduction/one_conduction_board.c +++ /dev/null @@ -1,401 +0,0 @@ -#include "one_conduction_board.h" - -#include "znordic.h" -// -#include "app_timer.h" -#include "diskio_blkdev.h" -#include "ff.h" -#include "nrf_block_dev_sdc.h" -#include "nrf_delay.h" -#include "nrf_drv_pwm.h" -#include "nrf_drv_saadc.h" -#include "nrf_drv_twi.h" -#include "nrf_drv_wdt.h" -#include "nrf_gpio.h" -// -#include "basic/ssd1306/driver_ssd1306.h" -#include "basic/ssd1306/driver_ssd1306_basic.h" - -#define SCREEN_SPI_INSTANCE 0 -#define SCREEN_RESET_PIN 20 -#define SCREEN_POWER_PIN 30 -#define SCREEN_A0PIN 31 -#define SCREEN_CS_PIN 29 -#define SCREEN_CLK_PIN 4 -#define SCREEN_MOSI_PIN 11 - -#define LED_GREEN_PIN 9 -#define LED_BLUE_PIN 10 -// #define LED_GREEN_PIN 27 -// #define LED_BLUE_PIN 28 - -#define ECG_NLOD_PIN 3 -#define ECG_PLOD_PIN 28 -#define ECG_ADC_PIN NRF_SAADC_INPUT_AIN0 -#define ECG_ADC_CHANNEL 0 // 不重复即可 - -#define BATTERY_ADC_PIN NRF_SAADC_INPUT_AIN3 -#define BATTERY_ADC_CHANNEL 1 // 不重复即可 - -#define EEPROM_I2C_SCL_M 15 // I2C SCL引脚 -#define EEPROM_I2C_SDA_M 17 // I2C SDA引脚 -#define EEPROM_I2C_INSTANCE 1 // I2C使用的硬件控制器ID - -#define BEEP_PWM_INSTANCE 0 -#define BEEP_PIN 1 - -#define BATTERY_CHARGE_DETECT_PIN 18 - -/******************************************************************************* - * TOOLS * - *******************************************************************************/ - -/******************************************************************************* - * ADC * - *******************************************************************************/ - -uint8_t m_now_adc_channel = 0xff; - -void SingleLeadECG_adc_set_ch(uint8_t ch); -void SingleLeadECG_adc_module_init() { - nrf_drv_saadc_config_t adccfg = NRFX_SAADC_DEFAULT_CONFIG; - adccfg.resolution = NRF_SAADC_RESOLUTION_12BIT; // 4096 等于满采样率 - ZERROR_CHECK(nrf_drv_saadc_init(&adccfg, NULL)); - // SingleLeadECG_adc_set_ch(BATTERY_ADC_CHANNEL); -} -void SingleLeadECG_adc_set_ch(uint8_t ch) { - if (m_now_adc_channel != ch) { - if (m_now_adc_channel != 0xff) nrfx_saadc_channel_uninit(m_now_adc_channel); - - if (ch == ECG_ADC_CHANNEL) { - nrf_saadc_channel_config_t channel_config = NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(ECG_ADC_PIN); - channel_config.acq_time = NRF_SAADC_ACQTIME_40US; - ZERROR_CHECK(nrfx_saadc_channel_init(ECG_ADC_CHANNEL, &channel_config)); - } else if (ch == BATTERY_ADC_CHANNEL) { - nrf_saadc_channel_config_t channel_config = NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(BATTERY_ADC_PIN); - channel_config.acq_time = NRF_SAADC_ACQTIME_40US; - ZERROR_CHECK(nrfx_saadc_channel_init(BATTERY_ADC_CHANNEL, &channel_config)); - } - } - m_now_adc_channel = ch; -} - -int16_t SingleLeadECG_adc_get_val(uint8_t ch) { - SingleLeadECG_adc_set_ch(ch); - return znrf_adc_channel_read_val(ch); -} - -void SingleLeadECG_adc_module_deinit() { - SingleLeadECG_adc_set_ch(0xff); - nrf_drv_saadc_uninit(); -} - -/******************************************************************************* - * 蜂鸣器 * - *******************************************************************************/ -static nrf_drv_pwm_t m_beep_pwm0 = NRF_DRV_PWM_INSTANCE(BEEP_PWM_INSTANCE); -static nrf_pwm_values_individual_t m_beep_pwm0_seq_values = {0}; -static nrf_pwm_sequence_t const m_beep_pwm0_seq = { - .values.p_individual = &m_beep_pwm0_seq_values, - .length = NRF_PWM_VALUES_LENGTH(m_beep_pwm0_seq_values), - .repeats = 0, - .end_delay = 0, -}; -static nrf_drv_pwm_config_t const m_beep_pwm0_config0 = { - .output_pins = {BEEP_PIN}, - .irq_priority = APP_IRQ_PRIORITY_LOWEST, - .base_clock = NRF_PWM_CLK_125kHz, - .count_mode = NRF_PWM_MODE_UP, - .top_value = 46, // 125kHz / 46 = 2.717k - .load_mode = NRF_PWM_LOAD_INDIVIDUAL, - .step_mode = NRF_PWM_STEP_AUTO, -}; -APP_TIMER_DEF(m_beep_tmr); // 蜂鸣器自动关闭定时器 -bool m_beep_tmr_is_inited = false; -static void beep_tmr_handler(void *context) { SingleLeadECG_beep_set_state(false); } -void SingleLeadECG_beep_init() { - if (!m_beep_tmr_is_inited) { - m_beep_tmr_is_inited = true; - app_timer_create(&m_beep_tmr, APP_TIMER_MODE_SINGLE_SHOT, beep_tmr_handler); - } - - APP_ERROR_CHECK(nrfx_pwm_init(&m_beep_pwm0, &m_beep_pwm0_config0, NULL)); -} -void SingleLeadECG_beep_deinit() { - SingleLeadECG_beep_set_state(false); - nrfx_pwm_uninit(&m_beep_pwm0); -} - -void SingleLeadECG_beep_set_state(bool state) { - if (state) { - m_beep_pwm0_seq_values.channel_0 = 23; // 设置占空比,数值最大不超过 top_value - nrfx_pwm_simple_playback(&m_beep_pwm0, &m_beep_pwm0_seq, 1, NRF_DRV_PWM_FLAG_LOOP); - } else { - nrfx_pwm_stop(&m_beep_pwm0, true); - } -} -void SingleLeadECG_beep_trigger_once() { - SingleLeadECG_beep_set_state(true); - app_timer_start(m_beep_tmr, APP_TIMER_TICKS(200), NULL); -} - -/******************************************************************************* - * SCREEN * - *******************************************************************************/ - -static const nrf_drv_spi_t m_screen_spi = NRF_DRV_SPI_INSTANCE(SCREEN_SPI_INSTANCE); /**< SPI instance. */ - -void SingleLeadECG_screen_init() { - znrf_gpio_cfg_output(SCREEN_RESET_PIN, NRF_GPIO_PIN_NOPULL); - znrf_gpio_cfg_output(SCREEN_POWER_PIN, NRF_GPIO_PIN_NOPULL); - znrf_gpio_cfg_output(SCREEN_A0PIN, NRF_GPIO_PIN_NOPULL); - - nrf_gpio_pin_set(SCREEN_POWER_PIN); - // 参考 - // OLED驱动程序 : https://iflytop1.feishu.cn/wiki/OQ4Iwv0DpiQDJvkjftjcQHJBnCg - // nRF5_SDK-使用手册: https://iflytop1.feishu.cn/wiki/ThaAwZEGVi2bspkfGU9cbl9Enqd - nrf_drv_spi_config_t spi_config = NRF_DRV_SPI_DEFAULT_CONFIG; - spi_config.ss_pin = SCREEN_CS_PIN; // NRF_DRV_SPI_PIN_NOT_USED - spi_config.miso_pin = NRF_DRV_SPI_PIN_NOT_USED; - spi_config.mosi_pin = SCREEN_MOSI_PIN; - spi_config.sck_pin = SCREEN_CLK_PIN; - spi_config.frequency = NRF_DRV_SPI_FREQ_8M; - spi_config.mode = NRF_DRV_SPI_MODE_3; - ZERROR_CHECK(nrf_drv_spi_init(&m_screen_spi, &spi_config, NULL, NULL)); - ssd1306_basic_init(SSD1306_INTERFACE_SPI, SSD1306_ADDR_SA0_0); -} - -void SingleLeadECG_screen_deinit() { - ssd1306_basic_deinit(); - nrf_drv_spi_uninit(&m_screen_spi); -} - -uint8_t SingleLeadECG_spi_init(void) { return 0; } -uint8_t SingleLeadECG_spi_deinit(void) { return 0; } -uint8_t SingleLeadECG_spi_cmd_data_gpio_init(void) { return 0; } -uint8_t SingleLeadECG_spi_cmd_data_gpio_deinit(void) { return 0; } -void SingleLeadECG_debug_print(const char *const fmt, ...) {} -uint8_t SingleLeadECG_reset_gpio_init(void) { return 0; } -uint8_t SingleLeadECG_reset_gpio_deinit(void) { return 0; } -uint8_t SingleLeadECG_spi_write_cmd(uint8_t *buf, uint16_t len) { // - ZERROR_CHECK(nrf_drv_spi_transfer(&m_screen_spi, buf, len, NULL, 0)); - return 0; -} -void SingleLeadECG_delay_ms(uint32_t ms) { nrf_delay_ms(ms); } -uint8_t SingleLeadECG_spi_cmd_data_gpio_write(uint8_t value) { - if (value) { - nrf_gpio_pin_set(SCREEN_A0PIN); - } else { - nrf_gpio_pin_clear(SCREEN_A0PIN); - } - return 0; -} -uint8_t SingleLeadECG_reset_gpio_write(uint8_t value) { - if (value) { - nrf_gpio_pin_set(SCREEN_RESET_PIN); - } else { - nrf_gpio_pin_clear(SCREEN_RESET_PIN); - } - return 0; -} - -/******************************************************************************* - * LED * - *******************************************************************************/ -static bool io_init = false; - -void SingleLeadECG_led_init() { - if (io_init) { - return; - } - znrf_gpio_cfg_output(LED_GREEN_PIN, NRF_GPIO_PIN_NOPULL); - znrf_gpio_cfg_output(LED_BLUE_PIN, NRF_GPIO_PIN_NOPULL); - - // nrf_gpio_pin_write(LED_GREEN_PIN, 1); - // nrf_gpio_pin_write(LED_GREEN_PIN, 1); - - SingleLeadECG_led_green_set_state(false); - SingleLeadECG_led_blue_set_state(false); - io_init = true; -} -void SingleLeadECG_led_deinit() { - SingleLeadECG_led_green_set_state(false); - SingleLeadECG_led_blue_set_state(false); -} - -void SingleLeadECG_led_green_set_state(bool state) { - if (state) { - nrf_gpio_pin_set(LED_GREEN_PIN); - } else { - nrf_gpio_pin_clear(LED_GREEN_PIN); - } -} -void SingleLeadECG_led_blue_set_state(bool state) { - if (state) { - nrf_gpio_pin_set(LED_BLUE_PIN); - } else { - nrf_gpio_pin_clear(LED_BLUE_PIN); - } -} - -/******************************************************************************* - * ecg * - *******************************************************************************/ - -/** - * @brief - * PLOD: 表明当前点击连接状态,如果为0,表示连接,如果为1,表示断开 - */ - -void SingleLeadECG_ecg_init() {} - -void SingleLeadECG_ecg_deinit() {} - -void SingleLeadECG_ecg_io_init() { - nrf_gpio_cfg_sense_input(ECG_NLOD_PIN, NRF_GPIO_PIN_PULLUP, NRF_GPIO_PIN_NOSENSE); - nrf_gpio_cfg_sense_input(ECG_PLOD_PIN, NRF_GPIO_PIN_PULLUP, NRF_GPIO_PIN_NOSENSE); -} - -uint32_t SingleLeadECG_ecg_nlod_get_connected_state() { return nrf_gpio_pin_read(ECG_NLOD_PIN); } -uint32_t SingleLeadECG_ecg_plod_get_connected_state() { return !nrf_gpio_pin_read(ECG_PLOD_PIN); } -int16_t SingleLeadECG_ecg_plod_get_ecg_val() { return SingleLeadECG_adc_get_val(ECG_ADC_CHANNEL); } - -/******************************************************************************* - * BATTERY * - *******************************************************************************/ -void SingleLeadECG_battery_init() {} -void SingleLeadECG_battery_deinit() {} - -int16_t SingleLeadECG_battery_get_adc_val() { return SingleLeadECG_adc_get_val(BATTERY_ADC_CHANNEL); } -int16_t SingleLeadECG_battery_val() { // - - static const float maxv = 4.0; - static const float minv = 3.5; - - float voltage = SingleLeadECG_battery_get_adc_val() / 4096.0 * 3.3 / 2.0 * 3; - if (voltage > maxv) voltage = maxv; - if (voltage < minv) voltage = minv; - - float percent = (voltage - minv) / (maxv - minv) * 100 + (float)0.1 /*加0.1是为了避免999.999时显示电量为90*/; - int16_t percent_int = (int16_t)percent; - if (percent_int < 10 && percent_int != 0) { - percent_int = 3; - } else { - percent_int = percent_int / 10 * 10; - } - // ZLOGI("battery %d ", SingleLeadECG_battery_get_adc_val()); - return percent_int; -} -void SingleLeadECG_battery_charge_detect_io_init() { // - nrf_gpio_cfg_sense_input(BATTERY_CHARGE_DETECT_PIN, NRF_GPIO_PIN_PULLUP, NRF_GPIO_PIN_NOSENSE); -} -bool SingleLeadECG_battery_charge_get_state() { return nrf_gpio_pin_read(BATTERY_CHARGE_DETECT_PIN) == 0; } - -/******************************************************************************* - * eeprom * - *******************************************************************************/ -static const nrf_drv_twi_t m_eeprom_twi_master = NRF_DRV_TWI_INSTANCE(EEPROM_I2C_INSTANCE); - -void SingleLeadECG_eeprom_init() { - nrf_drv_twi_config_t config = NRF_DRV_TWI_DEFAULT_CONFIG; - - config.scl = EEPROM_I2C_SCL_M; - config.sda = EEPROM_I2C_SDA_M; - config.frequency = NRF_DRV_TWI_FREQ_400K; - ZERROR_CHECK(nrf_drv_twi_init(&m_eeprom_twi_master, &config, NULL, NULL)); - nrf_drv_twi_enable(&m_eeprom_twi_master); -} - -void SingleLeadECG_eeprom_uninit() { - nrf_drv_twi_disable(&m_eeprom_twi_master); - nrf_drv_twi_uninit(&m_eeprom_twi_master); -} - -static uint8_t eeprom_cache[EEPROM_PAGE + 2]; - -static void assign_i2c_add(uint32_t add, bool wr, uint8_t *i2cadd, uint8_t *memadd0, uint8_t *memadd1) { - // DEVICE SELECT - // bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0 - // 1 0 1 0 E2 A17 A16 RW(W=0) - // - // PS: E2 参考原理图中的电平为0,所以bit3为0 - // - // MEM0 - // bit15 bit14 bit13 bit12 bit11 bit10 bit9 bit8 - // MEM1 - // bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0 - // - - *i2cadd = 0xA0; - uint8_t a16a17 = (add >> 16) & 0x03; - *i2cadd |= a16a17 << 1; - *i2cadd = *i2cadd >> 1; - - *memadd0 = add >> 8; - *memadd1 = add & 0xFF; -} - -void SingleLeadECG_eeprom_write(uint32_t addr, const uint8_t *data, uint16_t len) { // - // uint32_t addr = page * EEPROM_PAGE; - // len = len > EEPROM_PAGE ? EEPROM_PAGE : len; - - // ZASSERT(len == EEPROM_PAGE); - ZASSERT((addr % EEPROM_PAGE) == 0); - // ZLOGI_BLOCK("eeprom_write %d %d", addr, len); - uint8_t deviceSelect = 0; - - assign_i2c_add(addr, true, &deviceSelect, &eeprom_cache[0], &eeprom_cache[1]); - memcpy(&eeprom_cache[2], data, len); - - ret_code_t ecode = nrf_drv_twi_tx(&m_eeprom_twi_master, deviceSelect, eeprom_cache, len + 2, false); - if (ecode != NRF_SUCCESS) { - ZLOGE("nrf_drv_twi_tx error %x", ecode); - NRF_LOG_INTERNAL_FLUSH(); - } -} -/** - * @brief 用来检测读取整个eeprom是否正常 - */ -void SingleLeadECG_eeprom_wr_check() { - /** - * @brief - * 256kbyte - * 写入数据,回读检查数据是否正确 - */ - - static uint8_t wdata_cache[256]; - static uint8_t rdata_cache[256]; -#define CHECKCODE (i % 21) - - for (uint32_t i = 0; i < 1024; i++) { - uint32_t addr = i * EEPROM_PAGE; - for (uint32_t j = 0; j < EEPROM_PAGE; j++) { - wdata_cache[j] = CHECKCODE; - } - ZLOGI_BLOCK("write %d", i); - SingleLeadECG_eeprom_write(addr, wdata_cache, EEPROM_PAGE); - nrf_delay_ms(15); - } - - for (uint32_t i = 0; i < 1024; i++) { - uint32_t addr = i * EEPROM_PAGE; - ZLOGI_BLOCK("check %d", i); - SingleLeadECG_eeprom_read(addr, rdata_cache, EEPROM_PAGE); - for (uint32_t j = 0; j < EEPROM_PAGE; j++) { - if (rdata_cache[j] != (CHECKCODE)) { - ZLOGE("SingleLeadECG_eeprom_wr_check error %d %d %d", i, j, rdata_cache[j]); - } - } - } -} - -void SingleLeadECG_eeprom_read(uint32_t add, uint8_t *data, uint16_t len) { - uint8_t deviceSelect = 0; - uint8_t wadd[2] = {0}; - - assign_i2c_add(add, false, &deviceSelect, &wadd[0], &wadd[1]); - nrf_drv_twi_tx(&m_eeprom_twi_master, deviceSelect, wadd, 2, false); - - deviceSelect |= 0x01; // read - nrf_drv_twi_rx(&m_eeprom_twi_master, deviceSelect, data, len); -} diff --git a/app/src/one_conduction/one_conduction_board.h b/app/src/one_conduction/one_conduction_board.h deleted file mode 100644 index f2c33f6..0000000 --- a/app/src/one_conduction/one_conduction_board.h +++ /dev/null @@ -1,77 +0,0 @@ -#pragma once -#define VERSION 1 -#define MANUFACTURER_NAME "iflytop" - -/******************************************************************************* - * INCLUDE * - *******************************************************************************/ -#include - -#include "basic/ssd1306/driver_ssd1306_interface.h" -#include "znordic.h" - -/******************************************************************************* - * basic * - *******************************************************************************/ -void SingleLeadECG_adc_module_init(); -void SingleLeadECG_adc_module_deinit(); - -/******************************************************************************* - * 蜂鸣器 * - *******************************************************************************/ -void SingleLeadECG_beep_init(); -void SingleLeadECG_beep_deinit(); -void SingleLeadECG_beep_set_state(bool state); -void SingleLeadECG_beep_trigger_once(); - -/******************************************************************************* - * EEPROM * - *******************************************************************************/ -/** - * - * PageSize 256byte - * - */ -#define EEPROM_PAGE 256 -void SingleLeadECG_eeprom_init(); -void SingleLeadECG_eeprom_uninit(); -void SingleLeadECG_eeprom_write(uint32_t page, const uint8_t* data, uint16_t len); -void SingleLeadECG_eeprom_read(uint32_t add, uint8_t* data, uint16_t len); - -/******************************************************************************* - * SCREEN * - *******************************************************************************/ - -void SingleLeadECG_screen_init(); -void SingleLeadECG_screen_deinit(); - -/******************************************************************************* - * LED * - *******************************************************************************/ -void SingleLeadECG_led_init(); -void SingleLeadECG_led_deinit(); -void SingleLeadECG_led_green_set_state(bool state); -void SingleLeadECG_led_blue_set_state(bool state); - -/******************************************************************************* - * ECG * - *******************************************************************************/ - -void SingleLeadECG_ecg_init(); -void SingleLeadECG_ecg_deinit(); -void SingleLeadECG_ecg_io_init(); - -uint32_t SingleLeadECG_ecg_nlod_get_connected_state(); -uint32_t SingleLeadECG_ecg_plod_get_connected_state(); -int16_t SingleLeadECG_ecg_plod_get_ecg_val(); - -/******************************************************************************* - * BATTERY * - *******************************************************************************/ -void SingleLeadECG_battery_init(); -void SingleLeadECG_battery_deinit(); -int16_t SingleLeadECG_battery_get_adc_val(); -int16_t SingleLeadECG_battery_val(); - -void SingleLeadECG_battery_charge_detect_io_init(); -bool SingleLeadECG_battery_charge_get_state(); diff --git a/app/src/one_conduction/one_conduction_main.c b/app/src/one_conduction/one_conduction_main.c deleted file mode 100644 index 0a28a23..0000000 --- a/app/src/one_conduction/one_conduction_main.c +++ /dev/null @@ -1,449 +0,0 @@ -#include - -#include "app_event.h" -#include "ble_cmd_process_service.h" -#include "config.h" -#include "display_manager.h" -#include "heart_wave_sample_service.h" -#include "one_conduction_board.h" -#include "sample_data_manager.h" -#include "zble_module.h" -#include "zdatachannel_service.h" -#include "znordic.h" -#include "znordic_device_info_mgr.h" - -/******************************************************************************* - * GLOBAL * - *******************************************************************************/ - -ZDATACHANNEL_DEF(m_zhrs, 2 /*优先级*/, 1 /*client num*/); // 蓝牙服务 -APP_TIMER_DEF(m_state_machine_driver_tmr); // 状态机驱动定时器 -APP_TIMER_DEF(m_plod_state_event_detect_tmr); // 导联连接状态检测定时器 -APP_TIMER_DEF(m_charge_event_detect_tmr); // 充电事件检测 -extern uint32_t g_nrf_log_tx_pin; - -static int m_cur_fd; -static sample_data_filename_t sampledata_file_name; - -#define SCHED_MAX_EVENT_DATA_SIZE MAX(sizeof(app_event_t), APP_TIMER_SCHED_EVENT_DATA_SIZE) - -/******************************************************************************* - * 函数声明 * - *******************************************************************************/ - -// 业务事件处理函数 - -/******************************************************************************* - * 事件生成器 * - *******************************************************************************/ - -// 导联连接状态事件生成器 -static bool m_plod_state_connected_state = false; -static uint32_t m_connecte_state_last_trigger_timepoint = 0; - -static uint32_t plod_state_has_disconnected_ms() { return znordic_haspassed_ms(m_connecte_state_last_trigger_timepoint); } -static bool plod_state_is_connected() { return m_plod_state_connected_state; } - -static void m_plod_state_event_detect_tmr_cb(void* p_context) { // - static uint32_t connecte_state_trigger_cnt = 0; - static app_event_t appevent; - memset(&appevent, 0, sizeof(appevent)); - - if (SingleLeadECG_ecg_plod_get_connected_state()) { - connecte_state_trigger_cnt++; - m_connecte_state_last_trigger_timepoint = znordic_getpower_on_ms(); - } else { - connecte_state_trigger_cnt = 0; - } - - if (!m_plod_state_connected_state && connecte_state_trigger_cnt >= 10) { - // 连接事件 - appevent.eventType = kplod_connected_event; - m_plod_state_connected_state = true; - app_sched_event_put(&appevent, sizeof(appevent), app_event_process_cb); - } else if (m_plod_state_connected_state && connecte_state_trigger_cnt == 0) { - // 断开事件 - appevent.eventType = kplod_disconnected_event; - m_plod_state_connected_state = false; - app_sched_event_put(&appevent, sizeof(appevent), app_event_process_cb); - } - - // else if (connecte_state_trigger_cnt >= 10 && connecte_state_trigger_cnt % 10 == 0) { - // // 连接持续事件 - // appevent.eventType = kplod_connecting_event; - // appevent.val.plod_connected_accumulation_time = connecte_state_trigger_cnt / 10; - // app_sched_event_put(&appevent, sizeof(appevent), app_event_process_cb); - // } -} - -static void m_charge_event_detect_tmr_cb(void* p_context) { // - static app_event_t appevent; - memset(&appevent, 0, sizeof(appevent)); - static bool ischarging = false; - if (!SingleLeadECG_battery_charge_get_state()) { - if (!ischarging) { - appevent.eventType = kplod_start_charge_event; - ischarging = true; - app_sched_event_put(&appevent, sizeof(appevent), app_event_process_cb); - } else { - appevent.eventType = kplod_charging_event; - app_sched_event_put(&appevent, sizeof(appevent), app_event_process_cb); - } - } else { - if (ischarging) { - ischarging = false; - appevent.eventType = kplod_end_charge_event; - app_sched_event_put(&appevent, sizeof(appevent), app_event_process_cb); - } - } -} - -static void state_machine_driver_tmr_cb(void* p_context) { // - static app_event_t appevent; - appevent.eventType = kevent_tmr_scheduler_event; - app_sched_event_put(&appevent, sizeof(appevent), app_event_process_cb); -} - -/******************************************************************************* - * 事件处理 * - *******************************************************************************/ -static bool m_poweronflag; -static void power_on() { - if (m_poweronflag) { - return; - } - SingleLeadECG_adc_module_init(); - SingleLeadECG_beep_init(); - SingleLeadECG_led_init(); - SingleLeadECG_ecg_init(); - SingleLeadECG_battery_init(); - hwss_init(); - sample_data_mgr_init(); - dsp_mgr_init(); - ble_cmder_init(); - ble_cmder_start_adv(); - - // SingleLeadECG_beep_trigger_once(); - - m_poweronflag = true; - ZERROR_CHECK(app_timer_start(m_state_machine_driver_tmr, APP_TIMER_TICKS(100), NULL)); // 200HZ采样 -} -static void power_off() { - dsp_mgr_uninit(); - sample_data_mgr_uninit(); - hwss_uninit(); - - SingleLeadECG_battery_deinit(); - SingleLeadECG_ecg_deinit(); - SingleLeadECG_led_deinit(); - SingleLeadECG_beep_deinit(); - SingleLeadECG_adc_module_deinit(); - ble_cmder_stop_adv(); - ble_cmder_uninit(); - ZERROR_CHECK(app_timer_stop(m_state_machine_driver_tmr)); - m_poweronflag = false; -} -/******************************************************************************* - * 状态切换方法 * - *******************************************************************************/ -/** - * @brief 切换到充电中状态 - */ -static void state_machine__change_to_charging_state() { // - if (ds_now_state() == kdevice_state_home) { - // 已开机 DO Nothing - } else if (ds_now_state() == kdevice_state_standby) { - power_on(); - } else { - ZASSERT(false); - } - // 切换到充电显示页面 - dsp_mgr_change_to_chargingPage(); - ds_change_to_state(kdevice_state_charging); -} - -/** - * @brief 切换到待机状态 - */ - -static void state_machine__change_to_standby_state() { - ZLOGI_BLOCK("change to standby"); - power_off(); - ds_change_to_state(kdevice_state_standby); -} - -/** - * @brief 切换到开机中画面 - */ -static void state_machine__change_to_poweroning_state() { - power_on(); - dsp_mgr_change_to_welcome(); - ds_change_to_state(kdevice_state_poweron); -} - -/** - * @brief 切换到首页 - */ -static void state_machine__change_to_home_state() { - ds_change_to_state(kdevice_state_home); - dsp_mgr_change_to_main(); -} -void app_event_process_cb(void* p_event_data, uint16_t event_size) { - if (!p_event_data) return; - app_event_t* p_event = (app_event_t*)p_event_data; - - if (zdatachannel_is_connected()) { - SingleLeadECG_led_blue_set_state(true); - } else { - SingleLeadECG_led_blue_set_state(false); - } - - if (ds_now_state() == kdevice_state_standby) { - /******************************************************************************* - * 待机状态 * - *******************************************************************************/ - if (SingleLeadECG_battery_charge_get_state()) { - // 切换到充电状态 - state_machine__change_to_charging_state(); - } - - if (p_event->eventType == kplod_connected_event) { - // 切换到开机状态 - state_machine__change_to_poweroning_state(); - } - - } else if (ds_now_state() == kdevice_state_charging) { - /******************************************************************************* - * 充电状态 * - *******************************************************************************/ - if (!SingleLeadECG_battery_charge_get_state()) { - state_machine__change_to_standby_state(); - } - } else if (ds_now_state() == kdevice_state_poweron) { - /******************************************************************************* - * 开机中 * - *******************************************************************************/ - if (ds_cur_state_haspassed_ms() >= 1500) { - state_machine__change_to_home_state(); - } - } else if (ds_now_state() == kdevice_state_home) { - /******************************************************************************* - * 首页 * - *******************************************************************************/ - // // 如果用户长时间不操作,自动切换到待机状态 - if (!zdatachannel_is_connected() && // - !plod_state_is_connected() && // - plod_state_has_disconnected_ms() >= 3000 && // - ds_cur_state_haspassed_ms() >= AUTOMATIC_SLEEP_TIME) { -#ifdef ENABLE_SLEEP - state_machine__change_to_standby_state(); -#endif - } - // 如果用户继续保持静止,切换到采集页面 - else if (plod_state_is_connected() && ds_cur_state_haspassed_ms() > 1500) { - // dsp_mgr_change_to_preparePage - ds_change_to_state(kdevice_state_keep_still); - dsp_mgr_change_to_preparePage(); - } - // ZLOGI("bt:%d plod:%d has_disc:%d state:%d", zdatachannel_is_connected(), plod_state_is_connected(), plod_state_has_disconnected_ms(), ds_cur_state_haspassed_ms()); - } else if (ds_now_state() == kdevice_state_keep_still) { - /******************************************************************************* - * 保持静止页面 * - *******************************************************************************/ - if (!plod_state_is_connected()) { - // 如果用户未保持静止,切换到首页 - state_machine__change_to_home_state(); - } else { - /******************************************************************************* - * 页面加载中 * - *******************************************************************************/ - if (ds_cur_state_haspassed_ms() >= (2000 * 5)) { - /** - * @brief 保持静止2500ms后,切换到采集页面 - * - * 1. 启动采样定时器 - * 2. 切换状态 - * 3. 切换页面 - */ - ds_change_to_state(kdevice_state_sampling); - dsp_mgr_change_to_sampling(0, 0); - hwss_start_capture(); - static ztm_t tm; - memset(&sampledata_file_name, 0, sizeof(sampledata_file_name)); - znordic_rtc_gettime(&tm); - sample_capture_state_reset(); - - sampledata_file_name.year = tm.tm_year + 1900 - 2000; - sampledata_file_name.month = tm.tm_mon + 1; - sampledata_file_name.day = tm.tm_mday; - sampledata_file_name.hour = tm.tm_hour; - sampledata_file_name.min = tm.tm_min; - sampledata_file_name.sec = tm.tm_sec; - m_cur_fd = sample_data_mgr_open(&sampledata_file_name, kwrflag_write_only); - - } else if (ds_cur_state_haspassed_ms() >= (2000 * 4)) { - if (dsp_mgr_preparePage_get_progress() != 4) { - dsp_mgr_preparePage_set_progress(4); - } - } else if (ds_cur_state_haspassed_ms() >= (2000 * 3)) { - if (dsp_mgr_preparePage_get_progress() != 3) { - dsp_mgr_preparePage_set_progress(3); - } - } else if (ds_cur_state_haspassed_ms() >= (2000 * 2)) { - if (dsp_mgr_preparePage_get_progress() != 2) { - dsp_mgr_preparePage_set_progress(2); - } - } else if (ds_cur_state_haspassed_ms() >= (2000 * 1)) { - if (dsp_mgr_preparePage_get_progress() != 1) { - dsp_mgr_preparePage_set_progress(1); - } - } - } - } else if (ds_now_state() == kdevice_state_sampling) { - /******************************************************************************* - * 采样页面逻辑 * - *******************************************************************************/ - - /** - * @brief - * 数据事件 - * ---> 存储 - * 不足30秒 - * ---> 切换到采样出错状态 - * 超过30秒且采集完成 或 采满存储空间 - * ---> 切换到存储中 - */ - - bool always_capture = false; - if (p_event->eventType == kevent_capture_256data_event) { - if (hwss_has_captured_time_ms() <= (MAX_STORAGE_TIMEOUT_S * 1000)) { - // ZLOGI("storage data 256 [%d]ms", hwss_has_captured_time_ms()); - sample_data_mgr_write(m_cur_fd, p_event->val.capture_data_cache, 256); - } else { - // 采满存储 - /******************************************************************************* - * 存满切换到采集完成页面 * - *******************************************************************************/ - if (!always_capture) { - sample_data_mgr_close(m_cur_fd); - ds_change_to_state(kdevice_state_sampling_complete); - hwss_stop_capture(); - } - } - } else if (p_event->eventType == kevent_capture_1data_event) { - // 单帧实时上报 - ble_cmder_try_report_one_sample_data(p_event->val.frame_data.frameIndex, p_event->val.frame_data.data); - } else if (p_event->eventType == kplod_disconnected_event || !m_plod_state_connected_state) { - /******************************************************************************* - * 导联断开 * - *******************************************************************************/ - - if (hwss_has_captured_time_ms() < (SAMPLE_MIN_TIME_S * 1000)) { - // 采集不足30秒 - ble_cmder_try_report_sensor_drop_event(0x01, 0); - /******************************************************************************* - * 切换到采集出错页面 * - *******************************************************************************/ - if (!always_capture) { - sample_data_mgr_close(m_cur_fd); - sample_data_mgr_delete_file(&sampledata_file_name); - dsp_mgr_change_to_samplingError(); - ds_change_to_state(kdevice_state_sampling_error); - hwss_stop_capture(); - } - - } else { - // 采集超过30秒 - /******************************************************************************* - * 切换到采集完成页面 * - *******************************************************************************/ - if (!always_capture) { - SingleLeadECG_beep_trigger_once(); - sample_data_mgr_close(m_cur_fd); - dsp_mgr_change_to_sampleSuc(); - ds_change_to_state(kdevice_state_sampling_complete); - hwss_stop_capture(); - } - } - } else { - if (hwss_has_captured_time_ms() >= (SAMPLE_MIN_TIME_S * 1000)) { - if (!sample_capture_state_get()->is_over30s) { - SingleLeadECG_beep_trigger_once(); - sample_capture_state_set_is_over30s(true); - } - } - } - } else if (ds_now_state() == kdevice_state_sampling_complete) { - if (ds_cur_state_haspassed_ms() >= 3000) { - ZLOGI("ds_cur_state_haspassed_ms() %d> 3000", ds_cur_state_haspassed_ms()); - state_machine__change_to_home_state(); - ble_cmder_report_sample_finish_event(); - } - } else if (ds_now_state() == kdevice_state_sampling_error) { - if ((ds_cur_state_haspassed_ms() >= 3000) || (ds_cur_state_haspassed_ms() >= 1000 && m_plod_state_connected_state)) { - ZLOGI("ds_cur_state_haspassed_ms() %d> 3000", ds_cur_state_haspassed_ms()); - state_machine__change_to_home_state(); - ble_cmder_report_sample_finish_event(); - } - } -} - -/** - * @brief 蓝牙消息解析 - */ -void zdatachannel_data_handler(zdatachannel_evt_t* p_evt) { - /** - * @brief - */ - if (p_evt->type == ZDATACHANNEL_EVT_RX_DATA) { - ble_cmder_process_rx((uint8_t*)p_evt->params.rx_data.p_data, p_evt->params.rx_data.length); - } -} - -/******************************************************************************* - * MAIN_CODE * - *******************************************************************************/ -void on_service_init(void) { - ZLOGI("init zdatachannel service"); - zdatachannel_init_t zdatachannle_init; - memset(&zdatachannle_init, 0, sizeof(zdatachannle_init)); - zdatachannle_init.data_handler = zdatachannel_data_handler; - ZERROR_CHECK(zdatachannel_init(&m_zhrs, &zdatachannle_init)); -} -void one_conduction_main() { - APP_SCHED_INIT(SCHED_MAX_EVENT_DATA_SIZE, 20); - g_nrf_log_tx_pin = 41; - - znordic_init(); - NRF_LOG_INFO("compile time :%s", __TIME__); - NRF_LOG_INFO("Version :%d", VERSION); - NRF_LOG_INFO("Manufacturer :%s", MANUFACTURER_NAME); - - ztm_t tm; - znordic_rtc_gettime(&tm); - NRF_LOG_INFO("RTC time :%d-%d-%d %d:%d:%d", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec); - static char ble_name[20]; - sn_t sn; - device_info_read_sn(&sn); - memcpy(ble_name, sn.sn, sizeof(sn.sn)); - - static zble_module_cfg_t cfg = // - { - .deviceName = ble_name, - .on_service_init = on_service_init, - }; - zble_module_init(&cfg); - hwss_init(); - - SingleLeadECG_ecg_io_init(); - SingleLeadECG_battery_charge_detect_io_init(); - ZERROR_CHECK(app_timer_create(&m_state_machine_driver_tmr, APP_TIMER_MODE_REPEATED, state_machine_driver_tmr_cb)); - ZERROR_CHECK(app_timer_create(&m_plod_state_event_detect_tmr, APP_TIMER_MODE_REPEATED, m_plod_state_event_detect_tmr_cb)); - ZERROR_CHECK(app_timer_create(&m_charge_event_detect_tmr, APP_TIMER_MODE_REPEATED, m_charge_event_detect_tmr_cb)); - - ZERROR_CHECK(app_timer_start(m_plod_state_event_detect_tmr, APP_TIMER_TICKS(30), NULL)); - ZERROR_CHECK(app_timer_start(m_charge_event_detect_tmr, APP_TIMER_TICKS(100), NULL)); - - state_machine__change_to_poweroning_state(); - znordic_loop(); -} diff --git a/app/src/one_conduction/one_conduction_main.h b/app/src/one_conduction/one_conduction_main.h deleted file mode 100644 index e245aa9..0000000 --- a/app/src/one_conduction/one_conduction_main.h +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once - - -void one_conduction_main(); diff --git a/app/src/one_conduction/sample_data_manager.c b/app/src/one_conduction/sample_data_manager.c deleted file mode 100644 index fdc822b..0000000 --- a/app/src/one_conduction/sample_data_manager.c +++ /dev/null @@ -1,83 +0,0 @@ -#include "sample_data_manager.h" - -#include - -#include "zeeprom_fs.h" -#include "znordic.h" - -static sample_data_fileinfo_t fileinfocache[FILE_MAX_COUNT]; -static uint8_t fileinfocache_count = 0; - -void sample_data_mgr_init() { zeeprom_fs_init(); } -void sample_data_mgr_uninit() { zeeprom_fs_uinit(); } - -sample_data_fileinfo_list_t* sample_data_mgr_get_fileinfo_list() { // - static sample_data_fileinfo_list_t fileinfo_list; - memset(&fileinfo_list, 0, sizeof(fileinfo_list)); - - // 读取所有记录信息 - zeeprom_header_t* header = zeeprom_fs_get_header(); - - for (uint16_t i = 0; i < ZARRAY_SIZE(header->sectorinfos); i++) { - zeeprom_sector_info_t* sectorinfo = &header->sectorinfos[i]; - if (sectorinfo->usage == 1 && sectorinfo->sector_index_in_file == 0) { - // 读取文件信息 - sample_data_fileinfo_t* fileinfo = &fileinfocache[i]; - fileinfo->fileuuid = sectorinfo->fileuuid; - memcpy(fileinfo->filename, sectorinfo->filename, sizeof(fileinfo->filename)); - fileinfo->size = zeeprom_fs_get_filesize_by_fileuuid(fileinfo->fileuuid); - - fileinfo_list.fileinfo[fileinfo_list.count] = fileinfo; - fileinfo_list.count++; - } - } - // 根据文件uuid排序,uuid最大的排在最前面 - for (uint16_t i = 0; i < fileinfo_list.count; i++) { - for (uint16_t j = i + 1; j < fileinfo_list.count; j++) { - if (fileinfo_list.fileinfo[i]->fileuuid < fileinfo_list.fileinfo[j]->fileuuid) { - sample_data_fileinfo_t* tmp = fileinfo_list.fileinfo[i]; - fileinfo_list.fileinfo[i] = fileinfo_list.fileinfo[j]; - fileinfo_list.fileinfo[j] = tmp; - } - } - } - return &fileinfo_list; -} - -bool sample_data_mgr_storage_is_full() { return zeeprom_fs_get_file_num() >= FILE_MAX_COUNT; } -int32_t sample_data_mgr_get_file_num() { return zeeprom_fs_get_file_num(); } - -#if 1 -static const char* filename2str(uint8_t* filename) { - static char filename_str[32]; - sprintf(filename_str, "%02x%02x%02x%02x%02x%02x%02x%02x", filename[0], filename[1], filename[2], filename[3], filename[4], filename[5], filename[6], filename[7]); - return filename_str; -} -#endif - -void sample_data_mgr_dump_fileinfo_list() { - zeeprom_fs_dump_sector_state(); - sample_data_fileinfo_list_t* fileinfo_list = sample_data_mgr_get_fileinfo_list(); - ZLOGI_BLOCK("fileinfo_list->count=%d\n", fileinfo_list->count); - for (uint16_t i = 0; i < fileinfo_list->count; i++) { - sample_data_fileinfo_t* fileinfo = fileinfo_list->fileinfo[i]; - ZLOGI_BLOCK("[%d]: filename=%s, fileuuid=%d, size=%d", i, filename2str(fileinfo->filename), fileinfo->fileuuid, fileinfo->size); - } -} - -int32_t sample_data_mgr_open(sample_data_filename_t* filename, wrflag_t flag) { - /** - * @brief 查看文件数量 - */ - if (flag == kwrflag_write_only) { - if (zeeprom_fs_get_file_num() >= FILE_MAX_COUNT) { - zeeprom_fs_delete_the_oldest_file(); - } - } - return zeeprom_fs_open((uint8_t*)filename, flag); -} -int32_t sample_data_mgr_close(int32_t fd) { return zeeprom_fs_close(fd); } -int32_t sample_data_mgr_write(int32_t fd, const uint8_t* data, int32_t size) { return zeeprom_fs_write(fd, data, size); } -int32_t sample_data_mgr_read(int32_t fd, uint8_t* data, int32_t size) { return zeeprom_fs_read(fd, data, size); } -int32_t sample_data_mgr_get_file_size_by_fd(int32_t fd) { return zeeprom_fs_get_filesize_by_fd(fd); } -int32_t sample_data_mgr_delete_file(sample_data_filename_t* filename) { return zeeprom_fs_delete_by_name((uint8_t*)filename); } diff --git a/app/src/one_conduction/sample_data_manager.h b/app/src/one_conduction/sample_data_manager.h deleted file mode 100644 index 07cd4af..0000000 --- a/app/src/one_conduction/sample_data_manager.h +++ /dev/null @@ -1,47 +0,0 @@ -#pragma once -#include -#include - -#include "config.h" -#include "zeeprom_fs.h" - -void sample_data_mgr_init(); - -#define FILE_MAX_COUNT MAX_FILE_NUM - -typedef struct { - uint8_t year; - uint8_t month; - uint8_t day; - uint8_t hour; - uint8_t min; - uint8_t sec; - uint8_t placeholder[2]; -} sample_data_filename_t; - -typedef struct { - uint8_t filename[8]; - int32_t fileuuid; - int32_t size; -} sample_data_fileinfo_t; - -typedef struct { - sample_data_fileinfo_t* fileinfo[FILE_MAX_COUNT]; - int count; -} sample_data_fileinfo_list_t; - -void sample_data_mgr_init(); -void sample_data_mgr_uninit(); - -sample_data_fileinfo_list_t* sample_data_mgr_get_fileinfo_list(); -bool sample_data_mgr_storage_is_full(); -int32_t sample_data_mgr_get_file_num(); - -int32_t sample_data_mgr_open(sample_data_filename_t* filename, wrflag_t flag); -int32_t sample_data_mgr_close(int32_t fd); - -int32_t sample_data_mgr_write(int32_t fd, const uint8_t* data, int32_t size); -int32_t sample_data_mgr_read(int32_t fd, uint8_t* data, int32_t size); -int32_t sample_data_mgr_get_file_size_by_fd(int32_t fd); - -int32_t sample_data_mgr_delete_file(sample_data_filename_t* filename); diff --git a/app/src/one_conduction/zeeprom_fs.c b/app/src/one_conduction/zeeprom_fs.c deleted file mode 100644 index 20b5fee..0000000 --- a/app/src/one_conduction/zeeprom_fs.c +++ /dev/null @@ -1,543 +0,0 @@ -#include "zeeprom_fs.h" - -#include "one_conduction_board.h" - -static zeeprom_header_t m_eeprom_header; -static bool m_is_init = false; - -static filehandler_t m_filehandler[2]; -static int m_fd_off; - -/******************************************************************************* - * 函数声明 * - *******************************************************************************/ - -static filehandler_t* filehandler_find(int fd); -static filehandler_t* filehandler_alloc(); -static void filehandler_rlease(int fd); - -static int32_t sector_mgr_find_earliest_file_created_index(); -static int32_t sector_mgr_free_sector(int32_t fileuuid); -static zeeprom_sector_info_t* sector_mgr_find_idle_sector(); -static bool sector_mgr_sector_is_open(int32_t fileuuid); -static zeeprom_sector_info_t* sector_mgr_force_find_idle_sector(); -static void sector_mgr_open_sector(int32_t fileuuid); -static void sector_mgr_close_sector(int32_t fileuuid); -// static zeeprom_sector_info_t* sector_mgr_find_fileheader(int32_t fileuuid); -static zeeprom_sector_info_t* sector_mgr_find_end_sector(int32_t fileuuid); -static zeeprom_sector_info_t* sector_mgr_find_sector(int32_t fileuuid, int32_t sector_index_in_file); -static int32_t sector_mgr_file_get_size(int32_t fileuuid); - -static zeeprom_sector_info_t* sector_mgr_find_fileheader_by_filename(uint8_t* fileid); -static int32_t sector_mgr_get_sector_offset(zeeprom_sector_info_t* sector); -static int32_t sector_mgr_get_sector_rom_add(zeeprom_sector_info_t* sector); - -static void zeeprom_read(int32_t add, uint8_t* data, uint16_t len); -static void zeeprom_write(int32_t add, const uint8_t* data, uint16_t len); -static int32_t compute_checksum(uint8_t* data, uint16_t len); - -/******************************************************************************* - * CODE * - *******************************************************************************/ - -static bool m_eeprom_header_inited = false; -int zeeprom_fs_init() { // - SingleLeadECG_eeprom_init(); - if (!m_eeprom_header_inited) { - zeeprom_read(0, (uint8_t*)&m_eeprom_header, sizeof(m_eeprom_header)); - int32_t checksum_val = compute_checksum((uint8_t*)&m_eeprom_header, sizeof(m_eeprom_header) - sizeof(m_eeprom_header.checksum)); - if (checksum_val != m_eeprom_header.checksum) { - memset(&m_eeprom_header, 0, sizeof(m_eeprom_header)); - } - } - m_is_init = true; - m_eeprom_header_inited = true; - return 0; -} -int zeeprom_fs_uinit() { // - // zeeprom_write(0, (uint8_t*)&m_eeprom_header, sizeof(m_eeprom_header)); - SingleLeadECG_eeprom_uninit(); - m_is_init = false; - return 0; -} - -zeeprom_header_t* zeeprom_fs_get_header() { return &m_eeprom_header; } - -int zeeprom_fs_open(uint8_t* filename, wrflag_t wrflag) { - ZASSERT(m_is_init); - /** - * @brief - * 1. 如果文件已经存在,则打开文件 - * 2. 如果文件不存在, 则创建文件 - * - * 创建文件: - * 1. 找到一个空闲扇区 - * 2. 初始化文件头 - */ - - filehandler_t* fileHander = filehandler_alloc(); - if (!fileHander) { - ZLOGI("fileHander_alloc fail"); - return -1; - } - - if (wrflag == kwrflag_write_only) { - /******************************************************************************* - * 写文件 * - *******************************************************************************/ - zeeprom_sector_info_t* sectorHeaderInfo = NULL; - zeeprom_fs_delete_by_name(filename); - - sectorHeaderInfo = sector_mgr_force_find_idle_sector(); - if (!sectorHeaderInfo) { - ZLOGE("sector_mgr_force_find_idle_sector fail"); - filehandler_rlease(fileHander->fd); - return -1; - } - - memset(sectorHeaderInfo, 0, sizeof(zeeprom_sector_info_t)); - sectorHeaderInfo->usage = 1; - sectorHeaderInfo->opened = 1; - memcpy(sectorHeaderInfo->filename, filename, 8); - sectorHeaderInfo->sector_index_in_file = 0; - sectorHeaderInfo->datalen = 0; - sectorHeaderInfo->fileuuid = m_eeprom_header.fileuuid++; - fileHander->fileuuid = sectorHeaderInfo->fileuuid; - fileHander->sector_header = sectorHeaderInfo; - fileHander->file_offset = 0; - fileHander->file_size = 0; - return fileHander->fd; - - } else { - /******************************************************************************* - * 读文件 * - *******************************************************************************/ - zeeprom_sector_info_t* sectorHeaderInfo = sector_mgr_find_fileheader_by_filename(filename); - if (sectorHeaderInfo) { - fileHander->fileuuid = sectorHeaderInfo->fileuuid; - fileHander->file_offset = 0; - fileHander->fd = fileHander->fd; - fileHander->sector_header = sectorHeaderInfo; - fileHander->file_size = sector_mgr_file_get_size(fileHander->fileuuid); - memcpy(fileHander->filename, filename, 8); - memcpy(fileHander->usrdata, sectorHeaderInfo->usrdata, sizeof(sectorHeaderInfo->usrdata)); - sector_mgr_open_sector(fileHander->fileuuid); - return fileHander->fd; - } else { - filehandler_rlease(fileHander->fd); - return -1; - } - } -} - -int zeeprom_fs_write(int fileid, const uint8_t* data, int32_t size) { - ZASSERT(m_is_init); - - filehandler_t* fileHander = NULL; - zeeprom_sector_info_t* header_sinfo = NULL; - zeeprom_sector_info_t* endsector = NULL; - int32_t wadd = 0; - - ZASSERT(size == 256); - - fileHander = filehandler_find(fileid); - if (!fileHander) { - ZLOGE("fileHander_find fail"); - return -1; - } - - header_sinfo = fileHander->sector_header; - if (!header_sinfo) { - ZLOGE("header_sinfo fail"); - return -1; - } - - endsector = sector_mgr_find_end_sector(fileHander->fileuuid); - if (!endsector) { - ZLOGE("sector_mgr_find_end_sector fail"); - return -1; - } - - if (endsector->datalen + size > EEPROM_SECTOR_SIZE) { - ZLOGE("endsector->datalen + size > EEPROM_SECTOR_SIZE"); - return -1; - } - - wadd = sector_mgr_get_sector_rom_add(endsector); - if (wadd < 0) { - ZLOGE("sector_mgr_get_sector_rom_add fail"); - return -1; - } - ZASSERT(wadd % 256 == 0); - ZASSERT(wadd >= EEPROM_SECTOR_SIZE); - zeeprom_write(wadd + endsector->datalen, data, size); - - endsector->datalen = endsector->datalen + size; - fileHander->file_offset += size; - fileHander->file_size += size; - - if (endsector->datalen == EEPROM_SECTOR_SIZE) { - zeeprom_sector_info_t* newsector = sector_mgr_force_find_idle_sector(); - if (!newsector) { - ZLOGE("sector_mgr_force_find_idle_sector fail"); - return -1; - } - - memset(newsector, 0, sizeof(zeeprom_sector_info_t)); - newsector->usage = 1; - newsector->opened = 1; - memcpy(newsector->filename, header_sinfo->filename, 8); - newsector->sector_index_in_file = endsector->sector_index_in_file + 1; - newsector->datalen = 0; - newsector->fileuuid = header_sinfo->fileuuid; - } - return size; -} - -int zeeprom_fs_close(int fileid) { - ZASSERT(m_is_init); - - filehandler_t* fileHander = filehandler_find(fileid); - if (!fileHander) { - ZLOGE("zeeprom_fs_close fileHander_find fail"); - return -1; - } - - // sector_mgr_close_sector(fileHander->fileuuid); - // int32_t checksum_val = compute_checksum((uint8_t*)&m_eeprom_header, sizeof(m_eeprom_header) - sizeof(m_eeprom_header.checksum)); - // m_eeprom_header.checksum = checksum_val; - // zeeprom_write(0, (uint8_t*)&m_eeprom_header, sizeof(m_eeprom_header)); - - filehandler_rlease(fileid); - return 0; -} - -int zeeprom_fs_get_filesize_by_fd(int fd) { - ZASSERT(m_is_init); - filehandler_t* fileHander = filehandler_find(fd); - if (!fileHander) return 0; - return fileHander->file_size; -} - -int zeeprom_fs_read(int fileid, uint8_t* data, int32_t size) { - ZASSERT(m_is_init); - - /** - * @brief - * 找到当前扇区 - */ - ZASSERT(size == 256); - filehandler_t* fileHander = filehandler_find(fileid); - if (!fileHander) return -1; - - zeeprom_sector_info_t* header_sinfo = fileHander->sector_header; - if (!header_sinfo) { - return -1; - } - - int32_t sector_idx = fileHander->file_offset / EEPROM_SECTOR_SIZE; - int32_t sector_off = fileHander->file_offset % EEPROM_SECTOR_SIZE; - - zeeprom_sector_info_t* sector = sector_mgr_find_sector(fileHander->fileuuid, sector_idx); - if (!sector) { - return -1; - } - - int32_t radd = sector_mgr_get_sector_rom_add(sector); - ZASSERT(radd % 256 == 0); - radd += sector_off; - - zeeprom_read(radd, data, size); - fileHander->file_offset += size; - return size; -} - -int zeeprom_fs_delete(int32_t fileuuid) { - ZASSERT(m_is_init); - - sector_mgr_free_sector(fileuuid); - return 0; -} -int zeeprom_fs_delete_by_name(uint8_t* filename) { - ZASSERT(m_is_init); - - zeeprom_sector_info_t* sectorHeaderInfo = sector_mgr_find_fileheader_by_filename(filename); - if (sectorHeaderInfo) { - sector_mgr_free_sector(sectorHeaderInfo->fileuuid); - } - return 0; -} - -int zeeprom_fs_get_file_num() { - ZASSERT(m_is_init); - - int count = 0; - for (int i = 0; i < MAX_SECTOR_NUM; i++) { - zeeprom_sector_info_t* sinfo = &m_eeprom_header.sectorinfos[i]; - if (sinfo->usage == 1 && sinfo->sector_index_in_file == 0) { - count++; - } - } - return count; -} -int zeeprom_fs_delete_the_oldest_file() { - ZASSERT(m_is_init); - - int32_t earliest_file_created_index = sector_mgr_find_earliest_file_created_index(); - sector_mgr_free_sector(earliest_file_created_index); - return 0; -} - -int zeeprom_fs_get_filesize_by_fileuuid(int32_t fileuuid) { - ZASSERT(m_is_init); - return sector_mgr_file_get_size(fileuuid); -} - -static void zeeprom_read(int32_t add, uint8_t* data, uint16_t len) { // - int wrsize = EEPROM_SECTOR_MIN_WR_SIZE; - - int readTimes = len / wrsize; - int readRemain = len % wrsize; - - for (int i = 0; i < readTimes; i++) { - SingleLeadECG_eeprom_read(add + i * wrsize, data + i * wrsize, wrsize); - } - if (readRemain > 0) { - SingleLeadECG_eeprom_read(add + readTimes * wrsize, data + readTimes * wrsize, readRemain); - } -} -static void zeeprom_write(int32_t add, const uint8_t* data, uint16_t len) { - int wrsize = EEPROM_SECTOR_MIN_WR_SIZE; - - int writeTimes = len / wrsize; - int writeRemain = len % wrsize; - - for (int i = 0; i < writeTimes; i++) { - // int pageoff = add / wrsize + i; - int32_t writeadd = add + i * wrsize; - SingleLeadECG_eeprom_write(writeadd, data + i * wrsize, wrsize); - } - if (writeRemain > 0) { - int32_t writeadd = add + writeTimes * wrsize; - SingleLeadECG_eeprom_write(writeadd, data + writeTimes * wrsize, writeRemain); - } -} - -static int32_t compute_checksum(uint8_t* data, uint16_t len) { - int32_t sum = 0; - for (int i = 0; i < len; i++) { - sum += data[i]; - } - return sum; -} -/******************************************************************************* - * filehandler * - *******************************************************************************/ -static filehandler_t* filehandler_find(int fd) { - for (int i = 0; i < ZARRAY_SIZE(m_filehandler); i++) { - if (m_filehandler[i].fd == fd) { - return &m_filehandler[i]; - } - } - return NULL; -} -static filehandler_t* filehandler_alloc() { - for (int i = 0; i < ZARRAY_SIZE(m_filehandler); i++) { - if (m_filehandler[i].fd == 0) { - m_filehandler[i].fd = ++m_fd_off; - return &m_filehandler[i]; - } - } - return NULL; -} -static void filehandler_rlease(int fd) { - for (int i = 0; i < ZARRAY_SIZE(m_filehandler); i++) { - if (m_filehandler[i].fd == fd) { - m_filehandler[i].fd = 0; - return; - } - } -} -/******************************************************************************* - * sector_mgr * - *******************************************************************************/ - -// 查找最早创建的文件的file_created_index -static int32_t sector_mgr_find_earliest_file_created_index() { - int32_t earliest_file_created_index = INT32_MAX; - for (int i = 0; i < MAX_SECTOR_NUM; i++) { - zeeprom_sector_info_t* sinfo = &m_eeprom_header.sectorinfos[i]; - if (sinfo->usage == 1) { - if (sinfo->fileuuid < earliest_file_created_index) { - earliest_file_created_index = sinfo->fileuuid; - } - } - } - return earliest_file_created_index; -} -// 删除文件 -static int32_t sector_mgr_free_sector(int32_t fileuuid) { - for (int i = 0; i < MAX_SECTOR_NUM; i++) { - zeeprom_sector_info_t* sinfo = &m_eeprom_header.sectorinfos[i]; - if (sinfo->usage == 1 && sinfo->fileuuid == fileuuid) { - sinfo->usage = 0; - } - } - return 0; -} -// -static zeeprom_sector_info_t* sector_mgr_find_idle_sector() { - for (int i = 0; i < MAX_SECTOR_NUM; i++) { - zeeprom_sector_info_t* sinfo = &m_eeprom_header.sectorinfos[i]; - if (sinfo->usage == 0) { - return sinfo; - } - } - return NULL; -} -static bool sector_mgr_sector_is_open(int32_t fileuuid) { - for (int i = 0; i < MAX_SECTOR_NUM; i++) { - zeeprom_sector_info_t* sinfo = &m_eeprom_header.sectorinfos[i]; - if (sinfo->usage == 1 && sinfo->fileuuid == fileuuid) { - return sinfo->opened; - } - } - return false; -} - -static zeeprom_sector_info_t* sector_mgr_force_find_idle_sector() { - /** - * @brief 查找空闲扇区 - */ - zeeprom_sector_info_t* ret_sinfo = sector_mgr_find_idle_sector(); - if (ret_sinfo) return ret_sinfo; - /** - * @brief 查找最早创建的文件 - */ - int32_t earliest_file_created_index = sector_mgr_find_earliest_file_created_index(); - if (sector_mgr_sector_is_open(earliest_file_created_index)) { - return NULL; - } - - /** - * @brief 删除最早创建的文件 - */ - sector_mgr_free_sector(earliest_file_created_index); - - /** - * @brief 重新查找空闲扇区 - */ - ret_sinfo = sector_mgr_find_idle_sector(); - if (ret_sinfo) return ret_sinfo; - - return NULL; -} - -static void sector_mgr_open_sector(int32_t fileuuid) { - for (int i = 0; i < MAX_SECTOR_NUM; i++) { - zeeprom_sector_info_t* sinfo = &m_eeprom_header.sectorinfos[i]; - if (sinfo->usage == 1 && sinfo->fileuuid == fileuuid) { - sinfo->opened = true; - } - } -} - -static void sector_mgr_close_sector(int32_t fileuuid) { - for (int i = 0; i < MAX_SECTOR_NUM; i++) { - zeeprom_sector_info_t* sinfo = &m_eeprom_header.sectorinfos[i]; - if (sinfo->usage == 1 && sinfo->fileuuid == fileuuid) { - sinfo->opened = false; - } - } -} - -// static zeeprom_sector_info_t* sector_mgr_find_fileheader(int32_t fileuuid) { -// for (int i = 0; i < MAX_SECTOR_NUM; i++) { -// zeeprom_sector_info_t* sinfo = &m_eeprom_header.sectorinfos[i]; -// if (sinfo->usage == 1 && sinfo->sector_index_in_file == 0 && sinfo->fileuuid == fileuuid) { -// return sinfo; -// } -// } -// return NULL; -// } - -static zeeprom_sector_info_t* sector_mgr_find_sector(int32_t fileuuid, int32_t sector_index_in_file) { - for (int i = 0; i < MAX_SECTOR_NUM; i++) { - zeeprom_sector_info_t* sinfo = &m_eeprom_header.sectorinfos[i]; - if (sinfo->usage == 1 && sinfo->sector_index_in_file == sector_index_in_file && sinfo->fileuuid == fileuuid) { - return sinfo; - } - } - return NULL; -} - -static zeeprom_sector_info_t* sector_mgr_find_end_sector(int32_t fileuuid) { - int32_t maxsectorindex = 0; - for (int i = 0; i < MAX_SECTOR_NUM; i++) { - zeeprom_sector_info_t* sinfo = &m_eeprom_header.sectorinfos[i]; - if (sinfo->usage == 1 && sinfo->fileuuid == fileuuid) { - if (sinfo->sector_index_in_file >= maxsectorindex) { - maxsectorindex = sinfo->sector_index_in_file; - } - } - } - return sector_mgr_find_sector(fileuuid, maxsectorindex); -} - -static zeeprom_sector_info_t* sector_mgr_find_fileheader_by_filename(uint8_t* fileid) { - for (int i = 0; i < MAX_SECTOR_NUM; i++) { - zeeprom_sector_info_t* sinfo = &m_eeprom_header.sectorinfos[i]; - if (sinfo->usage == 1 && sinfo->sector_index_in_file == 0 && memcmp(sinfo->filename, fileid, 8) == 0) { - return sinfo; - } - } - return NULL; -} - -static int32_t sector_mgr_get_sector_offset(zeeprom_sector_info_t* sector) { - for (int i = 0; i < MAX_SECTOR_NUM; i++) { - zeeprom_sector_info_t* sinfo = &m_eeprom_header.sectorinfos[i]; - if (sinfo == sector) { - return i; - } - } - return -1; -} - -static int32_t sector_mgr_get_sector_rom_add(zeeprom_sector_info_t* sector) { - int32_t offset = sector_mgr_get_sector_offset(sector); - if (offset < 0) return -1; - return (offset + 1) * EEPROM_SECTOR_SIZE; -} - -static int32_t sector_mgr_file_get_size(int32_t fileuuid) { - int32_t filesize = 0; - for (int i = 0; i < MAX_SECTOR_NUM; i++) { - zeeprom_sector_info_t* sinfo = &m_eeprom_header.sectorinfos[i]; - - if (sinfo->usage == 1 && sinfo->fileuuid == fileuuid) { - filesize += sinfo->datalen; - } - } - return filesize; -} - -static const char* filename2str(uint8_t* filename) { - static char filename_str[32]; - sprintf(filename_str, "%02x%02x%02x%02x%02x%02x%02x%02x", filename[0], filename[1], filename[2], filename[3], filename[4], filename[5], filename[6], filename[7]); - return filename_str; -} - -int zeeprom_fs_dump_sector_state() { - ZLOGI_BLOCK("zeeprom_fs_dump_sector_state\n"); - for (int i = 0; i < MAX_SECTOR_NUM; i++) { - zeeprom_sector_info_t* sinfo = &m_eeprom_header.sectorinfos[i]; - if (sinfo->usage == 1) { - ZLOGI_BLOCK("[%d]: usage=%d opened=%d", i, sinfo->usage, sinfo->opened); - ZLOGI_BLOCK(" fname=%s, index_in_file=%d, datalen=%d, fileuuid=%d", filename2str(sinfo->filename), sinfo->sector_index_in_file, sinfo->datalen, sinfo->fileuuid); - } else { - ZLOGI_BLOCK("[%d]: usage=%d", i, sinfo->usage); - } - } - return 0; -} diff --git a/app/src/one_conduction/zeeprom_fs.h b/app/src/one_conduction/zeeprom_fs.h deleted file mode 100644 index 7ede932..0000000 --- a/app/src/one_conduction/zeeprom_fs.h +++ /dev/null @@ -1,66 +0,0 @@ -#pragma once -#include - -#define EEPROM_SIZE (256 * 1024) -#define EEPROM_SECTOR_MIN_WR_SIZE (256) -#define EEPROM_SECTOR_SIZE (8 * 1024) -#define MAX_SECTOR_NUM (EEPROM_SIZE / EEPROM_SECTOR_SIZE - 1) -#define EEPROM_FILE_SIZE (EEPROM_SECTOR_SIZE * MAX_SECTOR_NUM) - -// -#pragma pack(1) -typedef struct { - uint8_t usage; - uint8_t opened; - uint8_t filename[8]; // 注意文件名为固定八个字节的二进制数据,不是字符串 - int32_t sector_index_in_file; // 当前扇区中文件数据的起始地址 - int32_t datalen; // 当前扇区中文件数据的长度 - int32_t fileuuid; // 递增,根据这个index判断文件创建的先后顺序,同时也相当于文件唯一标识 - uint8_t usrdata[20]; -} zeeprom_sector_info_t; - -typedef struct { - uint8_t filename[8]; - uint8_t usrdata[20]; - - zeeprom_sector_info_t* sector_header; - int32_t file_offset; - int32_t file_size; - - int fd; - int32_t fileuuid; -} filehandler_t; - -typedef struct { - zeeprom_sector_info_t sectorinfos[MAX_SECTOR_NUM]; - int32_t fileuuid; - int32_t checksum; -} zeeprom_header_t; -#pragma pack() - -int zeeprom_fs_init(); -int zeeprom_fs_uinit(); - -typedef enum { - kwrflag_read_only, - kwrflag_write_only, -} wrflag_t; - -zeeprom_header_t* zeeprom_fs_get_header(); - -int zeeprom_fs_open(uint8_t* filename, wrflag_t flag); - -int zeeprom_fs_close(int fd); - -int zeeprom_fs_write(int fd, const uint8_t* data, int32_t size); -int zeeprom_fs_read(int fd, uint8_t* data, int32_t size); - -int zeeprom_fs_get_filesize_by_fd(int fd); - -int zeeprom_fs_get_file_num(); -int zeeprom_fs_delete_the_oldest_file(); -int zeeprom_fs_delete(int32_t fileuuid); -int zeeprom_fs_delete_by_name(uint8_t* filename); - -int zeeprom_fs_dump_sector_state(); -int zeeprom_fs_get_filesize_by_fileuuid(int32_t fileuuid); diff --git a/app/src/one_conduction_board.c b/app/src/one_conduction_board.c new file mode 100644 index 0000000..8eab403 --- /dev/null +++ b/app/src/one_conduction_board.c @@ -0,0 +1,401 @@ +#include "one_conduction_board.h" + +#include "znordic.h" +// +#include "app_timer.h" +#include "diskio_blkdev.h" +#include "ff.h" +#include "nrf_block_dev_sdc.h" +#include "nrf_delay.h" +#include "nrf_drv_pwm.h" +#include "nrf_drv_saadc.h" +#include "nrf_drv_twi.h" +#include "nrf_drv_wdt.h" +#include "nrf_gpio.h" +// +#include "basic/ssd1306/driver_ssd1306.h" +#include "basic/ssd1306/driver_ssd1306_basic.h" + +#define SCREEN_SPI_INSTANCE 0 +#define SCREEN_RESET_PIN 20 +#define SCREEN_POWER_PIN 30 +#define SCREEN_A0PIN 31 +#define SCREEN_CS_PIN 29 +#define SCREEN_CLK_PIN 4 +#define SCREEN_MOSI_PIN 11 + +#define LED_GREEN_PIN 9 +#define LED_BLUE_PIN 10 +// #define LED_GREEN_PIN 27 +// #define LED_BLUE_PIN 28 + +#define ECG_NLOD_PIN 3 +#define ECG_PLOD_PIN 28 +#define ECG_ADC_PIN NRF_SAADC_INPUT_AIN0 +#define ECG_ADC_CHANNEL 0 // 不重复即可 + +#define BATTERY_ADC_PIN NRF_SAADC_INPUT_AIN3 +#define BATTERY_ADC_CHANNEL 1 // 不重复即可 + +#define EEPROM_I2C_SCL_M 15 // I2C SCL引脚 +#define EEPROM_I2C_SDA_M 17 // I2C SDA引脚 +#define EEPROM_I2C_INSTANCE 1 // I2C使用的硬件控制器ID + +#define BEEP_PWM_INSTANCE 0 +#define BEEP_PIN 1 + +#define BATTERY_CHARGE_DETECT_PIN 18 + +/******************************************************************************* + * TOOLS * + *******************************************************************************/ + +/******************************************************************************* + * ADC * + *******************************************************************************/ + +uint8_t m_now_adc_channel = 0xff; + +void SingleLeadECG_adc_set_ch(uint8_t ch); +void SingleLeadECG_adc_module_init() { + nrf_drv_saadc_config_t adccfg = NRFX_SAADC_DEFAULT_CONFIG; + adccfg.resolution = NRF_SAADC_RESOLUTION_12BIT; // 4096 等于满采样率 + ZERROR_CHECK(nrf_drv_saadc_init(&adccfg, NULL)); + // SingleLeadECG_adc_set_ch(BATTERY_ADC_CHANNEL); +} +void SingleLeadECG_adc_set_ch(uint8_t ch) { + if (m_now_adc_channel != ch) { + if (m_now_adc_channel != 0xff) nrfx_saadc_channel_uninit(m_now_adc_channel); + + if (ch == ECG_ADC_CHANNEL) { + nrf_saadc_channel_config_t channel_config = NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(ECG_ADC_PIN); + channel_config.acq_time = NRF_SAADC_ACQTIME_40US; + ZERROR_CHECK(nrfx_saadc_channel_init(ECG_ADC_CHANNEL, &channel_config)); + } else if (ch == BATTERY_ADC_CHANNEL) { + nrf_saadc_channel_config_t channel_config = NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(BATTERY_ADC_PIN); + channel_config.acq_time = NRF_SAADC_ACQTIME_40US; + ZERROR_CHECK(nrfx_saadc_channel_init(BATTERY_ADC_CHANNEL, &channel_config)); + } + } + m_now_adc_channel = ch; +} + +int16_t SingleLeadECG_adc_get_val(uint8_t ch) { + SingleLeadECG_adc_set_ch(ch); + return znrf_adc_channel_read_val(ch); +} + +void SingleLeadECG_adc_module_deinit() { + SingleLeadECG_adc_set_ch(0xff); + nrf_drv_saadc_uninit(); +} + +/******************************************************************************* + * 蜂鸣器 * + *******************************************************************************/ +static nrf_drv_pwm_t m_beep_pwm0 = NRF_DRV_PWM_INSTANCE(BEEP_PWM_INSTANCE); +static nrf_pwm_values_individual_t m_beep_pwm0_seq_values = {0}; +static nrf_pwm_sequence_t const m_beep_pwm0_seq = { + .values.p_individual = &m_beep_pwm0_seq_values, + .length = NRF_PWM_VALUES_LENGTH(m_beep_pwm0_seq_values), + .repeats = 0, + .end_delay = 0, +}; +static nrf_drv_pwm_config_t const m_beep_pwm0_config0 = { + .output_pins = {BEEP_PIN}, + .irq_priority = APP_IRQ_PRIORITY_LOWEST, + .base_clock = NRF_PWM_CLK_125kHz, + .count_mode = NRF_PWM_MODE_UP, + .top_value = 46, // 125kHz / 46 = 2.717k + .load_mode = NRF_PWM_LOAD_INDIVIDUAL, + .step_mode = NRF_PWM_STEP_AUTO, +}; +APP_TIMER_DEF(m_beep_tmr); // 蜂鸣器自动关闭定时器 +bool m_beep_tmr_is_inited = false; +static void beep_tmr_handler(void *context) { SingleLeadECG_beep_set_state(false); } +void SingleLeadECG_beep_init() { + if (!m_beep_tmr_is_inited) { + m_beep_tmr_is_inited = true; + app_timer_create(&m_beep_tmr, APP_TIMER_MODE_SINGLE_SHOT, beep_tmr_handler); + } + + APP_ERROR_CHECK(nrfx_pwm_init(&m_beep_pwm0, &m_beep_pwm0_config0, NULL)); +} +void SingleLeadECG_beep_deinit() { + SingleLeadECG_beep_set_state(false); + nrfx_pwm_uninit(&m_beep_pwm0); +} + +void SingleLeadECG_beep_set_state(bool state) { + if (state) { + m_beep_pwm0_seq_values.channel_0 = 23; // 设置占空比,数值最大不超过 top_value + nrfx_pwm_simple_playback(&m_beep_pwm0, &m_beep_pwm0_seq, 1, NRF_DRV_PWM_FLAG_LOOP); + } else { + nrfx_pwm_stop(&m_beep_pwm0, true); + } +} +void SingleLeadECG_beep_trigger_once() { + SingleLeadECG_beep_set_state(true); + app_timer_start(m_beep_tmr, APP_TIMER_TICKS(200), NULL); +} + +/******************************************************************************* + * SCREEN * + *******************************************************************************/ + +static const nrf_drv_spi_t m_screen_spi = NRF_DRV_SPI_INSTANCE(SCREEN_SPI_INSTANCE); /**< SPI instance. */ + +void SingleLeadECG_screen_init() { + znrf_gpio_cfg_output(SCREEN_RESET_PIN, NRF_GPIO_PIN_NOPULL); + znrf_gpio_cfg_output(SCREEN_POWER_PIN, NRF_GPIO_PIN_NOPULL); + znrf_gpio_cfg_output(SCREEN_A0PIN, NRF_GPIO_PIN_NOPULL); + + nrf_gpio_pin_set(SCREEN_POWER_PIN); + // 参考 + // OLED驱动程序 : https://iflytop1.feishu.cn/wiki/OQ4Iwv0DpiQDJvkjftjcQHJBnCg + // nRF5_SDK-使用手册: https://iflytop1.feishu.cn/wiki/ThaAwZEGVi2bspkfGU9cbl9Enqd + nrf_drv_spi_config_t spi_config = NRF_DRV_SPI_DEFAULT_CONFIG; + spi_config.ss_pin = SCREEN_CS_PIN; // NRF_DRV_SPI_PIN_NOT_USED + spi_config.miso_pin = NRF_DRV_SPI_PIN_NOT_USED; + spi_config.mosi_pin = SCREEN_MOSI_PIN; + spi_config.sck_pin = SCREEN_CLK_PIN; + spi_config.frequency = NRF_DRV_SPI_FREQ_8M; + spi_config.mode = NRF_DRV_SPI_MODE_3; + ZERROR_CHECK(nrf_drv_spi_init(&m_screen_spi, &spi_config, NULL, NULL)); + ssd1306_basic_init(SSD1306_INTERFACE_SPI, SSD1306_ADDR_SA0_0); +} + +void SingleLeadECG_screen_deinit() { + ssd1306_basic_deinit(); + nrf_drv_spi_uninit(&m_screen_spi); +} + +uint8_t SingleLeadECG_spi_init(void) { return 0; } +uint8_t SingleLeadECG_spi_deinit(void) { return 0; } +uint8_t SingleLeadECG_spi_cmd_data_gpio_init(void) { return 0; } +uint8_t SingleLeadECG_spi_cmd_data_gpio_deinit(void) { return 0; } +void SingleLeadECG_debug_print(const char *const fmt, ...) {} +uint8_t SingleLeadECG_reset_gpio_init(void) { return 0; } +uint8_t SingleLeadECG_reset_gpio_deinit(void) { return 0; } +uint8_t SingleLeadECG_spi_write_cmd(uint8_t *buf, uint16_t len) { // + ZERROR_CHECK(nrf_drv_spi_transfer(&m_screen_spi, buf, len, NULL, 0)); + return 0; +} +void SingleLeadECG_delay_ms(uint32_t ms) { nrf_delay_ms(ms); } +uint8_t SingleLeadECG_spi_cmd_data_gpio_write(uint8_t value) { + if (value) { + nrf_gpio_pin_set(SCREEN_A0PIN); + } else { + nrf_gpio_pin_clear(SCREEN_A0PIN); + } + return 0; +} +uint8_t SingleLeadECG_reset_gpio_write(uint8_t value) { + if (value) { + nrf_gpio_pin_set(SCREEN_RESET_PIN); + } else { + nrf_gpio_pin_clear(SCREEN_RESET_PIN); + } + return 0; +} + +/******************************************************************************* + * LED * + *******************************************************************************/ +static bool io_init = false; + +void SingleLeadECG_led_init() { + if (io_init) { + return; + } + znrf_gpio_cfg_output(LED_GREEN_PIN, NRF_GPIO_PIN_NOPULL); + znrf_gpio_cfg_output(LED_BLUE_PIN, NRF_GPIO_PIN_NOPULL); + + // nrf_gpio_pin_write(LED_GREEN_PIN, 1); + // nrf_gpio_pin_write(LED_GREEN_PIN, 1); + + SingleLeadECG_led_green_set_state(false); + SingleLeadECG_led_blue_set_state(false); + io_init = true; +} +void SingleLeadECG_led_deinit() { + SingleLeadECG_led_green_set_state(false); + SingleLeadECG_led_blue_set_state(false); +} + +void SingleLeadECG_led_green_set_state(bool state) { + if (state) { + nrf_gpio_pin_set(LED_GREEN_PIN); + } else { + nrf_gpio_pin_clear(LED_GREEN_PIN); + } +} +void SingleLeadECG_led_blue_set_state(bool state) { + if (state) { + nrf_gpio_pin_set(LED_BLUE_PIN); + } else { + nrf_gpio_pin_clear(LED_BLUE_PIN); + } +} + +/******************************************************************************* + * ecg * + *******************************************************************************/ + +/** + * @brief + * PLOD: 表明当前点击连接状态,如果为0,表示连接,如果为1,表示断开 + */ + +void SingleLeadECG_ecg_init() {} + +void SingleLeadECG_ecg_deinit() {} + +void SingleLeadECG_ecg_io_init() { + nrf_gpio_cfg_sense_input(ECG_NLOD_PIN, NRF_GPIO_PIN_PULLUP, NRF_GPIO_PIN_NOSENSE); + nrf_gpio_cfg_sense_input(ECG_PLOD_PIN, NRF_GPIO_PIN_PULLUP, NRF_GPIO_PIN_NOSENSE); +} + +uint32_t SingleLeadECG_ecg_nlod_get_connected_state() { return nrf_gpio_pin_read(ECG_NLOD_PIN); } +uint32_t SingleLeadECG_ecg_plod_get_connected_state() { return !nrf_gpio_pin_read(ECG_PLOD_PIN); } +int16_t SingleLeadECG_ecg_plod_get_ecg_val() { return SingleLeadECG_adc_get_val(ECG_ADC_CHANNEL); } + +/******************************************************************************* + * BATTERY * + *******************************************************************************/ +void SingleLeadECG_battery_init() {} +void SingleLeadECG_battery_deinit() {} + +int16_t SingleLeadECG_battery_get_adc_val() { return SingleLeadECG_adc_get_val(BATTERY_ADC_CHANNEL); } +int16_t SingleLeadECG_battery_val() { // + + static const float maxv = 4.0; + static const float minv = 3.5; + + float voltage = SingleLeadECG_battery_get_adc_val() / 4096.0 * 3.3 / 2.0 * 3; + if (voltage > maxv) voltage = maxv; + if (voltage < minv) voltage = minv; + + float percent = (voltage - minv) / (maxv - minv) * 100 + (float)0.1 /*加0.1是为了避免999.999时显示电量为90*/; + int16_t percent_int = (int16_t)percent; + if (percent_int < 10 && percent_int != 0) { + percent_int = 3; + } else { + percent_int = percent_int / 10 * 10; + } + // ZLOGI("battery %d ", SingleLeadECG_battery_get_adc_val()); + return percent_int; +} +void SingleLeadECG_battery_charge_detect_io_init() { // + nrf_gpio_cfg_sense_input(BATTERY_CHARGE_DETECT_PIN, NRF_GPIO_PIN_PULLUP, NRF_GPIO_PIN_NOSENSE); +} +bool SingleLeadECG_battery_charge_get_state() { return nrf_gpio_pin_read(BATTERY_CHARGE_DETECT_PIN) == 0; } + +/******************************************************************************* + * eeprom * + *******************************************************************************/ +static const nrf_drv_twi_t m_eeprom_twi_master = NRF_DRV_TWI_INSTANCE(EEPROM_I2C_INSTANCE); + +void SingleLeadECG_eeprom_init() { + nrf_drv_twi_config_t config = NRF_DRV_TWI_DEFAULT_CONFIG; + + config.scl = EEPROM_I2C_SCL_M; + config.sda = EEPROM_I2C_SDA_M; + config.frequency = NRF_DRV_TWI_FREQ_400K; + ZERROR_CHECK(nrf_drv_twi_init(&m_eeprom_twi_master, &config, NULL, NULL)); + nrf_drv_twi_enable(&m_eeprom_twi_master); +} + +void SingleLeadECG_eeprom_uninit() { + nrf_drv_twi_disable(&m_eeprom_twi_master); + nrf_drv_twi_uninit(&m_eeprom_twi_master); +} + +static uint8_t eeprom_cache[EEPROM_PAGE + 2]; + +static void assign_i2c_add(uint32_t add, bool wr, uint8_t *i2cadd, uint8_t *memadd0, uint8_t *memadd1) { + // DEVICE SELECT + // bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0 + // 1 0 1 0 E2 A17 A16 RW(W=0) + // + // PS: E2 参考原理图中的电平为0,所以bit3为0 + // + // MEM0 + // bit15 bit14 bit13 bit12 bit11 bit10 bit9 bit8 + // MEM1 + // bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0 + // + + *i2cadd = 0xA0; + uint8_t a16a17 = (add >> 16) & 0x03; + *i2cadd |= a16a17 << 1; + *i2cadd = *i2cadd >> 1; + + *memadd0 = add >> 8; + *memadd1 = add & 0xFF; +} + +void SingleLeadECG_eeprom_write(uint32_t addr, const uint8_t *data, uint16_t len) { // + // uint32_t addr = page * EEPROM_PAGE; + // len = len > EEPROM_PAGE ? EEPROM_PAGE : len; + + // ZASSERT(len == EEPROM_PAGE); + ZASSERT((addr % EEPROM_PAGE) == 0); + // ZLOGI_BLOCK("eeprom_write %d %d", addr, len); + uint8_t deviceSelect = 0; + + assign_i2c_add(addr, true, &deviceSelect, &eeprom_cache[0], &eeprom_cache[1]); + memcpy(&eeprom_cache[2], data, len); + + ret_code_t ecode = nrf_drv_twi_tx(&m_eeprom_twi_master, deviceSelect, eeprom_cache, len + 2, false); + if (ecode != NRF_SUCCESS) { + ZLOGE("nrf_drv_twi_tx error %x", ecode); + NRF_LOG_INTERNAL_FLUSH(); + } +} +/** + * @brief 用来检测读取整个eeprom是否正常 + */ +void SingleLeadECG_eeprom_wr_check() { + /** + * @brief + * 256kbyte + * 写入数据,回读检查数据是否正确 + */ + + static uint8_t wdata_cache[256]; + static uint8_t rdata_cache[256]; +#define CHECKCODE (i % 21) + + for (uint32_t i = 0; i < 1024; i++) { + uint32_t addr = i * EEPROM_PAGE; + for (uint32_t j = 0; j < EEPROM_PAGE; j++) { + wdata_cache[j] = CHECKCODE; + } + ZLOGI_BLOCK("write %d", i); + SingleLeadECG_eeprom_write(addr, wdata_cache, EEPROM_PAGE); + nrf_delay_ms(15); + } + + for (uint32_t i = 0; i < 1024; i++) { + uint32_t addr = i * EEPROM_PAGE; + ZLOGI_BLOCK("check %d", i); + SingleLeadECG_eeprom_read(addr, rdata_cache, EEPROM_PAGE); + for (uint32_t j = 0; j < EEPROM_PAGE; j++) { + if (rdata_cache[j] != (CHECKCODE)) { + ZLOGE("SingleLeadECG_eeprom_wr_check error %d %d %d", i, j, rdata_cache[j]); + } + } + } +} + +void SingleLeadECG_eeprom_read(uint32_t add, uint8_t *data, uint16_t len) { + uint8_t deviceSelect = 0; + uint8_t wadd[2] = {0}; + + assign_i2c_add(add, false, &deviceSelect, &wadd[0], &wadd[1]); + nrf_drv_twi_tx(&m_eeprom_twi_master, deviceSelect, wadd, 2, false); + + deviceSelect |= 0x01; // read + nrf_drv_twi_rx(&m_eeprom_twi_master, deviceSelect, data, len); +} diff --git a/app/src/one_conduction_board.h b/app/src/one_conduction_board.h new file mode 100644 index 0000000..f2c33f6 --- /dev/null +++ b/app/src/one_conduction_board.h @@ -0,0 +1,77 @@ +#pragma once +#define VERSION 1 +#define MANUFACTURER_NAME "iflytop" + +/******************************************************************************* + * INCLUDE * + *******************************************************************************/ +#include + +#include "basic/ssd1306/driver_ssd1306_interface.h" +#include "znordic.h" + +/******************************************************************************* + * basic * + *******************************************************************************/ +void SingleLeadECG_adc_module_init(); +void SingleLeadECG_adc_module_deinit(); + +/******************************************************************************* + * 蜂鸣器 * + *******************************************************************************/ +void SingleLeadECG_beep_init(); +void SingleLeadECG_beep_deinit(); +void SingleLeadECG_beep_set_state(bool state); +void SingleLeadECG_beep_trigger_once(); + +/******************************************************************************* + * EEPROM * + *******************************************************************************/ +/** + * + * PageSize 256byte + * + */ +#define EEPROM_PAGE 256 +void SingleLeadECG_eeprom_init(); +void SingleLeadECG_eeprom_uninit(); +void SingleLeadECG_eeprom_write(uint32_t page, const uint8_t* data, uint16_t len); +void SingleLeadECG_eeprom_read(uint32_t add, uint8_t* data, uint16_t len); + +/******************************************************************************* + * SCREEN * + *******************************************************************************/ + +void SingleLeadECG_screen_init(); +void SingleLeadECG_screen_deinit(); + +/******************************************************************************* + * LED * + *******************************************************************************/ +void SingleLeadECG_led_init(); +void SingleLeadECG_led_deinit(); +void SingleLeadECG_led_green_set_state(bool state); +void SingleLeadECG_led_blue_set_state(bool state); + +/******************************************************************************* + * ECG * + *******************************************************************************/ + +void SingleLeadECG_ecg_init(); +void SingleLeadECG_ecg_deinit(); +void SingleLeadECG_ecg_io_init(); + +uint32_t SingleLeadECG_ecg_nlod_get_connected_state(); +uint32_t SingleLeadECG_ecg_plod_get_connected_state(); +int16_t SingleLeadECG_ecg_plod_get_ecg_val(); + +/******************************************************************************* + * BATTERY * + *******************************************************************************/ +void SingleLeadECG_battery_init(); +void SingleLeadECG_battery_deinit(); +int16_t SingleLeadECG_battery_get_adc_val(); +int16_t SingleLeadECG_battery_val(); + +void SingleLeadECG_battery_charge_detect_io_init(); +bool SingleLeadECG_battery_charge_get_state(); diff --git a/app/src/one_conduction_main.c b/app/src/one_conduction_main.c new file mode 100644 index 0000000..13c86db --- /dev/null +++ b/app/src/one_conduction_main.c @@ -0,0 +1,458 @@ +#include + +#include "app_event.h" +#include "ble_cmd_process_service.h" +#include "config.h" +#include "display_manager.h" +#include "heart_wave_sample_service.h" +#include "one_conduction_board.h" +#include "sample_data_manager.h" +#include "zble_module.h" +#include "zdatachannel_service.h" +#include "znordic.h" +#include "znordic_device_info_mgr.h" +#include "app_event_distribute.h" + +/******************************************************************************* + * GLOBAL * + *******************************************************************************/ + +ZDATACHANNEL_DEF(m_zhrs, 2 /*优先级*/, 1 /*client num*/); // 蓝牙服务 +APP_TIMER_DEF(m_state_machine_driver_tmr); // 状态机驱动定时器 +APP_TIMER_DEF(m_plod_state_event_detect_tmr); // 导联连接状态检测定时器 +APP_TIMER_DEF(m_charge_event_detect_tmr); // 充电事件检测 +extern uint32_t g_nrf_log_tx_pin; + +static int m_cur_fd; +static sample_data_filename_t sampledata_file_name; + +#define SCHED_MAX_EVENT_DATA_SIZE MAX(sizeof(app_event_t), APP_TIMER_SCHED_EVENT_DATA_SIZE) + +/******************************************************************************* + * 函数声明 * + *******************************************************************************/ + +// 业务事件处理函数 + +/******************************************************************************* + * 事件生成器 * + *******************************************************************************/ + +// 导联连接状态事件生成器 +static bool m_plod_state_connected_state = false; +static uint32_t m_connecte_state_last_trigger_timepoint = 0; + +static uint32_t plod_state_has_disconnected_ms() { return znordic_haspassed_ms(m_connecte_state_last_trigger_timepoint); } +static bool plod_state_is_connected() { return m_plod_state_connected_state; } + +static void m_plod_state_event_detect_tmr_cb(void* p_context) { // + static uint32_t connecte_state_trigger_cnt = 0; + static app_event_t appevent; + memset(&appevent, 0, sizeof(appevent)); + + if (SingleLeadECG_ecg_plod_get_connected_state()) { + connecte_state_trigger_cnt++; + m_connecte_state_last_trigger_timepoint = znordic_getpower_on_ms(); + } else { + connecte_state_trigger_cnt = 0; + } + + if (!m_plod_state_connected_state && connecte_state_trigger_cnt >= 10) { + // 连接事件 + appevent.eventType = kplod_connected_event; + m_plod_state_connected_state = true; + AppEvent_pushEvent(&appevent); + } else if (m_plod_state_connected_state && connecte_state_trigger_cnt == 0) { + // 断开事件 + appevent.eventType = kplod_disconnected_event; + m_plod_state_connected_state = false; + AppEvent_pushEvent(&appevent); + } + + // else if (connecte_state_trigger_cnt >= 10 && connecte_state_trigger_cnt % 10 == 0) { + // // 连接持续事件 + // appevent.eventType = kplod_connecting_event; + // appevent.val.plod_connected_accumulation_time = connecte_state_trigger_cnt / 10; + // AppEvent_pushEvent(&appevent); + // } +} + +static void m_charge_event_detect_tmr_cb(void* p_context) { // + static app_event_t appevent; + memset(&appevent, 0, sizeof(appevent)); + static bool ischarging = false; + if (!SingleLeadECG_battery_charge_get_state()) { + if (!ischarging) { + appevent.eventType = kplod_start_charge_event; + ischarging = true; + AppEvent_pushEvent(&appevent); + } else { + appevent.eventType = kplod_charging_event; + AppEvent_pushEvent(&appevent); + } + } else { + if (ischarging) { + ischarging = false; + appevent.eventType = kplod_end_charge_event; + AppEvent_pushEvent(&appevent); + } + } +} + +static void state_machine_driver_tmr_cb(void* p_context) { // + static app_event_t appevent; + appevent.eventType = kevent_tmr_scheduler_event; + AppEvent_pushEvent(&appevent); +} + +/******************************************************************************* + * 事件处理 * + *******************************************************************************/ +static bool m_poweronflag; +static void power_on() { + if (m_poweronflag) { + return; + } + SingleLeadECG_adc_module_init(); + SingleLeadECG_beep_init(); + SingleLeadECG_led_init(); + SingleLeadECG_ecg_init(); + SingleLeadECG_battery_init(); + hwss_init(); + sample_data_mgr_init(); + dsp_mgr_init(); + ble_cmder_init(); + ble_cmder_start_adv(); + + // SingleLeadECG_beep_trigger_once(); + + m_poweronflag = true; + ZERROR_CHECK(app_timer_start(m_state_machine_driver_tmr, APP_TIMER_TICKS(100), NULL)); // 200HZ采样 +} +static void power_off() { + dsp_mgr_uninit(); + sample_data_mgr_uninit(); + hwss_uninit(); + + SingleLeadECG_battery_deinit(); + SingleLeadECG_ecg_deinit(); + SingleLeadECG_led_deinit(); + SingleLeadECG_beep_deinit(); + SingleLeadECG_adc_module_deinit(); + ble_cmder_stop_adv(); + ble_cmder_uninit(); + ZERROR_CHECK(app_timer_stop(m_state_machine_driver_tmr)); + m_poweronflag = false; +} +/******************************************************************************* + * 状态切换方法 * + *******************************************************************************/ +/** + * @brief 切换到充电中状态 + */ +static void state_machine__change_to_charging_state() { // + if (ds_now_state() == kdevice_state_home) { + // 已开机 DO Nothing + } else if (ds_now_state() == kdevice_state_standby) { + power_on(); + } else { + ZASSERT(false); + } + // 切换到充电显示页面 + dsp_mgr_change_to_chargingPage(); + ds_change_to_state(kdevice_state_charging); +} + +/** + * @brief 切换到待机状态 + */ + +static void state_machine__change_to_standby_state() { + ZLOGI_BLOCK("change to standby"); + power_off(); + ds_change_to_state(kdevice_state_standby); +} + +/** + * @brief 切换到开机中画面 + */ +static void state_machine__change_to_poweroning_state() { + power_on(); + dsp_mgr_change_to_welcome(); + ds_change_to_state(kdevice_state_poweron); +} + +/** + * @brief 切换到首页 + */ +static void state_machine__change_to_home_state() { + ds_change_to_state(kdevice_state_home); + dsp_mgr_change_to_main(); +} +static void app_event_listener(void* p_event_data, uint16_t event_size) { + if (!p_event_data) return; + app_event_t* p_event = (app_event_t*)p_event_data; + + if (zdatachannel_is_connected()) { + SingleLeadECG_led_blue_set_state(true); + } else { + SingleLeadECG_led_blue_set_state(false); + } + + if (ds_now_state() == kdevice_state_standby) { + /******************************************************************************* + * 待机状态 * + *******************************************************************************/ + if (SingleLeadECG_battery_charge_get_state()) { + // 切换到充电状态 + state_machine__change_to_charging_state(); + } + + if (p_event->eventType == kplod_connected_event) { + // 切换到开机状态 + state_machine__change_to_poweroning_state(); + } + + } else if (ds_now_state() == kdevice_state_charging) { + /******************************************************************************* + * 充电状态 * + *******************************************************************************/ + if (!SingleLeadECG_battery_charge_get_state()) { + state_machine__change_to_standby_state(); + } + } else if (ds_now_state() == kdevice_state_poweron) { + /******************************************************************************* + * 开机中 * + *******************************************************************************/ + if (ds_cur_state_haspassed_ms() >= 1500) { + state_machine__change_to_home_state(); + } + } else if (ds_now_state() == kdevice_state_home) { + /******************************************************************************* + * 首页 * + *******************************************************************************/ + // // 如果用户长时间不操作,自动切换到待机状态 + if (!zdatachannel_is_connected() && // + !plod_state_is_connected() && // + plod_state_has_disconnected_ms() >= 3000 && // + ds_cur_state_haspassed_ms() >= AUTOMATIC_SLEEP_TIME) { +#ifdef ENABLE_SLEEP + state_machine__change_to_standby_state(); +#endif + } + // 如果用户继续保持静止,切换到采集页面 + else if (plod_state_is_connected() && ds_cur_state_haspassed_ms() > 1500) { + // dsp_mgr_change_to_preparePage + ds_change_to_state(kdevice_state_keep_still); + dsp_mgr_change_to_preparePage(); + } + // ZLOGI("bt:%d plod:%d has_disc:%d state:%d", zdatachannel_is_connected(), plod_state_is_connected(), plod_state_has_disconnected_ms(), ds_cur_state_haspassed_ms()); + } else if (ds_now_state() == kdevice_state_keep_still) { + /******************************************************************************* + * 保持静止页面 * + *******************************************************************************/ + if (!plod_state_is_connected()) { + // 如果用户未保持静止,切换到首页 + state_machine__change_to_home_state(); + } else { + /******************************************************************************* + * 页面加载中 * + *******************************************************************************/ + if (ds_cur_state_haspassed_ms() >= (2000 * 5)) { + /** + * @brief 保持静止2500ms后,切换到采集页面 + * + * 1. 启动采样定时器 + * 2. 切换状态 + * 3. 切换页面 + */ + ds_change_to_state(kdevice_state_sampling); + dsp_mgr_change_to_sampling(0, 0); + hwss_start_capture(); + static ztm_t tm; + memset(&sampledata_file_name, 0, sizeof(sampledata_file_name)); + znordic_rtc_gettime(&tm); + sample_capture_state_reset(); + + sampledata_file_name.year = tm.tm_year + 1900 - 2000; + sampledata_file_name.month = tm.tm_mon + 1; + sampledata_file_name.day = tm.tm_mday; + sampledata_file_name.hour = tm.tm_hour; + sampledata_file_name.min = tm.tm_min; + sampledata_file_name.sec = tm.tm_sec; + m_cur_fd = sample_data_mgr_open(&sampledata_file_name, kwrflag_write_only); + + } else if (ds_cur_state_haspassed_ms() >= (2000 * 4)) { + if (dsp_mgr_preparePage_get_progress() != 4) { + dsp_mgr_preparePage_set_progress(4); + } + } else if (ds_cur_state_haspassed_ms() >= (2000 * 3)) { + if (dsp_mgr_preparePage_get_progress() != 3) { + dsp_mgr_preparePage_set_progress(3); + } + } else if (ds_cur_state_haspassed_ms() >= (2000 * 2)) { + if (dsp_mgr_preparePage_get_progress() != 2) { + dsp_mgr_preparePage_set_progress(2); + } + } else if (ds_cur_state_haspassed_ms() >= (2000 * 1)) { + if (dsp_mgr_preparePage_get_progress() != 1) { + dsp_mgr_preparePage_set_progress(1); + } + } + } + } else if (ds_now_state() == kdevice_state_sampling) { + /******************************************************************************* + * 采样页面逻辑 * + *******************************************************************************/ + + /** + * @brief + * 数据事件 + * ---> 存储 + * 不足30秒 + * ---> 切换到采样出错状态 + * 超过30秒且采集完成 或 采满存储空间 + * ---> 切换到存储中 + */ + + bool always_capture = false; + if (p_event->eventType == kevent_capture_256data_event) { + if (hwss_has_captured_time_ms() <= (MAX_STORAGE_TIMEOUT_S * 1000)) { + // ZLOGI("storage data 256 [%d]ms", hwss_has_captured_time_ms()); + sample_data_mgr_write(m_cur_fd, p_event->val.capture_data_cache, 256); + } else { + // 采满存储 + /******************************************************************************* + * 存满切换到采集完成页面 * + *******************************************************************************/ + if (!always_capture) { + sample_data_mgr_close(m_cur_fd); + ds_change_to_state(kdevice_state_sampling_complete); + hwss_stop_capture(); + } + } + } else if (p_event->eventType == kevent_capture_little_data_block_event) { + // 单帧实时上报 + ZASSERT(LITTLE_DATA_BLOCK_FRAME_NUM == 4); + ble_cmder_try_report_one_sample_data(p_event->val.little_data_block.frameIndex, // + p_event->val.little_data_block.data[0].data, // + p_event->val.little_data_block.data[1].data, // + p_event->val.little_data_block.data[2].data, // + p_event->val.little_data_block.data[3].data // + ); + } else if (p_event->eventType == kplod_disconnected_event || !m_plod_state_connected_state) { + /******************************************************************************* + * 导联断开 * + *******************************************************************************/ + + if (hwss_has_captured_time_ms() < (SAMPLE_MIN_TIME_S * 1000)) { + // 采集不足30秒 + ble_cmder_try_report_sensor_drop_event(0x01, 0); + /******************************************************************************* + * 切换到采集出错页面 * + *******************************************************************************/ + if (!always_capture) { + sample_data_mgr_close(m_cur_fd); + sample_data_mgr_delete_file(&sampledata_file_name); + dsp_mgr_change_to_samplingError(); + ds_change_to_state(kdevice_state_sampling_error); + hwss_stop_capture(); + } + + } else { + // 采集超过30秒 + /******************************************************************************* + * 切换到采集完成页面 * + *******************************************************************************/ + if (!always_capture) { + SingleLeadECG_beep_trigger_once(); + sample_data_mgr_close(m_cur_fd); + dsp_mgr_change_to_sampleSuc(); + ds_change_to_state(kdevice_state_sampling_complete); + hwss_stop_capture(); + } + } + } else { + if (hwss_has_captured_time_ms() >= (SAMPLE_MIN_TIME_S * 1000)) { + if (!sample_capture_state_get()->is_over30s) { + SingleLeadECG_beep_trigger_once(); + sample_capture_state_set_is_over30s(true); + } + } + } + } else if (ds_now_state() == kdevice_state_sampling_complete) { + if (ds_cur_state_haspassed_ms() >= 3000) { + ZLOGI("ds_cur_state_haspassed_ms() %d> 3000", ds_cur_state_haspassed_ms()); + state_machine__change_to_home_state(); + ble_cmder_report_sample_finish_event(); + } + } else if (ds_now_state() == kdevice_state_sampling_error) { + if ((ds_cur_state_haspassed_ms() >= 3000) || (ds_cur_state_haspassed_ms() >= 1000 && m_plod_state_connected_state)) { + ZLOGI("ds_cur_state_haspassed_ms() %d> 3000", ds_cur_state_haspassed_ms()); + state_machine__change_to_home_state(); + ble_cmder_report_sample_finish_event(); + } + } +} + +/** + * @brief 蓝牙消息解析 + */ +void zdatachannel_data_handler(zdatachannel_evt_t* p_evt) { + /** + * @brief + */ + if (p_evt->type == ZDATACHANNEL_EVT_RX_DATA) { + ble_cmder_process_rx((uint8_t*)p_evt->params.rx_data.p_data, p_evt->params.rx_data.length); + } +} + +/******************************************************************************* + * MAIN_CODE * + *******************************************************************************/ +void on_service_init(void) { + ZLOGI("init zdatachannel service"); + zdatachannel_init_t zdatachannle_init; + memset(&zdatachannle_init, 0, sizeof(zdatachannle_init)); + zdatachannle_init.data_handler = zdatachannel_data_handler; + ZERROR_CHECK(zdatachannel_init(&m_zhrs, &zdatachannle_init)); +} +void one_conduction_main() { + APP_SCHED_INIT(SCHED_MAX_EVENT_DATA_SIZE, 20); + g_nrf_log_tx_pin = 41; + + znordic_init(); + NRF_LOG_INFO("compile time :%s", __TIME__); + NRF_LOG_INFO("Version :%d", VERSION); + NRF_LOG_INFO("Manufacturer :%s", MANUFACTURER_NAME); + + ztm_t tm; + znordic_rtc_gettime(&tm); + NRF_LOG_INFO("RTC time :%d-%d-%d %d:%d:%d", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec); + static char ble_name[20]; + sn_t sn; + device_info_read_sn(&sn); + memcpy(ble_name, sn.sn, sizeof(sn.sn)); + + static zble_module_cfg_t cfg = // + { + .deviceName = ble_name, + .on_service_init = on_service_init, + }; + zble_module_init(&cfg); + hwss_init(); + + SingleLeadECG_ecg_io_init(); + SingleLeadECG_battery_charge_detect_io_init(); + AppEvent_regListener(app_event_listener); + + ZERROR_CHECK(app_timer_create(&m_state_machine_driver_tmr, APP_TIMER_MODE_REPEATED, state_machine_driver_tmr_cb)); + ZERROR_CHECK(app_timer_create(&m_plod_state_event_detect_tmr, APP_TIMER_MODE_REPEATED, m_plod_state_event_detect_tmr_cb)); + ZERROR_CHECK(app_timer_create(&m_charge_event_detect_tmr, APP_TIMER_MODE_REPEATED, m_charge_event_detect_tmr_cb)); + + ZERROR_CHECK(app_timer_start(m_plod_state_event_detect_tmr, APP_TIMER_TICKS(30), NULL)); + ZERROR_CHECK(app_timer_start(m_charge_event_detect_tmr, APP_TIMER_TICKS(100), NULL)); + + state_machine__change_to_poweroning_state(); + znordic_loop(); +} diff --git a/app/src/one_conduction_main.h b/app/src/one_conduction_main.h new file mode 100644 index 0000000..e245aa9 --- /dev/null +++ b/app/src/one_conduction_main.h @@ -0,0 +1,4 @@ +#pragma once + + +void one_conduction_main(); diff --git a/app/src/sample_data_manager.c b/app/src/sample_data_manager.c new file mode 100644 index 0000000..fdc822b --- /dev/null +++ b/app/src/sample_data_manager.c @@ -0,0 +1,83 @@ +#include "sample_data_manager.h" + +#include + +#include "zeeprom_fs.h" +#include "znordic.h" + +static sample_data_fileinfo_t fileinfocache[FILE_MAX_COUNT]; +static uint8_t fileinfocache_count = 0; + +void sample_data_mgr_init() { zeeprom_fs_init(); } +void sample_data_mgr_uninit() { zeeprom_fs_uinit(); } + +sample_data_fileinfo_list_t* sample_data_mgr_get_fileinfo_list() { // + static sample_data_fileinfo_list_t fileinfo_list; + memset(&fileinfo_list, 0, sizeof(fileinfo_list)); + + // 读取所有记录信息 + zeeprom_header_t* header = zeeprom_fs_get_header(); + + for (uint16_t i = 0; i < ZARRAY_SIZE(header->sectorinfos); i++) { + zeeprom_sector_info_t* sectorinfo = &header->sectorinfos[i]; + if (sectorinfo->usage == 1 && sectorinfo->sector_index_in_file == 0) { + // 读取文件信息 + sample_data_fileinfo_t* fileinfo = &fileinfocache[i]; + fileinfo->fileuuid = sectorinfo->fileuuid; + memcpy(fileinfo->filename, sectorinfo->filename, sizeof(fileinfo->filename)); + fileinfo->size = zeeprom_fs_get_filesize_by_fileuuid(fileinfo->fileuuid); + + fileinfo_list.fileinfo[fileinfo_list.count] = fileinfo; + fileinfo_list.count++; + } + } + // 根据文件uuid排序,uuid最大的排在最前面 + for (uint16_t i = 0; i < fileinfo_list.count; i++) { + for (uint16_t j = i + 1; j < fileinfo_list.count; j++) { + if (fileinfo_list.fileinfo[i]->fileuuid < fileinfo_list.fileinfo[j]->fileuuid) { + sample_data_fileinfo_t* tmp = fileinfo_list.fileinfo[i]; + fileinfo_list.fileinfo[i] = fileinfo_list.fileinfo[j]; + fileinfo_list.fileinfo[j] = tmp; + } + } + } + return &fileinfo_list; +} + +bool sample_data_mgr_storage_is_full() { return zeeprom_fs_get_file_num() >= FILE_MAX_COUNT; } +int32_t sample_data_mgr_get_file_num() { return zeeprom_fs_get_file_num(); } + +#if 1 +static const char* filename2str(uint8_t* filename) { + static char filename_str[32]; + sprintf(filename_str, "%02x%02x%02x%02x%02x%02x%02x%02x", filename[0], filename[1], filename[2], filename[3], filename[4], filename[5], filename[6], filename[7]); + return filename_str; +} +#endif + +void sample_data_mgr_dump_fileinfo_list() { + zeeprom_fs_dump_sector_state(); + sample_data_fileinfo_list_t* fileinfo_list = sample_data_mgr_get_fileinfo_list(); + ZLOGI_BLOCK("fileinfo_list->count=%d\n", fileinfo_list->count); + for (uint16_t i = 0; i < fileinfo_list->count; i++) { + sample_data_fileinfo_t* fileinfo = fileinfo_list->fileinfo[i]; + ZLOGI_BLOCK("[%d]: filename=%s, fileuuid=%d, size=%d", i, filename2str(fileinfo->filename), fileinfo->fileuuid, fileinfo->size); + } +} + +int32_t sample_data_mgr_open(sample_data_filename_t* filename, wrflag_t flag) { + /** + * @brief 查看文件数量 + */ + if (flag == kwrflag_write_only) { + if (zeeprom_fs_get_file_num() >= FILE_MAX_COUNT) { + zeeprom_fs_delete_the_oldest_file(); + } + } + return zeeprom_fs_open((uint8_t*)filename, flag); +} +int32_t sample_data_mgr_close(int32_t fd) { return zeeprom_fs_close(fd); } +int32_t sample_data_mgr_write(int32_t fd, const uint8_t* data, int32_t size) { return zeeprom_fs_write(fd, data, size); } +int32_t sample_data_mgr_read(int32_t fd, uint8_t* data, int32_t size) { return zeeprom_fs_read(fd, data, size); } +int32_t sample_data_mgr_get_file_size_by_fd(int32_t fd) { return zeeprom_fs_get_filesize_by_fd(fd); } +int32_t sample_data_mgr_delete_file(sample_data_filename_t* filename) { return zeeprom_fs_delete_by_name((uint8_t*)filename); } diff --git a/app/src/sample_data_manager.h b/app/src/sample_data_manager.h new file mode 100644 index 0000000..07cd4af --- /dev/null +++ b/app/src/sample_data_manager.h @@ -0,0 +1,47 @@ +#pragma once +#include +#include + +#include "config.h" +#include "zeeprom_fs.h" + +void sample_data_mgr_init(); + +#define FILE_MAX_COUNT MAX_FILE_NUM + +typedef struct { + uint8_t year; + uint8_t month; + uint8_t day; + uint8_t hour; + uint8_t min; + uint8_t sec; + uint8_t placeholder[2]; +} sample_data_filename_t; + +typedef struct { + uint8_t filename[8]; + int32_t fileuuid; + int32_t size; +} sample_data_fileinfo_t; + +typedef struct { + sample_data_fileinfo_t* fileinfo[FILE_MAX_COUNT]; + int count; +} sample_data_fileinfo_list_t; + +void sample_data_mgr_init(); +void sample_data_mgr_uninit(); + +sample_data_fileinfo_list_t* sample_data_mgr_get_fileinfo_list(); +bool sample_data_mgr_storage_is_full(); +int32_t sample_data_mgr_get_file_num(); + +int32_t sample_data_mgr_open(sample_data_filename_t* filename, wrflag_t flag); +int32_t sample_data_mgr_close(int32_t fd); + +int32_t sample_data_mgr_write(int32_t fd, const uint8_t* data, int32_t size); +int32_t sample_data_mgr_read(int32_t fd, uint8_t* data, int32_t size); +int32_t sample_data_mgr_get_file_size_by_fd(int32_t fd); + +int32_t sample_data_mgr_delete_file(sample_data_filename_t* filename); diff --git a/app/src/zeeprom_fs.c b/app/src/zeeprom_fs.c new file mode 100644 index 0000000..20b5fee --- /dev/null +++ b/app/src/zeeprom_fs.c @@ -0,0 +1,543 @@ +#include "zeeprom_fs.h" + +#include "one_conduction_board.h" + +static zeeprom_header_t m_eeprom_header; +static bool m_is_init = false; + +static filehandler_t m_filehandler[2]; +static int m_fd_off; + +/******************************************************************************* + * 函数声明 * + *******************************************************************************/ + +static filehandler_t* filehandler_find(int fd); +static filehandler_t* filehandler_alloc(); +static void filehandler_rlease(int fd); + +static int32_t sector_mgr_find_earliest_file_created_index(); +static int32_t sector_mgr_free_sector(int32_t fileuuid); +static zeeprom_sector_info_t* sector_mgr_find_idle_sector(); +static bool sector_mgr_sector_is_open(int32_t fileuuid); +static zeeprom_sector_info_t* sector_mgr_force_find_idle_sector(); +static void sector_mgr_open_sector(int32_t fileuuid); +static void sector_mgr_close_sector(int32_t fileuuid); +// static zeeprom_sector_info_t* sector_mgr_find_fileheader(int32_t fileuuid); +static zeeprom_sector_info_t* sector_mgr_find_end_sector(int32_t fileuuid); +static zeeprom_sector_info_t* sector_mgr_find_sector(int32_t fileuuid, int32_t sector_index_in_file); +static int32_t sector_mgr_file_get_size(int32_t fileuuid); + +static zeeprom_sector_info_t* sector_mgr_find_fileheader_by_filename(uint8_t* fileid); +static int32_t sector_mgr_get_sector_offset(zeeprom_sector_info_t* sector); +static int32_t sector_mgr_get_sector_rom_add(zeeprom_sector_info_t* sector); + +static void zeeprom_read(int32_t add, uint8_t* data, uint16_t len); +static void zeeprom_write(int32_t add, const uint8_t* data, uint16_t len); +static int32_t compute_checksum(uint8_t* data, uint16_t len); + +/******************************************************************************* + * CODE * + *******************************************************************************/ + +static bool m_eeprom_header_inited = false; +int zeeprom_fs_init() { // + SingleLeadECG_eeprom_init(); + if (!m_eeprom_header_inited) { + zeeprom_read(0, (uint8_t*)&m_eeprom_header, sizeof(m_eeprom_header)); + int32_t checksum_val = compute_checksum((uint8_t*)&m_eeprom_header, sizeof(m_eeprom_header) - sizeof(m_eeprom_header.checksum)); + if (checksum_val != m_eeprom_header.checksum) { + memset(&m_eeprom_header, 0, sizeof(m_eeprom_header)); + } + } + m_is_init = true; + m_eeprom_header_inited = true; + return 0; +} +int zeeprom_fs_uinit() { // + // zeeprom_write(0, (uint8_t*)&m_eeprom_header, sizeof(m_eeprom_header)); + SingleLeadECG_eeprom_uninit(); + m_is_init = false; + return 0; +} + +zeeprom_header_t* zeeprom_fs_get_header() { return &m_eeprom_header; } + +int zeeprom_fs_open(uint8_t* filename, wrflag_t wrflag) { + ZASSERT(m_is_init); + /** + * @brief + * 1. 如果文件已经存在,则打开文件 + * 2. 如果文件不存在, 则创建文件 + * + * 创建文件: + * 1. 找到一个空闲扇区 + * 2. 初始化文件头 + */ + + filehandler_t* fileHander = filehandler_alloc(); + if (!fileHander) { + ZLOGI("fileHander_alloc fail"); + return -1; + } + + if (wrflag == kwrflag_write_only) { + /******************************************************************************* + * 写文件 * + *******************************************************************************/ + zeeprom_sector_info_t* sectorHeaderInfo = NULL; + zeeprom_fs_delete_by_name(filename); + + sectorHeaderInfo = sector_mgr_force_find_idle_sector(); + if (!sectorHeaderInfo) { + ZLOGE("sector_mgr_force_find_idle_sector fail"); + filehandler_rlease(fileHander->fd); + return -1; + } + + memset(sectorHeaderInfo, 0, sizeof(zeeprom_sector_info_t)); + sectorHeaderInfo->usage = 1; + sectorHeaderInfo->opened = 1; + memcpy(sectorHeaderInfo->filename, filename, 8); + sectorHeaderInfo->sector_index_in_file = 0; + sectorHeaderInfo->datalen = 0; + sectorHeaderInfo->fileuuid = m_eeprom_header.fileuuid++; + fileHander->fileuuid = sectorHeaderInfo->fileuuid; + fileHander->sector_header = sectorHeaderInfo; + fileHander->file_offset = 0; + fileHander->file_size = 0; + return fileHander->fd; + + } else { + /******************************************************************************* + * 读文件 * + *******************************************************************************/ + zeeprom_sector_info_t* sectorHeaderInfo = sector_mgr_find_fileheader_by_filename(filename); + if (sectorHeaderInfo) { + fileHander->fileuuid = sectorHeaderInfo->fileuuid; + fileHander->file_offset = 0; + fileHander->fd = fileHander->fd; + fileHander->sector_header = sectorHeaderInfo; + fileHander->file_size = sector_mgr_file_get_size(fileHander->fileuuid); + memcpy(fileHander->filename, filename, 8); + memcpy(fileHander->usrdata, sectorHeaderInfo->usrdata, sizeof(sectorHeaderInfo->usrdata)); + sector_mgr_open_sector(fileHander->fileuuid); + return fileHander->fd; + } else { + filehandler_rlease(fileHander->fd); + return -1; + } + } +} + +int zeeprom_fs_write(int fileid, const uint8_t* data, int32_t size) { + ZASSERT(m_is_init); + + filehandler_t* fileHander = NULL; + zeeprom_sector_info_t* header_sinfo = NULL; + zeeprom_sector_info_t* endsector = NULL; + int32_t wadd = 0; + + ZASSERT(size == 256); + + fileHander = filehandler_find(fileid); + if (!fileHander) { + ZLOGE("fileHander_find fail"); + return -1; + } + + header_sinfo = fileHander->sector_header; + if (!header_sinfo) { + ZLOGE("header_sinfo fail"); + return -1; + } + + endsector = sector_mgr_find_end_sector(fileHander->fileuuid); + if (!endsector) { + ZLOGE("sector_mgr_find_end_sector fail"); + return -1; + } + + if (endsector->datalen + size > EEPROM_SECTOR_SIZE) { + ZLOGE("endsector->datalen + size > EEPROM_SECTOR_SIZE"); + return -1; + } + + wadd = sector_mgr_get_sector_rom_add(endsector); + if (wadd < 0) { + ZLOGE("sector_mgr_get_sector_rom_add fail"); + return -1; + } + ZASSERT(wadd % 256 == 0); + ZASSERT(wadd >= EEPROM_SECTOR_SIZE); + zeeprom_write(wadd + endsector->datalen, data, size); + + endsector->datalen = endsector->datalen + size; + fileHander->file_offset += size; + fileHander->file_size += size; + + if (endsector->datalen == EEPROM_SECTOR_SIZE) { + zeeprom_sector_info_t* newsector = sector_mgr_force_find_idle_sector(); + if (!newsector) { + ZLOGE("sector_mgr_force_find_idle_sector fail"); + return -1; + } + + memset(newsector, 0, sizeof(zeeprom_sector_info_t)); + newsector->usage = 1; + newsector->opened = 1; + memcpy(newsector->filename, header_sinfo->filename, 8); + newsector->sector_index_in_file = endsector->sector_index_in_file + 1; + newsector->datalen = 0; + newsector->fileuuid = header_sinfo->fileuuid; + } + return size; +} + +int zeeprom_fs_close(int fileid) { + ZASSERT(m_is_init); + + filehandler_t* fileHander = filehandler_find(fileid); + if (!fileHander) { + ZLOGE("zeeprom_fs_close fileHander_find fail"); + return -1; + } + + // sector_mgr_close_sector(fileHander->fileuuid); + // int32_t checksum_val = compute_checksum((uint8_t*)&m_eeprom_header, sizeof(m_eeprom_header) - sizeof(m_eeprom_header.checksum)); + // m_eeprom_header.checksum = checksum_val; + // zeeprom_write(0, (uint8_t*)&m_eeprom_header, sizeof(m_eeprom_header)); + + filehandler_rlease(fileid); + return 0; +} + +int zeeprom_fs_get_filesize_by_fd(int fd) { + ZASSERT(m_is_init); + filehandler_t* fileHander = filehandler_find(fd); + if (!fileHander) return 0; + return fileHander->file_size; +} + +int zeeprom_fs_read(int fileid, uint8_t* data, int32_t size) { + ZASSERT(m_is_init); + + /** + * @brief + * 找到当前扇区 + */ + ZASSERT(size == 256); + filehandler_t* fileHander = filehandler_find(fileid); + if (!fileHander) return -1; + + zeeprom_sector_info_t* header_sinfo = fileHander->sector_header; + if (!header_sinfo) { + return -1; + } + + int32_t sector_idx = fileHander->file_offset / EEPROM_SECTOR_SIZE; + int32_t sector_off = fileHander->file_offset % EEPROM_SECTOR_SIZE; + + zeeprom_sector_info_t* sector = sector_mgr_find_sector(fileHander->fileuuid, sector_idx); + if (!sector) { + return -1; + } + + int32_t radd = sector_mgr_get_sector_rom_add(sector); + ZASSERT(radd % 256 == 0); + radd += sector_off; + + zeeprom_read(radd, data, size); + fileHander->file_offset += size; + return size; +} + +int zeeprom_fs_delete(int32_t fileuuid) { + ZASSERT(m_is_init); + + sector_mgr_free_sector(fileuuid); + return 0; +} +int zeeprom_fs_delete_by_name(uint8_t* filename) { + ZASSERT(m_is_init); + + zeeprom_sector_info_t* sectorHeaderInfo = sector_mgr_find_fileheader_by_filename(filename); + if (sectorHeaderInfo) { + sector_mgr_free_sector(sectorHeaderInfo->fileuuid); + } + return 0; +} + +int zeeprom_fs_get_file_num() { + ZASSERT(m_is_init); + + int count = 0; + for (int i = 0; i < MAX_SECTOR_NUM; i++) { + zeeprom_sector_info_t* sinfo = &m_eeprom_header.sectorinfos[i]; + if (sinfo->usage == 1 && sinfo->sector_index_in_file == 0) { + count++; + } + } + return count; +} +int zeeprom_fs_delete_the_oldest_file() { + ZASSERT(m_is_init); + + int32_t earliest_file_created_index = sector_mgr_find_earliest_file_created_index(); + sector_mgr_free_sector(earliest_file_created_index); + return 0; +} + +int zeeprom_fs_get_filesize_by_fileuuid(int32_t fileuuid) { + ZASSERT(m_is_init); + return sector_mgr_file_get_size(fileuuid); +} + +static void zeeprom_read(int32_t add, uint8_t* data, uint16_t len) { // + int wrsize = EEPROM_SECTOR_MIN_WR_SIZE; + + int readTimes = len / wrsize; + int readRemain = len % wrsize; + + for (int i = 0; i < readTimes; i++) { + SingleLeadECG_eeprom_read(add + i * wrsize, data + i * wrsize, wrsize); + } + if (readRemain > 0) { + SingleLeadECG_eeprom_read(add + readTimes * wrsize, data + readTimes * wrsize, readRemain); + } +} +static void zeeprom_write(int32_t add, const uint8_t* data, uint16_t len) { + int wrsize = EEPROM_SECTOR_MIN_WR_SIZE; + + int writeTimes = len / wrsize; + int writeRemain = len % wrsize; + + for (int i = 0; i < writeTimes; i++) { + // int pageoff = add / wrsize + i; + int32_t writeadd = add + i * wrsize; + SingleLeadECG_eeprom_write(writeadd, data + i * wrsize, wrsize); + } + if (writeRemain > 0) { + int32_t writeadd = add + writeTimes * wrsize; + SingleLeadECG_eeprom_write(writeadd, data + writeTimes * wrsize, writeRemain); + } +} + +static int32_t compute_checksum(uint8_t* data, uint16_t len) { + int32_t sum = 0; + for (int i = 0; i < len; i++) { + sum += data[i]; + } + return sum; +} +/******************************************************************************* + * filehandler * + *******************************************************************************/ +static filehandler_t* filehandler_find(int fd) { + for (int i = 0; i < ZARRAY_SIZE(m_filehandler); i++) { + if (m_filehandler[i].fd == fd) { + return &m_filehandler[i]; + } + } + return NULL; +} +static filehandler_t* filehandler_alloc() { + for (int i = 0; i < ZARRAY_SIZE(m_filehandler); i++) { + if (m_filehandler[i].fd == 0) { + m_filehandler[i].fd = ++m_fd_off; + return &m_filehandler[i]; + } + } + return NULL; +} +static void filehandler_rlease(int fd) { + for (int i = 0; i < ZARRAY_SIZE(m_filehandler); i++) { + if (m_filehandler[i].fd == fd) { + m_filehandler[i].fd = 0; + return; + } + } +} +/******************************************************************************* + * sector_mgr * + *******************************************************************************/ + +// 查找最早创建的文件的file_created_index +static int32_t sector_mgr_find_earliest_file_created_index() { + int32_t earliest_file_created_index = INT32_MAX; + for (int i = 0; i < MAX_SECTOR_NUM; i++) { + zeeprom_sector_info_t* sinfo = &m_eeprom_header.sectorinfos[i]; + if (sinfo->usage == 1) { + if (sinfo->fileuuid < earliest_file_created_index) { + earliest_file_created_index = sinfo->fileuuid; + } + } + } + return earliest_file_created_index; +} +// 删除文件 +static int32_t sector_mgr_free_sector(int32_t fileuuid) { + for (int i = 0; i < MAX_SECTOR_NUM; i++) { + zeeprom_sector_info_t* sinfo = &m_eeprom_header.sectorinfos[i]; + if (sinfo->usage == 1 && sinfo->fileuuid == fileuuid) { + sinfo->usage = 0; + } + } + return 0; +} +// +static zeeprom_sector_info_t* sector_mgr_find_idle_sector() { + for (int i = 0; i < MAX_SECTOR_NUM; i++) { + zeeprom_sector_info_t* sinfo = &m_eeprom_header.sectorinfos[i]; + if (sinfo->usage == 0) { + return sinfo; + } + } + return NULL; +} +static bool sector_mgr_sector_is_open(int32_t fileuuid) { + for (int i = 0; i < MAX_SECTOR_NUM; i++) { + zeeprom_sector_info_t* sinfo = &m_eeprom_header.sectorinfos[i]; + if (sinfo->usage == 1 && sinfo->fileuuid == fileuuid) { + return sinfo->opened; + } + } + return false; +} + +static zeeprom_sector_info_t* sector_mgr_force_find_idle_sector() { + /** + * @brief 查找空闲扇区 + */ + zeeprom_sector_info_t* ret_sinfo = sector_mgr_find_idle_sector(); + if (ret_sinfo) return ret_sinfo; + /** + * @brief 查找最早创建的文件 + */ + int32_t earliest_file_created_index = sector_mgr_find_earliest_file_created_index(); + if (sector_mgr_sector_is_open(earliest_file_created_index)) { + return NULL; + } + + /** + * @brief 删除最早创建的文件 + */ + sector_mgr_free_sector(earliest_file_created_index); + + /** + * @brief 重新查找空闲扇区 + */ + ret_sinfo = sector_mgr_find_idle_sector(); + if (ret_sinfo) return ret_sinfo; + + return NULL; +} + +static void sector_mgr_open_sector(int32_t fileuuid) { + for (int i = 0; i < MAX_SECTOR_NUM; i++) { + zeeprom_sector_info_t* sinfo = &m_eeprom_header.sectorinfos[i]; + if (sinfo->usage == 1 && sinfo->fileuuid == fileuuid) { + sinfo->opened = true; + } + } +} + +static void sector_mgr_close_sector(int32_t fileuuid) { + for (int i = 0; i < MAX_SECTOR_NUM; i++) { + zeeprom_sector_info_t* sinfo = &m_eeprom_header.sectorinfos[i]; + if (sinfo->usage == 1 && sinfo->fileuuid == fileuuid) { + sinfo->opened = false; + } + } +} + +// static zeeprom_sector_info_t* sector_mgr_find_fileheader(int32_t fileuuid) { +// for (int i = 0; i < MAX_SECTOR_NUM; i++) { +// zeeprom_sector_info_t* sinfo = &m_eeprom_header.sectorinfos[i]; +// if (sinfo->usage == 1 && sinfo->sector_index_in_file == 0 && sinfo->fileuuid == fileuuid) { +// return sinfo; +// } +// } +// return NULL; +// } + +static zeeprom_sector_info_t* sector_mgr_find_sector(int32_t fileuuid, int32_t sector_index_in_file) { + for (int i = 0; i < MAX_SECTOR_NUM; i++) { + zeeprom_sector_info_t* sinfo = &m_eeprom_header.sectorinfos[i]; + if (sinfo->usage == 1 && sinfo->sector_index_in_file == sector_index_in_file && sinfo->fileuuid == fileuuid) { + return sinfo; + } + } + return NULL; +} + +static zeeprom_sector_info_t* sector_mgr_find_end_sector(int32_t fileuuid) { + int32_t maxsectorindex = 0; + for (int i = 0; i < MAX_SECTOR_NUM; i++) { + zeeprom_sector_info_t* sinfo = &m_eeprom_header.sectorinfos[i]; + if (sinfo->usage == 1 && sinfo->fileuuid == fileuuid) { + if (sinfo->sector_index_in_file >= maxsectorindex) { + maxsectorindex = sinfo->sector_index_in_file; + } + } + } + return sector_mgr_find_sector(fileuuid, maxsectorindex); +} + +static zeeprom_sector_info_t* sector_mgr_find_fileheader_by_filename(uint8_t* fileid) { + for (int i = 0; i < MAX_SECTOR_NUM; i++) { + zeeprom_sector_info_t* sinfo = &m_eeprom_header.sectorinfos[i]; + if (sinfo->usage == 1 && sinfo->sector_index_in_file == 0 && memcmp(sinfo->filename, fileid, 8) == 0) { + return sinfo; + } + } + return NULL; +} + +static int32_t sector_mgr_get_sector_offset(zeeprom_sector_info_t* sector) { + for (int i = 0; i < MAX_SECTOR_NUM; i++) { + zeeprom_sector_info_t* sinfo = &m_eeprom_header.sectorinfos[i]; + if (sinfo == sector) { + return i; + } + } + return -1; +} + +static int32_t sector_mgr_get_sector_rom_add(zeeprom_sector_info_t* sector) { + int32_t offset = sector_mgr_get_sector_offset(sector); + if (offset < 0) return -1; + return (offset + 1) * EEPROM_SECTOR_SIZE; +} + +static int32_t sector_mgr_file_get_size(int32_t fileuuid) { + int32_t filesize = 0; + for (int i = 0; i < MAX_SECTOR_NUM; i++) { + zeeprom_sector_info_t* sinfo = &m_eeprom_header.sectorinfos[i]; + + if (sinfo->usage == 1 && sinfo->fileuuid == fileuuid) { + filesize += sinfo->datalen; + } + } + return filesize; +} + +static const char* filename2str(uint8_t* filename) { + static char filename_str[32]; + sprintf(filename_str, "%02x%02x%02x%02x%02x%02x%02x%02x", filename[0], filename[1], filename[2], filename[3], filename[4], filename[5], filename[6], filename[7]); + return filename_str; +} + +int zeeprom_fs_dump_sector_state() { + ZLOGI_BLOCK("zeeprom_fs_dump_sector_state\n"); + for (int i = 0; i < MAX_SECTOR_NUM; i++) { + zeeprom_sector_info_t* sinfo = &m_eeprom_header.sectorinfos[i]; + if (sinfo->usage == 1) { + ZLOGI_BLOCK("[%d]: usage=%d opened=%d", i, sinfo->usage, sinfo->opened); + ZLOGI_BLOCK(" fname=%s, index_in_file=%d, datalen=%d, fileuuid=%d", filename2str(sinfo->filename), sinfo->sector_index_in_file, sinfo->datalen, sinfo->fileuuid); + } else { + ZLOGI_BLOCK("[%d]: usage=%d", i, sinfo->usage); + } + } + return 0; +} diff --git a/app/src/zeeprom_fs.h b/app/src/zeeprom_fs.h new file mode 100644 index 0000000..7ede932 --- /dev/null +++ b/app/src/zeeprom_fs.h @@ -0,0 +1,66 @@ +#pragma once +#include + +#define EEPROM_SIZE (256 * 1024) +#define EEPROM_SECTOR_MIN_WR_SIZE (256) +#define EEPROM_SECTOR_SIZE (8 * 1024) +#define MAX_SECTOR_NUM (EEPROM_SIZE / EEPROM_SECTOR_SIZE - 1) +#define EEPROM_FILE_SIZE (EEPROM_SECTOR_SIZE * MAX_SECTOR_NUM) + +// +#pragma pack(1) +typedef struct { + uint8_t usage; + uint8_t opened; + uint8_t filename[8]; // 注意文件名为固定八个字节的二进制数据,不是字符串 + int32_t sector_index_in_file; // 当前扇区中文件数据的起始地址 + int32_t datalen; // 当前扇区中文件数据的长度 + int32_t fileuuid; // 递增,根据这个index判断文件创建的先后顺序,同时也相当于文件唯一标识 + uint8_t usrdata[20]; +} zeeprom_sector_info_t; + +typedef struct { + uint8_t filename[8]; + uint8_t usrdata[20]; + + zeeprom_sector_info_t* sector_header; + int32_t file_offset; + int32_t file_size; + + int fd; + int32_t fileuuid; +} filehandler_t; + +typedef struct { + zeeprom_sector_info_t sectorinfos[MAX_SECTOR_NUM]; + int32_t fileuuid; + int32_t checksum; +} zeeprom_header_t; +#pragma pack() + +int zeeprom_fs_init(); +int zeeprom_fs_uinit(); + +typedef enum { + kwrflag_read_only, + kwrflag_write_only, +} wrflag_t; + +zeeprom_header_t* zeeprom_fs_get_header(); + +int zeeprom_fs_open(uint8_t* filename, wrflag_t flag); + +int zeeprom_fs_close(int fd); + +int zeeprom_fs_write(int fd, const uint8_t* data, int32_t size); +int zeeprom_fs_read(int fd, uint8_t* data, int32_t size); + +int zeeprom_fs_get_filesize_by_fd(int fd); + +int zeeprom_fs_get_file_num(); +int zeeprom_fs_delete_the_oldest_file(); +int zeeprom_fs_delete(int32_t fileuuid); +int zeeprom_fs_delete_by_name(uint8_t* filename); + +int zeeprom_fs_dump_sector_state(); +int zeeprom_fs_get_filesize_by_fileuuid(int32_t fileuuid);