Browse Source

update

master
zhaohe 1 year ago
parent
commit
07d283f20f
  1. 4
      .vscode/settings.json
  2. 16
      app/app.uvoptx
  3. 28
      app/app.uvprojx
  4. 6
      app/src/app_basic_service/basic/event.h
  5. 5
      app/src/app_basic_service/zapp.c
  6. 7
      app/src/app_service/ecg_service/algo/ecg_data_analyszer.c
  7. 9
      app/src/app_service/ecg_service/algo/ecg_data_analyszer.h
  8. 44
      app/src/app_service/ecg_service/algo/iflytop_simple_filter.c
  9. 5
      app/src/app_service/ecg_service/algo/iflytop_simple_filter.h
  10. 0
      app/src/app_service/ecg_service/algo/iflytop_simple_qrs.c
  11. 19
      app/src/app_service/ecg_service/algo/iflytop_simple_qrs.h
  12. 38
      app/src/app_service/ecg_service/algo/zdata_statistics.c
  13. 28
      app/src/app_service/ecg_service/algo/zdata_statistics.h
  14. 42
      app/src/app_service/ecg_service/algo/zsimple_qrs.c
  15. 32
      app/src/app_service/ecg_service/algo/zsimple_qrs.h
  16. 46
      app/src/app_service/ecg_service/ecg_algo.c
  17. 3
      app/src/app_service/ecg_service/ecg_algo.h
  18. 164
      app/src/app_service/ecg_service/ecg_service.c
  19. 1
      app/src/app_service/ecg_service/ecg_service.h
  20. 2
      app/src/main.c
  21. 11
      app/src/one_conduction_main.c
  22. 2
      ify_hrs_protocol

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

16
app/app.uvoptx

@ -1746,8 +1746,8 @@
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>.\src\app_service\ecg_service\algo\ecg_data_analyszer.c</PathWithFileName>
<FilenameWithoutPath>ecg_data_analyszer.c</FilenameWithoutPath>
<PathWithFileName>.\src\app_service\ecg_service\algo\iflytop_simple_filter.c</PathWithFileName>
<FilenameWithoutPath>iflytop_simple_filter.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
@ -1758,8 +1758,8 @@
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>.\src\app_service\ecg_service\algo\iflytop_simple_filter.c</PathWithFileName>
<FilenameWithoutPath>iflytop_simple_filter.c</FilenameWithoutPath>
<PathWithFileName>.\src\app_service\ecg_service\algo\iflytop_simple_filter_ext.c</PathWithFileName>
<FilenameWithoutPath>iflytop_simple_filter_ext.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
@ -1770,8 +1770,8 @@
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>.\src\app_service\ecg_service\algo\iflytop_simple_filter_ext.c</PathWithFileName>
<FilenameWithoutPath>iflytop_simple_filter_ext.c</FilenameWithoutPath>
<PathWithFileName>.\src\app_service\ecg_service\algo\zsimple_qrs.c</PathWithFileName>
<FilenameWithoutPath>zsimple_qrs.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>
@ -1782,8 +1782,8 @@
<tvExp>0</tvExp>
<tvExpOptDlg>0</tvExpOptDlg>
<bDave2>0</bDave2>
<PathWithFileName>.\src\app_service\ecg_service\algo\iflytop_simple_qrs.c</PathWithFileName>
<FilenameWithoutPath>iflytop_simple_qrs.c</FilenameWithoutPath>
<PathWithFileName>.\src\app_service\ecg_service\algo\zdata_statistics.c</PathWithFileName>
<FilenameWithoutPath>zdata_statistics.c</FilenameWithoutPath>
<RteFlg>0</RteFlg>
<bShared>0</bShared>
</File>

28
app/app.uvprojx

@ -3886,11 +3886,6 @@
<FilePath>.\src\app_service\ecg_service\ecg_data_mgr.c</FilePath>
</File>
<File>
<FileName>ecg_data_analyszer.c</FileName>
<FileType>1</FileType>
<FilePath>.\src\app_service\ecg_service\algo\ecg_data_analyszer.c</FilePath>
</File>
<File>
<FileName>iflytop_simple_filter.c</FileName>
<FileType>1</FileType>
<FilePath>.\src\app_service\ecg_service\algo\iflytop_simple_filter.c</FilePath>
@ -3901,9 +3896,14 @@
<FilePath>.\src\app_service\ecg_service\algo\iflytop_simple_filter_ext.c</FilePath>
</File>
<File>
<FileName>iflytop_simple_qrs.c</FileName>
<FileName>zsimple_qrs.c</FileName>
<FileType>1</FileType>
<FilePath>.\src\app_service\ecg_service\algo\zsimple_qrs.c</FilePath>
</File>
<File>
<FileName>zdata_statistics.c</FileName>
<FileType>1</FileType>
<FilePath>.\src\app_service\ecg_service\algo\iflytop_simple_qrs.c</FilePath>
<FilePath>.\src\app_service\ecg_service\algo\zdata_statistics.c</FilePath>
</File>
</Files>
</Group>
@ -7795,11 +7795,6 @@
<FilePath>.\src\app_service\ecg_service\ecg_data_mgr.c</FilePath>
</File>
<File>
<FileName>ecg_data_analyszer.c</FileName>
<FileType>1</FileType>
<FilePath>.\src\app_service\ecg_service\algo\ecg_data_analyszer.c</FilePath>
</File>
<File>
<FileName>iflytop_simple_filter.c</FileName>
<FileType>1</FileType>
<FilePath>.\src\app_service\ecg_service\algo\iflytop_simple_filter.c</FilePath>
@ -7810,9 +7805,14 @@
<FilePath>.\src\app_service\ecg_service\algo\iflytop_simple_filter_ext.c</FilePath>
</File>
<File>
<FileName>iflytop_simple_qrs.c</FileName>
<FileName>zsimple_qrs.c</FileName>
<FileType>1</FileType>
<FilePath>.\src\app_service\ecg_service\algo\zsimple_qrs.c</FilePath>
</File>
<File>
<FileName>zdata_statistics.c</FileName>
<FileType>1</FileType>
<FilePath>.\src\app_service\ecg_service\algo\iflytop_simple_qrs.c</FilePath>
<FilePath>.\src\app_service\ecg_service\algo\zdata_statistics.c</FilePath>
</File>
</Files>
</Group>

6
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;

5
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*);

7
app/src/app_service/ecg_service/algo/ecg_data_analyszer.c

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

9
app/src/app_service/ecg_service/algo/ecg_data_analyszer.h

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

44
app/src/app_service/ecg_service/algo/iflytop_simple_filter.c

@ -5,6 +5,7 @@
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#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->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;
}
}
}
// 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];
}
return filter->temp[filter->medianSize / 2];
}

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

0
app/src/app_service/ecg_service/algo/iflytop_simple_qrs.c

19
app/src/app_service/ecg_service/algo/iflytop_simple_qrs.h

@ -1,19 +0,0 @@
#pragma once
#include <stdbool.h>
#include <stdint.h>
typedef struct
{
//
//
//
// 1.
// 2.
// 3.
// 4. ?
// 5.
}iflytop_simple_qrs_t;

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

28
app/src/app_service/ecg_service/algo/zdata_statistics.h

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

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

32
app/src/app_service/ecg_service/algo/zsimple_qrs.h

@ -0,0 +1,32 @@
#pragma once
#include <stdbool.h>
#include <stdint.h>
#include "iflytop_simple_filter.h"
#include "zdata_statistics.h"
#define QRS_PEAK_THRESHOLD (0.5f)
/**
* @brief
* 200,0.3s0.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);

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

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

164
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 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);
ecg_algo_process_data(capture_data.ch1data);
//
// ecg_algo_process_data(capture_data.ch1data);
//
one_frame_t frame;
frame.data = ecg_algo_get_report_data();
// 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(&regcache);
ads129x_dump_regs(&regcache);
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(&regcache);
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(&regcache);
ads129x_dump_regs(&regcache);
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(&regcache);
}
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(&regcache);
uint8_t* p = (uint8_t*)&regcache;
p[addr] = val;
ads129x_write_regs(&regcache);
}
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;
}

1
app/src/app_service/ecg_service/ecg_service.h

@ -35,3 +35,4 @@ 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);

2
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();
/*******************************************************************************

11
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

2
ify_hrs_protocol

@ -1 +1 @@
Subproject commit 08b14b499e98175014068f19fdfaddded14718b3
Subproject commit a1fda58c30f6bb892c9f503280b3896c67e00dda
Loading…
Cancel
Save