更新获取血压和ecg房颤测试接口 3454/1 3454/head 3455/target/1
author1624952103 <pl@DESKTOP-EN9LKR5.localdomain>
Wed, 10 Jun 2026 08:12:50 +0000 (16:12 +0800)
committer1624952103 <pl@DESKTOP-EN9LKR5.localdomain>
Wed, 10 Jun 2026 08:12:50 +0000 (16:12 +0800)
code/sdk/zhihui/drivers/ppg/hal/ppg_hal.c
code/sdk/zhihui/drivers/ppg/hal/ppg_hal.h
code/sdk/zhihui/drivers/ppg/pah831x/PXI_ALG/ECG_AFIB/V2022/pah_ecg_afib_alg.c
code/sdk/zhihui/drivers/ppg/pah831x/PXI_ALG/ECG_AFIB/V2022/pah_ecg_afib_alg.h
code/sdk/zhihui/drivers/ppg/pah831x/PXI_ALG/ECG_PPG_BP/v3070/pah_ecg_bp_alg.c
code/sdk/zhihui/drivers/ppg/pah831x/PXI_ALG/ECG_PPG_BP/v3070/pah_ecg_bp_alg.h
code/sdk/zhihui/drivers/ppg/pah831x/pah_sensor/pah831x_comm.c
code/sdk/zhihui/drivers/ppg/pah831x/pah_sensor/pah831x_main.c
code/sdk/zhihui/drivers/ppg/pah831x/pah_sensor/pah831x_main.h

index ce80a1c..ee28809 100644 (file)
@@ -137,10 +137,20 @@ uint8_t ppg_get_hrv(void)
     return hrv;
 }
 
-void ppg_get_bp(int *sbp,int *dbp)
+void ppg_get_ecg_bp(int *sbp, int *dbp, uint8_t *status)
 {
+    if (sbp != NULL) {
+        *sbp = 0;
+    }
+    if (dbp != NULL) {
+        *dbp = 0;
+    }
+    if (status != NULL) {
+        *status = PPG_ECG_BP_STATUS_MEASURING;
+    }
+
 #if defined PPG_PAH831X
-    pah8311_get_bp(sbp,dbp);
+    pah831x_get_ecg_bp(sbp, dbp, status);
 #endif
 }
 
@@ -170,6 +180,20 @@ uint32_t ppg_read_ecg_raw(int32_t *buf, uint32_t buf_len)
 #endif
 }
 
+void ppg_get_ecg_afib(uint8_t *ecg_hr, uint8_t *afib_result)
+{
+    if (ecg_hr != NULL) {
+        *ecg_hr = 0;
+    }
+    if (afib_result != NULL) {
+        *afib_result = PPG_ECG_AFIB_RESULT_INVALID;
+    }
+
+#if defined PPG_PAH831X
+    pah831x_get_ecg_afib(ecg_hr, afib_result);
+#endif
+}
+
 uint8_t ppg_get_wear_status(void)
 {
     uint8_t wear_status = 0;
index 1370435..423779c 100644 (file)
@@ -35,6 +35,9 @@ extern "C" {
 #define PPG_CHIP_ID 0
 #endif
 
+
+#define PPG_ECG_AFIB_RESULT_INVALID  0xFF
+
 typedef uint32_t PPG_CMD_TYPE_T ;
 
 typedef enum{
@@ -69,8 +72,6 @@ void ppg_set_factory_log_switch(uint8_t cmd);
 uint8_t ppg_get_factory_log_switch(void);
 uint8_t ppg_get_hrv(void);
 
-void ppg_get_bp(int *sbp,int *dbp);
-
 //输入校准血压
 void ppg_set_bp_cali_data(int *sbp,int *dbp);
 
@@ -84,6 +85,21 @@ bool is_ppg_bp_need_cali(void);
  * 开始/停止 ecgbp、ecgafib、ecgraw 时驱动内部自动清缓冲。 */
 uint32_t ppg_read_ecg_raw(int32_t *buf, uint32_t buf_len);
 
+/* 获取 ECG 房颤测试结果。
+ * ecg_hr: ECG 心率(bpm),测量过程中持续更新;
+ * afib_result: 房颤结论,测试未完成时为 0xFF
+ *   0 窦性心律  1 不确定(不规则)  2 可能房颤
+ *   3 不确定(信号/特征)  4 心率过低  5 心率过高 */
+void ppg_get_ecg_afib(uint8_t *ecg_hr, uint8_t *afib_result);
+
+#define PPG_ECG_BP_STATUS_MEASURING    0  /* 测量中 */
+#define PPG_ECG_BP_STATUS_WEAK_SIGNAL  1  /* ECG已停止,疑似信号弱,请重新测试 */
+
+/* 获取 ECG 血压测量结果。
+ * sbp/dbp: 收缩压/舒张压,未出结果时为 0;
+ * status: 0 测量中  1 ECG已停止(疑似信号弱,请重新测试) */
+void ppg_get_ecg_bp(int *sbp, int *dbp, uint8_t *status);
+
 #ifdef __cplusplus
 #if __cplusplus
 }
index 6c365cd..5ee975c 100644 (file)
@@ -53,15 +53,14 @@ typedef struct
 static bool need_log_header = true;\r
 static main_ecg_afib_state_s _state;\r
 \r
-static float alg_value =0.0f;\r
-\r
 #define K_sampling_rate 256\r
 static uint16_t     ECG_FS = 256; // ECG Afib function support : 128, 256 , 512 ,1024 Hz \r
 static uint16_t     ECG_time = 30; // Sec\r
 \r
 static uint8_t  ReadyFlag = 0;\r
 static uint8_t  AFIB_ReadyFlag = 0;\r
-static uint8_t  ecg_afib_result = 0;\r
+static uint8_t  ecg_afib_result = PAH_ECG_AFIB_RESULT_INVALID;\r
+static uint8_t  ecg_afib_hr = 0;\r
 static uint16_t ecg_ready_count = 0;\r
 static int32_t  ecg_frame_count = 0;\r
 \r
@@ -168,7 +167,11 @@ uint8_t is_touched
     //if(is_touched)\r
     {\r
         ecg_afib_algorithm_process(&_state.pxialg_data, _state.pxialg_data.nf_ppg_channel);\r
-        *alg_value_out = (uint8_t) alg_value ;\r
+        if (_state.has_got_AFIB) {\r
+            *alg_value_out = ecg_afib_result;\r
+        } else {\r
+            *alg_value_out = PAH_ECG_AFIB_RESULT_INVALID;\r
+        }\r
     }\r
     \r
     *got_AFIB = _state.has_got_AFIB;\r
@@ -265,6 +268,7 @@ static uint8_t run_afib_pxialg(uint32_t duration, const uint32_t* ecg_data, uint
         ECG_Analysis_Process(_state.pxialg_buffer_hrv, touch_flag, ecg_data[j], interval_time);\r
     }\r
     float HR =ECG_Analysis_Get_HR(_state.pxialg_buffer_hrv);\r
+    ecg_afib_hr = (uint8_t)HR;\r
     ALG_PRINT("ECG Heart Rate = %d  \n", (int)HR);\r
   #endif  //    ENABLE_PXI_ALG_ECG_HRD\r
     \r
@@ -311,6 +315,7 @@ static uint8_t run_afib_pxialg(uint32_t duration, const uint32_t* ecg_data, uint
 #if 1       // Use ECG HRV realtime HR. for get mean HR\r
             int16_t mean_hr = 0;\r
             mean_hr = PXIAFIB_ComputeMeanHR(_state.pxialg_state_afib); //need to instead hrv lib hr.\r
+            ecg_afib_hr = (uint8_t)mean_hr;\r
             ALG_PRINT("mean_hr=%d\n", mean_hr);\r
 #endif\r
             //for check p,r,t number\r
@@ -398,6 +403,8 @@ void ecg_afib_algorithm_init(void)
     _state.pxialg_has_init = false;\r
     need_log_header = true;\r
     AFIB_ReadyFlag = 0;\r
+    ecg_afib_result = PAH_ECG_AFIB_RESULT_INVALID;\r
+    ecg_afib_hr = 0;\r
     _state.has_got_AFIB=0;\r
     _state.has_time_out=0;\r
     _state.pxialg_data.frame_count = 0 ;\r
@@ -417,3 +424,20 @@ void ecg_afib_algorithm_init(void)
     }\r
 #endif // ENABLE_PXI_ALG_ECG_AFIB\r
 }\r
+\r
+uint8_t pah_ecg_afib_get_result(void)\r
+{\r
+#if defined(ENABLE_PXI_ALG_ECG_AFIB)\r
+    if (!_state.has_got_AFIB) {\r
+        return PAH_ECG_AFIB_RESULT_INVALID;\r
+    }\r
+    return ecg_afib_result;\r
+#else\r
+    return PAH_ECG_AFIB_RESULT_INVALID;\r
+#endif\r
+}\r
+\r
+uint8_t pah_ecg_afib_get_hr(void)\r
+{\r
+    return ecg_afib_hr;\r
+}\r
index 10d69c9..b88020e 100644 (file)
@@ -39,6 +39,11 @@ void ecg_afib_algorithm_init(void);
 \r
 void ecg_afib_algorithm_close(void);\r
 \r
+#define PAH_ECG_AFIB_RESULT_INVALID  0xFF\r
+\r
+uint8_t pah_ecg_afib_get_hr(void);\r
+uint8_t pah_ecg_afib_get_result(void);\r
+\r
 \r
 #endif  // header guard\r
 \r
index 1d47ae1..6fa70ee 100644 (file)
@@ -62,6 +62,7 @@ static struct ECG_result ecg_result;
 static int alg_value[2];\r
 \r
 static uint16_t ecg_ready_count = 0;\r
+static uint8_t  ecg_bp_hr = 0;\r
 \r
 \r
 int ppg_pf_output;\r
@@ -359,6 +360,7 @@ static uint8_t run_ecg_bp_pxialg(uint32_t duration, const uint32_t* ecg_data, co
         ECG_Analysis_Process(_state.pxialg_buffer_hrv, touch_flag, ecg_data[j], interval_time);\r
     }\r
     HR =ECG_Analysis_Get_HR(_state.pxialg_buffer_hrv);\r
+    ecg_bp_hr = (uint8_t)HR;\r
     ALG_PRINT("ECG Heart Rate = %d  ready_flag = %d\n", (int)HR,ecg_result.ready_flag);\r
   #endif  //    ENABLE_PXI_ALG_ECG_HRD\r
 \r
@@ -443,6 +445,13 @@ static uint8_t run_ecg_bp_pxialg(uint32_t duration, const uint32_t* ecg_data, co
 void ecg_bp_algorithm_init(void)\r
 {\r
 #if defined(ENABLE_PXI_ALG_ECG_BP)\r
+    BP_ReadyFlag = 0;\r
+    _state.has_got_BP = 0;\r
+    _state.has_time_out = 0;\r
+    ecg_bp_hr = 0;\r
+    alg_value[0] = 0;\r
+    alg_value[1] = 0;\r
+\r
     if (_state.pxialg_has_init)\r
     {\r
         _state.pxialg_has_init = false;\r
@@ -454,9 +463,6 @@ void ecg_bp_algorithm_init(void)
         free(_state.pxialg_buffer_bp);\r
         memset(&ecg_result,0,sizeof(ecg_result));\r
         need_log_header = true;\r
-        BP_ReadyFlag = 0;\r
-        _state.has_got_BP = 0;\r
-        _state.has_time_out = 0;\r
         _state.pxialg_data.frame_count = 0 ;\r
         LOG_PRINT("ecg_bp_algorithm_init \n");\r
     }\r
@@ -480,11 +486,64 @@ void ecg_bp_algorithm_close(void)
         BP_ReadyFlag = 0;\r
         _state.has_got_BP = 0;\r
         _state.has_time_out = 0;\r
+        ecg_bp_hr = 0;\r
         need_log_header = true;\r
         _state.pxialg_data.frame_count = 0 ;\r
     }\r
 #endif // ENABLE_PXI_ALG_ECG_BP\r
 }\r
+\r
+uint8_t pah_ecg_bp_get_status(void)\r
+{\r
+#if defined(ENABLE_PXI_ALG_ECG_BP)\r
+    if (_state.has_time_out) {\r
+        return PAH_ECG_BP_STATUS_WEAK_SIGNAL;\r
+    }\r
+    return PAH_ECG_BP_STATUS_MEASURING;\r
+#else\r
+    return PAH_ECG_BP_STATUS_MEASURING;\r
+#endif\r
+}\r
+\r
+void pah_ecg_bp_get_bp(int *sbp, int *dbp)\r
+{\r
+    int out_sbp = 0;\r
+    int out_dbp = 0;\r
+\r
+    if (sbp != NULL) {\r
+        *sbp = 0;\r
+    }\r
+    if (dbp != NULL) {\r
+        *dbp = 0;\r
+    }\r
+    if (sbp == NULL && dbp == NULL) {\r
+        return;\r
+    }\r
+\r
+#if defined(ENABLE_PXI_ALG_ECG_BP)\r
+    if (_state.has_got_BP == 0) {\r
+        return;\r
+    }\r
+\r
+    if (cal_mode == ECG_PPG_BP_CALI) {\r
+        out_sbp = NoCal_SBP;\r
+        out_dbp = NoCal_DBP;\r
+        NoCal_SBP = 0;\r
+        NoCal_DBP = 0;\r
+    } else {\r
+        out_sbp = alg_value[0];\r
+        out_dbp = alg_value[1];\r
+    }\r
+#endif\r
+\r
+    if (sbp != NULL) {\r
+        *sbp = out_sbp;\r
+    }\r
+    if (dbp != NULL) {\r
+        *dbp = out_dbp;\r
+    }\r
+}\r
+\r
 bool get_bp_cal_data(int* cal_data)\r
 {\r
     cal_data[0]=calibration_bp[0];\r
@@ -496,12 +555,5 @@ bool get_bp_cal_data(int* cal_data)
 \r
 void pah8311_get_bp(int *sbp,int *dbp)\r
 {\r
-    if(sbp == NULL || dbp == NULL)\r
-        return;\r
-        \r
-    *sbp = NoCal_SBP;\r
-    *dbp = NoCal_DBP;\r
-\r
-    NoCal_SBP = 0;\r
-    NoCal_DBP = 0;\r
+    pah_ecg_bp_get_bp(sbp, dbp);\r
 }
\ No newline at end of file
index 9ecc16b..6cf4a94 100644 (file)
@@ -54,6 +54,11 @@ void ecg_bp_algorithm_close(void);
 \r
 bool get_bp_cal_data(int* cal_data);\r
 \r
+#define PAH_ECG_BP_STATUS_MEASURING    0  /* 测量中 */\r
+#define PAH_ECG_BP_STATUS_WEAK_SIGNAL  1  /* ECG已停止,疑似信号弱,请重新测试 */\r
+\r
+uint8_t pah_ecg_bp_get_status(void);\r
+void pah_ecg_bp_get_bp(int *sbp, int *dbp);\r
 \r
 #endif  // header guard\r
 \r
index b1c3f1a..7fb04b4 100644 (file)
@@ -33,14 +33,13 @@ static uint8_t _curr_bank = 0xFF;
 pah_ret pah_comm_i2c_write( uint8_t addr, const uint8_t *data, size_t write_size)\r
 {\r
     // DEBUG_PRINT("Write { 0x%02X, 0x%02X }\n",addr, data[0]);\r
-    custom_i2c_write_reg(PAH831X_DEFAULT_I2C_SLAVE_ADDR, addr, 1, data, write_size, PAH831X_I2C_BUS);\r
-    return PAH_RET_SUCCESS;\r
+    return custom_i2c_write_reg(PAH831X_DEFAULT_I2C_SLAVE_ADDR, addr, 1, data, write_size, PAH831X_I2C_BUS);\r
 }\r
 \r
 pah_ret pah_comm_i2c_read( uint8_t addr, uint8_t *data, size_t read_size)\r
 {\r
     // DEBUG_PRINT("Read { 0x%02X }, Length =%d\n",addr,read_size);\r
-    custom_i2c_read_regs(PAH831X_DEFAULT_I2C_SLAVE_ADDR, addr, 1, data, read_size,PAH831X_I2C_BUS);\r
+    return custom_i2c_read_regs(PAH831X_DEFAULT_I2C_SLAVE_ADDR, addr, 1, data, read_size,PAH831X_I2C_BUS);\r
     // if(read_size==2)\r
     // {\r
     //     DEBUG_PRINT("Read { 0x%02X }, Data { 0x%02X, 0x%02x }\n",addr, data[0],data[1]);\r
@@ -49,7 +48,6 @@ pah_ret pah_comm_i2c_read( uint8_t addr, uint8_t *data, size_t read_size)
     // {\r
     //     DEBUG_PRINT("Read {0x%02X  }, Data { 0x%02x }\n", addr, data[0]);\r
     // }\r
-    return PAH_RET_SUCCESS;\r
 }\r
 \r
 void pah_delay_ms( uint32_t ms)\r
index 4022989..29603f9 100644 (file)
@@ -29,6 +29,7 @@
 #endif\r
 #include "pah831x_factory_test_v3.h"\r
 #include "pah_ecg_afib_alg.h"\r
+#include "pah_ecg_bp_alg.h"\r
 #include "pah_ecg_raw.h"\r
 //============================================================================\r
 // Macro\r
@@ -151,6 +152,9 @@ static uint8_t ppg_work_status = 0 ;
 static uint8_t ret_hrs = 0;\r
 static uint8_t ret_spo2 = 0;\r
 static uint8_t ret_hrv = 0;\r
+static uint8_t ret_ecg_afib_hr = 0;\r
+static uint8_t ret_ecg_afib_result = PAH_ECG_AFIB_RESULT_INVALID;\r
+static uint8_t ret_ecg_bp_status = PAH_ECG_BP_STATUS_MEASURING;\r
 static uint8_t ret_wear = 0;\r
 static ecg_data_out _ecg_data_out_alg;\r
 \r
@@ -1460,6 +1464,9 @@ static void pah831x_ecg_bp_timer_handler(void)
         CalValue_in   ,\r
         CalValue1_in  \r
         );\r
+\r
+        ret_ecg_bp_status = pah_ecg_bp_get_status();\r
+\r
         // LOG_PRINT("got_time_out =%d\n",got_time_out);\r
         // LOG_PRINT("got_BP =%d\n",got_BP);\r
         // LOG_PRINT("_ecg_data_out_alg.is_touched =%d\n",_ecg_data_out_alg.is_touched);\r
@@ -1536,6 +1543,10 @@ static void pah831x_ecg_afib_timer_handler(void)
             &got_time_out,\r
             _ecg_data_out_alg.is_touched  \r
         );\r
+\r
+        ret_ecg_afib_hr = pah_ecg_afib_get_hr();\r
+        ret_ecg_afib_result = pah_ecg_afib_get_result();\r
+\r
         clear_ecg_data_ready();\r
     }\r
     if((get_ecg_enable())!=(ppg_work_status)){\r
@@ -1740,6 +1751,9 @@ void pah831x_hr_start(void)
 \r
 void pah831x_ecg_bp_start(uint8_t cmd)\r
 {\r
+    ret_ecg_bp_status = PAH_ECG_BP_STATUS_MEASURING;\r
+    ecg_param_init = 0;\r
+\r
     if(cmd == 0)\r
     {\r
         calibration_mode = ECG_PPG_BP_CALI;\r
@@ -1795,6 +1809,8 @@ void pah831x_wear_start(void)
 \r
 void pah831x_ecg_afib_start(void)\r
 {\r
+    ret_ecg_afib_hr = 0;\r
+    ret_ecg_afib_result = PAH_ECG_AFIB_RESULT_INVALID;\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,256,3.91f  );\r
     ecg_afib_algorithm_init();\r
@@ -1841,6 +1857,8 @@ void pah831x_hrv_stop(void)
 \r
 void pah831x_ecgbp_stop(void)\r
 {\r
+    ret_ecg_bp_status = PAH_ECG_BP_STATUS_MEASURING;\r
+\r
     pah_sensor_stop();\r
     ecg_bp_algorithm_close();\r
 \r
@@ -1960,6 +1978,9 @@ void pah831x_sensor_stop(void)
     ret_spo2 = 0;\r
     ret_hrv = 0;\r
     ret_wear = 0;\r
+    ret_ecg_afib_hr = 0;\r
+    ret_ecg_afib_result = PAH_ECG_AFIB_RESULT_INVALID;\r
+    ret_ecg_bp_status = PAH_ECG_BP_STATUS_MEASURING;\r
     history_wear_status = -1;\r
 \r
     memset(acc_data, 0, sizeof(acc_data));\r
@@ -2146,6 +2167,24 @@ uint8_t pah831x_get_hrv(void)
     return ret_hrv;\r
 }\r
 \r
+void pah831x_get_ecg_afib(uint8_t *ecg_hr, uint8_t *afib_result)\r
+{\r
+    if (ecg_hr != NULL) {\r
+        *ecg_hr = ret_ecg_afib_hr;\r
+    }\r
+    if (afib_result != NULL) {\r
+        *afib_result = ret_ecg_afib_result;\r
+    }\r
+}\r
+\r
+void pah831x_get_ecg_bp(int *sbp, int *dbp, uint8_t *status)\r
+{\r
+    pah_ecg_bp_get_bp(sbp, dbp);\r
+    if (status != NULL) {\r
+        *status = ret_ecg_bp_status;\r
+    }\r
+}\r
+\r
 uint8_t pah831x_get_wear_status(void)\r
 {\r
     return ret_wear;\r
index 6d4c424..abf2049 100644 (file)
@@ -369,6 +369,9 @@ uint8_t pah831x_get_spo2(void);
 \r
 uint8_t pah831x_get_hrv(void);\r
 \r
+void pah831x_get_ecg_afib(uint8_t *ecg_hr, uint8_t *afib_result);\r
+\r
+void pah831x_get_ecg_bp(int *sbp, int *dbp, uint8_t *status);\r
 \r
 void pah8311_get_bp(int *sbp,int *dbp);\r
 \r