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.

313 lines
8.7 KiB

  1. #include "heart_wave_sample_service.h"
  2. #include "app_event.h"
  3. #include "app_event_distribute.h"
  4. #include "basic/FIR.h"
  5. #include "basic/HC_Chen_detect.h"
  6. #include "basic/So_Chen_detect.h"
  7. #include "basic/adaptive_algorithm.h"
  8. #include "basic/Pan_Tompkins_detect.h"
  9. #include "board/board_ecg_sensor.h"
  10. #include "nrfx_timer.h"
  11. static uint16_t m_capture_buffer_a[128];
  12. static uint16_t m_capture_buffer_b[128];
  13. static uint16_t* m_capture_buffer;
  14. static uint16_t m_capture_buffer_index = 0;
  15. volatile static float m_sensor_display_data = 0; // 0->100
  16. static uint32_t m_start_capture_tp;
  17. static uint32_t m_frame_index = 0;
  18. static one_frame_data_t m_sensor_little_frame_cache[LITTLE_DATA_BLOCK_FRAME_NUM];
  19. static uint32_t m_little_frame_index;
  20. static bool m_prestart_flag;
  21. static nrfx_timer_t m_timer = NRFX_TIMER_INSTANCE(HEART_WAVE_SAMPLE_TMR_INSTANCE);
  22. typedef struct {
  23. int heartSignalCnt;
  24. int heart_rate;
  25. uint32_t last_qrs_point;
  26. uint32_t time_cnt;
  27. uint32_t origin_time_cnt;
  28. uint32_t index;
  29. float index_f;
  30. } QRS_t;
  31. QRS_t m_qrs;
  32. void QRS_reset() {
  33. m_qrs.heartSignalCnt = 0;
  34. m_qrs.heart_rate = 0;
  35. m_qrs.time_cnt = 0;
  36. m_qrs.index = 0;
  37. m_qrs.index_f = 0;
  38. FIR_reset_buffer();
  39. }
  40. void QRS_process(float value) {
  41. bool isPeak = false;
  42. #if 1
  43. float result = value;
  44. SignalPoint sp;
  45. sp.value = result;
  46. sp.index = m_qrs.time_cnt;
  47. SignalPoint peak = So_Chen_detect(sp, SAMPLING_RATE * 0.25f, 4, 16);
  48. if (peak.index != -1) {
  49. isPeak = true;
  50. }
  51. #endif
  52. #if 0
  53. isPeak = HC_Chen_detect(value);
  54. #endif
  55. #if 0
  56. static const float CV_LIMIT = 50.0f;
  57. static const float THRESHOLD_FACTOR = 3.0f;
  58. double mean = CalculateMean(value);
  59. double rms = CalculateRootMeanSquare(value);
  60. double cv = CalculateCoefficientOfVariation(value);
  61. double threshold;
  62. if (cv > CV_LIMIT) {
  63. threshold = rms;
  64. } else {
  65. threshold = rms * (cv / 100.0f) * THRESHOLD_FACTOR;
  66. }
  67. bool is_peak;
  68. SignalPoint result;
  69. result = PeakDetect(value, m_qrs.time_cnt, threshold, &is_peak);
  70. if (result.index != -1) {
  71. if (is_peak) {
  72. isPeak = true;
  73. }
  74. }
  75. #endif
  76. #if 0
  77. double result = value;
  78. double bandpass;
  79. double integral;
  80. double square;
  81. bandpass = result;
  82. result = Derivative(result);
  83. result = Squar(result);
  84. square = result;
  85. result = MovingWindowIntegral(result);
  86. integral = result;
  87. SignalPoint peak = ThresholdCalculate(m_qrs.time_cnt,value,bandpass,square,integral);
  88. if(peak.index != -1){
  89. isPeak = true;
  90. }
  91. #endif
  92. // if (isPeak) {
  93. // uint32_t time_diff = m_qrs.time_cnt - m_qrs.last_qrs_point;
  94. // m_qrs.last_qrs_point = m_qrs.time_cnt;
  95. // m_qrs.heartSignalCnt++;
  96. // // m_qrs.heart_rate = m_qrs.heartSignalCnt;
  97. // if (m_qrs.last_qrs_point != 0) {
  98. // m_qrs.heart_rate = 60 * (1 / (time_diff * 1.0 / SAMPLING_RATE));
  99. // }
  100. // }
  101. m_qrs.time_cnt++;
  102. }
  103. static const void compute_heart_rate(float sample_data) {
  104. ZASSERT(SAMPLE_RATE == 500);
  105. m_qrs.index_f = m_frame_index / 500.0 * 360;
  106. if ((m_qrs.index_f - m_qrs.index) > 1) {
  107. m_qrs.index = m_qrs.index_f;
  108. float val = sample_data;
  109. QRS_process(FIR_filter(val));
  110. }
  111. }
  112. static void swap_buffer() {
  113. if (m_capture_buffer == NULL) {
  114. m_capture_buffer = m_capture_buffer_a;
  115. m_capture_buffer_index = 0;
  116. return;
  117. }
  118. if (m_capture_buffer == m_capture_buffer_a) {
  119. m_capture_buffer = m_capture_buffer_b;
  120. } else {
  121. m_capture_buffer = m_capture_buffer_a;
  122. }
  123. m_capture_buffer_index = 0;
  124. return;
  125. }
  126. static float amp_val(uint16_t val, uint16_t valcener, float amp) {
  127. float valf = (float)val - valcener;
  128. valf = valf * amp;
  129. valf += valcener;
  130. if (valf >= 100) {
  131. valf = 100;
  132. }
  133. if (valf <= 0) {
  134. valf = 0;
  135. }
  136. return valf;
  137. }
  138. typedef struct {
  139. float value;
  140. float efectiveFactor;
  141. } filter_t;
  142. filter_t m_filter = {0, 0.8};
  143. static float Filter(filter_t* filter, float newInput) {
  144. float newv = ((float)filter->value * (1.0f - filter->efectiveFactor)) + ((float)newInput * filter->efectiveFactor);
  145. filter->value = newv;
  146. return newv;
  147. }
  148. /*******************************************************************************
  149. * С�������ϱ� *
  150. *******************************************************************************/
  151. static inline void prvf_little_block_cache_push_one_frame(uint16_t data) {
  152. if (m_little_frame_index >= LITTLE_DATA_BLOCK_FRAME_NUM) {
  153. return;
  154. }
  155. m_sensor_little_frame_cache[m_little_frame_index].data = data;
  156. m_little_frame_index++;
  157. }
  158. static inline bool prvf_light_block_cache_is_full(void) {
  159. if (m_little_frame_index >= LITTLE_DATA_BLOCK_FRAME_NUM) {
  160. return true;
  161. }
  162. return false;
  163. }
  164. static inline void prvf_light_block_cache_clear(void) { m_little_frame_index = 0; }
  165. static inline void prvf_light_block_trigger_event() {
  166. static app_event_t event;
  167. event.eventType = kevent_capture_little_data_block_event;
  168. for (uint32_t i = 0; i < LITTLE_DATA_BLOCK_FRAME_NUM; i++) {
  169. event.val.little_data_block.data[i].data = m_sensor_little_frame_cache[i].data;
  170. }
  171. event.val.little_data_block.frameIndex = m_frame_index - LITTLE_DATA_BLOCK_FRAME_NUM;
  172. // ZLOGI("%d", event.val.little_data_block.frameIndex);
  173. AppEvent_pushEvent(&event);
  174. }
  175. void nrfx_timer_event_handler(nrf_timer_event_t event_type, void* p_context) { //
  176. uint16_t val = BoardEcgSensor_plod_get_ecg_val(); // 12bit
  177. float val_af100 = (float)val / 4096.0f * 100;
  178. if (m_prestart_flag) {
  179. compute_heart_rate(val_af100);
  180. return;
  181. } else {
  182. compute_heart_rate(val_af100);
  183. }
  184. /*******************************************************************************
  185. * ��ʾ���ݼ��㲢��ֵ *
  186. *******************************************************************************/
  187. m_frame_index++;
  188. val_af100 = amp_val(val_af100, 45, 3.5f);
  189. val_af100 = Filter(&m_filter, val_af100);
  190. m_sensor_display_data = val_af100;
  191. /*******************************************************************************
  192. * �������ݻ��� *
  193. *******************************************************************************/
  194. if (m_capture_buffer == NULL) {
  195. swap_buffer();
  196. }
  197. if (m_capture_buffer_index < 128) {
  198. m_capture_buffer[m_capture_buffer_index++] = val;
  199. }
  200. if (m_capture_buffer_index == 128) {
  201. app_event_t evt;
  202. evt.eventType = kevent_capture_256data_event;
  203. evt.val.capture_data_cache = (uint8_t*)m_capture_buffer;
  204. swap_buffer();
  205. AppEvent_pushEvent(&evt);
  206. }
  207. /*******************************************************************************
  208. * ʵʱ���������¼��ϱ� *
  209. *******************************************************************************/
  210. /**
  211. * @brief �������ݣ�������С���ݿ��¼�
  212. */
  213. prvf_little_block_cache_push_one_frame(val);
  214. if (prvf_light_block_cache_is_full()) {
  215. prvf_light_block_trigger_event();
  216. prvf_light_block_cache_clear();
  217. }
  218. }
  219. void hwss_init(void) {
  220. static bool m_timer_inited = false;
  221. if (!m_timer_inited) {
  222. /**
  223. * @brief ��ʼ����ʱ��
  224. */
  225. static nrfx_timer_config_t timer_cfg = {
  226. .frequency = NRF_TIMER_FREQ_500kHz,
  227. .mode = NRF_TIMER_MODE_TIMER,
  228. .bit_width = NRF_TIMER_BIT_WIDTH_24,
  229. .p_context = NULL,
  230. .interrupt_priority = NRFX_TIMER_DEFAULT_CONFIG_IRQ_PRIORITY,
  231. };
  232. // nrfx_timer_init(&m_timer, &timer_cfg, nrfx_timer_event_handler);
  233. ZERROR_CHECK(nrfx_timer_init(&m_timer, &timer_cfg, nrfx_timer_event_handler));
  234. uint32_t timer_ticks = nrfx_timer_ms_to_ticks(&m_timer, 2); //
  235. ZASSERT(SAMPLE_RATE == 500);
  236. nrfx_timer_extended_compare(&m_timer, NRF_TIMER_CC_CHANNEL0, timer_ticks, NRF_TIMER_SHORT_COMPARE0_CLEAR_MASK, true);
  237. m_timer_inited = true;
  238. }
  239. }
  240. void hwss_uninit(void) { nrfx_timer_disable(&m_timer); }
  241. void hwss_pre_start_capture(void) {
  242. m_start_capture_tp = znordic_getpower_on_s();
  243. swap_buffer();
  244. m_frame_index = 0;
  245. QRS_reset();
  246. prvf_light_block_cache_clear();
  247. nrfx_timer_enable(&m_timer);
  248. m_prestart_flag = true;
  249. }
  250. void hwss_start_capture(void) { m_prestart_flag = false; }
  251. void hwss_stop_capture(void) {
  252. nrfx_timer_disable(&m_timer);
  253. m_frame_index = 0;
  254. prvf_light_block_cache_clear();
  255. }
  256. float hwss_read_val(void) {
  257. __disable_irq();
  258. float val = m_sensor_display_data;
  259. __enable_irq();
  260. return val;
  261. }
  262. float hwss_read_heart_rate(void) { //
  263. return m_qrs.heart_rate;
  264. }
  265. int hwss_has_captured_time_ms() { return (znordic_getpower_on_s() - m_start_capture_tp) * 1000; }