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/ble_cmd_process_service.c b/app/src/bak/ble_cmd_process_service.c
similarity index 100%
rename from app/src/ble_cmd_process_service.c
rename to app/src/bak/ble_cmd_process_service.c
diff --git a/app/src/ble_cmd_process_service.h b/app/src/bak/ble_cmd_process_service.h
similarity index 100%
rename from app/src/ble_cmd_process_service.h
rename to app/src/bak/ble_cmd_process_service.h
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/board/three_lead_board.c b/app/src/bak/three_lead_board.c
similarity index 99%
rename from app/src/board/three_lead_board.c
rename to app/src/bak/three_lead_board.c
index df1a802..bf27630 100644
--- a/app/src/board/three_lead_board.c
+++ b/app/src/bak/three_lead_board.c
@@ -113,6 +113,11 @@ void ThreeLeadECG_led_green_set_state(bool state) {
}
}
+void ThreeLeadECG_led_green_toggle(){
+ nrf_gpio_pin_toggle(LED_GREEN_PIN);
+}
+
+
/*******************************************************************************
* BATTERY *
*******************************************************************************/
diff --git a/app/src/board/three_lead_board.h b/app/src/bak/three_lead_board.h
similarity index 97%
rename from app/src/board/three_lead_board.h
rename to app/src/bak/three_lead_board.h
index fef15fd..e630954 100644
--- a/app/src/board/three_lead_board.h
+++ b/app/src/bak/three_lead_board.h
@@ -29,6 +29,7 @@ void ThreeLeadECG_beep_set_state(bool state);
*******************************************************************************/
void ThreeLeadECG_led_init();
void ThreeLeadECG_led_green_set_state(bool state);
+void ThreeLeadECG_led_green_toggle();
/*******************************************************************************
* BATTERY *
*******************************************************************************/
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/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/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