diff --git a/.vscode/settings.json b/.vscode/settings.json
index 08583fc..f73691d 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -168,7 +168,11 @@
"thread": "cpp",
"cinttypes": "cpp",
"device_exception_manager.h": "c",
- "xiosbase": "c"
+ "xiosbase": "c",
+ "baseline_filtering.h": "c",
+ "heart_wave_sample_service_report_buf.h": "c",
+ "vcruntime.h": "c",
+ "smoothing_filter.h": "c"
},
"files.encoding": "gbk"
}
\ No newline at end of file
diff --git a/README.md b/README.md
index ff86fa2..e596afb 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,10 @@
# three_lead_ecg_v2
```
+V101:
+ 1. 修改每包上报数据长度,从4帧修改成25帧
+ 2. 添加去基线算法,上位机收到数据后需减去8388607,即可得到基线为0的数据
+
V28:
1.优化电池电量
diff --git a/app/app.uvoptx b/app/app.uvoptx
index 833c64c..1a77a3b 100644
--- a/app/app.uvoptx
+++ b/app/app.uvoptx
@@ -588,6 +588,66 @@
0
0
+
+ 1
+ 18
+ 1
+ 0
+ 0
+ 0
+ .\src\heart_wave_sample_service\heart_wave_sample_service_report_buf.c
+ heart_wave_sample_service_report_buf.c
+ 0
+ 0
+
+
+ 1
+ 19
+ 1
+ 0
+ 0
+ 0
+ .\src\algo\baseline_filtering.c
+ baseline_filtering.c
+ 0
+ 0
+
+
+ 1
+ 20
+ 1
+ 0
+ 0
+ 0
+ .\src\algo\fix_delay_fifo.c
+ fix_delay_fifo.c
+ 0
+ 0
+
+
+ 1
+ 21
+ 1
+ 0
+ 0
+ 0
+ .\src\algo\MedianFilter.c
+ MedianFilter.c
+ 0
+ 0
+
+
+ 1
+ 22
+ 1
+ 0
+ 0
+ 0
+ .\src\algo\smoothing_filter.c
+ smoothing_filter.c
+ 0
+ 0
+
@@ -598,7 +658,7 @@
0
2
- 18
+ 23
1
0
0
@@ -618,7 +678,7 @@
0
3
- 19
+ 24
1
0
0
@@ -630,7 +690,7 @@
3
- 20
+ 25
1
0
0
@@ -650,7 +710,7 @@
0
4
- 21
+ 26
1
0
0
@@ -670,7 +730,7 @@
0
5
- 22
+ 27
1
0
0
@@ -682,7 +742,7 @@
5
- 23
+ 28
1
0
0
@@ -694,7 +754,7 @@
5
- 24
+ 29
1
0
0
@@ -706,7 +766,7 @@
5
- 25
+ 30
1
0
0
@@ -718,7 +778,7 @@
5
- 26
+ 31
1
0
0
@@ -730,7 +790,7 @@
5
- 27
+ 32
1
0
0
@@ -742,7 +802,7 @@
5
- 28
+ 33
1
0
0
@@ -754,7 +814,7 @@
5
- 29
+ 34
1
0
0
@@ -774,7 +834,7 @@
0
6
- 30
+ 35
1
0
0
@@ -794,7 +854,7 @@
0
7
- 31
+ 36
1
0
0
@@ -806,7 +866,7 @@
7
- 32
+ 37
1
0
0
@@ -818,7 +878,7 @@
7
- 33
+ 38
1
0
0
@@ -830,7 +890,7 @@
7
- 34
+ 39
1
0
0
@@ -842,7 +902,7 @@
7
- 35
+ 40
1
0
0
@@ -854,7 +914,7 @@
7
- 36
+ 41
1
0
0
@@ -866,7 +926,7 @@
7
- 37
+ 42
1
0
0
@@ -878,7 +938,7 @@
7
- 38
+ 43
1
0
0
@@ -890,7 +950,7 @@
7
- 39
+ 44
1
0
0
@@ -902,7 +962,7 @@
7
- 40
+ 45
1
0
0
@@ -914,7 +974,7 @@
7
- 41
+ 46
1
0
0
@@ -926,7 +986,7 @@
7
- 42
+ 47
1
0
0
@@ -938,7 +998,7 @@
7
- 43
+ 48
1
0
0
@@ -950,7 +1010,7 @@
7
- 44
+ 49
1
0
0
@@ -962,7 +1022,7 @@
7
- 45
+ 50
1
0
0
@@ -974,7 +1034,7 @@
7
- 46
+ 51
1
0
0
@@ -986,7 +1046,7 @@
7
- 47
+ 52
1
0
0
@@ -998,7 +1058,7 @@
7
- 48
+ 53
1
0
0
@@ -1010,7 +1070,7 @@
7
- 49
+ 54
1
0
0
@@ -1022,7 +1082,7 @@
7
- 50
+ 55
1
0
0
@@ -1042,7 +1102,7 @@
0
8
- 51
+ 56
1
0
0
@@ -1054,7 +1114,7 @@
8
- 52
+ 57
1
0
0
@@ -1066,7 +1126,7 @@
8
- 53
+ 58
1
0
0
@@ -1078,7 +1138,7 @@
8
- 54
+ 59
1
0
0
@@ -1090,7 +1150,7 @@
8
- 55
+ 60
1
0
0
@@ -1102,7 +1162,7 @@
8
- 56
+ 61
1
0
0
@@ -1114,7 +1174,7 @@
8
- 57
+ 62
1
0
0
@@ -1126,7 +1186,7 @@
8
- 58
+ 63
1
0
0
@@ -1138,7 +1198,7 @@
8
- 59
+ 64
1
0
0
@@ -1150,7 +1210,7 @@
8
- 60
+ 65
1
0
0
@@ -1162,7 +1222,7 @@
8
- 61
+ 66
1
0
0
@@ -1174,7 +1234,7 @@
8
- 62
+ 67
1
0
0
@@ -1186,7 +1246,7 @@
8
- 63
+ 68
1
0
0
@@ -1198,7 +1258,7 @@
8
- 64
+ 69
1
0
0
@@ -1210,7 +1270,7 @@
8
- 65
+ 70
1
0
0
@@ -1222,7 +1282,7 @@
8
- 66
+ 71
1
0
0
@@ -1234,7 +1294,7 @@
8
- 67
+ 72
1
0
0
@@ -1246,7 +1306,7 @@
8
- 68
+ 73
1
0
0
@@ -1258,7 +1318,7 @@
8
- 69
+ 74
1
0
0
@@ -1270,7 +1330,7 @@
8
- 70
+ 75
1
0
0
@@ -1282,7 +1342,7 @@
8
- 71
+ 76
1
0
0
@@ -1294,7 +1354,7 @@
8
- 72
+ 77
1
0
0
@@ -1306,7 +1366,7 @@
8
- 73
+ 78
1
0
0
@@ -1318,7 +1378,7 @@
8
- 74
+ 79
1
0
0
@@ -1330,7 +1390,7 @@
8
- 75
+ 80
1
0
0
@@ -1342,7 +1402,7 @@
8
- 76
+ 81
1
0
0
@@ -1354,7 +1414,7 @@
8
- 77
+ 82
1
0
0
@@ -1374,7 +1434,7 @@
0
9
- 78
+ 83
1
0
0
@@ -1386,7 +1446,7 @@
9
- 79
+ 84
1
0
0
@@ -1398,7 +1458,7 @@
9
- 80
+ 85
1
0
0
@@ -1410,7 +1470,7 @@
9
- 81
+ 86
1
0
0
@@ -1422,7 +1482,7 @@
9
- 82
+ 87
1
0
0
@@ -1434,7 +1494,7 @@
9
- 83
+ 88
1
0
0
@@ -1454,7 +1514,7 @@
0
10
- 84
+ 89
1
0
0
@@ -1466,7 +1526,7 @@
10
- 85
+ 90
1
0
0
@@ -1478,7 +1538,7 @@
10
- 86
+ 91
1
0
0
@@ -1498,7 +1558,7 @@
0
11
- 87
+ 92
1
0
0
@@ -1510,7 +1570,7 @@
11
- 88
+ 93
1
0
0
@@ -1522,7 +1582,7 @@
11
- 89
+ 94
1
0
0
@@ -1542,7 +1602,7 @@
0
12
- 90
+ 95
1
0
0
@@ -1554,7 +1614,7 @@
12
- 91
+ 96
1
0
0
@@ -1566,7 +1626,7 @@
12
- 92
+ 97
1
0
0
@@ -1586,7 +1646,7 @@
0
13
- 93
+ 98
1
0
0
@@ -1598,7 +1658,7 @@
13
- 94
+ 99
1
0
0
@@ -1618,7 +1678,7 @@
0
14
- 95
+ 100
1
0
0
@@ -1630,7 +1690,7 @@
14
- 96
+ 101
1
0
0
@@ -1642,7 +1702,7 @@
14
- 97
+ 102
1
0
0
@@ -1654,7 +1714,7 @@
14
- 98
+ 103
1
0
0
diff --git a/app/app.uvprojx b/app/app.uvprojx
index ac6f118..2f82e54 100644
--- a/app/app.uvprojx
+++ b/app/app.uvprojx
@@ -468,6 +468,31 @@
1
.\src\board\device_exception_manager.c
+
+ heart_wave_sample_service_report_buf.c
+ 1
+ .\src\heart_wave_sample_service\heart_wave_sample_service_report_buf.c
+
+
+ baseline_filtering.c
+ 1
+ .\src\algo\baseline_filtering.c
+
+
+ fix_delay_fifo.c
+ 1
+ .\src\algo\fix_delay_fifo.c
+
+
+ MedianFilter.c
+ 1
+ .\src\algo\MedianFilter.c
+
+
+ smoothing_filter.c
+ 1
+ .\src\algo\smoothing_filter.c
+
@@ -4317,6 +4342,31 @@
1
.\src\board\device_exception_manager.c
+
+ heart_wave_sample_service_report_buf.c
+ 1
+ .\src\heart_wave_sample_service\heart_wave_sample_service_report_buf.c
+
+
+ baseline_filtering.c
+ 1
+ .\src\algo\baseline_filtering.c
+
+
+ fix_delay_fifo.c
+ 1
+ .\src\algo\fix_delay_fifo.c
+
+
+ MedianFilter.c
+ 1
+ .\src\algo\MedianFilter.c
+
+
+ smoothing_filter.c
+ 1
+ .\src\algo\smoothing_filter.c
+
diff --git a/app/src/algo/MedianFilter.c b/app/src/algo/MedianFilter.c
new file mode 100644
index 0000000..bd78960
--- /dev/null
+++ b/app/src/algo/MedianFilter.c
@@ -0,0 +1,78 @@
+/*
+ * MedianFilter.c
+ *
+ * Created on: May 19, 2018
+ * Author: alexandru.bogdan
+ */
+
+#include "MedianFilter.h"
+
+#include
+
+int32_t MEDIANFILTER_Init(sMedianFilter_t *medianFilter) {
+ if (medianFilter && medianFilter->medianBuffer && (medianFilter->numNodes % 2) && (medianFilter->numNodes > 1)) {
+ // initialize buffer nodes
+ for (unsigned int i = 0; i < medianFilter->numNodes; i++) {
+ medianFilter->medianBuffer[i].value = 0;
+ medianFilter->medianBuffer[i].nextAge = &medianFilter->medianBuffer[(i + 1) % medianFilter->numNodes];
+ medianFilter->medianBuffer[i].nextValue = &medianFilter->medianBuffer[(i + 1) % medianFilter->numNodes];
+ medianFilter->medianBuffer[(i + 1) % medianFilter->numNodes].prevValue = &medianFilter->medianBuffer[i];
+ }
+ // initialize heads
+ medianFilter->ageHead = medianFilter->medianBuffer;
+ medianFilter->valueHead = medianFilter->medianBuffer;
+ medianFilter->medianHead = &medianFilter->medianBuffer[medianFilter->numNodes / 2];
+
+ return 0;
+ }
+
+ return -1;
+}
+
+int32_t MEDIANFILTER_Insert(sMedianFilter_t *medianFilter, int32_t sample) {
+ unsigned int i;
+ sMedianNode_t *newNode, *it;
+
+ if (medianFilter->ageHead == medianFilter->valueHead) { // if oldest node is also the smallest node, increment value head
+ medianFilter->valueHead = medianFilter->valueHead->nextValue;
+ }
+
+ if ((medianFilter->ageHead == medianFilter->medianHead) || (medianFilter->ageHead->value > medianFilter->medianHead->value)) { // prepare for median correction
+ medianFilter->medianHead = medianFilter->medianHead->prevValue;
+ }
+
+ // replace age head with new sample
+ newNode = medianFilter->ageHead;
+ newNode->value = sample;
+
+ // remove age head from list
+ medianFilter->ageHead->nextValue->prevValue = medianFilter->ageHead->prevValue;
+ medianFilter->ageHead->prevValue->nextValue = medianFilter->ageHead->nextValue;
+ // increment age head
+ medianFilter->ageHead = medianFilter->ageHead->nextAge;
+
+ // find new node position
+ it = medianFilter->valueHead; // set iterator as value head
+ for (i = 0; i < medianFilter->numNodes - 1; i++) {
+ if (sample < it->value) {
+ if (i == 0) { // replace value head if new node is the smallest
+ medianFilter->valueHead = newNode;
+ }
+ break;
+ }
+ it = it->nextValue;
+ }
+
+ // insert new node in list
+ it->prevValue->nextValue = newNode;
+ newNode->prevValue = it->prevValue;
+ it->prevValue = newNode;
+ newNode->nextValue = it;
+
+ // adjust median node
+ if (i >= (medianFilter->numNodes / 2)) {
+ medianFilter->medianHead = medianFilter->medianHead->nextValue;
+ }
+
+ return medianFilter->medianHead->value;
+}
\ No newline at end of file
diff --git a/app/src/algo/MedianFilter.h b/app/src/algo/MedianFilter.h
new file mode 100644
index 0000000..92bc379
--- /dev/null
+++ b/app/src/algo/MedianFilter.h
@@ -0,0 +1,39 @@
+/*
+ * MedianFilter.h
+ *
+ * Created on: May 19, 2018
+ * Author: alexandru.bogdan
+ */
+
+#ifndef MEDIANFILTER_H_
+#define MEDIANFILTER_H_
+#include
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct sMedianNode
+{
+ int32_t value; //sample value
+ struct sMedianNode *nextAge; //pointer to next oldest value
+ struct sMedianNode *nextValue; //pointer to next smallest value
+ struct sMedianNode *prevValue; //pointer to previous smallest value
+}sMedianNode_t;
+
+typedef struct
+{
+ unsigned int numNodes; //median node buffer length
+ sMedianNode_t *medianBuffer; //median node buffer
+ sMedianNode_t *ageHead; //pointer to oldest value
+ sMedianNode_t *valueHead; //pointer to smallest value
+ sMedianNode_t *medianHead; //pointer to median value
+}sMedianFilter_t;
+
+int32_t MEDIANFILTER_Init(sMedianFilter_t *medianFilter);
+int32_t MEDIANFILTER_Insert(sMedianFilter_t *medianFilter, int32_t sample);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
\ No newline at end of file
diff --git a/app/src/algo/baseline_filtering.c b/app/src/algo/baseline_filtering.c
new file mode 100644
index 0000000..8b83fd3
--- /dev/null
+++ b/app/src/algo/baseline_filtering.c
@@ -0,0 +1,118 @@
+#include "baseline_filtering.h"
+
+#include
+#include
+
+#include "MedianFilter.h"
+#include "fix_delay_fifo.h"
+#include "smoothing_filter.h"
+
+#define REPORT_MEDIAN_WINDOWS_SIZE 101 // 必须是奇数
+
+#define _ARRARY_SIZE(arr) (sizeof(arr) / sizeof(arr[0]))
+
+static sMedianFilter_t medianFilter0;
+static sMedianNode_t medianBufferBuffer0[REPORT_MEDIAN_WINDOWS_SIZE];
+static int32_t m_fifo_buffer_0[REPORT_MEDIAN_WINDOWS_SIZE / 2];
+static fix_delay_fifo_t m_fifo0;
+
+static sMedianFilter_t medianFilter1;
+static sMedianNode_t medianBufferBuffer1[REPORT_MEDIAN_WINDOWS_SIZE];
+static int32_t m_fifo_buffer_1[REPORT_MEDIAN_WINDOWS_SIZE / 2];
+static fix_delay_fifo_t m_fifo1;
+
+static sMedianFilter_t medianFilter2;
+static sMedianNode_t medianBufferBuffer2[REPORT_MEDIAN_WINDOWS_SIZE];
+static int32_t m_fifo_buffer_2[REPORT_MEDIAN_WINDOWS_SIZE / 2];
+static fix_delay_fifo_t m_fifo2;
+
+static SmoothingFilter_t smoothingFilter0;
+static SmoothingFilter_t smoothingFilter1;
+static SmoothingFilter_t smoothingFilter2;
+
+static int32_t m_frame_cnt;
+static int32_t result0;
+static int32_t result1;
+static int32_t result2;
+
+void baseline_filter_init() { baseline_filter_reset(); }
+
+void baseline_filter_reset() {
+ {
+ memset(&medianFilter0, 0, sizeof(medianFilter0));
+ memset(medianBufferBuffer0, 0, sizeof(medianBufferBuffer0));
+ medianFilter0.numNodes = REPORT_MEDIAN_WINDOWS_SIZE;
+ medianFilter0.medianBuffer = medianBufferBuffer0;
+ MEDIANFILTER_Init(&medianFilter0);
+
+ fix_delay_fifo_init(&m_fifo0, m_fifo_buffer_0, REPORT_MEDIAN_WINDOWS_SIZE / 2);
+ }
+
+ {
+ memset(&medianFilter1, 0, sizeof(medianFilter1));
+ memset(medianBufferBuffer1, 0, sizeof(medianBufferBuffer1));
+ medianFilter1.numNodes = REPORT_MEDIAN_WINDOWS_SIZE;
+ medianFilter1.medianBuffer = medianBufferBuffer1;
+ MEDIANFILTER_Init(&medianFilter1);
+
+ fix_delay_fifo_init(&m_fifo1, m_fifo_buffer_1, REPORT_MEDIAN_WINDOWS_SIZE / 2);
+ }
+
+ {
+ memset(&medianFilter2, 0, sizeof(medianFilter2));
+ memset(medianBufferBuffer2, 0, sizeof(medianBufferBuffer2));
+ medianFilter2.numNodes = REPORT_MEDIAN_WINDOWS_SIZE;
+ medianFilter2.medianBuffer = medianBufferBuffer2;
+ MEDIANFILTER_Init(&medianFilter2);
+
+ fix_delay_fifo_init(&m_fifo2, m_fifo_buffer_2, REPORT_MEDIAN_WINDOWS_SIZE / 2);
+ }
+
+ // smoothingFilter0
+ // smoothingFilter1
+ // smoothingFilter2
+
+ SmoothingFilter_Init(&smoothingFilter0, 5, true);
+ SmoothingFilter_Init(&smoothingFilter1, 5, true);
+ SmoothingFilter_Init(&smoothingFilter2, 5, true);
+
+ m_frame_cnt = 0;
+}
+
+void baseline_filter_push(int32_t val0, int32_t val1, int32_t val2) {
+ int32_t medianValue0 = MEDIANFILTER_Insert(&medianFilter0, val0);
+ int32_t delay_data0 = fix_delay_fifo_update(&m_fifo0, val0);
+
+ float medianValue1 = MEDIANFILTER_Insert(&medianFilter1, val1);
+ float delay_data1 = fix_delay_fifo_update(&m_fifo1, val1);
+
+ float medianValue2 = MEDIANFILTER_Insert(&medianFilter2, val2);
+ float delay_data2 = fix_delay_fifo_update(&m_fifo2, val2);
+
+ m_frame_cnt++;
+
+ if (m_frame_cnt < REPORT_MEDIAN_WINDOWS_SIZE) {
+ result0 = 0;
+ result1 = 0;
+ result2 = 0;
+ return;
+ }
+ result0 = delay_data0 - medianValue0;
+ result1 = delay_data1 - medianValue1;
+ result2 = delay_data2 - medianValue2;
+
+ result0 = SmoothingFilter_Update(&smoothingFilter0, result0);
+ result1 = SmoothingFilter_Update(&smoothingFilter1, result1);
+ result2 = SmoothingFilter_Update(&smoothingFilter2, result2);
+}
+
+int32_t baseline_filter_get_result(int32_t index) {
+ if (index == 0) {
+ return result0;
+ } else if (index == 1) {
+ return result1;
+ } else if (index == 2) {
+ return result2;
+ }
+ return 0;
+}
diff --git a/app/src/algo/baseline_filtering.h b/app/src/algo/baseline_filtering.h
new file mode 100644
index 0000000..31e77dd
--- /dev/null
+++ b/app/src/algo/baseline_filtering.h
@@ -0,0 +1,7 @@
+#pragma once
+#include
+
+void baseline_filter_init();
+void baseline_filter_reset();
+void baseline_filter_push(int32_t val0, int32_t val1, int32_t val2);
+int32_t baseline_filter_get_result(int32_t index);
diff --git a/app/src/algo/fix_delay_fifo.c b/app/src/algo/fix_delay_fifo.c
new file mode 100644
index 0000000..345ebc4
--- /dev/null
+++ b/app/src/algo/fix_delay_fifo.c
@@ -0,0 +1,23 @@
+#include "fix_delay_fifo.h"
+
+void fix_delay_fifo_init(fix_delay_fifo_t *buffer, int32_t *fifo, int fifosize){
+
+ buffer->fifo = fifo;
+ buffer->fifosize = fifosize;
+ buffer->head = 0;
+ buffer->tail = 0;
+ memset(buffer->fifo, 0, fifosize * sizeof(int32_t));
+
+}
+int32_t fix_delay_fifo_update(fix_delay_fifo_t *buffer, int32_t vin){
+
+ buffer->fifo[buffer->tail] = vin;
+ buffer->tail = (buffer->tail + 1) % buffer->fifosize;
+ int32_t fifoheadval = 0;
+ if (buffer->tail == buffer->head) {
+ fifoheadval = buffer->fifo[buffer->head];
+ buffer->head = (buffer->head + 1) % buffer->fifosize;
+ }
+ return fifoheadval;
+
+}
\ No newline at end of file
diff --git a/app/src/algo/fix_delay_fifo.h b/app/src/algo/fix_delay_fifo.h
new file mode 100644
index 0000000..12c4ea3
--- /dev/null
+++ b/app/src/algo/fix_delay_fifo.h
@@ -0,0 +1,17 @@
+#ifndef FILTERS_H
+#define FILTERS_H
+#include
+#include
+typedef struct {
+ int32_t *fifo;
+ int fifosize;
+
+ int head;
+ int tail;
+
+} fix_delay_fifo_t;
+
+void fix_delay_fifo_init(fix_delay_fifo_t *buffer, int32_t *fifo, int fifosize);
+int32_t fix_delay_fifo_update(fix_delay_fifo_t *buffer, int32_t vin);
+
+#endif
\ No newline at end of file
diff --git a/app/src/algo/smoothing_filter.c b/app/src/algo/smoothing_filter.c
new file mode 100644
index 0000000..6273b68
--- /dev/null
+++ b/app/src/algo/smoothing_filter.c
@@ -0,0 +1,30 @@
+#include "smoothing_filter.h"
+void SmoothingFilter_Init(SmoothingFilter_t *filter, int windows_size, bool enable) {
+ if (windows_size > 1000) {
+ windows_size = 1000;
+ }
+ filter->windows_size = windows_size;
+ filter->datanum = 0;
+ filter->sum = 0;
+ filter->datanum = 0;
+ for (int i = 0; i < windows_size; i++) {
+ filter->datawindows[i] = 0;
+ }
+ filter->data_offset = 0;
+ filter->enable = enable;
+}
+int32_t SmoothingFilter_Update(SmoothingFilter_t *filter, int32_t vin) {
+ if (!filter->enable) return vin;
+
+ filter->sum -= filter->datawindows[filter->data_offset];
+ filter->datawindows[filter->data_offset] = vin;
+ filter->sum += filter->datawindows[filter->data_offset];
+ filter->data_offset = (filter->data_offset + 1) % filter->windows_size;
+
+ filter->datanum++;
+ if (filter->datanum > filter->windows_size) {
+ filter->datanum = filter->windows_size;
+ }
+
+ return filter->sum / filter->datanum;
+}
\ No newline at end of file
diff --git a/app/src/algo/smoothing_filter.h b/app/src/algo/smoothing_filter.h
new file mode 100644
index 0000000..513cddf
--- /dev/null
+++ b/app/src/algo/smoothing_filter.h
@@ -0,0 +1,14 @@
+#pragma once
+#include
+#include
+typedef struct {
+ int32_t datawindows[30];
+ int windows_size;
+ int datanum;
+ int data_offset;
+ int32_t sum;
+ bool enable;
+} SmoothingFilter_t;
+
+void SmoothingFilter_Init(SmoothingFilter_t *filter, int windows_size, bool enable);
+int32_t SmoothingFilter_Update(SmoothingFilter_t *filter, int32_t vin);
\ No newline at end of file
diff --git a/app/src/app_event.h b/app/src/app_event.h
index 3db6639..86719ca 100644
--- a/app/src/app_event.h
+++ b/app/src/app_event.h
@@ -1,8 +1,8 @@
#pragma once
#include
#include
-#include "board/board.h"
+#include "board/board.h"
typedef enum {
kevent_sensor_drop = 0, // 导联连接事件
@@ -33,8 +33,10 @@ typedef struct {
app_event_type_t eventType;
union {
struct {
- uint32_t frameIndex;
- one_frame_data_t data[LITTLE_DATA_BLOCK_FRAME_NUM];
+ uint32_t frameIndex;
+ // one_frame_data_t data[LITTLE_DATA_BLOCK_FRAME_NUM];
+ one_frame_data_t* data;
+ int len;
} little_data_block;
struct {
diff --git a/app/src/basic/version.h b/app/src/basic/version.h
index e156853..296c04f 100644
--- a/app/src/basic/version.h
+++ b/app/src/basic/version.h
@@ -2,7 +2,7 @@
#define CATEGORY "M1002" // 三导联
#define MANUFACTURER_NAME "iflytop"
-#define FIRMWARE_VERSION (28)
+#define FIRMWARE_VERSION (102)
#define BLESTACK_VERSION 1
#define BOOTLOADER_VERSION 1
#define HARDWARE_VERSION (1)
diff --git a/app/src/board/board.h b/app/src/board/board.h
index 32735a2..2d69074 100644
--- a/app/src/board/board.h
+++ b/app/src/board/board.h
@@ -63,7 +63,7 @@
#define APP_MAX_STORAGE_TIME_S (uint32_t)(72 * 60 * 60)
//
#define SAMPLE_RATE 400
-#define LITTLE_DATA_BLOCK_FRAME_NUM 4 // 每两帧回调一次,对应100HZ
+#define LITTLE_DATA_BLOCK_FRAME_NUM 25 // 每两帧回调一次,对应100HZ
#define SAMPLE_PRECISION 24
#define APP_MAX_EVEN_SIZE (MAX(APP_TIMER_SCHED_EVENT_DATA_SIZE, sizeof(app_event_t)))
diff --git a/app/src/heart_wave_sample_service.c b/app/src/heart_wave_sample_service.c
index 375cc46..bc0cd38 100644
--- a/app/src/heart_wave_sample_service.c
+++ b/app/src/heart_wave_sample_service.c
@@ -2,12 +2,14 @@
//
#include "znordic.h"
//
+#include "algo/baseline_filtering.h"
#include "app_button.h"
#include "app_event.h"
#include "app_event_distribute.h"
#include "basic/ads1293/ads1293.h"
#include "basic/filters.h"
#include "board/device_exception_manager.h"
+#include "heart_wave_sample_service/heart_wave_sample_service_report_buf.h"
#include "nrf_drv_gpiote.h"
#include "nrfx_timer.h"
#include "sample_data_manager_service.h"
@@ -84,10 +86,6 @@ static uint8_t m_frame_buffer_b[HEART_WAVE_SAMPLE_SERVICE_CACHE_SIZE];
static uint8_t *m_frame_buffer;
static int32_t m_frame_buffer_index;
-// 小包采样数据缓存,用于触发实时上报逻辑使用
-static one_frame_data_t m_sensor_little_frame_cache[LITTLE_DATA_BLOCK_FRAME_NUM];
-static uint32_t m_little_frame_index;
-
static uint8_t m_lodstate0;
static uint8_t m_lodstate1;
@@ -146,24 +144,6 @@ static inline void pFrameBufferAB_push_one_byte(uint8_t byte) {
* LittleDataBuffer操作 *
*******************************************************************************/
-static inline void pLittleBlockCache_push_one_frame(uint32_t *data) {
- if (m_little_frame_index >= LITTLE_DATA_BLOCK_FRAME_NUM) {
- return;
- }
- m_sensor_little_frame_cache[m_little_frame_index].data0 = data[0];
- m_sensor_little_frame_cache[m_little_frame_index].data1 = data[1];
- m_sensor_little_frame_cache[m_little_frame_index].data2 = data[2];
- m_little_frame_index++;
-}
-
-static inline bool pLittleBlockCache_is_full(void) {
- if (m_little_frame_index >= LITTLE_DATA_BLOCK_FRAME_NUM) {
- return true;
- }
- return false;
-}
-static inline void pLittleBlockCache_reset(void) { m_little_frame_index = 0; }
-
/*******************************************************************************
* 事件操作辅助方法 *
*******************************************************************************/
@@ -176,24 +156,6 @@ static inline void pEventHelper_trigger_capture_data_block_event(uint8_t *data,
AppEvent_pushEvent(&event);
}
-static inline void pEventHelper_trigger_little_block_data_event() {
- static app_event_t event;
- event.eventType = kevent_capture_little_data_block_event;
- // memcpy(event.val.little_data_block.data, m_sensor_little_frame_cache, LITTLE_DATA_BLOCK_FRAME_NUM * sizeof(one_frame_data_t));
-
- for (uint32_t i = 0; i < LITTLE_DATA_BLOCK_FRAME_NUM; i++) {
- event.val.little_data_block.data[i].data0 = m_sensor_little_frame_cache[i].data0;
- event.val.little_data_block.data[i].data1 = m_sensor_little_frame_cache[i].data1;
- event.val.little_data_block.data[i].data2 = m_sensor_little_frame_cache[i].data2;
- // event.val.little_data_block.data[0].data0 = 1111111111;
- // event.val.little_data_block.data[0].data1 = 2222222222;
- // event.val.little_data_block.data[0].data2 = 3333333333;
- }
-
- event.val.little_data_block.frameIndex = m_frame_index - LITTLE_DATA_BLOCK_FRAME_NUM;
- AppEvent_pushEvent(&event);
-}
-
static inline void pEventHelper_trigger_sensor_drop_event(uint8_t drop0, uint8_t drop1) {
static app_event_t event;
event.eventType = kevent_sensor_drop;
@@ -472,18 +434,25 @@ static void ads1293_sample_one_frame() {
// medianFilter
uint32_t val[3];
- val[0] = MedianFilter_Update(&medianFilter[0], sample[SENSOR0_ID]);
- val[1] = MedianFilter_Update(&medianFilter[1], sample[SENSOR1_ID]);
- val[2] = MedianFilter_Update(&medianFilter[2], sample[SENSOR2_ID]);
-
- // int32_t val0 = LPFilter_Update(&lowpassfilter[0], sample[SENSOR0_ID]);
- // int32_t val1 = LPFilter_Update(&lowpassfilter[1], sample[SENSOR1_ID]);
- // int32_t val2 = LPFilter_Update(&lowpassfilter[2], sample[SENSOR2_ID]);
+#if 1
+ baseline_filter_push((int32_t)sample[SENSOR0_ID], (int32_t)sample[SENSOR1_ID], (int32_t)sample[SENSOR2_ID]);
+ int32_t val0 = (int32_t)baseline_filter_get_result(0) + 0x7FFFFF;
+ int32_t val1 = (int32_t)baseline_filter_get_result(1) + 0x7FFFFF;
+ int32_t val2 = (int32_t)baseline_filter_get_result(2) + 0x7FFFFF;
+
+ if (val0 < 0) val0 = 0;
+ if (val1 < 0) val1 = 0;
+ if (val2 < 0) val2 = 0;
+
+ val[0] = val0;
+ val[1] = val1;
+ val[2] = val2;
+#else
val[0] = sample[SENSOR0_ID];
val[1] = sample[SENSOR1_ID];
val[2] = sample[SENSOR2_ID];
-
+#endif
if (val[0] > 0xffffff) val[0] = 0xffffff;
if (val[1] > 0xffffff) val[1] = 0xffffff;
if (val[2] > 0xffffff) val[2] = 0xffffff;
@@ -516,10 +485,9 @@ static void ads1293_sample_one_frame() {
/**
* @brief 缓存数据,并触发小数据块事件
*/
- pLittleBlockCache_push_one_frame(&val[0]);
- if (pLittleBlockCache_is_full()) {
- pEventHelper_trigger_little_block_data_event();
- pLittleBlockCache_reset();
+ HWSSReportBuf_push_one_frame(&val[0]);
+ if (HWSSReportBuf_is_full()) {
+ HWSSReportBuf_trigger_little_block_data_event();
}
}
@@ -529,7 +497,7 @@ static void ads1293_uninit() {
nrf_drv_spi_uninit(&spi);
}
-void hwss_init(void) {}
+void hwss_init(void) { baseline_filter_init(); }
void hwss_load(void) {
ZERROR_CHECK(nrfx_gpiote_init());
@@ -571,7 +539,7 @@ void hwss_start_capture(void) {
MedianFilter_Init(&medianFilter[1]);
MedianFilter_Init(&medianFilter[2]);
- pLittleBlockCache_reset();
+ HWSSReportBuf_reset();
// ads1293_start_conversion(&m_ads1293_0);
// ads1293_start_conversion(&m_ads1293_1);
@@ -608,6 +576,8 @@ void hwss_start_capture(void) {
nrf_gpio_pin_set(ADS1293_SPI_CS1_PIN);
}
+ baseline_filter_reset();
+
nrfx_gpiote_in_event_enable(ADS1293_READY_PIN, true);
}
@@ -617,7 +587,6 @@ void hwss_stop_capture(void) {
m_work_flag = false;
m_frame_index = 0;
m_frame_filter_index = 0;
- pLittleBlockCache_reset();
// ads1293_stop_conversion(&m_ads1293_0);
// ads1293_stop_conversion(&m_ads1293_1);
diff --git a/app/src/heart_wave_sample_service/heart_wave_sample_service_report_buf.c b/app/src/heart_wave_sample_service/heart_wave_sample_service_report_buf.c
new file mode 100644
index 0000000..d7d7f7f
--- /dev/null
+++ b/app/src/heart_wave_sample_service/heart_wave_sample_service_report_buf.c
@@ -0,0 +1,54 @@
+
+#include
+
+#include "app_event.h"
+#include "app_event_distribute.h"
+
+// 小包采样数据缓存,用于触发实时上报逻辑使用
+static one_frame_data_t m_sensor_little_frame_cache_A[LITTLE_DATA_BLOCK_FRAME_NUM];
+static one_frame_data_t m_sensor_little_frame_cache_B[LITTLE_DATA_BLOCK_FRAME_NUM];
+static one_frame_data_t *curbuf = m_sensor_little_frame_cache_A;
+static uint32_t m_little_frame_index;
+static uint32_t m_frame_index;
+
+static void HWSSReportBuf_ExchangeAB() {
+ if (curbuf == m_sensor_little_frame_cache_A) {
+ curbuf = m_sensor_little_frame_cache_B;
+ } else {
+ curbuf = m_sensor_little_frame_cache_A;
+ }
+}
+
+void HWSSReportBuf_push_one_frame(uint32_t *data) {
+ if (m_little_frame_index >= LITTLE_DATA_BLOCK_FRAME_NUM) {
+ return;
+ }
+ curbuf[m_little_frame_index].data0 = data[0];
+ curbuf[m_little_frame_index].data1 = data[1];
+ curbuf[m_little_frame_index].data2 = data[2];
+ m_little_frame_index++;
+ m_frame_index++;
+}
+
+bool HWSSReportBuf_is_full(void) {
+ if (m_little_frame_index >= LITTLE_DATA_BLOCK_FRAME_NUM) {
+ return true;
+ }
+ return false;
+}
+void HWSSReportBuf_reset(void) {
+ m_little_frame_index = 0;
+ m_frame_index = 0;
+}
+
+void HWSSReportBuf_trigger_little_block_data_event() {
+ static app_event_t event;
+ event.eventType = kevent_capture_little_data_block_event;
+
+ event.val.little_data_block.data = curbuf;
+ event.val.little_data_block.len = LITTLE_DATA_BLOCK_FRAME_NUM;
+ event.val.little_data_block.frameIndex = m_frame_index - LITTLE_DATA_BLOCK_FRAME_NUM;
+ m_little_frame_index = 0;
+ AppEvent_pushEvent(&event);
+ HWSSReportBuf_ExchangeAB();
+}
\ No newline at end of file
diff --git a/app/src/heart_wave_sample_service/heart_wave_sample_service_report_buf.h b/app/src/heart_wave_sample_service/heart_wave_sample_service_report_buf.h
new file mode 100644
index 0000000..fbec34e
--- /dev/null
+++ b/app/src/heart_wave_sample_service/heart_wave_sample_service_report_buf.h
@@ -0,0 +1,9 @@
+#pragma once
+#include
+
+void HWSSReportBuf_push_one_frame(uint32_t *data);
+
+bool HWSSReportBuf_is_full(void);
+void HWSSReportBuf_reset(void);
+
+void HWSSReportBuf_trigger_little_block_data_event();
\ No newline at end of file