diff --git a/.vscode/settings.json b/.vscode/settings.json
index 5a21775..2095780 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -187,7 +187,8 @@
"pan_tompkins_detect.h": "c",
"qrs_time_domain_zh.h": "c",
"board_eeprom_driver.h": "c",
- "board_power_mgr.h": "c"
+ "board_power_mgr.h": "c",
+ "heart_ware_sample_data_mgr.h": "c"
},
"files.encoding": "gbk"
}
\ No newline at end of file
diff --git a/app/app.uvoptx b/app/app.uvoptx
index b4abcef..b3d3821 100644
--- a/app/app.uvoptx
+++ b/app/app.uvoptx
@@ -739,6 +739,30 @@
0
0
+
+ 1
+ 32
+ 1
+ 0
+ 0
+ 0
+ .\src\heart_ware_sample_data_mgr.c
+ heart_ware_sample_data_mgr.c
+ 0
+ 0
+
+
+ 1
+ 33
+ 1
+ 0
+ 0
+ 0
+ .\src\heart_wave_sample_data_pre_process.c
+ heart_wave_sample_data_pre_process.c
+ 0
+ 0
+
@@ -749,7 +773,7 @@
0
2
- 32
+ 34
1
0
0
@@ -769,7 +793,7 @@
0
3
- 33
+ 35
1
0
0
@@ -781,7 +805,7 @@
3
- 34
+ 36
1
0
0
@@ -801,7 +825,7 @@
0
4
- 35
+ 37
1
0
0
@@ -821,7 +845,7 @@
0
5
- 36
+ 38
1
0
0
@@ -833,7 +857,7 @@
5
- 37
+ 39
1
0
0
@@ -845,7 +869,7 @@
5
- 38
+ 40
1
0
0
@@ -857,7 +881,7 @@
5
- 39
+ 41
1
0
0
@@ -869,7 +893,7 @@
5
- 40
+ 42
1
0
0
@@ -881,7 +905,7 @@
5
- 41
+ 43
1
0
0
@@ -893,7 +917,7 @@
5
- 42
+ 44
1
0
0
@@ -905,7 +929,7 @@
5
- 43
+ 45
1
0
0
@@ -925,7 +949,7 @@
0
6
- 44
+ 46
1
0
0
@@ -945,7 +969,7 @@
0
7
- 45
+ 47
1
0
0
@@ -957,7 +981,7 @@
7
- 46
+ 48
1
0
0
@@ -969,7 +993,7 @@
7
- 47
+ 49
1
0
0
@@ -981,7 +1005,7 @@
7
- 48
+ 50
1
0
0
@@ -993,7 +1017,7 @@
7
- 49
+ 51
1
0
0
@@ -1005,7 +1029,7 @@
7
- 50
+ 52
1
0
0
@@ -1017,7 +1041,7 @@
7
- 51
+ 53
1
0
0
@@ -1029,7 +1053,7 @@
7
- 52
+ 54
1
0
0
@@ -1041,7 +1065,7 @@
7
- 53
+ 55
1
0
0
@@ -1053,7 +1077,7 @@
7
- 54
+ 56
1
0
0
@@ -1065,7 +1089,7 @@
7
- 55
+ 57
1
0
0
@@ -1077,7 +1101,7 @@
7
- 56
+ 58
1
0
0
@@ -1089,7 +1113,7 @@
7
- 57
+ 59
1
0
0
@@ -1101,7 +1125,7 @@
7
- 58
+ 60
1
0
0
@@ -1113,7 +1137,7 @@
7
- 59
+ 61
1
0
0
@@ -1125,7 +1149,7 @@
7
- 60
+ 62
1
0
0
@@ -1137,7 +1161,7 @@
7
- 61
+ 63
1
0
0
@@ -1149,7 +1173,7 @@
7
- 62
+ 64
1
0
0
@@ -1161,7 +1185,7 @@
7
- 63
+ 65
1
0
0
@@ -1173,7 +1197,7 @@
7
- 64
+ 66
1
0
0
@@ -1193,7 +1217,7 @@
0
8
- 65
+ 67
1
0
0
@@ -1205,7 +1229,7 @@
8
- 66
+ 68
1
0
0
@@ -1217,7 +1241,7 @@
8
- 67
+ 69
1
0
0
@@ -1229,7 +1253,7 @@
8
- 68
+ 70
1
0
0
@@ -1241,7 +1265,7 @@
8
- 69
+ 71
1
0
0
@@ -1253,7 +1277,7 @@
8
- 70
+ 72
1
0
0
@@ -1265,7 +1289,7 @@
8
- 71
+ 73
1
0
0
@@ -1277,7 +1301,7 @@
8
- 72
+ 74
1
0
0
@@ -1289,7 +1313,7 @@
8
- 73
+ 75
1
0
0
@@ -1301,7 +1325,7 @@
8
- 74
+ 76
1
0
0
@@ -1313,7 +1337,7 @@
8
- 75
+ 77
1
0
0
@@ -1325,7 +1349,7 @@
8
- 76
+ 78
1
0
0
@@ -1337,7 +1361,7 @@
8
- 77
+ 79
1
0
0
@@ -1349,7 +1373,7 @@
8
- 78
+ 80
1
0
0
@@ -1361,7 +1385,7 @@
8
- 79
+ 81
1
0
0
@@ -1373,7 +1397,7 @@
8
- 80
+ 82
1
0
0
@@ -1385,7 +1409,7 @@
8
- 81
+ 83
1
0
0
@@ -1397,7 +1421,7 @@
8
- 82
+ 84
1
0
0
@@ -1409,7 +1433,7 @@
8
- 83
+ 85
1
0
0
@@ -1421,7 +1445,7 @@
8
- 84
+ 86
1
0
0
@@ -1433,7 +1457,7 @@
8
- 85
+ 87
1
0
0
@@ -1445,7 +1469,7 @@
8
- 86
+ 88
1
0
0
@@ -1457,7 +1481,7 @@
8
- 87
+ 89
1
0
0
@@ -1469,7 +1493,7 @@
8
- 88
+ 90
1
0
0
@@ -1481,7 +1505,7 @@
8
- 89
+ 91
1
0
0
@@ -1493,7 +1517,7 @@
8
- 90
+ 92
1
0
0
@@ -1505,7 +1529,7 @@
8
- 91
+ 93
1
0
0
@@ -1525,7 +1549,7 @@
0
9
- 92
+ 94
1
0
0
@@ -1537,7 +1561,7 @@
9
- 93
+ 95
1
0
0
@@ -1549,7 +1573,7 @@
9
- 94
+ 96
1
0
0
@@ -1561,7 +1585,7 @@
9
- 95
+ 97
1
0
0
@@ -1573,7 +1597,7 @@
9
- 96
+ 98
1
0
0
@@ -1585,7 +1609,7 @@
9
- 97
+ 99
1
0
0
@@ -1605,7 +1629,7 @@
0
10
- 98
+ 100
1
0
0
@@ -1617,7 +1641,7 @@
10
- 99
+ 101
1
0
0
@@ -1629,7 +1653,7 @@
10
- 100
+ 102
1
0
0
@@ -1649,7 +1673,7 @@
0
11
- 101
+ 103
1
0
0
@@ -1661,7 +1685,7 @@
11
- 102
+ 104
1
0
0
@@ -1673,7 +1697,7 @@
11
- 103
+ 105
1
0
0
@@ -1693,7 +1717,7 @@
0
12
- 104
+ 106
1
0
0
@@ -1705,7 +1729,7 @@
12
- 105
+ 107
1
0
0
@@ -1717,7 +1741,7 @@
12
- 106
+ 108
1
0
0
@@ -1737,7 +1761,7 @@
0
13
- 107
+ 109
1
0
0
@@ -1749,7 +1773,7 @@
13
- 108
+ 110
1
0
0
@@ -1769,7 +1793,7 @@
0
14
- 109
+ 111
1
0
0
@@ -1781,7 +1805,7 @@
14
- 110
+ 112
1
0
0
@@ -1793,7 +1817,7 @@
14
- 111
+ 113
1
0
0
@@ -1805,7 +1829,7 @@
14
- 112
+ 114
1
0
0
diff --git a/app/app.uvprojx b/app/app.uvprojx
index a0827b3..df1da2f 100644
--- a/app/app.uvprojx
+++ b/app/app.uvprojx
@@ -538,6 +538,16 @@
1
.\src\board\board_power_mgr.c
+
+ heart_ware_sample_data_mgr.c
+ 1
+ .\src\heart_ware_sample_data_mgr.c
+
+
+ heart_wave_sample_data_pre_process.c
+ 1
+ .\src\heart_wave_sample_data_pre_process.c
+
@@ -4457,6 +4467,16 @@
1
.\src\board\board_power_mgr.c
+
+ heart_ware_sample_data_mgr.c
+ 1
+ .\src\heart_ware_sample_data_mgr.c
+
+
+ heart_wave_sample_data_pre_process.c
+ 1
+ .\src\heart_wave_sample_data_pre_process.c
+
diff --git a/app/src/board/board.h b/app/src/board/board.h
index 6954a97..634db12 100644
--- a/app/src/board/board.h
+++ b/app/src/board/board.h
@@ -41,9 +41,9 @@
#define LIGHT_PWM_INSTANCE 1
-#define APP_BATTERY_PROTECT_LEVEL 2 // 低于此电量不能开机,保护电池
-#define APP_AUTO_STANDY_BATTERY_LEVEL 5 // 低于此电量自动待机,保持时钟
-#define APP_WORK_BATTERY_LEVEL 10 // Main初始化时候和从standy切换到work的时候,检查这个电量
+// #define APP_BATTERY_PROTECT_LEVEL 2 // 低于此电量不能开机,保护电池
+// #define APP_AUTO_STANDY_BATTERY_LEVEL 5 // 低于此电量自动待机,保持时钟
+// #define APP_WORK_BATTERY_LEVEL 10 // Main初始化时候和从standy切换到work的时候,检查这个电量
#define APP_LOW_BATTERY_WARNING_LIMIT 20 //
#define LOW_BATTERY_REMINDER_DELAY_MS 3000
diff --git a/app/src/board/board_ecg_sensor.c b/app/src/board/board_ecg_sensor.c
index 28d604d..6788dd6 100644
--- a/app/src/board/board_ecg_sensor.c
+++ b/app/src/board/board_ecg_sensor.c
@@ -18,7 +18,7 @@ static void module_tmr_cb(void *context) { //
memset(&appevent, 0, sizeof(appevent));
// ZLOGI("ecg sensor %d",m_plod_state_connected_state);
- if (!nrf_gpio_pin_read(ECG_PLOD_PIN)) {
+ if (true) {
connecte_state_trigger_cnt++;
m_connecte_state_last_trigger_timepoint = znordic_getpower_on_ms();
} else {
@@ -39,8 +39,8 @@ static void module_tmr_cb(void *context) { //
}
void BoardEcgSensor_init() {
- nrf_gpio_cfg_sense_input(ECG_NLOD_PIN, NRF_GPIO_PIN_PULLUP, NRF_GPIO_PIN_NOSENSE);
- nrf_gpio_cfg_sense_input(ECG_PLOD_PIN, NRF_GPIO_PIN_PULLUP, NRF_GPIO_PIN_NOSENSE); // 低有效
+ // nrf_gpio_cfg_sense_input(ECG_NLOD_PIN, NRF_GPIO_PIN_PULLUP, NRF_GPIO_PIN_NOSENSE);
+ // nrf_gpio_cfg_sense_input(ECG_PLOD_PIN, NRF_GPIO_PIN_PULLUP, NRF_GPIO_PIN_NOSENSE); // 低有效
app_timer_create(&module_tmr, APP_TIMER_MODE_REPEATED, module_tmr_cb);
app_timer_start(module_tmr, APP_TIMER_TICKS(100), NULL);
@@ -48,9 +48,9 @@ void BoardEcgSensor_init() {
void BoardEcgSensor_load() { BoardAdc_load(); }
void BoardEcgSensor_unload() { BoardAdc_unload(); }
-int16_t BoardEcgSensor_nlod_get_connected_state() { return nrf_gpio_pin_read(ECG_NLOD_PIN); }
-int16_t BoardEcgSensor_plod_get_connected_state() { return !nrf_gpio_pin_read(ECG_PLOD_PIN); }
-int16_t BoardEcgSensor_plod_get_ecg_val() { return BoardAdc_get_val(ECG_ADC_CHANNEL); }
+int16_t BoardEcgSensor_nlod_get_connected_state() { return true; }
+int16_t BoardEcgSensor_plod_get_connected_state() { return true; }
+int16_t BoardEcgSensor_plod_get_ecg_val() { return 0; }
int16_t BoardEcgSensor_plod_get_connected_state_after_filter() { return plod_state_is_connected(); }
int16_t BoardEcgSensor_plod_state_has_disconnected_ms() { return plod_state_has_disconnected_ms(); }
diff --git a/app/src/device_state.h b/app/src/device_state.h
index dd99c41..5d1e3c6 100644
--- a/app/src/device_state.h
+++ b/app/src/device_state.h
@@ -17,9 +17,7 @@ typedef enum {
kevent_capture_little_data_block_event, // 单次采样数据回调
} app_event_type_t;
-typedef struct {
- uint16_t data;
-} one_frame_data_t;
+typedef uint16_t one_frame_t;
typedef struct {
app_event_type_t eventType;
@@ -27,8 +25,8 @@ typedef struct {
uint32_t plod_connected_accumulation_time; // 导联连接累计时间
uint8_t* capture_data_cache; // 实时采样数据,数据长度为256字节
struct {
- uint32_t frameIndex;
- one_frame_data_t data[LITTLE_DATA_BLOCK_FRAME_NUM];
+ uint32_t frameIndex;
+ one_frame_t data[LITTLE_DATA_BLOCK_FRAME_NUM];
} little_data_block;
} val;
} app_event_t;
diff --git a/app/src/heart_ware_sample_data_mgr.c b/app/src/heart_ware_sample_data_mgr.c
new file mode 100644
index 0000000..f28c7a0
--- /dev/null
+++ b/app/src/heart_ware_sample_data_mgr.c
@@ -0,0 +1,108 @@
+#include "app_event.h"
+#include "app_event_distribute.h"
+#include "basic/qrs_time_domain_zh.h"
+#include "board/board_ecg_sensor.h"
+#include "heart_wave_sample_service.h"
+#include "nrfx_timer.h"
+
+static uint32_t m_frame_index = 0; // 帧绝对序号
+/***********************************************************************************************************************
+ * ab buffer *
+ ***********************************************************************************************************************/
+#define FRAME_BUFFER_SIZE (256 / sizeof(one_frame_t))
+
+static one_frame_t m_capture_buffer_a[FRAME_BUFFER_SIZE];
+static one_frame_t m_capture_buffer_b[FRAME_BUFFER_SIZE];
+static one_frame_t* m_capture_buffer;
+static one_frame_t m_capture_buffer_index = 0;
+
+static void eeprom_cache_buffer_swap() {
+ 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;
+}
+
+/***********************************************************************************************************************
+ * littlebuffer *
+ ***********************************************************************************************************************/
+static one_frame_t m_prepare_data_cache[LITTLE_DATA_BLOCK_FRAME_NUM];
+static uint32_t m_prepare_data_cache_index;
+
+static inline void preview_data_cache_push_data(one_frame_t data) {
+ if (m_prepare_data_cache_index >= LITTLE_DATA_BLOCK_FRAME_NUM) {
+ return;
+ }
+ m_prepare_data_cache[m_prepare_data_cache_index] = data;
+ m_prepare_data_cache_index++;
+}
+
+static inline bool preview_data_cache_is_full(void) {
+ if (m_prepare_data_cache_index >= LITTLE_DATA_BLOCK_FRAME_NUM) {
+ return true;
+ }
+ return false;
+}
+static inline void preview_data_cache_clear(void) { m_prepare_data_cache_index = 0; }
+static inline void preview_data_trigger_event() {
+ static app_event_t event;
+ event.eventType = kevent_capture_little_data_block_event;
+ for (uint32_t i = 0; i < LITTLE_DATA_BLOCK_FRAME_NUM; i++) {
+ event.val.little_data_block.data[i] = m_prepare_data_cache[i];
+ }
+ event.val.little_data_block.frameIndex = m_frame_index - LITTLE_DATA_BLOCK_FRAME_NUM;
+ AppEvent_pushEvent(&event);
+}
+
+/***********************************************************************************************************************
+ * EXT *
+ ***********************************************************************************************************************/
+
+void hwsd_mgr_push_one_frame(one_frame_t data) {
+ m_frame_index++;
+
+ /***********************************************************************************************************************
+ * EEPROM数据采样存储 *
+ ***********************************************************************************************************************/
+ if (m_capture_buffer == NULL) eeprom_cache_buffer_swap();
+
+ if (m_capture_buffer_index < FRAME_BUFFER_SIZE) {
+ m_capture_buffer[m_capture_buffer_index++] = data;
+ }
+
+ if (m_capture_buffer_index == FRAME_BUFFER_SIZE) {
+ app_event_t evt;
+ evt.eventType = kevent_capture_256data_event;
+ evt.val.capture_data_cache = (uint8_t*)m_capture_buffer;
+ eeprom_cache_buffer_swap();
+ AppEvent_pushEvent(&evt);
+ }
+
+ /*******************************************************************************
+ * 实时采样数据事件上报 *
+ *******************************************************************************/
+ /**
+ * @brief 缓存数据,并触发小数据块事件
+ */
+ preview_data_cache_push_data(data);
+ if (preview_data_cache_is_full()) {
+ preview_data_trigger_event();
+ preview_data_cache_clear();
+ }
+}
+
+void hwsd_mgr_reset_buffer(){
+ m_frame_index = 0;
+ m_capture_buffer = NULL;
+ m_capture_buffer_index = 0;
+ preview_data_cache_clear();
+}
diff --git a/app/src/heart_ware_sample_data_mgr.h b/app/src/heart_ware_sample_data_mgr.h
new file mode 100644
index 0000000..24a7e9b
--- /dev/null
+++ b/app/src/heart_ware_sample_data_mgr.h
@@ -0,0 +1,9 @@
+#pragma once
+#include
+
+#include "app_event.h"
+#include "app_event_distribute.h"
+#include "nrfx_timer.h"
+
+void hwsd_mgr_push_one_frame(one_frame_t data);
+void hwsd_mgr_reset_buffer();
\ No newline at end of file
diff --git a/app/src/heart_wave_sample_data_pre_process.c b/app/src/heart_wave_sample_data_pre_process.c
new file mode 100644
index 0000000..984b197
--- /dev/null
+++ b/app/src/heart_wave_sample_data_pre_process.c
@@ -0,0 +1,107 @@
+#include "heart_wave_sample_data_pre_process.h"
+
+/***********************************************************************************************************************
+ * ALGO *
+ ***********************************************************************************************************************/
+
+typedef struct {
+ float value;
+ float efectiveFactor;
+} filter_t;
+
+typedef struct {
+ float coef[2];
+ float v_out[2];
+} LPFilter;
+#define PI 3.14159265358979323846f
+
+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 LPFilter_Init(LPFilter* filter, float cutoffFreqHz, float sampleTimeS) {
+ float RC = 0.0;
+ RC = 1.0 / (2 * PI * cutoffFreqHz);
+ filter->coef[0] = sampleTimeS / (sampleTimeS + RC);
+ filter->coef[1] = RC / (sampleTimeS + RC);
+
+ filter->v_out[0] = 0.0;
+ filter->v_out[1] = 0.0;
+}
+
+float LPFilter_Update(LPFilter* filter, float v_in) {
+ filter->v_out[1] = filter->v_out[0];
+ filter->v_out[0] = (filter->coef[0] * v_in) + (filter->coef[1] * filter->v_out[1]);
+
+ return (filter->v_out[0]);
+}
+
+/**
+ * @brief 放大显示数据
+ *
+ * @param val
+ * @param valcener
+ * @param amp
+ * @return float
+ */
+static float amp_display_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;
+}
+
+uint16_t getRecommendedMagnification() {
+ // return 0;
+ uint16_t max = QRS_getMaxValueLastVal();
+ if (max == 0) {
+ return 15;
+ }
+ // 3750.0f
+ if (max <= (3750 / 2)) {
+ return 15;
+ }
+ float af = (3750 / 2) / (max - 3750 / 2);
+ if (af > 15) {
+ return 15;
+ }
+ return af;
+}
+
+/***********************************************************************************************************************
+ * VAR *
+ ***********************************************************************************************************************/
+static one_frame_t m_datacache;
+static one_frame_t m_displaydata;
+filter_t m_filter = {0, 0.8};
+LPFilter m_lpfilter_01;
+LPFilter m_lpfilter_02;
+
+void hwsd_pre_processer_init() { QRS_resetBuf(); }
+void hwsd_pre_processer_process(one_frame_t framdata) { //
+ m_datacache = framdata;
+ m_displaydata = framdata;
+ /*******************************************************************************
+ * 显示数据计算并赋值 *
+ *******************************************************************************/
+ // QRS_getMaxValueLastVal();
+ // float lowpassf_val = LPFilter_Update(&m_lpfilter_01, framdata);
+ // QRS_processData(lowpassf_val);
+ // float val_af100 = (float)lowpassf_val / 3750.0f * 100; // 参考电压为3.6v,但信号范围为3.3v
+ // val_af100 = amp_val(val_af100, 50, getRecommendedMagnification());
+ // val_af100 = LPFilter_Update(&m_lpfilter_02, val_af100);
+ // m_displaydata = m_datacache;
+}
+
+uint16_t hwsd_pre_processer_get_display_data() { return m_displaydata; }
+one_frame_t hwsd_pre_processer_get_storage_data() { return m_datacache; }
diff --git a/app/src/heart_wave_sample_data_pre_process.h b/app/src/heart_wave_sample_data_pre_process.h
new file mode 100644
index 0000000..bb594e4
--- /dev/null
+++ b/app/src/heart_wave_sample_data_pre_process.h
@@ -0,0 +1,9 @@
+#pragma once
+#include
+
+#include "app_event.h"
+
+void hwsd_pre_processer_init();
+void hwsd_pre_processer_process(one_frame_t framdata);
+one_frame_t hwsd_pre_processer_get_display_data();
+one_frame_t hwsd_pre_processer_get_storage_data();
diff --git a/app/src/heart_wave_sample_service.c b/app/src/heart_wave_sample_service.c
index beb05ed..bb65c00 100644
--- a/app/src/heart_wave_sample_service.c
+++ b/app/src/heart_wave_sample_service.c
@@ -4,189 +4,31 @@
#include "app_event_distribute.h"
#include "basic/qrs_time_domain_zh.h"
#include "board/board_ecg_sensor.h"
+#include "heart_ware_sample_data_mgr.h"
+#include "heart_wave_sample_data_pre_process.h"
#include "nrfx_timer.h"
-
-static uint16_t m_capture_buffer_a[128];
-static uint16_t m_capture_buffer_b[128];
+typedef enum {
+ kidle,
+ kprepare,
+ kcapture,
+} capture_state_t;
-static uint16_t* m_capture_buffer;
-static uint16_t m_capture_buffer_index = 0;
-
-volatile static float m_sensor_display_data = 0; // 0->100
-static uint32_t m_start_capture_tp;
-static uint32_t m_frame_index = 0;
-static bool m_prepare_capture = false;
-
-static one_frame_data_t m_sensor_little_frame_cache[LITTLE_DATA_BLOCK_FRAME_NUM];
-static uint32_t m_little_frame_index;
+static capture_state_t m_prepare_capture_state = kidle;
+static uint32_t m_start_capture_tp;
static nrfx_timer_t m_timer = NRFX_TIMER_INSTANCE(HEART_WAVE_SAMPLE_TMR_INSTANCE);
-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;
-
-typedef struct {
- float coef[2];
- float v_out[2];
-} LPFilter;
-#define PI 3.14159265358979323846f
-
-filter_t m_filter = {0, 0.8};
-
-LPFilter m_lpfilter_01;
-LPFilter m_lpfilter_02;
-
-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 LPFilter_Init(LPFilter* filter, float cutoffFreqHz, float sampleTimeS) {
- float RC = 0.0;
- RC = 1.0 / (2 * PI * cutoffFreqHz);
- filter->coef[0] = sampleTimeS / (sampleTimeS + RC);
- filter->coef[1] = RC / (sampleTimeS + RC);
-
- filter->v_out[0] = 0.0;
- filter->v_out[1] = 0.0;
-}
-
-float LPFilter_Update(LPFilter* filter, float v_in) {
- filter->v_out[1] = filter->v_out[0];
- filter->v_out[0] = (filter->coef[0] * v_in) + (filter->coef[1] * filter->v_out[1]);
-
- return (filter->v_out[0]);
-}
-
-/*******************************************************************************
- * 小包数据上报 *
- *******************************************************************************/
-static inline void prvf_little_block_cache_push_one_frame(uint16_t data) {
- if (m_little_frame_index >= LITTLE_DATA_BLOCK_FRAME_NUM) {
- return;
- }
- m_sensor_little_frame_cache[m_little_frame_index].data = data;
- m_little_frame_index++;
-}
-
-static inline bool prvf_light_block_cache_is_full(void) {
- if (m_little_frame_index >= LITTLE_DATA_BLOCK_FRAME_NUM) {
- return true;
- }
- return false;
-}
-static inline void prvf_light_block_cache_clear(void) { m_little_frame_index = 0; }
-static inline void prvf_light_block_trigger_event() {
- static app_event_t event;
- event.eventType = kevent_capture_little_data_block_event;
- for (uint32_t i = 0; i < LITTLE_DATA_BLOCK_FRAME_NUM; i++) {
- event.val.little_data_block.data[i].data = m_sensor_little_frame_cache[i].data;
- }
- event.val.little_data_block.frameIndex = m_frame_index - LITTLE_DATA_BLOCK_FRAME_NUM;
- // ZLOGI("%d", event.val.little_data_block.frameIndex);
- AppEvent_pushEvent(&event);
-}
-
-// QRS_getMaxValueLastVal();
-
-uint16_t getRecommendedMagnification() {
- // return 0;
- uint16_t max = QRS_getMaxValueLastVal();
- if (max == 0) {
- return 15;
- }
- // 3750.0f
- if (max <= (3750 / 2)) {
- return 15;
- }
- float af = (3750 / 2) / (max - 3750 / 2);
- if (af > 15) {
- return 15;
- }
- return af;
-}
-
void nrfx_timer_event_handler(nrf_timer_event_t event_type, void* p_context) { //
- uint16_t val = BoardEcgSensor_plod_get_ecg_val(); // 12bit
-
- /*******************************************************************************
- * 显示数据计算并赋值 *
- *******************************************************************************/
-
- // QRS_getMaxValueLastVal();
- int16_t lowpassf_val = LPFilter_Update(&m_lpfilter_01, val);
- QRS_processData(lowpassf_val);
- float val_af100 = (float)lowpassf_val / 3750.0f * 100; // 参考电压为3.6v,但信号范围为3.3v
- val_af100 = amp_val(val_af100, 50, getRecommendedMagnification());
- val_af100 = LPFilter_Update(&m_lpfilter_02, val_af100);
- m_sensor_display_data = val_af100;
-
- if (m_prepare_capture) return;
-
- /*******************************************************************************
- * 采样数据缓存 *
- *******************************************************************************/
- m_frame_index++;
- if (m_capture_buffer == NULL) {
- swap_buffer();
- }
-
- if (m_capture_buffer_index < 128) {
- m_capture_buffer[m_capture_buffer_index++] = val;
- }
-
- if (m_capture_buffer_index == 128) {
- app_event_t evt;
- evt.eventType = kevent_capture_256data_event;
- evt.val.capture_data_cache = (uint8_t*)m_capture_buffer;
- swap_buffer();
- AppEvent_pushEvent(&evt);
- }
-
- /*******************************************************************************
- * 实时采样数据事件上报 *
- *******************************************************************************/
- /**
- * @brief 缓存数据,并触发小数据块事件
- */
- prvf_little_block_cache_push_one_frame(val);
- if (prvf_light_block_cache_is_full()) {
- prvf_light_block_trigger_event();
- prvf_light_block_cache_clear();
+ static uint16_t val = 25;
+ val++;
+ if (val > 75) val = 25;
+
+ if (m_prepare_capture_state == kprepare) {
+ hwsd_pre_processer_process(val);
+ } else if (m_prepare_capture_state == kcapture) {
+ hwsd_pre_processer_process(val);
+ hwsd_mgr_push_one_frame(hwsd_pre_processer_get_storage_data());
}
}
@@ -214,44 +56,29 @@ void hwss_init(void) {
}
void hwss_uninit(void) { nrfx_timer_disable(&m_timer); }
void hwss_start_prepare_capture(void) {
- m_start_capture_tp = znordic_getpower_on_s();
- m_prepare_capture = true;
- m_frame_index = 0;
-
- swap_buffer();
- LPFilter_Init(&m_lpfilter_01, 30, 0.002);
- LPFilter_Init(&m_lpfilter_02, 30, 0.002);
- QRS_resetBuf();
- prvf_light_block_cache_clear();
+ m_start_capture_tp = znordic_getpower_on_s();
+ m_prepare_capture_state = kprepare;
+ hwsd_pre_processer_init();
+ hwsd_mgr_reset_buffer();
nrfx_timer_enable(&m_timer);
}
void hwss_start_capture(void) {
- m_start_capture_tp = znordic_getpower_on_s();
- m_prepare_capture = false;
- // swap_buffer();
- // m_frame_index = 0;
- // LPFilter_Init(&m_lpfilter_01, 30, 0.002);
- // LPFilter_Init(&m_lpfilter_02, 30, 0.002);
-
- // QRS_resetBuf();
-
- // prvf_light_block_cache_clear();
- // nrfx_timer_enable(&m_timer);
+ m_start_capture_tp = znordic_getpower_on_s();
+ m_prepare_capture_state = kcapture;
}
void hwss_stop_capture(void) {
+ m_prepare_capture_state = kidle;
nrfx_timer_disable(&m_timer);
- m_frame_index = 0;
- prvf_light_block_cache_clear();
+ hwsd_mgr_reset_buffer();
}
float hwss_read_val(void) {
__disable_irq();
- float val = m_sensor_display_data;
+ float val = hwsd_pre_processer_get_display_data();
__enable_irq();
return val;
}
float hwss_read_heart_rate(void) { //
return QRS_getHeartRate();
}
-
int hwss_has_captured_time_ms() { return (znordic_getpower_on_s() - m_start_capture_tp) * 1000; }
diff --git a/app/src/heart_wave_sample_service.c.bak b/app/src/heart_wave_sample_service.c.bak
deleted file mode 100644
index d130e03..0000000
--- a/app/src/heart_wave_sample_service.c.bak
+++ /dev/null
@@ -1,313 +0,0 @@
-#include "heart_wave_sample_service.h"
-
-#include "app_event.h"
-#include "app_event_distribute.h"
-#include "basic/FIR.h"
-#include "basic/HC_Chen_detect.h"
-#include "basic/So_Chen_detect.h"
-#include "basic/adaptive_algorithm.h"
-#include "basic/Pan_Tompkins_detect.h"
-#include "board/board_ecg_sensor.h"
-#include "nrfx_timer.h"
-
-
-static uint16_t m_capture_buffer_a[128];
-static uint16_t m_capture_buffer_b[128];
-
-static uint16_t* m_capture_buffer;
-static uint16_t m_capture_buffer_index = 0;
-
-volatile static float m_sensor_display_data = 0; // 0->100
-static uint32_t m_start_capture_tp;
-static uint32_t m_frame_index = 0;
-
-static one_frame_data_t m_sensor_little_frame_cache[LITTLE_DATA_BLOCK_FRAME_NUM];
-static uint32_t m_little_frame_index;
-static bool m_prestart_flag;
-
-static nrfx_timer_t m_timer = NRFX_TIMER_INSTANCE(HEART_WAVE_SAMPLE_TMR_INSTANCE);
-
-typedef struct {
- int heartSignalCnt;
- int heart_rate;
- uint32_t last_qrs_point;
- uint32_t time_cnt;
- uint32_t origin_time_cnt;
-
- uint32_t index;
- float index_f;
-} QRS_t;
-
-QRS_t m_qrs;
-
-void QRS_reset() {
- m_qrs.heartSignalCnt = 0;
- m_qrs.heart_rate = 0;
- m_qrs.time_cnt = 0;
- m_qrs.index = 0;
- m_qrs.index_f = 0;
- FIR_reset_buffer();
-}
-
-void QRS_process(float value) {
- bool isPeak = false;
-#if 1
- float result = value;
- SignalPoint sp;
- sp.value = result;
- sp.index = m_qrs.time_cnt;
- SignalPoint peak = So_Chen_detect(sp, SAMPLING_RATE * 0.25f, 4, 16);
- if (peak.index != -1) {
- isPeak = true;
- }
-#endif
-
-#if 0
- isPeak = HC_Chen_detect(value);
-#endif
-
-#if 0
- static const float CV_LIMIT = 50.0f;
- static const float THRESHOLD_FACTOR = 3.0f;
- double mean = CalculateMean(value);
- double rms = CalculateRootMeanSquare(value);
- double cv = CalculateCoefficientOfVariation(value);
- double threshold;
- if (cv > CV_LIMIT) {
- threshold = rms;
- } else {
- threshold = rms * (cv / 100.0f) * THRESHOLD_FACTOR;
- }
- bool is_peak;
- SignalPoint result;
- result = PeakDetect(value, m_qrs.time_cnt, threshold, &is_peak);
- if (result.index != -1) {
- if (is_peak) {
- isPeak = true;
- }
- }
-#endif
-
-#if 0
-
-
- double result = value;
- double bandpass;
- double integral;
- double square;
-
- bandpass = result;
- result = Derivative(result);
- result = Squar(result);
- square = result;
- result = MovingWindowIntegral(result);
- integral = result;
-
- SignalPoint peak = ThresholdCalculate(m_qrs.time_cnt,value,bandpass,square,integral);
-
- if(peak.index != -1){
- isPeak = true;
- }
-
-#endif
-
- // if (isPeak) {
- // uint32_t time_diff = m_qrs.time_cnt - m_qrs.last_qrs_point;
- // m_qrs.last_qrs_point = m_qrs.time_cnt;
- // m_qrs.heartSignalCnt++;
- // // m_qrs.heart_rate = m_qrs.heartSignalCnt;
- // if (m_qrs.last_qrs_point != 0) {
- // m_qrs.heart_rate = 60 * (1 / (time_diff * 1.0 / SAMPLING_RATE));
- // }
- // }
-
- m_qrs.time_cnt++;
-}
-
-static const void compute_heart_rate(float sample_data) {
- ZASSERT(SAMPLE_RATE == 500);
- m_qrs.index_f = m_frame_index / 500.0 * 360;
- if ((m_qrs.index_f - m_qrs.index) > 1) {
- m_qrs.index = m_qrs.index_f;
- float val = sample_data;
- QRS_process(FIR_filter(val));
- }
-}
-
-static void swap_buffer() {
- if (m_capture_buffer == NULL) {
- m_capture_buffer = m_capture_buffer_a;
- m_capture_buffer_index = 0;
- return;
- }
-
- if (m_capture_buffer == m_capture_buffer_a) {
- m_capture_buffer = m_capture_buffer_b;
- } else {
- m_capture_buffer = m_capture_buffer_a;
- }
- m_capture_buffer_index = 0;
- return;
-}
-static float amp_val(uint16_t val, uint16_t valcener, float amp) {
- float valf = (float)val - valcener;
- valf = valf * amp;
- valf += valcener;
-
- if (valf >= 100) {
- valf = 100;
- }
-
- if (valf <= 0) {
- valf = 0;
- }
- return valf;
-}
-
-typedef struct {
- float value;
- float efectiveFactor;
-} filter_t;
-
-filter_t m_filter = {0, 0.8};
-
-static float Filter(filter_t* filter, float newInput) {
- float newv = ((float)filter->value * (1.0f - filter->efectiveFactor)) + ((float)newInput * filter->efectiveFactor);
- filter->value = newv;
- return newv;
-}
-
-/*******************************************************************************
- * 小包数据上报 *
- *******************************************************************************/
-static inline void prvf_little_block_cache_push_one_frame(uint16_t data) {
- if (m_little_frame_index >= LITTLE_DATA_BLOCK_FRAME_NUM) {
- return;
- }
- m_sensor_little_frame_cache[m_little_frame_index].data = data;
- m_little_frame_index++;
-}
-
-static inline bool prvf_light_block_cache_is_full(void) {
- if (m_little_frame_index >= LITTLE_DATA_BLOCK_FRAME_NUM) {
- return true;
- }
- return false;
-}
-static inline void prvf_light_block_cache_clear(void) { m_little_frame_index = 0; }
-static inline void prvf_light_block_trigger_event() {
- static app_event_t event;
- event.eventType = kevent_capture_little_data_block_event;
- for (uint32_t i = 0; i < LITTLE_DATA_BLOCK_FRAME_NUM; i++) {
- event.val.little_data_block.data[i].data = m_sensor_little_frame_cache[i].data;
- }
- event.val.little_data_block.frameIndex = m_frame_index - LITTLE_DATA_BLOCK_FRAME_NUM;
- // ZLOGI("%d", event.val.little_data_block.frameIndex);
- AppEvent_pushEvent(&event);
-}
-
-void nrfx_timer_event_handler(nrf_timer_event_t event_type, void* p_context) { //
- uint16_t val = BoardEcgSensor_plod_get_ecg_val(); // 12bit
- float val_af100 = (float)val / 4096.0f * 100;
- if (m_prestart_flag) {
- compute_heart_rate(val_af100);
- return;
- } else {
- compute_heart_rate(val_af100);
- }
-
- /*******************************************************************************
- * 显示数据计算并赋值 *
- *******************************************************************************/
-
- m_frame_index++;
- val_af100 = amp_val(val_af100, 45, 3.5f);
- val_af100 = Filter(&m_filter, val_af100);
- m_sensor_display_data = val_af100;
-
- /*******************************************************************************
- * 采样数据缓存 *
- *******************************************************************************/
- if (m_capture_buffer == NULL) {
- swap_buffer();
- }
-
- if (m_capture_buffer_index < 128) {
- m_capture_buffer[m_capture_buffer_index++] = val;
- }
-
- if (m_capture_buffer_index == 128) {
- app_event_t evt;
- evt.eventType = kevent_capture_256data_event;
- evt.val.capture_data_cache = (uint8_t*)m_capture_buffer;
- swap_buffer();
- AppEvent_pushEvent(&evt);
- }
-
- /*******************************************************************************
- * 实时采样数据事件上报 *
- *******************************************************************************/
- /**
- * @brief 缓存数据,并触发小数据块事件
- */
- prvf_little_block_cache_push_one_frame(val);
- if (prvf_light_block_cache_is_full()) {
- prvf_light_block_trigger_event();
- prvf_light_block_cache_clear();
- }
-}
-
-void hwss_init(void) {
- static bool m_timer_inited = false;
- if (!m_timer_inited) {
- /**
- * @brief 初始化定时器
- */
- static nrfx_timer_config_t timer_cfg = {
- .frequency = NRF_TIMER_FREQ_500kHz,
- .mode = NRF_TIMER_MODE_TIMER,
- .bit_width = NRF_TIMER_BIT_WIDTH_24,
- .p_context = NULL,
- .interrupt_priority = NRFX_TIMER_DEFAULT_CONFIG_IRQ_PRIORITY,
- };
-
- // nrfx_timer_init(&m_timer, &timer_cfg, nrfx_timer_event_handler);
- ZERROR_CHECK(nrfx_timer_init(&m_timer, &timer_cfg, nrfx_timer_event_handler));
- uint32_t timer_ticks = nrfx_timer_ms_to_ticks(&m_timer, 2); //
- ZASSERT(SAMPLE_RATE == 500);
- nrfx_timer_extended_compare(&m_timer, NRF_TIMER_CC_CHANNEL0, timer_ticks, NRF_TIMER_SHORT_COMPARE0_CLEAR_MASK, true);
- m_timer_inited = true;
- }
-}
-void hwss_uninit(void) { nrfx_timer_disable(&m_timer); }
-
-void hwss_pre_start_capture(void) {
- m_start_capture_tp = znordic_getpower_on_s();
- swap_buffer();
- m_frame_index = 0;
-
- QRS_reset();
-
- prvf_light_block_cache_clear();
- nrfx_timer_enable(&m_timer);
- m_prestart_flag = true;
-}
-
-void hwss_start_capture(void) { m_prestart_flag = false; }
-void hwss_stop_capture(void) {
- nrfx_timer_disable(&m_timer);
- m_frame_index = 0;
- prvf_light_block_cache_clear();
-}
-
-float hwss_read_val(void) {
- __disable_irq();
- float val = m_sensor_display_data;
- __enable_irq();
- return val;
-}
-float hwss_read_heart_rate(void) { //
- return m_qrs.heart_rate;
-}
-
-int hwss_has_captured_time_ms() { return (znordic_getpower_on_s() - m_start_capture_tp) * 1000; }
diff --git a/app/src/one_conduction_main.c b/app/src/one_conduction_main.c
index a484598..0b9ea5b 100644
--- a/app/src/one_conduction_main.c
+++ b/app/src/one_conduction_main.c
@@ -181,7 +181,8 @@ static void app_event_listener(void* p_event_data, uint16_t event_size) {
else if (BoardEcgSensor_plod_get_connected_state_after_filter() && znordic_haspassed_ms(lasttrypoweron_time) >= LOW_BATTERY_REMINDER_DELAY_MS) {
lasttrypoweron_time = znordic_getpower_on_ms();
- if (BoardBattery_get_battery_level() > APP_WORK_BATTERY_LEVEL) {
+ // if (BoardBattery_get_battery_level() > APP_WORK_BATTERY_LEVEL) {
+ if (true) {
state_machine__change_to_poweroning_state();
} else {
BoardLight_load();
@@ -195,9 +196,9 @@ static void app_event_listener(void* p_event_data, uint16_t event_size) {
if (!znordic_rtc_has_setted()) {
ENTER_DEEP_SLEEP();
}
- if (APP_BATTERY_PROTECT_LEVEL > BoardBattery_get_battery_level()) {
- ENTER_DEEP_SLEEP();
- }
+ // if (APP_BATTERY_PROTECT_LEVEL > BoardBattery_get_battery_level()) {
+ // ENTER_DEEP_SLEEP();
+ // }
}
}
@@ -245,10 +246,12 @@ static void app_event_listener(void* p_event_data, uint16_t event_size) {
}
}
+#if 0
// 低电量,设备进入待机模式
else if (BoardBattery_get_battery_level() < APP_AUTO_STANDY_BATTERY_LEVEL && ds_cur_state_haspassed_ms() > 3000) {
state_machine__change_to_standby_state();
} //
+#endif
else if (!ble_is_upload_record() && zble_module_is_connected() && zdatachannel_last_rx_data_haspassed_s() >= BLE_UNCONNECTED_OVERTIME_S) {
ZLOGI("auto sleep because ble unconnected");
@@ -339,11 +342,11 @@ static void app_event_listener(void* p_event_data, uint16_t event_size) {
// 单帧实时上报
ZASSERT(LITTLE_DATA_BLOCK_FRAME_NUM == 5);
ble_cmder_try_report_one_sample_data(p_event->val.little_data_block.frameIndex, //
- p_event->val.little_data_block.data[0].data, //
- p_event->val.little_data_block.data[1].data, //
- p_event->val.little_data_block.data[2].data, //
- p_event->val.little_data_block.data[3].data, //
- p_event->val.little_data_block.data[4].data);
+ p_event->val.little_data_block.data[0], //
+ p_event->val.little_data_block.data[1], //
+ p_event->val.little_data_block.data[2], //
+ p_event->val.little_data_block.data[3], //
+ p_event->val.little_data_block.data[4]);
}
/*******************************************************************************
@@ -431,7 +434,7 @@ void one_conduction_main() {
BoardEcgSensor_init();
BoardLight_Init();
BoardBattery_load();
-#if 1
+#if 0
if (BoardBattery_get_battery_level() < APP_WORK_BATTERY_LEVEL) {
BoardLight_load();
BoardLight_blockFlash(3, 100);