diff --git a/.vscode/settings.json b/.vscode/settings.json
index 277d677..898c4cb 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -215,7 +215,9 @@
"beep_ctrl.h": "c",
"hardware_power_mgr.h": "c",
"nrf_fstorage_sd.h": "c",
- "nrf_fstorage.h": "c"
+ "nrf_fstorage.h": "c",
+ "zdata_statistics.h": "c",
+ "iflytop_simple_filter.h": "c"
},
"files.encoding": "gbk"
}
\ No newline at end of file
diff --git a/app/app.uvoptx b/app/app.uvoptx
index 1f4e742..d4029d7 100644
--- a/app/app.uvoptx
+++ b/app/app.uvoptx
@@ -1746,8 +1746,8 @@
0
0
0
- .\src\app_service\ecg_service\algo\ecg_data_analyszer.c
- ecg_data_analyszer.c
+ .\src\app_service\ecg_service\algo\iflytop_simple_filter.c
+ iflytop_simple_filter.c
0
0
@@ -1758,8 +1758,8 @@
0
0
0
- .\src\app_service\ecg_service\algo\iflytop_simple_filter.c
- iflytop_simple_filter.c
+ .\src\app_service\ecg_service\algo\iflytop_simple_filter_ext.c
+ iflytop_simple_filter_ext.c
0
0
@@ -1770,8 +1770,8 @@
0
0
0
- .\src\app_service\ecg_service\algo\iflytop_simple_filter_ext.c
- iflytop_simple_filter_ext.c
+ .\src\app_service\ecg_service\algo\zsimple_qrs.c
+ zsimple_qrs.c
0
0
@@ -1782,8 +1782,8 @@
0
0
0
- .\src\app_service\ecg_service\algo\iflytop_simple_qrs.c
- iflytop_simple_qrs.c
+ .\src\app_service\ecg_service\algo\zdata_statistics.c
+ zdata_statistics.c
0
0
diff --git a/app/app.uvprojx b/app/app.uvprojx
index 325084f..c6e96d1 100644
--- a/app/app.uvprojx
+++ b/app/app.uvprojx
@@ -3886,11 +3886,6 @@
.\src\app_service\ecg_service\ecg_data_mgr.c
- ecg_data_analyszer.c
- 1
- .\src\app_service\ecg_service\algo\ecg_data_analyszer.c
-
-
iflytop_simple_filter.c
1
.\src\app_service\ecg_service\algo\iflytop_simple_filter.c
@@ -3901,9 +3896,14 @@
.\src\app_service\ecg_service\algo\iflytop_simple_filter_ext.c
- iflytop_simple_qrs.c
+ zsimple_qrs.c
+ 1
+ .\src\app_service\ecg_service\algo\zsimple_qrs.c
+
+
+ zdata_statistics.c
1
- .\src\app_service\ecg_service\algo\iflytop_simple_qrs.c
+ .\src\app_service\ecg_service\algo\zdata_statistics.c
@@ -7795,11 +7795,6 @@
.\src\app_service\ecg_service\ecg_data_mgr.c
- ecg_data_analyszer.c
- 1
- .\src\app_service\ecg_service\algo\ecg_data_analyszer.c
-
-
iflytop_simple_filter.c
1
.\src\app_service\ecg_service\algo\iflytop_simple_filter.c
@@ -7810,9 +7805,14 @@
.\src\app_service\ecg_service\algo\iflytop_simple_filter_ext.c
- iflytop_simple_qrs.c
+ zsimple_qrs.c
+ 1
+ .\src\app_service\ecg_service\algo\zsimple_qrs.c
+
+
+ zdata_statistics.c
1
- .\src\app_service\ecg_service\algo\iflytop_simple_qrs.c
+ .\src\app_service\ecg_service\algo\zdata_statistics.c
diff --git a/app/src/app_basic_service/basic/event.h b/app/src/app_basic_service/basic/event.h
index ee7b30a..3357438 100644
--- a/app/src/app_basic_service/basic/event.h
+++ b/app/src/app_basic_service/basic/event.h
@@ -8,13 +8,13 @@
#define ECG_DATA_REPORT_FRAME_NUM 64 // ecg每次上报的帧数
typedef enum {
- kevent_tmr_scheduler_event,
+ kappevent_tmr_scheduler_event,
kappevent_battery_start_charge, // 开始充电事件
kappevent_battery_end_charge, // 停止充电事件
- kappevent_start_capture,
- kappevent_stop_capture,
+ kappevent_start_capture, // 开始采集
+ kappevent_stop_capture, // 停止采集
kecg_data_report_event, // ecg数据上报事件
} app_event_type_t;
diff --git a/app/src/app_basic_service/zapp.c b/app/src/app_basic_service/zapp.c
index cf263bc..1326e68 100644
--- a/app/src/app_basic_service/zapp.c
+++ b/app/src/app_basic_service/zapp.c
@@ -54,7 +54,7 @@ static void state_machine_driver_tmr_cb(void* p_context) { //
wd_feed();
static app_event_t appevent;
static uint8_t event_hang_up = 0;
- appevent.eventType = kevent_tmr_scheduler_event;
+ appevent.eventType = kappevent_tmr_scheduler_event;
zapp_ebus_push_event_ext(&event_hang_up, &appevent);
}
@@ -199,6 +199,9 @@ void zapp_gstate_set_preview_state(bool is_preview) {
p_gstate->is_preview = is_preview;
}
+/***********************************************************************************************************************
+ * zapp_exec_in_main_context *
+ ***********************************************************************************************************************/
typedef struct {
uint8_t* hang_up_flag;
void (*handler)(void*);
diff --git a/app/src/app_service/ecg_service/algo/ecg_data_analyszer.c b/app/src/app_service/ecg_service/algo/ecg_data_analyszer.c
deleted file mode 100644
index 6138b2a..0000000
--- a/app/src/app_service/ecg_service/algo/ecg_data_analyszer.c
+++ /dev/null
@@ -1,7 +0,0 @@
-#include "ecg_data_analyszer.h"
-
-void ecg_data_analyszer_init() {}
-void ecg_data_analyszer_push_data(int32_t data) {}
-
-float ecg_data_analyszer_get_display_data() { return 50; }
-float ecg_data_analyszer_get_heart_rate() { return 50; }
\ No newline at end of file
diff --git a/app/src/app_service/ecg_service/algo/ecg_data_analyszer.h b/app/src/app_service/ecg_service/algo/ecg_data_analyszer.h
deleted file mode 100644
index ac04d7f..0000000
--- a/app/src/app_service/ecg_service/algo/ecg_data_analyszer.h
+++ /dev/null
@@ -1,9 +0,0 @@
-#pragma once
-
-#include
-
-void ecg_data_analyszer_init();
-void ecg_data_analyszer_push_data(int32_t data);
-
-float ecg_data_analyszer_get_display_data();
-float ecg_data_analyszer_get_heart_rate();
\ No newline at end of file
diff --git a/app/src/app_service/ecg_service/algo/iflytop_simple_filter.c b/app/src/app_service/ecg_service/algo/iflytop_simple_filter.c
index 9a8d8f9..c9ccc1c 100644
--- a/app/src/app_service/ecg_service/algo/iflytop_simple_filter.c
+++ b/app/src/app_service/ecg_service/algo/iflytop_simple_filter.c
@@ -5,6 +5,7 @@
#include
#include
#include
+#include
#define PI 3.141592653
@@ -140,36 +141,43 @@ typedef struct {
#endif
void median_filter_init(median_filter_t *filter, int medianSize) {
- filter->valStartPos = 0;
- filter->valEndPos = 0;
- filter->medianSize = medianSize;
+ filter->medianSize = medianSize;
+ filter->numVal = 0;
for (int i = 0; i < MEDIAN_FILTER_MAX_SIZE; i++) {
filter->val[i] = 0;
}
}
float median_filter_update(median_filter_t *filter, float val) {
- filter->val[filter->valEndPos] = val;
- filter->valEndPos++;
- if (filter->valEndPos >= filter->medianSize) {
- filter->valEndPos = 0;
+ if (filter->numVal >= filter->medianSize) {
+ memmove(filter->val, filter->val + 1, (filter->medianSize - 1) * sizeof(float));
+ filter->numVal--;
}
- if (filter->valEndPos == filter->valStartPos) {
- filter->valStartPos++;
- if (filter->valStartPos >= filter->medianSize) {
- filter->valStartPos = 0;
- }
- }
- for (int i = 0; i < filter->medianSize; i++) {
+
+ filter->val[filter->numVal] = val;
+ filter->numVal++;
+
+ for (int i = 0; i < filter->numVal; i++) {
filter->temp[i] = filter->val[i];
}
- for (int i = 0; i < filter->medianSize; i++) {
- for (int j = i + 1; j < filter->medianSize; j++) {
+
+ for (int i = 0; i < filter->numVal; i++) {
+ for (int j = i + 1; j < filter->numVal; j++) {
if (filter->temp[i] > filter->temp[j]) {
- float t = filter->temp[i];
+ float temp = filter->temp[i];
filter->temp[i] = filter->temp[j];
- filter->temp[j] = t;
+ filter->temp[j] = temp;
}
}
}
- return filter->temp[filter->medianSize / 2];
+
+ // 4 --> 1,2
+ // 3 --> 1
+ // 2 --> 0,1
+ // 1 --> 0
+
+ if (filter->numVal % 2 == 0) {
+ return (filter->temp[filter->numVal / 2 - 1] + filter->temp[filter->numVal / 2]) / 2;
+ } else {
+ return filter->temp[filter->numVal / 2];
+ }
}
diff --git a/app/src/app_service/ecg_service/algo/iflytop_simple_filter.h b/app/src/app_service/ecg_service/algo/iflytop_simple_filter.h
index edd1239..04627eb 100644
--- a/app/src/app_service/ecg_service/algo/iflytop_simple_filter.h
+++ b/app/src/app_service/ecg_service/algo/iflytop_simple_filter.h
@@ -67,15 +67,14 @@ float NOTCHFilter_Update(NOTCHFilter_t *filter, float vin);
// #ifdef __cplusplus
// }
// #endif
-#define MEDIAN_FILTER_MAX_SIZE 100
+#define MEDIAN_FILTER_MAX_SIZE 50
typedef struct {
float val[MEDIAN_FILTER_MAX_SIZE];
float temp[MEDIAN_FILTER_MAX_SIZE];
- int valStartPos;
- int valEndPos;
int medianSize;
+ int numVal;
} median_filter_t;
void median_filter_init(median_filter_t *filter, int medianSize);
diff --git a/app/src/app_service/ecg_service/algo/iflytop_simple_qrs.c b/app/src/app_service/ecg_service/algo/iflytop_simple_qrs.c
deleted file mode 100644
index e69de29..0000000
diff --git a/app/src/app_service/ecg_service/algo/iflytop_simple_qrs.h b/app/src/app_service/ecg_service/algo/iflytop_simple_qrs.h
deleted file mode 100644
index f7e94aa..0000000
--- a/app/src/app_service/ecg_service/algo/iflytop_simple_qrs.h
+++ /dev/null
@@ -1,19 +0,0 @@
-#pragma once
-#include
-#include
-
-
-typedef struct
-{
- //计算数据的滑动平均值
- //计算数据的滑动最大值
- //
-// 1. 原始数据的滑动窗口(滤波后的)
-// 2. 窗口选择多大?
-// 3. 均值,最大值
-// 4. 正负?
-// 5. 零点
-}iflytop_simple_qrs_t;
-
-
-
diff --git a/app/src/app_service/ecg_service/algo/zdata_statistics.c b/app/src/app_service/ecg_service/algo/zdata_statistics.c
new file mode 100644
index 0000000..630b5a1
--- /dev/null
+++ b/app/src/app_service/ecg_service/algo/zdata_statistics.c
@@ -0,0 +1,38 @@
+#include "zdata_statistics.h"
+
+void zdata_statistics_init(zdata_statistics_t* p_analyzer, int32_t* buf, int32_t bufsize) {
+ p_analyzer->buf = buf;
+ p_analyzer->bufsize = bufsize;
+ p_analyzer->head = 0;
+ p_analyzer->tail = 0;
+ p_analyzer->avg = 0;
+ p_analyzer->max = 0;
+ p_analyzer->min = 0;
+}
+void zdata_statistics_push(zdata_statistics_t* p_analyzer, int32_t data) {
+ p_analyzer->buf[p_analyzer->head] = data;
+ p_analyzer->head = (p_analyzer->head + 1) % p_analyzer->bufsize;
+ if (p_analyzer->head == p_analyzer->tail) {
+ p_analyzer->tail = (p_analyzer->tail + 1) % p_analyzer->bufsize;
+ p_analyzer->sum -= p_analyzer->buf[p_analyzer->tail];
+ }
+ p_analyzer->sum += data;
+ p_analyzer->avg = p_analyzer->sum / p_analyzer->bufsize;
+ p_analyzer->max = p_analyzer->max > data ? p_analyzer->max : data;
+ p_analyzer->min = p_analyzer->min < data ? p_analyzer->min : data;
+}
+
+void zdata_statistics_clear(zdata_statistics_t* p_analyzer) {
+ p_analyzer->head = 0;
+ p_analyzer->tail = 0;
+ p_analyzer->sum = 0;
+ p_analyzer->avg = 0;
+ p_analyzer->max = 0;
+ p_analyzer->min = 0;
+}
+
+float zdata_statistics_get_avg(zdata_statistics_t* p_analyzer) { return p_analyzer->avg; }
+float zdata_statistics_get_max(zdata_statistics_t* p_analyzer) { return p_analyzer->max; }
+float zdata_statistics_get_min(zdata_statistics_t* p_analyzer) { return p_analyzer->min; }
+
+bool zdata_statistics_is_full(zdata_statistics_t* p_analyzer) { return p_analyzer->head == p_analyzer->tail; }
diff --git a/app/src/app_service/ecg_service/algo/zdata_statistics.h b/app/src/app_service/ecg_service/algo/zdata_statistics.h
new file mode 100644
index 0000000..22ef9b6
--- /dev/null
+++ b/app/src/app_service/ecg_service/algo/zdata_statistics.h
@@ -0,0 +1,28 @@
+#pragma once
+#include
+#include
+
+typedef struct {
+ int32_t* buf;
+ int32_t bufsize;
+
+ float sum;
+
+ float avg;
+ float max;
+ float min;
+
+ uint32_t head;
+ uint32_t tail;
+
+} zdata_statistics_t;
+
+void zdata_statistics_init(zdata_statistics_t* p_analyzer, int32_t* buf, int32_t bufsize);
+void zdata_statistics_push(zdata_statistics_t* p_analyzer, int32_t data);
+void zdata_statistics_clear(zdata_statistics_t* p_analyzer);
+
+float zdata_statistics_get_avg(zdata_statistics_t* p_analyzer);
+float zdata_statistics_get_max(zdata_statistics_t* p_analyzer);
+float zdata_statistics_get_min(zdata_statistics_t* p_analyzer);
+
+bool zdata_statistics_is_full(zdata_statistics_t* p_analyzer);
\ No newline at end of file
diff --git a/app/src/app_service/ecg_service/algo/zsimple_qrs.c b/app/src/app_service/ecg_service/algo/zsimple_qrs.c
new file mode 100644
index 0000000..b0d2507
--- /dev/null
+++ b/app/src/app_service/ecg_service/algo/zsimple_qrs.c
@@ -0,0 +1,42 @@
+#include "zsimple_qrs.h"
+
+void zsimple_qrs_init(zsimple_qrs_t* p_qrs, float sample_rate_s) {
+ p_qrs->last_peak_pos = 0;
+ p_qrs->sample_rate_s = sample_rate_s;
+ p_qrs->heartrate = 0;
+
+ p_qrs->index = 0;
+ p_qrs->hasfindpeak = false;
+
+ median_filter_init(&p_qrs->heart_rate_filter, 10);
+}
+void zsimple_qrs_clear(zsimple_qrs_t* p_qrs) {
+ p_qrs->last_peak_pos = 0;
+ p_qrs->heartrate = 0;
+ p_qrs->index = 0;
+ p_qrs->hasfindpeak = false;
+ median_filter_init(&p_qrs->heart_rate_filter, 10);
+
+}
+void zsimple_qrs_process_data(zsimple_qrs_t* p_qrs, int32_t indata, float min, float max, float refavg) { //
+ p_qrs->index++;
+
+ int judge_threshold = min + (max - min) * QRS_PEAK_THRESHOLD;
+
+ if (!p_qrs->hasfindpeak) {
+ if (indata > judge_threshold) {
+ float peak_interval_s = (p_qrs->index - p_qrs->last_peak_pos) * p_qrs->sample_rate_s;
+ if (peak_interval_s > PEAK_MIN_INTERVAL) {
+ p_qrs->hasfindpeak = true;
+ p_qrs->last_peak_pos = p_qrs->index;
+ float heartrate = 60 / peak_interval_s;
+ p_qrs->heartrate = median_filter_update(&p_qrs->heart_rate_filter, heartrate);
+ }
+ }
+ } else {
+ if (indata < judge_threshold) {
+ p_qrs->hasfindpeak = false;
+ }
+ }
+}
+float zsimple_qrs_get_heartrate(zsimple_qrs_t* p_qrs) { return p_qrs->heartrate; }
diff --git a/app/src/app_service/ecg_service/algo/zsimple_qrs.h b/app/src/app_service/ecg_service/algo/zsimple_qrs.h
new file mode 100644
index 0000000..1b307d4
--- /dev/null
+++ b/app/src/app_service/ecg_service/algo/zsimple_qrs.h
@@ -0,0 +1,32 @@
+#pragma once
+#include
+#include
+
+#include "iflytop_simple_filter.h"
+#include "zdata_statistics.h"
+
+#define QRS_PEAK_THRESHOLD (0.5f)
+
+/**
+ * @brief
+ * 假设心率为200,此时两个峰之间的间隔为0.3s,这里设置最小间隔为0.15s
+ *
+ */
+#define PEAK_MIN_INTERVAL 0.15
+
+#define HEART_RATE_BUF_SIZE 10
+
+typedef struct {
+ int32_t last_peak_pos;
+ float sample_rate_s;
+ float heartrate;
+ uint32_t index;
+ bool hasfindpeak;
+
+ median_filter_t heart_rate_filter;
+} zsimple_qrs_t;
+
+void zsimple_qrs_init(zsimple_qrs_t* p_qrs, float sample_rate_s);
+void zsimple_qrs_clear();
+void zsimple_qrs_process_data(zsimple_qrs_t* p_qrs, int32_t indata, float min, float max, float refavg);
+float zsimple_qrs_get_heartrate(zsimple_qrs_t* p_qrs);
diff --git a/app/src/app_service/ecg_service/ecg_algo.c b/app/src/app_service/ecg_service/ecg_algo.c
index 002fe14..844142a 100644
--- a/app/src/app_service/ecg_service/ecg_algo.c
+++ b/app/src/app_service/ecg_service/ecg_algo.c
@@ -1,28 +1,62 @@
#include "ecg_algo.h"
#include "algo/iflytop_simple_filter_ext.h"
+#include "algo/zdata_statistics.h"
+#include "algo/zsimple_qrs.h"
+#include "znordic.h"
LPFilterExt_t m_lp_filter;
HPFilterExt_t m_hp_filter;
NOTCHFilterExt_t m_notch_filter;
+int32_t m_data_statistics_buf[STATISTICS_BUF_SIZE]; // 心率判断
+zdata_statistics_t m_data_statistics;
+zsimple_qrs_t m_qrs;
+
int32_t reportdata;
int32_t displaydata;
-void ecg_algo_init() { ecg_algo_reset(); }
+void ecg_algo_init() {
+ ecg_algo_reset();
+
+ zsimple_qrs_init(&m_qrs, SAMPLE_RATE);
+ zdata_statistics_init(&m_data_statistics, m_data_statistics_buf, ZARRAY_SIZE(m_data_statistics_buf));
+}
void ecg_algo_process_data(int32_t indata) {
int32_t data = indata;
data = LPFilterExt_update(&m_lp_filter, data);
data = HPFilterExt_update(&m_hp_filter, data);
data = NOTCHFilterExt_update(&m_notch_filter, data);
reportdata = data;
+
+ zdata_statistics_push(&m_data_statistics, data);
+ if (zdata_statistics_is_full(&m_data_statistics)) {
+ zsimple_qrs_process_data(&m_qrs, data, zdata_statistics_get_min(&m_data_statistics), zdata_statistics_get_max(&m_data_statistics),
+ zdata_statistics_get_avg(&m_data_statistics));
+
+ /**
+ * @brief
+ */
+ int32_t max = zdata_statistics_get_max(&m_data_statistics);
+ int32_t min = zdata_statistics_get_min(&m_data_statistics);
+
+
+ int32_t nowvaloff = data - min;
+ int32_t nowval100 = nowvaloff * 100 / (max - min);
+ displaydata = nowval100;
+
+ } else {
+ displaydata = 50;
+ }
}
void ecg_algo_reset() {
- LPFilterExt_init(&m_lp_filter, 40, 0.002, 5, true);
- HPFilterExt_init(&m_hp_filter, 1, 0.002, 3, true);
- NOTCHFilterExt_init(&m_notch_filter, 50, 1, 0.002, 1, true);
+ LPFilterExt_init(&m_lp_filter, 40, SAMPLE_RATE, 5, true);
+ HPFilterExt_init(&m_hp_filter, 1, SAMPLE_RATE, 3, true);
+ NOTCHFilterExt_init(&m_notch_filter, 50, 1, SAMPLE_RATE, 1, true);
+ zdata_statistics_clear(&m_data_statistics);
+ zsimple_qrs_clear();
}
int32_t ecg_algo_get_report_data() { return reportdata; }
-int32_t ecg_algo_get_display_data() { return 50; }
-int32_t ecg_algo_get_heart_rate() { return 100; }
+int32_t ecg_algo_get_display_data() { return displaydata; }
+int32_t ecg_algo_get_heart_rate() { return zsimple_qrs_get_heartrate(&m_qrs); }
diff --git a/app/src/app_service/ecg_service/ecg_algo.h b/app/src/app_service/ecg_service/ecg_algo.h
index c08c751..9ffe3c5 100644
--- a/app/src/app_service/ecg_service/ecg_algo.h
+++ b/app/src/app_service/ecg_service/ecg_algo.h
@@ -4,6 +4,9 @@
#include "app_basic_service/zapp.h"
+#define SAMPLE_PERIOD_S ( (float)(1.0/SAMPLE_RATE))
+#define STATISTICS_BUF_SIZE ((int32_t)(2 / SAMPLE_PERIOD_S))
+
void ecg_algo_init();
void ecg_algo_process_data(int32_t indata);
void ecg_algo_reset();
diff --git a/app/src/app_service/ecg_service/ecg_service.c b/app/src/app_service/ecg_service/ecg_service.c
index 50351da..e54d670 100644
--- a/app/src/app_service/ecg_service/ecg_service.c
+++ b/app/src/app_service/ecg_service/ecg_service.c
@@ -12,36 +12,19 @@
static nrf_drv_spi_t ads129x_spi = NRF_DRV_SPI_INSTANCE(ADS1291_SPI_INSTANCE); // global
static nrf_drv_spi_config_t ads129x_spi_config;
-
-// uint8_t port_spi_transmit_receive(uint8_t tx);
-// int32_t i24toi32(uint8_t* p_i32);
-// uint8_t ads129x_send_cmd(uint8_t cmd);
-// uint8_t ads129x_rw_reg(uint8_t cmd, uint8_t data);
-// void ads129x_write_multiregs(uint8_t reg, uint8_t* ch, uint8_t size);
-// void ads129x_read_multiregs(uint8_t reg, uint8_t* ch, uint8_t size);
-// void ads129x_readback_regs(ads129x_regs_t* regcache);
-// void ads129x_dump_regs(ads129x_regs_t* regcache);
-// bool ads129x_write_regs(ads129x_regs_t* writeval);
-// void ads129x_read_data(ads129x_capture_data_t* capture_data);
+static bool m_testmode_flag;
/***********************************************************************************************************************
* PRIVATE_FUNC *
***********************************************************************************************************************/
-#define ADS129X_CS_SET() nrf_gpio_pin_set(ADS1291_SPI_CS0_PIN);
-#define ADS129X_CS_RESET() nrf_gpio_pin_clear(ADS1291_SPI_CS0_PIN);
-#define ADS129X_START_SET() nrf_gpio_pin_set(ADS1291_START_PIN);
-#define ADS129X_START_RESET() nrf_gpio_pin_clear(ADS1291_START_PIN);
-#define ADS129X_REST_SET() nrf_gpio_pin_set(ADS1291_PWDN_PIN);
-#define ADS129X_REST_RESET() nrf_gpio_pin_clear(ADS1291_PWDN_PIN);
-#define ADS129X_DRDY_GET() nrf_gpio_pin_read(ADS1291_READY_PIN)
-uint8_t port_spi_transmit_receive(uint8_t tx) {
+static uint8_t port_spi_transmit_receive(uint8_t tx) {
uint8_t data;
nrf_drv_spi_transfer(&ads129x_spi, &tx, 1, &data, 1);
return data;
}
-int32_t i24toi32(uint8_t* p_i32) {
+static int32_t i24toi32(uint8_t* p_i32) {
int32_t rev = 0;
rev = (((int32_t)p_i32[0]) << 16) | (((int32_t)p_i32[1]) << 8) | ((int32_t)p_i32[2]);
if ((p_i32[0] & 0x80) == 0x80) {
@@ -51,25 +34,25 @@ int32_t i24toi32(uint8_t* p_i32) {
}
/* ads129X发送指令 */
-uint8_t ads129x_send_cmd(uint8_t cmd) {
+static uint8_t ads129x_send_cmd(uint8_t cmd) {
uint8_t rx = 0;
- ADS129X_CS_RESET(); /* 选中设备 */
+ nrf_gpio_pin_clear(ADS1291_SPI_CS0_PIN); /* 选中设备 */
nrf_delay_us(100);
rx = port_spi_transmit_receive(cmd);
nrf_delay_us(100);
- ADS129X_CS_SET(); /* 释放设备 */
+ nrf_gpio_pin_set(ADS1291_SPI_CS0_PIN); /* 释放设备 */
return rx;
}
/* ads129X读写寄存器,自动根据指令类型区分读和写操作 */
-uint8_t ads129x_rw_reg(uint8_t cmd, uint8_t data) {
+static uint8_t ads129x_rw_reg(uint8_t cmd, uint8_t data) {
uint8_t rx = 0;
- ADS129X_CS_RESET(); /* 选中设备 */
+ nrf_gpio_pin_clear(ADS1291_SPI_CS0_PIN); /* 选中设备 */
nrf_delay_us(1);
port_spi_transmit_receive(cmd); /* 发送读写指令 */
@@ -81,16 +64,16 @@ uint8_t ads129x_rw_reg(uint8_t cmd, uint8_t data) {
rx = port_spi_transmit_receive(data); /* 写入数值 */
nrf_delay_us(1);
- ADS129X_CS_SET(); /* 释放设备 */
+ nrf_gpio_pin_set(ADS1291_SPI_CS0_PIN); /* 释放设备 */
return rx;
}
/* 从指定寄存器开始读写一定数量的寄存器 */
-void ads129x_write_multiregs(uint8_t reg, uint8_t* ch, uint8_t size) {
+static void ads129x_write_multiregs(uint8_t reg, uint8_t* ch, uint8_t size) {
uint8_t i;
- ADS129X_CS_RESET(); /* 选中设备 */
+ nrf_gpio_pin_clear(ADS1291_SPI_CS0_PIN); /* 选中设备 */
nrf_delay_us(100);
port_spi_transmit_receive(ADS129X_COMMAND_WREG | reg);
@@ -104,14 +87,14 @@ void ads129x_write_multiregs(uint8_t reg, uint8_t* ch, uint8_t size) {
}
nrf_delay_us(100);
- ADS129X_CS_SET();
+ nrf_gpio_pin_set(ADS1291_SPI_CS0_PIN);
}
/* 从指定寄存器开始读写一定数量的寄存器 */
-void ads129x_read_multiregs(uint8_t reg, uint8_t* ch, uint8_t size) {
+static void ads129x_read_multiregs(uint8_t reg, uint8_t* ch, uint8_t size) {
uint8_t i;
- ADS129X_CS_RESET(); /* 选中设备 */
+ nrf_gpio_pin_clear(ADS1291_SPI_CS0_PIN); /* 选中设备 */
nrf_delay_us(100);
port_spi_transmit_receive(ADS129X_COMMAND_RREG | reg);
@@ -125,11 +108,11 @@ void ads129x_read_multiregs(uint8_t reg, uint8_t* ch, uint8_t size) {
}
nrf_delay_us(100);
- ADS129X_CS_SET();
+ nrf_gpio_pin_set(ADS1291_SPI_CS0_PIN);
}
-void ads129x_readback_regs(ads129x_regs_t* regcache) { ads129x_read_multiregs(ADS129X_REG_ID, (uint8_t*)regcache, sizeof(ads129x_regs_t)); }
-void ads129x_dump_regs(ads129x_regs_t* regcache) {
+static void ads129x_readback_regs(ads129x_regs_t* regcache) { ads129x_read_multiregs(ADS129X_REG_ID, (uint8_t*)regcache, sizeof(ads129x_regs_t)); }
+static void ads129x_dump_regs(ads129x_regs_t* regcache) {
ZLOGI("id : %x", regcache->id);
ZLOGI("cfg1 : %x", regcache->cfg1);
ZLOGI("cfg2 : %x", regcache->cfg2);
@@ -144,7 +127,7 @@ void ads129x_dump_regs(ads129x_regs_t* regcache) {
ZLOGI("gpio : %x", regcache->gpio);
}
-bool ads129x_write_regs(ads129x_regs_t* writeval) {
+static bool ads129x_write_regs(ads129x_regs_t* writeval) {
static ads129x_regs_t rdbak;
ads129x_write_multiregs(ADS129X_REG_ID, (uint8_t*)writeval, sizeof(ads129x_regs_t));
ads129x_read_multiregs(ADS129X_REG_ID, (uint8_t*)&rdbak, sizeof(ads129x_regs_t));
@@ -163,10 +146,10 @@ bool ads129x_write_regs(ads129x_regs_t* writeval) {
return true;
}
-void ads129x_read_data(ads129x_capture_data_t* capture_data) {
+static void ads129x_read_data(ads129x_capture_data_t* capture_data) {
uint8_t rddata[9];
- ADS129X_CS_RESET(); /* 选中设备 */
+ nrf_gpio_pin_clear(ADS1291_SPI_CS0_PIN); /* 选中设备 */
nrf_delay_us(10);
port_spi_transmit_receive(ADS129X_COMMAND_RDATA);
@@ -174,7 +157,7 @@ void ads129x_read_data(ads129x_capture_data_t* capture_data) {
for (int i = 0; i < 9; i++) {
rddata[i] = port_spi_transmit_receive(0);
}
- ADS129X_CS_SET();
+ nrf_gpio_pin_set(ADS1291_SPI_CS0_PIN);
/**
* @brief
@@ -195,21 +178,32 @@ void ads129x_read_data(ads129x_capture_data_t* capture_data) {
capture_data->ch2data = i24toi32(&rddata[6]);
}
+static bool ads129x_ping() {
+ uint8_t data;
+ ads129x_read_multiregs(ADS129X_REG_ID, (uint8_t*)&data, sizeof(uint8_t));
+ if (data == 0x052) {
+ return true;
+ }
+ return false;
+}
/***********************************************************************************************************************
* PUBLIC_FUNC *
***********************************************************************************************************************/
-void ads1291_ready_pin_irq(nrfx_gpiote_pin_t pin, nrf_gpiote_polarity_t action) {
- if (ADS129X_DRDY_GET()) {
- static ads129x_capture_data_t capture_data;
- ads129x_read_data(&capture_data);
- ecg_algo_process_data(capture_data.ch1data);
+static void ads1291_ready_pin_irq(nrfx_gpiote_pin_t pin, nrf_gpiote_polarity_t action) {
+ static ads129x_capture_data_t capture_data;
+ // 读
+ ads129x_read_data(&capture_data);
- one_frame_t frame;
- frame.data = ecg_algo_get_report_data();
- frame.leadoff = capture_data.loffstate;
- ecg_data_mgr_push_one_frame(frame);
- }
+ // 算法处理
+ // ecg_algo_process_data(capture_data.ch1data);
+
+ // 上报
+ one_frame_t frame;
+ // frame.data = ecg_algo_get_report_data();
+ frame.data = capture_data.ch1data;
+ frame.leadoff = capture_data.loffstate;
+ ecg_data_mgr_push_one_frame(frame);
}
void ecg_service_init() { //
@@ -217,17 +211,28 @@ void ecg_service_init() { //
* @brief
* 在这里初始化一些硬件无关的内存组件
*/
-
ecg_data_mgr_init();
ecg_algo_init();
+
+ // 初始化部分硬件
+ znrf_gpio_cfg_output(ADS1291_PWDN_PIN, NRF_GPIO_PIN_NOPULL);
+ nrf_gpio_pin_clear(ADS1291_PWDN_PIN);
}
void ecg_service_load() {
/**
* @brief 硬件接口初始化
*/
- nrfx_gpiote_init();
+ // GPIO初始化
+ znrf_gpio_cfg_output(ADS1291_SPI_CS0_PIN, NRF_GPIO_PIN_NOPULL);
+ znrf_gpio_cfg_output(ADS1291_PWDN_PIN, NRF_GPIO_PIN_NOPULL);
+ znrf_gpio_cfg_output(ADS1291_START_PIN, NRF_GPIO_PIN_NOPULL);
+ nrf_gpio_pin_set(ADS1291_SPI_CS0_PIN);
+ nrf_gpio_pin_clear(ADS1291_PWDN_PIN);
+ nrf_gpio_pin_clear(ADS1291_START_PIN);
+
+ // SPI初始化
ads129x_spi_config.sck_pin = ADS1291_SPI_SCK_PIN;
ads129x_spi_config.mosi_pin = ADS1291_SPI_MOSI_PIN;
ads129x_spi_config.miso_pin = ADS1291_SPI_MISO_PIN;
@@ -238,11 +243,9 @@ void ecg_service_load() {
ads129x_spi_config.mode = NRF_DRV_SPI_MODE_1;
ads129x_spi_config.bit_order = NRF_DRV_SPI_BIT_ORDER_MSB_FIRST;
nrf_drv_spi_init(&ads129x_spi, &ads129x_spi_config, NULL, NULL);
- znrf_gpio_cfg_output(ADS1291_SPI_CS0_PIN, NRF_GPIO_PIN_NOPULL);
- znrf_gpio_cfg_output(ADS1291_PWDN_PIN, NRF_GPIO_PIN_NOPULL);
- znrf_gpio_cfg_output(ADS1291_START_PIN, NRF_GPIO_PIN_NOPULL);
- ZASSERT(nrfx_gpiote_is_init());
+ // 中断初始化
+ nrfx_gpiote_init();
nrf_gpio_cfg_input(ADS1291_READY_PIN, NRF_GPIO_PIN_PULLUP);
nrf_drv_gpiote_in_config_t inConfig = GPIOTE_CONFIG_IN_SENSE_TOGGLE(false); //
inConfig.pull = NRF_GPIO_PIN_PULLUP; // 默认上拉
@@ -250,40 +253,39 @@ void ecg_service_load() {
nrfx_gpiote_in_init(ADS1291_READY_PIN, &inConfig, ads1291_ready_pin_irq);
nrfx_gpiote_in_event_enable(ADS1291_READY_PIN, true);
- /**
- * @brief ads129x 芯片初始化
- */
-
- ADS129X_CS_SET();
-
- ADS129X_REST_RESET();
- ADS129X_START_RESET();
- nrf_delay_ms(1000);
- ADS129X_REST_SET();
+ nrf_gpio_pin_set(ADS1291_PWDN_PIN);
nrf_delay_ms(30); /* 硬件复位 */
-
+ ads129x_send_cmd(ADS129X_COMMAND_WAKEUP);
ads129x_send_cmd(ADS129X_COMMAND_SDATAC); /* 软件复位,并停止连续读状态 */
- nrf_delay_ms(30);
+
+ for (size_t i = 0; i < 100; i++) {
+ if (ads129x_ping()) {
+ break;
+ }
+ nrf_delay_ms(1);
+ }
+
+ ZASSERT(ads129x_ping());
static ads129x_regs_t regcache;
ads129x_readback_regs(®cache);
ads129x_dump_regs(®cache);
regcache.cfg1 = 0x02;
regcache.cfg2 = 0xE0;
- regcache.loff = 0xF0;
+ regcache.loff = 0xF1;
regcache.ch1set = 0x00;
- regcache.ch2set = 0x00;
+ regcache.ch2set = 0x81;
regcache.rld_sens = 0x20;
regcache.loff_sens = 0x03;
+
ads129x_write_regs(®cache);
- ads129x_send_cmd(ADS129X_COMMAND_WAKEUP); /* 软件复位,并停止连续读状态 */
}
void ecg_service_unload() {
/**
* @brief
*/
ads129x_send_cmd(ADS129X_COMMAND_STANDBY); /* 软件复位,并停止连续读状态 */
- ADS129X_REST_RESET();
+ nrf_gpio_pin_clear(ADS1291_PWDN_PIN);
nrfx_gpiote_in_event_disable(ADS1291_READY_PIN);
@@ -308,6 +310,19 @@ static uint32_t ecg_service_captured_time = 0;
void ecg_service_start_capture() { //
ecg_data_mgr_clear_buffer();
+
+ if (m_testmode_flag) {
+ static ads129x_regs_t regcache;
+ ads129x_readback_regs(®cache);
+ ads129x_dump_regs(®cache);
+
+ regcache.cfg2 = ADS129X_SET_BITS(regcache.cfg2, ADS129X_INT_TEST, ADS129X_INT_TEST_ON);
+ regcache.cfg2 = ADS129X_SET_BITS(regcache.cfg2, ADS129X_INT_FREQ, ADS129X_INT_FREQ_AC);
+ regcache.ch1set = ADS129X_SET_BITS(regcache.ch1set, ADS129X_MUXx, ADS129X_CHx_INPUT_TEST);
+
+ ads129x_write_regs(®cache);
+ }
+
ads129x_send_cmd(ADS129X_COMMAND_START); /* 发送开始数据转换(等效于拉高START引脚) */
ecg_service_captured_time = znordic_getpower_on_ms();
}
@@ -315,10 +330,21 @@ void ecg_service_stop_capture() { //
ads129x_send_cmd(ADS129X_COMMAND_STOP); /* 发送停止数据转换(等效于拉低START引脚) */
}
uint32_t ecg_service_has_captured_time() { return znordic_haspassed_ms(ecg_service_captured_time); }
-
-void ecg_service_subic_write_reg(uint8_t addr, uint8_t val) { ads129x_rw_reg(ADS129X_COMMAND_WREG | addr, val); }
+void ecg_service_subic_write_reg(uint8_t addr, uint8_t val) {
+ if (addr > sizeof(ads129x_regs_t)) {
+ return;
+ }
+ static ads129x_regs_t regcache;
+ ads129x_readback_regs(®cache);
+ uint8_t* p = (uint8_t*)®cache;
+ p[addr] = val;
+ ads129x_write_regs(®cache);
+}
uint8_t ecg_service_subic_read_reg(uint8_t addr) { return ads129x_rw_reg(ADS129X_COMMAND_RREG | addr, 0); }
-
int32_t ecg_service_get_display_val() { return ecg_algo_get_display_data(); }
-
int32_t ecg_service_get_heart_rate() { return ecg_algo_get_heart_rate(); }
+
+void ecg_service_set_in_test_mode(bool testmode) {
+ ZLOGI("ecg_service_set_in_test_mode %d", testmode);
+ m_testmode_flag = testmode;
+}
diff --git a/app/src/app_service/ecg_service/ecg_service.h b/app/src/app_service/ecg_service/ecg_service.h
index d890698..ca6484c 100644
--- a/app/src/app_service/ecg_service/ecg_service.h
+++ b/app/src/app_service/ecg_service/ecg_service.h
@@ -26,12 +26,13 @@ void ecg_service_init();
void ecg_service_load();
void ecg_service_unload();
-void ecg_service_start_capture();
-void ecg_service_stop_capture();
+void ecg_service_start_capture();
+void ecg_service_stop_capture();
uint32_t ecg_service_has_captured_time();
-int32_t ecg_service_get_display_val();
-int32_t ecg_service_get_heart_rate();
+int32_t ecg_service_get_display_val();
+int32_t ecg_service_get_heart_rate();
void ecg_service_subic_write_reg(uint8_t addr, uint8_t val);
uint8_t ecg_service_subic_read_reg(uint8_t addr);
+void ecg_service_set_in_test_mode(bool testmode);
diff --git a/app/src/main.c b/app/src/main.c
index 3396a1e..9af7164 100644
--- a/app/src/main.c
+++ b/app/src/main.c
@@ -64,7 +64,7 @@ void app_error_fault_handler(uint32_t id, uint32_t pc, uint32_t info) {
int main() {
zapp_early_init();
- znordic_init_without_wd();
+ znordic_init();
zapp_init();
/*******************************************************************************
diff --git a/app/src/one_conduction_main.c b/app/src/one_conduction_main.c
index 1ac1f9f..e96d44f 100644
--- a/app/src/one_conduction_main.c
+++ b/app/src/one_conduction_main.c
@@ -184,6 +184,12 @@ void one_conduction_process_rx_packet(uint8_t* rx, int len) {
send_success_receipt(rxheader, 0);
}
+ else if (cmd == ify_hrs_cmd_set_ecg_in_test_mode) {
+ int32_t testmode = *(int32_t*)rxheader->data;
+ ecg_service_set_in_test_mode(testmode);
+ send_success_receipt(rxheader, 0);
+ }
+
else {
send_error_receipt(rxheader, kifyhrs_ecode_cmd_not_support);
}
@@ -261,6 +267,11 @@ void on_state_change(device_state_t from, device_state_t to) {
void on_zapp_ebus_event(void* p_event_data, uint16_t event_size) {
if (!p_event_data) return;
app_event_t* p_event = (app_event_t*)p_event_data;
+
+ if(p_event->eventType == kappevent_tmr_scheduler_event){
+ ZLOGI("tmr event.");
+ }
+
if (zapp_state_machine_now_state() == kstate_standby) {
/**
* @brief
diff --git a/ify_hrs_protocol b/ify_hrs_protocol
index 08b14b4..a1fda58 160000
--- a/ify_hrs_protocol
+++ b/ify_hrs_protocol
@@ -1 +1 @@
-Subproject commit 08b14b499e98175014068f19fdfaddded14718b3
+Subproject commit a1fda58c30f6bb892c9f503280b3896c67e00dda