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