From 358f0a806103145de051d806c158d09f3b7501ae Mon Sep 17 00:00:00 2001 From: zhaohe Date: Thu, 1 Feb 2024 17:22:56 +0800 Subject: [PATCH] update --- .vscode/settings.json | 7 +- README.md | 279 +------------- app/app.uvoptx | 162 ++++---- app/app.uvprojx | 10 + app/config/sdk_config.h | 4 +- app/src/app_ble_service.c | 57 +++ app/src/app_ble_service.h | 13 + app/src/app_event.h | 35 ++ app/src/bak/ble_cmd_process_service.c | 455 +++++++++++++++++++++++ app/src/bak/ble_cmd_process_service.h | 16 + app/src/bak/heart_wave_sample_service.c | 152 ++++++++ app/src/bak/heart_wave_sample_service.h | 15 + app/src/bak/three_lead_board.c | 527 +++++++++++++++++++++++++++ app/src/bak/three_lead_board.h | 56 +++ app/src/basic/ads1293/ads1293.c | 24 +- app/src/basic/ads1293/ads1293.h | 7 +- app/src/basic/config.h | 7 +- app/src/ble_cmd_process_service.c | 455 ----------------------- app/src/ble_cmd_process_service.h | 16 - app/src/board/TI_ADS1293_register_settings.h | 101 ----- app/src/board/ads_cfg.h | 148 -------- app/src/board/board.c | 0 app/src/board/board.h | 61 ++++ app/src/board/board_battery_state.c | 36 ++ app/src/board/board_battery_state.h | 15 + app/src/board/board_beep_ctrl.c | 93 +++++ app/src/board/board_beep_ctrl.h | 24 ++ app/src/board/board_button.c | 24 ++ app/src/board/board_button.h | 18 + app/src/board/board_light_ctrl.c | 70 ++++ app/src/board/board_light_ctrl.h | 23 ++ app/src/board/board_sdcard_driver.c | 176 +++++++++ app/src/board/board_sdcard_driver.h | 19 + app/src/board/three_lead_board.c | 522 -------------------------- app/src/board/three_lead_board.h | 55 --- app/src/device_state.c | 13 - app/src/device_state.h | 79 +--- app/src/heart_wave_sample_service.c | 342 +++++++++++------ app/src/heart_wave_sample_service.h | 34 +- app/src/main.bak.c | 372 +++++++++++++++++++ app/src/main.c | 361 +----------------- app/src/sample_data_manager_service.c | 155 ++++++++ app/src/sample_data_manager_service.h | 78 ++++ libznordic | 2 +- 44 files changed, 2933 insertions(+), 2185 deletions(-) create mode 100644 app/src/app_ble_service.c create mode 100644 app/src/app_ble_service.h create mode 100644 app/src/app_event.h create mode 100644 app/src/bak/ble_cmd_process_service.c create mode 100644 app/src/bak/ble_cmd_process_service.h create mode 100644 app/src/bak/heart_wave_sample_service.c create mode 100644 app/src/bak/heart_wave_sample_service.h create mode 100644 app/src/bak/three_lead_board.c create mode 100644 app/src/bak/three_lead_board.h delete mode 100644 app/src/ble_cmd_process_service.c delete mode 100644 app/src/ble_cmd_process_service.h delete mode 100644 app/src/board/TI_ADS1293_register_settings.h delete mode 100644 app/src/board/ads_cfg.h create mode 100644 app/src/board/board.c create mode 100644 app/src/board/board.h create mode 100644 app/src/board/board_battery_state.c create mode 100644 app/src/board/board_battery_state.h create mode 100644 app/src/board/board_beep_ctrl.c create mode 100644 app/src/board/board_beep_ctrl.h create mode 100644 app/src/board/board_button.c create mode 100644 app/src/board/board_button.h create mode 100644 app/src/board/board_light_ctrl.c create mode 100644 app/src/board/board_light_ctrl.h create mode 100644 app/src/board/board_sdcard_driver.c create mode 100644 app/src/board/board_sdcard_driver.h delete mode 100644 app/src/board/three_lead_board.c delete mode 100644 app/src/board/three_lead_board.h create mode 100644 app/src/main.bak.c create mode 100644 app/src/sample_data_manager_service.c create mode 100644 app/src/sample_data_manager_service.h diff --git a/.vscode/settings.json b/.vscode/settings.json index 9b70645..55958d4 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -93,7 +93,12 @@ "heart_wave_sample_service.h": "c", "znordic_device_info_mgr.h": "c", "nrf_uart.h": "c", - "ads_cfg.h": "c" + "ads_cfg.h": "c", + "sdk_config.h": "c", + "app_ble_service.h": "c", + "nrfx_timer.h": "c", + "app_button.h": "c", + "nrf_drv_gpiote.h": "c" }, "files.encoding": "gbk" } \ No newline at end of file diff --git a/README.md b/README.md index 75e982e..c042055 100644 --- a/README.md +++ b/README.md @@ -2,278 +2,39 @@ ## 使用说明 -``` -https://iflytop1.feishu.cn/wiki/Fp0fwciUEibtm4kaUeXcraOCneg - -``` ``` -开发板IO资源说明: - -#define BSP_LED_0 13 -#define BSP_LED_1 14 -#define BSP_LED_2 15 -#define BSP_LED_3 16 - -#define BUTTON_1 11 // 上拉低电平有效 -#define BUTTON_2 12 // 上拉低电平有效 -#define BUTTON_3 24 // 上拉低电平有效 -#define BUTTON_4 25 // 上拉低电平有效 - -sdk\components\boards\pca10100.h - -清风开发板 - - AIN2 -> 光感 - -I2C -#define TWI_SCL_M 28 //I2C SCL引脚 -#define TWI_SDA_M 30 //I2C SDA引脚 - ------------------------------------- - - -PIN4 PIN30/PIN31 PIN28/PIN29 PIN11/PIN20 - - - - +TODO: + 1. 所有的文件操作如果失败系统会自动复位。(通过ZASSERT触发的复位操作) + 2. 电池电量校准 ``` ``` 设备行为: -1. 按下按键或者电极触发后开始广播 -2. 当电极没有触发,且蓝牙没有连接,且超时10s后,停止广播,进入低功耗模式 +开机条件 + 1.轻按按键 -3. 设备状态 +关机条件 + 1.长按按键3秒 + 2.蓝牙连接断开后10秒 - 关机(休眠) - 开机蓝牙未连接(广播中) - 蓝牙已连接 +开机: + 1.打开蓝牙广播 + 2.指示灯闪烁1s慢闪,蓝牙连接后指示灯常亮。 +关机: + 1.关闭蓝牙广播 -``` -``` -难点: - 1.采样间隔2ms (500HZ) - 2.数据往flash中写入时间消耗,cache选择多大,数据什么时候上报。 - 1. ADC:单次采样,阻塞拿数值(50us) - 2. 电池电量的采集ADC和电压采集ADC用的是同一个ADC +开始采集触发条件 + 1.设备开机 + 2.APP控制 + 3.当前没有在充电(硬件限制了此条件) - (这里先使用最简单的阻塞式ADC采集,电池ADC3次,采样ADC3次) +蜂鸣器触发条件: + 1. 开始采集,蜂鸣器响一声 + 2. 传感器脱落,每隔10秒,蜂鸣器响三声, -``` - -``` -屏幕驱动: -https://github.com/libdriver/ssd1306 -1306驱动和1312是一样的,只不过1312默认是镜像的 - -``` - -``` - -UI元素: -------------------- -1. 不同大小的字体 -2. 进度条 -3. [X] -4. APP -------------------- - - -1. 进度条 -2. 圈,x -3. 时间 -4. LOGO -5. [X] -6. HR -7. APP查看结果 -8. 年月日/时分秒 -9. 不同大小的字体 - - -xxx -+xx - - - LOGO - 进度条 - - 年月日 - 时分秒 - - - 保持静止 - ___________ - [===== ] - ------------ - - 心电图 - [===== ] - - [X] - 不足30秒 - - 正在保存 - [===== ] - - APP - 查看结果 -``` - - -``` -存储: -1帧 -2byte -200帧 -400byte -1秒 -400byte -30秒 -12kbyte -120秒 -48kbyte - ----------------------------- -2Mbit -256Kbyte - -640秒 /120 = 5条记录 - -256kbyte - -256byte索引 - -[ - ID:[年月日] - packetOFF:[] - usage[]: - date:[] -] -48kbyte --> 一个扇区 - -256/4k = 64个扇区 10s数据 - -openStorage(年月日) -writeData(){ - -// 数据量是否大于最大数值 - -// 是否还有空间 -// 擦除旧的空间 -// 写入数据 -// 写入缓存 - -// 是否刷新缓存? - -找到空闲扇区,写入数据。 -找不到空闲扇区,按照顺序释放旧的扇区 -重新寻找扇区 -} - -// 倍数读取 -readData(){ - 1. 判断数据在哪个扇区 - 3. 读取扇区数据信息 - 2. 读取数据 - 3. 拷贝数据 -} - -// Header - -[ - usage: - fileHeaderdata: - fileId: - dataoff: - datalen: -] - -{ - fileUUID:年月日时分秒 - sector:[1,2,3,4,5] - datalen: 100 - //分辨率 - //总时长 - //采样率 -} - - -``` - -``` -硬件异常: - 1. eeprom读写失败 - 2. 电池电量低 -``` - -``` -编程注意事项: -1. 使用了app_timer后,如果在系统中某个位置延时时间过程,会导致系统重启 - -TODO: -1. eeprom的文件扇区信息没有存储,也就是说每次电池用没了之后,数据会丢失 -2. 如果要实现不丢数据,需要在eeprom中存储文件扇区信息,同时由于扇区的大小大于256字节,所以需要优化eeprom的写入函数。 - -单导蓝牙使用注意事项: - - 1. 开机后 - 开启广播 - 2. 关机 - 关闭广播 - 关机条件: - 1. 蓝牙断开 - 2. 设备未操作 - 3. 30s内无任何蓝牙指令(连接) - - - 1. 蓝牙的广播的启停独立控制和设备开机关机逻辑分开 - 开启广播:开机时候,如果当前没有开启广播,则打开广播 - 关闭广播: 关机后30s内无连接关闭广播 - 断开连接后30s关闭广播 - - 2. 蓝牙状态指示灯: - 1. 蓝牙广播打开:指示灯闪烁 - 2. 蓝牙广播关闭:指示灯关闭 - - 3. 采样时不支持电量上报 - 4. 采样时不支持记录查询相关指令 - 5. 不支持删除采样记录 - -``` - -``` -任务: - 16. 解决断开连接,再次唤醒,屏幕无显示的BUG OK TESTOK - 1. 提取休眠时间到宏配置中 OK - 9. 支持数据实时上报 OK TEST1/2OK,有数据,但数据是否正确,校验起来不方便 - 12. 支持数据上传 OK TESTOK - 15. 检查设备状态 OK TESTOK - 14. 支持掉落事件 OK TESTOK - - 6. 支持电池电量采集 OK - 8. 采集完30秒,蜂鸣器滴一声,采集完成,蜂鸣器滴一声 OK - 16. 调整UI位置 - 11. 死机后一直重启的BUG OK - 12. 修改蓝牙名称 OK - --------------------------------------------------------------- - 2. UI添加蓝牙状态 - 3. UI添加上传状态 - 4. UI添加心率计算 - 5. UI添加心脏跳动效果 - 7. 校准电池电量采集 - 7. 添加心率 - 10. 添加OTA支持 - 11. 数据掉电不丢失 - 12. 优化定时器周期 - 13. 支持低电量事件 - 14. 添加设备激活逻辑,根据设备是否通过过时间来判断当前是否彻底断电。 - 15. 优化蜂鸣器的声音 - ``` \ No newline at end of file diff --git a/app/app.uvoptx b/app/app.uvoptx index eabbfe4..2c9aab7 100644 --- a/app/app.uvoptx +++ b/app/app.uvoptx @@ -439,6 +439,18 @@ 0 0 + + 1 + 7 + 1 + 0 + 0 + 0 + .\src\app_ble_service.c + app_ble_service.c + 0 + 0 + @@ -449,7 +461,7 @@ 0 2 - 7 + 8 1 0 0 @@ -469,7 +481,7 @@ 0 3 - 8 + 9 1 0 0 @@ -481,7 +493,7 @@ 3 - 9 + 10 1 0 0 @@ -501,7 +513,7 @@ 0 4 - 10 + 11 1 0 0 @@ -521,7 +533,7 @@ 0 5 - 11 + 12 1 0 0 @@ -533,7 +545,7 @@ 5 - 12 + 13 1 0 0 @@ -545,7 +557,7 @@ 5 - 13 + 14 1 0 0 @@ -557,7 +569,7 @@ 5 - 14 + 15 1 0 0 @@ -569,7 +581,7 @@ 5 - 15 + 16 1 0 0 @@ -581,7 +593,7 @@ 5 - 16 + 17 1 0 0 @@ -593,7 +605,7 @@ 5 - 17 + 18 1 0 0 @@ -605,7 +617,7 @@ 5 - 18 + 19 1 0 0 @@ -625,7 +637,7 @@ 0 6 - 19 + 20 1 0 0 @@ -645,7 +657,7 @@ 0 7 - 20 + 21 1 0 0 @@ -657,7 +669,7 @@ 7 - 21 + 22 1 0 0 @@ -669,7 +681,7 @@ 7 - 22 + 23 1 0 0 @@ -681,7 +693,7 @@ 7 - 23 + 24 1 0 0 @@ -693,7 +705,7 @@ 7 - 24 + 25 1 0 0 @@ -705,7 +717,7 @@ 7 - 25 + 26 1 0 0 @@ -717,7 +729,7 @@ 7 - 26 + 27 1 0 0 @@ -729,7 +741,7 @@ 7 - 27 + 28 1 0 0 @@ -741,7 +753,7 @@ 7 - 28 + 29 1 0 0 @@ -753,7 +765,7 @@ 7 - 29 + 30 1 0 0 @@ -765,7 +777,7 @@ 7 - 30 + 31 1 0 0 @@ -777,7 +789,7 @@ 7 - 31 + 32 1 0 0 @@ -789,7 +801,7 @@ 7 - 32 + 33 1 0 0 @@ -801,7 +813,7 @@ 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 @@ -893,7 +905,7 @@ 0 8 - 40 + 41 1 0 0 @@ -905,7 +917,7 @@ 8 - 41 + 42 1 0 0 @@ -917,7 +929,7 @@ 8 - 42 + 43 1 0 0 @@ -929,7 +941,7 @@ 8 - 43 + 44 1 0 0 @@ -941,7 +953,7 @@ 8 - 44 + 45 1 0 0 @@ -953,7 +965,7 @@ 8 - 45 + 46 1 0 0 @@ -965,7 +977,7 @@ 8 - 46 + 47 1 0 0 @@ -977,7 +989,7 @@ 8 - 47 + 48 1 0 0 @@ -989,7 +1001,7 @@ 8 - 48 + 49 1 0 0 @@ -1001,7 +1013,7 @@ 8 - 49 + 50 1 0 0 @@ -1013,7 +1025,7 @@ 8 - 50 + 51 1 0 0 @@ -1025,7 +1037,7 @@ 8 - 51 + 52 1 0 0 @@ -1037,7 +1049,7 @@ 8 - 52 + 53 1 0 0 @@ -1049,7 +1061,7 @@ 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 @@ -1225,7 +1237,7 @@ 0 9 - 67 + 68 1 0 0 @@ -1237,7 +1249,7 @@ 9 - 68 + 69 1 0 0 @@ -1249,7 +1261,7 @@ 9 - 69 + 70 1 0 0 @@ -1261,7 +1273,7 @@ 9 - 70 + 71 1 0 0 @@ -1273,7 +1285,7 @@ 9 - 71 + 72 1 0 0 @@ -1285,7 +1297,7 @@ 9 - 72 + 73 1 0 0 @@ -1305,7 +1317,7 @@ 0 10 - 73 + 74 1 0 0 @@ -1317,7 +1329,7 @@ 10 - 74 + 75 1 0 0 @@ -1329,7 +1341,7 @@ 10 - 75 + 76 1 0 0 @@ -1349,7 +1361,7 @@ 0 11 - 76 + 77 1 0 0 @@ -1361,7 +1373,7 @@ 11 - 77 + 78 1 0 0 @@ -1373,7 +1385,7 @@ 11 - 78 + 79 1 0 0 @@ -1393,7 +1405,7 @@ 0 12 - 79 + 80 1 0 0 @@ -1413,7 +1425,7 @@ 0 13 - 80 + 81 1 0 0 @@ -1425,7 +1437,7 @@ 13 - 81 + 82 1 0 0 diff --git a/app/app.uvprojx b/app/app.uvprojx index 1121919..907dea7 100644 --- a/app/app.uvprojx +++ b/app/app.uvprojx @@ -413,6 +413,11 @@ 1 ..\libznordic\src\zdatachannel_service.c + + app_ble_service.c + 1 + .\src\app_ble_service.c + @@ -4172,6 +4177,11 @@ 1 ..\libznordic\src\zdatachannel_service.c + + app_ble_service.c + 1 + .\src\app_ble_service.c + diff --git a/app/config/sdk_config.h b/app/config/sdk_config.h index b5f7a21..bc77afc 100644 --- a/app/config/sdk_config.h +++ b/app/config/sdk_config.h @@ -7794,7 +7794,7 @@ // <268435456=> 1000000 baud #ifndef NRF_LOG_BACKEND_UART_BAUDRATE -#define NRF_LOG_BACKEND_UART_BAUDRATE 251658240 +#define NRF_LOG_BACKEND_UART_BAUDRATE 30801920 #endif // NRF_LOG_BACKEND_UART_TEMP_BUFFER_SIZE - Size of buffer for partially processed strings. @@ -9971,7 +9971,7 @@ // NRF_CLI_BLE_UART_CONFIG_LOG_ENABLED - Enables logging in the module. //========================================================== #ifndef NRF_CLI_BLE_UART_CONFIG_LOG_ENABLED -#define NRF_CLI_BLE_UART_CONFIG_LOG_ENABLED 0 +#define NRF_CLI_BLE_UART_CONFIG_LOG_ENABLED 1 #endif // NRF_CLI_BLE_UART_CONFIG_LOG_LEVEL - Default Severity level diff --git a/app/src/app_ble_service.c b/app/src/app_ble_service.c new file mode 100644 index 0000000..923e224 --- /dev/null +++ b/app/src/app_ble_service.c @@ -0,0 +1,57 @@ +#include "app_ble_service.h" + +#include "app_scheduler.h" +#include "zdatachannel_service.h" +#include "znordic.h" +static zdatachannel_init_t zdatachannle_init; + +static uint8_t rxbufcache[256]; +static bool is_rxbufcache_used = false; + +static void prvf_process_ble_rx_data(void* p_event_data, uint16_t event_size); + +/******************************************************************************* + * 蓝牙服务注册 * + *******************************************************************************/ +ZDATACHANNEL_DEF(m_zhrs, 2 /*优先级*/, 1 /*client num*/); +/** + * @brief 蓝牙消息回调 + */ +static void zdatachannel_data_handler(zdatachannel_evt_t* p_evt) { + if (p_evt->type != ZDATACHANNEL_EVT_RX_DATA) { + return; + } + + // 消息正在被处理中,丢弃新来的消息 + if (is_rxbufcache_used) return; + if (p_evt->params.rx_data.length > sizeof(rxbufcache)) return; + + memcpy(rxbufcache, p_evt->params.rx_data.p_data, p_evt->params.rx_data.length); + uint32_t suc = app_sched_event_put(rxbufcache, p_evt->params.rx_data.length, prvf_process_ble_rx_data); + if (suc == 0) { + is_rxbufcache_used = true; + } +} + +/******************************************************************************* + * 消息处理 * + *******************************************************************************/ +static void prvf_process_ble_rx_data(void* p_event_data, uint16_t data_size) { + ZLOGI("rx:"); + NRF_LOG_HEXDUMP_INFO(p_event_data, data_size); +} + +void AppBleService_startAdv() { zble_module_start_adv(); } +void AppBleService_stopAdv() { zble_module_stop_adv(); } + +void AppBleService_onServiceInitCB() { + 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 AppBleService_init() { + // +} diff --git a/app/src/app_ble_service.h b/app/src/app_ble_service.h new file mode 100644 index 0000000..761a2b2 --- /dev/null +++ b/app/src/app_ble_service.h @@ -0,0 +1,13 @@ +#pragma once +#include + +/** + * @brief + * zble_module_init 方法将此回调注册进去 + */ +void AppBleService_onServiceInitCB(); + + +void AppBleService_init(); +void AppBleService_uninit(); +void AppBleService_startAdv(); diff --git a/app/src/app_event.h b/app/src/app_event.h new file mode 100644 index 0000000..27b2237 --- /dev/null +++ b/app/src/app_event.h @@ -0,0 +1,35 @@ +#pragma once +#include +#include + +#define LITTLE_DATA_BLOCK_FRAME_NUM 4 // 每四帧回调一次 + +typedef enum { + kevent_sensor_drop = 0, // 导联连接事件 + kevent_tmr_scheduler, // 定时器调度事件 + kevent_capture_data_block_event, // 每采集一定数据后回调一次 + kevent_capture_little_data_block_event, // 传感器小数据块回调事件 +} app_event_type_t; + +typedef struct { + uint32_t data0; + uint32_t data1; + uint32_t data2; +} one_frame_data_t; + +typedef struct { + app_event_type_t eventType; + union { + struct { + uint32_t frameIndex; + one_frame_data_t data[LITTLE_DATA_BLOCK_FRAME_NUM]; + } little_data_block; + + struct { + uint8_t* data; // 不保证数据对齐 + int len; + } block_sensor_data; + } val; +} app_event_t; + +void app_event_process_cb(void* p_event_data, uint16_t event_size); \ No newline at end of file diff --git a/app/src/bak/ble_cmd_process_service.c b/app/src/bak/ble_cmd_process_service.c new file mode 100644 index 0000000..a2485a4 --- /dev/null +++ b/app/src/bak/ble_cmd_process_service.c @@ -0,0 +1,455 @@ +#include "ble_cmd_process_service.h" + +#include "basic/device_info_mgr.h" +#include "basic/heart_rate_sensor_protocol.h" +#include "basic/zble_module.h" +#include "basic/zdatachannel_service.h" +#include "config.h" +#include "one_conduction_board.h" +#include "sample_data_manager.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) { + 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(rxheader->data, len - sizeof(ify_hrs_packet_t)); + + 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.sensor0_pos = (!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/bak/ble_cmd_process_service.h b/app/src/bak/ble_cmd_process_service.h new file mode 100644 index 0000000..d6e039d --- /dev/null +++ b/app/src/bak/ble_cmd_process_service.h @@ -0,0 +1,16 @@ +#pragma once + +#include "basic/heart_rate_sensor_protocol.h" +#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/bak/heart_wave_sample_service.c b/app/src/bak/heart_wave_sample_service.c new file mode 100644 index 0000000..49ff56c --- /dev/null +++ b/app/src/bak/heart_wave_sample_service.c @@ -0,0 +1,152 @@ +#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); + } + + /******************************************************************************* + * 实时采样数据事件上报 * + *******************************************************************************/ + { + 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); + } +} + +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/bak/heart_wave_sample_service.h b/app/src/bak/heart_wave_sample_service.h new file mode 100644 index 0000000..65e18dc --- /dev/null +++ b/app/src/bak/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/bak/three_lead_board.c b/app/src/bak/three_lead_board.c new file mode 100644 index 0000000..bf27630 --- /dev/null +++ b/app/src/bak/three_lead_board.c @@ -0,0 +1,527 @@ +#include "three_lead_board.h" + +#include "znordic.h" +// +#include "app_timer.h" +#include "basic\ads1293\ads1293.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" + +#define LED_GREEN_PIN 9 + +#define BATTERY_ADC_PIN NRF_SAADC_INPUT_AIN0 +#define BATTERY_ADC_CHANNEL 1 // 不重复即可 + +#define BUTTON_PIN 0 + +#define BEEP_PWM_INSTANCE 0 +#define BEEP_PIN 18 + +#define SDCARD_SPI_SCK_PIN 4 +#define SDCARD_SPI_CS_PIN 5 +#define SDCARD_SPI_MISO_PIN 11 +#define SDCARD_SPI_MOSI_PIN 17 + +#define SDCARD_USBDRIVER_IC_JUNCTION_CTRL_NOE_PIN 1 +#define SDCARD_USBDRIVER_IC_RESET_PIN 28 +#define SDCARD_POWER_CTRL_PIN 30 + +#define ADS1293_SPI_SCK_PIN (32 + 9) +#define ADS1293_SPI_MOSI_PIN 15 +#define ADS1293_SPI_MISO_PIN 20 +#define ADS1293_SPI_CS0_PIN 3 +#define ADS1293_SPI_CS1_PIN 29 +#define ADS1293_READY_PIN 31 + +#define LINE_DET_PIN 10 + +/******************************************************************************* + * TOOLS * + *******************************************************************************/ + +/******************************************************************************* + * ADC * + *******************************************************************************/ +void ThreeLeadECG_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)); +} + +/******************************************************************************* + * BUTTON * + *******************************************************************************/ +void ThreeLeadECG_button_init() { // + nrf_gpio_cfg_sense_input(BUTTON_PIN, NRF_GPIO_PIN_NOPULL, NRF_GPIO_PIN_SENSE_LOW); +} +bool ThreeLeadECG_button_get_state() { + // 低电平有效 + return nrf_gpio_pin_read(BUTTON_PIN) == 0; +} + +/******************************************************************************* + * 蜂鸣器 * + *******************************************************************************/ +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, +}; +void ThreeLeadECG_beep_init() { + znrf_gpio_cfg_output(BEEP_PIN, NRF_GPIO_PIN_NOPULL); + nrf_gpio_pin_set(BEEP_PIN); + + APP_ERROR_CHECK(nrfx_pwm_init(&m_beep_pwm0, &m_beep_pwm0_config0, NULL)); +} +void ThreeLeadECG_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); + } +} + +/******************************************************************************* + * LED * + *******************************************************************************/ +void ThreeLeadECG_led_init() { znrf_gpio_cfg_output(LED_GREEN_PIN, NRF_GPIO_PIN_NOPULL); } +void ThreeLeadECG_led_green_set_state(bool state) { + if (state) { + nrf_gpio_pin_set(LED_GREEN_PIN); + } else { + nrf_gpio_pin_clear(LED_GREEN_PIN); + } +} + +void ThreeLeadECG_led_green_toggle(){ + nrf_gpio_pin_toggle(LED_GREEN_PIN); +} + + +/******************************************************************************* + * BATTERY * + *******************************************************************************/ +void ThreeLeadECG_battery_init() { + nrf_saadc_channel_config_t channel_config = NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(BATTERY_ADC_PIN); + channel_config.acq_time = NRF_SAADC_ACQTIME_10US; + ZERROR_CHECK(nrfx_saadc_channel_init(BATTERY_ADC_CHANNEL, &channel_config)); +} +int16_t ThreeLeadECG_battery_get_adc_val() { + int16_t val = znrf_adc_channel_read_val(BATTERY_ADC_CHANNEL); + return val; +} + +/******************************************************************************* + * SDCARD * + *******************************************************************************/ + +/** + * @brief + * + * SPI + * nand flash + * sd card + * switch + */ + +void ThreeLeadECG_sdcard_base_init() { // + /** + * @brief spi引脚切换成输入 + */ + nrf_gpio_cfg_sense_input(SDCARD_SPI_CS_PIN, NRF_GPIO_PIN_NOPULL, NRF_GPIO_PIN_NOSENSE); + nrf_gpio_cfg_sense_input(SDCARD_SPI_MISO_PIN, NRF_GPIO_PIN_NOPULL, NRF_GPIO_PIN_NOSENSE); + nrf_gpio_cfg_sense_input(SDCARD_SPI_MOSI_PIN, NRF_GPIO_PIN_NOPULL, NRF_GPIO_PIN_NOSENSE); + nrf_gpio_cfg_sense_input(SDCARD_SPI_SCK_PIN, NRF_GPIO_PIN_NOPULL, NRF_GPIO_PIN_NOSENSE); + /** + * @brief USBDRIVER_IC_RESET_PIN ctrl pin + */ + znrf_gpio_cfg_output(SDCARD_USBDRIVER_IC_RESET_PIN, NRF_GPIO_PIN_NOPULL); + nrf_gpio_pin_write(SDCARD_USBDRIVER_IC_RESET_PIN, 1); + /** + * @brief 初始化 SDCARD_USBDRIVER_IC_JUNCTION_CTRL_NOE_PIN + */ + znrf_gpio_cfg_output(SDCARD_USBDRIVER_IC_JUNCTION_CTRL_NOE_PIN, NRF_GPIO_PIN_NOPULL); + nrf_gpio_pin_write(SDCARD_USBDRIVER_IC_JUNCTION_CTRL_NOE_PIN, 0); // OE = 0 + /** + * @brief SDCARD电源控制引脚 + */ + znrf_gpio_cfg_output(SDCARD_POWER_CTRL_PIN, NRF_GPIO_PIN_NOPULL); + nrf_gpio_pin_write(SDCARD_POWER_CTRL_PIN, 0); // POWER = 0 +} +void ThreeLeadECG_sdcard_connect2_ext_usb_sdcard_driver_ic_reset() { + nrf_gpio_pin_clear(SDCARD_USBDRIVER_IC_RESET_PIN); + nrf_delay_ms(10); + nrf_gpio_pin_set(SDCARD_USBDRIVER_IC_RESET_PIN); +} +void ThreeLeadECG_sdcard_connect2_ext_usb_sdcard_driver_ic(bool connect) { + if (!connect) { + nrf_gpio_pin_clear(SDCARD_USBDRIVER_IC_JUNCTION_CTRL_NOE_PIN); + } else { + nrf_gpio_pin_set(SDCARD_USBDRIVER_IC_JUNCTION_CTRL_NOE_PIN); + } +} +void ThreeLeadECG_sdcard_flash_power_ctrl(bool power) { + if (!power) { + nrf_gpio_pin_set(SDCARD_POWER_CTRL_PIN); + } else { + nrf_gpio_pin_clear(SDCARD_POWER_CTRL_PIN); + } +} + +void ThreeLeadECG_sdcard_spi_umount() { + nrf_gpio_cfg_sense_input(SDCARD_SPI_CS_PIN, NRF_GPIO_PIN_NOPULL, NRF_GPIO_PIN_NOSENSE); + nrf_gpio_cfg_sense_input(SDCARD_SPI_MISO_PIN, NRF_GPIO_PIN_NOPULL, NRF_GPIO_PIN_NOSENSE); + nrf_gpio_cfg_sense_input(SDCARD_SPI_MOSI_PIN, NRF_GPIO_PIN_NOPULL, NRF_GPIO_PIN_NOSENSE); + nrf_gpio_cfg_sense_input(SDCARD_SPI_SCK_PIN, NRF_GPIO_PIN_NOPULL, NRF_GPIO_PIN_NOSENSE); +} + +void ThreeLeadECG_sdcard_init() { + /** + * @brief + * 0. 必要引脚初始化 + * 1. spi引脚切换成输入 + * 2. 连接flash和usbflash驱动器连接 + * <----option----> + * 4. 打开flash电源 + * + */ + ThreeLeadECG_sdcard_base_init(); // 必要引脚初始化 + // ThreeLeadECG_sdcard_spi_umount(); // + // ThreeLeadECG_sdcard_connect2_ext_usb_sdcard_driver_ic(true); + // ThreeLeadECG_sdcard_flash_power_ctrl(true); +} + +NRF_BLOCK_DEV_SDC_DEFINE(m_block_dev_sdc, // + NRF_BLOCK_DEV_SDC_CONFIG(SDC_SECTOR_SIZE, // + APP_SDCARD_CONFIG(SDCARD_SPI_MOSI_PIN, // + SDCARD_SPI_MISO_PIN, // + SDCARD_SPI_SCK_PIN, // + SDCARD_SPI_CS_PIN)), + NFR_BLOCK_DEV_INFO_CONFIG("Nordic", "SDC", "1.00")); +static FATFS fs; + +void sdcard_test_write_text() { +#define FILE_NAME "/6.TXT" + static FIL file; + uint32_t bytes_written; + static DIR dir; + static FILINFO fno; + + NRF_LOG_INFO("\r\n Listing directory: /"); + FRESULT ff_result = f_opendir(&dir, "/"); + if (ff_result) { + NRF_LOG_INFO("Directory listing failed!"); + return; + } + + do { + ff_result = f_readdir(&dir, &fno); + if (ff_result != FR_OK) { + NRF_LOG_INFO("Directory read failed."); + return; + } + + if (fno.fname[0]) { + if (fno.fattrib & AM_DIR) { + NRF_LOG_RAW_INFO(" %s", (uint32_t)fno.fname); + } else { + NRF_LOG_RAW_INFO("%9lu %s", fno.fsize, (uint32_t)fno.fname); + } + } + } while (fno.fname[0]); + NRF_LOG_RAW_INFO(""); + NRF_LOG_INFO("read from file " FILE_NAME "..."); + { + ff_result = f_open(&file, FILE_NAME, FA_READ); + if (ff_result == FR_OK) { + static char rxbuf[20] = {0}; + UINT rxsize; + ff_result = f_read(&file, rxbuf, 19, &rxsize); + if (ff_result != FR_OK) { + NRF_LOG_INFO("read failed\r\n."); + } else { + NRF_LOG_INFO("read %s(%d)", rxbuf, rxsize); + } + (void)f_close(&file); + } + } + + NRF_LOG_INFO("Writing to file " FILE_NAME "..."); + { + ff_result = f_open(&file, FILE_NAME, FA_CREATE_ALWAYS | FA_READ | FA_WRITE); + if (ff_result != FR_OK) { + NRF_LOG_INFO("Unable to open or create file: " FILE_NAME ". %d", ff_result); + return; + } + + ff_result = f_write(&file, "iflytop", sizeof("iflytop") - 1, (UINT*)&bytes_written); + if (ff_result != FR_OK) { + NRF_LOG_INFO("Write failed\r\n."); + } else { + NRF_LOG_INFO("%d bytes written.", bytes_written); + } + + (void)f_close(&file); + } +} +bool mountsuc = false; +/** + * @brief 对接 get_fattime + * @return DWORD + */ + + + +void ThreeLeadECG_sdcard_mount() { + /** + * @brief + * 1. 关闭flash电源 + * 2. 断开flash和usbflash驱动器连接 + * 3. 打开flash电源 + * 4. 初始化SPI引脚,驱动flash + */ + + nrf_gpio_pin_write(SDCARD_POWER_CTRL_PIN, 1); // 关 + nrf_gpio_pin_write(SDCARD_USBDRIVER_IC_JUNCTION_CTRL_NOE_PIN, 1); + nrf_gpio_pin_write(SDCARD_POWER_CTRL_PIN, 0); // 开 + + /** + * @brief + * 1. 初始化SPI引脚,驱动flash + */ + if (!mountsuc) { + static diskio_blkdev_t drives[] = // + {DISKIO_BLOCKDEV_CONFIG(NRF_BLOCKDEV_BASE_ADDR(m_block_dev_sdc, block_dev), NULL)}; + + diskio_blockdev_register(drives, ARRAY_SIZE(drives)); + + DSTATUS disk_state = STA_NOINIT; + for (uint32_t retries = 3; retries && disk_state; --retries) { + disk_state = disk_initialize(0); + } + if (disk_state) { + NRF_LOG_INFO("Disk initialization failed. %d", disk_state); + return; + } + NRF_LOG_INFO("Disk initialization succeeded."); + + FRESULT ff_result; + // ff_result = f_mkfs("0:", FM_FAT, 4096, NULL, 0); + // if (ff_result) { + // NRF_LOG_INFO("mkfs failed. %d",ff_result); + // return; + // } + + ff_result = f_mount(&fs, "", 1); + if (ff_result) { + NRF_LOG_INFO("Mount failed."); + return; + } + ZLOGI("Mount success"); + + uint32_t blocks_per_mb = (1024uL * 1024uL) / m_block_dev_sdc.block_dev.p_ops->geometry(&m_block_dev_sdc.block_dev)->blk_size; + uint32_t capacity = m_block_dev_sdc.block_dev.p_ops->geometry(&m_block_dev_sdc.block_dev)->blk_count / blocks_per_mb; + NRF_LOG_INFO("Capacity: %d MB", capacity); + + mountsuc = true; + } + + sdcard_test_write_text(); +} +void ThreeLeadECG_sdcard_umount() { + /** + * @brief + * 1. 卸载磁盘 + * 2. 失能SPI引脚 + * 3. SPI引脚切换成输入高阻 + * 4. 关闭flash电源 + * 5. 连接flash和usbflash驱动器连接 + * <----option----> + * 6. 打开flash电源(硬件改版后,flash的电可以从USB上取,就不需要再打开flash电源了) + */ + // umount + f_mount(NULL, "", 1); + disk_uninitialize(0); + ThreeLeadECG_sdcard_spi_umount(); + + nrf_gpio_pin_write(SDCARD_POWER_CTRL_PIN, 1); // 关 + nrf_gpio_pin_write(SDCARD_USBDRIVER_IC_JUNCTION_CTRL_NOE_PIN, 0); + nrf_delay_ms(100); + nrf_gpio_pin_write(SDCARD_POWER_CTRL_PIN, 0); // 开 + + nrf_gpio_pin_write(SDCARD_USBDRIVER_IC_RESET_PIN, 0); + nrf_delay_ms(10); + nrf_gpio_pin_write(SDCARD_USBDRIVER_IC_RESET_PIN, 1); +} + +/******************************************************************************* + * ecg * + *******************************************************************************/ + +static const nrf_drv_spi_t spi = NRF_DRV_SPI_INSTANCE(2); /**< SPI instance. */ + +static ads1293_t m_ads1293_0; // U2 +static ads1293_t m_ads1293_1; // U3 + +void ads1293_spi_tx_rx_0(uint8_t* tx, uint8_t* rx, uint8_t len) { + nrf_gpio_pin_clear(ADS1293_SPI_CS0_PIN); + nrf_drv_spi_transfer(&spi, tx, len, rx, len); + nrf_gpio_pin_set(ADS1293_SPI_CS0_PIN); +} +void ads1293_spi_tx_rx_1(uint8_t* tx, uint8_t* rx, uint8_t len) { + nrf_gpio_pin_clear(ADS1293_SPI_CS1_PIN); + nrf_drv_spi_transfer(&spi, tx, len, rx, len); + nrf_gpio_pin_set(ADS1293_SPI_CS1_PIN); +} +void ads1293_spi_writereg_and_check(ads1293_t* ads, uint8_t addr, uint8_t data) { + uint8_t readbak = 0; + // readonly add + if (addr == 0x19 || addr == 0x1a || addr == 0x1b || addr == 0x1c || addr == 0x40 || addr == 0x30) { + return; + } + ads1293_spi_writereg_and_readbak(ads, addr, data, &readbak); + if (readbak != data) { + ZLOGE("ads_%d write %x failed,w:%x readbak:%x", ads->id, addr, data, readbak); + } +} +#include "ads_cfg.h" +#include "TI_ADS1293_register_settings.h" +void ThreeLeadECG_ecg_reg_config() { + for (uint16_t i = 0; i < ZARRAY_SIZE(ads0cfg); i++) { + ads1293_spi_writereg_and_check(&m_ads1293_0, ads0cfg[i].add, ads0cfg[i].data); + } + for (uint16_t i = 0; i < ZARRAY_SIZE(ads1cfg); i++) { + ads1293_spi_writereg_and_check(&m_ads1293_1, ads1cfg[i].add, ads1cfg[i].data); + } + + // ads1293_spi_writereg_and_check(&m_ads1293_1,TI_ADS1293_CONFIG_REG, TI_ADS1293_CONFIG_REG_VALUE); + // ads1293_spi_writereg_and_check(&m_ads1293_1,TI_ADS1293_FLEX_CH1_CN_REG, TI_ADS1293_FLEX_CH1_CN_REG_VALUE); + // ads1293_spi_writereg_and_check(&m_ads1293_1,TI_ADS1293_FLEX_CH2_CN_REG, TI_ADS1293_FLEX_CH2_CN_REG_VALUE); + // ads1293_spi_writereg_and_check(&m_ads1293_1,TI_ADS1293_FLEX_CH3_CN_REG, TI_ADS1293_FLEX_CH3_CN_REG_VALUE); + // ads1293_spi_writereg_and_check(&m_ads1293_1,TI_ADS1293_FLEX_PACE_CN_REG, TI_ADS1293_FLEX_PACE_CN_REG_VALUE); + // ads1293_spi_writereg_and_check(&m_ads1293_1,TI_ADS1293_FLEX_VBAT_CN_REG, TI_ADS1293_FLEX_VBAT_CN_REG_VALUE); + // ads1293_spi_writereg_and_check(&m_ads1293_1,TI_ADS1293_LOD_CN_REG, TI_ADS1293_LOD_CN_REG_VALUE); + // ads1293_spi_writereg_and_check(&m_ads1293_1,TI_ADS1293_LOD_EN_REG, TI_ADS1293_LOD_EN_REG_VALUE); + // ads1293_spi_writereg_and_check(&m_ads1293_1,TI_ADS1293_LOD_CURRENT_REG, TI_ADS1293_LOD_CURRENT_REG_VALUE); + // ads1293_spi_writereg_and_check(&m_ads1293_1,TI_ADS1293_LOD_AC_CN_REG, TI_ADS1293_LOD_AC_CN_REG_VALUE); + // ads1293_spi_writereg_and_check(&m_ads1293_1,TI_ADS1293_CMDET_EN_REG, TI_ADS1293_CMDET_EN_REG_VALUE); + // ads1293_spi_writereg_and_check(&m_ads1293_1,TI_ADS1293_CMDET_CN_REG, TI_ADS1293_CMDET_CN_REG_VALUE); + // ads1293_spi_writereg_and_check(&m_ads1293_1,TI_ADS1293_RLD_CN_REG, TI_ADS1293_RLD_CN_REG_VALUE); + // ads1293_spi_writereg_and_check(&m_ads1293_1,TI_ADS1293_WILSON_EN1_REG, TI_ADS1293_WILSON_EN1_REG_VALUE); + // ads1293_spi_writereg_and_check(&m_ads1293_1,TI_ADS1293_WILSON_EN2_REG, TI_ADS1293_WILSON_EN2_REG_VALUE); + // ads1293_spi_writereg_and_check(&m_ads1293_1,TI_ADS1293_WILSON_EN3_REG, TI_ADS1293_WILSON_EN3_REG_VALUE); + // ads1293_spi_writereg_and_check(&m_ads1293_1,TI_ADS1293_WILSON_CN_REG, TI_ADS1293_WILSON_CN_REG_VALUE); + + // ads1293_spi_writereg_and_check(&m_ads1293_1,TI_ADS1293_REF_CN_REG, TI_ADS1293_REF_CN_REG_VALUE); + + // ads1293_spi_writereg_and_check(&m_ads1293_1,TI_ADS1293_OSC_CN_REG, TI_ADS1293_OSC_CN_REG_VALUE); + // ads1293_spi_writereg_and_check(&m_ads1293_1,TI_ADS1293_AFE_RES_REG, TI_ADS1293_AFE_RES_REG_VALUE); + // ads1293_spi_writereg_and_check(&m_ads1293_1,TI_ADS1293_AFE_SHDN_CN_REG, TI_ADS1293_AFE_SHDN_CN_REG_VALUE); + // ads1293_spi_writereg_and_check(&m_ads1293_1,TI_ADS1293_AFE_FAULT_CN_REG, TI_ADS1293_AFE_FAULT_CN_REG_VALUE); + // ads1293_spi_writereg_and_check(&m_ads1293_1,TI_ADS1293_AFE_DITHER_EN_REG, TI_ADS1293_AFE_DITHER_EN_REG_VALUE); + // ads1293_spi_writereg_and_check(&m_ads1293_1,TI_ADS1293_AFE_PACE_CN_REG, TI_ADS1293_AFE_PACE_CN_REG_VALUE); + + // ads1293_spi_writereg_and_check(&m_ads1293_1,TI_ADS1293_R2_RATE_REG, TI_ADS1293_R2_RATE_REG_VALUE); + // ads1293_spi_writereg_and_check(&m_ads1293_1,TI_ADS1293_R3_RATE1_REG, TI_ADS1293_R3_RATE1_REG_VALUE); + // ads1293_spi_writereg_and_check(&m_ads1293_1,TI_ADS1293_R3_RATE2_REG, TI_ADS1293_R3_RATE2_REG_VALUE); + // ads1293_spi_writereg_and_check(&m_ads1293_1,TI_ADS1293_R3_RATE3_REG, TI_ADS1293_R3_RATE3_REG_VALUE); + // ads1293_spi_writereg_and_check(&m_ads1293_1,TI_ADS1293_P_DRATE_REG, TI_ADS1293_P_DRATE_REG_VALUE); + // ads1293_spi_writereg_and_check(&m_ads1293_1,TI_ADS1293_DIS_EFILTER_REG, TI_ADS1293_DIS_EFILTER_REG_VALUE); + // ads1293_spi_writereg_and_check(&m_ads1293_1,TI_ADS1293_DRDYB_SRC_REG, TI_ADS1293_DRDYB_SRC_REG_VALUE); + // ads1293_spi_writereg_and_check(&m_ads1293_1,TI_ADS1293_SYNCOUTB_SRC_REG, TI_ADS1293_SYNCOUTB_SRC_REG_VALUE); + // ads1293_spi_writereg_and_check(&m_ads1293_1,TI_ADS1293_MASK_DRDYB_REG, TI_ADS1293_MASK_DRDYB_REG_VALUE); + // ads1293_spi_writereg_and_check(&m_ads1293_1,TI_ADS1293_MASK_ERR_REG, TI_ADS1293_MASK_ERR_REG_VALUE); + // ads1293_spi_writereg_and_check(&m_ads1293_1,TI_ADS1293_ALARM_FILTER_REG, TI_ADS1293_ALARM_FILTER_REG_VALUE); + // ads1293_spi_writereg_and_check(&m_ads1293_1,TI_ADS1293_CH_CNFG_REG, TI_ADS1293_CH_CNFG_REG_VALUE); +} + +void ThreeLeadECG_ads1293_start_convert() { + ads1293_spi_writereg(&m_ads1293_0, TI_ADS1293_CONFIG_REG, 0x01); + ads1293_spi_writereg(&m_ads1293_1, TI_ADS1293_CONFIG_REG, 0x01); +} +void ThreeLeadECG_ecg_init() { + nrf_drv_spi_config_t spi_config = NRF_DRV_SPI_DEFAULT_CONFIG; + spi_config.ss_pin = NRF_DRV_SPI_PIN_NOT_USED; // NRF_DRV_SPI_PIN_NOT_USED + spi_config.miso_pin = ADS1293_SPI_MISO_PIN; + spi_config.mosi_pin = ADS1293_SPI_MOSI_PIN; + spi_config.sck_pin = ADS1293_SPI_SCK_PIN; + spi_config.frequency = NRF_DRV_SPI_FREQ_8M; + spi_config.mode = NRF_DRV_SPI_MODE_3; + // spi_config.mode = + ZERROR_CHECK(nrf_drv_spi_init(&spi, &spi_config, NULL, NULL)); + + znrf_gpio_cfg_output(ADS1293_SPI_CS0_PIN, NRF_GPIO_PIN_NOPULL); + znrf_gpio_cfg_output(ADS1293_SPI_CS1_PIN, NRF_GPIO_PIN_NOPULL); + nrf_gpio_cfg_input(ADS1293_READY_PIN, NRF_GPIO_PIN_PULLUP); + + nrf_gpio_pin_set(ADS1293_SPI_CS0_PIN); + nrf_gpio_pin_set(ADS1293_SPI_CS1_PIN); + + m_ads1293_0.spi_tx_rx = ads1293_spi_tx_rx_0; + m_ads1293_0.id = 0; + m_ads1293_1.spi_tx_rx = ads1293_spi_tx_rx_1; + m_ads1293_1.id = 1; + + ads1293_spi_init(&m_ads1293_0, ads1293_spi_tx_rx_0); + ads1293_spi_init(&m_ads1293_1, ads1293_spi_tx_rx_1); + + uint8_t revid = ads1293_spi_readreg(&m_ads1293_0, TI_ADS1293_REVID_REG); + NRF_LOG_INFO("ads1293_0 revid: %d", revid); + revid = ads1293_spi_readreg(&m_ads1293_1, TI_ADS1293_REVID_REG); + NRF_LOG_INFO("ads1293_1 revid: %d", revid); + + ThreeLeadECG_ecg_reg_config(); + ThreeLeadECG_ads1293_start_convert(); +} +uint32_t ThreeLeadECG_ready_pin_state_get() { return nrf_gpio_pin_read(ADS1293_READY_PIN); } + +uint32_t ThreeLeadECG_ads1293_init() {} + +void ThreeLeadECG_ads1293_get_lod_state(uint16_t* state) { // + uint8_t lod0 = ads1293_read_error_lod(&m_ads1293_0); + uint8_t lod1 = ads1293_read_error_lod(&m_ads1293_1); + *state = (lod0) | (lod1 << 8); +} + +void ThreeLeadECG_ads1293_sample_all(uint32_t* sample0, uint32_t* sample1, uint32_t* sample2, uint32_t* sample10, uint32_t* sample11, uint32_t* sample12) { + // *sample0 + ads1293_read_ecg(&m_ads1293_0, 1, sample0); + ads1293_read_ecg(&m_ads1293_0, 2, sample1); + ads1293_read_ecg(&m_ads1293_0, 3, sample2); + // *sample1 + ads1293_read_ecg(&m_ads1293_1, 1, sample10); + ads1293_read_ecg(&m_ads1293_1, 2, sample11); + ads1293_read_ecg(&m_ads1293_1, 3, sample12); +} +void ThreeLeadECG_ads1293_sample(uint32_t* sample0, uint32_t* sample1, uint32_t* sample2) { + // *sample0 + ads1293_read_ecg(&m_ads1293_0, 1, sample0); + ads1293_read_ecg(&m_ads1293_1, 1, sample1); + ads1293_read_ecg(&m_ads1293_1, 2, sample2); +} + +void ThreeLeadECG_LineInputDet_init() { + // LINE_DET_PIN + nrf_gpio_cfg_input(LINE_DET_PIN, NRF_GPIO_PIN_PULLUP); +} +uint32_t ThreeLeadECG_LineInputDet_get_state() { return nrf_gpio_pin_read(LINE_DET_PIN); } diff --git a/app/src/bak/three_lead_board.h b/app/src/bak/three_lead_board.h new file mode 100644 index 0000000..e630954 --- /dev/null +++ b/app/src/bak/three_lead_board.h @@ -0,0 +1,56 @@ +#pragma once +#include +#define VERSION 1 +#define MANUFACTURER_NAME "iflytop" +#define BLE_NAME "iflytop_test" + +/******************************************************************************* + * INCLUDE * + *******************************************************************************/ +#include + +/******************************************************************************* + * basic * + *******************************************************************************/ +void ThreeLeadECG_adc_module_init(); +/******************************************************************************* + * BUTTON * + *******************************************************************************/ +void ThreeLeadECG_button_init(); +bool ThreeLeadECG_button_get_state(); +/******************************************************************************* + * 铚傞福鍣? * + *******************************************************************************/ +void ThreeLeadECG_beep_init(); +void ThreeLeadECG_beep_set_state(bool state); + +/******************************************************************************* + * LED * + *******************************************************************************/ +void ThreeLeadECG_led_init(); +void ThreeLeadECG_led_green_set_state(bool state); +void ThreeLeadECG_led_green_toggle(); +/******************************************************************************* + * BATTERY * + *******************************************************************************/ +void ThreeLeadECG_battery_init(); +int16_t ThreeLeadECG_battery_get_adc_val(); +/******************************************************************************* + * SDCARD * + *******************************************************************************/ +void ThreeLeadECG_sdcard_connect2_ext_usb_sdcard_driver_ic_reset(); +void ThreeLeadECG_sdcard_init(); +void ThreeLeadECG_sdcard_mount(); +void ThreeLeadECG_sdcard_umount(); +/******************************************************************************* + * ECG * + *******************************************************************************/ +void ThreeLeadECG_ecg_init(); +uint32_t ThreeLeadECG_ready_pin_state_get(); +void ThreeLeadECG_ads1293_get_lod_state(uint16_t* state); + +// +void ThreeLeadECG_LineInputDet_init(); +uint32_t ThreeLeadECG_LineInputDet_get_state(); +void ThreeLeadECG_ads1293_sample(uint32_t* sample0, uint32_t* sample1, uint32_t* sample2); +void ThreeLeadECG_ads1293_sample_all(uint32_t* sample0, uint32_t* sample1, uint32_t* sample2, uint32_t* sample10, uint32_t* sample11, uint32_t* sample12); \ No newline at end of file diff --git a/app/src/basic/ads1293/ads1293.c b/app/src/basic/ads1293/ads1293.c index 5e76713..8016b43 100644 --- a/app/src/basic/ads1293/ads1293.c +++ b/app/src/basic/ads1293/ads1293.c @@ -85,6 +85,17 @@ void ads1293_read_ecg(ads1293_t* ads, uint32_t ch, uint32_t* data) { *data = ((uint32_t)readbak[0] << 16) + ((uint32_t)readbak[1] << 8) + ((uint32_t)readbak[2] << 0); } +void ads1293_read_ecgs(ads1293_t* ads, uint32_t* data /*3*/) { + uint8_t add = 0; + add = TI_ADS1293_DATA_CH1_ECG_H_REG; + uint8_t readbak[9] = {0}; + ads1293_spi_autoinc_readreg(ads, add, readbak, 9); + + data[0] = ((uint32_t)readbak[0] << 16) + ((uint32_t)readbak[1] << 8) + ((uint32_t)readbak[2] << 0); + data[1] = ((uint32_t)readbak[3] << 16) + ((uint32_t)readbak[4] << 8) + ((uint32_t)readbak[5] << 0); + data[2] = ((uint32_t)readbak[6] << 16) + ((uint32_t)readbak[7] << 8) + ((uint32_t)readbak[8] << 0); +} + void ads1293_start_conversion(ads1293_t* ads) { uint8_t data = 0; data = 0x01; @@ -96,4 +107,15 @@ void ads1293_start_power_off(ads1293_t* ads) { ads1293_spi_writereg(ads, TI_ADS1293_CONFIG_REG, data); } -uint8_t ads1293_read_error_lod(ads1293_t* ads) { return ads1293_spi_readreg(ads, TI_ADS1293_ERROR_LOD_REG); } \ No newline at end of file +uint8_t ads1293_read_error_lod(ads1293_t* ads) { return ads1293_spi_readreg(ads, TI_ADS1293_ERROR_LOD_REG); } + +void ads1293_start_conversion(ads1293_t* ads) { + uint8_t data = 0; + data = 0x01; + ads1293_spi_writereg(ads, TI_ADS1293_CONFIG_REG, data); +} +void ads1293_stop_conversion(ads1293_t* ads){ + uint8_t data = 0; + data = 0x04; + ads1293_spi_writereg(ads, TI_ADS1293_CONFIG_REG, data); +} \ No newline at end of file diff --git a/app/src/basic/ads1293/ads1293.h b/app/src/basic/ads1293/ads1293.h index 107e102..3f5ddbc 100644 --- a/app/src/basic/ads1293/ads1293.h +++ b/app/src/basic/ads1293/ads1293.h @@ -118,7 +118,12 @@ void ads1293_spi_autoinc_writereg(ads1293_t* ads, uint8_t addr, uint8_t* data, u void ads1293_spi_autoinc_readreg(ads1293_t* ads, uint8_t addr, uint8_t* data, uint8_t len); void ads1293_spi_stream_readreg(ads1293_t* ads, uint8_t* data, uint8_t len); -void ads1293_read_ecg(ads1293_t* ads, uint32_t ch, uint32_t* data); +void ads1293_read_ecg(ads1293_t* ads, uint32_t ch, uint32_t* data); +void ads1293_read_ecgs(ads1293_t* ads, uint32_t* data /*3*/); + uint8_t ads1293_read_error_lod(ads1293_t* ads); +void ads1293_start_conversion(ads1293_t* ads); +void ads1293_stop_conversion(ads1293_t* ads); + #endif // HEADER_FILE_TI_ADS1293_H diff --git a/app/src/basic/config.h b/app/src/basic/config.h index 48cec86..a4438b1 100644 --- a/app/src/basic/config.h +++ b/app/src/basic/config.h @@ -19,4 +19,9 @@ #define SAMPLE_PRECISION 12 #define AUTOMATIC_SLEEP_TIME 15000 -#define SAMPLE_MIN_TIME_S (30.0) \ No newline at end of file +#define SAMPLE_MIN_TIME_S (30.0) + +/******************************************************************************* + * 优先级 * + *******************************************************************************/ + diff --git a/app/src/ble_cmd_process_service.c b/app/src/ble_cmd_process_service.c deleted file mode 100644 index a2485a4..0000000 --- a/app/src/ble_cmd_process_service.c +++ /dev/null @@ -1,455 +0,0 @@ -#include "ble_cmd_process_service.h" - -#include "basic/device_info_mgr.h" -#include "basic/heart_rate_sensor_protocol.h" -#include "basic/zble_module.h" -#include "basic/zdatachannel_service.h" -#include "config.h" -#include "one_conduction_board.h" -#include "sample_data_manager.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) { - 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(rxheader->data, len - sizeof(ify_hrs_packet_t)); - - 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.sensor0_pos = (!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/ble_cmd_process_service.h b/app/src/ble_cmd_process_service.h deleted file mode 100644 index d6e039d..0000000 --- a/app/src/ble_cmd_process_service.h +++ /dev/null @@ -1,16 +0,0 @@ -#pragma once - -#include "basic/heart_rate_sensor_protocol.h" -#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/board/TI_ADS1293_register_settings.h b/app/src/board/TI_ADS1293_register_settings.h deleted file mode 100644 index e95e613..0000000 --- a/app/src/board/TI_ADS1293_register_settings.h +++ /dev/null @@ -1,101 +0,0 @@ -//---------------------------------------------------------------------------- -// Description: This file contains the initialization values for the -// ADS1293 registers. -// -// MSP430/ADS1293 Interface Code Library v1.0 -// -// Vishy Natarajan -// Texas Instruments Inc. -// April 2013 -// Built with IAR Embedded Workbench Version: 5.5x -//------------------------------------------------------------------------------ -// Change Log: -//------------------------------------------------------------------------------ -// Version: 1.00 -// Comments: Initial Release Version -//------------------------------------------------------------------------------ -#ifndef HEADER_FILE_TI_ADS1293_REGISTER_SETTINGS_H - -#define HEADER_FILE_TI_ADS1293_REGISTER_SETTINGS_H - -/************************************************************ -* TI ADS1293 REGISTER SET INITIALIZATION VALUES -************************************************************/ - -#define TI_ADS1293_CONFIG_REG_VALUE (0x00) /* Main Configuration */ - -#define TI_ADS1293_FLEX_CH1_CN_REG_VALUE (0x0A) /* Flex Routing Swich Control for Channel 1 */ -#define TI_ADS1293_FLEX_CH2_CN_REG_VALUE (0x1A) /* Flex Routing Swich Control for Channel 2 */ -#define TI_ADS1293_FLEX_CH3_CN_REG_VALUE (0x00) /* Flex Routing Swich Control for Channel 3 */ -#define TI_ADS1293_FLEX_PACE_CN_REG_VALUE (0x00) /* Flex Routing Swich Control for Pace Channel */ -#define TI_ADS1293_FLEX_VBAT_CN_REG_VALUE (0x00) /* Flex Routing Swich Control for Battery Monitoriing */ - -#define TI_ADS1293_LOD_CN_REG_VALUE (0x08) /* Lead Off Detect Control */ -#define TI_ADS1293_LOD_EN_REG_VALUE (0x00) /* Lead Off Detect Enable */ -#define TI_ADS1293_LOD_CURRENT_REG_VALUE (0x00) /* Lead Off Detect Current */ -#define TI_ADS1293_LOD_AC_CN_REG_VALUE (0x00) /* AC Lead Off Detect Current */ - -#define TI_ADS1293_CMDET_EN_REG_VALUE (0x07) /* Common Mode Detect Enable */ -#define TI_ADS1293_CMDET_CN_REG_VALUE (0x00) /* Commond Mode Detect Control */ -#define TI_ADS1293_RLD_CN_REG_VALUE (0x04) /* Right Leg Drive Control */ - -#define TI_ADS1293_WILSON_EN1_REG_VALUE (0x00) /* Wilson Reference Input one Selection */ -#define TI_ADS1293_WILSON_EN2_REG_VALUE (0x00) /* Wilson Reference Input two Selection */ -#define TI_ADS1293_WILSON_EN3_REG_VALUE (0x00) /* Wilson Reference Input three Selection */ -#define TI_ADS1293_WILSON_CN_REG_VALUE (0x00) /* Wilson Reference Input Control */ - -#define TI_ADS1293_REF_CN_REG_VALUE (0x00) /* Internal Reference Voltage Control */ - -#define TI_ADS1293_OSC_CN_REG_VALUE (0x04) /* Clock Source and Output Clock Control */ - -#define TI_ADS1293_AFE_RES_REG_VALUE (0x00) /* Analog Front-End Frequency and Resolution */ -#define TI_ADS1293_AFE_SHDN_CN_REG_VALUE (0x00) /* Analog Front-End Shutdown Control */ -#define TI_ADS1293_AFE_FAULT_CN_REG_VALUE (0x00) /* Analog Front-End Fault Detection Control */ -#define TI_ADS1293_AFE_DITHER_EN_REG_VALUE (0x00) /* Enable Dithering in Signma-Delta */ -#define TI_ADS1293_AFE_PACE_CN_REG_VALUE (0x05) /* Analog Pace Channel Output Routing Control */ - -//#define TI_ADS1293_ERROR_LOD_REG_VALUE (0x00) /* Lead Off Detect Error Status */ -//#define TI_ADS1293_ERROR_STATUS_REG_VALUE (0x72) /* Other Error Status */ -//#define TI_ADS1293_ERROR_RANGE1_REG_VALUE (0x12) /* Channel 1 Amplifier Out of Range Status */ -//#define TI_ADS1293_ERROR_RANGE2_REG_VALUE (0x12) /* Channel 1 Amplifier Out of Range Status */ -//#define TI_ADS1293_ERROR_RANGE3_REG_VALUE (0x36) /* Channel 1 Amplifier Out of Range Status */ -//#define TI_ADS1293_ERROR_SYNC_REG_VALUE (0x00) /* Synchronization Error */ - - -#define TI_ADS1293_R2_RATE_REG_VALUE (0x02) /* R2 Decimation Rate */ -#define TI_ADS1293_R3_RATE1_REG_VALUE (0x02) /* R3 Decimation Rate for Channel 1 */ -#define TI_ADS1293_R3_RATE2_REG_VALUE (0x02) /* R3 Decimation Rate for Channel 2 */ -#define TI_ADS1293_R3_RATE3_REG_VALUE (0x02) /* R3 Decimation Rate for Channel 3 */ -#define TI_ADS1293_P_DRATE_REG_VALUE (0x00) /* 2x Pace Data Rate for all channels */ -#define TI_ADS1293_DIS_EFILTER_REG_VALUE (0x00) /* ECG Filters Disabled */ -#define TI_ADS1293_DRDYB_SRC_REG_VALUE (0x08) /* Data Ready Pin Source */ -#define TI_ADS1293_SYNCOUTB_SRC_REG_VALUE (0x00) /* Sync Out Pin Source */ -#define TI_ADS1293_MASK_DRDYB_REG_VALUE (0x00) /* Optional Mask Control for DRDYB Output */ -#define TI_ADS1293_MASK_ERR_REG_VALUE (0x00) /* Mask Error on ALARMB Pin */ - -#define TI_ADS1293_ALARM_FILTER_REG_VALUE (0x33) /* Digital Filter for Analog Alarm Signals */ -#define TI_ADS1293_CH_CNFG_REG_VALUE (0x30) /* Configure Channel for Loop Read Back Mode */ - -//#define TI_ADS1293_DATA_STATUS_REG_VALUE (0x00) /* ECG and Pace Data Ready Status */ -//#define TI_ADS1293_DATA_CH1_PACE_H_REG_VALUE (0x00) /* Channel1 Pace Data High [15:8] */ -//#define TI_ADS1293_DATA_CH1_PACE_L_REG_VALUE (0x00) /* Channel1 Pace Data Low [7:0] */ -//#define TI_ADS1293_DATA_CH2_PACE_H_REG_VALUE (0x00) /* Channel2 Pace Data High [15:8] */ -//#define TI_ADS1293_DATA_CH2_PACE_L_REG_VALUE (0x00) /* Channel2 Pace Data Low [7:0] */ -//#define TI_ADS1293_DATA_CH3_PACE_H_REG_VALUE (0x00) /* Channel3 Pace Data High [15:8] */ -//#define TI_ADS1293_DATA_CH3_PACE_L_REG_VALUE (0x00) /* Channel3 Pace Data Low [7:0] */ -//#define TI_ADS1293_DATA_CH1_ECG_H_REG_VALUE (0x00) /* Channel1 ECG Data High [23:16] */ -//#define TI_ADS1293_DATA_CH1_ECG_M_REG_VALUE (0x00) /* Channel1 ECG Data Medium [15:8] */ -//#define TI_ADS1293_DATA_CH1_ECG_L_REG_VALUE (0x00) /* Channel1 ECG Data Low [7:0] */ -//#define TI_ADS1293_DATA_CH2_ECG_H_REG_VALUE (0x00) /* Channel2 ECG Data High [23:16] */ -//#define TI_ADS1293_DATA_CH2_ECG_M_REG_VALUE (0x00) /* Channel2 ECG Data Medium [15:8] */ -//#define TI_ADS1293_DATA_CH2_ECG_L_REG_VALUE (0x00) /* Channel2 ECG Data Low [7:0] */ -//#define TI_ADS1293_DATA_CH3_ECG_H_REG_VALUE (0x00) /* Channel3 ECG Data High [23:16] */ -//#define TI_ADS1293_DATA_CH3_ECG_M_REG_VALUE (0x00) /* Channel3 ECG Data Medium [15:8] */ -//#define TI_ADS1293_DATA_CH3_ECG_L_REG_VALUE (0x00) /* Channel3 ECG Data Low [7:0] */ - -#define TI_ADS1293_REVID_REG_VALUE (0x40) /* Revision ID */ -#define TI_ADS1293_DATA_LOOP_REG_VALUE (0x50) /* Loop Read Back Address */ - -// Useful definitions -#define ADS1293_START_CONV (0x01) // Start Conversion Bit -#endif \ No newline at end of file diff --git a/app/src/board/ads_cfg.h b/app/src/board/ads_cfg.h deleted file mode 100644 index 2d97f6e..0000000 --- a/app/src/board/ads_cfg.h +++ /dev/null @@ -1,148 +0,0 @@ -#pragma once -#include - -typedef struct { - uint8_t add; - uint8_t data; -} adscfg_t; -#if 1 -static adscfg_t ads0cfg[] = { - {0x00, 0x00}, // - {0x01, 0x0a}, // - {0x02, 0x1a}, // - {0x03, 0x00}, // - {0x04, 0x00}, // - {0x05, 0x00}, // - {0x06, 0x04}, // - {0x07, 0x0f}, // - {0x08, 0xff}, // - {0x09, 0x00}, // - {0x0a, 0x07}, // - {0x0b, 0x00}, // - {0x0c, 0x04}, // - {0x0d, 0x00}, // - {0x0e, 0x00}, // - {0x0f, 0x00}, // - {0x10, 0x00}, // - {0x11, 0x00}, // - {0x12, 0x04}, // - {0x13, 0x00}, // - {0x14, 0x00}, // - {0x15, 0x00}, // - {0x16, 0x00}, // - {0x17, 0x05}, // - {0x18, 0x00}, // - {0x19, 0x00}, // - {0x1a, 0x00}, // - {0x1b, 0x00}, // - {0x1c, 0x00}, // - {0x1d, 0x00}, // - {0x21, 0x02}, // - {0x22, 0x02}, // - {0x23, 0x02}, // - {0x24, 0x02}, // - {0x25, 0x00}, // - {0x26, 0x00}, // - {0x27, 0x08}, // - {0x28, 0x00}, // - {0x29, 0x00}, // - {0x2a, 0x00}, // - {0x2b, 0x00}, // - {0x2c, 0x00}, // - {0x2d, 0x00}, // - {0x2e, 0x33}, // - {0x2f, 0x30}, // - {0x30, 0x00}, // - {0x31, 0x00}, // - {0x32, 0x00}, // - {0x33, 0x00}, // - {0x34, 0x00}, // - {0x35, 0x00}, // - {0x36, 0x00}, // - {0x37, 0x00}, // - {0x38, 0x00}, // - {0x39, 0x00}, // - {0x3a, 0x00}, // - {0x3b, 0x00}, // - {0x3c, 0x00}, // - {0x3d, 0x00}, // - {0x3e, 0x00}, // - {0x3f, 0x00}, // - {0x40, 0xff}, // - {0x50, 0x00}, // - {0x60, 0x00}, // - {0x62, 0x00}, // -}; - -static adscfg_t ads1cfg[] = { - {0x00, 0x00}, // - {0x01, 0x0c}, // - {0x02, 0x14}, // - {0x03, 0x04}, // - {0x04, 0x00}, // - {0x05, 0x00}, // - {0x06, 0x02}, // - {0x07, 0x0f}, // - {0x08, 0x13}, // - {0x09, 0x01}, // - {0x0a, 0x0f}, // - {0x0b, 0x00}, // - {0x0c, 0x00}, // - {0x0d, 0x00}, // - {0x0e, 0x00}, // - {0x0f, 0x00}, // - {0x10, 0x01}, // - - {0x11, 0x00}, // - {0x12, 0x07}, // - {0x13, 0x00}, // - {0x14, 0x00}, // - {0x15, 0x00}, // - {0x16, 0x00}, // - {0x17, 0x05}, // - {0x18, 0x00}, // - {0x19, 0x00}, // - {0x1a, 0x00}, // - {0x1b, 0x00}, // - {0x1c, 0x00}, // - {0x1d, 0x00}, // - {0x21, 0x02}, // - {0x22, 0x02}, // - {0x23, 0x02}, // - {0x24, 0x02}, // - - {0x25, 0x00}, // - {0x26, 0x00}, // - {0x27, 0x08}, // - {0x28, 0x08}, // - {0x29, 0x00}, // - {0x2a, 0x00}, // - {0x2b, 0x00}, // - {0x2c, 0x00}, // - {0x2d, 0x00}, // - {0x2e, 0x33}, // - {0x2f, 0x30}, // - {0x30, 0x00}, // - {0x31, 0x00}, // - {0x32, 0x00}, // - {0x33, 0x00}, // - {0x34, 0x00}, // - {0x35, 0x00}, // - - {0x36, 0x00}, // - {0x37, 0x00}, // - {0x38, 0x00}, // - {0x39, 0x00}, // - {0x3a, 0x00}, // - {0x3b, 0x00}, // - {0x3c, 0x00}, // - {0x3d, 0x00}, // - {0x3e, 0x00}, // - {0x3f, 0x00}, // - {0x40, 0xff}, // - {0x50, 0x00}, // - {0x60, 0x00}, // - {0x62, 0x00}, // - -}; -#endif \ No newline at end of file diff --git a/app/src/board/board.c b/app/src/board/board.c new file mode 100644 index 0000000..e69de29 diff --git a/app/src/board/board.h b/app/src/board/board.h new file mode 100644 index 0000000..28f4bb0 --- /dev/null +++ b/app/src/board/board.h @@ -0,0 +1,61 @@ +#pragma once + +/******************************************************************************* + * ADS * + *******************************************************************************/ + +#define ADS1293_SPI_SCK_PIN (32 + 9) +#define ADS1293_SPI_MOSI_PIN 15 +#define ADS1293_SPI_MISO_PIN 20 +#define ADS1293_SPI_CS0_PIN 3 +#define ADS1293_SPI_CS1_PIN 29 +#define ADS1293_READY_PIN 31 +#define LINE_DET_PIN 10 + +/** + * @brief SDCARD + */ +#define SDCARD_SPI_SCK_PIN 4 // SDCARD SCK +#define SDCARD_SPI_CS_PIN 5 // SDCARD CS +#define SDCARD_SPI_MISO_PIN 11 // SDCARD MISO +#define SDCARD_SPI_MOSI_PIN 17 // SDCARD MOSI + +#define SDCARD_USBDRIVER_IC_JUNCTION_CTRL_NOE_PIN 1 // flash连接控制引脚 +#define SDCARD_USBDRIVER_IC_RESET_PIN 28 // flash复位引脚 +#define SDCARD_POWER_CTRL_PIN 30 // flash供电控制引脚 + +/******************************************************************************* + * 外设分配 * + *******************************************************************************/ +#define ADS1293_SPI_INSTANCE 2 +#define BEEP_PWM_INSTANCE 0 +#define BATTERY_ADC_CHANNEL 1 // 不重复即可 + +/******************************************************************************* + * LIGHT * + *******************************************************************************/ + +#define LED_GREEN_PIN 9 + +/******************************************************************************* + * 按键 * + *******************************************************************************/ +#define BUTTON_PIN 0 + +/******************************************************************************* + * 蜂鸣器 * + *******************************************************************************/ +#define BEEP_PIN 18 + +/******************************************************************************* + * 电池电量 * + *******************************************************************************/ +#define BATTERY_ADC_PIN NRF_SAADC_INPUT_AIN0 + +/******************************************************************************* + * 应用程序配置 * + *******************************************************************************/ + +#define HEART_WAVE_SAMPLE_SERVICE_CACHE_SIZE (3 * 3 * 256) +#define FILE_MAX_COUNT 1 +#define SDCARD_MAX_FILE_SIZE (4 * 1024 * 1024) \ No newline at end of file diff --git a/app/src/board/board_battery_state.c b/app/src/board/board_battery_state.c new file mode 100644 index 0000000..2e27006 --- /dev/null +++ b/app/src/board/board_battery_state.c @@ -0,0 +1,36 @@ + +#include "board_battery_state.h" + +void BoardBattery_init() {} +void BoardBattery_load() { + 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)); + + nrf_saadc_channel_config_t channel_config = NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(BATTERY_ADC_PIN); + channel_config.acq_time = NRF_SAADC_ACQTIME_20US; + ZERROR_CHECK(nrfx_saadc_channel_init(BATTERY_ADC_CHANNEL, &channel_config)); +} +void BoardBattery_unload() { nrf_drv_saadc_uninit(); } + +int16_t BoardBattery_get_adc_val() { + int16_t val = znrf_adc_channel_read_val(BATTERY_ADC_CHANNEL); + return val; +} +int16_t BoardBattery_get_battery_level() { + static const float maxv = 4.0; + static const float minv = 3.3; + + float voltage = BoardBattery_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; + } + return percent_int; +} diff --git a/app/src/board/board_battery_state.h b/app/src/board/board_battery_state.h new file mode 100644 index 0000000..fb19830 --- /dev/null +++ b/app/src/board/board_battery_state.h @@ -0,0 +1,15 @@ +#pragma once + +#include +#include + +#include "board/board.h" +#include "znordic.h" + +void BoardBattery_init(); +void BoardBattery_load(); +void BoardBattery_unload(); + +int16_t BoardBattery_get_adc_val(); +int16_t BoardBattery_val(); +int16_t BoardBattery_get_battery_level(); // 0->100 diff --git a/app/src/board/board_beep_ctrl.c b/app/src/board/board_beep_ctrl.c new file mode 100644 index 0000000..8eb2e21 --- /dev/null +++ b/app/src/board/board_beep_ctrl.c @@ -0,0 +1,93 @@ +#include "board_beep_ctrl.h" +#define BEEP_TIMER_INTERVAL (200) + +APP_TIMER_DEF(m_beep_tmr); // +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, +}; +BoardBeepEffect_t m_beep_effect = kBoardBeepEffect_none; +static m_beep_cnt = 0; + +static void beep_tmr_handler(void *context) { + if (m_beep_effect == kBoardBeepEffect_none) { + BoardBeepCtrl_set(false); + } else if (m_beep_effect == kBoardBeepEffect_oneShortBeep) { + if (m_beep_cnt == 0) { + BoardBeepCtrl_set(true); + } else if (m_beep_cnt >= 1) { + BoardBeepCtrl_set(false); + app_timer_stop(m_beep_tmr); + m_beep_effect = kBoardBeepEffect_none; + } + } else if (m_beep_effect == kBoardBeepEffect_threeShortBeep) { + if (m_beep_cnt % 2 == 0) { + BoardBeepCtrl_set(true); + } else if (m_beep_cnt % 2 == 1) { + BoardBeepCtrl_set(false); + } else if (m_beep_cnt >= 6) { + BoardBeepCtrl_set(false); + app_timer_stop(m_beep_tmr); + m_beep_effect = kBoardBeepEffect_none; + } + } else if (m_beep_effect == kBoardBeepEffect_continuousShortBeep) { + // 每隔1秒响三声 + ZASSERT(BEEP_TIMER_INTERVAL == 200); + if (m_beep_cnt <= 6) { + if (m_beep_cnt % 2 == 0) { + BoardBeepCtrl_set(true); + } else if (m_beep_cnt % 2 == 1) { + BoardBeepCtrl_set(false); + } + } else { + if (BEEP_TIMER_INTERVAL * m_beep_cnt >= 1000) { + m_beep_cnt = 0; + } + } + } + m_beep_cnt++; +} + +void BoardBeepCtrl_init(void) { app_timer_create(&m_beep_tmr, APP_TIMER_MODE_REPEATED, beep_tmr_handler); } +void BoardBeepCtrl_load() { APP_ERROR_CHECK(nrfx_pwm_init(&m_beep_pwm0, &m_beep_pwm0_config0, NULL)); } + +void BoardBeepCtrl_unload() { + BoardBeepCtrl_set(0); + nrfx_pwm_uninit(&m_beep_pwm0); +} + +void BoardBeepCtrl_set(uint8_t state) { + if (state) { + m_beep_pwm0_seq_values.channel_0 = m_beep_pwm0_config0.top_value / 2; // 设置占空比,数值最大不超过 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 BoardBeepCtrl_setEffect(BoardBeepEffect_t effect) { + m_beep_effect = effect; + + app_timer_stop(m_beep_tmr); + m_beep_cnt = 0; + if (m_beep_effect == kBoardBeepEffect_none) { + BoardBeepCtrl_set(false); + } + + else { + app_timer_start(m_beep_tmr, APP_TIMER_TICKS(BEEP_TIMER_INTERVAL), NULL); + } +} diff --git a/app/src/board/board_beep_ctrl.h b/app/src/board/board_beep_ctrl.h new file mode 100644 index 0000000..28d8a11 --- /dev/null +++ b/app/src/board/board_beep_ctrl.h @@ -0,0 +1,24 @@ +#pragma once + +#include +#include + +#include "board/board.h" +#include "znordic.h" + +typedef enum { + kBoardBeepEffect_none = 0, + // 响一声 + kBoardBeepEffect_oneShortBeep, + // 响三声 + kBoardBeepEffect_threeShortBeep, + // 持续短鸣报警 + kBoardBeepEffect_continuousShortBeep, +} BoardBeepEffect_t; + +void BoardBeepCtrl_init(void); +void BoardBeepCtrl_load(); +void BoardBeepCtrl_unload(); + +void BoardBeepCtrl_set(uint8_t beep); +void BoardBeepCtrl_setEffect(BoardBeepEffect_t effect); diff --git a/app/src/board/board_button.c b/app/src/board/board_button.c new file mode 100644 index 0000000..65c620f --- /dev/null +++ b/app/src/board/board_button.c @@ -0,0 +1,24 @@ +#include "board_button.h" + +#include "app_button.h" +#include "board.h" +#include "znordic.h" + +#define BUTTON_DETECTION_DELAY APP_TIMER_TICKS(50) +static board_button_cb_t m_cb; +// +void button_process_handler(uint8_t pin_no, uint8_t button_action) {} + +static app_button_cfg_t buttons[] = { + {BUTTON_PIN, false, NRF_GPIO_PIN_PULLUP, button_process_handler}, +}; +void BoardButton_Init(board_button_cb_t cb) { // + ZASSERT(app_button_init(buttons, ARRAY_SIZE(buttons), BUTTON_DETECTION_DELAY)); +} +void BoardButton_load() { ZASSERT(app_button_enable()); } +void BoardButton_unload() { ZASSERT(app_button_disable()); } + +void BoardButton_enable_sense() { + app_button_disable(); + nrf_gpio_cfg_sense_input(BUTTON_PIN, NRF_GPIO_PIN_PULLUP, NRF_GPIO_PIN_SENSE_LOW); +} diff --git a/app/src/board/board_button.h b/app/src/board/board_button.h new file mode 100644 index 0000000..705c830 --- /dev/null +++ b/app/src/board/board_button.h @@ -0,0 +1,18 @@ +#pragma once + +#include +#include + +#include "board/board.h" + +typedef enum { + kButton_mainButton, +} ButtonIndex_t; + +typedef void (*board_button_cb_t)(ButtonIndex_t pin_no, uint8_t button_action); + +void BoardButton_Init(board_button_cb_t cb); // main中初始化一遍 +void BoardButton_load(); +void BoardButton_unload(); + +void BoardButton_enable_sense(); // 低功耗睡眠前调用该方法 \ No newline at end of file diff --git a/app/src/board/board_light_ctrl.c b/app/src/board/board_light_ctrl.c new file mode 100644 index 0000000..476fd17 --- /dev/null +++ b/app/src/board/board_light_ctrl.c @@ -0,0 +1,70 @@ +#include "board_light_ctrl.h" + +#include "board.h" +#include "znordic.h" + +#define BLINK_CNT 1 +#define BLINK_PERIOD_MS (1000) + +static LightEffect m_light_effect; +static bool m_led_green_light_state; +static int m_blink_cnt; +APP_TIMER_DEF(m_green_light_effect_tmr); + +static void BoardLight_effect_tmr_handler(void *p_context) { // + if (m_light_effect == kLightEffect_close) { + if (m_led_green_light_state) { + BoardLight_setGreenLightState(false); + } + } else if (m_light_effect == kLightEffect_open) { + if (!m_led_green_light_state) { + BoardLight_setGreenLightState(true); + } + } else if (m_light_effect == kLightEffect_slowFlash) { + if (m_blink_cnt % 1 == 0) { + BoardLight_toggleGreenLightState(); + } + } + m_blink_cnt++; +} + +void BoardLight_Init() { + znrf_gpio_cfg_output(LED_GREEN_PIN, NRF_GPIO_PIN_NOPULL); + + ZERROR_CHECK(app_timer_create(&m_green_light_effect_tmr, APP_TIMER_MODE_REPEATED, BoardLight_effect_tmr_handler)); +} +void BoardLight_load() {} +void BoardLight_unload() {} + +void BoardLight_setGreenLightState(bool state) { + if (state) { + nrf_gpio_pin_set(LED_GREEN_PIN); + m_led_green_light_state = true; + } else { + nrf_gpio_pin_clear(LED_GREEN_PIN); + m_led_green_light_state = false; + } +} + +void BoardLight_toggleGreenLightState() { nrf_gpio_pin_toggle(LED_GREEN_PIN); } + +void BoardLight_setGreenLightEffect(LightEffect effect) { + m_light_effect = effect; + + switch (effect) { + case kLightEffect_close: + app_timer_stop(m_green_light_effect_tmr); + BoardLight_setGreenLightState(false); + break; + case kLightEffect_open: + app_timer_stop(m_green_light_effect_tmr); + BoardLight_setGreenLightState(true); + break; + case kLightEffect_slowFlash: + app_timer_start(m_green_light_effect_tmr, APP_TIMER_TICKS(BLINK_PERIOD_MS), NULL); + break; + default: + break; + } + return; +} diff --git a/app/src/board/board_light_ctrl.h b/app/src/board/board_light_ctrl.h new file mode 100644 index 0000000..e5016a5 --- /dev/null +++ b/app/src/board/board_light_ctrl.h @@ -0,0 +1,23 @@ +#pragma once + +#include +#include + +#include "board/board.h" + +typedef enum { + + kLightEffect_close, + kLightEffect_open, + kLightEffect_slowFlash, + +} LightEffect; + +void BoardLight_Init(); // main中初始化一遍 +void BoardLight_load(); +void BoardLight_unload(); + +void BoardLight_setGreenLightState(bool state); // 尽量不要直接使用该函数 +void BoardLight_toggleGreenLightState(); // 尽量不要直接使用该函数 + +void BoardLight_setGreenLightEffect(LightEffect effect); diff --git a/app/src/board/board_sdcard_driver.c b/app/src/board/board_sdcard_driver.c new file mode 100644 index 0000000..98fd49b --- /dev/null +++ b/app/src/board/board_sdcard_driver.c @@ -0,0 +1,176 @@ +#include "board/board_sdcard_driver.h" + +#include "board/board.h" +#include "znordic.h" +/******************************************************************************* + * 结构体定义 * + *******************************************************************************/ +typedef enum { + kConnectToInternal, + kConnectToExt, +} ConnectTo_t; + +FATFS m_fs; +ConnectTo_t m_connectTo = kConnectToNone; +static bool m_sdcard_inited; + +NRF_BLOCK_DEV_SDC_DEFINE( // + m_block_dev_sdc, // + NRF_BLOCK_DEV_SDC_CONFIG(SDC_SECTOR_SIZE, // + APP_SDCARD_CONFIG(SDCARD_SPI_MOSI_PIN, // + SDCARD_SPI_MISO_PIN, // + SDCARD_SPI_SCK_PIN, // + SDCARD_SPI_CS_PIN)), + NFR_BLOCK_DEV_INFO_CONFIG("IFLYTOP", "SDC", "1.00")); + +/** + * + * @warning: + * SD卡和单片机是一直连接着的,SD卡和读卡器是通过一个电子开关隔离开的的。 + * 所以如果SD卡切换到读卡器,单片机需要先将SPI引脚初始化成输入高阻,然后再切换到读卡器。避免引脚竞争。 + * 此处代码需要谨慎修改,容易造成硬件损坏。 + * + * SDCARD_POWER_CTRL_PIN:低电平有效 + * SDCARD_USBDRIVER_IC_JUNCTION_CTRL_NOE_PIN:0:连接读卡器 1:连接单片机 + * + */ +void Board_sdcardInit() { + if (!m_sdcard_inited) return; + /** + * @brief SDCARD SPI 引脚初始化 + */ + nrf_gpio_cfg_sense_input(SDCARD_SPI_CS_PIN, NRF_GPIO_PIN_NOPULL, NRF_GPIO_PIN_NOSENSE); + nrf_gpio_cfg_sense_input(SDCARD_SPI_MISO_PIN, NRF_GPIO_PIN_NOPULL, NRF_GPIO_PIN_NOSENSE); + nrf_gpio_cfg_sense_input(SDCARD_SPI_MOSI_PIN, NRF_GPIO_PIN_NOPULL, NRF_GPIO_PIN_NOSENSE); + nrf_gpio_cfg_sense_input(SDCARD_SPI_SCK_PIN, NRF_GPIO_PIN_NOPULL, NRF_GPIO_PIN_NOSENSE); + /** + * @brief SD卡 USB读卡器IC复位引脚 + * 引脚一直配置成高即可 + */ + znrf_gpio_cfg_output(SDCARD_USBDRIVER_IC_RESET_PIN, NRF_GPIO_PIN_NOPULL); + nrf_gpio_pin_write(SDCARD_USBDRIVER_IC_RESET_PIN, 1); + /** + * @brief 初始化 SD卡连接切换引脚 + */ + znrf_gpio_cfg_output(SDCARD_USBDRIVER_IC_JUNCTION_CTRL_NOE_PIN, NRF_GPIO_PIN_NOPULL); + nrf_gpio_pin_write(SDCARD_USBDRIVER_IC_JUNCTION_CTRL_NOE_PIN, 0); // OE = 0 + /** + * @brief SDCARD电源控制引脚 + */ + znrf_gpio_cfg_output(SDCARD_POWER_CTRL_PIN, NRF_GPIO_PIN_NOPULL); + nrf_gpio_pin_write(SDCARD_POWER_CTRL_PIN, 0); // POWER = 0 打开电源 + m_connectTo = kConnectToExt; + + static diskio_blkdev_t drives[] = // + {DISKIO_BLOCKDEV_CONFIG(NRF_BLOCKDEV_BASE_ADDR(m_block_dev_sdc, block_dev), NULL)}; + diskio_blockdev_register(drives, ARRAY_SIZE(drives)); + m_sdcard_inited = true; +} + +void Board_sdcardConnectToExt() { + /** + * @brief + */ + if (m_connectTo == kConnectToExt) { + return; + } + + /** + * @brief + * 0. 卸载文件系统 + * 2. 配置SPI引脚成输入 + * 3. 切换引脚连接 + * 4. 通过给SD卡重启上电,复位SD卡状态 + */ + + /** + * @brief 卸载文件系统 + * + * PS:这里会自动卸载SPI驱动 + */ + + f_mount(NULL, "", 1); // 卸载文件系统 + disk_uninitialize(0); // 卸载磁盘驱动 + + /** + * @brief 配置SPI引脚成输入 + */ + nrf_gpio_cfg_sense_input(SDCARD_SPI_CS_PIN, NRF_GPIO_PIN_NOPULL, NRF_GPIO_PIN_NOSENSE); + nrf_gpio_cfg_sense_input(SDCARD_SPI_MISO_PIN, NRF_GPIO_PIN_NOPULL, NRF_GPIO_PIN_NOSENSE); + nrf_gpio_cfg_sense_input(SDCARD_SPI_MOSI_PIN, NRF_GPIO_PIN_NOPULL, NRF_GPIO_PIN_NOSENSE); + nrf_gpio_cfg_sense_input(SDCARD_SPI_SCK_PIN, NRF_GPIO_PIN_NOPULL, NRF_GPIO_PIN_NOSENSE); + + /** + * @brief 关闭SD卡电源 + */ + nrf_gpio_pin_write(SDCARD_POWER_CTRL_PIN, 1); + + /** + * @brief 切换引脚连接 + */ + nrf_gpio_pin_write(SDCARD_USBDRIVER_IC_JUNCTION_CTRL_NOE_PIN, 0); + + /** + * @brief 打开SD卡电源 + */ + nrf_delay_ms(30); // 让SD卡通过断电复位一会 + nrf_gpio_pin_write(SDCARD_POWER_CTRL_PIN, 0); // 开 + m_connectTo = kConnectToExt; +} +void Board_sdcardConnectToInternal() { + if (m_connectTo == kConnectToInternal) { + return; + } + + /** + * @brief + * 0. 断开SD卡电源 + * 1. 断开SD卡与读卡器的连接 + * 2. 打开SD电源 + * 3. 挂载SD卡 + */ + + /** + * @brief 断开SD卡电源 + */ + nrf_gpio_pin_write(SDCARD_POWER_CTRL_PIN, 1); + + /** + * @brief 断开SD卡与读卡器的连接 + */ + nrf_gpio_pin_write(SDCARD_USBDRIVER_IC_JUNCTION_CTRL_NOE_PIN, 1); + + /** + * @brief 打开SD电源 + */ + nrf_delay_ms(30); // 让SD卡通过断电复位一会 + nrf_gpio_pin_write(SDCARD_POWER_CTRL_PIN, 0); // 开 + + /** + * @brief 挂载SD卡 + */ + DSTATUS disk_state = STA_NOINIT; + for (uint32_t retries = 3; retries && disk_state; --retries) { + disk_state = disk_initialize(0); + } + if (disk_state != 0) { + NRF_LOG_INFO("Disk initialization failed. %d", disk_state); + ZASSERT(0); + } + NRF_LOG_INFO("Disk initialization succeeded."); + FRESULT ff_result; + ff_result = f_mount(&m_fs, "", 1); + if (ff_result) { + NRF_LOG_INFO("Mount failed."); + ZASSERT(0); + } + uint32_t blocks_per_mb = (1024uL * 1024uL) / m_block_dev_sdc.block_dev.p_ops->geometry(&m_block_dev_sdc.block_dev)->blk_size; + uint32_t capacity = m_block_dev_sdc.block_dev.p_ops->geometry(&m_block_dev_sdc.block_dev)->blk_count / blocks_per_mb; + + ZLOGI("Mount success"); + NRF_LOG_INFO("Capacity: %d MB", capacity); + + m_connectTo == kConnectToInternal; +} + +BoardSdcardConnectTo_t Board_sdcardGetConnectTo() { return m_connectTo; } \ No newline at end of file diff --git a/app/src/board/board_sdcard_driver.h b/app/src/board/board_sdcard_driver.h new file mode 100644 index 0000000..d706a47 --- /dev/null +++ b/app/src/board/board_sdcard_driver.h @@ -0,0 +1,19 @@ +#pragma once + +#include +#include + +#include "board/board.h" + +typedef enum { + kConnectToNone = 0, + kConnectToInternal, + kConnectToExt, +} BoardSdcardConnectTo_t; + +void Board_sdcardInit(); // main中初始化一遍 + +void Board_sdcardConnectToExt(); // SD卡连接到外部SD卡读卡器 +void Board_sdcardConnectToInternal(); // SD卡连接到单片机 + +BoardSdcardConnectTo_t Board_sdcardGetConnectTo(); diff --git a/app/src/board/three_lead_board.c b/app/src/board/three_lead_board.c deleted file mode 100644 index df1a802..0000000 --- a/app/src/board/three_lead_board.c +++ /dev/null @@ -1,522 +0,0 @@ -#include "three_lead_board.h" - -#include "znordic.h" -// -#include "app_timer.h" -#include "basic\ads1293\ads1293.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" - -#define LED_GREEN_PIN 9 - -#define BATTERY_ADC_PIN NRF_SAADC_INPUT_AIN0 -#define BATTERY_ADC_CHANNEL 1 // 不重复即可 - -#define BUTTON_PIN 0 - -#define BEEP_PWM_INSTANCE 0 -#define BEEP_PIN 18 - -#define SDCARD_SPI_SCK_PIN 4 -#define SDCARD_SPI_CS_PIN 5 -#define SDCARD_SPI_MISO_PIN 11 -#define SDCARD_SPI_MOSI_PIN 17 - -#define SDCARD_USBDRIVER_IC_JUNCTION_CTRL_NOE_PIN 1 -#define SDCARD_USBDRIVER_IC_RESET_PIN 28 -#define SDCARD_POWER_CTRL_PIN 30 - -#define ADS1293_SPI_SCK_PIN (32 + 9) -#define ADS1293_SPI_MOSI_PIN 15 -#define ADS1293_SPI_MISO_PIN 20 -#define ADS1293_SPI_CS0_PIN 3 -#define ADS1293_SPI_CS1_PIN 29 -#define ADS1293_READY_PIN 31 - -#define LINE_DET_PIN 10 - -/******************************************************************************* - * TOOLS * - *******************************************************************************/ - -/******************************************************************************* - * ADC * - *******************************************************************************/ -void ThreeLeadECG_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)); -} - -/******************************************************************************* - * BUTTON * - *******************************************************************************/ -void ThreeLeadECG_button_init() { // - nrf_gpio_cfg_sense_input(BUTTON_PIN, NRF_GPIO_PIN_NOPULL, NRF_GPIO_PIN_SENSE_LOW); -} -bool ThreeLeadECG_button_get_state() { - // 低电平有效 - return nrf_gpio_pin_read(BUTTON_PIN) == 0; -} - -/******************************************************************************* - * 蜂鸣器 * - *******************************************************************************/ -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, -}; -void ThreeLeadECG_beep_init() { - znrf_gpio_cfg_output(BEEP_PIN, NRF_GPIO_PIN_NOPULL); - nrf_gpio_pin_set(BEEP_PIN); - - APP_ERROR_CHECK(nrfx_pwm_init(&m_beep_pwm0, &m_beep_pwm0_config0, NULL)); -} -void ThreeLeadECG_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); - } -} - -/******************************************************************************* - * LED * - *******************************************************************************/ -void ThreeLeadECG_led_init() { znrf_gpio_cfg_output(LED_GREEN_PIN, NRF_GPIO_PIN_NOPULL); } -void ThreeLeadECG_led_green_set_state(bool state) { - if (state) { - nrf_gpio_pin_set(LED_GREEN_PIN); - } else { - nrf_gpio_pin_clear(LED_GREEN_PIN); - } -} - -/******************************************************************************* - * BATTERY * - *******************************************************************************/ -void ThreeLeadECG_battery_init() { - nrf_saadc_channel_config_t channel_config = NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(BATTERY_ADC_PIN); - channel_config.acq_time = NRF_SAADC_ACQTIME_10US; - ZERROR_CHECK(nrfx_saadc_channel_init(BATTERY_ADC_CHANNEL, &channel_config)); -} -int16_t ThreeLeadECG_battery_get_adc_val() { - int16_t val = znrf_adc_channel_read_val(BATTERY_ADC_CHANNEL); - return val; -} - -/******************************************************************************* - * SDCARD * - *******************************************************************************/ - -/** - * @brief - * - * SPI - * nand flash - * sd card - * switch - */ - -void ThreeLeadECG_sdcard_base_init() { // - /** - * @brief spi引脚切换成输入 - */ - nrf_gpio_cfg_sense_input(SDCARD_SPI_CS_PIN, NRF_GPIO_PIN_NOPULL, NRF_GPIO_PIN_NOSENSE); - nrf_gpio_cfg_sense_input(SDCARD_SPI_MISO_PIN, NRF_GPIO_PIN_NOPULL, NRF_GPIO_PIN_NOSENSE); - nrf_gpio_cfg_sense_input(SDCARD_SPI_MOSI_PIN, NRF_GPIO_PIN_NOPULL, NRF_GPIO_PIN_NOSENSE); - nrf_gpio_cfg_sense_input(SDCARD_SPI_SCK_PIN, NRF_GPIO_PIN_NOPULL, NRF_GPIO_PIN_NOSENSE); - /** - * @brief USBDRIVER_IC_RESET_PIN ctrl pin - */ - znrf_gpio_cfg_output(SDCARD_USBDRIVER_IC_RESET_PIN, NRF_GPIO_PIN_NOPULL); - nrf_gpio_pin_write(SDCARD_USBDRIVER_IC_RESET_PIN, 1); - /** - * @brief 初始化 SDCARD_USBDRIVER_IC_JUNCTION_CTRL_NOE_PIN - */ - znrf_gpio_cfg_output(SDCARD_USBDRIVER_IC_JUNCTION_CTRL_NOE_PIN, NRF_GPIO_PIN_NOPULL); - nrf_gpio_pin_write(SDCARD_USBDRIVER_IC_JUNCTION_CTRL_NOE_PIN, 0); // OE = 0 - /** - * @brief SDCARD电源控制引脚 - */ - znrf_gpio_cfg_output(SDCARD_POWER_CTRL_PIN, NRF_GPIO_PIN_NOPULL); - nrf_gpio_pin_write(SDCARD_POWER_CTRL_PIN, 0); // POWER = 0 -} -void ThreeLeadECG_sdcard_connect2_ext_usb_sdcard_driver_ic_reset() { - nrf_gpio_pin_clear(SDCARD_USBDRIVER_IC_RESET_PIN); - nrf_delay_ms(10); - nrf_gpio_pin_set(SDCARD_USBDRIVER_IC_RESET_PIN); -} -void ThreeLeadECG_sdcard_connect2_ext_usb_sdcard_driver_ic(bool connect) { - if (!connect) { - nrf_gpio_pin_clear(SDCARD_USBDRIVER_IC_JUNCTION_CTRL_NOE_PIN); - } else { - nrf_gpio_pin_set(SDCARD_USBDRIVER_IC_JUNCTION_CTRL_NOE_PIN); - } -} -void ThreeLeadECG_sdcard_flash_power_ctrl(bool power) { - if (!power) { - nrf_gpio_pin_set(SDCARD_POWER_CTRL_PIN); - } else { - nrf_gpio_pin_clear(SDCARD_POWER_CTRL_PIN); - } -} - -void ThreeLeadECG_sdcard_spi_umount() { - nrf_gpio_cfg_sense_input(SDCARD_SPI_CS_PIN, NRF_GPIO_PIN_NOPULL, NRF_GPIO_PIN_NOSENSE); - nrf_gpio_cfg_sense_input(SDCARD_SPI_MISO_PIN, NRF_GPIO_PIN_NOPULL, NRF_GPIO_PIN_NOSENSE); - nrf_gpio_cfg_sense_input(SDCARD_SPI_MOSI_PIN, NRF_GPIO_PIN_NOPULL, NRF_GPIO_PIN_NOSENSE); - nrf_gpio_cfg_sense_input(SDCARD_SPI_SCK_PIN, NRF_GPIO_PIN_NOPULL, NRF_GPIO_PIN_NOSENSE); -} - -void ThreeLeadECG_sdcard_init() { - /** - * @brief - * 0. 必要引脚初始化 - * 1. spi引脚切换成输入 - * 2. 连接flash和usbflash驱动器连接 - * <----option----> - * 4. 打开flash电源 - * - */ - ThreeLeadECG_sdcard_base_init(); // 必要引脚初始化 - // ThreeLeadECG_sdcard_spi_umount(); // - // ThreeLeadECG_sdcard_connect2_ext_usb_sdcard_driver_ic(true); - // ThreeLeadECG_sdcard_flash_power_ctrl(true); -} - -NRF_BLOCK_DEV_SDC_DEFINE(m_block_dev_sdc, // - NRF_BLOCK_DEV_SDC_CONFIG(SDC_SECTOR_SIZE, // - APP_SDCARD_CONFIG(SDCARD_SPI_MOSI_PIN, // - SDCARD_SPI_MISO_PIN, // - SDCARD_SPI_SCK_PIN, // - SDCARD_SPI_CS_PIN)), - NFR_BLOCK_DEV_INFO_CONFIG("Nordic", "SDC", "1.00")); -static FATFS fs; - -void sdcard_test_write_text() { -#define FILE_NAME "/6.TXT" - static FIL file; - uint32_t bytes_written; - static DIR dir; - static FILINFO fno; - - NRF_LOG_INFO("\r\n Listing directory: /"); - FRESULT ff_result = f_opendir(&dir, "/"); - if (ff_result) { - NRF_LOG_INFO("Directory listing failed!"); - return; - } - - do { - ff_result = f_readdir(&dir, &fno); - if (ff_result != FR_OK) { - NRF_LOG_INFO("Directory read failed."); - return; - } - - if (fno.fname[0]) { - if (fno.fattrib & AM_DIR) { - NRF_LOG_RAW_INFO(" %s", (uint32_t)fno.fname); - } else { - NRF_LOG_RAW_INFO("%9lu %s", fno.fsize, (uint32_t)fno.fname); - } - } - } while (fno.fname[0]); - NRF_LOG_RAW_INFO(""); - NRF_LOG_INFO("read from file " FILE_NAME "..."); - { - ff_result = f_open(&file, FILE_NAME, FA_READ); - if (ff_result == FR_OK) { - static char rxbuf[20] = {0}; - UINT rxsize; - ff_result = f_read(&file, rxbuf, 19, &rxsize); - if (ff_result != FR_OK) { - NRF_LOG_INFO("read failed\r\n."); - } else { - NRF_LOG_INFO("read %s(%d)", rxbuf, rxsize); - } - (void)f_close(&file); - } - } - - NRF_LOG_INFO("Writing to file " FILE_NAME "..."); - { - ff_result = f_open(&file, FILE_NAME, FA_CREATE_ALWAYS | FA_READ | FA_WRITE); - if (ff_result != FR_OK) { - NRF_LOG_INFO("Unable to open or create file: " FILE_NAME ". %d", ff_result); - return; - } - - ff_result = f_write(&file, "iflytop", sizeof("iflytop") - 1, (UINT*)&bytes_written); - if (ff_result != FR_OK) { - NRF_LOG_INFO("Write failed\r\n."); - } else { - NRF_LOG_INFO("%d bytes written.", bytes_written); - } - - (void)f_close(&file); - } -} -bool mountsuc = false; -/** - * @brief 对接 get_fattime - * @return DWORD - */ - - - -void ThreeLeadECG_sdcard_mount() { - /** - * @brief - * 1. 关闭flash电源 - * 2. 断开flash和usbflash驱动器连接 - * 3. 打开flash电源 - * 4. 初始化SPI引脚,驱动flash - */ - - nrf_gpio_pin_write(SDCARD_POWER_CTRL_PIN, 1); // 关 - nrf_gpio_pin_write(SDCARD_USBDRIVER_IC_JUNCTION_CTRL_NOE_PIN, 1); - nrf_gpio_pin_write(SDCARD_POWER_CTRL_PIN, 0); // 开 - - /** - * @brief - * 1. 初始化SPI引脚,驱动flash - */ - if (!mountsuc) { - static diskio_blkdev_t drives[] = // - {DISKIO_BLOCKDEV_CONFIG(NRF_BLOCKDEV_BASE_ADDR(m_block_dev_sdc, block_dev), NULL)}; - - diskio_blockdev_register(drives, ARRAY_SIZE(drives)); - - DSTATUS disk_state = STA_NOINIT; - for (uint32_t retries = 3; retries && disk_state; --retries) { - disk_state = disk_initialize(0); - } - if (disk_state) { - NRF_LOG_INFO("Disk initialization failed. %d", disk_state); - return; - } - NRF_LOG_INFO("Disk initialization succeeded."); - - FRESULT ff_result; - // ff_result = f_mkfs("0:", FM_FAT, 4096, NULL, 0); - // if (ff_result) { - // NRF_LOG_INFO("mkfs failed. %d",ff_result); - // return; - // } - - ff_result = f_mount(&fs, "", 1); - if (ff_result) { - NRF_LOG_INFO("Mount failed."); - return; - } - ZLOGI("Mount success"); - - uint32_t blocks_per_mb = (1024uL * 1024uL) / m_block_dev_sdc.block_dev.p_ops->geometry(&m_block_dev_sdc.block_dev)->blk_size; - uint32_t capacity = m_block_dev_sdc.block_dev.p_ops->geometry(&m_block_dev_sdc.block_dev)->blk_count / blocks_per_mb; - NRF_LOG_INFO("Capacity: %d MB", capacity); - - mountsuc = true; - } - - sdcard_test_write_text(); -} -void ThreeLeadECG_sdcard_umount() { - /** - * @brief - * 1. 卸载磁盘 - * 2. 失能SPI引脚 - * 3. SPI引脚切换成输入高阻 - * 4. 关闭flash电源 - * 5. 连接flash和usbflash驱动器连接 - * <----option----> - * 6. 打开flash电源(硬件改版后,flash的电可以从USB上取,就不需要再打开flash电源了) - */ - // umount - f_mount(NULL, "", 1); - disk_uninitialize(0); - ThreeLeadECG_sdcard_spi_umount(); - - nrf_gpio_pin_write(SDCARD_POWER_CTRL_PIN, 1); // 关 - nrf_gpio_pin_write(SDCARD_USBDRIVER_IC_JUNCTION_CTRL_NOE_PIN, 0); - nrf_delay_ms(100); - nrf_gpio_pin_write(SDCARD_POWER_CTRL_PIN, 0); // 开 - - nrf_gpio_pin_write(SDCARD_USBDRIVER_IC_RESET_PIN, 0); - nrf_delay_ms(10); - nrf_gpio_pin_write(SDCARD_USBDRIVER_IC_RESET_PIN, 1); -} - -/******************************************************************************* - * ecg * - *******************************************************************************/ - -static const nrf_drv_spi_t spi = NRF_DRV_SPI_INSTANCE(2); /**< SPI instance. */ - -static ads1293_t m_ads1293_0; // U2 -static ads1293_t m_ads1293_1; // U3 - -void ads1293_spi_tx_rx_0(uint8_t* tx, uint8_t* rx, uint8_t len) { - nrf_gpio_pin_clear(ADS1293_SPI_CS0_PIN); - nrf_drv_spi_transfer(&spi, tx, len, rx, len); - nrf_gpio_pin_set(ADS1293_SPI_CS0_PIN); -} -void ads1293_spi_tx_rx_1(uint8_t* tx, uint8_t* rx, uint8_t len) { - nrf_gpio_pin_clear(ADS1293_SPI_CS1_PIN); - nrf_drv_spi_transfer(&spi, tx, len, rx, len); - nrf_gpio_pin_set(ADS1293_SPI_CS1_PIN); -} -void ads1293_spi_writereg_and_check(ads1293_t* ads, uint8_t addr, uint8_t data) { - uint8_t readbak = 0; - // readonly add - if (addr == 0x19 || addr == 0x1a || addr == 0x1b || addr == 0x1c || addr == 0x40 || addr == 0x30) { - return; - } - ads1293_spi_writereg_and_readbak(ads, addr, data, &readbak); - if (readbak != data) { - ZLOGE("ads_%d write %x failed,w:%x readbak:%x", ads->id, addr, data, readbak); - } -} -#include "ads_cfg.h" -#include "TI_ADS1293_register_settings.h" -void ThreeLeadECG_ecg_reg_config() { - for (uint16_t i = 0; i < ZARRAY_SIZE(ads0cfg); i++) { - ads1293_spi_writereg_and_check(&m_ads1293_0, ads0cfg[i].add, ads0cfg[i].data); - } - for (uint16_t i = 0; i < ZARRAY_SIZE(ads1cfg); i++) { - ads1293_spi_writereg_and_check(&m_ads1293_1, ads1cfg[i].add, ads1cfg[i].data); - } - - // ads1293_spi_writereg_and_check(&m_ads1293_1,TI_ADS1293_CONFIG_REG, TI_ADS1293_CONFIG_REG_VALUE); - // ads1293_spi_writereg_and_check(&m_ads1293_1,TI_ADS1293_FLEX_CH1_CN_REG, TI_ADS1293_FLEX_CH1_CN_REG_VALUE); - // ads1293_spi_writereg_and_check(&m_ads1293_1,TI_ADS1293_FLEX_CH2_CN_REG, TI_ADS1293_FLEX_CH2_CN_REG_VALUE); - // ads1293_spi_writereg_and_check(&m_ads1293_1,TI_ADS1293_FLEX_CH3_CN_REG, TI_ADS1293_FLEX_CH3_CN_REG_VALUE); - // ads1293_spi_writereg_and_check(&m_ads1293_1,TI_ADS1293_FLEX_PACE_CN_REG, TI_ADS1293_FLEX_PACE_CN_REG_VALUE); - // ads1293_spi_writereg_and_check(&m_ads1293_1,TI_ADS1293_FLEX_VBAT_CN_REG, TI_ADS1293_FLEX_VBAT_CN_REG_VALUE); - // ads1293_spi_writereg_and_check(&m_ads1293_1,TI_ADS1293_LOD_CN_REG, TI_ADS1293_LOD_CN_REG_VALUE); - // ads1293_spi_writereg_and_check(&m_ads1293_1,TI_ADS1293_LOD_EN_REG, TI_ADS1293_LOD_EN_REG_VALUE); - // ads1293_spi_writereg_and_check(&m_ads1293_1,TI_ADS1293_LOD_CURRENT_REG, TI_ADS1293_LOD_CURRENT_REG_VALUE); - // ads1293_spi_writereg_and_check(&m_ads1293_1,TI_ADS1293_LOD_AC_CN_REG, TI_ADS1293_LOD_AC_CN_REG_VALUE); - // ads1293_spi_writereg_and_check(&m_ads1293_1,TI_ADS1293_CMDET_EN_REG, TI_ADS1293_CMDET_EN_REG_VALUE); - // ads1293_spi_writereg_and_check(&m_ads1293_1,TI_ADS1293_CMDET_CN_REG, TI_ADS1293_CMDET_CN_REG_VALUE); - // ads1293_spi_writereg_and_check(&m_ads1293_1,TI_ADS1293_RLD_CN_REG, TI_ADS1293_RLD_CN_REG_VALUE); - // ads1293_spi_writereg_and_check(&m_ads1293_1,TI_ADS1293_WILSON_EN1_REG, TI_ADS1293_WILSON_EN1_REG_VALUE); - // ads1293_spi_writereg_and_check(&m_ads1293_1,TI_ADS1293_WILSON_EN2_REG, TI_ADS1293_WILSON_EN2_REG_VALUE); - // ads1293_spi_writereg_and_check(&m_ads1293_1,TI_ADS1293_WILSON_EN3_REG, TI_ADS1293_WILSON_EN3_REG_VALUE); - // ads1293_spi_writereg_and_check(&m_ads1293_1,TI_ADS1293_WILSON_CN_REG, TI_ADS1293_WILSON_CN_REG_VALUE); - - // ads1293_spi_writereg_and_check(&m_ads1293_1,TI_ADS1293_REF_CN_REG, TI_ADS1293_REF_CN_REG_VALUE); - - // ads1293_spi_writereg_and_check(&m_ads1293_1,TI_ADS1293_OSC_CN_REG, TI_ADS1293_OSC_CN_REG_VALUE); - // ads1293_spi_writereg_and_check(&m_ads1293_1,TI_ADS1293_AFE_RES_REG, TI_ADS1293_AFE_RES_REG_VALUE); - // ads1293_spi_writereg_and_check(&m_ads1293_1,TI_ADS1293_AFE_SHDN_CN_REG, TI_ADS1293_AFE_SHDN_CN_REG_VALUE); - // ads1293_spi_writereg_and_check(&m_ads1293_1,TI_ADS1293_AFE_FAULT_CN_REG, TI_ADS1293_AFE_FAULT_CN_REG_VALUE); - // ads1293_spi_writereg_and_check(&m_ads1293_1,TI_ADS1293_AFE_DITHER_EN_REG, TI_ADS1293_AFE_DITHER_EN_REG_VALUE); - // ads1293_spi_writereg_and_check(&m_ads1293_1,TI_ADS1293_AFE_PACE_CN_REG, TI_ADS1293_AFE_PACE_CN_REG_VALUE); - - // ads1293_spi_writereg_and_check(&m_ads1293_1,TI_ADS1293_R2_RATE_REG, TI_ADS1293_R2_RATE_REG_VALUE); - // ads1293_spi_writereg_and_check(&m_ads1293_1,TI_ADS1293_R3_RATE1_REG, TI_ADS1293_R3_RATE1_REG_VALUE); - // ads1293_spi_writereg_and_check(&m_ads1293_1,TI_ADS1293_R3_RATE2_REG, TI_ADS1293_R3_RATE2_REG_VALUE); - // ads1293_spi_writereg_and_check(&m_ads1293_1,TI_ADS1293_R3_RATE3_REG, TI_ADS1293_R3_RATE3_REG_VALUE); - // ads1293_spi_writereg_and_check(&m_ads1293_1,TI_ADS1293_P_DRATE_REG, TI_ADS1293_P_DRATE_REG_VALUE); - // ads1293_spi_writereg_and_check(&m_ads1293_1,TI_ADS1293_DIS_EFILTER_REG, TI_ADS1293_DIS_EFILTER_REG_VALUE); - // ads1293_spi_writereg_and_check(&m_ads1293_1,TI_ADS1293_DRDYB_SRC_REG, TI_ADS1293_DRDYB_SRC_REG_VALUE); - // ads1293_spi_writereg_and_check(&m_ads1293_1,TI_ADS1293_SYNCOUTB_SRC_REG, TI_ADS1293_SYNCOUTB_SRC_REG_VALUE); - // ads1293_spi_writereg_and_check(&m_ads1293_1,TI_ADS1293_MASK_DRDYB_REG, TI_ADS1293_MASK_DRDYB_REG_VALUE); - // ads1293_spi_writereg_and_check(&m_ads1293_1,TI_ADS1293_MASK_ERR_REG, TI_ADS1293_MASK_ERR_REG_VALUE); - // ads1293_spi_writereg_and_check(&m_ads1293_1,TI_ADS1293_ALARM_FILTER_REG, TI_ADS1293_ALARM_FILTER_REG_VALUE); - // ads1293_spi_writereg_and_check(&m_ads1293_1,TI_ADS1293_CH_CNFG_REG, TI_ADS1293_CH_CNFG_REG_VALUE); -} - -void ThreeLeadECG_ads1293_start_convert() { - ads1293_spi_writereg(&m_ads1293_0, TI_ADS1293_CONFIG_REG, 0x01); - ads1293_spi_writereg(&m_ads1293_1, TI_ADS1293_CONFIG_REG, 0x01); -} -void ThreeLeadECG_ecg_init() { - nrf_drv_spi_config_t spi_config = NRF_DRV_SPI_DEFAULT_CONFIG; - spi_config.ss_pin = NRF_DRV_SPI_PIN_NOT_USED; // NRF_DRV_SPI_PIN_NOT_USED - spi_config.miso_pin = ADS1293_SPI_MISO_PIN; - spi_config.mosi_pin = ADS1293_SPI_MOSI_PIN; - spi_config.sck_pin = ADS1293_SPI_SCK_PIN; - spi_config.frequency = NRF_DRV_SPI_FREQ_8M; - spi_config.mode = NRF_DRV_SPI_MODE_3; - // spi_config.mode = - ZERROR_CHECK(nrf_drv_spi_init(&spi, &spi_config, NULL, NULL)); - - znrf_gpio_cfg_output(ADS1293_SPI_CS0_PIN, NRF_GPIO_PIN_NOPULL); - znrf_gpio_cfg_output(ADS1293_SPI_CS1_PIN, NRF_GPIO_PIN_NOPULL); - nrf_gpio_cfg_input(ADS1293_READY_PIN, NRF_GPIO_PIN_PULLUP); - - nrf_gpio_pin_set(ADS1293_SPI_CS0_PIN); - nrf_gpio_pin_set(ADS1293_SPI_CS1_PIN); - - m_ads1293_0.spi_tx_rx = ads1293_spi_tx_rx_0; - m_ads1293_0.id = 0; - m_ads1293_1.spi_tx_rx = ads1293_spi_tx_rx_1; - m_ads1293_1.id = 1; - - ads1293_spi_init(&m_ads1293_0, ads1293_spi_tx_rx_0); - ads1293_spi_init(&m_ads1293_1, ads1293_spi_tx_rx_1); - - uint8_t revid = ads1293_spi_readreg(&m_ads1293_0, TI_ADS1293_REVID_REG); - NRF_LOG_INFO("ads1293_0 revid: %d", revid); - revid = ads1293_spi_readreg(&m_ads1293_1, TI_ADS1293_REVID_REG); - NRF_LOG_INFO("ads1293_1 revid: %d", revid); - - ThreeLeadECG_ecg_reg_config(); - ThreeLeadECG_ads1293_start_convert(); -} -uint32_t ThreeLeadECG_ready_pin_state_get() { return nrf_gpio_pin_read(ADS1293_READY_PIN); } - -uint32_t ThreeLeadECG_ads1293_init() {} - -void ThreeLeadECG_ads1293_get_lod_state(uint16_t* state) { // - uint8_t lod0 = ads1293_read_error_lod(&m_ads1293_0); - uint8_t lod1 = ads1293_read_error_lod(&m_ads1293_1); - *state = (lod0) | (lod1 << 8); -} - -void ThreeLeadECG_ads1293_sample_all(uint32_t* sample0, uint32_t* sample1, uint32_t* sample2, uint32_t* sample10, uint32_t* sample11, uint32_t* sample12) { - // *sample0 - ads1293_read_ecg(&m_ads1293_0, 1, sample0); - ads1293_read_ecg(&m_ads1293_0, 2, sample1); - ads1293_read_ecg(&m_ads1293_0, 3, sample2); - // *sample1 - ads1293_read_ecg(&m_ads1293_1, 1, sample10); - ads1293_read_ecg(&m_ads1293_1, 2, sample11); - ads1293_read_ecg(&m_ads1293_1, 3, sample12); -} -void ThreeLeadECG_ads1293_sample(uint32_t* sample0, uint32_t* sample1, uint32_t* sample2) { - // *sample0 - ads1293_read_ecg(&m_ads1293_0, 1, sample0); - ads1293_read_ecg(&m_ads1293_1, 1, sample1); - ads1293_read_ecg(&m_ads1293_1, 2, sample2); -} - -void ThreeLeadECG_LineInputDet_init() { - // LINE_DET_PIN - nrf_gpio_cfg_input(LINE_DET_PIN, NRF_GPIO_PIN_PULLUP); -} -uint32_t ThreeLeadECG_LineInputDet_get_state() { return nrf_gpio_pin_read(LINE_DET_PIN); } diff --git a/app/src/board/three_lead_board.h b/app/src/board/three_lead_board.h deleted file mode 100644 index fef15fd..0000000 --- a/app/src/board/three_lead_board.h +++ /dev/null @@ -1,55 +0,0 @@ -#pragma once -#include -#define VERSION 1 -#define MANUFACTURER_NAME "iflytop" -#define BLE_NAME "iflytop_test" - -/******************************************************************************* - * INCLUDE * - *******************************************************************************/ -#include - -/******************************************************************************* - * basic * - *******************************************************************************/ -void ThreeLeadECG_adc_module_init(); -/******************************************************************************* - * BUTTON * - *******************************************************************************/ -void ThreeLeadECG_button_init(); -bool ThreeLeadECG_button_get_state(); -/******************************************************************************* - * 铚傞福鍣? * - *******************************************************************************/ -void ThreeLeadECG_beep_init(); -void ThreeLeadECG_beep_set_state(bool state); - -/******************************************************************************* - * LED * - *******************************************************************************/ -void ThreeLeadECG_led_init(); -void ThreeLeadECG_led_green_set_state(bool state); -/******************************************************************************* - * BATTERY * - *******************************************************************************/ -void ThreeLeadECG_battery_init(); -int16_t ThreeLeadECG_battery_get_adc_val(); -/******************************************************************************* - * SDCARD * - *******************************************************************************/ -void ThreeLeadECG_sdcard_connect2_ext_usb_sdcard_driver_ic_reset(); -void ThreeLeadECG_sdcard_init(); -void ThreeLeadECG_sdcard_mount(); -void ThreeLeadECG_sdcard_umount(); -/******************************************************************************* - * ECG * - *******************************************************************************/ -void ThreeLeadECG_ecg_init(); -uint32_t ThreeLeadECG_ready_pin_state_get(); -void ThreeLeadECG_ads1293_get_lod_state(uint16_t* state); - -// -void ThreeLeadECG_LineInputDet_init(); -uint32_t ThreeLeadECG_LineInputDet_get_state(); -void ThreeLeadECG_ads1293_sample(uint32_t* sample0, uint32_t* sample1, uint32_t* sample2); -void ThreeLeadECG_ads1293_sample_all(uint32_t* sample0, uint32_t* sample1, uint32_t* sample2, uint32_t* sample10, uint32_t* sample11, uint32_t* sample12); \ No newline at end of file diff --git a/app/src/device_state.c b/app/src/device_state.c index 243c1b5..77c8394 100644 --- a/app/src/device_state.c +++ b/app/src/device_state.c @@ -10,18 +10,5 @@ void ds_change_to_state(device_state_t 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 index 9a6f645..b322f9e 100644 --- a/app/src/device_state.h +++ b/app/src/device_state.h @@ -1,87 +1,28 @@ #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; - +#include 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, + // Ready + kdevice_state_ready = 1, + // sample + kdevice_state_sampling = 2, } device_state_t; -static const char* device_state_to_str(device_state_t ds) { +static const char* ds2str(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_ready: + return "ready"; 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"; + return "unknown"; } } -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); +device_state_t ds_now_state(); \ No newline at end of file diff --git a/app/src/heart_wave_sample_service.c b/app/src/heart_wave_sample_service.c index 49ff56c..dc7f48c 100644 --- a/app/src/heart_wave_sample_service.c +++ b/app/src/heart_wave_sample_service.c @@ -1,152 +1,280 @@ #include "heart_wave_sample_service.h" - +// +#include "znordic.h" +// +#include "app_button.h" #include "app_event.h" +#include "basic/ads1293/ads1293.h" +#include "nrf_drv_gpiote.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. */ +#define SENSOR0_ID 0 +#define SENSOR1_ID 3 +#define SENSOR2_ID 4 -static uint16_t m_capture_buffer_a[128]; -static uint16_t m_capture_buffer_b[128]; +/******************************************************************************* + * STRUCT * + *******************************************************************************/ +typedef struct { + uint8_t add; + uint8_t data; +} adscfg_t; -static uint16_t* m_capture_buffer; -static uint16_t m_capture_buffer_index = 0; +/******************************************************************************* + * CONFIG * + *******************************************************************************/ -volatile static float m_sensor_display_data = 0; // 0->100 -static uint32_t m_start_capture_tp; -static uint32_t m_frameindex = 0; +static adscfg_t m_prvads0cfg[] = // + {{0x00, 0x00}, {0x01, 0x19}, {0x02, 0x11}, {0x03, 0x00}, {0x04, 0x00}, {0x05, 0x00}, {0x06, 0x00}, {0x07, 0x0f}, {0x08, 0xff}, {0x09, 0x00}, {0x0a, 0x07}, {0x0b, 0x07}, {0x0c, 0x74}, {0x0d, 0x01}, {0x0e, 0x02}, {0x0f, 0x03}, {0x10, 0x04}, + {0x11, 0x00}, {0x12, 0x05}, {0x13, 0x39}, {0x14, 0x36}, {0x15, 0x06}, {0x16, 0x00}, {0x17, 0x05}, {0x18, 0x00}, {0x19, 0x00}, {0x1a, 0x00}, {0x1b, 0x00}, {0x1c, 0x00}, {0x1d, 0x00}, {0x21, 0x01}, {0x22, 0x20}, {0x23, 0x20}, {0x24, 0x02}, + {0x25, 0x00}, {0x26, 0x00}, {0x27, 0x08}, {0x28, 0x08}, {0x29, 0x00}, {0x2a, 0x00}, {0x2b, 0x00}, {0x2c, 0x00}, {0x2d, 0x00}, {0x2e, 0x33}, {0x2f, 0x30}, {0x30, 0x00}, {0x31, 0x00}, {0x32, 0x00}, {0x33, 0x00}, {0x34, 0x00}, {0x35, 0x00}, + {0x36, 0x00}, {0x37, 0x00}, {0x38, 0x00}, {0x39, 0x00}, {0x3a, 0x00}, {0x3b, 0x00}, {0x3c, 0x00}, {0x3d, 0x00}, {0x3e, 0x00}, {0x3f, 0x00}, {0x40, 0xff}, {0x50, 0x00}, {0x60, 0x00}, {0x62, 0x00}}; -static void swap_buffer() { - if (m_capture_buffer == NULL) { - m_capture_buffer = m_capture_buffer_a; - m_capture_buffer_index = 0; - return; - } +static adscfg_t m_prvads1cfg[] = // + {{0x00, 0x00}, {0x01, 0x19}, {0x02, 0x11}, {0x03, 0x00}, {0x04, 0x00}, {0x05, 0x00}, {0x06, 0x00}, {0x07, 0x0f}, {0x08, 0xff}, {0x09, 0x00}, {0x0a, 0x07}, {0x0b, 0x07}, {0x0c, 0x74}, {0x0d, 0x01}, {0x0e, 0x02}, {0x0f, 0x03}, {0x10, 0x04}, + {0x11, 0x00}, {0x12, 0x05}, {0x13, 0x39}, {0x14, 0x36}, {0x15, 0x06}, {0x16, 0x00}, {0x17, 0x05}, {0x18, 0x00}, {0x19, 0x00}, {0x1a, 0x00}, {0x1b, 0x00}, {0x1c, 0x00}, {0x1d, 0x00}, {0x21, 0x01}, {0x22, 0x20}, {0x23, 0x20}, {0x24, 0x02}, + {0x25, 0x00}, {0x26, 0x00}, {0x27, 0x08}, {0x28, 0x08}, {0x29, 0x00}, {0x2a, 0x00}, {0x2b, 0x00}, {0x2c, 0x00}, {0x2d, 0x00}, {0x2e, 0x33}, {0x2f, 0x30}, {0x30, 0x00}, {0x31, 0x00}, {0x32, 0x00}, {0x33, 0x00}, {0x34, 0x00}, {0x35, 0x00}, + {0x36, 0x00}, {0x37, 0x00}, {0x38, 0x00}, {0x39, 0x00}, {0x3a, 0x00}, {0x3b, 0x00}, {0x3c, 0x00}, {0x3d, 0x00}, {0x3e, 0x00}, {0x3f, 0x00}, {0x40, 0xff}, {0x50, 0x00}, {0x60, 0x00}, {0x62, 0x00}}; +/******************************************************************************* + * VARIABLE * + *******************************************************************************/ +static ads1293_t m_ads1293_0; // U2 +static ads1293_t m_ads1293_1; // U3 +static const nrf_drv_spi_t spi = NRF_DRV_SPI_INSTANCE(ADS1293_SPI_INSTANCE); /**< SPI instance. */ +static bool m_ads1293_driver_is_inited = false; +static uint32_t m_frame_index; +static bool m_work_flag; + +static uint8_t m_frame_buffer_a[HEART_WAVE_SAMPLE_SERVICE_CACHE_SIZE]; +static uint8_t m_frame_buffer_b[HEART_WAVE_SAMPLE_SERVICE_CACHE_SIZE]; +static uint8_t* m_frame_buffer; +static int32_t m_frame_buffer_index; + +static one_frame_data_t m_sensor_little_frame_cache[LITTLE_DATA_BLOCK_FRAME_NUM]; +static uint32_t m_little_frame_index; + +/******************************************************************************* + * 函数声明 * + *******************************************************************************/ + +// READY_PIN 中断回调函数 +static void ads1293_ready_pin_irq(nrfx_gpiote_pin_t pin, nrf_gpiote_polarity_t action); +// 缓冲区切换BUFFER +static void prvf_buffer_switch(void); - if (m_capture_buffer == m_capture_buffer_a) { - m_capture_buffer = m_capture_buffer_b; +/******************************************************************************* + * FUNCTION * + *******************************************************************************/ +static void prvf_buffer_switch(void) { + if (m_frame_buffer == m_frame_buffer_a) { + m_frame_buffer = m_frame_buffer_b; + m_frame_buffer_index = 0; } else { - m_capture_buffer = m_capture_buffer_a; + m_frame_buffer = m_frame_buffer_a; + m_frame_buffer_index = 0; } - 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; +static inline bool prvf_buffer_is_full(void) { + if (m_frame_buffer_index >= HEART_WAVE_SAMPLE_SERVICE_CACHE_SIZE) { + return true; } + return false; +} - if (valf <= 0) { - valf = 0; +static inline void prvf_buffer_push_one_byte(uint8_t byte) { + if (m_frame_buffer_index >= HEART_WAVE_SAMPLE_SERVICE_CACHE_SIZE) { + return; } - return valf; + m_frame_buffer[m_frame_buffer_index] = byte; + m_frame_buffer_index++; } -typedef struct { - float value; - float efectiveFactor; -} filter_t; +static inline void prvf_trigger_capture_data_block_event(uint8_t* data, int datalen) { + static app_event_t event; + event.eventType = kevent_capture_data_block_event; + event.val.block_sensor_data.data = data; + event.val.block_sensor_data.len = datalen; + app_sched_event_put(&event, sizeof(app_event_t), app_event_process_cb); +} -filter_t m_filter = {0, 0.8}; +static inline void prvf_little_block_cache_push_one_frame(uint32_t data0, uint32_t data1, uint32_t data2) { + if (m_little_frame_index >= LITTLE_DATA_BLOCK_FRAME_NUM) { + return; + } + m_sensor_little_frame_cache[m_little_frame_index].data0 = data0; + m_sensor_little_frame_cache[m_little_frame_index].data1 = data1; + m_sensor_little_frame_cache[m_little_frame_index].data2 = data2; + m_little_frame_index++; +} -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 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; + memcpy(event.val.little_data_block.data, m_sensor_little_frame_cache, LITTLE_DATA_BLOCK_FRAME_NUM); + event.val.little_data_block.frameIndex = m_frame_index - LITTLE_DATA_BLOCK_FRAME_NUM; + app_sched_event_put(&event, sizeof(app_event_t), app_event_process_cb); } +static void ads1293_spi_tx_rx_0(uint8_t* tx, uint8_t* rx, uint8_t len) { + if (!m_ads1293_driver_is_inited) { + return; + } -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++; + nrf_gpio_pin_clear(ADS1293_SPI_CS0_PIN); + nrf_drv_spi_transfer(&spi, tx, len, rx, len); + nrf_gpio_pin_set(ADS1293_SPI_CS0_PIN); +} +static void ads1293_spi_tx_rx_1(uint8_t* tx, uint8_t* rx, uint8_t len) { + if (!m_ads1293_driver_is_inited) { + return; + } + nrf_gpio_pin_clear(ADS1293_SPI_CS1_PIN); + nrf_drv_spi_transfer(&spi, tx, len, rx, len); + nrf_gpio_pin_set(ADS1293_SPI_CS1_PIN); +} +static ads1293_init() { /******************************************************************************* - * 显示数据计算并赋值 * + * SPI初始化 * *******************************************************************************/ - 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; + static nrf_drv_spi_config_t spi_config = NRF_DRV_SPI_DEFAULT_CONFIG; + spi_config.ss_pin = NRF_DRV_SPI_PIN_NOT_USED; // NRF_DRV_SPI_PIN_NOT_USED + spi_config.miso_pin = ADS1293_SPI_MISO_PIN; + spi_config.mosi_pin = ADS1293_SPI_MOSI_PIN; + spi_config.sck_pin = ADS1293_SPI_SCK_PIN; + spi_config.frequency = NRF_DRV_SPI_FREQ_8M; + spi_config.mode = NRF_DRV_SPI_MODE_3; + // spi_config.mode = + ZERROR_CHECK(nrf_drv_spi_init(&spi, &spi_config, NULL, NULL)); - /******************************************************************************* - * 采样数据缓存 * - *******************************************************************************/ - if (m_capture_buffer == NULL) { - swap_buffer(); - } + znrf_gpio_cfg_output(ADS1293_SPI_CS0_PIN, NRF_GPIO_PIN_NOPULL); + znrf_gpio_cfg_output(ADS1293_SPI_CS1_PIN, NRF_GPIO_PIN_NOPULL); + nrf_gpio_pin_set(ADS1293_SPI_CS0_PIN); + nrf_gpio_pin_set(ADS1293_SPI_CS1_PIN); - if (m_capture_buffer_index < 128) { - m_capture_buffer[m_capture_buffer_index++] = val; - } + m_ads1293_0.spi_tx_rx = ads1293_spi_tx_rx_0; + m_ads1293_0.id = 0; + m_ads1293_1.spi_tx_rx = ads1293_spi_tx_rx_1; + m_ads1293_1.id = 1; + + ads1293_spi_init(&m_ads1293_0, ads1293_spi_tx_rx_0); + ads1293_spi_init(&m_ads1293_1, ads1293_spi_tx_rx_1); + + uint8_t revid = ads1293_spi_readreg(&m_ads1293_0, TI_ADS1293_REVID_REG); + ZLOGI("ads1293_0 revid: %d\n", revid); + revid = ads1293_spi_readreg(&m_ads1293_1, TI_ADS1293_REVID_REG); + ZLOGI("ads1293_1 revid: %d\n", revid); - 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); + ads1293_spi_writereg(&m_ads1293_0, TI_ADS1293_CONFIG_REG, 0); + + for (uint16_t i = 0; i < ZARRAY_SIZE(m_prvads0cfg); i++) { + ads1293_spi_writereg_and_check(&m_ads1293_0, m_prvads0cfg[i].add, m_prvads0cfg[i].data); + } + for (uint16_t i = 0; i < ZARRAY_SIZE(m_prvads1cfg); i++) { + ads1293_spi_writereg_and_check(&m_ads1293_1, m_prvads1cfg[i].add, m_prvads1cfg[i].data); } + m_ads1293_driver_is_inited = true; - /******************************************************************************* - * 实时采样数据事件上报 * - *******************************************************************************/ + /** + * @brief READY引脚中断初始化 + */ { - 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); + // nrf_gpio_cfg_input(ADS1293_READY_PIN, NRF_GPIO_PIN_PULLUP); + ZERROR_CHECK(nrfx_gpiote_init()); + nrf_drv_gpiote_in_config_t inConfig = GPIOTE_CONFIG_IN_SENSE_TOGGLE(false); // 双边沿中断触发 + inConfig.pull = NRF_GPIO_PIN_PULLUP; // 默认上拉 + inConfig.sense = NRF_GPIOTE_POLARITY_LOTOHI; // 上升沿触发 + + ZERROR_CHECK(nrfx_gpiote_in_init(ADS1293_READY_PIN, &inConfig, ads1293_ready_pin_irq)); + nrfx_gpiote_in_event_enable(ADS1293_READY_PIN, true); } } -void hwss_init(void) { - if (m_timer_started) { +/** + * @brief 数据准备号中断回调函数 + * + * @param pin + * @param action + */ +static void ads1293_ready_pin_irq(nrfx_gpiote_pin_t pin, nrf_gpiote_polarity_t action) { + if (!m_work_flag) { return; } + m_frame_index++; + // 检查缓冲区是否为空 + if (!m_frame_buffer) prvf_buffer_switch(); + + static uint32_t sample[6]; + ads1293_read_ecgs(&m_ads1293_0, &sample[0]); + ads1293_read_ecgs(&m_ads1293_1, &sample[3]); + + static uint8_t cache[9]; + cache[0] = (sample[SENSOR0_ID] >> 0) & 0xff; + cache[1] = (sample[SENSOR0_ID] >> 8) & 0xff; + cache[2] = (sample[SENSOR0_ID] >> 16) & 0xff; + + cache[3] = (sample[SENSOR1_ID] >> 0) & 0xff; + cache[4] = (sample[SENSOR1_ID] >> 8) & 0xff; + cache[5] = (sample[SENSOR1_ID] >> 16) & 0xff; + + cache[6] = (sample[SENSOR2_ID] >> 0) & 0xff; + cache[7] = (sample[SENSOR2_ID] >> 8) & 0xff; + cache[8] = (sample[SENSOR2_ID] >> 16) & 0xff; + /** - * @brief 初始化定时器 + * @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); + for (int i = 0; i < 9; i++) { + if (prvf_buffer_is_full()) { + prvf_trigger_capture_data_block_event(m_frame_buffer, HEART_WAVE_SAMPLE_SERVICE_CACHE_SIZE); + prvf_buffer_switch(); + } + prvf_buffer_push_one_byte(cache[i]); } - 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); + /** + * @brief 缓存数据,并触发小数据块事件 + */ + prvf_little_block_cache_push_one_frame(sample[SENSOR0_ID], sample[SENSOR1_ID], sample[SENSOR2_ID]); + if (prvf_light_block_cache_is_full()) { + prvf_light_block_trigger_event(); + prvf_light_block_cache_clear(); + } } -void hwss_stop_capture(void) { - nrfx_timer_disable(&m_timer); - m_frameindex = 0; + +static ads1293_uninit() { + hwss_stop_capture(); + m_ads1293_driver_is_inited = false; + nrf_drv_spi_uninit(&spi); } -float hwss_read_val(void) { - __disable_irq(); - float val = m_sensor_display_data; - __enable_irq(); - return val; +void hwss_init(void) { + /** + * @brief 初始化ads1293硬件接口 + */ + ads1293_init(); +} +void hwss_uninit(void) { + /** + * @brief 反初始化ads1293硬件接口 + */ + ads1293_uninit(); } -float hwss_read_heart_rate(void) { return 0; } -int hwss_has_captured_time_ms() { return (znordic_getpower_on_s() - m_start_capture_tp) * 1000; } +void hwss_start_capture(void) { + m_work_flag = true; + ads1293_start_conversion(&m_ads1293_0); + ads1293_start_conversion(&m_ads1293_1); +} +void hwss_stop_capture(void) { + m_work_flag = false; + ads1293_stop_conversion(&m_ads1293_0); + ads1293_stop_conversion(&m_ads1293_1); +} \ No newline at end of file diff --git a/app/src/heart_wave_sample_service.h b/app/src/heart_wave_sample_service.h index 65e18dc..d569724 100644 --- a/app/src/heart_wave_sample_service.h +++ b/app/src/heart_wave_sample_service.h @@ -1,15 +1,31 @@ +/** + * @file heart_wave_sample_service.h + * @author zhaohe (h_zhaohe@163.com) + * @brief 心电波形采样服务 + * @version 0.1 + * @date 2024-02-01 + * + * @copyright Copyright (c) 2024 + * + */ #pragma once -#include "one_conduction_board.h" - -// 每256个字节触发一次回调 -typedef void (*heart_wave_sample_service_callback_t)(uint16_t *p_data, uint16_t length); +#include "app_event.h" +#include "board/board.h" +/** + * @brief 初始化 + */ void hwss_init(void); +/** + * @brief unint + */ void hwss_uninit(void); +/** + * @brief 开始采集 + */ 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(); +/** + * @brief 停止采集 + */ +void hwss_stop_capture(void); \ No newline at end of file diff --git a/app/src/main.bak.c b/app/src/main.bak.c new file mode 100644 index 0000000..9c7aab1 --- /dev/null +++ b/app/src/main.bak.c @@ -0,0 +1,372 @@ +#include "znordic.h" +// +#include +#include +#include +#include +// +#include "app_uart.h" +#include "basic/ads1293/ads1293.h" +#include "zble_module.h" +#include "zdatachannel_service.h" +#include "znordic_device_info_mgr.h" + +#if defined(UART_PRESENT) +#include "nrf_uart.h" +#endif +#if defined(UARTE_PRESENT) +#include "nrf_uarte.h" +#endif + +#if 0 + +int main() { return 0; } +#endif + +#if 1 + +#define ADS1293_SPI_SCK_PIN (32 + 9) +#define ADS1293_SPI_MOSI_PIN 15 +#define ADS1293_SPI_MISO_PIN 20 +#define ADS1293_SPI_CS0_PIN 3 +#define ADS1293_SPI_CS1_PIN 29 +#define ADS1293_READY_PIN 31 +#define LINE_DET_PIN 10 + +#define UART_TX_BUF_SIZE 256 /**< UART TX buffer size. */ +#define UART_RX_BUF_SIZE 256 /**< UART RX buffer size. */ + +#include "board/ads_cfg.h" +void uart_error_handle(app_uart_evt_t* p_event) {} + +/**@brief Function for initializing the UART. */ +static void uart_init(void) { + ret_code_t err_code; + + app_uart_comm_params_t const comm_params = { + .rx_pin_no = UART_PIN_DISCONNECTED, + .tx_pin_no = 0, + .rts_pin_no = UART_PIN_DISCONNECTED, + .cts_pin_no = UART_PIN_DISCONNECTED, + .flow_control = APP_UART_FLOW_CONTROL_DISABLED, + .use_parity = false, + .baud_rate = UART_BAUDRATE_BAUDRATE_Baud115200, + }; + APP_UART_FIFO_INIT(&comm_params, UART_RX_BUF_SIZE, UART_TX_BUF_SIZE, uart_error_handle, APP_IRQ_PRIORITY_HIGHEST, err_code); + APP_ERROR_CHECK(err_code); +} + +/******************************************************************************* + * 3导联-ADS1293-测试 * + *******************************************************************************/ +APP_TIMER_DEF(m_init_tmr); +APP_TIMER_DEF(m_report_tmr); +ZDATACHANNEL_DEF(m_zhrs, 2 /**/, 1 /*client num*/); +static const nrf_drv_spi_t spi = NRF_DRV_SPI_INSTANCE(2); /**< SPI instance. */ +static ads1293_t m_ads1293_0; // U2 +static ads1293_t m_ads1293_1; // U3 +static void zdatachanel_send_log(const char* fmt, ...); +static void three_lead_ecg_ecg_init(); + +uint32_t get_ready_pin_state_get() { return nrf_gpio_pin_read(ADS1293_READY_PIN); } + +static 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 = NULL; + ZERROR_CHECK(zdatachannel_init(&m_zhrs, &zdatachannle_init)); +} +static int changecount = 0; +void dump_state() { + static uint32_t last = 0; + uint32_t nows = znordic_rtc_gettime_s(); + if (nows != last) { + zdatachanel_send_log("%d\n", changecount); + + uint8_t leadoffstate = ads1293_spi_readreg(&m_ads1293_0, TI_ADS1293_ERROR_LOD_REG); + zdatachanel_send_log("%d%d%d%d_%d%d%d%d\n", // + leadoffstate >> 7 & 0x1, leadoffstate >> 6 & 0x1, leadoffstate >> 5 & 0x1, leadoffstate >> 4 & 0x1, // + leadoffstate >> 3 & 0x1, leadoffstate >> 2 & 0x1, leadoffstate >> 1 & 0x1, leadoffstate >> 0 & 0x1); // + + last = nows; + changecount = 0; + } +} + +int main() { + APP_SCHED_INIT(APP_TIMER_SCHED_EVENT_DATA_SIZE, 20); + znordic_init(); + static zble_module_cfg_t cfg = // + { + .deviceName = "ThreeLeadECG", + .on_service_init = on_service_init, + }; + zble_module_init(&cfg); + NRF_LOG_INFO("compile time :%s", __TIME__); + uart_init(); + + nrf_gpio_cfg_input(LINE_DET_PIN, NRF_GPIO_PIN_PULLUP); + three_lead_ecg_ecg_init(); + ads1293_spi_writereg(&m_ads1293_0, TI_ADS1293_CONFIG_REG, 0x01); + ads1293_spi_writereg(&m_ads1293_1, TI_ADS1293_CONFIG_REG, 0x01); + + while (true) { + app_sched_execute(); + if (NRF_LOG_PROCESS() == false) { + // nrf_pwr_mgmt_run(); + } + static bool state = false; + bool now = get_ready_pin_state_get(); + if (state != now) { + state = now; + changecount++; + + if (now) { + uint32_t val = 0; + ads1293_read_ecg(&m_ads1293_0, 1, &val); + zdatachanel_send_log("%d\n", val); + } + } + // dump_state(); + } +} + +static void ads1293_spi_tx_rx_0(uint8_t* tx, uint8_t* rx, uint8_t len) { + nrf_gpio_pin_clear(ADS1293_SPI_CS0_PIN); + nrf_drv_spi_transfer(&spi, tx, len, rx, len); + nrf_gpio_pin_set(ADS1293_SPI_CS0_PIN); +} +static void ads1293_spi_tx_rx_1(uint8_t* tx, uint8_t* rx, uint8_t len) { + nrf_gpio_pin_clear(ADS1293_SPI_CS1_PIN); + nrf_drv_spi_transfer(&spi, tx, len, rx, len); + nrf_gpio_pin_set(ADS1293_SPI_CS1_PIN); +} + +static void ads1293_spi_writereg_and_check(ads1293_t* ads, uint8_t addr, uint8_t data) { + uint8_t readbak = 0; + // readonly add + if (addr == 0x19 || addr == 0x1a || addr == 0x1b || addr == 0x1c || addr == 0x40 || addr == 0x30) { + return; + } + ads1293_spi_writereg_and_readbak(ads, addr, data, &readbak); + if (readbak != data) { + zdatachanel_send_log("ads_%d write %x failed,w:%x readbak:%x\n", ads->id, addr, data, readbak); + } +} + +static adscfg_t prvads0cfg[] = { + {0x00, 0x00}, // + {0x01, 0x19}, // + {0x02, 0x11}, // + {0x03, 0x00}, // + {0x04, 0x00}, // + {0x05, 0x00}, // + {0x06, 0x00}, // + {0x07, 0x0f}, // + {0x08, 0xff}, // + {0x09, 0x00}, // + {0x0a, 0x07}, // + {0x0b, 0x07}, // + {0x0c, 0x74}, // + {0x0d, 0x01}, // + {0x0e, 0x02}, // + {0x0f, 0x03}, // + {0x10, 0x04}, // + {0x11, 0x00}, // + {0x12, 0x05}, // + {0x13, 0x39}, // + {0x14, 0x36}, // + {0x15, 0x06}, // + {0x16, 0x00}, // + {0x17, 0x05}, // + {0x18, 0x00}, // + {0x19, 0x00}, // + {0x1a, 0x00}, // + {0x1b, 0x00}, // + {0x1c, 0x00}, // + {0x1d, 0x00}, // + {0x21, 0x01}, // + {0x22, 0x20}, // + {0x23, 0x20}, // + {0x24, 0x02}, // + {0x25, 0x00}, // + {0x26, 0x00}, // + {0x27, 0x08}, // + {0x28, 0x08}, // + {0x29, 0x00}, // + {0x2a, 0x00}, // + {0x2b, 0x00}, // + {0x2c, 0x00}, // + {0x2d, 0x00}, // + {0x2e, 0x33}, // + {0x2f, 0x30}, // + {0x30, 0x00}, // + {0x31, 0x00}, // + {0x32, 0x00}, // + {0x33, 0x00}, // + {0x34, 0x00}, // + {0x35, 0x00}, // + {0x36, 0x00}, // + {0x37, 0x00}, // + {0x38, 0x00}, // + {0x39, 0x00}, // + {0x3a, 0x00}, // + {0x3b, 0x00}, // + {0x3c, 0x00}, // + {0x3d, 0x00}, // + {0x3e, 0x00}, // + {0x3f, 0x00}, // + {0x40, 0xff}, // + {0x50, 0x00}, // + {0x60, 0x00}, // + {0x62, 0x00} // +}; + +static adscfg_t prvads1cfg[] = { + {0x00, 0x00}, // + {0x01, 0x0c}, // + {0x02, 0x14}, // + {0x03, 0x00}, // + {0x04, 0x00}, // + {0x05, 0x00}, // + {0x06, 0x00}, // + {0x07, 0x0f}, // + {0x08, 0xff}, // + {0x09, 0x00}, // + {0x0a, 0x00}, // + {0x0b, 0x07}, // + {0x0c, 0x78}, // + {0x0d, 0x00}, // + {0x0e, 0x00}, // + {0x0f, 0x00}, // + {0x10, 0x04}, // + {0x11, 0x00}, // + {0x12, 0x07}, // + {0x13, 0x3b}, // + {0x14, 0x24}, // + {0x15, 0x04}, // + {0x16, 0x00}, // + {0x17, 0x05}, // + {0x18, 0x00}, // + {0x19, 0x00}, // + {0x1a, 0x00}, // + {0x1b, 0x00}, // + {0x1c, 0x00}, // + {0x1d, 0x00}, // + {0x21, 0x01}, // + {0x22, 0x20}, // + {0x23, 0x20}, // + {0x24, 0x02}, // + {0x25, 0x00}, // + {0x26, 0x00}, // + {0x27, 0x08}, // + {0x28, 0x40}, // + {0x29, 0x00}, // + {0x2a, 0x00}, // + {0x2b, 0x00}, // + {0x2c, 0x00}, // + {0x2d, 0x00}, // + {0x2e, 0x33}, // + {0x2f, 0x30}, // + {0x30, 0x00}, // + {0x31, 0x00}, // + {0x32, 0x00}, // + {0x33, 0x00}, // + {0x34, 0x00}, // + {0x35, 0x00}, // + {0x36, 0x00}, // + {0x37, 0x00}, // + {0x38, 0x00}, // + {0x39, 0x00}, // + {0x3a, 0x00}, // + {0x3b, 0x00}, // + {0x3c, 0x00}, // + {0x3d, 0x00}, // + {0x3e, 0x00}, // + {0x3f, 0x00}, // + {0x40, 0xff}, // + {0x50, 0x00}, // + {0x60, 0x00}, // + {0x62, 0x00}, // +}; + +void config_lod(uint8_t aclvl_lod, uint8_t selac_lod, uint8_t shdn_lod, uint8_t acad_lod) { + uint8_t reg = 0; + reg |= aclvl_lod; + reg |= selac_lod << 2; + reg |= shdn_lod << 3; + reg |= acad_lod << 4; + ads1293_spi_writereg(&m_ads1293_0, TI_ADS1293_LOD_CN_REG, reg); +} + +void enable_lod(void) { + uint8_t reg = ads1293_spi_readreg(&m_ads1293_0, TI_ADS1293_CONFIG_REG); + reg |= 1 << 3; + ads1293_spi_writereg(&m_ads1293_0, TI_ADS1293_LOD_EN_REG, reg); +} + +void three_lead_ecg_ecg_init() { + nrf_drv_spi_config_t spi_config = NRF_DRV_SPI_DEFAULT_CONFIG; + spi_config.ss_pin = NRF_DRV_SPI_PIN_NOT_USED; // NRF_DRV_SPI_PIN_NOT_USED + spi_config.miso_pin = ADS1293_SPI_MISO_PIN; + spi_config.mosi_pin = ADS1293_SPI_MOSI_PIN; + spi_config.sck_pin = ADS1293_SPI_SCK_PIN; + spi_config.frequency = NRF_DRV_SPI_FREQ_8M; + spi_config.mode = NRF_DRV_SPI_MODE_3; + // spi_config.mode = + ZERROR_CHECK(nrf_drv_spi_init(&spi, &spi_config, NULL, NULL)); + + znrf_gpio_cfg_output(ADS1293_SPI_CS0_PIN, NRF_GPIO_PIN_NOPULL); + znrf_gpio_cfg_output(ADS1293_SPI_CS1_PIN, NRF_GPIO_PIN_NOPULL); + nrf_gpio_cfg_input(ADS1293_READY_PIN, NRF_GPIO_PIN_PULLUP); + + nrf_gpio_pin_set(ADS1293_SPI_CS0_PIN); + nrf_gpio_pin_set(ADS1293_SPI_CS1_PIN); + + m_ads1293_0.spi_tx_rx = ads1293_spi_tx_rx_0; + m_ads1293_0.id = 0; + // m_ads1293_1.spi_tx_rx = ads1293_spi_tx_rx_1; + // m_ads1293_1.id = 1; + + ads1293_spi_init(&m_ads1293_0, ads1293_spi_tx_rx_0); + ads1293_spi_init(&m_ads1293_1, ads1293_spi_tx_rx_1); + + uint8_t revid = ads1293_spi_readreg(&m_ads1293_0, TI_ADS1293_REVID_REG); + zdatachanel_send_log("ads1293_0 revid: %d\n", revid); + revid = ads1293_spi_readreg(&m_ads1293_1, TI_ADS1293_REVID_REG); + zdatachanel_send_log("ads1293_1 revid: %d\n", revid); + + zdatachanel_send_log("reset ads1293_0\n"); + ads1293_spi_writereg(&m_ads1293_0, TI_ADS1293_CONFIG_REG, 0); + nrf_delay_ms(1000); + + for (uint16_t i = 0; i < ZARRAY_SIZE(prvads0cfg); i++) { + ads1293_spi_writereg_and_check(&m_ads1293_0, prvads0cfg[i].add, prvads0cfg[i].data); + } + for (uint16_t i = 0; i < ZARRAY_SIZE(prvads1cfg); i++) { + ads1293_spi_writereg_and_check(&m_ads1293_1, prvads1cfg[i].add, prvads1cfg[i].data); + } + + // ads1293_spi_writereg(&m_ads1293_1, TI_ADS1293_CONFIG_REG, 0x01); +} + +static void zdatachanel_send_log(const char* fmt, ...) { + static char tx[256] = {0}; + int len = 0; + va_list args; + va_start(args, fmt); + len = vsprintf(tx, fmt, args); + len = strlen(tx); + int ret_val; + if (len >= 0) { + for (uint16_t i = 0; i < len; i++) { + do { + ret_val = app_uart_put(tx[i]); + } while (ret_val != NRF_SUCCESS); + } + return; + } + va_end(args); +} +#endif \ No newline at end of file diff --git a/app/src/main.c b/app/src/main.c index 9c7aab1..0d8b1ed 100644 --- a/app/src/main.c +++ b/app/src/main.c @@ -5,368 +5,31 @@ #include #include // -#include "app_uart.h" +#include "app_ble_service.h" #include "basic/ads1293/ads1293.h" #include "zble_module.h" #include "zdatachannel_service.h" #include "znordic_device_info_mgr.h" +// -#if defined(UART_PRESENT) -#include "nrf_uart.h" -#endif -#if defined(UARTE_PRESENT) -#include "nrf_uarte.h" -#endif - -#if 0 - -int main() { return 0; } -#endif - -#if 1 - -#define ADS1293_SPI_SCK_PIN (32 + 9) -#define ADS1293_SPI_MOSI_PIN 15 -#define ADS1293_SPI_MISO_PIN 20 -#define ADS1293_SPI_CS0_PIN 3 -#define ADS1293_SPI_CS1_PIN 29 -#define ADS1293_READY_PIN 31 -#define LINE_DET_PIN 10 - -#define UART_TX_BUF_SIZE 256 /**< UART TX buffer size. */ -#define UART_RX_BUF_SIZE 256 /**< UART RX buffer size. */ - -#include "board/ads_cfg.h" -void uart_error_handle(app_uart_evt_t* p_event) {} - -/**@brief Function for initializing the UART. */ -static void uart_init(void) { - ret_code_t err_code; - - app_uart_comm_params_t const comm_params = { - .rx_pin_no = UART_PIN_DISCONNECTED, - .tx_pin_no = 0, - .rts_pin_no = UART_PIN_DISCONNECTED, - .cts_pin_no = UART_PIN_DISCONNECTED, - .flow_control = APP_UART_FLOW_CONTROL_DISABLED, - .use_parity = false, - .baud_rate = UART_BAUDRATE_BAUDRATE_Baud115200, - }; - APP_UART_FIFO_INIT(&comm_params, UART_RX_BUF_SIZE, UART_TX_BUF_SIZE, uart_error_handle, APP_IRQ_PRIORITY_HIGHEST, err_code); - APP_ERROR_CHECK(err_code); -} - -/******************************************************************************* - * 3导联-ADS1293-测试 * - *******************************************************************************/ -APP_TIMER_DEF(m_init_tmr); -APP_TIMER_DEF(m_report_tmr); -ZDATACHANNEL_DEF(m_zhrs, 2 /**/, 1 /*client num*/); -static const nrf_drv_spi_t spi = NRF_DRV_SPI_INSTANCE(2); /**< SPI instance. */ -static ads1293_t m_ads1293_0; // U2 -static ads1293_t m_ads1293_1; // U3 -static void zdatachanel_send_log(const char* fmt, ...); -static void three_lead_ecg_ecg_init(); - -uint32_t get_ready_pin_state_get() { return nrf_gpio_pin_read(ADS1293_READY_PIN); } - -static 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 = NULL; - ZERROR_CHECK(zdatachannel_init(&m_zhrs, &zdatachannle_init)); -} -static int changecount = 0; -void dump_state() { - static uint32_t last = 0; - uint32_t nows = znordic_rtc_gettime_s(); - if (nows != last) { - zdatachanel_send_log("%d\n", changecount); - - uint8_t leadoffstate = ads1293_spi_readreg(&m_ads1293_0, TI_ADS1293_ERROR_LOD_REG); - zdatachanel_send_log("%d%d%d%d_%d%d%d%d\n", // - leadoffstate >> 7 & 0x1, leadoffstate >> 6 & 0x1, leadoffstate >> 5 & 0x1, leadoffstate >> 4 & 0x1, // - leadoffstate >> 3 & 0x1, leadoffstate >> 2 & 0x1, leadoffstate >> 1 & 0x1, leadoffstate >> 0 & 0x1); // - - last = nows; - changecount = 0; - } +APP_TIMER_DEF(state_machine_scheduler_tmr); +static void test_tx_timer_cb(void* p_context) { // + ZLOGI("test_tx_timer_cb"); + ThreeLeadECG_led_green_toggle(); } - int main() { APP_SCHED_INIT(APP_TIMER_SCHED_EVENT_DATA_SIZE, 20); znordic_init(); static zble_module_cfg_t cfg = // { .deviceName = "ThreeLeadECG", - .on_service_init = on_service_init, + .on_service_init = AppBleService_onServiceInitCB, }; zble_module_init(&cfg); + AppBleService_startAdv(); + ThreeLeadECG_led_init(); + ZERROR_CHECK(app_timer_create(&state_machine_scheduler_tmr, APP_TIMER_MODE_REPEATED, test_tx_timer_cb)); + ZERROR_CHECK(app_timer_start(state_machine_scheduler_tmr, APP_TIMER_TICKS(1000), NULL)); NRF_LOG_INFO("compile time :%s", __TIME__); - uart_init(); - - nrf_gpio_cfg_input(LINE_DET_PIN, NRF_GPIO_PIN_PULLUP); - three_lead_ecg_ecg_init(); - ads1293_spi_writereg(&m_ads1293_0, TI_ADS1293_CONFIG_REG, 0x01); - ads1293_spi_writereg(&m_ads1293_1, TI_ADS1293_CONFIG_REG, 0x01); - - while (true) { - app_sched_execute(); - if (NRF_LOG_PROCESS() == false) { - // nrf_pwr_mgmt_run(); - } - static bool state = false; - bool now = get_ready_pin_state_get(); - if (state != now) { - state = now; - changecount++; - - if (now) { - uint32_t val = 0; - ads1293_read_ecg(&m_ads1293_0, 1, &val); - zdatachanel_send_log("%d\n", val); - } - } - // dump_state(); - } -} - -static void ads1293_spi_tx_rx_0(uint8_t* tx, uint8_t* rx, uint8_t len) { - nrf_gpio_pin_clear(ADS1293_SPI_CS0_PIN); - nrf_drv_spi_transfer(&spi, tx, len, rx, len); - nrf_gpio_pin_set(ADS1293_SPI_CS0_PIN); -} -static void ads1293_spi_tx_rx_1(uint8_t* tx, uint8_t* rx, uint8_t len) { - nrf_gpio_pin_clear(ADS1293_SPI_CS1_PIN); - nrf_drv_spi_transfer(&spi, tx, len, rx, len); - nrf_gpio_pin_set(ADS1293_SPI_CS1_PIN); -} - -static void ads1293_spi_writereg_and_check(ads1293_t* ads, uint8_t addr, uint8_t data) { - uint8_t readbak = 0; - // readonly add - if (addr == 0x19 || addr == 0x1a || addr == 0x1b || addr == 0x1c || addr == 0x40 || addr == 0x30) { - return; - } - ads1293_spi_writereg_and_readbak(ads, addr, data, &readbak); - if (readbak != data) { - zdatachanel_send_log("ads_%d write %x failed,w:%x readbak:%x\n", ads->id, addr, data, readbak); - } -} - -static adscfg_t prvads0cfg[] = { - {0x00, 0x00}, // - {0x01, 0x19}, // - {0x02, 0x11}, // - {0x03, 0x00}, // - {0x04, 0x00}, // - {0x05, 0x00}, // - {0x06, 0x00}, // - {0x07, 0x0f}, // - {0x08, 0xff}, // - {0x09, 0x00}, // - {0x0a, 0x07}, // - {0x0b, 0x07}, // - {0x0c, 0x74}, // - {0x0d, 0x01}, // - {0x0e, 0x02}, // - {0x0f, 0x03}, // - {0x10, 0x04}, // - {0x11, 0x00}, // - {0x12, 0x05}, // - {0x13, 0x39}, // - {0x14, 0x36}, // - {0x15, 0x06}, // - {0x16, 0x00}, // - {0x17, 0x05}, // - {0x18, 0x00}, // - {0x19, 0x00}, // - {0x1a, 0x00}, // - {0x1b, 0x00}, // - {0x1c, 0x00}, // - {0x1d, 0x00}, // - {0x21, 0x01}, // - {0x22, 0x20}, // - {0x23, 0x20}, // - {0x24, 0x02}, // - {0x25, 0x00}, // - {0x26, 0x00}, // - {0x27, 0x08}, // - {0x28, 0x08}, // - {0x29, 0x00}, // - {0x2a, 0x00}, // - {0x2b, 0x00}, // - {0x2c, 0x00}, // - {0x2d, 0x00}, // - {0x2e, 0x33}, // - {0x2f, 0x30}, // - {0x30, 0x00}, // - {0x31, 0x00}, // - {0x32, 0x00}, // - {0x33, 0x00}, // - {0x34, 0x00}, // - {0x35, 0x00}, // - {0x36, 0x00}, // - {0x37, 0x00}, // - {0x38, 0x00}, // - {0x39, 0x00}, // - {0x3a, 0x00}, // - {0x3b, 0x00}, // - {0x3c, 0x00}, // - {0x3d, 0x00}, // - {0x3e, 0x00}, // - {0x3f, 0x00}, // - {0x40, 0xff}, // - {0x50, 0x00}, // - {0x60, 0x00}, // - {0x62, 0x00} // -}; - -static adscfg_t prvads1cfg[] = { - {0x00, 0x00}, // - {0x01, 0x0c}, // - {0x02, 0x14}, // - {0x03, 0x00}, // - {0x04, 0x00}, // - {0x05, 0x00}, // - {0x06, 0x00}, // - {0x07, 0x0f}, // - {0x08, 0xff}, // - {0x09, 0x00}, // - {0x0a, 0x00}, // - {0x0b, 0x07}, // - {0x0c, 0x78}, // - {0x0d, 0x00}, // - {0x0e, 0x00}, // - {0x0f, 0x00}, // - {0x10, 0x04}, // - {0x11, 0x00}, // - {0x12, 0x07}, // - {0x13, 0x3b}, // - {0x14, 0x24}, // - {0x15, 0x04}, // - {0x16, 0x00}, // - {0x17, 0x05}, // - {0x18, 0x00}, // - {0x19, 0x00}, // - {0x1a, 0x00}, // - {0x1b, 0x00}, // - {0x1c, 0x00}, // - {0x1d, 0x00}, // - {0x21, 0x01}, // - {0x22, 0x20}, // - {0x23, 0x20}, // - {0x24, 0x02}, // - {0x25, 0x00}, // - {0x26, 0x00}, // - {0x27, 0x08}, // - {0x28, 0x40}, // - {0x29, 0x00}, // - {0x2a, 0x00}, // - {0x2b, 0x00}, // - {0x2c, 0x00}, // - {0x2d, 0x00}, // - {0x2e, 0x33}, // - {0x2f, 0x30}, // - {0x30, 0x00}, // - {0x31, 0x00}, // - {0x32, 0x00}, // - {0x33, 0x00}, // - {0x34, 0x00}, // - {0x35, 0x00}, // - {0x36, 0x00}, // - {0x37, 0x00}, // - {0x38, 0x00}, // - {0x39, 0x00}, // - {0x3a, 0x00}, // - {0x3b, 0x00}, // - {0x3c, 0x00}, // - {0x3d, 0x00}, // - {0x3e, 0x00}, // - {0x3f, 0x00}, // - {0x40, 0xff}, // - {0x50, 0x00}, // - {0x60, 0x00}, // - {0x62, 0x00}, // -}; - -void config_lod(uint8_t aclvl_lod, uint8_t selac_lod, uint8_t shdn_lod, uint8_t acad_lod) { - uint8_t reg = 0; - reg |= aclvl_lod; - reg |= selac_lod << 2; - reg |= shdn_lod << 3; - reg |= acad_lod << 4; - ads1293_spi_writereg(&m_ads1293_0, TI_ADS1293_LOD_CN_REG, reg); -} - -void enable_lod(void) { - uint8_t reg = ads1293_spi_readreg(&m_ads1293_0, TI_ADS1293_CONFIG_REG); - reg |= 1 << 3; - ads1293_spi_writereg(&m_ads1293_0, TI_ADS1293_LOD_EN_REG, reg); -} - -void three_lead_ecg_ecg_init() { - nrf_drv_spi_config_t spi_config = NRF_DRV_SPI_DEFAULT_CONFIG; - spi_config.ss_pin = NRF_DRV_SPI_PIN_NOT_USED; // NRF_DRV_SPI_PIN_NOT_USED - spi_config.miso_pin = ADS1293_SPI_MISO_PIN; - spi_config.mosi_pin = ADS1293_SPI_MOSI_PIN; - spi_config.sck_pin = ADS1293_SPI_SCK_PIN; - spi_config.frequency = NRF_DRV_SPI_FREQ_8M; - spi_config.mode = NRF_DRV_SPI_MODE_3; - // spi_config.mode = - ZERROR_CHECK(nrf_drv_spi_init(&spi, &spi_config, NULL, NULL)); - - znrf_gpio_cfg_output(ADS1293_SPI_CS0_PIN, NRF_GPIO_PIN_NOPULL); - znrf_gpio_cfg_output(ADS1293_SPI_CS1_PIN, NRF_GPIO_PIN_NOPULL); - nrf_gpio_cfg_input(ADS1293_READY_PIN, NRF_GPIO_PIN_PULLUP); - - nrf_gpio_pin_set(ADS1293_SPI_CS0_PIN); - nrf_gpio_pin_set(ADS1293_SPI_CS1_PIN); - - m_ads1293_0.spi_tx_rx = ads1293_spi_tx_rx_0; - m_ads1293_0.id = 0; - // m_ads1293_1.spi_tx_rx = ads1293_spi_tx_rx_1; - // m_ads1293_1.id = 1; - - ads1293_spi_init(&m_ads1293_0, ads1293_spi_tx_rx_0); - ads1293_spi_init(&m_ads1293_1, ads1293_spi_tx_rx_1); - - uint8_t revid = ads1293_spi_readreg(&m_ads1293_0, TI_ADS1293_REVID_REG); - zdatachanel_send_log("ads1293_0 revid: %d\n", revid); - revid = ads1293_spi_readreg(&m_ads1293_1, TI_ADS1293_REVID_REG); - zdatachanel_send_log("ads1293_1 revid: %d\n", revid); - - zdatachanel_send_log("reset ads1293_0\n"); - ads1293_spi_writereg(&m_ads1293_0, TI_ADS1293_CONFIG_REG, 0); - nrf_delay_ms(1000); - - for (uint16_t i = 0; i < ZARRAY_SIZE(prvads0cfg); i++) { - ads1293_spi_writereg_and_check(&m_ads1293_0, prvads0cfg[i].add, prvads0cfg[i].data); - } - for (uint16_t i = 0; i < ZARRAY_SIZE(prvads1cfg); i++) { - ads1293_spi_writereg_and_check(&m_ads1293_1, prvads1cfg[i].add, prvads1cfg[i].data); - } - - // ads1293_spi_writereg(&m_ads1293_1, TI_ADS1293_CONFIG_REG, 0x01); -} - -static void zdatachanel_send_log(const char* fmt, ...) { - static char tx[256] = {0}; - int len = 0; - va_list args; - va_start(args, fmt); - len = vsprintf(tx, fmt, args); - len = strlen(tx); - int ret_val; - if (len >= 0) { - for (uint16_t i = 0; i < len; i++) { - do { - ret_val = app_uart_put(tx[i]); - } while (ret_val != NRF_SUCCESS); - } - return; - } - va_end(args); + znordic_loop(); } -#endif \ No newline at end of file diff --git a/app/src/sample_data_manager_service.c b/app/src/sample_data_manager_service.c new file mode 100644 index 0000000..4d74b02 --- /dev/null +++ b/app/src/sample_data_manager_service.c @@ -0,0 +1,155 @@ +#include "sample_data_manager_service.h" + +#include "board/board.h" +#include "board/board_sdcard_driver.h" +#include "znordic.h" +/******************************************************************************* + * 全局变量 * + *******************************************************************************/ +static FIL m_default_file_handler; +static sample_data_fileinfo_list_t m_sample_fileinfo_list; +static sample_data_fileinfo_t m_sample_fileinfo[FILE_MAX_COUNT]; + +/******************************************************************************* + * 接口层 * + *******************************************************************************/ + +static void read_file_info() { + /** + * @brief + * + * fdate: + * bit15:9 + * Year origin from 1980 (0..127) + * bit8:5 + * Month (1..12) + * bit4:0 + * Day of the month(1..31) + * ftime: + * bit15:11 + * Hour (0..23) + * bit10:5 + * Minute (0..59) + * bit4:0 + * Second / 2 (0..29) + */ + FILINFO fno; + FRESULT ff_result = f_stat("0.bin", &fno); + m_sample_fileinfo_list.fileinfo[0] = &m_sample_fileinfo[0]; + + if (ff_result == FR_OK) { + static sample_data_filename_t _filename; + _filename.year = (fno.fdate >> 9) + 1980 - 2000; + _filename.month = (fno.fdate >> 5) & 0x0F; + _filename.day = fno.fdate & 0x1F; + _filename.hour = (fno.ftime >> 11); + _filename.min = (fno.ftime >> 5) & 0x3F; + _filename.sec = (fno.ftime & 0x1F) * 2; + m_sample_fileinfo_list.fileinfo[0]->size = fno.fsize; + m_sample_fileinfo_list.count = 1; + } else { + m_sample_fileinfo_list.fileinfo[0]->size = 0; + m_sample_fileinfo_list.count = 0; + } +} + +/** + * @brief 文件驱动管理 + */ +void sample_data_mgr_init() { + Board_sdcardInit(); + + // 先连接到单片机,读取下文件状态信息 + sample_data_mgr_change_to_local_mode(); + sample_data_mgr_change_to_ext_mode(); +} +void sample_data_mgr_loadDriver() { + // donothing +} +void sample_data_mgr_unloadDriver() { + // donothin +} +typedef struct { + uint8_t filename[8]; + uint32_t filesize; + +} disk_state_t; + +/** + * @brief 存储器连接单片机 + */ +void sample_data_mgr_change_to_local_mode() { + Board_sdcardConnectToInternal(); + read_file_info(); +} +/** + * @brief 存储器连接外部typec + */ +void sample_data_mgr_change_to_ext_mode() { + if (Board_sdcardGetConnectTo() == kConnectToInternal) { + read_file_info(); + return; + } + Board_sdcardConnectToExt(); +} + +/** + * @brief 打开文件 + * + * @param filename + * @param flag + * @return int32_t + */ + +static FIL m_default_file_handler; +static bool m_is_open; +int32_t sample_data_mgr_open(sample_data_filename_t* filename, wrflag_t flag) { + FRESULT ff_result = f_open(&m_default_file_handler, (const TCHAR*)"0.bin", FA_CREATE_ALWAYS | FA_READ | FA_WRITE); + ZASSERT(ff_result == FR_OK); + m_is_open = true; + return 1; +} +int32_t sample_data_mgr_close(int32_t fd) { + ZASSERT(m_is_open); + FRESULT ff_result = f_close(&m_default_file_handler); + ZASSERT(ff_result == FR_OK); + m_is_open = false; + return 0; +} +int32_t sample_data_mgr_write(int32_t fd, const uint8_t* data, int32_t size) { + ZASSERT(m_is_open); + UINT write_size; + FRESULT ff_result = f_write(&m_default_file_handler, data, size, &write_size); + ZASSERT(ff_result == FR_OK); + return write_size; +} +int32_t sample_data_mgr_read(int32_t fd, uint8_t* data, int32_t size) { + ZASSERT(m_is_open); + UINT read_size; + FRESULT ff_result = f_read(&m_default_file_handler, data, size, &read_size); + ZASSERT(ff_result == FR_OK); + return read_size; +} +int32_t sample_data_mgr_get_file_size_by_fd(int32_t fd) { + ZASSERT(m_is_open); + return f_size(&m_default_file_handler); +} + +int32_t sample_data_mgr_delete_file(sample_data_filename_t* filename) { + if (Board_sdcardGetConnectTo() == kConnectToExt) { + /** + * @brief + * 由于设备空闲阶段,SD卡连接的是外部读卡器,所以无法删除文件 + */ + ZLOGW("unsupport now"); + return 0; + } + f_unlink((const TCHAR*)"0.bin"); + return 0; +} + +sample_data_fileinfo_list_t* sample_data_mgr_get_fileinfo_list() { // + return &m_sample_fileinfo_list; +} +bool sample_data_mgr_storage_is_full() { return m_sample_fileinfo_list.count >= FILE_MAX_COUNT; } +int32_t sample_data_mgr_get_file_num() { return m_sample_fileinfo_list.count; } diff --git a/app/src/sample_data_manager_service.h b/app/src/sample_data_manager_service.h new file mode 100644 index 0000000..a6f7b95 --- /dev/null +++ b/app/src/sample_data_manager_service.h @@ -0,0 +1,78 @@ +/** + * @file sample_data_manager_service.h + * @author zhaohe (h_zhaohe@domain.com) + * @brief 采样数据存储服务 + * @version 0.1 + * @date 2024-02-01 + * + * @copyright Copyright (c) 2024 + * + */ +#pragma once + +#include +#include + +#include "board/board.h" + +typedef struct { + uint8_t year; // from 2000 + uint8_t month; // 1-12 + uint8_t day; // 1-31 + uint8_t hour; // 0-23 + uint8_t min; // 0-59 + uint8_t sec; // 0-59 + 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 enum { + kwrflag_read_only, + kwrflag_write_only, +} wrflag_t; + +typedef struct { + sample_data_fileinfo_t* fileinfo[FILE_MAX_COUNT]; + int count; +} sample_data_fileinfo_list_t; + +/** + * @brief 文件驱动管理 + */ +void sample_data_mgr_init(); +void sample_data_mgr_loadDriver(); +void sample_data_mgr_unloadDriver(); +/******************************************************************************* + * 模式切换操作 * + *******************************************************************************/ + +/** + * @brief 存储器连接单片机 + */ +void sample_data_mgr_change_to_local_mode(); +/** + * @brief 存储器连接外部typec + */ +void sample_data_mgr_change_to_ext_mode(); + +/******************************************************************************* + * FILE_OPERATION * + *******************************************************************************/ +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); +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(); diff --git a/libznordic b/libznordic index 92a15d4..2e46516 160000 --- a/libznordic +++ b/libznordic @@ -1 +1 @@ -Subproject commit 92a15d47cbe16579d92ba8385ddbeaeb37778506 +Subproject commit 2e46516dec82a92dd796312c6787f35e5adf7922