#include "pah831x_main.h"\r
#include "pah831x_comm.h"\r
#include "cmsis_os2.h"\r
+#include "osal_mutex.h"\r
// c\r
#include <stdarg.h>\r
#include <stdio.h>\r
\r
static int32_t factory_data = 0;\r
static uint8_t work_mode = 0;\r
-static uint8_t wear_status = 0;\r
\r
static osTimerId_t g_pah831x_timer = NULL;\r
\r
static FILE *logFp = NULL;\r
static uint8_t *log_swtich = 0;\r
static int time_out = 200;\r
-static uint8_t time_cnt = 0;\r
-static uint8_t wear_cnt = 0;\r
\r
static int history_wear_status = -1;\r
static uint8_t ppg_work_status = 0 ;\r
static ecg_data_out _ecg_data_out_alg;\r
\r
static uint8_t bp_cali_cnt = 0;\r
+\r
+#ifdef ENABLE_PAH831X_ECG_FUNCTION\r
+#define ECG_RAW_RING_CAPACITY 8192\r
+static int32_t g_ecg_raw_ring[ECG_RAW_RING_CAPACITY];\r
+static uint32_t g_ecg_raw_wr = 0;\r
+static uint32_t g_ecg_raw_count = 0;\r
+static osal_mutex g_ecg_raw_mutex;\r
+static uint8_t g_ecg_raw_mutex_inited = 0;\r
+\r
+static uint8_t living_status = 0;\r
+\r
+\r
+#define HRS_WINDOW_SIZE 7\r
+static uint8_t hrs_num = 0;\r
+static int32_t sum_hrs = 0;\r
+static int32_t hrs_data[7] = {0};\r
+static uint8_t left = 0;\r
+static uint8_t right = 0;\r
+static uint8_t time_cnt = 0;\r
+static uint8_t living_wear_cnt = 0;\r
+\r
+static void ecg_raw_mutex_init(void)\r
+{\r
+ if (g_ecg_raw_mutex_inited == 0) {\r
+ if (osal_mutex_init(&g_ecg_raw_mutex) == 0) {\r
+ g_ecg_raw_mutex_inited = 1;\r
+ }\r
+ }\r
+}\r
+\r
+static void ecg_raw_mutex_lock(void)\r
+{\r
+ ecg_raw_mutex_init();\r
+ if (g_ecg_raw_mutex_inited) {\r
+ osal_mutex_lock(&g_ecg_raw_mutex);\r
+ }\r
+}\r
+\r
+static void ecg_raw_mutex_unlock(void)\r
+{\r
+ if (g_ecg_raw_mutex_inited) {\r
+ osal_mutex_unlock(&g_ecg_raw_mutex);\r
+ }\r
+}\r
+\r
+static uint32_t ecg_raw_ring_rd_pos(void)\r
+{\r
+ return (g_ecg_raw_wr + ECG_RAW_RING_CAPACITY - g_ecg_raw_count) % ECG_RAW_RING_CAPACITY;\r
+}\r
+\r
+static void ecg_raw_ring_reset(void)\r
+{\r
+ ecg_raw_mutex_lock();\r
+ g_ecg_raw_wr = 0;\r
+ g_ecg_raw_count = 0;\r
+ ecg_raw_mutex_unlock();\r
+}\r
+\r
+static void ecg_raw_ring_push(const int32_t *data, uint32_t num)\r
+{\r
+ uint32_t i;\r
+\r
+ if (data == NULL || num == 0) {\r
+ return;\r
+ }\r
+\r
+ ecg_raw_mutex_lock();\r
+ for (i = 0; i < num; i++) {\r
+ g_ecg_raw_ring[g_ecg_raw_wr] = data[i];\r
+ g_ecg_raw_wr = (g_ecg_raw_wr + 1) % ECG_RAW_RING_CAPACITY;\r
+ if (g_ecg_raw_count < ECG_RAW_RING_CAPACITY) {\r
+ g_ecg_raw_count++;\r
+ }\r
+ }\r
+ ecg_raw_mutex_unlock();\r
+}\r
+#else\r
+static void ecg_raw_ring_reset(void)\r
+{\r
+}\r
+#endif\r
//void demo_pah831x(void);\r
\r
static bool sensor_basic_verification(main_state *this, pah_plat *plat);\r
return _ecg_data_out ;\r
}\r
\r
+#ifdef ENABLE_PAH831X_ECG_FUNCTION\r
+uint32_t pah831x_read_ecg_raw(int32_t *buf, uint32_t buf_len)\r
+{\r
+ uint32_t to_read = 0;\r
+ uint32_t rd = 0;\r
+ uint32_t i = 0;\r
+\r
+ if (buf == NULL || buf_len == 0) {\r
+ return 0;\r
+ }\r
+\r
+ ecg_raw_mutex_lock();\r
+ to_read = buf_len;\r
+ if (to_read > g_ecg_raw_count) {\r
+ to_read = g_ecg_raw_count;\r
+ }\r
+\r
+ rd = ecg_raw_ring_rd_pos();\r
+ for (i = 0; i < to_read; i++) {\r
+ buf[i] = g_ecg_raw_ring[(rd + i) % ECG_RAW_RING_CAPACITY];\r
+ }\r
+ g_ecg_raw_count -= to_read;\r
+ ecg_raw_mutex_unlock();\r
+\r
+ return to_read;\r
+}\r
+\r
+static void pah831x_notify_ecg_raw(const ecg_data_out *out)\r
+{\r
+ if (out == NULL || out->ecg_raw_data == NULL || out->sample_num_per_ch == 0) {\r
+ return;\r
+ }\r
+\r
+ ecg_raw_ring_push((const int32_t *)out->ecg_raw_data, out->sample_num_per_ch);\r
+}\r
+#else\r
+uint32_t pah831x_read_ecg_raw(int32_t *buf, uint32_t buf_len)\r
+{\r
+ (void)buf;\r
+ (void)buf_len;\r
+ return 0;\r
+}\r
+\r
+static void pah831x_notify_ecg_raw(const ecg_data_out *out)\r
+{\r
+ (void)out;\r
+}\r
+#endif\r
+\r
uint8_t get_ecg_enable(void)\r
{\r
return _state.config.ecg_is_enabled ;\r
}\r
\r
\r
+static void get_avg_hrs(uint8_t hrs)\r
+{\r
+ if (hrs_num >= HRS_WINDOW_SIZE) {\r
+ sum_hrs -= hrs_data[left];\r
+ left = (left + 1) % HRS_WINDOW_SIZE;\r
+ hrs_num--;\r
+ }\r
+\r
+ hrs_data[right] = hrs;\r
+ sum_hrs += hrs;\r
+ right = (right + 1) % HRS_WINDOW_SIZE;\r
+ hrs_num++;\r
+\r
+\r
+ if (hrs_num > 2) \r
+ {\r
+\r
+ uint8_t first_idx = left;\r
+ int32_t min_hrs = hrs_data[first_idx];\r
+ int32_t max_hrs = hrs_data[first_idx];\r
+\r
+\r
+ for (uint8_t i = 0; i < hrs_num; i++) {\r
+ uint8_t current_idx = (left + i) % HRS_WINDOW_SIZE;\r
+ uint8_t current_hrs = hrs_data[current_idx];\r
+\r
+ if (current_hrs < min_hrs) {\r
+ min_hrs = current_hrs;\r
+ }\r
+ if (current_hrs > max_hrs) {\r
+ max_hrs = current_hrs;\r
+ }\r
+ }\r
+\r
+ uint8_t valid_count = hrs_num - 2;\r
+ ret_hrs = (sum_hrs - max_hrs - min_hrs) / valid_count;\r
+\r
+\r
+ // if (last_hrs >= 30 && last_hrs <= 210) \r
+ // {\r
+ // int16_t diff = avg_hrs - last_hrs;\r
+ // if (abs(diff) > 10) \r
+ // {\r
+ // if (diff > 0) \r
+ // avg_hrs = last_hrs + 5;\r
+ // else \r
+ // avg_hrs = last_hrs - 5;\r
+ // }\r
+ // }\r
+ // last_hrs = avg_hrs;\r
+ // printf("max_hrs[%d],min_hrs[%d],avg_hrs[%d]\n",max_hrs,min_hrs,avg_hrs);\r
+ }\r
+}\r
+\r
+\r
static void pah831x_hr_timer_handler(void)\r
{\r
pah831x_sensor_task();\r
);\r
LOG_PRINT("_ppg_data_out_alg.is_touched %d\n", _ppg_data_out_alg.is_touched );\r
LOG_PRINT("hr_out:%d,hr_trust_level_out:%d,acc_num:%d\n", hr_out,hr_trust_level_out,acc_num);\r
+ LOG_PRINT("living_status:%d\n",living_status);\r
\r
-// \r
- ret_hrs = hr_out;\r
ret_wear = _ppg_data_out_alg.is_touched;\r
\r
+ if(hr_out)\r
+ {\r
+ if(hr_trust_level_out < 2)\r
+ living_status = 2;\r
+ else\r
+ living_status = 1;\r
+ }\r
+ else\r
+ living_status = 0;\r
+\r
+// \r
+ time_cnt++;\r
+\r
+ if(time_cnt >= 5)\r
+ {\r
+ time_cnt = 0;\r
+ if(uapi_dev_runtime_get_train_status())\r
+ {\r
+ if(hr_out >= 30 && hr_out <= 210)\r
+ get_avg_hrs(hr_out);\r
+ }\r
+ else\r
+ {\r
+ if(living_status == 1)\r
+ {\r
+ living_wear_cnt = 0;\r
+\r
+ if(hr_out >= 30 && hr_out <= 210)\r
+ get_avg_hrs(hr_out);\r
+\r
+ living_status = 1;\r
+ #ifdef SUPPORT_CYWEE_SERVICE\r
+ cywee_wear_status_update(&living_status);\r
+ #endif\r
+ }\r
+ else if(living_status == 2)\r
+ {\r
+ living_wear_cnt++;\r
+ if(living_wear_cnt >= 5)\r
+ {\r
+ ret_hrs = 0;\r
+ living_status = 2;\r
+ ret_wear = 0;\r
+ history_wear_status = 0;\r
+ // hx3695_unwearstatus_update();\r
+\r
+ #ifdef SUPPORT_CYWEE_SERVICE\r
+ cywee_wear_status_update(&living_status);\r
+ #endif\r
+ living_wear_cnt = 0;\r
+ }\r
+ }\r
+ else\r
+ {\r
+ living_wear_cnt = 0;\r
+ living_status = 0;\r
+ }\r
+ }\r
+ }\r
+\r
+\r
clear_ppg_data_ready();\r
}\r
if((get_ppg_enable())!=(ppg_work_status)){\r
// printf("history_wear_status:%d,ret_wear:%d\n",history_wear_status,ret_wear);\r
if(history_wear_status != ret_wear)\r
{\r
+ if(uapi_dev_runtime_get_train_status() && !ret_wear)\r
+ ret_hrs = 0;\r
+\r
history_wear_status = ret_wear;\r
- #ifdef SUPPORT_CYWEE_SERVICE\r
- // do_cywee_service_check_msg(CYWEE_SERVICE_CMD_WEAR_STATUS_CHANGE,&wear_status);\r
- cywee_wear_status_update(&ret_wear);\r
- #endif\r
+\r
+ if(uapi_dev_runtime_get_sleep_monitoring_status())\r
+ {\r
+ if(!ret_wear)\r
+ {\r
+ #ifdef SUPPORT_CYWEE_SERVICE\r
+ cywee_wear_status_update(&ret_wear);\r
+ #endif\r
+ }\r
+ else if(living_status == 1 && ret_wear)\r
+ {\r
+ #ifdef SUPPORT_CYWEE_SERVICE\r
+ cywee_wear_status_update(&ret_wear);\r
+ #endif\r
+ }\r
+ }\r
+ else\r
+ {\r
+ if(living_status != 2)\r
+ {\r
+\r
+ #ifdef SUPPORT_CYWEE_SERVICE\r
+ cywee_wear_status_update(&ret_wear);\r
+ #endif\r
+ }\r
+ }\r
}\r
\r
clear_ppg_data_ready();\r
{\r
_ecg_data_out_alg = get_ecg_data_out() ;\r
\r
+ pah831x_notify_ecg_raw(&_ecg_data_out_alg);\r
+\r
report_ecg_fifo_data(\r
(uint32_t)_ecg_data_out_alg.end_timestamp, \r
_ecg_data_out_alg.duration, \r
\r
void pah831x_ecg_raw_start(void)\r
{\r
+ ecg_raw_ring_reset();\r
pah831x_sensor_init();\r
pah831x_sensor_start(PAH831X_WORK_POLLING, PAH831X_INIT_ALWAYS_RUN, PAH831X_PPG_REG_SETTING_IDLE, PAH831X_ECG_REG_SETTING_1, 250, 2);\r
ecg_filter_init(); \r
{\r
pah_sensor_stop();\r
hr_algorithm_close();\r
+\r
+ hrs_num = 0;\r
+ sum_hrs = 0;\r
+ memset(hrs_data,0,7);\r
+\r
+ left = 0;\r
+ right = 0;\r
+ ret_hrs = 0;\r
+ living_wear_cnt = 0;\r
+ living_status = 0;\r
}\r
\r
void pah831x_hrv_stop(void)\r
\r
void pah831x_ecg_raw_stop(void)\r
{\r
+ ecg_raw_ring_reset();\r
pah_sensor_stop();\r
ecg_filter_close();\r
}\r
else if(work_mode == 9)\r
pah831x_ecg_raw_stop();\r
\r
- ret_hrs = 0;\r
ret_spo2 = 0;\r
ret_hrv = 0;\r
ret_wear = 0;\r
+ history_wear_status = -1;\r
\r
memset(acc_data, 0, sizeof(acc_data));\r
}\r