Browse Source

update

master
zhaohe 1 year ago
parent
commit
358f0a8061
  1. 7
      .vscode/settings.json
  2. 279
      README.md
  3. 162
      app/app.uvoptx
  4. 10
      app/app.uvprojx
  5. 4
      app/config/sdk_config.h
  6. 57
      app/src/app_ble_service.c
  7. 13
      app/src/app_ble_service.h
  8. 35
      app/src/app_event.h
  9. 0
      app/src/bak/ble_cmd_process_service.c
  10. 0
      app/src/bak/ble_cmd_process_service.h
  11. 152
      app/src/bak/heart_wave_sample_service.c
  12. 15
      app/src/bak/heart_wave_sample_service.h
  13. 5
      app/src/bak/three_lead_board.c
  14. 1
      app/src/bak/three_lead_board.h
  15. 24
      app/src/basic/ads1293/ads1293.c
  16. 7
      app/src/basic/ads1293/ads1293.h
  17. 7
      app/src/basic/config.h
  18. 101
      app/src/board/TI_ADS1293_register_settings.h
  19. 148
      app/src/board/ads_cfg.h
  20. 0
      app/src/board/board.c
  21. 61
      app/src/board/board.h
  22. 36
      app/src/board/board_battery_state.c
  23. 15
      app/src/board/board_battery_state.h
  24. 93
      app/src/board/board_beep_ctrl.c
  25. 24
      app/src/board/board_beep_ctrl.h
  26. 24
      app/src/board/board_button.c
  27. 18
      app/src/board/board_button.h
  28. 70
      app/src/board/board_light_ctrl.c
  29. 23
      app/src/board/board_light_ctrl.h
  30. 176
      app/src/board/board_sdcard_driver.c
  31. 19
      app/src/board/board_sdcard_driver.h
  32. 13
      app/src/device_state.c
  33. 79
      app/src/device_state.h
  34. 342
      app/src/heart_wave_sample_service.c
  35. 34
      app/src/heart_wave_sample_service.h
  36. 372
      app/src/main.bak.c
  37. 361
      app/src/main.c
  38. 155
      app/src/sample_data_manager_service.c
  39. 78
      app/src/sample_data_manager_service.h
  40. 2
      libznordic

7
.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"
}

279
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. 优化蜂鸣器的声音
```

162
app/app.uvoptx

@ -439,6 +439,18 @@
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
<File>
<GroupNumber>1</GroupNumber>
<FileNumber>7</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>.\src\app_ble_service.c</PathWithFileName>
<FilenameWithoutPath>app_ble_service.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
</Group>
<Group>
@ -449,7 +461,7 @@
<RteFlg>0</RteFlg>
<File>
<GroupNumber>2</GroupNumber>
<FileNumber>7</FileNumber>
<FileNumber>8</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -469,7 +481,7 @@
<RteFlg>0</RteFlg>
<File>
<GroupNumber>3</GroupNumber>
<FileNumber>8</FileNumber>
<FileNumber>9</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -481,7 +493,7 @@
</File>
<File>
<GroupNumber>3</GroupNumber>
<FileNumber>9</FileNumber>
<FileNumber>10</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -501,7 +513,7 @@
<RteFlg>0</RteFlg>
<File>
<GroupNumber>4</GroupNumber>
<FileNumber>10</FileNumber>
<FileNumber>11</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -521,7 +533,7 @@
<RteFlg>0</RteFlg>
<File>
<GroupNumber>5</GroupNumber>
<FileNumber>11</FileNumber>
<FileNumber>12</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -533,7 +545,7 @@
</File>
<File>
<GroupNumber>5</GroupNumber>
<FileNumber>12</FileNumber>
<FileNumber>13</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -545,7 +557,7 @@
</File>
<File>
<GroupNumber>5</GroupNumber>
<FileNumber>13</FileNumber>
<FileNumber>14</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -557,7 +569,7 @@
</File>
<File>
<GroupNumber>5</GroupNumber>
<FileNumber>14</FileNumber>
<FileNumber>15</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -569,7 +581,7 @@
</File>
<File>
<GroupNumber>5</GroupNumber>
<FileNumber>15</FileNumber>
<FileNumber>16</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -581,7 +593,7 @@
</File>
<File>
<GroupNumber>5</GroupNumber>
<FileNumber>16</FileNumber>
<FileNumber>17</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -593,7 +605,7 @@
</File>
<File>
<GroupNumber>5</GroupNumber>
<FileNumber>17</FileNumber>
<FileNumber>18</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -605,7 +617,7 @@
</File>
<File>
<GroupNumber>5</GroupNumber>
<FileNumber>18</FileNumber>
<FileNumber>19</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -625,7 +637,7 @@
<RteFlg>0</RteFlg>
<File>
<GroupNumber>6</GroupNumber>
<FileNumber>19</FileNumber>
<FileNumber>20</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -645,7 +657,7 @@
<RteFlg>0</RteFlg>
<File>
<GroupNumber>7</GroupNumber>
<FileNumber>20</FileNumber>
<FileNumber>21</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -657,7 +669,7 @@
</File>
<File>
<GroupNumber>7</GroupNumber>
<FileNumber>21</FileNumber>
<FileNumber>22</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -669,7 +681,7 @@
</File>
<File>
<GroupNumber>7</GroupNumber>
<FileNumber>22</FileNumber>
<FileNumber>23</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -681,7 +693,7 @@
</File>
<File>
<GroupNumber>7</GroupNumber>
<FileNumber>23</FileNumber>
<FileNumber>24</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -693,7 +705,7 @@
</File>
<File>
<GroupNumber>7</GroupNumber>
<FileNumber>24</FileNumber>
<FileNumber>25</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -705,7 +717,7 @@
</File>
<File>
<GroupNumber>7</GroupNumber>
<FileNumber>25</FileNumber>
<FileNumber>26</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -717,7 +729,7 @@
</File>
<File>
<GroupNumber>7</GroupNumber>
<FileNumber>26</FileNumber>
<FileNumber>27</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -729,7 +741,7 @@
</File>
<File>
<GroupNumber>7</GroupNumber>
<FileNumber>27</FileNumber>
<FileNumber>28</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -741,7 +753,7 @@
</File>
<File>
<GroupNumber>7</GroupNumber>
<FileNumber>28</FileNumber>
<FileNumber>29</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -753,7 +765,7 @@
</File>
<File>
<GroupNumber>7</GroupNumber>
<FileNumber>29</FileNumber>
<FileNumber>30</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -765,7 +777,7 @@
</File>
<File>
<GroupNumber>7</GroupNumber>
<FileNumber>30</FileNumber>
<FileNumber>31</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -777,7 +789,7 @@
</File>
<File>
<GroupNumber>7</GroupNumber>
<FileNumber>31</FileNumber>
<FileNumber>32</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -789,7 +801,7 @@
</File>
<File>
<GroupNumber>7</GroupNumber>
<FileNumber>32</FileNumber>
<FileNumber>33</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -801,7 +813,7 @@
</File>
<File>
<GroupNumber>7</GroupNumber>
<FileNumber>33</FileNumber>
<FileNumber>34</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -813,7 +825,7 @@
</File>
<File>
<GroupNumber>7</GroupNumber>
<FileNumber>34</FileNumber>
<FileNumber>35</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -825,7 +837,7 @@
</File>
<File>
<GroupNumber>7</GroupNumber>
<FileNumber>35</FileNumber>
<FileNumber>36</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -837,7 +849,7 @@
</File>
<File>
<GroupNumber>7</GroupNumber>
<FileNumber>36</FileNumber>
<FileNumber>37</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -849,7 +861,7 @@
</File>
<File>
<GroupNumber>7</GroupNumber>
<FileNumber>37</FileNumber>
<FileNumber>38</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -861,7 +873,7 @@
</File>
<File>
<GroupNumber>7</GroupNumber>
<FileNumber>38</FileNumber>
<FileNumber>39</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -873,7 +885,7 @@
</File>
<File>
<GroupNumber>7</GroupNumber>
<FileNumber>39</FileNumber>
<FileNumber>40</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -893,7 +905,7 @@
<RteFlg>0</RteFlg>
<File>
<GroupNumber>8</GroupNumber>
<FileNumber>40</FileNumber>
<FileNumber>41</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -905,7 +917,7 @@
</File>
<File>
<GroupNumber>8</GroupNumber>
<FileNumber>41</FileNumber>
<FileNumber>42</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -917,7 +929,7 @@
</File>
<File>
<GroupNumber>8</GroupNumber>
<FileNumber>42</FileNumber>
<FileNumber>43</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -929,7 +941,7 @@
</File>
<File>
<GroupNumber>8</GroupNumber>
<FileNumber>43</FileNumber>
<FileNumber>44</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -941,7 +953,7 @@
</File>
<File>
<GroupNumber>8</GroupNumber>
<FileNumber>44</FileNumber>
<FileNumber>45</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -953,7 +965,7 @@
</File>
<File>
<GroupNumber>8</GroupNumber>
<FileNumber>45</FileNumber>
<FileNumber>46</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -965,7 +977,7 @@
</File>
<File>
<GroupNumber>8</GroupNumber>
<FileNumber>46</FileNumber>
<FileNumber>47</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -977,7 +989,7 @@
</File>
<File>
<GroupNumber>8</GroupNumber>
<FileNumber>47</FileNumber>
<FileNumber>48</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -989,7 +1001,7 @@
</File>
<File>
<GroupNumber>8</GroupNumber>
<FileNumber>48</FileNumber>
<FileNumber>49</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -1001,7 +1013,7 @@
</File>
<File>
<GroupNumber>8</GroupNumber>
<FileNumber>49</FileNumber>
<FileNumber>50</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -1013,7 +1025,7 @@
</File>
<File>
<GroupNumber>8</GroupNumber>
<FileNumber>50</FileNumber>
<FileNumber>51</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -1025,7 +1037,7 @@
</File>
<File>
<GroupNumber>8</GroupNumber>
<FileNumber>51</FileNumber>
<FileNumber>52</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -1037,7 +1049,7 @@
</File>
<File>
<GroupNumber>8</GroupNumber>
<FileNumber>52</FileNumber>
<FileNumber>53</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -1049,7 +1061,7 @@
</File>
<File>
<GroupNumber>8</GroupNumber>
<FileNumber>53</FileNumber>
<FileNumber>54</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -1061,7 +1073,7 @@
</File>
<File>
<GroupNumber>8</GroupNumber>
<FileNumber>54</FileNumber>
<FileNumber>55</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -1073,7 +1085,7 @@
</File>
<File>
<GroupNumber>8</GroupNumber>
<FileNumber>55</FileNumber>
<FileNumber>56</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -1085,7 +1097,7 @@
</File>
<File>
<GroupNumber>8</GroupNumber>
<FileNumber>56</FileNumber>
<FileNumber>57</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -1097,7 +1109,7 @@
</File>
<File>
<GroupNumber>8</GroupNumber>
<FileNumber>57</FileNumber>
<FileNumber>58</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -1109,7 +1121,7 @@
</File>
<File>
<GroupNumber>8</GroupNumber>
<FileNumber>58</FileNumber>
<FileNumber>59</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -1121,7 +1133,7 @@
</File>
<File>
<GroupNumber>8</GroupNumber>
<FileNumber>59</FileNumber>
<FileNumber>60</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -1133,7 +1145,7 @@
</File>
<File>
<GroupNumber>8</GroupNumber>
<FileNumber>60</FileNumber>
<FileNumber>61</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -1145,7 +1157,7 @@
</File>
<File>
<GroupNumber>8</GroupNumber>
<FileNumber>61</FileNumber>
<FileNumber>62</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -1157,7 +1169,7 @@
</File>
<File>
<GroupNumber>8</GroupNumber>
<FileNumber>62</FileNumber>
<FileNumber>63</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -1169,7 +1181,7 @@
</File>
<File>
<GroupNumber>8</GroupNumber>
<FileNumber>63</FileNumber>
<FileNumber>64</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -1181,7 +1193,7 @@
</File>
<File>
<GroupNumber>8</GroupNumber>
<FileNumber>64</FileNumber>
<FileNumber>65</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -1193,7 +1205,7 @@
</File>
<File>
<GroupNumber>8</GroupNumber>
<FileNumber>65</FileNumber>
<FileNumber>66</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -1205,7 +1217,7 @@
</File>
<File>
<GroupNumber>8</GroupNumber>
<FileNumber>66</FileNumber>
<FileNumber>67</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -1225,7 +1237,7 @@
<RteFlg>0</RteFlg>
<File>
<GroupNumber>9</GroupNumber>
<FileNumber>67</FileNumber>
<FileNumber>68</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -1237,7 +1249,7 @@
</File>
<File>
<GroupNumber>9</GroupNumber>
<FileNumber>68</FileNumber>
<FileNumber>69</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -1249,7 +1261,7 @@
</File>
<File>
<GroupNumber>9</GroupNumber>
<FileNumber>69</FileNumber>
<FileNumber>70</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -1261,7 +1273,7 @@
</File>
<File>
<GroupNumber>9</GroupNumber>
<FileNumber>70</FileNumber>
<FileNumber>71</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -1273,7 +1285,7 @@
</File>
<File>
<GroupNumber>9</GroupNumber>
<FileNumber>71</FileNumber>
<FileNumber>72</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -1285,7 +1297,7 @@
</File>
<File>
<GroupNumber>9</GroupNumber>
<FileNumber>72</FileNumber>
<FileNumber>73</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -1305,7 +1317,7 @@
<RteFlg>0</RteFlg>
<File>
<GroupNumber>10</GroupNumber>
<FileNumber>73</FileNumber>
<FileNumber>74</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -1317,7 +1329,7 @@
</File>
<File>
<GroupNumber>10</GroupNumber>
<FileNumber>74</FileNumber>
<FileNumber>75</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -1329,7 +1341,7 @@
</File>
<File>
<GroupNumber>10</GroupNumber>
<FileNumber>75</FileNumber>
<FileNumber>76</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -1349,7 +1361,7 @@
<RteFlg>0</RteFlg>
<File>
<GroupNumber>11</GroupNumber>
<FileNumber>76</FileNumber>
<FileNumber>77</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -1361,7 +1373,7 @@
</File>
<File>
<GroupNumber>11</GroupNumber>
<FileNumber>77</FileNumber>
<FileNumber>78</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -1373,7 +1385,7 @@
</File>
<File>
<GroupNumber>11</GroupNumber>
<FileNumber>78</FileNumber>
<FileNumber>79</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -1393,7 +1405,7 @@
<RteFlg>0</RteFlg>
<File>
<GroupNumber>12</GroupNumber>
<FileNumber>79</FileNumber>
<FileNumber>80</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -1413,7 +1425,7 @@
<RteFlg>0</RteFlg>
<File>
<GroupNumber>13</GroupNumber>
<FileNumber>80</FileNumber>
<FileNumber>81</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
@ -1425,7 +1437,7 @@
</File>
<File>
<GroupNumber>13</GroupNumber>
<FileNumber>81</FileNumber>
<FileNumber>82</FileNumber>
<FileType>1</FileType>
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>

10
app/app.uvprojx

@ -413,6 +413,11 @@
<FileType>1</FileType>
<FilePath>..\libznordic\src\zdatachannel_service.c</FilePath>
</File>
<File>
<FileName>app_ble_service.c</FileName>
<FileType>1</FileType>
<FilePath>.\src\app_ble_service.c</FilePath>
</File>
</Files>
</Group>
<Group>
@ -4172,6 +4177,11 @@
<FileType>1</FileType>
<FilePath>..\libznordic\src\zdatachannel_service.c</FilePath>
</File>
<File>
<FileName>app_ble_service.c</FileName>
<FileType>1</FileType>
<FilePath>.\src\app_ble_service.c</FilePath>
</File>
</Files>
</Group>
<Group>

4
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
// <o> NRF_LOG_BACKEND_UART_TEMP_BUFFER_SIZE - Size of buffer for partially processed strings.
@ -9971,7 +9971,7 @@
// <e> 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
// <o> NRF_CLI_BLE_UART_CONFIG_LOG_LEVEL - Default Severity level

57
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() {
//
}

13
app/src/app_ble_service.h

@ -0,0 +1,13 @@
#pragma once
#include <stdint.h>
/**
* @brief
* zble_module_init
*/
void AppBleService_onServiceInitCB();
void AppBleService_init();
void AppBleService_uninit();
void AppBleService_startAdv();

35
app/src/app_event.h

@ -0,0 +1,35 @@
#pragma once
#include <stdbool.h>
#include <stdint.h>
#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);

0
app/src/ble_cmd_process_service.c → app/src/bak/ble_cmd_process_service.c

0
app/src/ble_cmd_process_service.h → app/src/bak/ble_cmd_process_service.h

152
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; }

15
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();

5
app/src/board/three_lead_board.c → 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 *
*******************************************************************************/

1
app/src/board/three_lead_board.h → 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 *
*******************************************************************************/

24
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); }
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);
}

7
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

7
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)
#define SAMPLE_MIN_TIME_S (30.0)
/*******************************************************************************
* ÓÅÏȼ *
*******************************************************************************/

101
app/src/board/TI_ADS1293_register_settings.h

@ -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

148
app/src/board/ads_cfg.h

@ -1,148 +0,0 @@
#pragma once
#include <stdint.h>
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

0
app/src/board/board.c

61
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)

36
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;
}

15
app/src/board/board_battery_state.h

@ -0,0 +1,15 @@
#pragma once
#include <stdbool.h>
#include <stdint.h>
#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

93
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);
}
}

24
app/src/board/board_beep_ctrl.h

@ -0,0 +1,24 @@
#pragma once
#include <stdbool.h>
#include <stdint.h>
#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);

24
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);
}

18
app/src/board/board_button.h

@ -0,0 +1,18 @@
#pragma once
#include <stdbool.h>
#include <stdint.h>
#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(); //

70
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;
}

23
app/src/board/board_light_ctrl.h

@ -0,0 +1,23 @@
#pragma once
#include <stdbool.h>
#include <stdint.h>
#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);

176
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_PIN0: 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; }

19
app/src/board/board_sdcard_driver.h

@ -0,0 +1,19 @@
#pragma once
#include <stdbool.h>
#include <stdint.h>
#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();

13
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;
}

79
app/src/device_state.h

@ -1,87 +1,28 @@
#pragma once
#include <stdint.h>
#include <stdbool.h>
typedef enum {
kplod_connected_event = 0, //
kplod_disconnected_event, //
kplod_connecting_event, //
kplod_start_charge_event, //
kplod_charging_event, //
kplod_end_charge_event, //
kevent_tmr_scheduler_event, //
kevent_capture_256data_event, //
kevent_capture_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 <stdint.h>
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();

342
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);
}

34
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);

372
app/src/main.bak.c

@ -0,0 +1,372 @@
#include "znordic.h"
//
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//
#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

361
app/src/main.c

@ -5,368 +5,31 @@
#include <stdlib.h>
#include <string.h>
//
#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

155
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; }

78
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 <stdbool.h>
#include <stdint.h>
#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();

2
libznordic

@ -1 +1 @@
Subproject commit 92a15d47cbe16579d92ba8385ddbeaeb37778506
Subproject commit 2e46516dec82a92dd796312c6787f35e5adf7922
Loading…
Cancel
Save