You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

231 lines
6.6 KiB

1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
  1. #include "qrs_time_domain_zh.h"
  2. #include <stdbool.h>
  3. #include <stdint.h>
  4. #include <string.h>
  5. #define HEART_RATE_FILTER_SIZE 10
  6. typedef struct {
  7. uint16_t data[HEART_RATE_FILTER_SIZE];
  8. uint16_t data_process_buf[HEART_RATE_FILTER_SIZE];
  9. uint32_t cnt;
  10. uint32_t index;
  11. } HeartRateMedianFilter_t; // ��ֵ�˲���
  12. typedef struct {
  13. uint16_t data[HEART_RATE_FILTER_SIZE];
  14. uint32_t cnt;
  15. uint32_t index;
  16. uint32_t sum;
  17. } HeartRateMeanFilter_t; // ��ֵ�˲���
  18. HeartRateMedianFilter_t m_heart_rate_median_filter;
  19. HeartRateMeanFilter_t m_heart_rate_mean_filter;
  20. static void HeartRateMedianFilter_reset() {
  21. memset(m_heart_rate_median_filter.data, 0, sizeof(m_heart_rate_median_filter.data));
  22. m_heart_rate_median_filter.cnt = 0;
  23. m_heart_rate_median_filter.index = 0;
  24. }
  25. static uint16_t HeartRateMedianFilter_process(uint16_t data) {
  26. HeartRateMedianFilter_t* pfilter = &m_heart_rate_median_filter;
  27. pfilter->data[pfilter->index] = data;
  28. pfilter->index++;
  29. pfilter->cnt++;
  30. if (pfilter->index >=HEART_RATE_FILTER_SIZE) {
  31. pfilter->index = 0;
  32. }
  33. if (pfilter->cnt <HEART_RATE_FILTER_SIZE) {
  34. return data;
  35. }
  36. memcpy(pfilter->data_process_buf, pfilter->data, HEART_RATE_FILTER_SIZE * sizeof(uint16_t));
  37. for (uint8_t i = 0; i < HEART_RATE_FILTER_SIZE; i++) {
  38. for (uint8_t j = i + 1; j < HEART_RATE_FILTER_SIZE; j++) {
  39. if (pfilter->data_process_buf[i] > pfilter->data_process_buf[j]) {
  40. uint16_t temp = pfilter->data_process_buf[i];
  41. pfilter->data_process_buf[i] = pfilter->data_process_buf[j];
  42. pfilter->data_process_buf[j] = temp;
  43. }
  44. }
  45. }
  46. return pfilter->data_process_buf[2];
  47. }
  48. static void HeartRateMeanFilter_reset() {
  49. memset(m_heart_rate_mean_filter.data, 0, sizeof(m_heart_rate_mean_filter.data));
  50. m_heart_rate_mean_filter.cnt = 0;
  51. m_heart_rate_mean_filter.index = 0;
  52. m_heart_rate_mean_filter.sum = 0;
  53. }
  54. static uint16_t HeartRateMeanFilter_process(uint16_t data) {
  55. HeartRateMeanFilter_t* pfilter = &m_heart_rate_mean_filter;
  56. pfilter->sum -= pfilter->data[pfilter->index];
  57. pfilter->data[pfilter->index] = data;
  58. pfilter->sum += data;
  59. pfilter->index++;
  60. pfilter->cnt++;
  61. if (pfilter->index >= HEART_RATE_FILTER_SIZE) {
  62. pfilter->index = 0;
  63. }
  64. if (pfilter->cnt < HEART_RATE_FILTER_SIZE) {
  65. return data;
  66. }
  67. return pfilter->sum / HEART_RATE_FILTER_SIZE;
  68. }
  69. static uint16_t m_data[TABLE_SIZE];
  70. static uint32_t m_ndata = 0;
  71. static uint32_t m_dataindex = 0;
  72. static uint32_t m_data_cnt = 0;
  73. static uint16_t m_heartrate = 0;
  74. static uint32_t m_datasum = 0;
  75. static float m_avg = 0;
  76. static uint32_t m_max_val_in_m_data;
  77. static bool m_findpeak = false;
  78. static uint16_t pQRS_median_filter_cache[HEART_RATE_FILTER_SIZE];
  79. static uint16_t pQRS_median_filter_cache_index = 0;
  80. static uint16_t pQRS_median_filter_cache_cnt = 0;
  81. static uint32_t m_last_peak_pos = 0;
  82. static uint32_t m_peakcnt = 0;
  83. static uint16_t pQRS_median_filter(uint16_t indata) {
  84. // memcpy(pQRS_median_filter_cache + 1, pQRS_median_filter_cache, 4 * sizeof(uint16_t));
  85. pQRS_median_filter_cache[pQRS_median_filter_cache_index] = indata;
  86. pQRS_median_filter_cache_index++;
  87. pQRS_median_filter_cache_cnt++;
  88. if (pQRS_median_filter_cache_index >= HEART_RATE_FILTER_SIZE) {
  89. pQRS_median_filter_cache_index = 0;
  90. }
  91. if (pQRS_median_filter_cache_cnt < HEART_RATE_FILTER_SIZE) {
  92. return indata;
  93. }
  94. static uint16_t process_cache[HEART_RATE_FILTER_SIZE];
  95. memcpy(process_cache, pQRS_median_filter_cache, HEART_RATE_FILTER_SIZE * sizeof(uint16_t));
  96. for (uint8_t i = 0; i < HEART_RATE_FILTER_SIZE; i++) {
  97. for (uint8_t j = i + 1; j < HEART_RATE_FILTER_SIZE; j++) {
  98. if (process_cache[i] > process_cache[j]) {
  99. uint16_t temp = process_cache[i];
  100. process_cache[i] = process_cache[j];
  101. process_cache[j] = temp;
  102. }
  103. }
  104. }
  105. return process_cache[2];
  106. }
  107. static uint32_t pQRS_findMaxValue() {
  108. uint32_t max_val = 0;
  109. for (uint32_t i = 0; i < TABLE_SIZE; i++) {
  110. if (m_data[i] > max_val) {
  111. max_val = m_data[i];
  112. }
  113. }
  114. return max_val;
  115. }
  116. void QRS_resetBuf() { //
  117. m_ndata = 0;
  118. m_dataindex = 0;
  119. m_heartrate = 0;
  120. m_data_cnt = 0;
  121. memset(m_data, 0, sizeof(m_data));
  122. m_datasum = 0;
  123. m_findpeak = false;
  124. pQRS_median_filter_cache_index = 0;
  125. pQRS_median_filter_cache_cnt = 0;
  126. m_peakcnt = 0;
  127. HeartRateMedianFilter_reset();
  128. HeartRateMeanFilter_reset();
  129. }
  130. void QRS_processData(uint16_t _data) {
  131. uint16_t data = pQRS_median_filter(_data);
  132. /*******************************************************************************
  133. * BUF *
  134. *******************************************************************************/
  135. m_datasum -= m_data[m_dataindex];
  136. m_data[m_dataindex] = data;
  137. m_datasum += data;
  138. m_data_cnt++;
  139. if (m_dataindex < TABLE_SIZE) {
  140. m_dataindex++;
  141. } else {
  142. m_dataindex = 0;
  143. }
  144. m_ndata++;
  145. if (m_ndata > TABLE_SIZE) {
  146. m_ndata = TABLE_SIZE;
  147. }
  148. /*******************************************************************************
  149. * BUFƽֵֵ *
  150. *******************************************************************************/
  151. if (m_ndata == TABLE_SIZE) {
  152. m_avg = (float)m_datasum / m_ndata;
  153. m_max_val_in_m_data = pQRS_findMaxValue();
  154. }
  155. /*******************************************************************************
  156. * ѰQRSͲ *
  157. *******************************************************************************/
  158. if (!m_findpeak) {
  159. uint16_t thresholdValue = (m_max_val_in_m_data - m_avg) * 0.666 + m_avg;
  160. if (data > thresholdValue) {
  161. m_findpeak = true;
  162. m_peakcnt++;
  163. if (m_last_peak_pos != 0) {
  164. uint16_t diff_peak_pos = m_data_cnt - m_last_peak_pos;
  165. if (diff_peak_pos > 0) {
  166. //
  167. // m_heartrate = 60 * 500 / diff_peak_pos;
  168. uint16_t diff_peak_ms = diff_peak_pos * 2; // 500Hz
  169. uint16_t heart_rate = 60 * 1000 / diff_peak_ms;
  170. m_heartrate = HeartRateMeanFilter_process(HeartRateMedianFilter_process(heart_rate));
  171. }
  172. }
  173. m_last_peak_pos = m_data_cnt;
  174. }
  175. } else {
  176. if (data < m_avg) {
  177. m_findpeak = false;
  178. }
  179. }
  180. }
  181. uint16_t QRS_getHeartRate() {
  182. __disable_fiq();
  183. uint16_t heartrate = m_heartrate;
  184. __enable_fiq();
  185. if (heartrate > 200) return 0;
  186. if (heartrate < 55) return 0;
  187. return heartrate;
  188. }
  189. uint16_t QRS_getMaxValueLastVal() { return m_max_val_in_m_data; }
  190. uint16_t QRS_getAvgValueVal() { //
  191. return m_avg;
  192. }