hx3918驱动添加
authorp15692025051 <846603105@qq.com>
Mon, 16 Oct 2023 06:56:27 +0000 (14:56 +0800)
committerp15692025051 <846603105@qq.com>
Mon, 16 Oct 2023 06:56:27 +0000 (14:56 +0800)
25 files changed:
2.sdk/sdk/gui/lv_drivers/CMakeLists.txt
2.sdk/sdk/gui/lv_drivers/indev/HX3918/hx3918.c [new file with mode: 0644]
2.sdk/sdk/gui/lv_drivers/indev/HX3918/hx3918.h [new file with mode: 0644]
2.sdk/sdk/gui/lv_drivers/indev/HX3918/hx3918_check_touch.c [new file with mode: 0644]
2.sdk/sdk/gui/lv_drivers/indev/HX3918/hx3918_check_touch.h [new file with mode: 0644]
2.sdk/sdk/gui/lv_drivers/indev/HX3918/hx3918_factory_test.c [new file with mode: 0644]
2.sdk/sdk/gui/lv_drivers/indev/HX3918/hx3918_factory_test.h [new file with mode: 0644]
2.sdk/sdk/gui/lv_drivers/indev/HX3918/hx3918_hrs_agc.c [new file with mode: 0644]
2.sdk/sdk/gui/lv_drivers/indev/HX3918/hx3918_hrs_agc.h [new file with mode: 0644]
2.sdk/sdk/gui/lv_drivers/indev/HX3918/hx3918_hrv_agc.c [new file with mode: 0644]
2.sdk/sdk/gui/lv_drivers/indev/HX3918/hx3918_hrv_agc.h [new file with mode: 0644]
2.sdk/sdk/gui/lv_drivers/indev/HX3918/hx3918_prox.c [new file with mode: 0644]
2.sdk/sdk/gui/lv_drivers/indev/HX3918/hx3918_prox.h [new file with mode: 0644]
2.sdk/sdk/gui/lv_drivers/indev/HX3918/hx3918_spo2_agc.c [new file with mode: 0644]
2.sdk/sdk/gui/lv_drivers/indev/HX3918/hx3918_spo2_agc.h [new file with mode: 0644]
2.sdk/sdk/gui/lv_drivers/indev/HX3918/tyhx_hrs_alg.h [new file with mode: 0644]
2.sdk/sdk/gui/lv_drivers/indev/HX3918/tyhx_hrv_alg.h [new file with mode: 0644]
2.sdk/sdk/gui/lv_drivers/indev/HX3918/tyhx_spo2_alg.h [new file with mode: 0644]
2.sdk/sdk/gui/lv_watch/app_adaptor/app_adaptor_sensor_interface.c
2.sdk/sdk/gui/lv_watch/app_adaptor/app_sensor_task.h
2.sdk/sdk/product/craneg_modem/CMakeLists.txt
2.sdk/sdk/product/craneg_modem/config/watch/lv_drv_conf.h
2.sdk/sdk/product/craneg_modem/cust/HX3918/Gcc_lib_R5F_hx3918_hrs_spo2_hrv_20230922_v02a.a [new file with mode: 0644]
2.sdk/sdk/product/craneg_modem/cust/HX3918/Gcc_lib_R5_hx3918_hrs_spo2_hrv_20231013_v02a.a [new file with mode: 0644]
2.sdk/sdk/product/craneg_modem/lv_gui_main.c

index 7f13748..07b070e 100644 (file)
@@ -77,6 +77,14 @@ set(lv_drivers_sources
   indev/gh3018_source/HRNet_knWeights.c
   indev/gh3018_source/HRNet_knWeightsSmall.c
   indev/gh3018_source/pv_v2.0.1_sm_spo2wrnet_for_GH3018_masimo_0f423c.c
+  indev/HX3918/hx3918.c
+  indev/HX3918/hx3918_check_touch.c
+  indev/HX3918/hx3918_factory_test.c
+  indev/HX3918/hx3918_hrs_agc.c
+  indev/HX3918/hx3918_hrv_agc.c
+  indev/HX3918/hx3918_prox.c
+  indev/HX3918/hx3918_spo2_agc.c
+
   indev/ACNT180.c
   indev/ACNT117.c  
   jpeg/crane_jpuc_common.c
@@ -91,7 +99,10 @@ set(lv_drivers_sources
   #bt_SensorHub/bt_SensorHub_uart.c
   #bt_SensorHub/hal_bt_SensorHub_uart.c
 )
-
+include_directories(
+  indev/HX3918/
+  
+)
 # Add the static library
 add_library(lv_drivers STATIC ${lv_drivers_sources})
 target_include_directories(lv_drivers PRIVATE ${SDL2_INCLUDE_DIRS} ${PRODUCT_CONFIG_DIR} ${LVGL_DIR})
diff --git a/2.sdk/sdk/gui/lv_drivers/indev/HX3918/hx3918.c b/2.sdk/sdk/gui/lv_drivers/indev/HX3918/hx3918.c
new file mode 100644 (file)
index 0000000..b6ed219
--- /dev/null
@@ -0,0 +1,1647 @@
+
+
+
+#include "lv_drv_conf.h"
+#if USE_HX3918
+
+#include <stdio.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <math.h>
+#include "hx3918.h"
+
+#include "../../board.h"
+#include "../../common/i2c.h"
+#include "../../../../product/craneg_modem/framework/inc/gpio_api.h"
+#include "lvgl/hal/hal.h"
+#include "../../../lv_watch/app_adaptor/app_sensor_task.h"
+
+
+
+#define HX3918_ADDR 0x44
+
+//#include "tyhx_hrs_custom.h"
+#ifdef SAR_ALG_LIB
+#include "hx3918_prox.h"
+#endif
+
+#ifdef HRS_ALG_LIB
+#include "hx3918_hrs_agc.h"
+#include "tyhx_hrs_alg.h"
+
+#ifdef SPO2_ALG_LIB
+#include "hx3918_spo2_agc.h"
+#include "tyhx_spo2_alg.h"
+#endif
+
+#ifdef HRV_ALG_LIB
+#include "hx3918_hrv_agc.h"
+#include "tyhx_hrv_alg.h"
+#endif
+
+#ifdef CHECK_TOUCH_LIB
+#include "hx3918_check_touch.h"
+#endif
+#include "hx3918_factory_test.h"
+
+
+
+#ifdef SPO2_VECTOR
+#include "spo2_vec.h"
+uint32_t spo2_send_cnt = 0;
+int32_t red_buf_vec[8];
+int32_t ir_buf_vec[8];
+int32_t green_buf_vec[8];
+#endif
+
+#ifdef HR_VECTOR
+#include "hr_vec.h"
+uint32_t hrs_send_cnt = 0;
+int32_t PPG_buf_vec[8];
+#endif
+
+#ifdef HRV_TESTVEC
+#include "hrv_testvec.h"
+#endif
+char hx3918_ppg_timerout_flag = 0;
+static void * hx3918_ppg_timer = NULL;
+
+char hx3918_agc_timerout_flag = 0;
+static void * hx3918_agc_timer = NULL;
+/************************simware add start***********************************/
+/************************simware add start***********************************/
+static  uint32_t hx3918_mfp_cfgs[] = {
+     MFP_REG(GPIO_32) | MFP_AF0 | MFP_DRIVE_MEDIUM | MFP_PULL_LOW | MFP_SLEEP_DIR | MFP_LPM_EDGE_NONE,
+     MFP_REG(GPIO_18) | MFP_AF0 | MFP_DRIVE_MEDIUM | MFP_PULL_LOW | MFP_SLEEP_DIR | MFP_LPM_EDGE_NONE,
+     MFP_REG(GPIO_81) | MFP_AF0 | MFP_DRIVE_MEDIUM | MFP_PULL_LOW | MFP_SLEEP_DIR | MFP_LPM_EDGE_NONE,
+     MFP_REG(GPIO_84) | MFP_AF0 | MFP_DRIVE_MEDIUM | MFP_PULL_LOW | MFP_SLEEP_DIR | MFP_LPM_EDGE_NONE,
+    MFP_EOC
+};
+
+typedef    void*    OS_HISR;
+static OS_HISR     hx3918_hisr_ref;
+
+
+static unsigned char is_HX3918 = 0;//是否存在IC
+static unsigned char is_open_HX3918 = 0; //是否打开测试
+static unsigned char s_HX3918_heart_rate = 0x0;//心律
+static unsigned char s_HX3918_high_blood = 0x0;//血压/高压
+static unsigned char s_HX3918_low_blood = 0x0;//血压/低压
+static unsigned char s_HX3918_blood_oxygen = 0x0;//血氧
+static unsigned char s_HX3918_HRV = 0x0;//hrv
+static unsigned char s_HX3918_wear_status = 1;//佩戴状态
+#define HEART_RATE_BUFF_LEN 10
+unsigned char s_HX3918_heart_rate_buff[HEART_RATE_BUFF_LEN]={0};
+unsigned short s_HX3918_heart_rate_buff_count = 0;
+uint32_t HX3918_run_mode = NULL_MODE;
+uint32_t HX3918_jobs_mode = NULL_MODE;
+int ir_wear = 0;//红外佩戴状态
+int cap_wear = 1;//电容佩戴状态
+char is_open_sar = 1;//是否打开sar检测
+void hal_gh30x_int_handler(uint32_t *process_data);
+void HX3918_close(void);
+static void hx3918_en_gpio_init(void)
+{
+    gpio_set_direction(GPIO18, GPIO_OUT);
+    gpio_set_direction(GPIO81, GPIO_OUT);
+    gpio_set_direction(GPIO84, GPIO_OUT);
+}
+//Hsensor 电源、复位
+static void hx3918_en_gpio_enable(bool param)
+{
+    static flag = 0;
+    if(param)
+        flag++;
+    else 
+    {
+        if(flag > 0)
+            flag --;
+    }
+        
+    if(flag > 0) {
+        gpio_set_value(GPIO18, GPIO_HIGH);
+        gpio_set_value(GPIO81, GPIO_HIGH);
+        gpio_set_value(GPIO84, GPIO_HIGH);
+    } else {
+        gpio_set_value(GPIO18, GPIO_LOW);
+        gpio_set_value(GPIO81, GPIO_LOW);
+        // gpio_set_value(GPIO84, GPIO_LOW);
+    }
+}
+
+static void hx3918_hisr_callback(void)
+{
+    sensor_task_send_message(HX3918_ID,SENSOR_MSG_PROCESS_DATA);
+}
+
+static void hx3918_create_hisr(void)
+{
+    OS_Create_HISR(&hx3918_hisr_ref,"icm_hisr", hx3918_hisr_callback, HISR_PRIORITY_2);
+}
+
+// static void hx3918_isr_callback(void)
+// {
+//     OS_Activate_HISR(&hx3918_hisr_ref);
+// }
+
+/* Timer0_0 is configured to free run @1MHz from BootROM. */
+// static void DelayInUs(unsigned int us)
+// {
+//     unsigned long startTime, endTime;
+
+//     startTime = GetTimer0CNT(); 
+//     do
+//     {
+//         endTime = GetTimer0CNT();    
+//     }
+//     while(Timer0IntervalInMicro(startTime, endTime) < us);
+// }
+void HX3918_test(uint32_t mode)
+{
+       s_HX3918_heart_rate = 0x0;
+       s_HX3918_heart_rate_buff_count = 0; 
+       s_HX3918_high_blood = 0x0;
+       s_HX3918_low_blood = 0x0;
+       s_HX3918_HRV = 0;
+       //s_HX3918_wear_status = 0;
+       s_HX3918_blood_oxygen = 0x0;
+    HX3918_LOG("HX3918_test1:%d!!!!\n\n",mode);
+       if(mode <= close_MODE)
+       {
+               if(hx3918_init(mode) == true)
+               {
+                       is_open_HX3918 = 1;
+            HX3918_LOG("hx3918_init:ok!!!!\n\n");
+                       // if(sensor_timer== 0)
+                       // {
+                       //      sensor_timer = Helios_Timer_init( (void* )sensor_timerout_cb, NULL);
+                       // }
+                       
+                       // Helios_Timer_Start(sensor_timer, TIMER_TIME_MS, IS_CYCLICAL);
+               }else
+            HX3918_LOG("hx3918_init:error!!!!\n\n");
+       }else if(mode == 255)//活体校准功能
+       {
+               // Helios_GPIO_SetLevel(g_HX3918->power, HELIOS_LVL_LOW);
+               // Helios_msleep(150);
+               // Helios_GPIO_SetLevel(g_HX3918->power, HELIOS_LVL_HIGH);
+               // Helios_msleep(20);
+               // hx3918_init(WEAR_MODE);//打开佩戴检测
+               #ifdef  SAR_ALG_LIB
+               hx3918_prox_factory_hanging_cali();
+               #endif
+       }
+       HX3918_LOG("HX3918_test2:%d!!!!\n\n",mode);
+}
+static void hx3918_start(void)
+{
+
+    HX3918_LOG("hx3918_start:HX3918_run_mode:%d\n",HX3918_run_mode);
+    hal_hx3918_int_init();
+    HX3918_restart();
+    if(HX3918_jobs_mode != NULL_MODE)//没关闭就打开其他模式,先关闭一次
+    {
+        // HX3918_close();
+        // hx3918_delay(20);
+        // HX3918_jobs_mode = NULL_MODE;
+    }
+    // else
+    //         HX3918_restart();
+    
+    HX3918_test(HX3918_run_mode);
+    HX3918_jobs_mode = HX3918_run_mode;
+    HX3918_run_mode = NULL_MODE;
+
+    // hal_gh30x_int_init();
+    // hx3918_en_gpio_enable(false);
+    // DelayInUs(10*1000);
+    // hx3918_en_gpio_enable(true);
+    // DelayInUs(50*1000);
+    // int ret = gh30x_module_init();
+    
+    
+    //gh30x_module_start_without_adt(measure_mode);
+}
+
+static void hx3918_stop(void)
+{
+    HX3918_LOG("[%s][%d]: \n", __FUNCTION__, __LINE__);
+    //gh30x_module_stop();
+    
+    //hx3918_en_gpio_enable(false);
+    HX3918_close();
+    //HX3918_LOG("HX3918_irq_cb: 1111111111111!!!!!!!!\r\n");
+    HX3918_run_mode = NULL_MODE;
+    HX3918_jobs_mode = NULL_MODE;
+    hx3918_ppg_timerout_flag = 0;
+    hx3918_agc_timerout_flag = 0;
+
+       
+}
+void hx3918_process_data(uint32_t *process_data)
+{
+    if(hx3918_ppg_timerout_flag)
+       {
+               hx3918_ppg_Int_handle();
+               hx3918_ppg_timerout_flag = 0;
+        //HX3918_LOG("hx3918_process_data : hx3918_ppg\n");
+       }
+       if(hx3918_agc_timerout_flag)
+       {
+               agc_timeout_handler(NULL);
+               hx3918_agc_timerout_flag =0;
+        //HX3918_LOG("hx3918_process_data : hx3918_agc\n");
+       }
+}
+void hal_hx3918_int_init(void)
+{
+    // code implement by user
+    // must register func hal_gh30x_int_handler as callback
+    
+    mfp_config(hx3918_mfp_cfgs);
+    hx3918_en_gpio_init();
+    HX3918_LOG("HX3918 ID : 0x%02x\n",get_hx3918_id());
+    
+}
+void Hx3918_Init(void)
+{
+
+    static bool register_dev_flag = false;
+    if(!register_dev_flag)
+    {
+        register_dev_flag = true;
+        sensor_drv_t sensor_drv;
+        sensor_drv.sensor_name = "hx3918";
+        sensor_drv.sensor_start = hx3918_start;
+        sensor_drv.sensor_stop = hx3918_stop;
+        sensor_drv.sensor_process_data = hx3918_process_data;
+        sensor_drv_register(HX3918_ID,&sensor_drv);
+    }
+    hx3918_create_hisr();
+    hal_hx3918_int_init();
+
+}
+
+uint8_t get_hx3918_id(void)
+{
+    uint8_t hx3918_chip_id = 0;
+    hx3918_en_gpio_enable(true);
+    hx3918_delay(50);
+    hx3918_write_reg(0x01, 0x00);
+    hx3918_delay(5);
+    hx3918_chip_id = hx3918_read_reg(0x00);
+    hx3918_en_gpio_enable(false);
+    return hx3918_chip_id;
+}
+
+static bool is_measuring_flag = false;
+void hx3918_measure_hr_start(void)
+{
+    sys_pm_wakeup_no_lcd();
+    
+
+    HX3918_run_mode = HRS_MODE;
+    HX3918_LOG("hx3918_measure_hr_start :HX3918_run_mode:%d!!!!!!!!\n",HX3918_run_mode);
+    sensor_task_send_message(HX3918_ID,SENSOR_MSG_START);
+}
+
+void hx3918_measure_bo_start(void)
+{
+    sys_pm_wakeup_no_lcd();
+
+
+    HX3918_run_mode = SPO2_MODE        ;
+    HX3918_LOG("hx3918_measure_bo_start :HX3918_run_mode:%d!!!!!!!!\n",HX3918_run_mode);
+    sensor_task_send_message(HX3918_ID,SENSOR_MSG_START);
+}
+void HX3918_restart(void)
+{
+       hx3918_en_gpio_enable(false);
+       hx3918_delay(50);
+       hx3918_en_gpio_enable(true);
+       hx3918_delay(50);
+}
+void hx3918_measure_stop(void)
+{
+    HX3918_LOG("hx3918_measure_stop !!!!!!!!\n");
+    HX3918_run_mode = close_MODE;
+    sensor_task_send_message(HX3918_ID,SENSOR_MSG_STOP);
+}
+void HX3918_close(void)
+{
+    HX3918_LOG("HX3918_close !!!!!!!!\n");
+    watch_set_sleep_lcd_only(false);
+    is_measuring_flag = false;
+    //asl_hr_bp_bo_measure_finish_flag_set();
+    //hx3918_hrs_disable
+    if(HX3918_jobs_mode == HRS_MODE)
+    {
+        hx3918_hrs_disable();
+    }else if(HX3918_jobs_mode == SPO2_MODE)
+    {
+        hx3918_spo2_disable();
+    }else if(HX3918_jobs_mode == HRV_MODE)
+    {
+        //hx3918_hrv_disable();
+    }
+    // if(sensor_timer != 0)
+    // {
+    //     Helios_Timer_Stop(sensor_timer);
+    // }
+    HX3918_restart();
+       #ifdef  SAR_ALG_LIB
+       hx3918_prox_init();
+       #endif
+       hx3918_init(WEAR_MODE);//打开佩戴检测
+    
+}
+
+static void hx3918_hr_bp_bo_value_update(uint16_t hr, uint16_t bp_high, uint16_t bp_low, uint16_t bo)
+{
+       HX3918_LOG("[@CHENG_DEBUG][%s][%d]: %d,%d,%d,%d\n", __FUNCTION__, __LINE__, hr, bp_high, bp_low, bo);
+       s_HX3918_heart_rate = hr;
+    s_HX3918_blood_oxygen = bo;
+    s_HX3918_high_blood = bp_high ;
+    s_HX3918_low_blood = bp_low ;
+    
+
+    // if(hr > 0) {
+    //     hx3918_hr_bp_bo_value.hr = hr;
+    // }
+    // if(bp_high > 0 && bp_low > 0) {
+    //     hx3918_hr_bp_bo_value.bp_high = bp_high;
+    //     hx3918_hr_bp_bo_value.bp_low = bp_low;
+    // }
+    // if(bo > 0) {
+    //     hx3918_hr_bp_bo_value.bo = bo;
+    // }
+    // //app_adaptor_pedometer_data_clear();
+}
+
+uint16_t get_hx3918_hr_value(void)
+{
+    return s_HX3918_heart_rate;
+}
+
+uint16_t get_hx3918_b0_value(void)
+{
+    return s_HX3918_blood_oxygen;
+}
+
+void hx3918_hr_bp_bo_value_get(uint16_t *hr, uint16_t *bp_high, uint16_t *bp_low, uint16_t *bo)
+{
+    if(hr != NULL)
+        *hr = s_HX3918_heart_rate;
+    if(bp_high != NULL)
+        *bp_high = s_HX3918_high_blood;
+    if(bp_low != NULL)
+        *bp_low = s_HX3918_low_blood;
+    if(bo != NULL)
+        *bo = s_HX3918_blood_oxygen;
+}
+
+void hx3918_hr_bp_bo_value_clear(void)
+{
+    s_HX3918_heart_rate = 0x0;
+       s_HX3918_heart_rate_buff_count = 0; 
+       s_HX3918_high_blood = 0x0;
+       s_HX3918_low_blood = 0x0;
+       s_HX3918_HRV = 0;
+       //s_HX3918_wear_status = 0;
+       s_HX3918_blood_oxygen = 0x0;
+    //memset(&hx3918_hr_bp_bo_value, 0, sizeof(hx3918_hr_bp_bo_value));
+
+}
+/******************************************************************************/
+void HX3918_result_set_heart_rate(unsigned char heart_rate)
+{
+//    s_HX3918_heart_rate_buff[HEART_RATE_BUFF_LEN]={0};
+// uint16 s_HX3918_heart_rate_buff_count = 0;
+   uint32_t i,tmp = 0;
+   s_HX3918_heart_rate_buff[s_HX3918_heart_rate_buff_count] = heart_rate;
+   s_HX3918_heart_rate_buff_count++;
+   for(i=0;i<s_HX3918_heart_rate_buff_count;i++)//算总和,取平均值
+   {
+      tmp+=s_HX3918_heart_rate_buff[i];
+   }
+   s_HX3918_heart_rate = tmp/s_HX3918_heart_rate_buff_count;//取平均值
+   //s_HX3918_heart_rate = heart_rate; 
+   if(s_HX3918_heart_rate_buff_count >=  HEART_RATE_BUFF_LEN)
+      s_HX3918_heart_rate_buff_count = 0;
+   s_HX3918_high_blood = (uint8_t)(heart_rate * 1.5);
+   
+   s_HX3918_low_blood = (uint8_t)(heart_rate * 0.95);
+}
+void HX3918_result_set_wear_status(unsigned char wear_status)
+{
+       if(wear_status != 1)
+               s_HX3918_wear_status = 0;
+       else
+               s_HX3918_wear_status = 1;
+   //HX3918_LOG("s_HX3918_wear_status:%d !!!!!!!!!!!!!!!!!\n\n\n",s_HX3918_wear_status);
+}
+void HX3918_result_set_blood_oxygen(unsigned char blood_oxygen)
+{
+   s_HX3918_blood_oxygen = blood_oxygen;    
+}
+ 
+void HX3918_result_set_hrv(unsigned char hrv)
+{
+   s_HX3918_HRV = hrv;    
+}
+/*****************************************************************************/
+tyhx_hrsresult_t hrsresult;
+
+#ifdef GSENSER_DATA
+volatile int16_t gsen_fifo_x[32];  //ppg time 330ms..330/40 = 8.25
+volatile int16_t gsen_fifo_y[32];
+volatile int16_t gsen_fifo_z[32];
+int16_t gsen_fifo_count = 0;
+#else
+int16_t gen_dummy[32] = {0};
+#endif
+//SPO2 agc
+const uint8_t  hx3918_spo2_agc_green_idac = GREEN_AGC_OFFSET;
+const uint8_t  hx3918_spo2_agc_red_idac = RED_AGC_OFFSET;
+const uint8_t  hx3918_spo2_agc_ir_idac = IR_AGC_OFFSET;
+//hrs agc
+const uint8_t  hx3918_hrs_agc_idac = HR_GREEN_AGC_OFFSET;
+//hrv agc
+const uint8_t  hx3918_hrv_agc_idac = HR_GREEN_AGC_OFFSET;
+
+const uint8_t  red_led_max_init = 200;
+const uint8_t  ir_led_max_init = 200;
+const uint8_t  green_led_max_init = 150;
+
+uint8_t low_vbat_flag =0;
+//WORK_MODE_T work_mode_flag = HRS_MODE;
+
+const uint16_t static_thre_val = 150;
+const uint8_t  gsen_lv_val = 0;
+
+
+//HRS_INFRARED_THRES
+const int32_t  hrs_ir_unwear_thres = 5000;
+const int32_t  hrs_ir_wear_thres = 6000;
+//HRV_INFRARED_THRES
+const int32_t  hrv_ir_unwear_thres = 5000;
+const int32_t  hrv_ir_wear_thres = 6000;
+//SPO2_INFRARED_THRES
+const uint8_t  spo2_check_unwear_oft = 4;
+const int32_t  spo2_ir_wear_thres = 20000;
+//CHECK_WEAR_MODE_THRES
+const int32_t  check_mode_unwear_thre = 5000;
+const int32_t  check_mode_wear_thre = 6000;
+//const int32_t  check_mode_sar_thre = 6000;
+#ifndef  SAR_ALG_LIB
+#define NORMALWEARDIFF  12000
+#endif
+int32_t  sar_wear_thres = NORMALWEARDIFF/3;  // 可设定为正常的1/3, 必须小于32767
+int32_t  sar_unwear_thres = NORMALWEARDIFF/30*8; // 可设定为 sar_wear_thres *0.8
+
+uint8_t alg_ram[11 * 1024] __attribute__((aligned(4)));
+ppg_sensor_data_t ppg_s_dat;
+uint8_t read_fifo_first_flg = 0;
+hrs_sports_mode_t hrs_mode = NORMAL_MODE;
+#endif
+
+//////// spo2 para and switches
+const  uint8_t   COUNT_BLOCK_NUM = 50;            //delay the block of some single good signal after a series of bad signal
+const  uint8_t   SPO2_LOW_XCORR_THRE = 30;        //(64*xcorr)'s square below this threshold, means error signal
+const  uint8_t   SPO2_CALI = 1;                       //spo2_result cali mode
+const  uint8_t   XCORR_MODE = 1;                  //xcorr mode switch
+const  uint8_t   QUICK_RESULT = 1;                //come out the spo2 result quickly ;0 is normal,1 is quick
+const  uint16_t  MEAN_NUM = 32;                  //the length of smooth-average ;the value of MEAN_NUM can be given only 256 and 512
+const  uint8_t   G_SENSOR = 0;                      //if =1, open the gsensor mode
+const  uint8_t   SPO2_GSEN_POW_THRE = 150;         //gsen pow judge move, range:0-200;
+const  uint32_t  SPO2_BASE_LINE_INIT = 135000;    //spo2 baseline init, = 103000 + ratio(a variable quantity,depends on different cases)*SPO2_SLOPE
+const  int32_t   SOP2_DEGLITCH_THRE = 100000;     //remove signal glitch over this threshold
+const  int32_t   SPO2_REMOVE_JUMP_THRE = 100000;  //remove signal jump over this threshold
+const  uint32_t  SPO2_SLOPE = 50000;              //increase this slope, spo2 reduce more
+const  uint16_t  SPO2_LOW_CLIP_END_TIME = 1500;   //low clip mode before this data_cnt, normal clip mode after this
+const  uint16_t  SPO2_LOW_CLIP_DN  = 150;         //spo2 reduce 0.15/s at most in low clip mode
+const  uint16_t  SPO2_NORMAL_CLIP_DN  = 500;      //spo2 reduce 0.5/s at most in normal clip mode
+const  uint8_t   SPO2_LOW_SNR_THRE = 40;          //snr below this threshold, means error signal
+const  uint16_t  IR_AC_TOUCH_THRE = 200;          //AC_min*0.3
+const  uint16_t  IR_FFT_POW_THRE = 200;           //fft_pow_min
+const  uint8_t   SLOPE_PARA_MAX = 30;
+const  uint8_t   SLOPE_PARA_MIN = 3;
+
+WORK_MODE_T work_mode_flag = HRV_MODE;
+void display_refresh(void)
+{
+
+}
+
+
+void hx3918_delay(uint32_t ms)
+{
+    INT32 cnt = 0x29F9;  //uart_log cal as: 1ms
+       volatile INT32 i = 0;
+       
+       for(;ms != 0; ms--){
+               i = cnt;
+               for(;i != 0; i--);
+       }
+    
+}
+void hx3918_delay_us(uint32_t us)
+{
+
+    hx3918_delay(us/1000+1);
+}
+//Timer interrupt 40ms repeat mode
+void gsen_read_timeout_handler(void * p_context)
+{
+    hx3918_agc_Int_handle();
+#ifdef GSEN_40MS_TIMMER
+    hx3918_gesensor_Int_handle();
+#endif
+
+#ifdef LAB_TEST_INT_MODE
+    if(work_mode_flag == LAB_TEST_MODE)// add ericy 20210127
+    {
+        hx3690l_lab_test_read();
+    }
+#endif
+}
+
+
+bool hx3918_write_reg(uint8_t addr, uint8_t data)
+{
+    // if(HELIOS_I2C_Write(0, HX3918_ADDR, &addr, 1, &data, 1) != 0)
+       // {
+               
+       //      //GH301x_LOG("hal_gh30x_i2c_write:error\r\n");
+       // }
+    //int i2c_write_regs(i2c_t dev, uint16_t address, uint16_t reg,
+    //               const void *data, size_t length, uint8_t flags)
+    if(-1 == i2c_write_regs(I2C_MASTER_CI2C1, HX3918_ADDR, addr, (void *)&data,1,0))
+    {
+        cplog_printf("write-------->>>i2c transmit failed! \r\n");
+        return false;
+    }
+    return true;
+}
+
+uint8_t hx3918_read_reg(uint8_t addr)
+{
+    uint8_t data_buf = 0;  
+
+    //int i2c_read_reg(i2c_t dev, uint16_t address, uint16_t reg, void *data, uint8_t flags)
+    if(-1 == i2c_read_reg(I2C_MASTER_CI2C1, HX3918_ADDR, addr,(void *)&data_buf,0))
+    {
+        cplog_printf("read-------->>>i2c receive failed! \r\n");
+        return false;
+    }
+    
+    // if(HELIOS_I2C_Read(0, HX3918_ADDR, &addr, 1, (void*)&data_buf, 1, 0) != 0)
+       // {
+       //      //GH301x_LOG("hal_gh30x_i2c_read:error\r\n");
+               
+       // }
+    return data_buf;
+}
+
+bool hx3918_brust_read_reg(uint8_t addr, uint8_t *buf, uint8_t length)
+{
+#ifdef  TYHX_DEMO
+       twi_pin_switch(1);
+    twi_master_transfer(0x88, &addr, 1, false);      //write
+    twi_master_transfer(0x89, buf, length, true); //read
+#endif
+    // if(HELIOS_I2C_Read(0, HX3918_ADDR, &addr, 1, (void*)buf, length, 0) != 0)
+       // {
+       //      //GH301x_LOG("hal_gh30x_i2c_read:error\r\n");
+               
+       // }
+    if(-1 == i2c_read_regs(I2C_MASTER_CI2C1, HX3918_ADDR, addr,(void *)buf,length,0))
+    {
+        cplog_printf("read-------->>>i2c receive failed! \r\n");
+        return false;
+    }
+    return true;
+}
+
+void hx3918_ppg_timerout_cb(void)
+{
+    hx3918_ppg_timerout_flag = 1;
+    //HX3918_LOG("hx3918_ppg_timerout_cb\n");
+    OS_Activate_HISR(&hx3918_hisr_ref);
+}
+void hx3918_ppg_timer_cfg(bool en)    //320ms
+{
+    HX3918_LOG("hx3918_ppg_timer_cfg :%d!!!!!!\n\n",en);
+    if(en)
+    {
+        if(hx3918_ppg_timer == NULL )
+            uos_timer_create(&hx3918_ppg_timer);
+            //hx3918_ppg_timer = Helios_Timer_init( (void* )hx3918_ppg_timerout_cb, NULL);
+        if(work_mode_flag == WEAR_MODE)
+        {
+            
+            uos_timer_start(hx3918_ppg_timer, MS_TO_TICKS(3000), MS_TO_TICKS(3000), hx3918_ppg_timerout_cb, NULL);
+            //Helios_Timer_Start(hx3918_ppg_timer, 3000, 1);
+            //Helios_Timer_Start(hx3918_ppg_timer, 320, 1);
+        }else
+        {
+            
+            uos_timer_start(hx3918_ppg_timer, MS_TO_TICKS(320), MS_TO_TICKS(320), hx3918_ppg_timerout_cb, NULL);
+        }
+            
+            //Helios_Timer_Start(hx3918_ppg_timer, 320, 1);
+
+    }
+    else
+    {
+        if(hx3918_ppg_timer)
+               {
+            HX3918_LOG("hx3918_ppg_timer_cfg Timer_Stop\n\n");
+            uos_timer_stop(hx3918_ppg_timer);
+                       //Helios_Timer_Stop(hx3918_ppg_timer);
+               }
+    }
+
+}
+
+void hx3918_agc_timerout_cb(void)
+{
+    hx3918_agc_timerout_flag = 1;
+    //HX3918_LOG("hx3918_agc_timerout_cb\n");
+    OS_Activate_HISR(&hx3918_hisr_ref);
+}
+/* 40ms void agc_timeout_handler(void * p_context) */
+void hx3918_agc_timer_cfg(bool en)
+{
+    HX3918_LOG("hx3918_agc_timer_cfg :%d!!!!!!!!!!!!\n",en);
+    if(en)
+    {
+        if(hx3918_agc_timer  == NULL)
+            uos_timer_create(&hx3918_agc_timer);
+        uos_timer_start(hx3918_agc_timer, MS_TO_TICKS(40), MS_TO_TICKS(40), hx3918_agc_timerout_cb, NULL);
+        
+        // if(hx3918_agc_timer == 0)
+        //     hx3918_agc_timer = Helios_Timer_init( (void* )hx3918_agc_timerout_cb, NULL);
+        // Helios_Timer_Start(hx3918_agc_timer, 40, 1);
+    }
+    else
+    {
+        if(hx3918_agc_timer )
+               {
+            uos_timer_stop(hx3918_agc_timer);
+                       //Helios_Timer_Stop(hx3918_agc_timer);
+               }
+    }
+
+}
+#if defined(INT_MODE)
+void hx3918_gpioint_cfg(bool en)
+{
+    if(en)
+    {
+        hx3918_gpioint_enable();
+    }
+    else
+    {
+        hx3918_gpioint_disable();
+    }
+
+}
+#endif
+
+uint8_t hx3918_chip_id = 0;
+bool hx3918_chip_check(void)
+{
+    uint8_t i = 0;
+
+    for(i=0; i<10; i++)
+    {
+        hx3918_write_reg(0x01, 0x00);
+        hx3918_delay(5);
+        hx3918_chip_id = hx3918_read_reg(0x00);
+        if (hx3918_chip_id == 0x27)             
+        {
+            HX3918_LOG("chip id  = 0x%x        check ok \r\n",hx3918_chip_id);
+            return true;
+        }
+    }
+    HX3918_LOG("hx3918_chip_check fail\r\n");
+    return false;
+}
+
+uint8_t hx3918_read_fifo_size(void)
+{
+    uint8_t fifo_num_temp = 0;
+    fifo_num_temp = hx3918_read_reg(0x40)&0x7f;  // ericy 230529
+
+    return fifo_num_temp;
+}
+uint16_t hx3918_read_fifo_data(int32_t *buf, uint8_t phase_num, uint8_t sig)
+{
+    uint8_t data_flg_start = 0;
+    uint8_t data_flg_end = 0;
+    uint8_t databuf[3];
+    uint32_t ii=0;
+    uint16_t data_len = 0;
+    uint16_t fifo_data_length = 0;
+    uint16_t fifo_read_length = 0;
+    uint16_t fifo_read_bytes = 0;
+    uint16_t fifo_out_length = 0;
+    uint16_t fifo_out_count = 0;
+    uint8_t fifo_data_buf[200] = {0};
+
+    data_len = hx3918_read_reg(0x40);// ericy 230529
+    fifo_data_length = data_len;
+    //HX3918_LOG("data_len:   %d\r\n",data_len);
+    if(fifo_data_length<2*phase_num)
+    {
+        return 0;
+    }
+    fifo_read_length = ((fifo_data_length-phase_num)/phase_num)*phase_num;
+    fifo_read_bytes = fifo_read_length*3;
+    if(read_fifo_first_flg == 1)
+    {
+        hx3918_brust_read_reg(0x41, databuf, 3);       // ericy 230529
+        read_fifo_first_flg = 0;
+    }
+    hx3918_brust_read_reg(0x41, fifo_data_buf, fifo_read_bytes);       // ericy 230529
+//             for(ii=0; ii<fifo_read_bytes; ii++)
+//             {
+//                     HX3918_LOG("%d/%d, %d\r\n", ii+1,fifo_read_bytes,fifo_data_buf[ii]);
+//             }
+    for(ii=0; ii<fifo_read_length; ii++)
+    {
+        if(sig==0)
+        {
+            buf[ii] = (int32_t)(fifo_data_buf[ii*3]|(fifo_data_buf[ii*3+1]<<8)|((fifo_data_buf[ii*3+2]&0x1f)<<16));
+        }
+        else
+        {
+            if((fifo_data_buf[ii*3+2]&0x10)!=0)
+            {
+                buf[ii] = (int32_t)(fifo_data_buf[ii*3]|(fifo_data_buf[ii*3+1]<<8)|((fifo_data_buf[ii*3+2]&0x0f)<<16))-1048576;
+            }
+            else
+            {
+                buf[ii] = (int32_t)(fifo_data_buf[ii*3]|(fifo_data_buf[ii*3+1]<<8)|((fifo_data_buf[ii*3+2]&0x1f)<<16));
+            }
+        }
+        //HX3918_LOG("%d/%d, %d %d\r\n", ii+1,fifo_read_length,buf[ii],(fifo_data_buf[ii*3+2]>>5)&0x03);
+    }
+    data_flg_start = (fifo_data_buf[2]>>5)&0x03;
+    data_flg_end = (fifo_data_buf[fifo_read_bytes-1]>>5)&0x03;
+    fifo_out_length = fifo_read_length;
+    if(data_flg_start>0)
+    {
+        fifo_out_length = fifo_read_length-phase_num+data_flg_start;
+        for(ii=0; ii<fifo_out_length; ii++)
+        {
+            buf[ii] = buf[ii+phase_num-data_flg_start];
+        }
+        for(ii=fifo_out_length; ii<fifo_read_length; ii++)
+        {
+            buf[ii] = 0;
+        }
+    }
+    if(data_flg_end<phase_num-1)
+    {
+        for(ii=fifo_out_length; ii<fifo_out_length+phase_num-data_flg_end-1; ii++)
+            hx3918_brust_read_reg(0x41, databuf, 3);// ericy 230529
+        buf[ii] = (int32_t)(databuf[0]|(databuf[1]<<8)|((databuf[2]&0x1f)<<16));
+    }
+//             for(ii=0; ii<fifo_out_length; ii++)
+//             {
+//                     HX3918_LOG("%d/%d, %d\r\n", ii+1,fifo_out_length,buf[ii]);
+//             }
+    fifo_out_length = fifo_out_length+phase_num-data_flg_end-1;
+    fifo_out_count = fifo_out_length/phase_num;
+    if(data_len==64)
+    {
+        uint8_t reg_0x2d = hx3918_read_reg(0x3d);// ericy 230529
+        hx3918_write_reg(0x3d,0x00);// ericy 230529
+        hx3918_delay(5);
+        hx3918_write_reg(0x3d,reg_0x2d);// ericy 230529
+        read_fifo_first_flg = 1;
+    }
+    return fifo_out_count;
+}
+
+void read_data_packet(int32_t *ps_data)  // 3918
+{
+    uint8_t  databuf1[6] = {0};
+    uint8_t  databuf2[6] = {0};
+    hx3918_brust_read_reg(0x02, databuf1, 6);
+    hx3918_brust_read_reg(0x08, databuf2, 6);
+
+    ps_data[0] = ((databuf1[0]) | (databuf1[1] << 8) | (databuf1[2] << 16));
+    ps_data[1] = ((databuf1[3]) | (databuf1[4] << 8) | (databuf1[5] << 16));
+    ps_data[2] = ((databuf2[0]) | (databuf2[1] << 8) | (databuf2[2] << 16));
+    ps_data[3] = ((databuf2[3]) | (databuf2[4] << 8) | (databuf2[5] << 16));
+    HX3918_LOG(" %d %d %d %d \r\n",  ps_data[0], ps_data[1], ps_data[2], ps_data[3]);
+}
+
+
+
+void hx3918_vin_check(uint16_t led_vin)
+{
+    low_vbat_flag = 0;
+    if(led_vin < 3700)
+    {
+        low_vbat_flag = 1;
+    }
+}
+
+void hx3918_ppg_off(void)
+{
+    hx3918_write_reg(0x2a, 0x00);
+    hx3918_write_reg(0x2b, 0x00);
+    hx3918_write_reg(0x16, 0x00);
+    hx3918_write_reg(0x01, 0x01);
+}
+
+void hx3918_ppg_on(void)
+{
+    hx3918_write_reg(0x01, 0x00);
+    hx3918_delay(5);
+}
+
+void hx3918_data_reset(void)
+{
+#if defined(TIMMER_MODE)
+    hx3918_ppg_timer_cfg(false);
+    hx3918_agc_timer_cfg(false);
+#elif defined(INT_MODE)
+    hx3918_gpioint_cfg(false);
+#endif
+#if defined(HRS_ALG_LIB)
+    hx3918_hrs_data_reset();
+#endif
+#if defined(SPO2_ALG_LIB)
+    hx3918_spo2_data_reset();
+#endif
+#if defined(HRV_ALG_LIB)
+    hx3918_hrv_data_reset();
+#endif
+    HX3918_LOG("hx3918 data reset!\r\n");
+}
+
+void Efuse_Mode_Check(void)
+{
+    uint8_t  REG_45_E, REG_46_E, REG_47_E, REG_48_E;
+
+    hx3918_write_reg(0x4b, 0x10);
+    hx3918_write_reg(0x4d, 0x18);
+    hx3918_write_reg(0x4e, 0x40);
+    hx3918_write_reg(0x4C, 0x04);
+    hx3918_write_reg(0x4C, 0x00);
+
+    REG_45_E = hx3918_read_reg(0x45);
+    REG_46_E = hx3918_read_reg(0x46);
+    REG_47_E = hx3918_read_reg(0x47);
+    REG_48_E = hx3918_read_reg(0x48);
+
+    hx3918_write_reg(0X4B,0x20);
+    hx3918_write_reg(0x45,REG_45_E);
+    hx3918_write_reg(0x46,REG_46_E);
+    hx3918_write_reg(0x47,REG_47_E);
+    hx3918_write_reg(0x48,REG_48_E);
+    hx3918_write_reg(0X4B,0x00);
+    
+    hx3918_write_reg(0x4d, 0x20);
+    hx3918_write_reg(0x4e, 0x00);
+    hx3918_write_reg(0x4C, 0x00);
+     
+}
+
+bool hx3918_init(WORK_MODE_T mode)
+{
+    HX3918_LOG("hx3918_init:mode:%d\n",mode);
+    work_mode_flag = mode;
+    hx3918_data_reset();
+    hx3918_vin_check(3800);
+    hx3918_ppg_on();
+    Efuse_Mode_Check();
+    switch (work_mode_flag)
+    {
+    case HRS_MODE:
+        tyhx_hrs_set_living(0,0,0); //  qu=15  std=30
+        if(hx3918_hrs_enable()== SENSOR_OP_FAILED)
+        {
+            return false;
+        }
+        break;
+
+    case LIVING_MODE:
+#ifdef CHECK_LIVING_LIB
+        if(hx3918_hrs_enable()== SENSOR_OP_FAILED)
+        {
+            return false;
+        }
+#endif
+        break;
+
+    case SPO2_MODE:
+#ifdef SPO2_DATA_CALI
+        hx3918_spo2_data_cali_init();
+#endif
+#ifdef SPO2_ALG_LIB
+        tyhx_spo2_para_usuallyadjust(SPO2_LOW_XCORR_THRE,SPO2_LOW_SNR_THRE,COUNT_BLOCK_NUM,SPO2_BASE_LINE_INIT,SPO2_SLOPE,SPO2_GSEN_POW_THRE);
+        tyhx_spo2_para_barelychange(MEAN_NUM,SOP2_DEGLITCH_THRE,SPO2_REMOVE_JUMP_THRE,SPO2_LOW_CLIP_END_TIME,SPO2_LOW_CLIP_DN, \
+                                    SPO2_NORMAL_CLIP_DN,IR_AC_TOUCH_THRE,IR_FFT_POW_THRE,SPO2_CALI,SLOPE_PARA_MAX,SLOPE_PARA_MIN);
+        if(hx3918_spo2_enable()== SENSOR_OP_FAILED)
+        {
+            return false;
+        }
+#endif
+        break;
+
+    case HRV_MODE:
+#ifdef HRV_ALG_LIB
+        if(hx3918_hrv_enable()== SENSOR_OP_FAILED)
+        {
+            return false;
+        }
+
+        break;
+#endif
+    case WEAR_MODE:
+#ifdef CHECK_TOUCH_LIB
+
+        if(hx3918_check_touch_enable()== SENSOR_OP_FAILED)
+        {
+            return false;
+        }
+#endif
+        break;
+
+    case FT_LEAK_LIGHT_MODE:
+        hx3918_hrs_disable();
+        HX3918_LOG("FT_LEAK_LIGHT_MODE1\n");
+        if (!hx3918_chip_check())
+        {
+            AGC_LOG("hx3918 check id failed!\r\n");
+            return false;
+        }
+        HX3918_LOG("FT_LEAK_LIGHT_MODE2\n");
+        hx3918_factroy_test(LEAK_LIGHT_TEST);
+        break;
+
+    case FT_GRAY_CARD_MODE:
+        hx3918_factroy_test(GRAY_CARD_TEST);
+        break;
+
+    case FT_INT_TEST_MODE:
+        hx3918_factroy_test(FT_INT_TEST);
+//                       hx3918_gpioint_cfg(true);
+        break;
+
+    case LAB_TEST_MODE:
+#ifdef LAB_TEST
+        if(hx3918_lab_test_enable()== SENSOR_OP_FAILED)
+        {
+            return false;
+        }
+#endif
+        break;
+
+    default:
+        break;
+    }
+
+    return true;
+}
+
+void hx3918_agc_Int_handle(void)
+{
+
+    switch (work_mode_flag)
+    {
+    case HRS_MODE:
+    {
+#ifdef HRS_ALG_LIB
+        HRS_CAL_SET_T cal;
+        cal = PPG_hrs_agc();
+        if(cal.work)
+        {
+            //AGC_LOG("AGC: led_drv=%d,ledDac=%d,ambDac=%d,ledstep=%d,rf=%d\r\n", \
+            cal.led_cur, cal.led_idac, cal.amb_idac,cal.led_step,cal.ontime);
+        }
+#endif
+        break;
+    }
+    case LIVING_MODE:
+    {
+#ifdef HRS_ALG_LIB
+        HRS_CAL_SET_T cal;
+        cal = PPG_hrs_agc();
+        if(cal.work)
+        {
+            //HX3918_LOG("AGC: led_drv=%d,ledDac=%d,ambDac=%d,ledstep=%d,rf=%d\r\n", \
+            cal.led_cur, cal.led_idac, cal.amb_idac,cal.led_step,cal.ontime);
+        }
+#endif
+        break;
+    }
+    case HRV_MODE:
+    {
+#ifdef HRV_ALG_LIB
+        HRV_CAL_SET_T cal;
+        cal = PPG_hrv_agc();
+        if(cal.work)
+        {
+            //AGC_LOG("AGC: led_drv=%d,ledDac=%d,ambDac=%d,ledstep=%d,rf=%d\r\n", \
+            cal.led_cur, cal.led_idac, cal.amb_idac,cal.led_step,cal.ontime);
+        }
+#endif
+        break;
+    }
+    case SPO2_MODE:
+    {
+#ifdef SPO2_ALG_LIB
+        SPO2_CAL_SET_T cal;
+        cal = PPG_spo2_agc();
+        if(cal.work)
+        {
+            //AGC_LOG("INT_AGC: Rled_drv=%d,Irled_drv=%d,RledDac=%d,IrledDac=%d,ambDac=%d,Rledstep=%d,Irledstep=%d,Rrf=%d,Irrf=%d,\r\n",\
+            cal.red_cur, cal.ir_cur,cal.red_idac,cal.ir_idac,cal.amb_idac,cal.red_led_step,cal.red_led_step,cal.ontime,cal.state);
+        }
+#endif
+        break;
+    }
+    case LAB_TEST_MODE:
+#ifdef LAB_TEST
+        hx3918_lab_test_Int_handle();
+#endif
+    default:
+        break;
+    }
+}
+void hx3918_gesensor_Int_handle(void)
+{
+    //readFifoByHrsModule();
+#ifdef GSENSER_DATA
+    // uint8_t ii = 0;
+    // AxesRaw_t gsen_buf;
+    // if(work_mode_flag == WEAR_MODE)
+    // {
+    //     return;
+    // }
+
+    // //LIS3DH_GetAccAxesRaw(&gsen_buf);
+
+    // for(ii=0; ii<9; ii++)
+    // {
+    //     gsen_fifo_x[ii] = gsen_fifo_x[ii+1];
+    //     gsen_fifo_y[ii] = gsen_fifo_y[ii+1];
+    //     gsen_fifo_z[ii] = gsen_fifo_z[ii+1];
+    // }
+    //     gsen_fifo_x[9] = gsen_buf.AXIS_X>>1;
+    //     gsen_fifo_y[9] = gsen_buf.AXIS_Y>>1;
+    //     gsen_fifo_z[9] = gsen_buf.AXIS_Z>>1;
+    // //SEGGER_RTT_printf(0,"gsen_x=%d gsen_y=%d gsen_z=%d\r\n", \
+    // gsen_fifo_x[9],gsen_fifo_y[9],gsen_fifo_z[9]);
+#endif
+}
+// volatile int16_t gsen_fifo_x[32];  //ppg time 330ms..330/40 = 8.25
+// volatile int16_t gsen_fifo_y[32];
+// volatile int16_t gsen_fifo_z[32];
+void hx3918_set_gsen_fifo(short *x,short *y,short *z, int count)
+{
+    
+    if(count > sizeof(gsen_fifo_y))
+    {
+        count = sizeof(gsen_fifo_y);
+    }
+    for(int i = 0;i<count;i++)
+    {
+
+        gsen_fifo_x[i] =x[i];
+        gsen_fifo_y[i] =y[i];
+        gsen_fifo_z[i] =z[i]; 
+        //HX3918_LOG("count: %d %03d gsen_fifo_x:%d gsen_fifo_y:%d gsen_fifo_z:%d\n",count,i,gsen_fifo_x[i],gsen_fifo_y[i],gsen_fifo_z[i]);
+    }
+    gsen_fifo_count = count;
+}
+void hx3918_get_gsen_fifo(short *x, short *y,short *z,int count)
+{
+    int16_t gsen_fifo_x_tmp[32]= {0};
+    int16_t gsen_fifo_y_tmp[32]= {0};
+    int16_t gsen_fifo_z_tmp[32]= {0};
+    
+    if(gsen_fifo_count > sizeof(gsen_fifo_x_tmp))
+        gsen_fifo_count = sizeof(gsen_fifo_x_tmp);
+    for(int i = 0;i<gsen_fifo_count;i++)//备份
+    {
+        gsen_fifo_x_tmp[i] = gsen_fifo_x[i] ;
+        gsen_fifo_y_tmp[i] = gsen_fifo_y[i];
+        gsen_fifo_z_tmp[i] = gsen_fifo_z[i]; 
+    }
+    if(count > sizeof(gsen_fifo_y))
+        count = sizeof(gsen_fifo_y);
+    
+    for(int i = 0;i<count;i++)//复制
+    {
+        if(i<gsen_fifo_count)
+        {
+            x[i] = gsen_fifo_x[i];
+            y[i] = gsen_fifo_y[i];
+            z[i] = gsen_fifo_z[i];
+        }else
+        {
+            x[i] = gsen_fifo_x[gsen_fifo_count-1];
+            y[i] = gsen_fifo_y[gsen_fifo_count-1];
+            z[i] = gsen_fifo_z[gsen_fifo_count-1];
+        }
+         
+    }
+    if(gsen_fifo_count > count)//移位
+    {
+        for(int i = 0;i<gsen_fifo_count-count;i++)
+        {
+            gsen_fifo_x[i] = gsen_fifo_x_tmp[count+i];
+            gsen_fifo_y[i] = gsen_fifo_y_tmp[count+i];
+            gsen_fifo_z[i] = gsen_fifo_z_tmp[count+i];
+        }
+        gsen_fifo_count -= count;
+    }
+    
+}
+void agc_timeout_handler(void * p_context)
+{
+#ifdef TIMMER_MODE
+    switch (work_mode_flag)
+    {
+    case HRS_MODE:
+    {
+#ifdef HRS_ALG_LIB
+    HRS_CAL_SET_T cal;
+    cal = PPG_hrs_agc();
+    if(cal.work)
+    {
+        //AGC_LOG("AGC: led_drv=%d,ledDac=%d,ambDac=%d,ledstep=%d,rf=%d\r\n", \
+        cal.led_cur, cal.led_idac, cal.amb_idac,cal.led_step,cal.ontime);
+        }
+#endif
+        break;
+    }
+    case LIVING_MODE:
+    {
+#ifdef HRS_ALG_LIB
+    HRS_CAL_SET_T cal;
+    cal = PPG_hrs_agc();
+    if(cal.work)
+    {
+        //AGC_LOG("AGC: led_drv=%d,ledDac=%d,ambDac=%d,ledstep=%d,rf=%d\r\n", \
+        cal.led_cur, cal.led_idac, cal.amb_idac,cal.led_step,cal.ontime);
+    }
+#endif
+        break;
+    }
+    case HRV_MODE:
+    {
+#ifdef HRV_ALG_LIB
+    HRV_CAL_SET_T cal;
+    cal = PPG_hrv_agc();
+    if(cal.work)
+    {
+        //AGC_LOG("AGC: led_drv=%d,ledDac=%d,ambDac=%d,ledstep=%d,rf=%d\r\n", \
+        cal.led_cur, cal.led_idac, cal.amb_idac,cal.led_step,cal.ontime);
+    }
+#endif
+        break;
+    }
+    case SPO2_MODE:
+    {
+#ifdef SPO2_ALG_LIB
+    SPO2_CAL_SET_T cal;
+    cal = PPG_spo2_agc();
+    if(cal.work)
+    {
+        //AGC_LOG("AGC: Rled_drv=%d,Irled_drv=%d,RledDac=%d,IrledDac=%d,ambDac=%d,Rledstep=%d,Irledstep=%d,Rrf=%d,Irrf=%d,\r\n", \
+        cal.red_cur, cal.ir_cur,cal.red_idac,cal.ir_idac,cal.amb_idac,cal.red_led_step,cal.red_led_step,cal.ontime,cal.state);
+    }
+#endif
+        break;
+    }
+    case LAB_TEST_MODE:
+    {
+#ifdef LAB_TEST
+        hx3918_lab_test_Int_handle();
+#endif
+    }
+    default:
+        break;
+    }
+#endif
+}
+
+//void ppg_timeout_handler(void * p_context)
+void heart_rate_meas_timeout_handler(void * p_context)
+{
+       hx3918_ppg_Int_handle();
+}
+
+void hx3918_ppg_Int_handle(void)
+{
+    #if defined(INT_MODE)
+        hx3918_agc_Int_handle();
+    #endif
+        //HX3918_LOG("hx3918_ppg_Int_handle\n\n\n\n");
+#ifdef SAR_ALG_LIB
+               hx3918_report_prox_status();
+#endif
+        switch(work_mode_flag)
+        {
+        case HRS_MODE:
+    #ifdef HRS_ALG_LIB
+            hx3918_hrs_ppg_Int_handle();
+    #endif
+            break;
+
+        case SPO2_MODE:
+    #ifdef SPO2_ALG_LIB
+            hx3918_spo2_ppg_Int_handle();
+    #endif
+            break;
+
+        case HRV_MODE:
+    #ifdef HRV_ALG_LIB
+            hx3918_hrv_ppg_Int_handle();
+    #endif
+            break;
+
+        case WEAR_MODE:
+    #ifdef CHECK_TOUCH_LIB
+            hx3918_wear_ppg_Int_handle();
+    #endif
+            break;
+
+        case LAB_TEST_MODE:
+    #ifdef LAB_TEST
+            hx3918_lab_test_Int_handle();
+    #endif
+
+        default:
+            break;
+  }
+
+}
+
+#ifdef HRS_ALG_LIB
+void hx3918_hrs_ppg_Int_handle(void)
+{
+    uint8_t        ii=0;
+    hrs_results_t alg_results = {MSG_HRS_ALG_NOT_OPEN,0,0,0,0};
+    hx3918_hrs_wear_msg_code_t hrs_wear_status = MSG_HRS_INIT;
+    int32_t *PPG_buf = &(ppg_s_dat.green_data[0]);
+    int32_t *ir_buf = &(ppg_s_dat.ir_data[0]);
+    uint8_t *count = &(ppg_s_dat.count);
+    int16_t gsen_fifo_x_send[32]= {0};
+    int16_t gsen_fifo_y_send[32]= {0};
+    int16_t gsen_fifo_z_send[32]= {0};
+    HRS_CAL_SET_T cal= get_hrs_agc_status();
+#ifdef BP_CUSTDOWN_ALG_LIB
+    bp_results_t    bp_alg_results ;
+#endif
+#ifdef HR_VECTOR
+    for(ii=0; ii<8; ii++)
+    {
+        PPG_buf_vec[ii] = hrm_input_data[hrs_send_cnt+ii];
+        gsen_fifo_x[ii] = gsen_input_data_x[hrs_send_cnt+ii];
+        gsen_fifo_y[ii] = gsen_input_data_y[hrs_send_cnt+ii];
+        gsen_fifo_z[ii] = gsen_input_data_z[hrs_send_cnt+ii];
+    }
+    hrs_send_cnt = hrs_send_cnt+8;
+    *count = 8;
+    tyhx_hrs_alg_send_data(PPG_buf_vec,*count, 0, gsen_fifo_x, gsen_fifo_y, gsen_fifo_z);
+#else
+    if(hx3918_hrs_read(&ppg_s_dat) == NULL)
+    {
+        return;
+    }
+#ifndef GSEN_40MS_TIMMER
+    readFifoByHrsModule();
+#endif
+    hx3918_get_gsen_fifo(gsen_fifo_x_send,gsen_fifo_y_send,gsen_fifo_z_send,*count);
+    for(ii=0; ii<*count; ii++)
+    {
+#ifdef GSENSER_DATA
+        // gsen_fifo_x_send[ii] = gsen_fifo_x[32-*count+ii];
+        // gsen_fifo_y_send[ii] = gsen_fifo_y[32-*count+ii];
+        // gsen_fifo_z_send[ii] = gsen_fifo_z[32-*count+ii];
+        
+#endif
+        //HX3918_LOG("ppg_Int_handle_da:%d %d %d %d %d %d \r\n", PPG_buf[ii],ir_buf[ii],gsen_fifo_x_send[ii],gsen_fifo_y_send[ii],gsen_fifo_z_send[ii],cal.led_cur);
+    }
+    hrs_wear_status = hx3918_hrs_get_wear_status();
+       hrsresult.wearstatus = hrs_wear_status;
+    HX3918_result_set_wear_status(hrs_wear_status);
+    
+    if(hrs_wear_status == MSG_HRS_WEAR)
+    {
+        tyhx_hrs_alg_send_data(PPG_buf, *count, gsen_fifo_x_send, gsen_fifo_y_send, gsen_fifo_z_send);
+    }
+#endif
+    alg_results = tyhx_hrs_alg_get_results();
+    hrsresult.lastesthrs = alg_results.hr_result;
+    HX3918_result_set_heart_rate(hrsresult.lastesthrs);
+  // HX3918_LOG("Hr=%d",alg_results.hr_result);
+#ifdef HRS_BLE_APP
+    {
+        rawdata_vector_t rawdata;
+        for(ii=0; ii<*count; ii++)
+        {
+            rawdata.vector_flag = HRS_VECTOR_FLAG;
+            rawdata.data_cnt = alg_results.data_cnt-*count+ii;
+            rawdata.hr_result = alg_results.hr_result;
+            rawdata.red_raw_data = PPG_buf[ii];
+            rawdata.ir_raw_data = gdiff[0];
+            rawdata.gsensor_x = gsen_fifo_x[ii];
+            rawdata.gsensor_y = gsen_fifo_y[ii];
+            rawdata.gsensor_z = gsen_fifo_z[ii];
+            rawdata.red_cur = cal.led_cur;
+            rawdata.ir_cur = alg_results.hrs_alg_status;
+
+            ble_rawdata_vector_push(rawdata);
+        }
+    }
+    ble_rawdata_send_handler();
+#endif
+}
+
+#ifdef CHECK_LIVING_LIB
+void hx3918_living_Int_handle(void)
+{
+
+    uint8_t        ii=0;
+    hx3918_living_results_t living_alg_results = {MSG_LIVING_NO_WEAR,0,0,0};
+
+    int32_t *PPG_buf = &(ppg_s_dat.green_data[0]);
+    uint8_t *count = &(ppg_s_dat.count);
+    hx3918_hrs_wear_msg_code_t     hrs_wear_status = MSG_HRS_NO_WEAR;
+    int16_t    gsen_fifo_x_send[32]= {0};
+    int16_t    gsen_fifo_y_send[32]= {0};
+    int16_t    gsen_fifo_z_send[32]= {0};
+
+    if(hx3918_hrs_read(&ppg_s_dat) == NULL)
+    {
+        return;
+    }
+#ifndef GSEN_40MS_TIMMER
+    readFifoByHrsModule();
+#endif
+    for(ii=0; ii<*count; ii++)
+    {
+        gsen_fifo_x_send[ii] = gsen_fifo_x[32-*count+ii];
+        gsen_fifo_y_send[ii] = gsen_fifo_y[32-*count+ii];
+        gsen_fifo_z_send[ii] = gsen_fifo_z[32-*count+ii];
+        //HX3918_LOG("%d/%d %d %d %d %d %d %d\r\n",1+ii,*count,PPG_buf[ii],ir_buf[ii],gsen_fifo_x[ii],gsen_fisignal_qualityfo_y[ii],gsen_fifo_z[ii],hrs_s_dat.agc_green);
+    }
+
+    living_alg_results = hx3918_living_get_results();
+    //HX3918_LOG("%d %d %d %d\r\n",living_alg_results.data_cnt,living_alg_results.motion_status,living_alg_results.signal_quality,living_alg_results.wear_status);
+
+}
+#endif
+
+
+#ifdef SPO2_ALG_LIB
+void hx3918_spo2_ppg_Int_handle(void)
+{
+    uint8_t        ii=0;
+    spo2_results_t alg_results = {MSG_SPO2_ALG_NOT_OPEN,MSG_SPO2_LIVING_INITIAL,0,0,0,0,0,0,1,0,0,0,0};
+    SPO2_CAL_SET_T cal=get_spo2_agc_status();
+    hx3918_spo2_wear_msg_code_t spo2_wear_status = MSG_SPO2_INIT;
+    int32_t *green_buf = &(ppg_s_dat.green_data[0]);
+    int32_t *red_buf = &(ppg_s_dat.red_data[0]);
+    int32_t *ir_buf = &(ppg_s_dat.ir_data[0]);
+    uint8_t *count = &(ppg_s_dat.count);
+    int16_t gsen_fifo_x_send[32]= {0};
+    int16_t gsen_fifo_y_send[32]= {0};
+    int16_t gsen_fifo_z_send[32]= {0};
+#ifdef SPO2_DATA_CALI
+    int32_t red_data_cali, ir_data_cali;
+#endif
+
+#ifdef SPO2_VECTOR
+    for(ii=0; ii<8; ii++)
+    {
+        red_buf_vec[ii] = vec_red_data[spo2_send_cnt+ii];
+        ir_buf_vec[ii] = vec_ir_data[spo2_send_cnt+ii];
+        green_buf_vec[ii] = vec_green_data[spo2_send_cnt+ii];
+    }
+    spo2_send_cnt = spo2_send_cnt+8;
+    *count = 8;
+    for(ii=0; ii<10; ii++)
+    {
+        gsen_fifo_x[ii] = vec_red_data[spo2_send_cnt1+ii];;
+        gsen_fifo_y[ii] = vec_ir_data[spo2_send_cnt1+ii];;
+        gsen_fifo_z[ii] = vec_green_data[spo2_send_cnt1+ii];;
+    }
+    spo2_send_cnt1 = spo2_send_cnt1+10;
+    hx3918_spo2_alg_send_data(red_buf_vec, ir_buf_vec, green_buf_vec, *count, gsen_fifo_x, gsen_fifo_y, gsen_fifo_z);
+#else
+    if(hx3918_spo2_read(&ppg_s_dat) == NULL)
+    {
+        return;
+    }
+#ifndef GSEN_40MS_TIMMER
+    readFifoByHrsModule();
+#endif
+    for(ii=0; ii<*count; ii++)
+    {
+         HX3918_LOG("spo2_data : %d/%d %d %d %d %d %d %d %d\r\n" ,1+ii,*count,\
+           red_buf[ii],ir_buf[ii],green_buf[ii],cal.red_idac,cal.ir_idac,cal.red_cur,cal.ir_cur);
+    }
+    spo2_wear_status = hx3918_spo2_get_wear_status();    
+       hrsresult.wearstatus = spo2_wear_status;
+    HX3918_result_set_wear_status(spo2_wear_status);
+    if(spo2_wear_status == MSG_SPO2_WEAR)
+    {
+      if(*count){
+        tyhx_spo2_alg_send_data(red_buf, ir_buf, green_buf, cal.red_idac, cal.ir_idac, cal.green_idac, gsen_fifo_x_send, gsen_fifo_y_send, gsen_fifo_z_send, *count);
+        }
+    }
+#endif
+
+       alg_results = tyhx_spo2_alg_get_results();
+       hrsresult.lastestspo2 = alg_results.spo2_result;
+       HX3918_result_set_blood_oxygen(hrsresult.lastestspo2);
+       HX3918_LOG("SPO2=%d\r\n",alg_results.spo2_result);
+
+#ifdef HRS_BLE_APP
+    {
+        rawdata_vector_t rawdata;
+        for(ii=0; ii<*count; ii++)
+        {
+#ifdef SPO2_DATA_CALI
+            ir_data_cali = hx3918_ir_data_cali(ir_buf[ii]);
+            red_data_cali = hx3918_red_data_cali(red_buf[ii]);
+            rawdata.red_raw_data = red_data_cali;
+            rawdata.ir_raw_data = ir_data_cali;
+#else
+            rawdata.red_raw_data = red_buf[ii];
+            rawdata.ir_raw_data = ir_buf[ii];
+#endif
+            rawdata.vector_flag = SPO2_VECTOR_FLAG;
+            //rawdata.data_cnt = alg_results.data_cnt-*count+ii;
+            rawdata.data_cnt = cal.green_idac;
+            rawdata.hr_result = alg_results.spo2_result;
+//            rawdata.gsensor_x = gsen_fifo_x[ii];
+//            rawdata.gsensor_y = gsen_fifo_y[ii];
+//            rawdata.gsensor_z = gsen_fifo_z[ii];
+            rawdata.gsensor_x = green_buf[ii]>>5;
+            rawdata.gsensor_y = cal.red_idac;
+            rawdata.gsensor_z = cal.ir_idac;
+            rawdata.red_cur = cal.red_cur;
+            rawdata.ir_cur = cal.ir_cur;
+            ble_rawdata_vector_push(rawdata);
+        }
+    }
+    ble_rawdata_send_handler();
+#endif
+}
+#endif
+
+#ifdef HRV_ALG_LIB
+hrv_sensor_data_t hrv_s_dat;
+void hx3918_hrv_ppg_Int_handle(void)
+{
+    uint8_t        ii=0;
+    hrv_results_t alg_hrv_results= {MSG_HRV_ALG_NOT_OPEN,0,0,0,0,0};
+    int32_t *PPG_buf = &(hrv_s_dat.ppg_data[0]);
+    uint8_t *count = &(hrv_s_dat.count);
+    hx3918_hrv_wear_msg_code_t wear_mode;
+
+#ifdef HRV_TESTVEC
+    int32_t hrm_raw_data;
+    hrm_raw_data = vec_data[vec_data_cnt];
+    vec_data_cnt++;
+    alg_hrv_results = hx3918_hrv_alg_send_data(hrm_raw_data, 0, 0);
+#else
+    if(hx3918_hrv_read(&hrv_s_dat) == NULL)
+    {
+        return;
+    }
+    for(ii=0; ii<*count; ii++)
+    {
+        //HX3918_LOG("[Hrv_Test]:%d/%d %d\r\n" ,1+ii,*count,PPG_buf[ii]);
+    }
+    wear_mode = hx3918_hrv_get_wear_status();
+    //HX3918_result_set_wear_status(wear_mode);
+       //hrsresult.wearstatus = wear_mode;
+    if(wear_mode==MSG_HRV_WEAR)
+    {
+        alg_hrv_results = tyhx_hrv_alg_send_bufdata(PPG_buf, *count, gen_dummy, gen_dummy,gen_dummy);
+        //hrsresult.lastesthrv = alg_hrv_results .hrv_result;
+        HX3918_result_set_hrv(alg_hrv_results.hrv_result);
+        HX3918_LOG("Hrv result:= %d\r\n",alg_hrv_results.hrv_result);
+    }
+#endif
+
+#ifdef HRS_BLE_APP
+    {
+        rawdata_vector_t rawdata;
+
+        HRS_CAL_SET_T cal= get_hrs_agc_status();
+        for(ii=0; ii<*count; ii++)
+        {
+            rawdata.vector_flag = HRS_VECTOR_FLAG;
+            rawdata.data_cnt = 0;
+            rawdata.hr_result = alg_hrv_results.hrv_result;
+            rawdata.red_raw_data = PPG_buf[ii];
+            rawdata.ir_raw_data = 0;
+            rawdata.gsensor_x = gsen_fifo_x[ii];
+            rawdata.gsensor_y = gsen_fifo_y[ii];
+            rawdata.gsensor_z = gsen_fifo_z[ii];
+            rawdata.red_cur = cal.led_cur;
+            rawdata.ir_cur = 0;
+            ble_rawdata_vector_push(rawdata);
+        }
+    }
+    ble_rawdata_send_handler();
+#endif
+}
+#endif
+
+
+#ifdef CHECK_TOUCH_LIB
+uint8_t hx3918_get_wear_ppg_Int_handle(void)
+{
+    uint8_t count = 0;
+    hx3918_wear_msg_code_t hx3918_check_mode_status = MSG_NO_WEAR;
+    count = hx3918_check_touch_read(&ppg_s_dat);
+    hx3918_check_mode_status = hx3918_check_touch(ppg_s_dat.s_buf,count);
+    hrsresult.wearstatus = hx3918_check_mode_status;
+    HX3918_LOG("wearstatus:%d\n",hrsresult.wearstatus);
+    if((count)&&(hrsresult.wearstatus == 0))
+    {
+        HX3918_LOG("count = %d, ir = %d\r\n",count,ppg_s_dat.s_buf[count-1]);
+        return 0;
+    }else
+        return 1;
+}
+void hx3918_wear_ppg_Int_handle(void)
+{
+    uint8_t count = 0;
+    uint8_t ii = 0;
+    hx3918_wear_msg_code_t hx3918_check_mode_status = MSG_NO_WEAR;
+    count = hx3918_check_touch_read(&ppg_s_dat);
+    hx3918_check_mode_status = hx3918_check_touch(ppg_s_dat.s_buf,count);
+    hrsresult.wearstatus = hx3918_check_mode_status;
+    if((count)&&(hrsresult.wearstatus == 0))
+    {
+        //HX3918_LOG("count = %d, ir = %d\r\n",count,ppg_s_dat.s_buf[count-1]);
+        //hx3918_auto_cali_backgroud(ppg_s_dat.s_buf[count-1]);
+               
+    }
+       //hx3918_ai_tune_nv(lp[0],bl[0]);
+    //HX3918_LOG("[hx3918_wear_ppg_Int_handle] ir result = %d, final result = %d\r\n",hx3918_check_mode_status,wear_result_by_IRandProx);
+#ifdef HRS_BLE_APP
+    {
+        rawdata_vector_t rawdata;
+        //for(ii=0; ii<*count; ii++)
+        //app_ctrl_test = true;
+        {
+            rawdata.vector_flag = HRS_VECTOR_FLAG;
+            rawdata.data_cnt = 0;
+            rawdata.hr_result = 0;
+            rawdata.red_raw_data = 0;
+            rawdata.ir_raw_data = lp[0];
+            rawdata.gsensor_x = bl[0];
+            rawdata.gsensor_y = gdiff[1];
+            rawdata.gsensor_z = nv_base_data[0];
+            rawdata.red_cur = ai_tune_cnt[0];
+            rawdata.ir_cur = ai_tune_cnt[1];
+
+            ble_rawdata_vector_push(rawdata);
+        }
+    }
+    ble_rawdata_send_handler();
+#endif
+
+}
+#endif
+
+
+void hx3918_lab_test_Int_handle(void)
+{
+#ifdef LAB_TEST
+#if defined(TIMMER_MODE)
+    uint32_t data_buf[4];
+    hx3918_lab_test_read_packet(data_buf);
+    //HX3918_LOG("%d %d %d %d\r\n", data_buf[0], data_buf[1], data_buf[2], data_buf[3]);
+#else
+    uint8_t count = 0;
+    int32_t buf[32];
+    count = hx3918_read_fifo_data(buf, 2, 1);
+    for (uint8_t i=0; i<count; i++)
+    {
+        //HX3918_LOG("%d/%d %d %d\r\n" ,1+i,count,buf[i*2],buf[i*2+1]);
+    }
+#endif
+#endif
+}
+#endif //CHIP_HX3918
+#endif //USE_HX3918
diff --git a/2.sdk/sdk/gui/lv_drivers/indev/HX3918/hx3918.h b/2.sdk/sdk/gui/lv_drivers/indev/HX3918/hx3918.h
new file mode 100644 (file)
index 0000000..81e1096
--- /dev/null
@@ -0,0 +1,363 @@
+#ifndef _hx3918_H_
+#define _hx3918_H_
+#include <stdint.h>
+#include <stdbool.h>
+
+#define HX3918_DEBUG  1
+#if HX3918_DEBUG == 1
+#define HX3918_LOG(msg, ...)      printf( msg, ##__VA_ARGS__)//cplog_printf( msg, ##__VA_ARGS__)
+#else
+#define HX3918_LOG(msg, ...)  
+#endif
+//#include "tyhx_mems.h"
+//#define DEBUG_PPG_ONLY     // 只用IR 判断佩带和非佩戴, 靠近感应功能关闭,  但是HX3918_PROX.C要合入编译
+/********************* alg_swi *********************
+HRS_ALG_LIB   心率功能
+SPO2_ALG_LIB  血氧功能
+HRV_ALG_LIB   HRV功能
+CHECK_TOUCH_LIB   纯佩戴功能(非心率血氧模式)
+CHECK_LIVING_LIB  纯物体识别功能(非心率血氧模式)
+BP_CUSTDOWN_ALG_LIB  血压功能
+
+TIMMER_MODE  定时器模式, 读PPG数据, 默认采用定时器模式
+INT_MODE     中断模式,读PPG数据
+
+DEMO_MI      demo相关配置, 客户关闭, 在下面else里进行配置
+HRS_BLE_APP  DEMO蓝牙控制宏, 客户关闭
+SPO2_DATA_CALI   血氧DC补偿模式, 客户关闭
+HRS_DEBUG    调试宏, 根据平台定义打印函数
+AGC_DEBUG    调试宏, 根据平台定义打印函数
+GSEN_40MS_TIMMER   DEMO调试使用, 客户关闭
+NEW_GSEN_SCHME     DEMO调试使用, 客户关闭
+*/
+#define HRS_ALG_LIB
+#define SPO2_ALG_LIB
+//#define HRV_ALG_LIB
+#define CHECK_TOUCH_LIB
+//#define CHECK_LIVING_LIB
+#define SAR_ALG_LIB
+#define BP_CUSTDOWN_ALG_LIB
+
+
+
+//**************** read_data_mode ******************//
+#define TIMMER_MODE           //timmer read fifo
+//#define INT_MODE                                                     //fifo_all_most_full
+//#define TYHX_DEMO           // for ty demo
+//****************** gsen_cgf *********************//
+#define GSENSER_DATA
+#define GSEN_40MS_TIMMER
+#define NEW_GSEN_SCHME
+
+//****************** other_cgf ********************//
+#define EVB
+//#define TWON3IN1LED
+//#define EVB
+//#define INT_FLOATING
+//#define HRS_BLE_APP
+//#define SPO2_DATA_CALI
+
+//***************** vecter_swi ********************//
+//#define SPO2_VECTOR
+//#define HR_VECTOR
+//#define HRV_TESTVEC
+
+//**************** lab_test_mode ******************//
+//#define LAB_TEST             
+//#define LAB_TEST_AGC                                                 
+
+//****************** print_swi ********************//
+//#define TYHX_LOG
+// #define AGC_DEBUG
+// #define HRS_DEBUG
+
+//**************************************************//
+
+#ifdef TYHX_LOG
+#define  TYHX_LOG(...)     SEGGER_RTT_printf(0,__VA_ARGS__)
+#else
+#define         TYHX_LOG(...)
+#endif
+
+#ifdef AGC_DEBUG
+#define  AGC_LOG(...)     SEGGER_RTT_printf(0,__VA_ARGS__)
+#else
+#define         AGC_LOG(...)
+#endif
+
+#ifdef HRS_DEBUG
+#define  DEBUG_PRINTF(...)     SEGGER_RTT_printf(0,__VA_ARGS__)
+#else
+#define         DEBUG_PRINTF(...)
+#endif
+
+
+//#define ARRAY_SIZE(x) (sizeof(x)/sizeof((x)[0]))
+typedef struct
+{
+    uint16_t      lastesthrs;                          //??????????
+    uint8_t       lastestspo2;                 //????
+    uint8_t       lastesthrv;                  //HRV??
+    uint16_t      wearstatus;
+       uint32_t      living_data_cnt;
+       uint8_t       living_signal_quality;
+       uint8_t       living_motion_status;
+       int32_t           leak_green;
+       int32_t           leak_red;
+       int32_t       leak_ir;
+       int32_t           card_green;
+       int32_t           card_red;
+       int32_t           card_ir;
+       uint8_t       hrv_tired_value;
+       uint8_t       hrv_spirit_pressure;
+       uint8_t       hr_living; 
+    uint32_t      hr_living_qu;
+    uint32_t      hr_living_std;
+       uint8_t       living_status;                //living_status
+} tyhx_hrsresult_t;
+
+#if defined(DEMO_COMMON)
+    #define HRS4100_IIC_CLK  30
+    #define HRS4100_IIC_SDA  0   
+    #define LIS3DH_IIC_CLK   18
+    #define LIS3DH_IIC_SDA   16
+    #define EXT_INT_PIN      1
+    #define GREEN_LED_SLE    1
+    #define RED_LED_SLE      4
+    #define IR_LED_SLE       2
+    #define RED_AGC_OFFSET   12
+    #define IR_AGC_OFFSET    12
+    #define GREEN_AGC_OFFSET    8
+    #define HR_GREEN_AGC_OFFSET 8
+    #define BIG_SCREEN  
+#elif defined(TWON3IN1LED)
+   #define HRS4100_IIC_CLK  30
+    #define HRS4100_IIC_SDA  0   
+    #define LIS3DH_IIC_CLK   18
+    #define LIS3DH_IIC_SDA   16
+    #define EXT_INT_PIN      1
+    #define GREEN_LED_SLE    2
+    #define RED_LED_SLE      4
+    #define IR_LED_SLE       1
+    #define RED_AGC_OFFSET   12
+    #define IR_AGC_OFFSET    12
+    #define GREEN_AGC_OFFSET    8
+    #define HR_GREEN_AGC_OFFSET 8
+    #define BIG_SCREEN  
+#elif defined(DEMO_NEW)
+  #define HRS4100_IIC_CLK  0
+  #define HRS4100_IIC_SDA  30   
+  #define LIS3DH_IIC_CLK   18
+  #define LIS3DH_IIC_SDA   16
+  #define EXT_INT_PIN      1
+  #define GREEN_LED_SLE    1
+  #define RED_LED_SLE      2
+  #define IR_LED_SLE       4
+  #define RED_AGC_OFFSET   50
+  #define IR_AGC_OFFSET    50
+       #define HR_GREEN_AGC_OFFSET 4
+  #define BIG_SCREEN
+  
+#elif defined(DEMO_BAND)
+  #define HRS4100_IIC_CLK  4
+  #define HRS4100_IIC_SDA  3  
+  #define LIS3DH_IIC_CLK   14
+  #define LIS3DH_IIC_SDA   12
+  #define EXT_INT_PIN      7
+  #define GREEN_LED_SLE    0
+  #define RED_LED_SLE      2
+  #define IR_LED_SLE       1
+  #define RED_AGC_OFFSET   64
+  #define IR_AGC_OFFSET    64
+  #define GREEN_AGC_OFFSET 8
+       #define HR_GREEN_AGC_OFFSET 8
+  
+#elif defined(DEMO_GT01)
+  #define HRS4100_IIC_CLK  5
+  #define HRS4100_IIC_SDA  6
+  #define LIS3DH_IIC_CLK   14
+  #define LIS3DH_IIC_SDA   12 
+  #define EXT_INT_PIN      7
+  #define GREEN_LED_SLE    1
+  #define RED_LED_SLE      4
+  #define IR_LED_SLE       2
+  #define RED_AGC_OFFSET   32
+  #define IR_AGC_OFFSET    32
+  #define GREEN_AGC_OFFSET 8
+  #define BIG_SCREEN
+  
+#elif defined(EVB)
+  #define HRS4100_IIC_CLK  9
+  #define HRS4100_IIC_SDA  10  
+  #define LIS3DH_IIC_CLK   13
+  #define LIS3DH_IIC_SDA   14
+  #define EXT_INT_PIN      11
+  #define GREEN_LED_SLE    1
+  #define RED_LED_SLE      4
+  #define IR_LED_SLE       2
+  #define RED_AGC_OFFSET   64
+  #define IR_AGC_OFFSET    64
+  #define GREEN_AGC_OFFSET 8
+       #define HR_GREEN_AGC_OFFSET 10
+  
+#else
+  #define HRS4100_IIC_CLK  9
+  #define HRS4100_IIC_SDA  10  
+  #define LIS3DH_IIC_CLK   13
+  #define LIS3DH_IIC_SDA   14
+  #define EXT_INT_PIN      11
+  #define GREEN_LED_SLE    1
+  #define RED_LED_SLE      4
+  #define IR_LED_SLE       2
+  #define RED_AGC_OFFSET   64
+  #define IR_AGC_OFFSET    64
+  #define GREEN_AGC_OFFSET 8
+  
+#endif
+
+
+typedef enum {    
+       PPG_INIT, 
+       PPG_OFF, 
+       PPG_LED_OFF,
+       CAL_INIT,
+       CAL_OFF,
+       RECAL_INIT    
+} hx3918_mode_t;
+
+typedef enum {    
+       SENSOR_OK, 
+       SENSOR_OP_FAILED,   
+} SENSOR_ERROR_T;
+
+typedef enum {    
+       HRS_MODE, 
+       SPO2_MODE,
+       WEAR_MODE,
+       HRV_MODE,
+       LIVING_MODE,
+       LAB_TEST_MODE,
+       FT_LEAK_LIGHT_MODE,
+       FT_GRAY_CARD_MODE,
+       FT_INT_TEST_MODE,
+    NULL_MODE,
+  close_MODE
+} WORK_MODE_T;
+
+typedef struct {
+       uint8_t count;
+    int32_t green_data[32];
+       int32_t red_data[16];
+       int32_t ir_data[16];  
+       int32_t s_buf[64];
+    int32_t sar_data;
+       uint8_t green_cur;
+       uint8_t red_cur; 
+       uint8_t ir_cur;
+       uint8_t green_offset;
+       uint8_t red_offset; 
+       uint8_t ir_offset;     
+}ppg_sensor_data_t;
+
+typedef enum {
+       MSG_LIVING_NO_WEAR,
+       MSG_LIVING_WEAR
+} hx3918_living_wear_msg_code_t;
+
+typedef enum {
+       MSG_NO_WEAR,
+       MSG_WEAR
+} hx3918_wear_msg_code_t;
+
+typedef struct {
+       hx3918_living_wear_msg_code_t  wear_status;
+       uint32_t           data_cnt;
+       uint8_t            signal_quality;
+       uint8_t            motion_status; 
+} hx3918_living_results_t;
+
+typedef struct {
+    int32_t p1_noise; 
+       int32_t p2_noise; 
+       int32_t p3_noise;
+       int32_t p4_noise;
+}NOISE_PS_T;
+
+
+
+extern uint8_t alg_ram[11*1024];
+extern uint8_t hx3918_chip_id;
+extern int32_t  sar_wear_thres;
+extern int32_t  sar_unwear_thres;
+
+extern WORK_MODE_T work_mode_flag;
+
+void hx_set_touch_mode(uint8_t current_mode);
+uint16_t hx3918_read_fifo_data(int32_t *buf, uint8_t phase_num, uint8_t sig);
+void read_data_packet(int32_t *ps_data);
+void hx3918_delay_us(uint32_t us);
+void hx3918_delay(uint32_t ms);
+bool hx3918_write_reg(uint8_t addr, uint8_t data); 
+bool hx3918_write_reg(uint8_t addr, uint8_t data);
+uint8_t hx3918_read_reg(uint8_t addr); 
+bool hx3918_brust_read_reg(uint8_t addr , uint8_t *buf, uint8_t length);
+bool hx3918_chip_check(void);
+uint8_t hx3918_read_fifo_size(void);
+void hx3918_ppg_off(void);
+void hx3918_ppg_on(void);  
+void hx3918_ppg_timer_cfg(bool en);
+void hx3918_agc_timer_cfg(bool en);
+void hx3918_gpioint_cfg(bool en);
+bool hx3918_init(WORK_MODE_T mode);
+void hx3918_agc_Int_handle(void); 
+void hx3918_gesensor_Int_handle(void);
+void hx3918_spo2_ppg_init(void);
+void hx3918_spo2_ppg_Int_handle(void);
+void hx3918_wear_ppg_Int_handle(void);
+uint8_t hx3918_get_wear_ppg_Int_handle(void);
+void hx3918_ft_hrs_Int_handle(void);
+void hx3918_ft_spo2_Int_handle(void);
+void hx3918_hrs_ppg_init(void);
+void hx3918_hrs_ppg_Int_handle(void);
+void hx3918_hrv_ppg_Int_handle(void);
+void hx3918_living_Int_handle(void);
+//void hx3918_gesensor_Int_handle(void);
+void hx3918_ppg_Int_handle(void);
+uint32_t hx3918_timers_start(void);
+uint32_t hx3918_timers_stop(void);
+uint32_t hx3918_gpioint_init(void);
+
+uint32_t hx3918_gpioint_enable(void);
+uint32_t hx3918_gpioint_disable(void);
+uint32_t hx3918_40ms_timers_start(void);
+uint32_t hx3918_40ms_timers_stop(void);
+
+void hx3918_vin_check(uint16_t led_vin);
+
+#ifdef LAB_TEST
+void hx3918_lab_test_init(void);
+void hx3918_test_alg_cfg(void);
+SENSOR_ERROR_T hx3918_lab_test_enable(void);
+void hx3918_lab_test_Int_handle(void);
+void hx3918_lab_test_read_packet(uint32_t *data_buf);
+#endif
+
+#ifdef CHECK_TOUCH_LIB
+hx3918_wear_msg_code_t hx3918_check_touch(int32_t *ir_data, uint8_t data_len);
+SENSOR_ERROR_T hx3918_check_touch_enable(void);
+#endif
+
+bool hx3918_living_send_data(int32_t *new_raw_data, uint8_t dat_len, uint32_t green_data_als, int16_t *gsen_data_x, int16_t *gsen_data_y, int16_t *gsen_data_z);
+hx3918_living_results_t hx3918_living_get_results(void);
+void agc_timeout_handler(void * p_context);
+void heart_rate_meas_timeout_handler(void * p_context);
+
+int16_t hx3918xxx_read_two_reg_low_triple(uint8_t addh, uint8_t addl);
+void display_refresh(void);
+extern char hx3918_ppg_timerout_flag ;
+extern char hx3918_agc_timerout_flag ;
+void hx3918_set_gsen_fifo(short *x,short *y,short *z, int count);
+void Hx3918_Init(void);
+uint8_t get_hx3918_id(void);
+void HX3918_result_set_wear_status(unsigned char wear_status);
+#endif
diff --git a/2.sdk/sdk/gui/lv_drivers/indev/HX3918/hx3918_check_touch.c b/2.sdk/sdk/gui/lv_drivers/indev/HX3918/hx3918_check_touch.c
new file mode 100644 (file)
index 0000000..49c1d90
--- /dev/null
@@ -0,0 +1,285 @@
+#include <stdio.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <math.h>
+
+//#include "twi_master.h"
+//#include "hx3918.h"
+//#include "SEGGER_RTT.h"
+
+//#include "tyhx_hrs_custom.h"
+#include "hx3918.h"
+#include "hx3918_check_touch.h"
+#ifdef SAR_ALG_LIB
+#include "hx3918_prox.h"
+#endif
+//#include "segger_rtt.h"
+
+hx3918_wear_msg_code_t hx3918_wear_status = MSG_NO_WEAR;
+hx3918_wear_msg_code_t hx3918_wear_status_pre = MSG_NO_WEAR;
+extern const int32_t check_mode_unwear_thre;
+extern const int32_t check_mode_wear_thre;
+extern const int32_t check_mode_sar_thre;
+uint8_t notouch_cnt = 0;
+uint8_t touch_cnt = 0;
+extern uint8_t read_fifo_first_flg;
+
+#ifdef CHECK_TOUCH_LIB
+void hx3918_check_touch_init(void) //20200615 ericy ppg fs=25hz, phase3 conversion ready interupt en
+{
+    uint16_t sample_rate = 10;                  /*config the data rate of chip alps2_fm ,uint is Hz*/
+    uint32_t prf_clk_num = 32000/sample_rate;   /*period in clk num, num = Fclk/fs */
+
+    uint8_t ps0_enable=1;       /*ps0_enable  , 1 mean enable ; 0 mean disable */
+    uint8_t ps1_enable=1;       /*ps1_enable  , 1 mean enable ; 0 mean disable */
+    uint8_t ps2_enable=0;       /*ps0_enable  , 1 mean enable ; 0 mean disable */
+    uint8_t ps3_enable=0;       /*ps1_enable  , 1 mean enable ; 0 mean disable */
+
+    uint8_t ps0_osr = 1;    /* 0 = 128 ; 1 = 256 ; 2 = 512 ; 3 = 1024 */
+    uint8_t ps1_osr = 1;    /* 0 = 128 ; 1 = 256 ; 2 = 512 ; 3 = 1024 */
+    uint8_t ps2_osr = 0;    /* 0 = 128 ; 1 = 256 ; 2 = 512 ; 3 = 1024 */
+    uint8_t ps3_osr = 0;    /* 0 = 128 ; 1 = 256 ; 2 = 512 ; 3 = 1024 */
+
+    uint8_t ps3_cp_avg_num_sel= 0;
+    uint8_t ps2_cp_avg_num_sel= 0;
+    uint8_t ps1_cp_avg_num_sel= 0;
+    uint8_t ps0_cp_avg_num_sel= 0;
+
+    uint8_t ps3_avg_num_sel_i2c=0;
+    uint8_t ps2_avg_num_sel_i2c=0;
+    uint8_t ps1_avg_num_sel_i2c=0;
+    uint8_t ps0_avg_num_sel_i2c=0;
+
+    /***********led open enable***********/
+
+    uint8_t ps0_led_en_i2c=1;
+    uint8_t ps1_led_en_i2c=0;
+    uint8_t ps2_led_en_i2c=0;
+    uint8_t ps3_led_en_i2c=0;
+
+    uint8_t ps0_ofidac_en_i2c=1;
+    uint8_t ps1_ofidac_en_i2c=1;
+    uint8_t ps2_ofidac_en_i2c=1;
+    uint8_t ps3_ofidac_en_i2c=1;
+
+    uint8_t dccancel_ps0 =0;    //offset idac   BIT[9:0]  0 31.25nA, 1023 32uA, step 31.25nA
+    uint8_t dccancel_ps1 =0;   //offset idac   BIT[9:0]  0 31.25nA, 1023 32uA, step 31.25nA
+    uint8_t dccancel_ps2 =0;    //offset idac   BIT[9:0]  0 31.25nA, 1023 32uA, step 31.25nA
+    uint8_t dccancel_ps3 =0;    //offset idac   BIT[9:0]  0 31.25nA, 1023 32uA, step 31.25nA
+
+    uint8_t leddrive_ps0 =64;     //LEDDRIVE_PS0  0~255 = 0~200ma
+    uint8_t leddrive_ps1 =0;     //LEDDRIVE_PS1  0~255 = 0~200ma
+    uint8_t leddrive_ps2 =0;    //LEDDRIVE_PS2  0~255 = 0~200ma
+    uint8_t leddrive_ps3 =0;     //LEDDRIVE_PS3  0~255 = 0~200ma
+
+    uint8_t led_en_begin =1;       // 0 = 2 ; 1 = 4 ; 2 = 8 ; 3 = 16 ;
+    uint8_t afe_reset = 1;        //* 0 = 32clk ; 1 = 64clk ; 2 = 128clk ; 3 = 256clk(d) ;
+    uint8_t en2rst_delay =3;      // pen 2 rst delay 0 = 128,256, 512, 1024
+    uint8_t init_wait_delay = 2; /* 0 = 800 ; 1 = 1600; 2 = 3200 ; 3 = 6400(d) */
+
+    uint8_t ps1_interval_i2c =0;    // ps2/ps3
+
+    uint8_t thres_int =1;    //thres int enable
+    uint8_t data_rdy_int =8;    //[3]:ps1_data2 [2]:ps1_data1 [1]:ps0_data2 [0]:ps0_data1
+
+
+    uint8_t ldrsel_ps0 =IR_LED_SLE;
+    uint8_t ldrsel_ps1 =0;
+    uint8_t ldrsel_ps2 =0;
+    uint8_t ldrsel_ps3 =0;
+
+    /***********cap *********/
+    uint8_t intcapsel_ps3 =2;   //00=4fp 01=8pf 02=12pf 03=16pf 04=20pf 05=24pf 06=28pf 07=32pf 08=36pf 09=40pf 10=44pf 11=48pf 12=52pf 13=56pf 14=60pf
+    uint8_t intcapsel_ps2 =2;   //00=4fp 01=8pf 02=12pf 03=16pf 04=20pf 05=24pf 06=28pf 07=32pf 08=36pf 09=40pf 10=44pf 11=48pf 12=52pf 13=56pf 14=60pf
+    uint8_t intcapsel_ps1 =2;   //00=4fp 01=8pf 02=12pf 03=16pf 04=20pf 05=24pf 06=28pf 07=32pf 08=36pf 09=40pf 10=44pf 11=48pf 12=52pf 13=56pf 14=60pf
+    uint8_t intcapsel_ps0 =2;   //00=4fp 01=8pf 02=12pf 03=16pf 04=20pf 05=24pf 06=28pf 07=32pf 08=36pf 09=40pf 10=44pf 11=48pf 12=52pf 13=56pf 14=60pf
+
+    uint8_t ps0_led_on_time=8;    /* 0 = 32clk2=8us ; 8 = 64clk=16us; 16=128clk=32us ; 32 = 256clk=64us ;
+                                     64 = 512clk=128us ; 128= 1024clk=256us; 256= 2048clk=512us*/
+    uint8_t ps1_led_on_time=8;    /* 0 = 32clk2=8us ; 8 = 64clk=16us; 16=128clk=32us ; 32 = 256clk=64us ;
+                                     64 = 512clk=128us ; 128= 1024clk=256us; 256= 2048clk=512us*/
+    uint8_t ps2_led_on_time=0;    /* 0 = 32clk2=8us ; 8 = 64clk=16us; 16=128clk=32us ; 32 = 256clk=64us ;
+                                     64 = 512clk=128us ; 128= 1024clk=256us; 256= 2048clk=512us*/
+    uint8_t ps3_led_on_time=0;    /* 0 = 32clk2=8us ; 8 = 64clk=16us; 16=128clk=32us ; 32 = 256clk=64us ;
+                                     64 = 512clk=128us ; 128= 1024clk=256us; 256= 2048clk=512us*/
+
+    uint8_t force_adc_clk_sel=0;
+    uint8_t force_adc_clk_cfg =0;
+    uint8_t force_PEN =0;     //phase enable
+    uint8_t force_PEN_cfg =0;
+    uint8_t force_LED_EN =0;
+    uint8_t force_LED_EN_cfg =0;
+    uint8_t force_CKAFEINT_sel =0;
+    uint8_t force_CKAFEINT_cfg =0;
+#ifdef SAR_ALG_LIB
+               hx3918_set_cap_data_ready(0);
+#endif
+    hx3918_write_reg(0X16, (ps3_enable<<3| ps2_enable<<2|ps1_enable<<1|ps0_enable));
+    hx3918_write_reg(0X17, (ps3_osr<<6| ps2_osr<<4|ps1_osr<<2|ps0_osr));
+    hx3918_write_reg(0X18, (uint8_t)prf_clk_num);
+    hx3918_write_reg(0X19, (uint8_t)(prf_clk_num>>8));
+    hx3918_write_reg(0X1a, (ps1_interval_i2c));
+    hx3918_write_reg(0X1b, led_en_begin<<6|afe_reset<<4|en2rst_delay <<2|init_wait_delay);
+    //hx3918_write_reg(0X1b, 0x03);
+    hx3918_write_reg(0X1c, ps0_led_on_time);
+    hx3918_write_reg(0X1d, ps1_led_on_time);
+    hx3918_write_reg(0X1e, ps2_led_on_time);
+    hx3918_write_reg(0X1f, ps3_led_on_time);
+    hx3918_write_reg(0X20, (ps3_cp_avg_num_sel<<6|ps2_cp_avg_num_sel<<4|ps1_cp_avg_num_sel<<2|ps0_cp_avg_num_sel)); 
+    hx3918_write_reg(0X21, (ps3_avg_num_sel_i2c<<6|ps2_avg_num_sel_i2c<<4|ps1_avg_num_sel_i2c<<2|ps0_avg_num_sel_i2c));
+    hx3918_write_reg(0X23, (ps0_led_en_i2c<<7|ps1_led_en_i2c<<6|ps2_led_en_i2c<<5|ps3_led_en_i2c<<4|ps0_ofidac_en_i2c<<3|ps1_ofidac_en_i2c<<2|ps2_ofidac_en_i2c<<1|ps3_ofidac_en_i2c));
+    hx3918_write_reg(0X24, (intcapsel_ps0<<4|intcapsel_ps1));
+    hx3918_write_reg(0X25, (intcapsel_ps2<<4|intcapsel_ps3));
+    hx3918_write_reg(0X26, leddrive_ps0);
+    hx3918_write_reg(0X27, leddrive_ps1);
+    hx3918_write_reg(0X28, leddrive_ps2);
+    hx3918_write_reg(0X29, leddrive_ps3);
+    hx3918_write_reg(0X2a, (ldrsel_ps0<<4|ldrsel_ps1));
+    hx3918_write_reg(0X2b, (ldrsel_ps2<<4|ldrsel_ps3));
+    hx3918_write_reg(0X2c, dccancel_ps0);
+    hx3918_write_reg(0X2d, dccancel_ps1);
+    hx3918_write_reg(0X2e, dccancel_ps2);
+    hx3918_write_reg(0X2f, dccancel_ps3);
+    hx3918_write_reg(0X36, (thres_int<<4|data_rdy_int));
+    hx3918_write_reg(0X4e, (force_adc_clk_sel<<7|force_adc_clk_cfg<<6|force_PEN<<5|force_PEN_cfg<<4|force_LED_EN<<3|
+                            force_LED_EN_cfg<<2|force_CKAFEINT_sel<<1|force_CKAFEINT_cfg));
+
+    hx3918_write_reg(0X6d, 0x00);
+    hx3918_write_reg(0XF0, 0x22);
+    hx3918_write_reg(0xF1, 0x28);
+    hx3918_write_reg(0xF2, 0x04);
+    hx3918_write_reg(0xF3, 0x70);
+    hx3918_write_reg(0xF4, 0x32);
+    hx3918_write_reg(0xF5, 0x89);
+    hx3918_write_reg(0xF6, 0x2b);
+    hx3918_write_reg(0xF7, 0x85);
+    hx3918_write_reg(0xF8, 0x27);
+    hx3918_write_reg(0xF9, 0x00);
+    hx3918_write_reg(0xFA, 0x88);
+    hx3918_write_reg(0xFB, 0x40);
+    hx3918_write_reg(0Xf6, 0X2b);
+
+#if defined(TIMMER_MODE)
+    hx3918_write_reg(0x3d,0x83);    //bits<3:0> fifo data sel, 0000 = p1;0001= p2;0010=p3;0011=p4;bits<7> fifo enble
+    hx3918_write_reg(0x3e,0x20);       //watermark
+    hx3918_write_reg(0x3c,0x1f);    // int_width_i2c
+    hx3918_write_reg(0X37, 0x00);   // int sel,01=prf int,04=enable almost full int
+    hx3918_write_reg(0X3b, 0x00);
+    hx3918_write_reg(0X3b, 0x10);
+#else ///////////INT Mode
+    hx3918_write_reg(0x3d,0x00);    //bits<3:0> fifo data sel, 0000 = p1;0001= p2;0010=p3;0011=p4;bits<7> fifo enble
+    hx3918_write_reg(0x3c,0x1f);    // int_width_i2c
+    hx3918_write_reg(0X37, 0x04);   // int sel,01=prf ,04=enable almost full
+#endif
+
+    hx3918_write_reg(0X4d, 0X01);   //soft reset
+    hx3918_delay(5);
+    hx3918_write_reg(0X4d, 0X00);   //release
+    hx3918_delay(5);
+#ifdef SAR_ALG_LIB
+       hx3918_prox_reg_init();
+#endif
+    read_fifo_first_flg = 1;
+}
+
+void hx3918_check_touch_open(void)
+{
+    notouch_cnt = 0;
+    touch_cnt = 0;
+    hx3918_wear_status = MSG_NO_WEAR;
+}
+
+SENSOR_ERROR_T hx3918_check_touch_enable(void)
+{
+    if (!hx3918_chip_check())
+    {
+        AGC_LOG("hx3918 check id failed!\r\n");
+        return SENSOR_OP_FAILED;
+    }
+    AGC_LOG("hx3918 check id success!\r\n");
+
+    hx3918_check_touch_open();
+    hx3918_check_touch_init();
+    hx3918_ppg_timer_cfg(true);
+
+    return SENSOR_OK;
+}
+
+extern int ir_wear ;//红外佩戴状态
+hx3918_wear_msg_code_t hx3918_check_touch(int32_t *ir_data, uint8_t data_len)
+{
+    uint8_t ii;
+               int16_t sar_data = 32767;
+#ifdef SAR_ALG_LIB
+       sar_data = hx90xx_get_prox_data();
+#endif
+    if (ir_data[0]>check_mode_wear_thre)
+        ir_wear = 1;
+    else
+        ir_wear = 0;
+    HX3918_LOG("ir_data:%d     \n", ir_data[0]);
+    for(ii=0; ii<data_len; ii++)
+    {
+       //HX3918_LOG("%d        \n", ir_data[ii]);
+        if(ir_data[ii]>check_mode_wear_thre&& sar_data > sar_wear_thres)
+        {
+            
+            if(notouch_cnt>0)
+            {
+                notouch_cnt--;
+            }
+            if(touch_cnt>=5)
+            {
+                hx3918_wear_status = MSG_WEAR;
+                touch_cnt=5;
+            }
+            else
+            {
+                touch_cnt++;
+            }
+        }
+        else if(ir_data[ii]<check_mode_unwear_thre || sar_data < sar_unwear_thres)
+        {
+            if(touch_cnt>0)
+            {
+                touch_cnt--;
+            }
+            if(notouch_cnt>=5)
+            {
+                hx3918_wear_status = MSG_NO_WEAR;
+                notouch_cnt=5;
+            }
+            else
+            {
+                notouch_cnt++;
+            }
+        }
+    }
+
+               #ifdef SAR_ALG_LIB
+               if (hx3918_wear_status == MSG_NO_WEAR)
+               {
+                       hx3918_cali_with_ir(ir_data[0], check_mode_unwear_thre);
+               }
+               #endif
+               
+
+    HX3918_result_set_wear_status(hx3918_wear_status);
+    return hx3918_wear_status;
+}
+
+uint8_t hx3918_check_touch_read(ppg_sensor_data_t *s_dat)
+{
+    int32_t *s_buf =  &(s_dat->s_buf[0]);
+    //int32_t *sar_lp_data  = &s_dat->sar_data;
+    uint8_t data_count = 0;
+
+    data_count = hx3918_read_fifo_data(s_buf,1,1);
+    //*sar_lp_data = hx3918_read_sar_data();
+    s_dat->count =  data_count;
+
+    return data_count;
+}
+
+#endif
diff --git a/2.sdk/sdk/gui/lv_drivers/indev/HX3918/hx3918_check_touch.h b/2.sdk/sdk/gui/lv_drivers/indev/HX3918/hx3918_check_touch.h
new file mode 100644 (file)
index 0000000..ee6a48e
--- /dev/null
@@ -0,0 +1,17 @@
+#ifndef _hx3918_CHECK_TOUCH_H_
+#define _hx3918_CHECK_TOUCH_H_
+
+#include <stdint.h>
+#include <stdbool.h>
+#include "hx3918.h"
+//#include "tyhx_hrs_custom.h"
+
+
+
+uint8_t hx3918_check_touch_read(ppg_sensor_data_t *s_dat);
+SENSOR_ERROR_T hx3918_check_touch_enable(void);
+uint8_t hx3918_check_touch_read(ppg_sensor_data_t *s_dat);
+hx3918_wear_msg_code_t hx3690l_check_touch_send_data(int32_t *ir_data, uint8_t count);
+hx3918_wear_msg_code_t check_touch_alg(int32_t ir_data);
+
+#endif
diff --git a/2.sdk/sdk/gui/lv_drivers/indev/HX3918/hx3918_factory_test.c b/2.sdk/sdk/gui/lv_drivers/indev/HX3918/hx3918_factory_test.c
new file mode 100644 (file)
index 0000000..2642888
--- /dev/null
@@ -0,0 +1,498 @@
+#include <stdio.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <math.h>
+
+#include "hx3918.h"
+#include "hx3918_factory_test.h"
+
+void hx3918_factory_ft_card_test_config(void)//»Ò¿¨10mm¸ß¶È²âÊÔÅäÖÃ
+{
+    uint16_t sample_rate = 25;                  /*config the data rate of chip alps2_fm ,uint is Hz*/
+    uint32_t prf_clk_num = 32000/sample_rate;   /*period in clk num, num = Fclk/fs */
+
+    uint8_t ps0_enable=1;       /*ps0_enable  , 1 mean enable ; 0 mean disable */
+    uint8_t ps1_enable=1;       /*ps1_enable  , 1 mean enable ; 0 mean disable */
+    uint8_t ps2_enable=1;       /*ps0_enable  , 1 mean enable ; 0 mean disable */
+    uint8_t ps3_enable=1;       /*ps1_enable  , 1 mean enable ; 0 mean disable */
+
+    uint8_t ps0_osr = 3;    /* 0 = 128 ; 1 = 256 ; 2 = 512 ; 3 = 1024 */
+    uint8_t ps1_osr = 3;    /* 0 = 128 ; 1 = 256 ; 2 = 512 ; 3 = 1024 */
+    uint8_t ps2_osr = 3;    /* 0 = 128 ; 1 = 256 ; 2 = 512 ; 3 = 1024 */
+    uint8_t ps3_osr = 3;    /* 0 = 128 ; 1 = 256 ; 2 = 512 ; 3 = 1024 */
+
+    uint8_t ps3_cp_avg_num_sel= 0;
+    uint8_t ps2_cp_avg_num_sel= 0;
+    uint8_t ps1_cp_avg_num_sel= 0;
+    uint8_t ps0_cp_avg_num_sel= 0;
+
+    uint8_t ps3_avg_num_sel_i2c=0;
+    uint8_t ps2_avg_num_sel_i2c=0;
+    uint8_t ps1_avg_num_sel_i2c=0;
+    uint8_t ps0_avg_num_sel_i2c=0;
+
+    /***********led open enable***********/
+
+    uint8_t ps0_led_en_i2c=1;
+    uint8_t ps1_led_en_i2c=1;
+    uint8_t ps2_led_en_i2c=1;
+    uint8_t ps3_led_en_i2c=1;
+
+    uint8_t ps0_ofidac_en_i2c=1;
+    uint8_t ps1_ofidac_en_i2c=1;
+    uint8_t ps2_ofidac_en_i2c=1;
+    uint8_t ps3_ofidac_en_i2c=1;
+
+    uint8_t dccancel_ps0 =0;    //offset idac   BIT[9:0]  0 31.25nA, 1023 32uA, step 31.25nA
+    uint8_t dccancel_ps1 =0;   //offset idac   BIT[9:0]  0 31.25nA, 1023 32uA, step 31.25nA
+    uint8_t dccancel_ps2 =0;    //offset idac   BIT[9:0]  0 31.25nA, 1023 32uA, step 31.25nA
+    uint8_t dccancel_ps3 =0;    //offset idac   BIT[9:0]  0 31.25nA, 1023 32uA, step 31.25nA
+
+    uint8_t leddrive_ps0 =0;     //LEDDRIVE_PS0  0~255 = 0~200ma
+    uint8_t leddrive_ps1 =32;     //LEDDRIVE_PS1  0~255 = 0~200ma
+    uint8_t leddrive_ps2 =32;    //LEDDRIVE_PS2  0~255 = 0~200ma
+    uint8_t leddrive_ps3 =32;     //LEDDRIVE_PS3  0~255 = 0~200ma
+
+    uint8_t led_en_begin =1;       // 0 = 2 ; 1 = 4 ; 2 = 8 ; 3 = 16 ;
+    uint8_t afe_reset = 1;        //* 0 = 32clk ; 1 = 64clk ; 2 = 128clk ; 3 = 256clk(d) ;
+    uint8_t en2rst_delay =3;      // pen 2 rst delay 0 = 128,256, 512, 1024
+    uint8_t init_wait_delay = 2; /* 0 = 800 ; 1 = 1600; 2 = 3200 ; 3 = 6400(d) */
+
+    uint8_t ps1_interval_i2c =0;    // ps2/ps3
+
+    uint8_t thres_int =1;    //thres int enable
+    uint8_t data_rdy_int =8;    //[3]:ps1_data2 [2]:ps1_data1 [1]:ps0_data2 [0]:ps0_data1
+
+
+    uint8_t ldrsel_ps0 =0;
+    uint8_t ldrsel_ps1 =GREEN_LED_SLE;
+    uint8_t ldrsel_ps2 =RED_LED_SLE;
+    uint8_t ldrsel_ps3 =IR_LED_SLE;
+
+    /***********cap *********/
+    uint8_t intcapsel_ps3 =5;   //00=4fp 01=8pf 02=12pf 03=16pf 04=20pf 05=24pf 06=28pf 07=32pf 08=36pf 09=40pf 10=44pf 11=48pf 12=52pf 13=56pf 14=60pf
+    uint8_t intcapsel_ps2 =5;   //00=4fp 01=8pf 02=12pf 03=16pf 04=20pf 05=24pf 06=28pf 07=32pf 08=36pf 09=40pf 10=44pf 11=48pf 12=52pf 13=56pf 14=60pf
+    uint8_t intcapsel_ps1 =5;   //00=4fp 01=8pf 02=12pf 03=16pf 04=20pf 05=24pf 06=28pf 07=32pf 08=36pf 09=40pf 10=44pf 11=48pf 12=52pf 13=56pf 14=60pf
+    uint8_t intcapsel_ps0 =5;   //00=4fp 01=8pf 02=12pf 03=16pf 04=20pf 05=24pf 06=28pf 07=32pf 08=36pf 09=40pf 10=44pf 11=48pf 12=52pf 13=56pf 14=60pf
+
+    uint8_t ps0_led_on_time=32;    /* 0 = 32clk2=8us ; 8 = 64clk=16us; 16=128clk=32us ; 32 = 256clk=64us ;
+                                     64 = 512clk=128us ; 128= 1024clk=256us; 256= 2048clk=512us*/
+    uint8_t ps1_led_on_time=32;    /* 0 = 32clk2=8us ; 8 = 64clk=16us; 16=128clk=32us ; 32 = 256clk=64us ;
+                                     64 = 512clk=128us ; 128= 1024clk=256us; 256= 2048clk=512us*/
+    uint8_t ps2_led_on_time=32;    /* 0 = 32clk2=8us ; 8 = 64clk=16us; 16=128clk=32us ; 32 = 256clk=64us ;
+                                     64 = 512clk=128us ; 128= 1024clk=256us; 256= 2048clk=512us*/
+    uint8_t ps3_led_on_time=32;    /* 0 = 32clk2=8us ; 8 = 64clk=16us; 16=128clk=32us ; 32 = 256clk=64us ;
+                                     64 = 512clk=128us ; 128= 1024clk=256us; 256= 2048clk=512us*/
+
+    uint8_t force_adc_clk_sel=0;
+    uint8_t force_adc_clk_cfg =0;
+    uint8_t force_PEN =0;     //phase enable
+    uint8_t force_PEN_cfg =0;
+    uint8_t force_LED_EN =0;
+    uint8_t force_LED_EN_cfg =0;
+    uint8_t force_CKAFEINT_sel =0;
+    uint8_t force_CKAFEINT_cfg =0;
+
+    hx3918_write_reg(0X16, (ps3_enable<<3| ps2_enable<<2|ps1_enable<<1|ps0_enable));
+    hx3918_write_reg(0X17, (ps3_osr<<6| ps2_osr<<4|ps1_osr<<2|ps0_osr));
+    hx3918_write_reg(0X18, (uint8_t)prf_clk_num);
+    hx3918_write_reg(0X19, (uint8_t)(prf_clk_num>>8));
+    hx3918_write_reg(0X1a, (ps1_interval_i2c));
+    hx3918_write_reg(0X1b, led_en_begin<<6|afe_reset<<4|en2rst_delay <<2|init_wait_delay);
+    hx3918_write_reg(0X1c, ps0_led_on_time);
+    hx3918_write_reg(0X1d, ps1_led_on_time);
+    hx3918_write_reg(0X1e, ps2_led_on_time);
+    hx3918_write_reg(0X1f, ps3_led_on_time);
+    hx3918_write_reg(0X20, (ps3_cp_avg_num_sel<<6|ps2_cp_avg_num_sel<<4|ps1_cp_avg_num_sel<<2|ps0_cp_avg_num_sel)); 
+    hx3918_write_reg(0X21, (ps3_avg_num_sel_i2c<<6|ps2_avg_num_sel_i2c<<4|ps1_avg_num_sel_i2c<<2|ps0_avg_num_sel_i2c));
+    hx3918_write_reg(0X23, (ps0_led_en_i2c<<7|ps1_led_en_i2c<<6|ps2_led_en_i2c<<5|ps3_led_en_i2c<<4|ps0_ofidac_en_i2c<<3|ps1_ofidac_en_i2c<<2|ps2_ofidac_en_i2c<<1|ps3_ofidac_en_i2c));
+    hx3918_write_reg(0X24, (intcapsel_ps0<<4|intcapsel_ps1));
+    hx3918_write_reg(0X25, (intcapsel_ps2<<4|intcapsel_ps3));
+    hx3918_write_reg(0X26, leddrive_ps0);
+    hx3918_write_reg(0X27, leddrive_ps1);
+    hx3918_write_reg(0X28, leddrive_ps2);
+    hx3918_write_reg(0X29, leddrive_ps3);
+    hx3918_write_reg(0X2a, (ldrsel_ps0<<4|ldrsel_ps1));
+    hx3918_write_reg(0X2b, (ldrsel_ps2<<4|ldrsel_ps3));
+    hx3918_write_reg(0X2c, dccancel_ps0);
+    hx3918_write_reg(0X2d, dccancel_ps1);
+    hx3918_write_reg(0X2e, dccancel_ps2);
+    hx3918_write_reg(0X2f, dccancel_ps3);
+    hx3918_write_reg(0X36, (thres_int<<4|data_rdy_int));
+    hx3918_write_reg(0X4e, (force_adc_clk_sel<<7|force_adc_clk_cfg<<6|force_PEN<<5|force_PEN_cfg<<4|force_LED_EN<<3|
+                            force_LED_EN_cfg<<2|force_CKAFEINT_sel<<1|force_CKAFEINT_cfg));
+
+    hx3918_write_reg(0X6d, 0x00);
+    hx3918_write_reg(0XF0, 0x22);
+    hx3918_write_reg(0xF1, 0x28);
+    hx3918_write_reg(0xF2, 0x04);
+    hx3918_write_reg(0xF3, 0x70);
+    hx3918_write_reg(0xF4, 0x32);
+    hx3918_write_reg(0xF5, 0x89);
+    hx3918_write_reg(0xF6, 0x2b);
+    hx3918_write_reg(0xF7, 0x85);
+    hx3918_write_reg(0xF8, 0x27);
+    hx3918_write_reg(0xF9, 0x00);
+    hx3918_write_reg(0xFA, 0x88);
+    hx3918_write_reg(0xFB, 0x40);
+    hx3918_write_reg(0Xf6, 0X2b);
+
+    hx3918_write_reg(0x3d, 0x00);    //bits<3:0> fifo data sel, 0000 = p1;0001= p2;0010=p3;0011=p4;bits<7> fifo enble
+    hx3918_write_reg(0x3e, 0x20);      //watermark
+    hx3918_write_reg(0x3c, 0x1f);    // int_width_i2c
+    hx3918_write_reg(0X37, 0x00);   // int sel,01=prf int,04=enable almost full int
+    hx3918_write_reg(0X3b, 0x00);
+    hx3918_write_reg(0X3b, 0x10);
+
+    hx3918_write_reg(0x4d, 0x01);   //soft reset
+    hx3918_delay(5);
+    hx3918_write_reg(0x4d, 0x00);   //release
+    hx3918_delay(5);
+}
+
+void hx3918_factory_ft_leak_light_test_config(void)//©¹â²âÊÔÅäÖÃ
+{
+    uint16_t sample_rate = 25;                  /*config the data rate of chip alps2_fm ,uint is Hz*/
+    uint32_t prf_clk_num = 32000/sample_rate;   /*period in clk num, num = Fclk/fs */
+
+    uint8_t ps0_enable=1;       /*ps0_enable  , 1 mean enable ; 0 mean disable */
+    uint8_t ps1_enable=1;       /*ps1_enable  , 1 mean enable ; 0 mean disable */
+    uint8_t ps2_enable=1;       /*ps0_enable  , 1 mean enable ; 0 mean disable */
+    uint8_t ps3_enable=1;       /*ps1_enable  , 1 mean enable ; 0 mean disable */
+
+    uint8_t ps0_osr = 3;    /* 0 = 128 ; 1 = 256 ; 2 = 512 ; 3 = 1024 */
+    uint8_t ps1_osr = 3;    /* 0 = 128 ; 1 = 256 ; 2 = 512 ; 3 = 1024 */
+    uint8_t ps2_osr = 3;    /* 0 = 128 ; 1 = 256 ; 2 = 512 ; 3 = 1024 */
+    uint8_t ps3_osr = 3;    /* 0 = 128 ; 1 = 256 ; 2 = 512 ; 3 = 1024 */
+
+    uint8_t ps3_cp_avg_num_sel= 0;
+    uint8_t ps2_cp_avg_num_sel= 0;
+    uint8_t ps1_cp_avg_num_sel= 0;
+    uint8_t ps0_cp_avg_num_sel= 0;
+
+    uint8_t ps3_avg_num_sel_i2c=0;
+    uint8_t ps2_avg_num_sel_i2c=0;
+    uint8_t ps1_avg_num_sel_i2c=0;
+    uint8_t ps0_avg_num_sel_i2c=0;
+
+    /***********led open enable***********/
+
+    uint8_t ps0_led_en_i2c=1;
+    uint8_t ps1_led_en_i2c=1;
+    uint8_t ps2_led_en_i2c=1;
+    uint8_t ps3_led_en_i2c=1;
+
+    uint8_t ps0_ofidac_en_i2c=1;
+    uint8_t ps1_ofidac_en_i2c=1;
+    uint8_t ps2_ofidac_en_i2c=1;
+    uint8_t ps3_ofidac_en_i2c=1;
+
+    uint8_t dccancel_ps0 =0;    //offset idac   BIT[9:0]  0 31.25nA, 1023 32uA, step 31.25nA
+    uint8_t dccancel_ps1 =0;   //offset idac   BIT[9:0]  0 31.25nA, 1023 32uA, step 31.25nA
+    uint8_t dccancel_ps2 =0;    //offset idac   BIT[9:0]  0 31.25nA, 1023 32uA, step 31.25nA
+    uint8_t dccancel_ps3 =0;    //offset idac   BIT[9:0]  0 31.25nA, 1023 32uA, step 31.25nA
+
+    uint8_t leddrive_ps0 =0;     //LEDDRIVE_PS0  0~255 = 0~200ma
+    uint8_t leddrive_ps1 =64;     //LEDDRIVE_PS1  0~255 = 0~200ma
+    uint8_t leddrive_ps2 =64;    //LEDDRIVE_PS2  0~255 = 0~200ma
+    uint8_t leddrive_ps3 =64;     //LEDDRIVE_PS3  0~255 = 0~200ma
+
+    uint8_t led_en_begin =1;       // 0 = 2 ; 1 = 4 ; 2 = 8 ; 3 = 16 ;
+    uint8_t afe_reset = 1;        //* 0 = 32clk ; 1 = 64clk ; 2 = 128clk ; 3 = 256clk(d) ;
+    uint8_t en2rst_delay =3;      // pen 2 rst delay 0 = 128,256, 512, 1024
+    uint8_t init_wait_delay = 2; /* 0 = 800 ; 1 = 1600; 2 = 3200 ; 3 = 6400(d) */
+
+    uint8_t ps1_interval_i2c =0;    // ps2/ps3
+
+    uint8_t thres_int =1;    //thres int enable
+    uint8_t data_rdy_int =8;    //[3]:ps1_data2 [2]:ps1_data1 [1]:ps0_data2 [0]:ps0_data1
+
+
+    uint8_t ldrsel_ps0 =0;
+    uint8_t ldrsel_ps1 =GREEN_LED_SLE;
+    uint8_t ldrsel_ps2 =RED_LED_SLE;
+    uint8_t ldrsel_ps3 =IR_LED_SLE;
+
+    /***********cap *********/
+    uint8_t intcapsel_ps3 =5;   //00=4fp 01=8pf 02=12pf 03=16pf 04=20pf 05=24pf 06=28pf 07=32pf 08=36pf 09=40pf 10=44pf 11=48pf 12=52pf 13=56pf 14=60pf
+    uint8_t intcapsel_ps2 =5;   //00=4fp 01=8pf 02=12pf 03=16pf 04=20pf 05=24pf 06=28pf 07=32pf 08=36pf 09=40pf 10=44pf 11=48pf 12=52pf 13=56pf 14=60pf
+    uint8_t intcapsel_ps1 =5;   //00=4fp 01=8pf 02=12pf 03=16pf 04=20pf 05=24pf 06=28pf 07=32pf 08=36pf 09=40pf 10=44pf 11=48pf 12=52pf 13=56pf 14=60pf
+    uint8_t intcapsel_ps0 =5;   //00=4fp 01=8pf 02=12pf 03=16pf 04=20pf 05=24pf 06=28pf 07=32pf 08=36pf 09=40pf 10=44pf 11=48pf 12=52pf 13=56pf 14=60pf
+
+    uint8_t ps0_led_on_time=64;    /* 0 = 32clk2=8us ; 8 = 64clk=16us; 16=128clk=32us ; 32 = 256clk=64us ;
+                                     64 = 512clk=128us ; 128= 1024clk=256us; 256= 2048clk=512us*/
+    uint8_t ps1_led_on_time=64;    /* 0 = 32clk2=8us ; 8 = 64clk=16us; 16=128clk=32us ; 32 = 256clk=64us ;
+                                     64 = 512clk=128us ; 128= 1024clk=256us; 256= 2048clk=512us*/
+    uint8_t ps2_led_on_time=64;    /* 0 = 32clk2=8us ; 8 = 64clk=16us; 16=128clk=32us ; 32 = 256clk=64us ;
+                                     64 = 512clk=128us ; 128= 1024clk=256us; 256= 2048clk=512us*/
+    uint8_t ps3_led_on_time=64;    /* 0 = 32clk2=8us ; 8 = 64clk=16us; 16=128clk=32us ; 32 = 256clk=64us ;
+                                     64 = 512clk=128us ; 128= 1024clk=256us; 256= 2048clk=512us*/
+
+    uint8_t force_adc_clk_sel=0;
+    uint8_t force_adc_clk_cfg =0;
+    uint8_t force_PEN =0;     //phase enable
+    uint8_t force_PEN_cfg =0;
+    uint8_t force_LED_EN =0;
+    uint8_t force_LED_EN_cfg =0;
+    uint8_t force_CKAFEINT_sel =0;
+    uint8_t force_CKAFEINT_cfg =0;
+
+    hx3918_write_reg(0X16, (ps3_enable<<3| ps2_enable<<2|ps1_enable<<1|ps0_enable));
+    hx3918_write_reg(0X17, (ps3_osr<<6| ps2_osr<<4|ps1_osr<<2|ps0_osr));
+    hx3918_write_reg(0X18, (uint8_t)prf_clk_num);
+    hx3918_write_reg(0X19, (uint8_t)(prf_clk_num>>8));
+    hx3918_write_reg(0X1a, (ps1_interval_i2c));
+    hx3918_write_reg(0X1b, led_en_begin<<6|afe_reset<<4|en2rst_delay <<2|init_wait_delay);
+    hx3918_write_reg(0X1c, ps0_led_on_time);
+    hx3918_write_reg(0X1d, ps1_led_on_time);
+    hx3918_write_reg(0X1e, ps2_led_on_time);
+    hx3918_write_reg(0X1f, ps3_led_on_time);
+    hx3918_write_reg(0X20, (ps3_cp_avg_num_sel<<6|ps2_cp_avg_num_sel<<4|ps1_cp_avg_num_sel<<2|ps0_cp_avg_num_sel)); 
+    hx3918_write_reg(0X21, (ps3_avg_num_sel_i2c<<6|ps2_avg_num_sel_i2c<<4|ps1_avg_num_sel_i2c<<2|ps0_avg_num_sel_i2c));
+    hx3918_write_reg(0X23, (ps0_led_en_i2c<<7|ps1_led_en_i2c<<6|ps2_led_en_i2c<<5|ps3_led_en_i2c<<4|ps0_ofidac_en_i2c<<3|ps1_ofidac_en_i2c<<2|ps2_ofidac_en_i2c<<1|ps3_ofidac_en_i2c));
+    hx3918_write_reg(0X24, (intcapsel_ps0<<4|intcapsel_ps1));
+    hx3918_write_reg(0X25, (intcapsel_ps2<<4|intcapsel_ps3));
+    hx3918_write_reg(0X26, leddrive_ps0);
+    hx3918_write_reg(0X27, leddrive_ps1);
+    hx3918_write_reg(0X28, leddrive_ps2);
+    hx3918_write_reg(0X29, leddrive_ps3);
+    hx3918_write_reg(0X2a, (ldrsel_ps0<<4|ldrsel_ps1));
+    hx3918_write_reg(0X2b, (ldrsel_ps2<<4|ldrsel_ps3));
+    hx3918_write_reg(0X2c, dccancel_ps0);
+    hx3918_write_reg(0X2d, dccancel_ps1);
+    hx3918_write_reg(0X2e, dccancel_ps2);
+    hx3918_write_reg(0X2f, dccancel_ps3);
+    hx3918_write_reg(0X36, (thres_int<<4|data_rdy_int));
+    hx3918_write_reg(0X4e, (force_adc_clk_sel<<7|force_adc_clk_cfg<<6|force_PEN<<5|force_PEN_cfg<<4|force_LED_EN<<3|
+                            force_LED_EN_cfg<<2|force_CKAFEINT_sel<<1|force_CKAFEINT_cfg));
+
+    hx3918_write_reg(0X6d, 0x00);
+    hx3918_write_reg(0XF0, 0x22);
+    hx3918_write_reg(0xF1, 0x28);
+    hx3918_write_reg(0xF2, 0x04);
+    hx3918_write_reg(0xF3, 0x70);
+    hx3918_write_reg(0xF4, 0x32);
+    hx3918_write_reg(0xF5, 0x89);
+    hx3918_write_reg(0xF6, 0x2b);
+    hx3918_write_reg(0xF7, 0x85);
+    hx3918_write_reg(0xF8, 0x27);
+    hx3918_write_reg(0xF9, 0x00);
+    hx3918_write_reg(0xFA, 0x88);
+    hx3918_write_reg(0xFB, 0x40);
+    hx3918_write_reg(0Xf6, 0X2b);
+
+    hx3918_write_reg(0x3d, 0x00);    //bits<3:0> fifo data sel, 0000 = p1;0001= p2;0010=p3;0011=p4;bits<7> fifo enble
+    hx3918_write_reg(0x3e, 0x20);      //watermark
+    hx3918_write_reg(0x3c, 0x1f);    // int_width_i2c
+    hx3918_write_reg(0X37, 0x00);   // int sel,01=prf int,04=enable almost full int
+    hx3918_write_reg(0X3b, 0x00);
+    hx3918_write_reg(0X3b, 0x10);
+
+    hx3918_write_reg(0x4d, 0x01);   //soft reset
+    hx3918_delay(5);
+    hx3918_write_reg(0x4d, 0x00);   //release
+    hx3918_delay(5);
+}
+
+void hx3918_factory_ft_int_test_config(void)//ÖжϲâÊÔÅäÖÃ
+{
+}
+
+bool hx3918_factory_test_read(int32_t *ps_data)
+{
+    uint8_t  databuf1[6] = {0};
+    uint8_t  databuf2[6] = {0};
+    int32_t P1 = 0, P2 = 0, P4 = 0, P3 = 0;
+    hx3918_brust_read_reg(0x02, databuf1, 6);
+    hx3918_brust_read_reg(0x08, databuf2, 6);
+
+    P1 = ((databuf1[0]) | (databuf1[1] << 8) | (databuf1[2] << 16));
+    P2 = ((databuf1[3]) | (databuf1[4] << 8) | (databuf1[5] << 16));
+    P3 = ((databuf2[0]) | (databuf2[1] << 8) | (databuf2[2] << 16));
+    P4 = ((databuf2[3]) | (databuf2[4] << 8) | (databuf2[5] << 16));
+
+    ps_data[0] = P1 ;
+    ps_data[1] = P2 ;
+    ps_data[2] = P3 ;
+    ps_data[3] = P4 ;
+    DEBUG_PRINTF("p1,p2,p3,p4 %d %d %d %d\r\n", P1, P2, P3, P4);
+    return true;
+}
+
+bool hx3918_chip_check_id(void)
+{
+    uint8_t i = 0;
+    uint8_t chip_idf =0;
+    for(i=0; i<10; i++)
+    {
+        hx3918_write_reg(0x01, 0x00);
+        hx3918_delay(5);
+        chip_idf = hx3918_read_reg(0x00);
+        if (chip_idf == 0x27)
+        {
+            return true;
+        }
+    }
+    return false;
+}
+factory_result_t factory_reslts = {0,0,0};
+factory_result_t hx3918_factroy_test(uint32_t  test_mode)
+{
+    int32_t green_buffer[4] = {0,0,0,0};
+    int32_t red_buffer[4] = {0,0,0,0};
+    int32_t ir_buffer[4] = {0,0,0,0};
+    int32_t ps_data[4]= {0,0,0,0};
+
+    int32_t  green_led_data= 0;
+    int32_t  red_led_data= 0;
+    int32_t  ir_led_data= 0;
+
+    int32_t green_psdif[4] = {0,0,0,0};
+    int32_t red_psdif[4] = {0,0,0,0};
+    int32_t ir_psdif[4] = {0,0,0,0};
+
+    int32_t green_final = 0;
+    int32_t red_final = 0;
+    int32_t ir_final = 0;
+    int32_t testdata_temp = 0;
+
+    uint8_t ii = 0;
+    uint8_t jj = 0;
+    HX3918_LOG("hx3918_factroy_test1\n");
+    if (hx3918_chip_check_id() == false)
+    {
+        return factory_reslts;
+    }
+    HX3918_LOG("hx3918_factroy_test2\n");
+    switch(test_mode)
+    {
+        case LEAK_LIGHT_TEST:
+            hx3918_factory_ft_leak_light_test_config();
+            break;
+        case GRAY_CARD_TEST:
+            hx3918_factory_ft_card_test_config();
+            break;
+        case FT_INT_TEST:
+            hx3918_factory_ft_int_test_config();
+            break;
+        default:
+            break;
+    }
+    hx3918_delay(100);
+    if(test_mode==FT_INT_TEST)
+    {
+        return factory_reslts;
+    }
+    HX3918_LOG("hx3918_factroy_test3\n");
+    for(ii=0; ii<4; ii++) //40ms read data
+    {
+        hx3918_delay(40);
+        hx3918_factory_test_read(ps_data);
+        green_led_data = ps_data[1] - ps_data[0];
+        red_led_data = ps_data[2] - ps_data[0];
+        ir_led_data = ps_data[3] - ps_data[0];
+        green_buffer[ii] = green_led_data;
+        ir_buffer[ii] = ir_led_data;
+        red_buffer[ii] = red_led_data;
+    }
+
+    for(ii=0; ii<3; ii++)
+    {
+        for(jj=0; jj<3-ii; jj++)
+        {
+            if(green_buffer[jj]>=green_buffer[jj+1])
+            {
+                testdata_temp = green_buffer[jj];
+                green_buffer[jj] = green_buffer[jj+1];
+                green_buffer[jj+1] = testdata_temp;
+            }
+
+            if(red_buffer[jj]>=red_buffer[jj+1])
+            {
+                testdata_temp = red_buffer[jj];
+                red_buffer[jj] = red_buffer[jj+1];
+                red_buffer[jj+1] = testdata_temp;
+            }
+            if(ir_buffer[jj]>=ir_buffer[jj+1])
+            {
+                testdata_temp = ir_buffer[jj];
+                ir_buffer[jj] = ir_buffer[jj+1];
+                ir_buffer[jj+1] = testdata_temp;
+            }
+        }
+    }
+    HX3918_LOG("hx3918_factroy_test4\n");
+    if(test_mode == LEAK_LIGHT_TEST)
+    {
+        hx3918_write_reg(0X2a, 0x00);
+        hx3918_write_reg(0X2b, 0x00);
+        hx3918_delay(100);
+        for(ii=0; ii<4; ii++) //40ms read data
+        {
+            hx3918_delay(40);
+            hx3918_factory_test_read(ps_data);
+            green_led_data = ps_data[1] - ps_data[0];
+            red_led_data = ps_data[2] - ps_data[0];
+            ir_led_data = ps_data[3] - ps_data[0];
+            green_psdif[ii] = green_led_data;
+            ir_psdif[ii] = ir_led_data;
+            red_psdif[ii] = red_led_data;
+        }
+        for(jj=0; jj<3-ii; jj++)
+        {
+            if(green_psdif[jj]>=green_psdif[jj+1])
+            {
+                testdata_temp = green_psdif[jj];
+                green_psdif[jj] = green_psdif[jj+1];
+                green_psdif[jj+1] = testdata_temp;
+            }
+
+            if(red_psdif[jj]>=red_psdif[jj+1])
+            {
+                testdata_temp = red_psdif[jj];
+                red_psdif[jj] = red_psdif[jj+1];
+                red_psdif[jj+1] = testdata_temp;
+            }
+            if(ir_psdif[jj]>=ir_psdif[jj+1])
+            {
+                testdata_temp = ir_psdif[jj];
+                ir_psdif[jj] = ir_psdif[jj+1];
+                ir_psdif[jj+1] = testdata_temp;
+            }
+        }
+    }
+
+    switch(test_mode)
+    {
+        case LEAK_LIGHT_TEST:
+            green_final = (green_buffer[1]+green_buffer[2])/2-(green_psdif[1]+green_psdif[2])/2;
+            red_final = (red_buffer[1]+red_buffer[2])/2-(red_psdif[1]+red_psdif[2])/2;
+            ir_final = (ir_buffer[1]+ir_buffer[2])/2-(ir_psdif[1]+ir_psdif[2])/2;
+            break;
+        case GRAY_CARD_TEST:
+            green_final = (green_buffer[1]+green_buffer[2])/2;
+            red_final = (red_buffer[1]+red_buffer[2])/2;
+            ir_final = (ir_buffer[1]+ir_buffer[2])/2;
+            break;
+        default:
+            break;
+    }
+    if(green_final<0)
+    {
+        green_final = 0;
+    }
+    if(red_final<0)
+    {
+        red_final = 0;
+    }
+    if(ir_final<0)
+    {
+        ir_final = 0;
+    }
+    factory_reslts.green_data_final = green_final;
+    factory_reslts.red_data_final = red_final;
+    factory_reslts.ir_data_final = ir_final;
+    HX3918_LOG("%d %d %d\r\n",factory_reslts.green_data_final, factory_reslts.red_data_final,factory_reslts.ir_data_final);
+    return factory_reslts;
+}
diff --git a/2.sdk/sdk/gui/lv_drivers/indev/HX3918/hx3918_factory_test.h b/2.sdk/sdk/gui/lv_drivers/indev/HX3918/hx3918_factory_test.h
new file mode 100644 (file)
index 0000000..a15cfb4
--- /dev/null
@@ -0,0 +1,41 @@
+#ifndef _hx3918_FACTORY_TEST_H_
+#define _hx3918_FACTORY_TEST_H_
+
+#include <stdint.h>
+#include <stdbool.h>
+
+#define FT_OPEN_G_LED_LTH     3000 
+#define FT_OPEN_R_LED_LTH     3000
+#define FT_OPEN_IR_LED_LTH    3000
+
+#define FT_CARD_G_LED_HTH     200000 
+#define FT_CARD_R_LED_HTH     400000
+#define FT_CARD_IR_LED_HTH    400000
+
+typedef enum {
+       LEAK_LIGHT_TEST = 1,
+       GRAY_CARD_TEST = 2,
+       FT_INT_TEST = 3
+} TEST_MODE_t;
+
+typedef struct {
+    int32_t green_data_final;
+    int32_t red_data_final;
+    int32_t ir_data_final;
+} factory_result_t;
+
+
+//void hx3918_factory_test_config(void);
+void hx3918_factory_ft_leak_light_test_config(void);
+void hx3918_factory_ft_card_test_config(void);
+void hx3918_factory_ft_int_test_config(void);
+
+bool hx3918_factory_test_read(int32_t *ps_data);
+factory_result_t hx3918_factroy_test(uint32_t  test_mode);
+
+
+#endif // _hx3918_FACTORY_TEST_H_
+
+
+
+
diff --git a/2.sdk/sdk/gui/lv_drivers/indev/HX3918/hx3918_hrs_agc.c b/2.sdk/sdk/gui/lv_drivers/indev/HX3918/hx3918_hrs_agc.c
new file mode 100644 (file)
index 0000000..bddbf9d
--- /dev/null
@@ -0,0 +1,753 @@
+#include <stdio.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <math.h>
+
+//#include "tyhx_hrs_custom.h"
+
+#include "hx3918.h"
+#include "hx3918_hrs_agc.h"
+#include "tyhx_hrs_alg.h"
+#ifdef SAR_ALG_LIB
+#include "hx3918_prox.h"
+#endif
+
+#ifdef HRS_ALG_LIB
+
+extern uint8_t hx3918_hrs_agc_idac;
+extern uint8_t green_led_max_init;
+extern uint8_t low_vbat_flag;
+extern uint8_t read_fifo_first_flg;
+
+extern const int32_t  hrs_ir_unwear_thres;
+extern const int32_t  hrs_ir_wear_thres;
+
+static uint8_t s_ppg_state = 0;
+static uint8_t s_cal_state = 0;
+static int32_t agc_buf[4] = {0};
+
+static uint8_t cal_delay = CAL_DELAY_COUNT;
+static HRS_CAL_SET_T  calReg;
+
+static hx3918_hrs_wear_msg_code_t hrs_wear_status = MSG_HRS_INIT;
+static hx3918_hrs_wear_msg_code_t hrs_wear_status_pre = MSG_HRS_INIT;
+
+static uint8_t no_touch_cnt = 0;
+
+void hx3918_hrs_ppg_init(void) //20200615 ericy ppg fs=25hz, phase3 conversion ready interupt en
+{
+    uint16_t sample_rate = 25;                  /*config the data rate of chip alps2_fm ,uint is Hz*/
+    uint32_t prf_clk_num = 32000/sample_rate;   /*period in clk num, num = Fclk/fs */
+
+    uint8_t ps0_enable=1;       /*ps0_enable  , 1 mean enable ; 0 mean disable */
+    uint8_t ps1_enable=1;       /*ps1_enable  , 1 mean enable ; 0 mean disable */
+    uint8_t ps2_enable=1;       /*ps0_enable  , 1 mean enable ; 0 mean disable */
+    uint8_t ps3_enable=1;       /*ps1_enable  , 1 mean enable ; 0 mean disable */
+
+    uint8_t ps0_osr = 1;    /* 0 = 128 ; 1 = 256 ; 2 = 512 ; 3 = 1024 */
+    uint8_t ps1_osr = 1;    /* 0 = 128 ; 1 = 256 ; 2 = 512 ; 3 = 1024 */
+    uint8_t ps2_osr = 3;    /* 0 = 128 ; 1 = 256 ; 2 = 512 ; 3 = 1024 */
+    uint8_t ps3_osr = 3;    /* 0 = 128 ; 1 = 256 ; 2 = 512 ; 3 = 1024 */
+
+    uint8_t ps3_cp_avg_num_sel= 0;
+    uint8_t ps2_cp_avg_num_sel= 2;
+    uint8_t ps1_cp_avg_num_sel= 0;
+    uint8_t ps0_cp_avg_num_sel= 0;
+
+    uint8_t ps3_avg_num_sel_i2c=0;
+    uint8_t ps2_avg_num_sel_i2c=0;
+    uint8_t ps1_avg_num_sel_i2c=0;
+    uint8_t ps0_avg_num_sel_i2c=0;
+
+    /***********led open enable***********/
+
+    uint8_t ps0_led_en_i2c=1;
+    uint8_t ps1_led_en_i2c=0;
+    uint8_t ps2_led_en_i2c=1;
+    uint8_t ps3_led_en_i2c=0;
+
+    uint8_t ps0_ofidac_en_i2c=1;
+    uint8_t ps1_ofidac_en_i2c=1;
+    uint8_t ps2_ofidac_en_i2c=1;
+    uint8_t ps3_ofidac_en_i2c=1;
+
+    uint8_t dccancel_ps0 =0;    //offset idac   BIT[9:0]  0 31.25nA, 1023 32uA, step 31.25nA
+    uint8_t dccancel_ps1 =0;   //offset idac   BIT[9:0]  0 31.25nA, 1023 32uA, step 31.25nA
+    uint8_t dccancel_ps2 =0;    //offset idac   BIT[9:0]  0 31.25nA, 1023 32uA, step 31.25nA
+    uint8_t dccancel_ps3 =0;    //offset idac   BIT[9:0]  0 31.25nA, 1023 32uA, step 31.25nA
+
+    uint8_t leddrive_ps0 =64;     //LEDDRIVE_PS0  0~255 = 0~200ma
+    uint8_t leddrive_ps1 =0;     //LEDDRIVE_PS1  0~255 = 0~200ma
+    uint8_t leddrive_ps2 =0;    //LEDDRIVE_PS2  0~255 = 0~200ma
+    uint8_t leddrive_ps3 =0;     //LEDDRIVE_PS3  0~255 = 0~200ma
+
+    uint8_t led_en_begin =1;       // 0 = 2 ; 1 = 4 ; 2 = 8 ; 3 = 16 ;
+    uint8_t afe_reset = 1;        //* 0 = 32clk ; 1 = 64clk ; 2 = 128clk ; 3 = 256clk(d) ;
+    uint8_t en2rst_delay =3;      // pen 2 rst delay 0 = 128,256, 512, 1024
+    uint8_t init_wait_delay = 2; /* 0 = 800 ; 1 = 1600; 2 = 3200 ; 3 = 6400(d) */
+
+    uint8_t ps1_interval_i2c =0;    // ps2/ps3
+
+    uint8_t thres_int =1;    //thres int enable
+    uint8_t data_rdy_int =8;    //[3]:ps1_data2 [2]:ps1_data1 [1]:ps0_data2 [0]:ps0_data1
+
+
+    uint8_t ldrsel_ps0 =IR_LED_SLE;
+    uint8_t ldrsel_ps1 =0;
+    uint8_t ldrsel_ps2 =GREEN_LED_SLE;
+    uint8_t ldrsel_ps3 =0;
+
+    /***********cap *********/
+    uint8_t intcapsel_ps3 =5;   //00=4fp 01=8pf 02=12pf 03=16pf 04=20pf 05=24pf 06=28pf 07=32pf 08=36pf 09=40pf 10=44pf 11=48pf 12=52pf 13=56pf 14=60pf
+    uint8_t intcapsel_ps2 =5;   //00=4fp 01=8pf 02=12pf 03=16pf 04=20pf 05=24pf 06=28pf 07=32pf 08=36pf 09=40pf 10=44pf 11=48pf 12=52pf 13=56pf 14=60pf
+    uint8_t intcapsel_ps1 =5;   //00=4fp 01=8pf 02=12pf 03=16pf 04=20pf 05=24pf 06=28pf 07=32pf 08=36pf 09=40pf 10=44pf 11=48pf 12=52pf 13=56pf 14=60pf
+    uint8_t intcapsel_ps0 =5;   //00=4fp 01=8pf 02=12pf 03=16pf 04=20pf 05=24pf 06=28pf 07=32pf 08=36pf 09=40pf 10=44pf 11=48pf 12=52pf 13=56pf 14=60pf
+
+    uint8_t ps0_led_on_time=16;    /* 0 = 32clk2=8us ; 8 = 64clk=16us; 16=128clk=32us ; 32 = 256clk=64us ;
+                                     64 = 512clk=128us ; 128= 1024clk=256us; 256= 2048clk=512us*/
+    uint8_t ps1_led_on_time=16;    /* 0 = 32clk2=8us ; 8 = 64clk=16us; 16=128clk=32us ; 32 = 256clk=64us ;
+                                     64 = 512clk=128us ; 128= 1024clk=256us; 256= 2048clk=512us*/
+    uint8_t ps2_led_on_time=64;    /* 0 = 32clk2=8us ; 8 = 64clk=16us; 16=128clk=32us ; 32 = 256clk=64us ;
+                                     64 = 512clk=128us ; 128= 1024clk=256us; 256= 2048clk=512us*/
+    uint8_t ps3_led_on_time=64;    /* 0 = 32clk2=8us ; 8 = 64clk=16us; 16=128clk=32us ; 32 = 256clk=64us ;
+                                     64 = 512clk=128us ; 128= 1024clk=256us; 256= 2048clk=512us*/
+
+    uint8_t force_adc_clk_sel=0;
+    uint8_t force_adc_clk_cfg =0;
+    uint8_t force_PEN =0;     //phase enable
+    uint8_t force_PEN_cfg =0;
+    uint8_t force_LED_EN =0;
+    uint8_t force_LED_EN_cfg =0;
+    uint8_t force_CKAFEINT_sel =0;
+    uint8_t force_CKAFEINT_cfg =0;
+
+#ifdef SAR_ALG_LIB
+               hx3918_set_cap_data_ready(0);
+#endif
+
+    hx3918_write_reg(0X16, (ps3_enable<<3| ps2_enable<<2|ps1_enable<<1|ps0_enable));
+    hx3918_write_reg(0X17, (ps3_osr<<6| ps2_osr<<4|ps1_osr<<2|ps0_osr));
+    hx3918_write_reg(0X18, (uint8_t)prf_clk_num);
+    hx3918_write_reg(0X19, (uint8_t)(prf_clk_num>>8));
+    hx3918_write_reg(0X1a, (ps1_interval_i2c));
+    hx3918_write_reg(0X1b, led_en_begin<<6|afe_reset<<4|en2rst_delay <<2|init_wait_delay);
+    //hx3918_write_reg(0X1b, 0x03);
+    hx3918_write_reg(0X1c, ps0_led_on_time);
+    hx3918_write_reg(0X1d, ps1_led_on_time);
+    hx3918_write_reg(0X1e, ps2_led_on_time);
+    hx3918_write_reg(0X1f, ps3_led_on_time);
+    hx3918_write_reg(0X20, (ps3_cp_avg_num_sel<<6|ps2_cp_avg_num_sel<<4|ps1_cp_avg_num_sel<<2|ps0_cp_avg_num_sel)); 
+    hx3918_write_reg(0X21, (ps3_avg_num_sel_i2c<<6|ps2_avg_num_sel_i2c<<4|ps1_avg_num_sel_i2c<<2|ps0_avg_num_sel_i2c));
+    hx3918_write_reg(0X23, (ps0_led_en_i2c<<7|ps1_led_en_i2c<<6|ps2_led_en_i2c<<5|ps3_led_en_i2c<<4|ps0_ofidac_en_i2c<<3|ps1_ofidac_en_i2c<<2|ps2_ofidac_en_i2c<<1|ps3_ofidac_en_i2c));
+    hx3918_write_reg(0X24, (intcapsel_ps0<<4|intcapsel_ps1));
+    hx3918_write_reg(0X25, (intcapsel_ps2<<4|intcapsel_ps3));
+    hx3918_write_reg(0X26, leddrive_ps0);
+    hx3918_write_reg(0X27, leddrive_ps1);
+    hx3918_write_reg(0X28, leddrive_ps2);
+    hx3918_write_reg(0X29, leddrive_ps3);
+    hx3918_write_reg(0X2a, (ldrsel_ps0<<4|ldrsel_ps1));
+    hx3918_write_reg(0X2b, (ldrsel_ps2<<4|ldrsel_ps3));
+    hx3918_write_reg(0X2c, dccancel_ps0);
+    hx3918_write_reg(0X2d, dccancel_ps1);
+    hx3918_write_reg(0X2e, dccancel_ps2);
+    hx3918_write_reg(0X2f, dccancel_ps3);
+    hx3918_write_reg(0X36, (thres_int<<4|data_rdy_int));
+    hx3918_write_reg(0X4e, (force_adc_clk_sel<<7|force_adc_clk_cfg<<6|force_PEN<<5|force_PEN_cfg<<4|force_LED_EN<<3|
+                            force_LED_EN_cfg<<2|force_CKAFEINT_sel<<1|force_CKAFEINT_cfg));
+
+    hx3918_write_reg(0X6d, 0x00);
+    hx3918_write_reg(0XF0, 0x22);
+    hx3918_write_reg(0xF1, 0x28);
+    hx3918_write_reg(0xF2, 0x04);
+    hx3918_write_reg(0xF3, 0x70);
+    hx3918_write_reg(0xF4, 0x32);
+    hx3918_write_reg(0xF5, 0x89);
+    hx3918_write_reg(0xF6, 0x2b);
+    hx3918_write_reg(0xF7, 0x85);
+    hx3918_write_reg(0xF8, 0x27);
+    hx3918_write_reg(0xF9, 0x00);
+    hx3918_write_reg(0xFA, 0x88);
+    hx3918_write_reg(0xFB, 0x40);
+    hx3918_write_reg(0Xf6, 0X2b);
+
+#if defined(TIMMER_MODE)
+    hx3918_write_reg(0x3d, 0x83);    //bits<3:0> fifo data sel, 0000 = p1;0001= p2;0010=p3;0011=p4;bits<7> fifo enble
+    hx3918_write_reg(0x3e, 0x20);      //watermark
+    hx3918_write_reg(0x3c, 0x1f);    // int_width_i2c
+    hx3918_write_reg(0X37, 0x00);   // int sel,01=prf int,04=enable almost full int
+    hx3918_write_reg(0X3b, 0x00);
+    hx3918_write_reg(0X3b, 0x10);
+#else ///////////INT Mode
+    hx3918_write_reg(0x3d, 0x00);    //bits<3:0> fifo data sel, 0000 = p1;0001= p2;0010=p3;0011=p4;bits<7> fifo enble
+    hx3918_write_reg(0x3c, 0x1f);    // int_width_i2c
+    hx3918_write_reg(0x37, 0x04);   // int sel,01=prf ,04=enable almost full
+#endif
+
+    hx3918_write_reg(0x4d, 0x01);   //soft reset
+    hx3918_delay(5);
+    hx3918_write_reg(0x4d, 0x00);   //release
+    hx3918_delay(5);
+    read_fifo_first_flg = 1;
+}
+
+void Init_hrs_PPG_Calibration_Routine(HRS_CAL_SET_T *calR)
+{
+    calR->flag = CAL_FLG_LED_DR|CAL_FLG_LED_DAC|CAL_FLG_AMB_DAC|CAL_FLG_RF;
+
+    calR->led_idac   = 0;
+    calR->amb_idac   = 0;
+    calR->ontime     = 5;
+    calR->led_cur    = HRS_CAL_INIT_LED;
+    calR->state      = hrsCalStart;
+    calR->int_cnt    = 0;
+    calR->cur255_cnt = 0;
+    if(low_vbat_flag==1)
+    {
+        calR->led_max_cur = green_led_max_init>>1;
+    }
+    else
+    {
+        calR->led_max_cur = green_led_max_init;
+    }
+}
+
+void Restart_hrs_PPG_Calibration_Routine(HRS_CAL_SET_T *calR)
+{
+    calR->flag = CAL_FLG_LED_DAC;
+    calR->state = hrsCalLed;
+    calR->int_cnt = 0;
+}
+
+hx3918_hrs_wear_msg_code_t hx3918_hrs_wear_mode_check(int32_t infrared_data)
+{
+    int32_t check_thre = 0;
+               int16_t sar_data = 32767;
+#ifdef SAR_ALG_LIB
+       sar_data = hx90xx_get_prox_data();
+#endif
+    if(hrs_wear_status == MSG_HRS_NO_WEAR)
+    {
+        check_thre = hrs_ir_wear_thres;
+    }
+    else
+    {
+        check_thre = hrs_ir_unwear_thres;
+    }
+
+    if(infrared_data < check_thre || sar_data < sar_unwear_thres)
+    {
+        if(no_touch_cnt < NO_TOUCH_CHECK_NUM)
+        {
+            no_touch_cnt++;
+        }
+        if(no_touch_cnt >= NO_TOUCH_CHECK_NUM)
+        {
+            hrs_wear_status = MSG_HRS_NO_WEAR;
+        }
+    }
+    else if(infrared_data >= check_thre && sar_data > sar_wear_thres)
+    {
+        if(no_touch_cnt>0)
+        {
+            no_touch_cnt--;
+        }
+        if(no_touch_cnt == 0)
+        {
+            hrs_wear_status = MSG_HRS_WEAR;
+        }
+    }
+    //AGC_LOG("hrs wear: ir=%d,  %x\r\n",infrared_data,hx3918_read_reg(0x6a));
+    //AGC_LOG("hrs wearstates: hrs_wear_status_pre=%d,hrs_wear_status=%d\r\n",\
+    //hrs_wear_status_pre,hrs_wear_status);
+
+       //hrs_wear_status = hx3918_get_wear_result(hrs_wear_status);
+       //HX3918_LOG("[hx3918_hrs_wear_mode_check end] final result = %d\r\n",hrs_wear_status);
+    if(hrs_wear_status_pre != hrs_wear_status)
+    {
+        hrs_wear_status_pre = hrs_wear_status;
+        if(hrs_wear_status == MSG_HRS_NO_WEAR)
+        {
+            hx3918_hrs_low_power();
+        }
+        else if(hrs_wear_status == MSG_HRS_WEAR)
+        {
+            tyhx_hrs_alg_open_deep();
+            hx3918_hrs_set_mode(PPG_INIT);
+            hx3918_hrs_set_mode(CAL_INIT);
+        }
+    }
+    return hrs_wear_status;
+}
+
+/*
+hx3918_hrs_wear_msg_code_t hx3918_hrs_check_unwear(int32_t infrared_data)
+{
+    AGC_LOG("infrared_data=%d,hrs_wear_status=%d\r\n",infrared_data,hrs_wear_status);
+    if(infrared_data < hrs_ir_unwear_thres)
+    {
+        if(no_touch_cnt == NO_TOUCH_CHECK_NUM)
+        {
+            hrs_wear_status = MSG_HRS_NO_WEAR;
+            if(hrs_wear_status_pre != hrs_wear_status)
+            {
+                hx3918_hrs_low_power();
+            }
+        }
+        else
+        {
+            no_touch_cnt++;
+        }
+    }
+    else
+    {
+        no_touch_cnt = 0;
+    }
+    hrs_wear_status_pre = hrs_wear_status;
+    return hrs_wear_status;
+}
+*/
+void PPG_hrs_Calibration_Routine(HRS_CAL_SET_T *calR, int32_t led, int32_t amb)
+{
+    switch(calR->state)
+    {
+    case hrsCalStart:
+        calR->state = hrsLedCur;
+        break;
+
+    case hrsLedCur:
+        if(amb>280000)
+        {
+            calR->amb_idac = (amb-280000)/10000;
+        }
+        else
+        {
+            calR->amb_idac = 0;
+        }
+        if(led>amb+128)
+        {
+            calR->led_step = (led-amb)/HRS_CAL_INIT_LED;
+            calR->led_cur = 5000*(hx3918_hrs_agc_idac+calR->amb_idac)/calR->led_step;
+            if(calR->led_cur>calR->led_max_cur)
+            {
+                calR->led_cur = calR->led_max_cur;
+            }
+            calR->led_idac = hx3918_hrs_agc_idac>>1;
+            calR->ontime = 64;
+            calR->flag = CAL_FLG_LED_DR|CAL_FLG_LED_DAC|CAL_FLG_AMB_DAC|CAL_FLG_RF;
+            calR->state = hrsCalLed;
+        }
+        else
+        {
+            calR->led_cur = calR->led_max_cur;
+            calR->led_idac = hx3918_hrs_agc_idac>>1;
+            calR->ontime = 64;
+            calR->flag = CAL_FLG_LED_DR|CAL_FLG_LED_DAC|CAL_FLG_AMB_DAC|CAL_FLG_RF;
+            calR->state = hrsCalLed;
+        }
+        break;
+
+    case hrsCalLed:
+        if(led>350000 && calR->led_idac<=120)
+        {
+            calR->led_idac = calR->led_idac + 1;
+            calR->state = hrsCalLed;
+        }
+        else if(led<150000 && calR->led_idac>=1)
+        {
+            calR->led_idac = calR->led_idac - 1;
+            calR->state = hrsCalLed;
+        }
+        else
+        {
+            calR->state = hrsCalFinish;
+        }
+        calR->flag = CAL_FLG_LED_DAC;
+        break;
+
+    default:
+        break;
+
+    }
+    AGC_LOG("AGC: led_drv=%d,ledDac=%d,ambDac=%d,ledstep=%d,ontime=%d,state=%d\r\n",\
+            calR->led_cur, calR->led_idac, calR->amb_idac,calR->led_step,calR->ontime,calR->state);
+}
+
+HRS_CAL_SET_T PPG_hrs_agc(void)
+{
+    int32_t led_val, amb_val;
+    calReg.work = false;
+    if (!s_cal_state)
+    {
+        return  calReg;
+    }
+
+#ifdef INT_MODE
+    calReg.int_cnt ++;
+    if(calReg.int_cnt < 4)
+    {
+        return calReg;
+    }
+    calReg.int_cnt = 0;
+    hx3918_gpioint_cfg(false);
+#endif
+    calReg.work = true;
+
+    read_data_packet(agc_buf);
+    led_val = agc_buf[2];
+    amb_val = agc_buf[3];
+
+    AGC_LOG("cal dat led_val=%d,amb_val=%d \r\n", led_val, amb_val);
+
+    PPG_hrs_Calibration_Routine(&calReg, led_val, amb_val);
+
+    if (calReg.state == hrsCalFinish)
+    {
+        hx3918_hrs_set_mode(CAL_OFF);
+    }
+    else
+    {
+        hx3918_hrs_updata_reg();
+    }
+    #if defined(INT_MODE)
+    hx3918_gpioint_cfg(true);
+    #endif
+    
+    return  calReg;
+}
+
+void hx3918_hrs_cal_init(void) // 20200615 ericy afe cali online
+{
+    uint16_t sample_rate = 100;                      /*config the data rate of chip alps2_fm ,uint is Hz*/
+    uint32_t prf_clk_num = 32000/sample_rate;        /*period in clk num, num = Fclk/fs */
+    uint8_t thres_int =0;    //thres int enable
+    uint8_t data_rdy_int =8;    //[3]:ps1_data2 [2]:ps1_data1 [1]:ps0_data2 [0]:ps0_data1
+#ifdef SAR_ALG_LIB
+               hx3918_set_cap_data_ready(0);
+#endif
+    hx3918_write_reg(0X18, (uint8_t)prf_clk_num);    // prf bit<7:0>6   default 0x00
+    hx3918_write_reg(0X19, (uint8_t)(prf_clk_num>>8)); // prf bit<15:8>  default 0x03
+    hx3918_write_reg(0x3d,0x00);     //bits<3:0> fifo data sel, 0000 = p1;0001= p2;0010=p3;0011=p4;bits<7> fifo enble
+    hx3918_write_reg(0X36, (thres_int<<4|data_rdy_int));   //default 0x0f
+
+    hx3918_write_reg(0X4d, 0X01);  //soft reset
+    hx3918_delay(5);
+    hx3918_write_reg(0X4d, 0X00);  //release
+    hx3918_delay(5);             //Delay for reset time
+}
+
+void hx3918_hrs_cal_off(void) // 20200615 ericy afe cali offline
+{
+    uint16_t sample_rate = 25;                      /*config the data rate of chip alps2_fm ,uint is Hz*/
+    uint32_t prf_clk_num = 32000/sample_rate;        /*period in clk num, num = Fclk/fs */
+
+    uint8_t thres_int =0;    //thres int enable
+    uint8_t data_rdy_int =0;    //[3]:ps1_data2 [2]:ps1_data1 [1]:ps0_data2 [0]:ps0_data1
+
+    hx3918_write_reg(0X18, (uint8_t)prf_clk_num);    // prf bit<7:0>6   default 0x00
+    hx3918_write_reg(0X19, (uint8_t)(prf_clk_num>>8)); // prf bit<15:8>  default 0x03
+
+    hx3918_write_reg(0x3d, 0x83);     //bits<3:0> fifo data sel, 0000 = p1;0001= p2;0010=p3;0011=p4;bits<7> fifo enble
+    hx3918_write_reg(0X36, (thres_int<<4|data_rdy_int));   //default 0x0f
+
+    hx3918_write_reg(0X4d, 0X01);  //soft reset
+    hx3918_delay(5);
+    hx3918_write_reg(0X4d, 0X00);  //release
+    hx3918_delay(5);             //Delay for reset time
+#ifdef SAR_ALG_LIB
+    hx3918_prox_reg_init();
+#endif
+    read_fifo_first_flg = 1;
+}
+
+void hx3918_hrs_low_power(void)
+{
+    uint16_t sample_rate = 10;                  /*config the data rate of chip alps2_fm ,uint is Hz*/
+    uint32_t prf_clk_num = 32000/sample_rate;   /*period in clk num, num = Fclk/fs */
+
+    uint8_t ps3_cp_avg_num_sel= 0;
+    uint8_t ps2_cp_avg_num_sel= 0;
+    uint8_t ps1_cp_avg_num_sel= 0;
+    uint8_t ps0_cp_avg_num_sel= 0;
+
+    uint8_t ps3_avg_num_sel_i2c=0;
+    uint8_t ps2_avg_num_sel_i2c=0;
+    uint8_t ps1_avg_num_sel_i2c=0;
+    uint8_t ps0_avg_num_sel_i2c=0;
+
+    uint8_t ps0_led_en_i2c=1;
+    uint8_t ps1_led_en_i2c=0;
+    uint8_t ps2_led_en_i2c=0;
+    uint8_t ps3_led_en_i2c=0;
+
+    uint8_t dccancel_ps0 =0;    //offset idac   BIT[9:0]  0 31.25nA, 1023 32uA, step 31.25nA
+    uint8_t dccancel_ps1 =0;    //offset idac   BIT[9:0]  0 31.25nA, 1023 32uA, step 31.25nA
+    uint8_t dccancel_ps2 =0;    //offset idac   BIT[9:0]  0 31.25nA, 1023 32uA, step 31.25nA
+    uint8_t dccancel_ps3 =0;    //offset idac   BIT[9:0]  0 31.25nA, 1023 32uA, step 31.25nA
+
+    uint8_t leddrive_ps0 =64;    //LEDDRIVE_PS0  0~255 = 0~200ma
+    uint8_t leddrive_ps1 =0;     //LEDDRIVE_PS1  0~255 = 0~200ma
+    uint8_t leddrive_ps2 =0;     //LEDDRIVE_PS2  0~255 = 0~200ma
+    uint8_t leddrive_ps3 =0;     //LEDDRIVE_PS3  0~255 = 0~200ma
+
+    hx3918_write_reg(0X18, (uint8_t)prf_clk_num);    // prf bit<7:0>6   default 0x00
+    hx3918_write_reg(0X19, (uint8_t)(prf_clk_num>>8)); // prf bit<11:8>  default 0x03
+    hx3918_write_reg(0X20, (ps3_cp_avg_num_sel<<6|ps2_cp_avg_num_sel<<4|ps1_cp_avg_num_sel<<2|ps0_cp_avg_num_sel) );
+    hx3918_write_reg(0X21, (ps3_avg_num_sel_i2c<<6|ps2_avg_num_sel_i2c<<4|ps1_avg_num_sel_i2c<<2|ps0_avg_num_sel_i2c));
+    hx3918_write_reg(0X23, (ps0_led_en_i2c<<7|ps1_led_en_i2c<<6|ps2_led_en_i2c<<5|ps3_led_en_i2c<<4|0x0f));
+
+    hx3918_write_reg(0X26, leddrive_ps0);
+    hx3918_write_reg(0X27, leddrive_ps1);
+    hx3918_write_reg(0X28, leddrive_ps2);
+    hx3918_write_reg(0X29, leddrive_ps3);
+
+    hx3918_write_reg(0X2c, dccancel_ps0);
+    hx3918_write_reg(0X2d, dccancel_ps1);
+    hx3918_write_reg(0X2e, dccancel_ps2);
+    hx3918_write_reg(0X2f, dccancel_ps3);
+
+    hx3918_write_reg(0x4d, 0x01);  //soft reset
+    hx3918_delay(5);
+    hx3918_write_reg(0x4d, 0x00);  //release
+    hx3918_delay(5);
+    calReg.led_cur = 0;
+#ifdef SAR_ALG_LIB
+               hx3918_prox_reg_init();
+#endif
+    read_fifo_first_flg = 1;
+    AGC_LOG(" chip go to low power mode  \r\n" );
+
+}
+
+void hx3918_hrs_updata_reg(void)
+{
+    if (calReg.flag & CAL_FLG_LED_DR)
+    {
+        hx3918_write_reg(0X28, calReg.led_cur);
+    }
+
+    if (calReg.flag & CAL_FLG_LED_DAC)
+    {
+        hx3918_write_reg(0X2e, (uint8_t)calReg.led_idac);
+    }
+
+    if (calReg.flag & CAL_FLG_AMB_DAC)
+    {
+        hx3918_write_reg(0X2f, (uint8_t)calReg.amb_idac);
+    }
+
+    if (calReg.flag & CAL_FLG_RF)
+    {
+        hx3918_write_reg(0X1e, calReg.ontime); //3918 p2
+        hx3918_write_reg(0X1f, calReg.ontime); //3918 p3
+    }
+}
+
+void hx3918_hrs_set_mode(uint8_t mode_cmd)
+{
+    switch (mode_cmd)
+    {
+    case PPG_INIT:
+        hx3918_hrs_ppg_init();
+        #if defined(TIMMER_MODE)
+        hx3918_ppg_timer_cfg(true);
+        #else
+        hx3918_gpioint_cfg(true);
+        #endif
+        s_ppg_state = 1;
+        AGC_LOG("ppg init mode\r\n");
+        break;
+
+    case PPG_OFF:
+        hx3918_ppg_off();
+        s_ppg_state = 0;
+        AGC_LOG("ppg off mode\r\n");
+        break;
+
+    case PPG_LED_OFF:
+        hx3918_hrs_low_power();
+        s_ppg_state = 0;
+        AGC_LOG("ppg led off mode\r\n");
+        break;
+
+    case CAL_INIT:
+        Init_hrs_PPG_Calibration_Routine(&calReg);
+        hx3918_hrs_cal_init();
+        hx3918_hrs_updata_reg();
+        #if defined(TIMMER_MODE)
+        hx3918_agc_timer_cfg(true);
+        #endif
+        s_cal_state = 1;
+        AGC_LOG("cal init mode\r\n");
+        break;
+
+    case RECAL_INIT:
+        Restart_hrs_PPG_Calibration_Routine(&calReg);
+        hx3918_hrs_cal_init();
+        hx3918_hrs_updata_reg();
+        #if defined(TIMMER_MODE)
+        hx3918_agc_timer_cfg(true);
+        #endif
+        s_cal_state = 1;
+        AGC_LOG("Recal init mode\r\n");
+        break;
+
+    case CAL_OFF:
+        #if defined(TIMMER_MODE)
+        hx3918_agc_timer_cfg(false);
+        #endif
+        hx3918_hrs_cal_off();
+        s_cal_state = 0;
+        AGC_LOG("cal off mode\r\n");
+        break;
+
+    default:
+        break;
+    }
+}
+
+SENSOR_ERROR_T hx3918_hrs_enable(void)
+{
+    if (!hx3918_chip_check())
+    {
+        TYHX_LOG("hx3918 check id failed!\r\n");
+        return SENSOR_OP_FAILED;
+    }
+    else
+    {
+        TYHX_LOG("hx3918 check id success!\r\n");
+    }
+    if (s_ppg_state)
+    {
+        TYHX_LOG("ppg already on!\r\n");
+        return SENSOR_OP_FAILED;
+    }
+    if(!tyhx_hrs_alg_open())
+    {
+        TYHX_LOG("hrs alg open fail,or dynamic ram not enough!\r\n");
+    }
+
+    hrs_wear_status = MSG_HRS_INIT;
+    hrs_wear_status_pre = MSG_HRS_INIT;
+    hx3918_hrs_set_mode(PPG_INIT);
+    TYHX_LOG("hx3918 enable!\r\n");
+
+    return SENSOR_OK;
+}
+
+void hx3918_hrs_disable(void)
+{
+#if defined(TIMMER_MODE)
+    hx3918_ppg_timer_cfg(false);
+    hx3918_agc_timer_cfg(false);
+    #elif defined(INT_MODE)
+    hx3918_gpioint_cfg(false);
+    #endif
+    hx3918_hrs_set_mode(PPG_OFF);
+    s_ppg_state = 0;
+    s_cal_state = 0;
+    tyhx_hrs_alg_close();
+}
+
+void hx3918_hrs_data_reset(void)
+{
+    s_ppg_state = 0;
+    s_cal_state = 0;
+    tyhx_hrs_alg_close();
+}
+
+hx3918_hrs_wear_msg_code_t hx3918_hrs_get_wear_status(void)
+{
+    return  hrs_wear_status;
+}
+
+HRS_CAL_SET_T get_hrs_agc_status(void)
+{
+    HRS_CAL_SET_T cal;
+    cal.flag     = calReg.flag;
+    cal.int_cnt  = calReg.int_cnt;
+    cal.led_cur  = calReg.led_cur;
+    cal.led_idac = calReg.led_idac;
+    cal.amb_idac = calReg.amb_idac;
+    cal.ontime   = calReg.ontime;
+    cal.led_step = calReg.led_step;
+    cal.state    = calReg.state;
+    return cal;
+}
+
+uint8_t hx3918_hrs_read(ppg_sensor_data_t * s_dat)
+{
+    int32_t PPG_src_data;
+    int32_t Ir_src_data;
+    bool recal = false;
+    int32_t *PPG_buf =  &(s_dat->green_data[0]);
+    int32_t *ir_buf =  &(s_dat->ir_data[0]);
+    int32_t *s_buf =  &(s_dat->s_buf[0]);
+    s_dat->green_cur =  calReg.led_cur;
+    //int32_t *sar_lp_data  = &s_dat->sar_data;
+    int32_t ps_data[4]= {0};
+    int32_t ps_green_data = 0;
+    uint8_t data_count = 0;
+
+    if (!s_ppg_state || s_cal_state)
+    {
+        return NULL;
+    }
+
+    read_data_packet(ps_data);
+    ps_green_data = ps_data[2];
+
+    data_count = hx3918_read_fifo_data(s_buf,2,1);
+    s_dat->count =  data_count;
+       //HX3918_LOG("hx3918_hrs_read data_count:%d\r\n         ",data_count);
+    for (uint8_t i=0; i<data_count; i++)
+    {
+        PPG_src_data = s_buf[i*2+1];
+        Ir_src_data = s_buf[i*2];
+        PPG_buf[i] = 2*PPG_src_data;
+        ir_buf[i] = Ir_src_data;
+               TYHX_LOG("%d    ",ir_buf[i]);
+        //HX3918_LOG("hx3918_hrs_read:ppg data size: %d\r\n", Ir_src_data);
+        hx3918_hrs_wear_mode_check(Ir_src_data);
+        
+        //DEBUG_PRINTF("%d/%d %d %d\r\n",1+i,data_count,PPG_buf[i],ir_buf[i]);
+    }
+       TYHX_LOG("\r\n");
+               
+               #ifdef SAR_ALG_LIB
+               if (hrs_wear_status == MSG_HRS_NO_WEAR)
+               {
+                       hx3918_cali_with_ir(Ir_src_data, hrs_ir_unwear_thres);
+               }
+               #endif
+               
+    if (ps_green_data<100000 || ps_green_data>400000)
+    {
+        recal = true;
+
+        if(hrs_wear_status==MSG_HRS_NO_WEAR)
+        {
+            recal = false;
+        }
+    }
+    if (recal)
+    {
+        cal_delay--;
+
+        if (cal_delay <= 0)
+        {
+            cal_delay = CAL_DELAY_COUNT;
+            hx3918_hrs_set_mode(RECAL_INIT);
+        }
+    }
+    else
+    {
+        cal_delay = CAL_DELAY_COUNT;
+    }
+    return 1;
+}
+#endif
+
+
+
+
diff --git a/2.sdk/sdk/gui/lv_drivers/indev/HX3918/hx3918_hrs_agc.h b/2.sdk/sdk/gui/lv_drivers/indev/HX3918/hx3918_hrs_agc.h
new file mode 100644 (file)
index 0000000..f657901
--- /dev/null
@@ -0,0 +1,68 @@
+#ifndef _hx3918_agc_H_
+#define _hx3918_agc_H_
+#include <stdint.h>
+#include <stdbool.h>
+#include "hx3918.h"
+
+#define CAL_DELAY_COUNT (3)
+
+#define CAL_FLG_LED_DR     0x01
+#define CAL_FLG_LED_DAC    0x02 
+#define CAL_FLG_AMB_DAC    0x04
+#define CAL_FLG_RF         0x08
+
+#define HRS_CAL_INIT_LED   64
+#define NO_TOUCH_CHECK_NUM 2
+
+
+typedef enum {      
+    hrsCalStart, 
+    hrsLedCur,
+    hrsCalLed,
+    hrsCalFinish, 
+}HRS_STATE_T;
+
+typedef struct {
+       uint8_t flag;
+       bool work;
+       uint8_t int_cnt;
+       uint8_t cur255_cnt;
+       uint16_t led_cur;
+       uint8_t led_idac; 
+       uint8_t amb_idac;
+       uint8_t ontime;
+       uint16_t led_step;
+       uint8_t state;
+       uint8_t led_max_cur;
+} HRS_CAL_SET_T;
+
+typedef enum {
+       MSG_HRS_NO_WEAR,
+       MSG_HRS_WEAR,
+       MSG_HRS_INIT
+} hx3918_hrs_wear_msg_code_t;
+
+void Init_hrs_PPG_Calibration_Routine(HRS_CAL_SET_T *calR);
+void Restart_hrs_PPG_Calibration_Routine(HRS_CAL_SET_T *calR);
+void PPG_hrs_Calibration_Routine(HRS_CAL_SET_T *calR, int32_t led, int32_t amb);
+HRS_CAL_SET_T PPG_hrs_agc(void);
+void hx3918_hrs_cal_init(void);
+void hx3918_hrs_cal_off(void);
+
+void hx3918_hrs_low_power(void);
+void hx3918_hrs_normal_power(void);
+void hx3918_hrs_updata_reg(void);
+void hx3918_hrs_set_mode(uint8_t mode_cmd);
+SENSOR_ERROR_T hx3918_hrs_enable(void);
+void hx3918_hrs_disable(void);
+hx3918_hrs_wear_msg_code_t hx3918_hrs_get_wear_status(void);
+uint8_t hx3918_hrs_read(ppg_sensor_data_t * s_dat);
+bool hx3918_hrs_init(void);
+
+hx3918_hrs_wear_msg_code_t hx3918_hrs_wear_mode_check(int32_t infrared_data);
+//hx3918_hrs_wear_msg_code_t hx3918_hrs_check_unwear(int32_t infrared_data);
+hx3918_hrs_wear_msg_code_t hx3918_hrs_check_wear(void);
+HRS_CAL_SET_T get_hrs_agc_status(void);
+void hx3918_hrs_data_reset(void);
+
+#endif
diff --git a/2.sdk/sdk/gui/lv_drivers/indev/HX3918/hx3918_hrv_agc.c b/2.sdk/sdk/gui/lv_drivers/indev/HX3918/hx3918_hrv_agc.c
new file mode 100644 (file)
index 0000000..3cf83f3
--- /dev/null
@@ -0,0 +1,969 @@
+#include <stdio.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <math.h>
+
+//#include "tyhx_hrs_custom.h"
+#include "hx3918_hrs_agc.h"
+#include "hx3918_hrv_agc.h"
+#include "tyhx_hrv_alg.h"
+#ifdef SAR_ALG_LIB
+#include "hx3918_prox.h"
+#endif
+//#ifdef TYHX_DEMO
+//#include "twi_master.h"
+//#include "SEGGER_RTT.h"
+//#endif
+
+#ifdef HRV_ALG_LIB
+
+extern const uint8_t  hx3918_hrs_agc_idac;
+extern const uint8_t  green_led_max_init;
+extern uint8_t low_vbat_flag;
+extern uint8_t read_fifo_first_flg;
+
+//hrv_INFRARED_THRES
+extern const int32_t  hrv_ir_unwear_thres;
+extern const int32_t  hrv_ir_wear_thres;
+
+static uint8_t s_ppg_state = 0;
+static uint8_t s_cal_state = 0;
+static int32_t agc_buf[4] = {0};
+
+static uint8_t cal_delay = CAL_DELAY_COUNT;
+static HRV_CAL_SET_T  calReg;
+//
+static hx3918_hrv_wear_msg_code_t hrv_wear_status = MSG_HRV_NO_WEAR;
+static hx3918_hrv_wear_msg_code_t hrv_wear_status_pre = MSG_HRV_NO_WEAR;
+
+static uint8_t no_touch_cnt = 0;
+
+void hx3918_hrv_ppg_init(void) //20200615 ericy ppg fs=25hz, phase3 conversion ready interupt en
+{
+    /* start cfg*/
+    uint16_t sample_rate = 125;                  /*config the data rate of chip alps2_fm ,uint is Hz*/
+    uint32_t prf_clk_num = 32000/sample_rate;   /*period in clk num, num = Fclk/fs */
+
+    uint8_t ps0_enable=1;       /*ps0_enable  , 1 mean enable ; 0 mean disable */
+    uint8_t ps1_enable=1;       /*ps1_enable  , 1 mean enable ; 0 mean disable */
+    uint8_t ps2_enable=1;       /*ps0_enable  , 1 mean enable ; 0 mean disable */
+    uint8_t ps3_enable=1;       /*ps1_enable  , 1 mean enable ; 0 mean disable */
+
+    uint8_t ps0_osr = 3;    /* 0 = 128 ; 1 = 256 ; 2 = 512 ; 3 = 1024 */
+    uint8_t ps1_osr = 3;    /* 0 = 128 ; 1 = 256 ; 2 = 512 ; 3 = 1024 */
+    uint8_t ps2_osr = 1;    /* 0 = 128 ; 1 = 256 ; 2 = 512 ; 3 = 1024 */
+    uint8_t ps3_osr = 1;    /* 0 = 128 ; 1 = 256 ; 2 = 512 ; 3 = 1024 */
+
+    uint8_t ps3_cp_avg_num_sel= 0;
+    uint8_t ps2_cp_avg_num_sel= 0;
+    uint8_t ps1_cp_avg_num_sel= 0;
+    uint8_t ps0_cp_avg_num_sel= 0;
+
+    uint8_t ps3_avg_num_sel_i2c=0;
+    uint8_t ps2_avg_num_sel_i2c=0;
+    uint8_t ps1_avg_num_sel_i2c=0;
+    uint8_t ps0_avg_num_sel_i2c=0;
+
+    /***********led open enable***********/
+
+    uint8_t ps0_led_en_i2c=1;
+    uint8_t ps1_led_en_i2c=0;
+    uint8_t ps2_led_en_i2c=1;
+    uint8_t ps3_led_en_i2c=0;
+
+    uint8_t ps0_ofidac_en_i2c=1;
+    uint8_t ps1_ofidac_en_i2c=1;
+    uint8_t ps2_ofidac_en_i2c=1;
+    uint8_t ps3_ofidac_en_i2c=1;
+
+    uint8_t dccancel_ps0 =8;    //offset idac   BIT[9:0]  0 31.25nA, 1023 32uA, step 31.25nA
+    uint8_t dccancel_ps1 =8;   //offset idac   BIT[9:0]  0 31.25nA, 1023 32uA, step 31.25nA
+    uint8_t dccancel_ps2 =8;    //offset idac   BIT[9:0]  0 31.25nA, 1023 32uA, step 31.25nA
+    uint8_t dccancel_ps3 =8;    //offset idac   BIT[9:0]  0 31.25nA, 1023 32uA, step 31.25nA
+
+    uint8_t leddrive_ps0 =0;     //LEDDRIVE_PS0  0~255 = 0~200ma
+    uint8_t leddrive_ps1 =0;     //LEDDRIVE_PS1  0~255 = 0~200ma
+    uint8_t leddrive_ps2 =64;    //LEDDRIVE_PS2  0~255 = 0~200ma
+    uint8_t leddrive_ps3 =0;     //LEDDRIVE_PS3  0~255 = 0~200ma
+
+    uint16_t thres_level =0;
+    uint8_t led_en_begin =1;       // 0 = 2 ; 1 = 4 ; 2 = 8 ; 3 = 16 ;
+    uint8_t afe_reset = 1;        //* 0 = 32clk ; 1 = 64clk ; 2 = 128clk ; 3 = 256clk(d) ;
+    uint8_t en2rst_delay =3;      // pen 2 rst delay 0 = 128,256, 512, 1024
+    uint8_t init_wait_delay = 2; /* 0 = 800 ; 1 = 1600; 2 = 3200 ; 3 = 6400(d) */
+
+    uint8_t ps1_interval_i2c =0;    // ps2/ps3
+
+    uint8_t thres_int =1;    //thres int enable
+    uint8_t data_rdy_int =8;    //[3]:ps1_data2 [2]:ps1_data1 [1]:ps0_data2 [0]:ps0_data1
+
+
+    uint8_t ldrsel_ps0 =1;      //ps0 LDR SELECT 01:ldr0-GLED  02:ldr1-IR   04:ldr2-RLED
+    uint8_t ldrsel_ps1 =0;      //ps1 LDR SELECT 01:ldr0-GLED  02:ldr1-IR   04:ldr2-RLED
+    uint8_t ldrsel_ps2 =2;      //ps1 LDR SELECT 01:ldr0-GLED  02:ldr1-IR   04:ldr2-RLED
+    uint8_t ldrsel_ps3 =0;      //ps1 LDR SELECT 01:ldr0-GLED  02:ldr1-IR   04:ldr2-RLED
+
+    /***********cap *********/
+    uint8_t intcapsel_ps3 =2;   //00=4fp 01=8pf 02=12pf 03=16pf 04=20pf 05=24pf 06=28pf 07=32pf 08=36pf 09=40pf 10=44pf 11=48pf 12=52pf 13=56pf 14=60pf
+    uint8_t intcapsel_ps2 =2;   //00=4fp 01=8pf 02=12pf 03=16pf 04=20pf 05=24pf 06=28pf 07=32pf 08=36pf 09=40pf 10=44pf 11=48pf 12=52pf 13=56pf 14=60pf
+    uint8_t intcapsel_ps1 =2;   //00=4fp 01=8pf 02=12pf 03=16pf 04=20pf 05=24pf 06=28pf 07=32pf 08=36pf 09=40pf 10=44pf 11=48pf 12=52pf 13=56pf 14=60pf
+    uint8_t intcapsel_ps0 =2;   //00=4fp 01=8pf 02=12pf 03=16pf 04=20pf 05=24pf 06=28pf 07=32pf 08=36pf 09=40pf 10=44pf 11=48pf 12=52pf 13=56pf 14=60pf
+
+    uint8_t ps0_led_on_time=32;    /* 0 = 32clk2=8us ; 8 = 64clk=16us; 16=128clk=32us ; 32 = 256clk=64us ;
+                                     64 = 512clk=128us ; 128= 1024clk=256us; 256= 2048clk=512us*/
+    uint8_t ps1_led_on_time=32;    /* 0 = 32clk2=8us ; 8 = 64clk=16us; 16=128clk=32us ; 32 = 256clk=64us ;
+                                     64 = 512clk=128us ; 128= 1024clk=256us; 256= 2048clk=512us*/
+    uint8_t ps2_led_on_time=16;    /* 0 = 32clk2=8us ; 8 = 64clk=16us; 16=128clk=32us ; 32 = 256clk=64us ;
+                                     64 = 512clk=128us ; 128= 1024clk=256us; 256= 2048clk=512us*/
+    uint8_t ps3_led_on_time=16;    /* 0 = 32clk2=8us ; 8 = 64clk=16us; 16=128clk=32us ; 32 = 256clk=64us ;
+                                     64 = 512clk=128us ; 128= 1024clk=256us; 256= 2048clk=512us*/
+
+    uint8_t force_adc_clk_sel=0;
+    uint8_t force_adc_clk_cfg =0;
+    uint8_t force_PEN =0;     //phase enable
+    uint8_t force_PEN_cfg =0;
+    uint8_t force_LED_EN =0;
+    uint8_t force_LED_EN_cfg =0;
+    uint8_t force_CKAFEINT_sel =0;
+    uint8_t force_CKAFEINT_cfg =0;
+
+    uint8_t PDBIASEN =0;
+    uint8_t PDILOADEN =0;
+
+    /***********************sar*****************************/
+    uint8_t  odr_short =1;
+
+    uint8_t  ch0_cfg =3;
+    uint8_t  ch1_cfg =12;
+    uint8_t  ch2_cfg =48;
+
+    uint8_t  ch0_range=1;   // 000=1.25pF  001=2.5pF  010=3.75pF  011=5pF   100=0.625pF
+    uint8_t  ch1_range=1;   // 000=1.25pF  001=2.5pF  010=3.75pF  011=5pF   100=0.625pF
+    uint8_t  ch2_range=1;   // 000=1.25pF  001=2.5pF  010=3.75pF  011=5pF   100=0.625pF
+
+    uint8_t ch0_avg_num=1;   //    000 =1; 001 = 2;.default;010= 4;011= 8; 100= 16;101= 32;
+    uint8_t ch1_avg_num=1;
+    uint8_t ch2_avg_num=1;
+
+    uint8_t ch0_wram_num=0;
+
+    uint8_t ch0_osr_num=2;   //   000= 16;001=32;010=64;011=128;100=256;
+    uint8_t ch1_osr_num=2;   //   000= 16;001=32;010=64;011=128;100=256;
+    uint8_t ch2_osr_num=2;   //   000= 16;001=32;010=64;011=128;100=256;
+
+    uint8_t c0_offset_dac=0;
+    uint8_t c1_offset_dac=0;
+    uint8_t c2_offset_dac=0;
+
+    uint8_t sar_sample_num=8;
+
+    uint8_t sar_integ_num=8;
+
+    uint8_t ch_num_sel=0;
+#ifdef SAR_ALG_LIB
+               hx3918_set_cap_data_ready(0);
+#endif
+    hx3918_write_reg(0X16, (ps3_enable<<3| ps2_enable<<2|ps1_enable<<1|ps0_enable));   //default 0x00
+    hx3918_write_reg(0X17, (ps3_osr<<6| ps2_osr<<4|ps1_osr<<2|ps0_osr));       //default 0x00
+    hx3918_write_reg(0X18, (uint8_t)prf_clk_num);    // prf bit<7:0>6   default 0x00
+    hx3918_write_reg(0X19, (uint8_t)(prf_clk_num>>8)); // prf bit<11:8>  default 0x03
+    hx3918_write_reg(0X1a, (ps1_interval_i2c));   //default 0x00
+    hx3918_write_reg(0X1b, led_en_begin<<6|afe_reset<<4|en2rst_delay <<2|init_wait_delay); // led_en_num*8     //default 0x00
+    //hx3918_write_reg(0X1b, 0x03);
+    hx3918_write_reg(0X1c, ps0_led_on_time); // led_en_num*8     //default 0x00
+    hx3918_write_reg(0X1d, ps1_led_on_time); // led_en_num*8     //default 0x00
+    hx3918_write_reg(0X1e, ps2_led_on_time); // led_en_num*8     //default 0x00
+    hx3918_write_reg(0X1f, ps3_led_on_time); // led_en_num*8     //default 0x00
+    hx3918_write_reg(0X20, (ps3_cp_avg_num_sel<<6|ps2_cp_avg_num_sel<<4|ps1_cp_avg_num_sel<<2|ps0_cp_avg_num_sel) );     //default 0x00
+    hx3918_write_reg(0X21, (ps3_avg_num_sel_i2c<<6|ps2_avg_num_sel_i2c<<4|ps1_avg_num_sel_i2c<<2|ps0_avg_num_sel_i2c));     //default 0x00
+    hx3918_write_reg(0X23, (ps0_led_en_i2c<<7|ps1_led_en_i2c<<6|ps2_led_en_i2c<<5|ps3_led_en_i2c<<4|ps0_ofidac_en_i2c<<3|ps1_ofidac_en_i2c<<2|ps2_ofidac_en_i2c<<1|ps3_ofidac_en_i2c)); // led_en  offset_en
+    hx3918_write_reg(0X24, (intcapsel_ps0<<4|intcapsel_ps1));   //default 0x00
+    hx3918_write_reg(0X25, (intcapsel_ps2<<4|intcapsel_ps3));   //default 0x00
+    hx3918_write_reg(0X26, leddrive_ps0); // led_en_num*8     //default 0x00
+    hx3918_write_reg(0X27, leddrive_ps1); // led_en_num*8     //default 0x00
+    hx3918_write_reg(0X28, leddrive_ps2); // led_en_num*8     //default 0x00
+    hx3918_write_reg(0X29, leddrive_ps3); // led_en_num*8     //default 0x00
+    hx3918_write_reg(0X2a, (ldrsel_ps0<<4|ldrsel_ps1));     //default 0x00
+    hx3918_write_reg(0X2b, (ldrsel_ps2<<4|ldrsel_ps3));     //default 0x00
+    hx3918_write_reg(0X2c, dccancel_ps0 );     //default 0x00
+    hx3918_write_reg(0X2d, dccancel_ps1 );     //default 0x00
+    hx3918_write_reg(0X2e, dccancel_ps2 );     //default 0x00
+    hx3918_write_reg(0X2f, dccancel_ps3);     //default 0x00
+    hx3918_write_reg(0X36, (thres_int<<4|data_rdy_int));
+    hx3918_write_reg(0X4e, (force_adc_clk_sel<<7|force_adc_clk_cfg<<6|force_PEN<<5|force_PEN_cfg<<4|force_LED_EN<<3|
+                            force_LED_EN_cfg<<2|force_CKAFEINT_sel<<1|force_CKAFEINT_cfg));   //default 0x00
+
+    hx3918_write_reg(0X54, odr_short);
+    hx3918_write_reg(0X55,ch0_cfg); // ch0 single input  cs0=p
+    hx3918_write_reg(0X56,ch0_cfg>>8); //
+    hx3918_write_reg(0X57,ch1_cfg); // ch1 dif input  cs0=p cs1=n
+    hx3918_write_reg(0X58,ch1_cfg>>8); //
+    hx3918_write_reg(0X59,ch2_cfg); // ch2 single input  cs2=p
+    hx3918_write_reg(0X5a,ch2_cfg>>8); //
+    hx3918_write_reg(0X5b,(ch1_range<<4|ch0_range));
+    hx3918_write_reg(0X5c, ch2_range);
+    hx3918_write_reg(0X5d, (ch0_avg_num<<5|ch0_osr_num<<2|ch0_wram_num));
+    hx3918_write_reg(0X5e, (ch2_osr_num<<4|ch0_osr_num));
+    hx3918_write_reg(0X5f, (ch2_avg_num<<4|ch1_avg_num));
+    hx3918_write_reg(0X60, c0_offset_dac);
+    hx3918_write_reg(0X61, c0_offset_dac>>8);
+    hx3918_write_reg(0X62, c1_offset_dac);
+    hx3918_write_reg(0X63, c1_offset_dac>>8);
+    hx3918_write_reg(0X64, c2_offset_dac);
+    hx3918_write_reg(0X65, c2_offset_dac>>8);
+    hx3918_write_reg(0X66, sar_sample_num);
+    hx3918_write_reg(0X67, sar_sample_num>>8);
+    hx3918_write_reg(0X68, sar_integ_num);
+    hx3918_write_reg(0X69, sar_integ_num>>8);
+    hx3918_write_reg(0X6a, ch_num_sel);
+
+    hx3918_write_reg(0X6d, 0x00);
+    hx3918_write_reg(0XF0, 0x22);
+    hx3918_write_reg(0xF1, 0x28);
+    hx3918_write_reg(0xF2, 0x04);
+    hx3918_write_reg(0xF3, 0x70);
+    hx3918_write_reg(0xF4, 0xb2);
+    hx3918_write_reg(0xF5, 0x89);
+    hx3918_write_reg(0xF6, 0x2b);
+    hx3918_write_reg(0xF7, 0x81);
+    hx3918_write_reg(0xF8, 0x27);
+    hx3918_write_reg(0xF9, 0x00);
+    hx3918_write_reg(0xFA, 0x88);
+    hx3918_write_reg(0xFB, 0x40);
+    hx3918_write_reg(0Xf6, 0X2b);
+
+#if defined(TIMMER_MODE)
+    hx3918_write_reg(0x3d,0x84);     //bits<3:0> fifo data sel, 0000 = p1;0001= p2;0010=p3;0011=p4;bits<7> fifo enble
+    hx3918_write_reg(0x3e,0x20);                //watermark
+    hx3918_write_reg(0x3c,0x1f);     // int_width_i2c
+    hx3918_write_reg(0X37, 0x00);   // int sel,01=prf int,04=enable almost full int
+    hx3918_write_reg(0X3b, 0x00);
+    hx3918_write_reg(0X3b, 0x10);
+#else ///////////INT Mode
+    hx3918_write_reg(0x3d,0x00);     //bits<3:0> fifo data sel, 0000 = p1;0001= p2;0010=p3;0011=p4;bits<7> fifo enble
+    hx3918_write_reg(0x3c,0x1f);     // int_width_i2c
+    hx3918_write_reg(0X37, 0x04);   // int sel,01=prf ,04=enable almost full
+#endif
+
+    hx3918_write_reg(0X4d, 0X01);  //soft reset
+    hx3918_delay(5);
+    hx3918_write_reg(0X4d, 0X00);  //release
+    hx3918_delay(5);
+    read_fifo_first_flg = 1;
+}
+
+hx3918_hrv_wear_msg_code_t hx3918_hrv_wear_mode_check(int32_t infrared_data)
+{
+       int16_t sar_data = 32767;
+#ifdef SAR_ALG_LIB
+       sar_data = hx90xx_get_prox_data();
+#endif
+    if(infrared_data > hrv_ir_wear_thres && sar_data > sar_wear_thres)
+    {
+        if(no_touch_cnt < NO_TOUCH_CHECK_NUM)
+        {
+            no_touch_cnt++;
+        }
+        if(no_touch_cnt >= NO_TOUCH_CHECK_NUM)
+        {
+            hrv_wear_status = MSG_HRV_WEAR;
+        }
+    }
+    else if(infrared_data < hrv_ir_unwear_thres || sar_data < sar_unwear_thres)
+    {
+        if(no_touch_cnt>0)
+        {
+            no_touch_cnt--;
+        }
+        if(no_touch_cnt == 0)
+        {
+            hrv_wear_status = MSG_HRV_NO_WEAR;
+        }
+    }
+
+    if(hrv_wear_status_pre != hrv_wear_status)
+    {
+        hrv_wear_status_pre = hrv_wear_status;         
+               //TYHX_LOG("[hx3918_hrv_wear_mode_check start] ir wear result = %d\r\n",hrv_wear_status);
+               //hrv_wear_status = hx3918_get_wear_result(hrv_wear_status);
+               //TYHX_LOG("[hx3918_hrv_wear_mode_check end] final result = %d\r\n",hrv_wear_status);
+        if(hrv_wear_status_pre == MSG_HRV_NO_WEAR)
+        {
+            hx3918_hrv_low_power();
+        }
+        else if(hrv_wear_status_pre == MSG_HRV_WEAR)
+        {
+            tyhx_hrv_alg_open_deep();
+            hx3918_hrv_set_mode(PPG_INIT);
+            hx3918_hrv_set_mode(CAL_INIT);
+        }
+    }
+
+    return hrv_wear_status;
+}
+
+void Init_hrv_PPG_Calibration_Routine(HRV_CAL_SET_T *calR,uint8_t led)
+{
+    calR->flag = CAL_FLG_LED_DR|CAL_FLG_LED_DAC|CAL_FLG_AMB_DAC|CAL_FLG_RF;
+
+    calR->led_idac   = 8;
+    calR->amb_idac   = 8;
+    calR->ontime     = 5;  //int cap=2 ontime=5  1ofidac=9000 code
+    calR->led_cur    = HRS_CAL_INIT_LED;
+    calR->state      = hrsCalStart;
+    calR->int_cnt    = 0;
+    calR->cur255_cnt = 0;
+    if(low_vbat_flag==1)
+    {
+        calR->led_max_cur = green_led_max_init>>1;
+    }
+    else
+    {
+        calR->led_max_cur = green_led_max_init;
+    }
+}
+
+void Restart_hrv_PPG_Calibration_Routine(HRV_CAL_SET_T *calR)
+{
+    calR->flag = CAL_FLG_LED_DR|CAL_FLG_LED_DAC|CAL_FLG_AMB_DAC|CAL_FLG_RF;
+    calR->state = hrvCalLed;
+    calR->int_cnt = 0;
+}
+
+void PPG_hrv_Calibration_Routine(HRV_CAL_SET_T *calR, int32_t led, int32_t amb)
+{
+    switch(calR->state)
+    {
+    case hrvCalStart:
+        calR->state = hrvLedCur;
+        break;
+
+    case hrvLedCur:
+        if(amb>280000)
+        {
+            calR->amb_idac = (amb-280000)/10000;
+        }
+        else
+        {
+            calR->amb_idac = 0;
+        }
+        if(led>amb+128)
+        {
+            calR->led_step = (led-amb)/HRV_CAL_INIT_LED;
+            calR->led_cur = 10000*(hx3918_hrs_agc_idac+calR->amb_idac)/calR->led_step;
+            if(calR->led_cur>calR->led_max_cur)
+            {
+                calR->led_cur = calR->led_max_cur;
+            }
+            calR->led_idac = 0;
+            calR->ontime = 32;
+            calR->flag = CAL_FLG_LED_DR|CAL_FLG_LED_DAC|CAL_FLG_AMB_DAC|CAL_FLG_RF;
+            calR->state = hrvCalLed;
+        }
+        else
+        {
+            calR->led_cur = calR->led_max_cur;
+            calR->led_idac = 0;
+            calR->ontime = 32;
+            calR->flag = CAL_FLG_LED_DR|CAL_FLG_LED_DAC|CAL_FLG_AMB_DAC|CAL_FLG_RF;
+            calR->state = hrvCalLed;
+        }
+        break;
+
+    case hrvCalLed:
+        if(led>320000 && calR->led_idac<=120)
+        {
+            calR->led_idac = calR->led_idac + 1;
+            calR->state = hrvCalLed;
+        }
+        else if(led<200000 && calR->led_idac>=1)
+        {
+            calR->led_idac = calR->led_idac - 1;
+            calR->state = hrvCalLed;
+        }
+        else
+        {
+            calR->state = hrvCalFinish;
+        }
+        calR->flag = CAL_FLG_LED_DAC;
+        break;
+
+    default:
+        break;
+
+    }
+    AGC_LOG("AGC: led_drv=%d,ledDac=%d,ambDac=%d,ledstep=%d,ontime=%d,state=%d\r\n",\
+            calR->led_cur, calR->led_idac, calR->amb_idac,calR->led_step,calR->ontime,calR->state);
+}
+
+HRV_CAL_SET_T PPG_hrv_agc(void)
+{
+    int32_t led_val, amb_val;
+    calReg.work = false;
+    if (!s_cal_state)
+    {
+        return  calReg;
+    }
+
+#ifdef INT_MODE
+    calReg.int_cnt ++;
+    if(calReg.int_cnt < 8)
+    {
+        return calReg;
+    }
+    calReg.int_cnt = 0;
+    hx3918_gpioint_cfg(false);
+#endif
+    calReg.work = true;
+
+    read_data_packet(agc_buf);
+    led_val = agc_buf[0];
+    amb_val = agc_buf[1];
+
+    AGC_LOG("cal dat led_val=%d,amb_val=%d \r\n", led_val, amb_val);
+
+    PPG_hrv_Calibration_Routine(&calReg, led_val, amb_val);
+
+    if (calReg.state == hrvCalFinish)
+    {
+        hx3918_hrv_set_mode(CAL_OFF);
+#if defined(TIMMER_MODE)
+#else
+        hx3918_gpioint_cfg(true);
+#endif
+    }
+    else
+    {
+        hx3918_hrv_updata_reg();
+#if defined(INT_MODE)
+        hx3918_gpioint_cfg(true);
+#endif
+    }
+    return  calReg;
+}
+
+
+
+void hx3918_hrv_cal_init(void) // 20200615 ericy afe cali online
+{
+    uint16_t sample_rate = 125;                      /*config the data rate of chip alps2_fm ,uint is Hz*/
+    uint32_t prf_clk_num = 32000/sample_rate;        /*period in clk num, num = Fclk/fs */
+    uint8_t ps1_cp_avg_num_sel= 0;
+    uint8_t ps0_cp_avg_num_sel= 0;
+    uint8_t thres_int =0;    //thres int enable
+    uint8_t data_rdy_int =8;    //[3]:ps1_data2 [2]:ps1_data1 [1]:ps0_data2 [0]:ps0_data1
+
+#ifdef SAR_ALG_LIB
+               hx3918_set_cap_data_ready(0);
+#endif
+    hx3918_write_reg(0X18, (uint8_t)prf_clk_num);    // prf bit<7:0>6   default 0x00
+    hx3918_write_reg(0X19, (uint8_t)(prf_clk_num>>8)); // prf bit<15:8>  default 0x03
+
+
+    hx3918_write_reg(0x3d,0x00);     //bits<3:0> fifo data sel, 0000 = p1;0001= p2;0010=p3;0011=p4;bits<7> fifo enble
+    hx3918_write_reg(0X36, (thres_int<<4|data_rdy_int));   //default 0x0f
+
+    hx3918_write_reg(0X4d, 0X01);  //soft reset
+    hx3918_delay(5);
+    hx3918_write_reg(0X4d, 0X00);  //release
+    hx3918_delay(5);             //Delay for reset time
+}
+
+void hx3918_hrv_cal_off(void) // 20200615 ericy afe cali offline
+{
+    uint16_t sample_rate = 125;                      /*config the data rate of chip alps2_fm ,uint is Hz*/
+    uint32_t prf_clk_num = 32000/sample_rate;        /*period in clk num, num = Fclk/fs */
+    uint8_t ps1_cp_avg_num_sel= 0;
+    uint8_t ps0_cp_avg_num_sel= 0;
+
+//             if(ps0_avg_flg==0)
+//             {
+//                     ps1_cp_avg_num_sel= 0;
+//                     ps0_cp_avg_num_sel= 0;
+//             }
+//             else
+//             {
+//                     ps1_cp_avg_num_sel= 0;
+//                     ps0_cp_avg_num_sel= 2;
+//             }
+    uint8_t thres_int =0;    //thres int enable
+    uint8_t data_rdy_int =0;    //[3]:ps1_data2 [2]:ps1_data1 [1]:ps0_data2 [0]:ps0_data1
+    uint8_t databuf[3] = {0};
+
+    hx3918_write_reg(0X18, (uint8_t)prf_clk_num);    // prf bit<7:0>6   default 0x00
+    hx3918_write_reg(0X19, (uint8_t)(prf_clk_num>>8)); // prf bit<15:8>  default 0x03
+
+    hx3918_write_reg(0x3d,0x84);     //bits<3:0> fifo data sel, 0000 = p1;0001= p2;0010=p3;0011=p4;bits<7> fifo enble
+    hx3918_write_reg(0X36, (thres_int<<4|data_rdy_int));   //default 0x0f
+
+    hx3918_write_reg(0X4d, 0X01);  //soft reset
+    hx3918_delay(5);
+    hx3918_write_reg(0X4d, 0X00);  //release
+    hx3918_delay(5);             //Delay for reset time
+#ifdef SAR_ALG_LIB
+    hx3918_prox_reg_init();
+#endif
+    read_fifo_first_flg = 1;
+}
+
+void hx3918_hrv_low_power(void)
+{
+    /* start cfg*/
+    /*****************PPG***************************/
+    uint16_t sample_rate = 10;                  /*config the data rate of chip alps2_fm ,uint is Hz*/
+    uint32_t prf_clk_num = 32000/sample_rate;   /*period in clk num, num = Fclk/fs */
+
+    uint8_t ps0_enable=1;       /*ps0_enable  , 1 mean enable ; 0 mean disable */
+    uint8_t ps1_enable=0;       /*ps1_enable  , 1 mean enable ; 0 mean disable */
+    uint8_t ps2_enable=1;       /*ps0_enable  , 1 mean enable ; 0 mean disable */
+    uint8_t ps3_enable=1;       /*ps1_enable  , 1 mean enable ; 0 mean disable */
+
+    uint8_t ps0_osr = 1;    /* 0 = 128 ; 1 = 256 ; 2 = 512 ; 3 = 1024 */
+    uint8_t ps1_osr = 3;    /* 0 = 128 ; 1 = 256 ; 2 = 512 ; 3 = 1024 */
+    uint8_t ps2_osr = 1;    /* 0 = 128 ; 1 = 256 ; 2 = 512 ; 3 = 1024 */
+    uint8_t ps3_osr = 1;    /* 0 = 128 ; 1 = 256 ; 2 = 512 ; 3 = 1024 */
+
+    uint8_t ps3_cp_avg_num_sel= 0;
+    uint8_t ps2_cp_avg_num_sel= 0;
+    uint8_t ps1_cp_avg_num_sel= 0;
+    uint8_t ps0_cp_avg_num_sel= 0;
+
+    uint8_t ps3_avg_num_sel_i2c=0;
+    uint8_t ps2_avg_num_sel_i2c=0;
+    uint8_t ps1_avg_num_sel_i2c=0;
+    uint8_t ps0_avg_num_sel_i2c=0;
+
+    /***********led open enable***********/
+
+    uint8_t ps0_led_en_i2c=0;
+    uint8_t ps1_led_en_i2c=0;
+    uint8_t ps2_led_en_i2c=1;
+    uint8_t ps3_led_en_i2c=0;
+
+    uint8_t ps0_ofidac_en_i2c=1;
+    uint8_t ps1_ofidac_en_i2c=1;
+    uint8_t ps2_ofidac_en_i2c=1;
+    uint8_t ps3_ofidac_en_i2c=1;
+
+    uint8_t dccancel_ps0 =8;    //offset idac   BIT[9:0]  0 31.25nA, 1023 32uA, step 31.25nA
+    uint8_t dccancel_ps1 =8;    //offset idac   BIT[9:0]  0 31.25nA, 1023 32uA, step 31.25nA
+    uint8_t dccancel_ps2 =8;    //offset idac   BIT[9:0]  0 31.25nA, 1023 32uA, step 31.25nA
+    uint8_t dccancel_ps3 =8;    //offset idac   BIT[9:0]  0 31.25nA, 1023 32uA, step 31.25nA
+
+    uint8_t leddrive_ps0 =0;     //LEDDRIVE_PS0  0~255 = 0~200ma
+    uint8_t leddrive_ps1 =0;     //LEDDRIVE_PS1  0~255 = 0~200ma
+    uint8_t leddrive_ps2 =64;     //LEDDRIVE_PS2  0~255 = 0~200ma
+    uint8_t leddrive_ps3 =0;     //LEDDRIVE_PS3  0~255 = 0~200ma
+
+    uint16_t thres_level =0;
+
+//    uint8_t adc_self  = 0;         //adc self test 1:enable  0:disable
+
+    uint8_t led_en_begin =1;       // 0 = 2 ; 1 = 4 ; 2 = 8 ; 3 = 16 ;
+    uint8_t afe_reset = 1;        //* 0 = 32clk ; 1 = 64clk ; 2 = 128clk ; 3 = 256clk(d) ;
+    uint8_t en2rst_delay =3;      // pen 2 rst delay 0 = 128,256, 512, 1024
+    uint8_t init_wait_delay = 2; /* 0 = 800 ; 1 = 1600; 2 = 3200 ; 3 = 6400(d) */
+
+
+    uint8_t ps1_interval_i2c =0;    // ps2/ps3
+
+    uint8_t thres_int =1;    //thres int enable
+    uint8_t data_rdy_int =8;    //[3]:ps1_data2 [2]:ps1_data1 [1]:ps0_data2 [0]:ps0_data1
+
+
+    uint8_t ldrsel_ps0 =0;      //ps0 LDR SELECT 01:ldr0-GLED  02:ldr1-IR   04:ldr2-RLED
+    uint8_t ldrsel_ps1 =0;      //ps1 LDR SELECT 01:ldr0-GLED  02:ldr1-IR   04:ldr2-RLED
+    uint8_t ldrsel_ps2 =2;      //ps1 LDR SELECT 01:ldr0-GLED  02:ldr1-IR   04:ldr2-RLED
+    uint8_t ldrsel_ps3 =0;      //ps1 LDR SELECT 01:ldr0-GLED  02:ldr1-IR   04:ldr2-RLED
+
+    /***********cap *********/
+    uint8_t intcapsel_ps3 =2;   //00=4fp 01=8pf 02=12pf 03=16pf 04=20pf 05=24pf 06=28pf 07=32pf 08=36pf 09=40pf 10=44pf 11=48pf 12=52pf 13=56pf 14=60pf
+    uint8_t intcapsel_ps2 =2;   //00=4fp 01=8pf 02=12pf 03=16pf 04=20pf 05=24pf 06=28pf 07=32pf 08=36pf 09=40pf 10=44pf 11=48pf 12=52pf 13=56pf 14=60pf
+    uint8_t intcapsel_ps1 =2;   //00=4fp 01=8pf 02=12pf 03=16pf 04=20pf 05=24pf 06=28pf 07=32pf 08=36pf 09=40pf 10=44pf 11=48pf 12=52pf 13=56pf 14=60pf
+    uint8_t intcapsel_ps0 =2;   //00=4fp 01=8pf 02=12pf 03=16pf 04=20pf 05=24pf 06=28pf 07=32pf 08=36pf 09=40pf 10=44pf 11=48pf 12=52pf 13=56pf 14=60pf
+
+    uint8_t ps0_led_on_time=32;    /* 0 = 32clk2=8us ; 8 = 64clk=16us; 16=128clk=32us ; 32 = 256clk=64us ;
+                                     64 = 512clk=128us ; 128= 1024clk=256us; 256= 2048clk=512us*/
+    uint8_t ps1_led_on_time=32;    /* 0 = 32clk2=8us ; 8 = 64clk=16us; 16=128clk=32us ; 32 = 256clk=64us ;
+                                     64 = 512clk=128us ; 128= 1024clk=256us; 256= 2048clk=512us*/
+    uint8_t ps2_led_on_time=16;    /* 0 = 32clk2=8us ; 8 = 64clk=16us; 16=128clk=32us ; 32 = 256clk=64us ;
+                                     64 = 512clk=128us ; 128= 1024clk=256us; 256= 2048clk=512us*/
+    uint8_t ps3_led_on_time=16;    /* 0 = 32clk2=8us ; 8 = 64clk=16us; 16=128clk=32us ; 32 = 256clk=64us ;
+                                     64 = 512clk=128us ; 128= 1024clk=256us; 256= 2048clk=512us*/
+
+    uint8_t force_adc_clk_sel=0;
+    uint8_t force_adc_clk_cfg =0;
+    uint8_t force_PEN =0;     //phase enable
+    uint8_t force_PEN_cfg =0;
+    uint8_t force_LED_EN =0;
+    uint8_t force_LED_EN_cfg =0;
+    uint8_t force_CKAFEINT_sel =0;
+    uint8_t force_CKAFEINT_cfg =0;
+
+    uint8_t PDBIASEN =0;
+    uint8_t PDILOADEN =0;
+
+    /***********************sar*****************************/
+    uint8_t  odr_short =1;
+
+    uint8_t  ch0_cfg =3;
+    uint8_t  ch1_cfg =12;
+    uint8_t  ch2_cfg =48;
+
+    uint8_t  ch0_range=1;   // 000=1.25pF  001=2.5pF  010=3.75pF  011=5pF   100=0.625pF
+    uint8_t  ch1_range=1;   // 000=1.25pF  001=2.5pF  010=3.75pF  011=5pF   100=0.625pF
+    uint8_t  ch2_range=1;   // 000=1.25pF  001=2.5pF  010=3.75pF  011=5pF   100=0.625pF
+
+    uint8_t ch0_avg_num=1;   //    000 =1; 001 = 2;.default;010= 4;011= 8; 100= 16;101= 32;
+    uint8_t ch1_avg_num=1;
+    uint8_t ch2_avg_num=1;
+
+    uint8_t ch0_wram_num=0;
+
+    uint8_t ch0_osr_num=2;   //   000= 16;001=32;010=64;011=128;100=256;
+    uint8_t ch1_osr_num=2;   //   000= 16;001=32;010=64;011=128;100=256;
+    uint8_t ch2_osr_num=2;   //   000= 16;001=32;010=64;011=128;100=256;
+
+    uint8_t c0_offset_dac=0;
+    uint8_t c1_offset_dac=0;
+    uint8_t c2_offset_dac=0;
+
+    uint8_t sar_sample_num=8;
+
+    uint8_t sar_integ_num=8;
+
+    uint8_t ch_num_sel=0;
+
+#ifdef SAR_ALG_LIB
+               hx3918_set_cap_data_ready(0);
+#endif
+    hx3918_write_reg(0X16, (ps3_enable<<3| ps2_enable<<2|ps1_enable<<1|ps0_enable));   //default 0x00
+    hx3918_write_reg(0X17, (ps3_osr<<6| ps2_osr<<4|ps1_osr<<2|ps0_osr));       //default 0x00
+    hx3918_write_reg(0X18, (uint8_t)prf_clk_num);    // prf bit<7:0>6   default 0x00
+    hx3918_write_reg(0X19, (uint8_t)(prf_clk_num>>8)); // prf bit<11:8>  default 0x03
+    hx3918_write_reg(0X1a, (ps1_interval_i2c));   //default 0x00
+    hx3918_write_reg(0X1b, led_en_begin<<6|afe_reset<<4|en2rst_delay <<2|init_wait_delay); // led_en_num*8     //default 0x00
+    //hx3918_write_reg(0X1b, 0x03);
+    hx3918_write_reg(0X1c, ps0_led_on_time); // led_en_num*8     //default 0x00
+    hx3918_write_reg(0X1d, ps1_led_on_time); // led_en_num*8     //default 0x00
+    hx3918_write_reg(0X1e, ps2_led_on_time); // led_en_num*8     //default 0x00
+    hx3918_write_reg(0X1f, ps3_led_on_time); // led_en_num*8     //default 0x00
+    hx3918_write_reg(0X20, (ps3_cp_avg_num_sel<<6|ps2_cp_avg_num_sel<<4|ps1_cp_avg_num_sel<<2|ps0_cp_avg_num_sel) );     //default 0x00
+    hx3918_write_reg(0X21, (ps3_avg_num_sel_i2c<<6|ps2_avg_num_sel_i2c<<4|ps1_avg_num_sel_i2c<<2|ps0_avg_num_sel_i2c));     //default 0x00
+    hx3918_write_reg(0X23, (ps0_led_en_i2c<<7|ps1_led_en_i2c<<6|ps2_led_en_i2c<<5|ps3_led_en_i2c<<4|ps0_ofidac_en_i2c<<3|ps1_ofidac_en_i2c<<2|ps2_ofidac_en_i2c<<1|ps3_ofidac_en_i2c)); // led_en  offset_en
+    hx3918_write_reg(0X24, (intcapsel_ps0<<4|intcapsel_ps1));   //default 0x00
+    hx3918_write_reg(0X25, (intcapsel_ps2<<4|intcapsel_ps3));   //default 0x00
+    hx3918_write_reg(0X26, leddrive_ps0); // led_en_num*8     //default 0x00
+    hx3918_write_reg(0X27, leddrive_ps1); // led_en_num*8     //default 0x00
+    hx3918_write_reg(0X28, leddrive_ps2); // led_en_num*8     //default 0x00
+    hx3918_write_reg(0X29, leddrive_ps3); // led_en_num*8     //default 0x00
+    hx3918_write_reg(0X2a, (ldrsel_ps0<<4|ldrsel_ps1));     //default 0x00
+    hx3918_write_reg(0X2b, (ldrsel_ps2<<4|ldrsel_ps3));     //default 0x00
+    hx3918_write_reg(0X2c, dccancel_ps0 );     //default 0x00
+    hx3918_write_reg(0X2d, dccancel_ps1 );     //default 0x00
+    hx3918_write_reg(0X2e, dccancel_ps2 );     //default 0x00
+    hx3918_write_reg(0X2f, dccancel_ps3);     //default 0x00
+    hx3918_write_reg(0X36, (thres_int<<4|data_rdy_int));
+    hx3918_write_reg(0X4e, (force_adc_clk_sel<<7|force_adc_clk_cfg<<6|force_PEN<<5|force_PEN_cfg<<4|force_LED_EN<<3|
+                            force_LED_EN_cfg<<2|force_CKAFEINT_sel<<1|force_CKAFEINT_cfg));   //default 0x00
+//    hx3918_write_reg(0X52, (adc_self<<2|second_time_en<<1));     //default 0x00
+//    hx3918_write_reg(0Xc0, 0x18);
+//    hx3918_write_reg(0Xc2, 0x0a);
+////    hx3918_write_reg(0Xc3, (PDBIASEN<<5|PDILOADEN<<4));   //default 0x27
+//    hx3918_write_reg(0Xc3, 0X27);
+    hx3918_write_reg(0X54, odr_short);
+    hx3918_write_reg(0X55,ch0_cfg); // ch0 single input  cs0=p
+    hx3918_write_reg(0X56,ch0_cfg>>8); //
+    hx3918_write_reg(0X57,ch1_cfg); // ch1 dif input  cs0=p cs1=n
+    hx3918_write_reg(0X58,ch1_cfg>>8); //
+    hx3918_write_reg(0X59,ch2_cfg); // ch2 single input  cs2=p
+    hx3918_write_reg(0X5a,ch2_cfg>>8); //
+    hx3918_write_reg(0X5b,(ch1_range<<4|ch0_range));
+    hx3918_write_reg(0X5c, ch2_range);
+    hx3918_write_reg(0X5d, (ch0_avg_num<<5|ch0_osr_num<<2|ch0_wram_num));
+    hx3918_write_reg(0X5e, (ch2_osr_num<<4|ch0_osr_num));
+    hx3918_write_reg(0X5f, (ch2_avg_num<<4|ch1_avg_num));
+    hx3918_write_reg(0X60, c0_offset_dac);
+    hx3918_write_reg(0X61, c0_offset_dac>>8);
+    hx3918_write_reg(0X62, c1_offset_dac);
+    hx3918_write_reg(0X63, c1_offset_dac>>8);
+    hx3918_write_reg(0X64, c2_offset_dac);
+    hx3918_write_reg(0X65, c2_offset_dac>>8);
+    hx3918_write_reg(0X66, sar_sample_num);
+    hx3918_write_reg(0X67, sar_sample_num>>8);
+    hx3918_write_reg(0X68, sar_integ_num);
+    hx3918_write_reg(0X69, sar_integ_num>>8);
+    hx3918_write_reg(0X6a, ch_num_sel);
+
+    hx3918_write_reg(0X6d, 0x00);
+    hx3918_write_reg(0XF0, 0x22);
+    hx3918_write_reg(0xF1, 0x28);
+    hx3918_write_reg(0xF2, 0x04);
+    hx3918_write_reg(0xF3, 0x70);
+    hx3918_write_reg(0xF4, 0xb2);
+    hx3918_write_reg(0xF5, 0x89);
+    hx3918_write_reg(0xF6, 0x2b);
+    hx3918_write_reg(0xF7, 0x81);
+    hx3918_write_reg(0xF8, 0x27);
+    hx3918_write_reg(0xF9, 0x00);
+    hx3918_write_reg(0xFA, 0x88);
+    hx3918_write_reg(0xFB, 0x40);
+    hx3918_write_reg(0Xf6, 0X2b);
+
+    hx3918_write_reg(0X4d, 0X01);  //soft reset
+    hx3918_delay(5);
+    hx3918_write_reg(0X4d, 0X00);  //release
+    hx3918_delay(5);
+    calReg.led_cur = 0;
+#ifdef SAR_ALG_LIB
+               hx3918_prox_reg_init();
+#endif
+//             hx3918_ppg_timer_cfg(false);
+//    hx3918_agc_timer_cfg(false);
+//             hx3918_gpioint_cfg(true);
+    AGC_LOG(" chip go to low power mode  \r\n" );
+}
+
+void hx3918_hrv_updata_reg(void)
+{
+    if (calReg.flag & CAL_FLG_LED_DR)
+    {
+        hx3918_write_reg(0X26, calReg.led_cur); // 3918
+    }
+
+    if (calReg.flag & CAL_FLG_LED_DAC)
+    {
+        hx3918_write_reg(0X2c, (uint8_t)calReg.led_idac);  //3918
+//                             hx3918_write_reg(0X19, (uint8_t)(calReg.led_idac>>8));
+    }
+
+    if (calReg.flag & CAL_FLG_AMB_DAC)
+    {
+        hx3918_write_reg(0X2d, (uint8_t)calReg.amb_idac);   // 3918
+//                             hx3918_write_reg(0X1b, (uint8_t)(calReg.amb_idac>>8));
+    }
+
+    if (calReg.flag & CAL_FLG_RF)
+    {
+        hx3918_write_reg(0X1c, calReg.ontime); //3918 p0
+        hx3918_write_reg(0X1d, calReg.ontime); //3918 p1
+        hx3918_write_reg(0X1e, calReg.ontime); //3918 p2
+        hx3918_write_reg(0X1f, calReg.ontime); //3918 p3
+    }
+}
+
+void hx3918_hrv_set_mode(uint8_t mode_cmd)
+{
+    switch (mode_cmd)
+    {
+    case PPG_INIT:
+        hx3918_hrv_ppg_init();
+#if defined(TIMMER_MODE)
+        hx3918_ppg_timer_cfg(true);
+#if defined(GSEN_40MS_TIMMER)
+        hx3918_agc_timer_cfg(true);
+#endif
+#else
+        hx3918_gpioint_cfg(true);
+#endif
+        s_ppg_state = 1;
+
+        AGC_LOG("ppg init mode\r\n");
+        break;
+
+    case PPG_OFF:
+        hx3918_ppg_off();
+        s_ppg_state = 0;
+        AGC_LOG("ppg off mode\r\n");
+        break;
+
+    case PPG_LED_OFF:
+        hx3918_hrv_low_power();
+        s_ppg_state = 0;
+        AGC_LOG("ppg led off mode\r\n");
+        break;
+
+    case CAL_INIT:
+        Init_hrv_PPG_Calibration_Routine(&calReg, 64);
+        hx3918_hrv_cal_init();
+        hx3918_hrv_updata_reg();
+#if defined(TIMMER_MODE)
+#if defined(GSEN_40MS_TIMMER)
+#else
+        hx3918_agc_timer_cfg(true);
+#endif
+#endif
+        //AGC_LOG("init  %x,%x \r\n", hx3918_read_reg(0x23),hx3918_read_reg(0x24));
+        s_cal_state = 1;
+        AGC_LOG("cal init mode\r\n");
+        break;
+
+    case RECAL_INIT:
+        Restart_hrv_PPG_Calibration_Routine(&calReg);
+        hx3918_hrv_cal_init();
+        hx3918_hrv_updata_reg();
+#if defined(TIMMER_MODE)
+#if defined(GSEN_40MS_TIMMER)
+#else
+        hx3918_agc_timer_cfg(true);
+#endif
+#endif
+        s_cal_state = 1;
+        AGC_LOG("Recal init mode\r\n");
+        break;
+
+    case CAL_OFF:
+#if defined(TIMMER_MODE)
+#if defined(GSEN_40MS_TIMMER)
+#else
+        hx3918_agc_timer_cfg(false);
+#endif
+#endif
+        hx3918_hrv_cal_off();
+        s_cal_state = 0;
+        AGC_LOG("cal off mode\r\n");
+        break;
+
+    default:
+        break;
+    }
+}
+
+SENSOR_ERROR_T hx3918_hrv_enable(void)
+{
+    if (!hx3918_chip_check())
+    {
+        AGC_LOG("hx3918 check id failed!\r\n");
+        return SENSOR_OP_FAILED;
+    }
+
+    AGC_LOG("hx3918 check id success!\r\n");
+
+    if (s_ppg_state)
+    {
+        AGC_LOG("ppg already on!\r\n");
+        return SENSOR_OP_FAILED;
+    }
+    if(!tyhx_hrv_alg_open())
+    {
+        AGC_LOG("hrv alg open fail,or dynamic ram not enough!\r\n");
+    }
+
+    hrv_wear_status = MSG_HRV_INIT;
+    hrv_wear_status_pre = MSG_HRV_INIT;
+
+    hx3918_hrv_set_mode(PPG_INIT);
+
+    AGC_LOG("hx3918 enable!\r\n");
+
+    return SENSOR_OK;
+}
+
+
+void hx3918_hrv_disable(void)
+{
+    hx3918_ppg_timer_cfg(false);
+    hx3918_agc_timer_cfg(false);
+
+    hx3918_hrv_set_mode(PPG_OFF);
+    s_ppg_state = 0;
+    s_cal_state = 0;
+    tyhx_hrv_alg_close();
+
+    AGC_LOG("hx3918 disable!\r\n");
+}
+
+void hx3918_hrv_data_reset(void)
+{
+    s_ppg_state = 0;
+    s_cal_state = 0;
+    tyhx_hrv_alg_close();
+}
+
+hx3918_hrv_wear_msg_code_t hx3918_hrv_get_wear_status(void)
+{
+    return  hrv_wear_status;
+}
+
+hx3918_hrv_wear_msg_code_t hx3918_hrv_get_wear_status_pre(void)
+{
+    return  hrv_wear_status_pre;
+}
+
+HRV_CAL_SET_T get_hrv_agc_status(void)
+{
+    HRV_CAL_SET_T cal;
+    cal.flag     = calReg.flag;
+    cal.int_cnt  = calReg.int_cnt;
+    cal.led_cur  = calReg.led_cur;
+    cal.led_idac = calReg.led_idac;
+    cal.amb_idac = calReg.amb_idac;
+    cal.ontime   = calReg.ontime;
+    cal.led_step = calReg.led_step;
+    cal.state    = calReg.state;
+    return cal;
+}
+
+uint8_t hx3918_hrv_read(hrv_sensor_data_t * s_dat)
+{
+    int32_t PPG_src_data;
+    int32_t Ir_src_data;
+    bool recal = false;
+//    uint8_t size = 0;
+//    uint8_t size_byte = 0;
+    int32_t *PPG_buf =  &(s_dat->ppg_data[0]);
+    int32_t *ir_buf =  &(s_dat->ir_data[0]);
+    int32_t *s_buf =  &(s_dat->s_buf[0]);
+    s_dat->agc_green =  calReg.led_cur;
+    int32_t ps_data[4]= {0};
+    int32_t ps_green_data = 0;
+    uint8_t data_count = 0;
+    if (!s_ppg_state || s_cal_state)
+    {
+        return NULL;
+    }
+
+    read_data_packet(ps_data);
+    Ir_src_data = ps_data[2]-ps_data[3];
+    ps_green_data = ps_data[0];
+    hx3918_hrv_wear_mode_check(Ir_src_data);
+    //DEBUG_PRINTF("%d %d %d %d\r\n" ,ps_data[0],ps_data[1],ps_data[2],ps_data[3]);
+
+    data_count = hx3918_read_fifo_data(s_buf,1,1);
+    //DEBUG_PRINTF("ppg data size: %d %d\r\n", data_count,hrs_phase_num);
+    s_dat->count =  data_count;
+    for (uint8_t i=0; i<data_count; i++)
+    {
+        PPG_src_data = s_buf[i];
+        PPG_buf[i] = 2*PPG_src_data;
+        ir_buf[i] = Ir_src_data;
+    }
+
+    if (ps_green_data<150000 || ps_green_data>350000)
+    {
+        recal = true;
+
+        if(hrv_wear_status==MSG_HRV_NO_WEAR)
+        {
+            recal = false;
+        }
+    }
+    if (recal)
+    {
+        cal_delay--;
+
+        if (cal_delay <= 0)
+        {
+            cal_delay = CAL_DELAY_COUNT;
+            hx3918_hrv_set_mode(RECAL_INIT);
+        }
+    }
+    else
+    {
+        cal_delay = CAL_DELAY_COUNT;
+    }
+    return 1;
+}
+
+#endif
diff --git a/2.sdk/sdk/gui/lv_drivers/indev/HX3918/hx3918_hrv_agc.h b/2.sdk/sdk/gui/lv_drivers/indev/HX3918/hx3918_hrv_agc.h
new file mode 100644 (file)
index 0000000..fc2f882
--- /dev/null
@@ -0,0 +1,80 @@
+#ifndef _HX3918_HRV_AGC_H_
+#define _HX3918_HRV_AGC_H_
+#include <stdint.h>
+#include <stdbool.h>
+#include "hx3918.h"
+
+#define CAL_DELAY_COUNT (3)
+
+#define CAL_FLG_LED_DR     0x01
+#define CAL_FLG_LED_DAC    0x02 
+#define CAL_FLG_AMB_DAC    0x04
+#define CAL_FLG_RF         0x08
+
+#define HRV_CAL_INIT_LED 16
+#define NO_TOUCH_CHECK_NUM 2 
+
+
+typedef enum {    
+    hrvCalStart, 
+               hrvLedCur,
+    hrvCalLed,
+    hrvCalLed2,
+    hrvCalFinish, 
+}HRV_STATE_T;
+
+typedef struct {
+       uint8_t count;
+       int32_t ppg_data[32];
+       int32_t ir_data[32];
+       int32_t s_buf[32]; 
+       uint32_t als;
+       uint32_t agc_green;
+}hrv_sensor_data_t;
+
+typedef enum {
+       MSG_HRV_NO_WEAR,
+       MSG_HRV_WEAR,
+       MSG_HRV_INIT
+} hx3918_hrv_wear_msg_code_t;
+
+typedef struct {
+       uint8_t flag;
+       bool work;
+       uint8_t int_cnt;
+       uint8_t cur255_cnt;
+       uint8_t led_cur;
+       uint8_t led_idac; 
+       uint8_t amb_idac;
+       uint8_t ontime;
+       uint16_t led_step;
+       uint8_t state;
+       uint8_t led_max_cur;
+} HRV_CAL_SET_T;
+
+void Init_hrv_PPG_Calibration_Routine(HRV_CAL_SET_T *calR,uint8_t led);
+void Restart_hrv_PPG_Calibration_Routine(HRV_CAL_SET_T *calR);
+void PPG_hrv_Calibration_Routine(HRV_CAL_SET_T *calR, int32_t led, int32_t amb);
+HRV_CAL_SET_T PPG_hrv_agc(void);
+
+void hx3918_hrv_cal_init(void);
+void hx3918_hrv_cal_off(void);
+uint8_t hx3918_read_fifo_size(void);
+void read_hrv_data_packet(int32_t *buf);
+void read_hrv_ir_packet(int32_t *buf);
+
+void hx3918_hrv_low_power(void);
+void hx3918_hrv_normal_power(void);
+void hx3918_hrv_updata_reg(void);
+void hx3918_hrv_set_mode(uint8_t mode_cmd);
+SENSOR_ERROR_T hx3918_hrv_enable(void);
+void hx3918_hrv_disable(void);
+hx3918_hrv_wear_msg_code_t hx3918_hrv_get_wear_status(void);
+uint8_t hx3918_hrv_read(hrv_sensor_data_t * s_dat);
+bool hx3918_hrv_init(void);
+
+hx3918_hrv_wear_msg_code_t hx3918_hrv_wear_mode_check(int32_t infrared_data);
+HRV_CAL_SET_T get_hrv_agc_status(void);
+void hx3918_hrv_data_reset(void);
+
+#endif
diff --git a/2.sdk/sdk/gui/lv_drivers/indev/HX3918/hx3918_prox.c b/2.sdk/sdk/gui/lv_drivers/indev/HX3918/hx3918_prox.c
new file mode 100644 (file)
index 0000000..cbd0815
--- /dev/null
@@ -0,0 +1,851 @@
+/*****************************************************************************
+    * @file     hx90xx.c
+    * @author
+    * @date
+    * @Emial
+    * @brief    HX3918 module
+******************************************************************************/
+
+#include <stdbool.h>
+#include <stdint.h>
+#include <string.h>
+#include <stdio.h>
+
+#include "hx3918_prox.h"
+#include "hx3918.h"
+//#include "helios_securedata.h"
+#ifdef TYHX_DEMO
+#include "nordic_common.h"
+#include "nrf.h"
+#include "app_error.h"
+#include "ble_hci.h"
+#include "ble_gap.h"
+#include "ble_err.h"
+#include "nrf_gpio.h"
+#include "nrf_drv_gpiote.h"
+#include "nrf_delay.h"
+#include "segger_rtt.h"
+#include "twi_master.h"
+#include "app_timer.h"
+#endif
+
+/* 产品需要改动的地方
+#define HX3918_IR_AIR       7000     //HX3918 对空测试佩戴IR的值范围,小于这个值代表对空
+#define NORMALWEARDIFF      6000     //HX3918 靠近感应佩戴时感应的结果, 一般是宽松佩戴结果
+hx_set_wear_detect_mode(NORMAL_WEAR_MODE)  // 在手表平常测试佩戴用
+hx_set_wear_detect_mode(SLEEP_WEAR_MODE)    //在手表检测到进入睡眠后需要调用
+*/
+
+/* --------------------------------程序说明------------------------------------------------------------
+1. 本程序HX3918作为佩戴感应部分的控制程序
+2.  HX3918 内置3通道CAP传感器;
+3. 读取的RAW DATA是最原始的模拟量转换过来的数字量,
+   LP是经过一次滤波来的(滤除高频环境噪声),
+   BL是RAW经过两次滤波来的(滤除低频噪声包含温度、湿度、压力带来的漂移),
+4. 有两种工作模式供实际使用选择,
+    相对值模式, 开机后,芯片自校准感应值到0附近, 靠近和远离,LP-BL会产生一个大的差值, 相对值模式;
+       绝对值模式,需要用户在工厂的时候, 产测程序要记录手表对空的一个BASE值(LP值), 后面用LP-BASE值来做判断;
+       相对值模式流程稍微简单, 但是因为上电会自我校准, 所以佩戴着开机无法检测佩戴情况. 绝对值模式无此问题.
+5.     hx3918_chip_id 是芯片ID的变量, 正确的ID值是0x27, 因为HX3918 是PPG和CAP, 用这个变量判断是不是芯片已经上电,
+       且PPG部分已经初始化, 如果等于0X27, 这边控制不需要上电下电, 如果碰到产测模式,CAP传感器需要单独工作,
+       PPG部分没有同时被初始化, 所以读到的hx3918_chip_id = 0, 那这里就是会加上芯片的上下电控制
+6.  注意CSx和CHx, CSx是指外部PAD接到芯片的对应CS管脚. CH是指内部采集数据的3个通道, CSx可配置在不同的CH上;
+-------------------------------- -------------------------------- -----------------------------------*/
+
+#ifdef  SAR_ALG_LIB
+//#define TEMP_COMPENSATION
+
+//#define INDEPENDDENT_CH  // 独立通道宏定义, 就是一个PAD对应一个CH
+#define DIFFERENCE_CH      //差分通道定义, 两个PAD作为一个CH的差分正端和负端, 挨着胳膊的佩戴为正端
+
+
+//#define HRS_VDD_ALWAYS_ON   //HRS 模块长供电
+
+extern uint8_t hx3918_chip_id;   // 芯片ID, 应该等于0x27
+int16_t nv_wear_offset[2] = {0};    // 芯片产测校准的两个通道的OFFSET值, 值记录在fash里面
+int16_t nv_base_data[2] = {0};     // 芯片产测校准的两个通道的对空LP值, 值记录在flash里面
+//extern uint16_t sendcnt;    // 蓝牙数据采集计数, 这个是采数用的, 可以不用
+int16_t gdiff[2] = {0};      // gdiff[0], gdiff[1] 分别保存WEAR_CH, REF_CH的结果
+int16_t glp[2] = {0};
+int16_t gbl[2] = {0};
+
+//flash 读写变量, 依次记录nv_wear_offset[0],nv_wear_offset[1],nv_base_data[0],nv_base_data[1]
+uint32_t fds_read[4] = {0}; //读出flash 存储数据的变量;
+uint32_t fds_write[4] = {0}; //写flash的变量, flash里面分别记录
+
+
+static uint8_t data_updata_ready = 0;
+uint8_t  is_factory_mode = 0;    // 产测模式, 用来读取整机对空时OFFSET和对空的nv_base值;
+uint8_t  is_offset_manual = 0;    // = 0自动校准模式, 用来读取整机对空时OFFSET和对空的nv_base值;
+static bool cap_enable = true;
+
+
+void hx3918_set_cap_enable(bool enable)
+{
+       cap_enable = enable;
+}
+
+void hx3918_set_cap_data_ready(uint8_t data_ready)
+{
+       data_updata_ready = data_ready;
+}
+
+/**
+ * 读一组16bit 数据值
+ * @param addh 寄存器地址
+ * @param addl 寄存器地址
+*/
+int16_t hx3918_read_two_reg_low_triple(uint8_t addh, uint8_t addl)
+{
+    uint8_t val_l = 0;
+    uint8_t val_h = 0;
+    uint8_t val_m= 0;
+    int32_t data = 0;
+               hx3918_write_reg(0x35,0x08); // man lock
+    val_l = hx3918_read_reg(addl-1);
+    val_m = hx3918_read_reg(addl);
+    val_h = hx3918_read_reg(addh);
+               hx3918_write_reg(0x35,0x00); // unlock
+    data =((val_l>>4) | (val_m<<4)|((val_h & 0x0f) << 12)) ;
+    if (data > 32767)
+        return (int16_t)(data - 65536);
+    else
+        return (int16_t)data;
+}
+
+/**
+ * 芯片上电,  对应的电源控制管脚跟实际电路相关,根据实际电路做好控制
+* @param NULL
+*/
+void hx3918_power_up(void)
+{
+#ifdef TYHX_DEMO
+    nrf_gpio_pin_set(4);
+    nrf_delay_ms(100);
+#endif
+}
+
+/**
+ * 芯片下电,  对应的电源控制管脚跟实际电路相关,根据实际电路做好控制
+* @param NULL
+*/
+void hx3918_power_down(void)
+{
+#ifdef TYHX_DEMO
+    nrf_gpio_pin_clear(4);
+    nrf_delay_ms(100);
+#endif
+}
+//extern void HX3918_restart(void);
+/**
+ * 芯片重新上电
+* @param NULL
+*/
+void hx3918_power_restart(void)
+{
+    //HX3918_restart();
+}
+
+/**
+ * HX3918 读芯片ID
+* @param NULL
+*/
+uint8_t hx3918_check_device_id(void)
+{
+    return hx3918_read_reg(0x00);
+}
+
+
+/**
+ * HX3918 写OFFSET的值
+* @param offset_value 写OFFSET的值
+* @param chx_offset 通道0/1/2 选择
+*/
+void  hx3918_write_offset(uint16_t offset_value, uint8_t chx_offset)
+{
+    uint8_t  write_val = 0;
+    uint8_t byte_high =0,  byte_low = 0;
+
+    byte_high = 0x61 + chx_offset*2;
+    byte_low = 0x60 + chx_offset*2;
+    write_val = ((uint8_t)(offset_value >> 8))&0xF;
+    hx3918_write_reg(byte_high,write_val);
+    write_val = (uint8_t)offset_value;
+    hx3918_write_reg(byte_low,write_val);
+
+}
+
+/**
+ * HX3918写OFFSET的值, 用在产测程序里面的OFFSET读取
+* @param offset_value 写OFFSET的值
+* @param chx_offset 通道0/1/2 选择
+*/
+static int16_t readlp_after_writeoffset(int16_t offset,uint8_t chx_offset)
+{
+    int16_t lpout;
+    hx3918_write_offset(offset,chx_offset);
+    hx3918_delay(32);
+    lpout = hx3918_read_diff_lp(chx_offset);
+    hx3918_delay(33);
+    lpout = hx3918_read_diff_lp(chx_offset);
+    return lpout;
+}
+
+/**
+ * HX3918 读OFFSET的值
+* @param chx_offset 通道0/1/2 选择
+*/
+uint16_t  hx3918_read_offset(uint8_t chx_offset)
+{
+    uint16_t writeoffset = 0;
+    int16_t lp=0;
+    uint16_t offset = 0;
+    uint16_t recordoffset = 0;
+    uint16_t mid;
+    static uint8_t cnt = 0;
+    hx3918_write_reg(0x8F,0x07);       //offset_dac_en_i2c
+    recordoffset = 1020;
+    cnt = 0;
+    while(writeoffset<=recordoffset)
+    {
+        mid =(writeoffset+recordoffset)/2;
+        lp = readlp_after_writeoffset(mid,chx_offset);
+
+        if(hx_abs(lp)>READ_DEVATION)
+        {
+            if(lp>READ_DEVATION)
+            {
+                writeoffset = mid+1;
+            }
+            else
+            {
+                recordoffset = mid-1;
+            }
+            cnt ++;
+        }
+        else
+        {
+            offset = mid;
+            TYHX_LOG(" final ch=%d,offset =%d lp=%d\r\n",chx_offset,offset,lp);
+            break;
+        }
+        //TYHX_LOG(" ch=%d,lp =%d,writeoffset=%d,recordoffset=%d\r\n",chx_offset,lp,writeoffset,recordoffset);
+    }
+    return offset;
+}
+
+
+/**
+ * HX3918读取raw data 或者baseline  data  //读取的是raw还是bl 通过0x38 寄存器设置
+* @param chx_raw 通道0/1/2 选择
+*/
+int16_t  hx3918_read_raw_bl(uint8_t chx_raw)
+{
+    int16_t raw = 0;
+    uint8_t byte_high =0,  byte_low = 0;
+
+    byte_high = 0xBE + chx_raw*3;
+    byte_low = 0xBD + chx_raw*3;
+
+    raw = hx3918_read_two_reg_low_triple(byte_high,byte_low);
+    return raw;
+}
+
+
+/**
+ * HX3918 读取LP data 或者diff data   //读取的是lp还是diff通过0x38 寄存器设置
+* @param chx_raw 通道0/1/2 选择
+*/
+int16_t  hx3918_read_diff_lp(uint8_t chx_diff)
+{
+    int16_t diff = 0;
+    uint8_t byte_high =0,  byte_low = 0;
+
+    byte_high = 0xC7+ chx_diff*3;
+    byte_low = 0xC6 + chx_diff*3;
+
+    diff = hx3918_read_two_reg_low_triple(byte_high,byte_low);
+    return diff;
+}
+
+/**
+ * HX3918 设置接近阈值和远离阈值
+* @param chx 通道0/1/2 选择
+* @param high_thres 接近阈值
+* @param low_thres 远离阈值
+* @param base_data
+*/
+void hx3918_config_thres(uint8_t chx,int16_t high_thres, int16_t low_thres, int16_t base_data)
+{
+    
+    //TYHX_LOG("[config_thres]CHX = %d, high thres =%d, low_thres=%d, base_data=%d\r\n",chx,high_thres,low_thres,base_data);
+    //if ((low_thres + base_data) <= 0)
+    {
+      //  return;
+    }
+    //TYHX_LOG("[config_thres]CHX = %d, high thres =%d, low_thres=%d\r\n",chx,high_thres,low_thres);
+    int16_t thres = 0;
+
+       
+               thres = (high_thres + base_data)/32;
+               if(thres<0)
+               {
+                       thres = 0;
+               }
+    
+    TYHX_LOG("[config_thres]CHX = %d, high thres =%d\r\n",chx,thres);
+    hx3918_write_reg(0x9D+1*chx, (thres&0x00FF));
+    hx3918_write_reg(0xA0+1*chx, (thres&0xFF00)>>8);
+
+    thres = (low_thres + base_data)/32;
+               if(thres<0)
+               {
+                       thres = 0;
+               }
+
+    TYHX_LOG("[config_thres]CHX = %d,low_thres=%d\r\n",chx,thres);
+    hx3918_write_reg(0xA5+1*chx, (thres&0x00FF));
+    hx3918_write_reg(0xA8+1*chx, (thres&0xFF00)>>8);
+}
+
+
+/**
+ * HX3918 init
+* @param NULL
+*/
+bool hx3918_prox_reg_init(void)
+{
+    bool write_ok = true;
+               data_updata_ready = 0;
+//prf 默认25HZ
+//    if (hx3918_chip_id != PROX_CHIPID)
+//    {
+//        TYHX_LOG("100hz\r\n");
+//        write_ok &= hx3918_write_reg(0x18,0x00);    //prf =100HZ
+//        write_ok &= hx3918_write_reg(0x19,0x05);    //
+//    }
+    write_ok &= hx3918_write_reg(0x6a,0x00);    //CH0~N disable
+//    write_ok &= hx3918_write_reg(0x51,0x00);    //default
+//    write_ok &= hx3918_write_reg(0x52,0x02);    //default
+//    write_ok &= hx3918_write_reg(0x53,0x00);    //default
+
+
+#ifdef INDEPENDDENT_CH //
+    write_ok &= hx3918_write_reg(0x55,0x0C);   //CS1->CH0
+       write_ok &= hx3918_write_reg(0x55,0x03);   //CS0->CH0
+               
+               
+//    write_ok &= hx3918_write_reg(0x57,0x30);   //CS2->CH1    
+//             write_ok &= hx3918_write_reg(0x57,0x03);   //CS0->CH1
+                 write_ok &= hx3918_write_reg(0x57,0x0c);   //CS1->CH1
+               
+#elif defined(DIFFERENCE_CH) //?????????????¨, ???????·??
+//    write_ok &= hx3918_write_reg(0x55,0x2c);   //CS1->CH0[P],CS2->CH0[N]
+//             write_ok &= hx3918_write_reg(0x55,0x0e);   //CS1->CH0[P],CS0->CH0[N]
+               write_ok &= hx3918_write_reg(0x55,0x0c);   //CS0->CH0[P],CS1->CH0[N]
+//    write_ok &= hx3918_write_reg(0x57,0x30);   //CS2->CH1
+//              write_ok &= hx3918_write_reg(0x57,0x03);   //CS0->CH1
+               write_ok &= hx3918_write_reg(0x57,0x0b);   //CS1->CH1
+#endif
+               write_ok &= hx3918_write_reg(0x59,0x0c);   //CH2  CS1
+
+
+#ifdef FULL25PF
+    write_ok &= hx3918_write_reg(0x5B,0x11);   //full range = 2.5pf 0x11=2.5pf 0x22 = 3.75pf, 0x33 = 5pf
+#elif defined(FULL125PF)
+               write_ok &= hx3918_write_reg(0x5B,0x00);   //full range 0x00 = 1.25pf
+#elif defined(FULL375PF)
+    write_ok &= hx3918_write_reg(0x5B,0x22);   //full range = 2.5pf 0x11=2.5pf 0x22 = 3.75pf, 0x33 = 5pf
+#elif defined(FULL50PF)
+    write_ok &= hx3918_write_reg(0x5B,0x33);   //full range = 2.5pf 0x11=2.5pf 0x22 = 3.75pf, 0x33 = 5pf
+#endif
+    write_ok &= hx3918_write_reg(0x5D,0x25);   //OSR AVG
+    write_ok &= hx3918_write_reg(0x5E,0x22);   //OSR nosr1_num_i2c nosr2_num_i2c
+    write_ok &= hx3918_write_reg(0x5F,0x11);   //AVG ch1_avg_num_i2c ch2_avg_num_i2c
+
+    write_ok &= hx3918_write_reg(0x66,0x08);   //采样时间
+    write_ok &= hx3918_write_reg(0x67,0x00);   //
+    write_ok &= hx3918_write_reg(0x68,0x08);   //积分时间
+    write_ok &= hx3918_write_reg(0x69,0x00);   //
+
+    write_ok &= hx3918_write_reg(0x6E,0x11);   //LP alpha
+    write_ok &= hx3918_write_reg(0x77,0x70);   //output 选择LP和BL
+
+    //write_ok &= hx3918_write_reg(0x99,0x40);  // ch0 coe  增益配置
+               //write_ok &= hx3918_write_reg(0x9A,0x40);   // ch1 coe  增益配置
+               //write_ok &= hx3918_write_reg(0x94,0x02);   // diff_en_ch01
+               
+                               
+    if(is_offset_manual == 0)
+    {
+        TYHX_LOG("is_offset_manual = 0\r\n");
+
+        write_ok &= hx3918_write_reg(0x90,(0x1<<WEAR_CH)); //ch1=P+ ch0=N-
+        write_ok &= hx3918_write_reg(0x8F,0x00);//00
+        write_ok &= hx3918_write_reg(0x95,0x00);
+        hx3918_config_thres(WEAR_CH,sar_wear_thres, sar_unwear_thres,0); // 
+        hx3918_config_thres(REF_CH,REF_HIGH_DIFF, REF_LOW_DIFF,0); // 
+
+    }
+    else
+    {
+
+        write_ok &= hx3918_write_reg(0x90,(0x1<<WEAR_CH));////ch1=P+ ch0=N-
+                               write_ok &= hx3918_write_reg(0x8F,(0x1<<WEAR_CH)); // ch1 offset_dac_en
+        write_ok &= hx3918_write_reg(0x95,0x00);//0xaa
+        hx3918_write_offset(nv_wear_offset[0], WEAR_CH);
+       //hx3918_write_offset(nv_wear_offset[1], REF_CH);
+        hx3918_config_thres(WEAR_CH,sar_wear_thres, sar_unwear_thres,0); // wear0
+        hx3918_config_thres(REF_CH,REF_HIGH_DIFF, REF_LOW_DIFF,0);
+                               
+                               //write_ok &= hx3918_write_reg(0x7A,0x07|(0x10<<WEAR_CH)); // 打开转换中断
+                               write_ok &= hx3918_write_reg(0x9c,0x00); // lp_out_delta_bypass
+                               write_ok &= hx3918_write_reg(0x85,0x0f); // prox_int_high_num_i2c
+                               write_ok &= hx3918_write_reg(0xa3,0xff); //lp_out_delta_thres_ch1[7:0]
+                               write_ok &= hx3918_write_reg(0xa4,0x0f); // lp_out_delta_thres_ch1[11:8]
+                               write_ok &= hx3918_write_reg(0x70,0x11); // RA_UP_ALP_1_0_CFG
+                               //write_ok &= hx3918_write_reg(0x71,0x11); //
+                               //write_ok &= hx3918_write_reg(0x72,0x11); //
+                               //write_ok &= hx3918_write_reg(0x73,0x11); //
+
+    }
+       write_ok &= hx3918_write_reg(0x6a,0x03); //CH0, CH1 enable
+   // hx3918_delay(50);
+    return write_ok;
+}
+
+
+//蓝牙发送数据给APP
+//extern uint32_t sendDataToClient(int16_t sendnum1,int16_t sendnum2,int16_t sendnum3,int16_t sendnum4);
+void hx3918_timerout_cb(void)
+{
+
+}
+/**
+ * hx3918 获取靠近感应的结果,结果=0, prox感应的结果为非佩戴, =1 佩戴
+* @param NULL
+*/
+extern char is_open_sar ; //是否打开sar检测
+
+extern int cap_wear ;//电容佩戴状态
+//static int hx3918_timer = 0;
+uint8_t hx3918_report_prox_status(void)
+{
+    static uint8_t cap_wear_flag = 0;
+    static int hx3918_report_prox_timer = 0;
+    if(is_open_sar == 0)
+    {
+                       gdiff[0] = 32767;
+            return 1;
+       }
+    // if(hx3918_timer== 0)
+    // {
+    //     hx3918_timer = Helios_Timer_init( (void* )hx3918_timerout_cb, NULL);
+    //     Helios_Timer_Start(hx3918_timer, 1500, 1);
+    // }
+    uint8_t ret = 0; 
+    
+    glp[0] = hx3918_read_diff_lp(WEAR_CH);
+    gbl[0] = hx3918_read_raw_bl(WEAR_CH);
+
+    glp[1] = hx3918_read_diff_lp(REF_CH);
+    gbl[1] = hx3918_read_raw_bl(REF_CH);
+       
+       if ((glp[0] == 0) && (gbl[0] == 0))  // agc 调节时出现
+               {
+                       data_updata_ready = 0;
+               }
+               
+               if (data_updata_ready == 1&& (glp[0] != gbl[0]))
+               {
+                       if (is_offset_manual == 0)
+                       {
+                               gdiff[0] = glp[0]- gbl[0];
+                       }
+                       else
+                       {
+                               gdiff[0] = glp[0]- nv_base_data[0];
+                       }
+                       gdiff[1] = glp[1]- gbl[1];
+                       
+                       hx3918_update_min_nv_data(gbl[0]);
+               }
+               
+               if ((glp[0] == gbl[0]) && (glp[0] != 0) && is_offset_manual ==1)
+               {
+                       if (data_updata_ready == 0)
+                       {
+                               // 恢复寄存器
+                               hx3918_write_reg(0x9c,0x07); // lp_out_delta_bypass
+                               //hx3918_write_reg(0x85,0x0f); // prox_int_high_num_i2c
+                               //hx3918_write_reg(0xa3,0xff); //lp_out_delta_thres_ch1[7:0]
+                               //hx3918_write_reg(0xa4,0x0f); // lp_out_delta_thres_ch1[11:8]
+                               hx3918_write_reg(0x70,0x99); // RA_UP_ALP_1_0_CFG
+                               data_updata_ready = 1;
+                               HX3918_LOG("data_updata_ready == 1\r\n");
+                       }
+               }
+               if(gdiff[0]>sar_wear_thres)
+            ret = 1;
+        else
+            ret = 0;
+        // if(ret == 1)//
+        //     cap_wear_flag = 1;
+        // if(cap_wear_flag == 0)
+        //     ret = 1;
+        cap_wear = ret;
+               HX3918_LOG("SARresult ready: %d, lp,%d,%d, bl,%d,%d, giff, %d,%d, offset, %d, nv_data,%d\r\n",data_updata_ready, glp[0],glp[1], gbl[0],gbl[1],gdiff[0],gdiff[1], nv_wear_offset[0],nv_base_data[0]);
+        return ret;
+}
+
+
+int32_t hx90xx_get_prox_data(void)
+{
+       if (data_updata_ready == 1)
+       {
+               // 异常处理
+               if (nv_base_data[0] <-16384|| nv_base_data[0] > 25000 || hx3918_chip_id != PROX_CHIPID )
+               {
+                       gdiff[0] = 32767;
+               }       
+       }
+       
+       if (is_offset_manual == 0 || cap_enable == false)
+       {
+               gdiff[0] = 32767;
+       }
+       //DEBUG_PRINTF("gdiff[0]: %d \r\n", gdiff[0]); 
+
+       return gdiff[0];
+}
+
+       //红外值很小时校准
+void hx3918_cali_with_ir(int32_t infrared_data, int32_t ir_thres)   
+{
+       //设定 对空红外值 校准
+       int32_t unwear_infrared_data = ir_thres/4;
+       if (data_updata_ready == 1)
+       {
+               if (infrared_data < unwear_infrared_data)
+               {
+                       if ((gdiff[0] > sar_unwear_thres/4)&& (gdiff[0] < sar_unwear_thres))
+                       {
+                                       nv_base_data[0] = gbl[0];
+                       }
+               }
+       }
+       DEBUG_PRINTF("infrared_data: %d , unwear_infrared_data %d, sar_unwear_thres: %d,gdiff[0],%d\r\n", infrared_data, unwear_infrared_data,sar_unwear_thres,gdiff[0]); 
+}
+
+
+//更新最小值
+void hx3918_update_min_nv_data(int16_t min_data)
+{
+       uint8_t nv_change_flag = 0;
+       if (is_offset_manual == 1&&data_updata_ready == 1)
+       {
+               // 取得最小信号量值
+               if(min_data < nv_base_data[0]-50)
+               {  
+                       nv_base_data[0] = min_data;
+                       nv_change_flag = 1;
+                       
+               }
+
+               if (nv_change_flag == 1)
+               {
+//                     hx90xx_config_thres(CH0,ch0_high_diff, ch0_low_diff,nv_base_data[0]); // wear0
+//                     hx90xx_config_thres(CH1,ch1_high_diff, ch1_low_diff,nv_base_data[1]); // wear1
+                       DEBUG_PRINTF("90XX update_min_nv_data nv_base_data0: %d,\r\n", nv_base_data[0]);
+               }
+       }
+}
+
+
+// 在充电状态下调用, 每次充电只调用一次
+void hx3918_update_nv_data()
+{
+       int16_t min_data0 = {0};
+       uint8_t nv_change_flag = 0;
+       
+       glp[0] = hx3918_read_diff_lp(WEAR_CH);
+       min_data0 = hx3918_read_raw_bl(WEAR_CH);
+
+       if (is_offset_manual == 1)
+       {
+               //nv_wear_offset[0] = hx3918_read_offset(CH0_OFFSET);
+               // 取得对空信号值
+               if((min_data0 - nv_base_data[0]) > 100 )
+               {  
+                       nv_base_data[0] = nv_base_data[0] + (min_data0 - nv_base_data[0])/2;
+                       nv_change_flag = 1;
+               }
+
+               // 异常处理
+               if (nv_base_data[0] <-16384|| nv_base_data[0] > 20000 || glp[0] > 32000)
+               {
+                       hx3918_prox_factory_hanging_cali();
+                       return;
+               }
+               if (nv_change_flag == 1)
+               {
+                       hx3918_factory_cali_save_nv();
+               }
+               hx3918_prox_init();
+               DEBUG_PRINTF("90XX update_nv_data nv_base_data0: %d, nv_base_data1: %d\r\n", nv_base_data[0], nv_base_data[1]);
+       }
+       else if (is_offset_manual == 0)
+       {
+               hx3918_prox_factory_hanging_cali();
+               DEBUG_PRINTF("is_offset_manual == 0 %d, %d \r\n", nv_base_data[0], nv_wear_offset[0]);
+       }
+}
+
+/**
+ * hx3918 从flash读取对空校准后的OFFSET和NV_BASE
+* @param NULL
+*/
+void hx3918_read_nv(void)
+{
+
+    // 
+    //从flash读取4个值, 分别是以前保存的值; 这个函数用户需要自己完成, flash存储的位置不能被用户操作删掉
+    //flash_fds_data_get(4);
+    // Helios_SecureData_t r_data={0};
+    // r_data.index = 1;
+    // r_data.pBuffer = (uint8_t *)fds_read;
+    // r_data.len = sizeof(fds_read);
+    // Helios_Securedata_Read(&r_data);
+    nv_wear_offset[0] = fds_read[0];
+    nv_wear_offset[1] = fds_read[1];
+    nv_base_data[0] = fds_read[2];
+    nv_base_data[1] = fds_read[3];
+
+       //如果flash记录的值大于上限, 则让靠近感应进入相对值模式
+    if ( (nv_wear_offset[0] == 0&& nv_base_data[0] == 0) || nv_wear_offset[0] == 0xFFFF)
+    {
+                       nv_wear_offset[0] = 0;
+                       nv_base_data[0] = 0;
+                       nv_wear_offset[1] = 0;
+                       nv_base_data[1] = 0;
+                       cap_enable = false;
+                       is_offset_manual = 0;
+    }
+    else
+    {
+        is_offset_manual = 1;
+    }
+
+               TYHX_LOG("hx3918_read_nv ,OFF[0]:       %d,  OFF[1]:%d\r\n",nv_wear_offset[0],nv_wear_offset[1]);
+               TYHX_LOG("BASE[0]:      %d, BASE[1]:%d,mode: %d \r\n",nv_base_data[0],nv_base_data[1],is_offset_manual);
+
+
+    
+}
+
+/**
+ * hx3918 靠近感应初始化, 通过对hx3918_chip_id 判断,来判断靠近感应是独立工作还是跟PPG一起工作
+* @param NULL
+*/
+bool hx3918_prox_init(void)
+{
+    int32_t i = 0;
+    bool ret = false;
+    TYHX_LOG("[hx3918_prox_init]prox device_id is : 0x%.2x !\r\n", hx3918_chip_id);
+    if (hx3918_chip_id != PROX_CHIPID)
+    {
+        hx3918_power_restart();
+        //i2c_hrs_init();
+                               // twi_master_init();
+        hx3918_read_nv();
+        hx3918_ppg_on();
+        
+        for (i = 0; i<5; i++)
+        {
+            hx3918_chip_id = hx3918_check_device_id();
+            TYHX_LOG(" power restart ,prox device_id is : 0x%.2x !\r\n", hx3918_chip_id);
+            if (hx3918_chip_id == PROX_CHIPID)
+            {
+                               hx3918_prox_reg_init();
+                break;
+            }
+        }
+
+        if(hx3918_chip_id != PROX_CHIPID)
+        {
+            TYHX_LOG("no proximity device\r\n");
+            //i2c_hrs_uninit();
+                                       
+            hx3918_power_down();
+        }
+    }
+    else
+    {
+        hx3918_chip_id = hx3918_check_device_id();
+        TYHX_LOG("read prox device_id is : 0x%.2x !\r\n", hx3918_chip_id);
+        hx3918_read_nv();
+        hx3918_prox_reg_init();
+    }
+               //hx3918_ppg_off();
+    return ret;
+}
+
+
+/**
+ * hx3918 靠近感应初始化, 通过对hx3918_chip_id 判断,来判断靠近感应是独立工作还是跟PPG一起工作
+* @param NULL
+*/
+bool hx3918_prox_factory_init(void)
+{
+#ifdef DEBUG_PPG_ONLY
+    return true;
+#endif
+    int32_t i = 0;
+    bool ret = false;
+
+    hx3918_chip_id = 0;
+
+    hx3918_power_restart();
+    //i2c_hrs_init();
+    hx3918_ppg_on();
+    for (i = 0; i<5; i++)
+    {
+        hx3918_chip_id = hx3918_check_device_id();
+        TYHX_LOG(" power restart ,prox device_id is : 0x%.2x !\r\n", hx3918_chip_id);
+        if (hx3918_chip_id == PROX_CHIPID)
+        {
+                                               hx3918_write_reg(0x18,0x40);    //prf =100HZ
+                                               hx3918_write_reg(0x19,0x01);    //
+                                         hx3918_prox_reg_init();
+            break;
+        }
+    }
+               
+    if(hx3918_chip_id != PROX_CHIPID)
+    {
+        TYHX_LOG("no proximity device\r\n");
+        hx3918_power_down();
+    }
+    return ret;
+}
+
+
+//佩戴数据
+void hx3918_factory_cali_read_data(void)
+{
+  int16_t lp[2] = {0};
+       int16_t bl[3] = {0};
+       int32_t diff[3] = {0};
+       
+       lp[0] = hx3918_read_diff_lp(WEAR_CH);
+       bl[0] = hx3918_read_raw_bl(WEAR_CH);
+
+       //lp[1] = hx3918_read_diff_lp(REF_CH);
+       //bl[1] = hx3918_read_raw_bl(REF_CH);
+
+       if (is_offset_manual ==1)
+       {
+               diff[0] = lp[0]- nv_base_data[0];
+       }
+       else
+       {
+               diff[0] = lp[0] - bl[0];
+       }
+
+
+  DEBUG_PRINTF("id: 0x%x,offset0,%%d, lp[0], %d, bl[0], %d, diff[0],%d\r\n", hx3918_chip_id,nv_wear_offset[0],lp[0],bl[0],diff[0]);
+}
+
+/**
+ * hx3918 靠近感应部分 工厂产测程序, 需将手表悬空或者远离其他可能影响电容值的物体.
+* @param NULL
+*/
+uint16_t prox_factory_offset0 = 0;
+uint16_t prox_factory_offset1 = 0;
+int16_t prox_factory_lp[2] = {0};
+void hx3918_prox_factory_hanging_cali(void)
+{
+    // uint16_t offset0 = 0;
+    // uint16_t offset1 = 0;
+    // int16_t lp[2] = {0};
+    //uint8_t device_id = 0x00;
+               is_offset_manual = 0;
+    hx3918_prox_factory_init();
+    hx3918_delay(50);//delay 100ms
+
+    prox_factory_offset0 = hx3918_read_offset(WEAR_CH);
+    prox_factory_offset1 = hx3918_read_offset(REF_CH);
+
+
+    prox_factory_lp[0] = hx3918_read_diff_lp(WEAR_CH);
+    prox_factory_lp[1] = hx3918_read_diff_lp(REF_CH);
+
+    HX3918_LOG("offset0,offset1=       %d  %d\r\n", prox_factory_offset0,prox_factory_offset1);
+
+#ifdef INDEPENDDENT_CH
+    if((prox_factory_offset0-prox_factory_offset1)<100)
+    {
+        HX3918_LOG("ERR,  resize cap of ch0\r\n");
+    }
+
+#endif
+    nv_wear_offset[0] = prox_factory_offset0;
+    nv_wear_offset[1] = prox_factory_offset1;
+    nv_base_data[0] = prox_factory_lp[0];
+    nv_base_data[1] = prox_factory_lp[1];
+    HX3918_LOG("base0,base1=    %d  %d\r\n", glp[0],glp[1]);
+
+#ifdef DIFFERENCE_CH
+    //将差分数据读到的OFFSET, NV_BASE记录到FLASH里面, 校准存储把自学习的记录也需要清掉重新计算
+
+    if((prox_factory_offset0 == 510) &&(prox_factory_offset1 == 510)&&(prox_factory_lp[0]==0)&&(prox_factory_lp[1]==0))
+    {
+        TYHX_LOG("ERR,  read offset err, please redo it !!!\r\n");
+    }
+    else
+    {
+        hx3918_factory_cali_save_nv();
+    }
+#endif
+
+       hx3918_prox_init();
+       hx3918_delay(1000);//delay 1000ms               
+
+}
+
+/**
+ * hx3918 靠近感应部分 工厂产测程序, 需将手表悬空或者远离其他可能影响电容值的物体.
+* @param NULL
+*/
+void hx3918_factory_cali_save_nv(void)
+{
+
+    fds_write[0] = nv_wear_offset[0];
+    fds_write[1] = nv_wear_offset[1];
+
+    fds_write[2] = nv_base_data[0];
+    fds_write[3] = nv_base_data[1];
+    fds_read[0] = fds_write[0];
+    fds_read[1] = fds_write[1];
+    fds_read[2] = fds_write[2];
+    fds_read[3] = fds_write[3];
+    // Helios_SecureData_t w_data={0};
+    // w_data.index = 1;
+    // w_data.pBuffer = (uint8_t *)fds_write;
+    // w_data.len = sizeof(fds_write);
+    // Helios_Securedata_Store(&w_data);
+    TYHX_LOG("[hx3918_factory_cali_save_nv]");
+    for(int i=0; i<4; i++)
+    {
+        TYHX_LOG("%d   ",fds_write[i]);
+    }
+       //用户需要flash保存
+    //flash_fds_data_write(4);
+}
+
+#endif // SAR_ALG_LIB
+
+
+
+
+
diff --git a/2.sdk/sdk/gui/lv_drivers/indev/HX3918/hx3918_prox.h b/2.sdk/sdk/gui/lv_drivers/indev/HX3918/hx3918_prox.h
new file mode 100644 (file)
index 0000000..6069fdd
--- /dev/null
@@ -0,0 +1,138 @@
+/**
+  ******************************************************************************
+  * @file           : hx3918_PROX.h
+  * @version        : v1.0
+  * @brief          :
+*/
+#ifndef __HX3918_PROX_H_
+#define __HX3918_PROX_H_
+
+#include <stdbool.h>
+#include <stdint.h>
+
+
+
+
+#define CH0   0
+#define CH1   1
+#define CH2   2
+
+
+
+
+#define CH0_OFFSET   0
+#define CH1_OFFSET   1
+#define CH2_OFFSET   2
+
+
+#define RAW0   0
+#define RAW1   1
+#define RAW2   2
+
+#define BL0   0
+#define BL1   1
+#define BL2   2
+
+
+#define LP0   0
+#define LP1   1
+#define LP2   2
+
+
+#define DIFF0   0
+#define DIFF1   1
+#define DIFF2   2
+
+// user  to config
+#define WEAR_CH   CH1
+#define REF_CH    CH0
+
+#define hx_min(x,y)  ( (x)>(y)?(y):(x) )
+#define hx_abs(x)    ((x)>0?(x):(-(x)))
+
+
+#define PROX_CHIPID         0x27
+
+
+#define NORMALWEARDIFF      12000                 //正常佩戴测试到的平均值, 宽松佩戴
+
+#define WEAR_HIGH_DIFF         NORMALWEARDIFF/6
+#define WEAR_LOW_DIFF          NORMALWEARDIFF/8
+#define REF_HIGH_DIFF          NORMALWEARDIFF/6
+#define REF_LOW_DIFF           NORMALWEARDIFF/8
+
+
+
+//HX3918 cap 测试电容的满量程设置, 最小
+//#define FULL0625PF  //HX3918 full range cap = 0.625pf //一般不用这个, 这个满量程设置, 说明感应pad很小,
+//#define FULL125PF   //HX3918 full range cap = 1.25pf
+//#define FULL25PF      //HX3918 full range cap = 2.5pf, 一般PAD大小默认这个.
+//#define FULL375PF   //HX3918 full range cap = 3.75 pf
+#define FULL50PF    //HX3918 full range cap = 5.0 pf
+
+//READ_DEVATION ,read offset 的偏差控制, 一个offset = 0.0586pf 按照不同量程, 对应的code, 留10%余量
+#ifdef FULL125PF 
+#define READ_DEVATION        1680
+#elif defined(FULL25PF)
+#define READ_DEVATION        845
+#elif defined(FULL375PF)
+#define READ_DEVATION        560
+#elif defined(FULL375PF)
+#define READ_DEVATION        420
+#elif defined(FULL50PF)
+#define READ_DEVATION        420
+#endif
+
+
+
+
+typedef enum
+{
+    prox_no_detect = 0,   // 靠近感应没有检测到
+    prox_detect =1,       // 靠近感应检测到
+} prox_result_t;
+
+typedef enum {
+       NORMAL_WEAR_MODE = 0,// 
+       SLEEP_WEAR_MODE = 1,//
+} wear_mode_t;
+
+
+extern int32_t  sar_wear_thres;
+extern int32_t  sar_unwear_thres;
+
+extern int16_t gdiff[2];
+extern int16_t glp[2];
+extern int16_t gbl[2];
+extern int16_t nv_base_data[2];
+extern int16_t nv_wear_offset[2];
+
+
+#define FDSLEN 4  //flash 存储的长度
+
+extern uint32_t fds_read[FDSLEN]; //flash 读
+extern uint32_t fds_write[FDSLEN];//flash 写
+extern uint8_t wear_detect_mode;
+
+
+
+void hx3918_power_up(void);
+void hx3918_power_down(void);
+void hx3918_power_restart(void);
+uint8_t hx3918_check_device_id(void);
+bool hx3918_prox_reg_init(void);
+uint8_t hx3918_report_prox_status(void);
+
+void hx3918_prox_factory_hanging_cali(void);
+bool hx3918_prox_init(void);
+void hx3918_factory_cali_save_nv(void);
+int16_t hx3918_read_diff_lp(uint8_t chx_diff);
+bool hx3918_prox_factory_init(void);
+void hx_set_wear_detect_mode(uint8_t current_mode);
+int32_t hx90xx_get_prox_data(void);
+void hx3918_cali_with_ir(int32_t infrared_data, int32_t ir_thres);   
+void hx3918_update_min_nv_data(int16_t min_data);
+void hx3918_set_cap_enable(bool enable);
+void hx3918_set_cap_data_ready(uint8_t data_ready);
+
+#endif
diff --git a/2.sdk/sdk/gui/lv_drivers/indev/HX3918/hx3918_spo2_agc.c b/2.sdk/sdk/gui/lv_drivers/indev/HX3918/hx3918_spo2_agc.c
new file mode 100644 (file)
index 0000000..03e0109
--- /dev/null
@@ -0,0 +1,993 @@
+#include <stdio.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <math.h>
+
+#include "hx3918.h"
+#include "hx3918_spo2_agc.h"
+#include "tyhx_spo2_alg.h"
+#include "tyhx_hrs_alg.h"
+//#include "tyhx_hrs_custom.h"
+#ifdef SAR_ALG_LIB
+#include "hx3918_prox.h"
+#endif
+
+
+#ifdef SPO2_ALG_LIB
+extern const uint8_t  hx3918_spo2_agc_green_idac;  // 6,7,8...
+extern const uint8_t  hx3918_spo2_agc_red_idac;  // 6,7,8...
+extern const uint8_t  hx3918_spo2_agc_ir_idac;  // 6,7,8...
+extern const uint8_t  green_led_max_init;
+extern const uint8_t  red_led_max_init;
+extern const uint8_t  ir_led_max_init;
+extern uint8_t low_vbat_flag;
+
+extern const uint8_t  spo2_check_unwear_oft;
+extern const int32_t  spo2_ir_wear_thres;
+
+extern uint8_t read_fifo_first_flg;
+
+static uint8_t s_ppg_state = 0;
+static uint8_t s_cal_state = 0;
+static int32_t agc_buf[4] = {0};
+
+static uint8_t cal_delay = CAL_DELAY_COUNT;
+static SPO2_CAL_SET_T  calReg;
+
+static hx3918_spo2_wear_msg_code_t spo2_wear_status = MSG_SPO2_INIT;
+static hx3918_spo2_wear_msg_code_t spo2_wear_status_pre = MSG_SPO2_INIT;
+
+void hx3918_spo2_ppg_init(void) //2023 3918
+{
+    uint16_t sample_rate = 25;                  /*config the data rate of chip alps2_fm ,uint is Hz*/
+    uint32_t prf_clk_num = 32000/sample_rate;   /*period in clk num, num = Fclk/fs */
+
+    uint8_t ps0_enable=1;       /*ps0_enable  , 1 mean enable ; 0 mean disable */
+    uint8_t ps1_enable=1;       /*ps1_enable  , 1 mean enable ; 0 mean disable */
+    uint8_t ps2_enable=1;       /*ps0_enable  , 1 mean enable ; 0 mean disable */
+    uint8_t ps3_enable=1;       /*ps1_enable  , 1 mean enable ; 0 mean disable */
+
+    uint8_t ps0_osr = 3;    /* 0 = 128 ; 1 = 256 ; 2 = 512 ; 3 = 1024 */
+    uint8_t ps1_osr = 3;    /* 0 = 128 ; 1 = 256 ; 2 = 512 ; 3 = 1024 */
+    uint8_t ps2_osr = 3;    /* 0 = 128 ; 1 = 256 ; 2 = 512 ; 3 = 1024 */
+    uint8_t ps3_osr = 3;    /* 0 = 128 ; 1 = 256 ; 2 = 512 ; 3 = 1024 */
+
+    uint8_t ps3_cp_avg_num_sel= 2;
+    uint8_t ps2_cp_avg_num_sel= 1;
+    uint8_t ps1_cp_avg_num_sel= 3;
+    uint8_t ps0_cp_avg_num_sel= 0;
+
+    uint8_t ps3_avg_num_sel_i2c=0;
+    uint8_t ps2_avg_num_sel_i2c=0;
+    uint8_t ps1_avg_num_sel_i2c=0;
+    uint8_t ps0_avg_num_sel_i2c=0;
+
+    uint8_t ps0_led_en_i2c=0;
+    uint8_t ps1_led_en_i2c=1;
+    uint8_t ps2_led_en_i2c=1;
+    uint8_t ps3_led_en_i2c=1;
+
+    uint8_t ps0_ofidac_en_i2c=1;
+    uint8_t ps1_ofidac_en_i2c=1;
+    uint8_t ps2_ofidac_en_i2c=1;
+    uint8_t ps3_ofidac_en_i2c=1;
+
+    uint8_t dccancel_ps0 =0;    //offset idac   BIT[9:0]  0 31.25nA, 1023 32uA, step 31.25nA
+    uint8_t dccancel_ps1 =0;   //offset idac   BIT[9:0]  0 31.25nA, 1023 32uA, step 31.25nA
+    uint8_t dccancel_ps2 =0;    //offset idac   BIT[9:0]  0 31.25nA, 1023 32uA, step 31.25nA
+    uint8_t dccancel_ps3 =0;    //offset idac   BIT[9:0]  0 31.25nA, 1023 32uA, step 31.25nA
+
+    uint8_t leddrive_ps0 =0;     //LEDDRIVE_PS0  0~255 = 0~200ma
+    uint8_t leddrive_ps1 =0;     //LEDDRIVE_PS1  0~255 = 0~200ma
+    uint8_t leddrive_ps2 =0;    //LEDDRIVE_PS2  0~255 = 0~200ma
+    uint8_t leddrive_ps3 =64;     //LEDDRIVE_PS3  0~255 = 0~200ma
+
+    uint8_t led_en_begin =1;       // 0 = 2 ; 1 = 4 ; 2 = 8 ; 3 = 16 ;
+    uint8_t afe_reset = 1;        //* 0 = 32clk ; 1 = 64clk ; 2 = 128clk ; 3 = 256clk(d) ;
+    uint8_t en2rst_delay =3;      // pen 2 rst delay 0 = 128,256, 512, 1024
+    uint8_t init_wait_delay = 2; /* 0 = 800 ; 1 = 1600; 2 = 3200 ; 3 = 6400(d) */
+
+    uint8_t ps1_interval_i2c =0;    // ps2/ps3
+
+    uint8_t thres_int =1;    //thres int enable
+    uint8_t data_rdy_int =8;    //[3]:ps1_data2 [2]:ps1_data1 [1]:ps0_data2 [0]:ps0_data1
+
+    uint8_t ldrsel_ps0 =0;      
+    uint8_t ldrsel_ps1 =RED_LED_SLE; 
+    uint8_t ldrsel_ps2 =GREEN_LED_SLE;
+    uint8_t ldrsel_ps3 =IR_LED_SLE;
+
+    /***********cap *********/
+    uint8_t intcapsel_ps3 =5;   //00=4fp 01=8pf 02=12pf 03=16pf 04=20pf 05=24pf 06=28pf 07=32pf 08=36pf 09=40pf 10=44pf 11=48pf 12=52pf 13=56pf 14=60pf
+    uint8_t intcapsel_ps2 =5;   //00=4fp 01=8pf 02=12pf 03=16pf 04=20pf 05=24pf 06=28pf 07=32pf 08=36pf 09=40pf 10=44pf 11=48pf 12=52pf 13=56pf 14=60pf
+    uint8_t intcapsel_ps1 =5;   //00=4fp 01=8pf 02=12pf 03=16pf 04=20pf 05=24pf 06=28pf 07=32pf 08=36pf 09=40pf 10=44pf 11=48pf 12=52pf 13=56pf 14=60pf
+    uint8_t intcapsel_ps0 =5;   //00=4fp 01=8pf 02=12pf 03=16pf 04=20pf 05=24pf 06=28pf 07=32pf 08=36pf 09=40pf 10=44pf 11=48pf 12=52pf 13=56pf 14=60pf
+
+    uint8_t ps0_led_on_time=64;    /* 0 = 32clk2=8us ; 8 = 64clk=16us; 16=128clk=32us ; 32 = 256clk=64us ;
+                                     64 = 512clk=128us ; 128= 1024clk=256us; 256= 2048clk=512us*/
+    uint8_t ps1_led_on_time=64;    /* 0 = 32clk2=8us ; 8 = 64clk=16us; 16=128clk=32us ; 32 = 256clk=64us ;
+                                     64 = 512clk=128us ; 128= 1024clk=256us; 256= 2048clk=512us*/
+    uint8_t ps2_led_on_time=64;    /* 0 = 32clk2=8us ; 8 = 64clk=16us; 16=128clk=32us ; 32 = 256clk=64us ;
+                                     64 = 512clk=128us ; 128= 1024clk=256us; 256= 2048clk=512us*/
+    uint8_t ps3_led_on_time=64;    /* 0 = 32clk2=8us ; 8 = 64clk=16us; 16=128clk=32us ; 32 = 256clk=64us ;
+                                     64 = 512clk=128us ; 128= 1024clk=256us; 256= 2048clk=512us*/
+
+    uint8_t force_adc_clk_sel=0;
+    uint8_t force_adc_clk_cfg =0;
+    uint8_t force_PEN =0;
+    uint8_t force_PEN_cfg =0;
+    uint8_t force_LED_EN =0;
+    uint8_t force_LED_EN_cfg =0;
+    uint8_t force_CKAFEINT_sel =0;
+    uint8_t force_CKAFEINT_cfg =0;
+
+#ifdef SAR_ALG_LIB
+               hx3918_set_cap_data_ready(0);
+#endif
+
+    hx3918_write_reg(0X16, (ps3_enable<<3| ps2_enable<<2|ps1_enable<<1|ps0_enable));   //default 0x00
+    hx3918_write_reg(0X17, (ps3_osr<<6| ps2_osr<<4|ps1_osr<<2|ps0_osr));       //default 0x00
+    hx3918_write_reg(0X18, (uint8_t)prf_clk_num);    // prf bit<7:0>6   default 0x00
+    hx3918_write_reg(0X19, (uint8_t)(prf_clk_num>>8)); // prf bit<11:8>  default 0x03
+    hx3918_write_reg(0X1a, (ps1_interval_i2c));   //default 0x00
+    hx3918_write_reg(0X1b, led_en_begin<<6|afe_reset<<4|en2rst_delay <<2|init_wait_delay); // led_en_num*8     //default 0x00
+    //hx3918_write_reg(0X1b, 0x03);
+    hx3918_write_reg(0X1c, ps0_led_on_time); // led_en_num*8     //default 0x00
+    hx3918_write_reg(0X1d, ps1_led_on_time); // led_en_num*8     //default 0x00
+    hx3918_write_reg(0X1e, ps2_led_on_time); // led_en_num*8     //default 0x00
+    hx3918_write_reg(0X1f, ps3_led_on_time); // led_en_num*8     //default 0x00
+    hx3918_write_reg(0X20, (ps3_cp_avg_num_sel<<6|ps2_cp_avg_num_sel<<4|ps1_cp_avg_num_sel<<2|ps0_cp_avg_num_sel) );     //default 0x00
+    hx3918_write_reg(0X21, (ps3_avg_num_sel_i2c<<6|ps2_avg_num_sel_i2c<<4|ps1_avg_num_sel_i2c<<2|ps0_avg_num_sel_i2c));     //default 0x00
+    hx3918_write_reg(0X23, (ps0_led_en_i2c<<7|ps1_led_en_i2c<<6|ps2_led_en_i2c<<5|ps3_led_en_i2c<<4|ps0_ofidac_en_i2c<<3|ps1_ofidac_en_i2c<<2|ps2_ofidac_en_i2c<<1|ps3_ofidac_en_i2c)); // led_en  offset_en
+    hx3918_write_reg(0X24, (intcapsel_ps0<<4|intcapsel_ps1));   //default 0x00
+    hx3918_write_reg(0X25, (intcapsel_ps2<<4|intcapsel_ps3));   //default 0x00
+    hx3918_write_reg(0X26, leddrive_ps0); // led_en_num*8     //default 0x00
+    hx3918_write_reg(0X27, leddrive_ps1); // led_en_num*8     //default 0x00
+    hx3918_write_reg(0X28, leddrive_ps2); // led_en_num*8     //default 0x00
+    hx3918_write_reg(0X29, leddrive_ps3); // led_en_num*8     //default 0x00
+    hx3918_write_reg(0X2a, (ldrsel_ps0<<4|ldrsel_ps1));     //default 0x00
+    hx3918_write_reg(0X2b, (ldrsel_ps2<<4|ldrsel_ps3));     //default 0x00
+    hx3918_write_reg(0X2c, dccancel_ps0 );     //default 0x00
+    hx3918_write_reg(0X2d, dccancel_ps1 );     //default 0x00
+    hx3918_write_reg(0X2e, dccancel_ps2 );     //default 0x00
+    hx3918_write_reg(0X2f, dccancel_ps3);     //default 0x00
+    hx3918_write_reg(0X36, (thres_int<<4|data_rdy_int));
+    hx3918_write_reg(0X4e, (force_adc_clk_sel<<7|force_adc_clk_cfg<<6|force_PEN<<5|force_PEN_cfg<<4|force_LED_EN<<3|
+                            force_LED_EN_cfg<<2|force_CKAFEINT_sel<<1|force_CKAFEINT_cfg));   //default 0x00
+
+    hx3918_write_reg(0X6d, 0x00);
+    hx3918_write_reg(0XF0, 0x22);
+    hx3918_write_reg(0xF1, 0x28);
+    hx3918_write_reg(0xF2, 0x04);
+    hx3918_write_reg(0xF3, 0x70);
+    hx3918_write_reg(0xF4, 0x32);
+    hx3918_write_reg(0xF5, 0x89);
+    hx3918_write_reg(0xF6, 0x2b);
+    hx3918_write_reg(0xF7, 0x85);
+    hx3918_write_reg(0xF8, 0x27);
+    hx3918_write_reg(0xF9, 0x00);
+    hx3918_write_reg(0xFA, 0x88);
+    hx3918_write_reg(0xFB, 0x40);
+    hx3918_write_reg(0Xf6, 0X2b);
+
+#if defined(TIMMER_MODE)
+    hx3918_write_reg(0x3d,0x80);     //bits<3:0> fifo data sel, 0000 = p1;0001= p2;0010=p3;0011=p4;bits<7> fifo enble
+    hx3918_write_reg(0x3e,0x20);                //watermark
+    hx3918_write_reg(0x3c,0x1f);     // int_width_i2c
+    hx3918_write_reg(0X37,0x00);   // int sel,01=prf int,04=enable almost full int
+    hx3918_write_reg(0X3b,0x00);
+    hx3918_write_reg(0X3b,0x10);
+#else ///////////INT Mode
+    hx3918_write_reg(0x3d,0x00);     //bits<3:0> fifo data sel, 0000 = p1;0001= p2;0010=p3;0011=p4;bits<7> fifo enble
+    hx3918_write_reg(0x3c,0x1f);     // int_width_i2c
+    hx3918_write_reg(0X37,0x04);   // int sel,01=prf ,04=enable almost full
+#endif
+
+    hx3918_write_reg(0X4d,0X01);  //soft reset
+    hx3918_delay(5);
+    hx3918_write_reg(0X4d,0X00);  //release
+    hx3918_delay(5);
+       
+    read_fifo_first_flg = 1;
+
+}
+
+void Init_Spo2_PPG_Calibration_Routine(SPO2_CAL_SET_T *calR)
+{
+    calR->flag = CAL_FLG_LED_DR|CAL_FLG_LED_DAC|CAL_FLG_AMB_DAC|CAL_FLG_RF;
+    calR->red_idac = 0;
+    calR->ir_idac = 0;
+    calR->green_idac = 0;
+    calR->amb_idac = 0;
+    calR->ontime = 5;
+    calR->green_cur = SPO2_CAL_INIT_LED_GREEN;
+    calR->red_cur = SPO2_CAL_INIT_LED_RED;
+    calR->ir_cur = SPO2_CAL_INIT_LED_IR;
+    calR->state = sCalStart;
+    calR->int_cnt = 0;
+    calR->cur255_cnt =0;
+    calR->green_led_step =0;
+    calR->red_led_step =0;
+    calR->ir_led_step =0;
+    if(low_vbat_flag == 1)
+    {
+        calR->green_max_cur = (green_led_max_init*3)>>2;
+        calR->red_max_cur = (red_led_max_init*3)>>2;
+        calR->ir_max_cur = (ir_led_max_init*3)>>2;
+    }
+    else
+    {
+        calR->green_max_cur = green_led_max_init;
+        calR->red_max_cur = red_led_max_init;
+        calR->ir_max_cur = ir_led_max_init;
+    }
+}
+
+void Restart_Spo2_PPG_Calibration_Routine(SPO2_CAL_SET_T *calR)
+{
+    calR->flag = CAL_FLG_LED_DAC;
+    calR->state = sCalLed;
+    calR->int_cnt = 0;
+}
+
+bool hx3918_spo2_check_unwear(void)
+{
+               int16_t sar_data = 32767;
+#ifdef SAR_ALG_LIB
+       sar_data = hx90xx_get_prox_data();
+#endif
+    if(calReg.ir_idac < spo2_check_unwear_oft || sar_data < sar_unwear_thres)
+    {
+        spo2_wear_status = MSG_SPO2_NO_WEAR;
+        if(spo2_wear_status_pre != MSG_SPO2_NO_WEAR)
+        {
+            spo2_wear_status_pre = MSG_SPO2_NO_WEAR;
+            hx3918_spo2_low_power();
+            return true;
+        }
+    }
+    return false;
+}
+
+bool hx3918_spo2_check_wear(int32_t infrared_data)
+{
+       int16_t sar_data = 32767;
+#ifdef SAR_ALG_LIB
+       sar_data = hx90xx_get_prox_data();
+#endif
+       if(infrared_data > spo2_ir_wear_thres && sar_data > sar_wear_thres)
+    {
+       
+        spo2_wear_status = MSG_SPO2_WEAR;              
+
+        if(spo2_wear_status_pre != MSG_SPO2_WEAR)
+        {
+            AGC_LOG("hx3918_spo2_check_wear ir = %d\r\n", infrared_data);
+            spo2_wear_status_pre = MSG_SPO2_WEAR;
+            tyhx_spo2_alg_open_deep();
+            hx3918_spo2_set_mode(PPG_INIT);
+            hx3918_spo2_set_mode(CAL_INIT);
+            return true;
+        }
+    }
+    return false;
+}
+
+
+void PPG_Spo2_Calibration_Routine(SPO2_CAL_SET_T *calR, int32_t amb, int32_t green_led, int32_t r_led, int32_t ir_led)
+{
+    int32_t r_led_temp = 0, ir_led_temp = 0, green_led_temp = 0;
+    TYHX_LOG("AGC_before: green_cur=%d,red_cur=%d,ir_cur=%d,green_idac=%d,red_idac=%d,ir_idac=%d,green_step=%d,red_step=%d,ir_step=%d,state=%d\r\n",\
+             calR->green_cur,calR->red_cur,calR->ir_cur,calR->green_idac,calR->red_idac,calR->ir_idac,calR->green_led_step,calR->red_led_step,calR->ir_led_step,calR->state);
+    switch(calR->state)
+    {
+        case sCalStart:
+            calR->state = sCalLedCur;
+            break;
+
+        case sCalLedCur:
+            if(spo2_wear_status == MSG_SPO2_NO_WEAR)
+            {
+                calR->state = sCalFinish;
+                break;
+            }
+            calR->amb_idac = 0;
+            if(green_led>amb+128)
+            {
+                calR->green_led_step = (green_led-amb)/SPO2_CAL_INIT_LED_GREEN;
+                green_led_temp = 5000*(hx3918_spo2_agc_green_idac+calR->amb_idac)/calR->green_led_step;
+                if(green_led_temp>calR->green_max_cur)
+                {
+                    green_led_temp = calR->green_max_cur;
+                }
+                calR->green_cur = green_led_temp;
+                calR->green_idac = hx3918_spo2_agc_green_idac>>1;
+            }
+            if(r_led>amb+128)
+            {
+                calR->red_led_step = (r_led-amb)/SPO2_CAL_INIT_LED_RED;
+                r_led_temp = 10000*(hx3918_spo2_agc_red_idac+calR->amb_idac)/calR->red_led_step;
+                if(r_led_temp>calR->red_max_cur)
+                {
+                    r_led_temp = calR->red_max_cur;
+                }
+                calR->red_cur = r_led_temp;
+                calR->red_idac = hx3918_spo2_agc_red_idac>>1;
+            }
+            if(ir_led>amb+128)
+            {
+                calR->ir_led_step = (ir_led-amb)/SPO2_CAL_INIT_LED_IR;
+                ir_led_temp = 10000*(hx3918_spo2_agc_ir_idac+calR->amb_idac)/calR->ir_led_step;
+                if(ir_led_temp>calR->ir_max_cur)
+                {
+                    ir_led_temp = calR->ir_max_cur;
+                }
+                calR->ir_cur = ir_led_temp;
+                calR->ir_idac = hx3918_spo2_agc_ir_idac>>1;
+            }
+            calR->ontime = 64;
+            calR->flag = CAL_FLG_LED_DR|CAL_FLG_LED_DAC|CAL_FLG_AMB_DAC|CAL_FLG_RF;
+            calR->state = sCalLed;
+            break;
+
+        case sCalLed:
+            if(green_led>450000 && calR->green_idac < 200)
+            {
+                calR->green_idac = calR->green_idac+2;
+            }
+
+            if(r_led>450000 && calR->red_idac < 200)
+            {
+                calR->red_idac = calR->red_idac+2;
+            }
+
+            if(ir_led>450000 && calR->ir_idac < 200)
+            {
+                calR->ir_idac = calR->ir_idac+2;
+            }
+
+            if(green_led<=450000 && ir_led<=450000 && r_led<=450000)
+            {
+                calR->state = sCalLed2;
+            }
+            else if(calR->green_idac >= 200 || calR->ir_idac >= 200 || calR->red_idac >= 200)
+            {
+                calR->state = sCalFinish;
+            }
+            else
+            {
+                calR->state = sCalLed;
+            }
+            calR->flag = CAL_FLG_LED_DAC;
+            break;
+
+        case sCalLed2:
+            if(green_led>350000 && calR->green_idac < 200)
+            {
+                calR->green_idac = calR->green_idac+1;
+            }
+            else if(green_led<150000 && calR->green_idac > 0)
+            {
+                calR->green_idac = calR->green_idac-1;
+            }
+            
+            if(r_led>350000 && calR->red_idac < 200)
+            {
+                calR->red_idac = calR->red_idac+1;
+            }
+            else if(r_led<150000 && calR->red_idac > 0)
+            {
+                calR->red_idac = calR->red_idac-1;
+            }
+
+            if(ir_led>350000 && calR->ir_idac < 200)
+            {
+                calR->ir_idac = calR->ir_idac+1;
+            }
+            else if(ir_led<150000 && calR->ir_idac > 0)
+            {
+                calR->ir_idac = calR->ir_idac-1;
+            }
+
+            if(green_led<350000 && green_led>150000 && ir_led<350000 && ir_led>150000 && r_led<350000 && r_led>150000)
+            {
+                calR->state = sCalFinish;
+            }
+            else if(calR->green_idac >= 200 || calR->ir_idac >= 200 || calR->red_idac >= 200)
+            {
+                calR->state = sCalFinish;
+            }
+            else
+            {
+                calR->state = sCalLed2;
+            }
+            calR->flag = CAL_FLG_LED_DAC;
+            break;
+
+        default:
+            break;
+    }
+    TYHX_LOG("AGC_after: green_cur=%d,red_cur=%d,ir_cur=%d,green_idac=%d,red_idac=%d,ir_idac=%d,green_step=%d,red_step=%d,ir_step=%d,state=%d\r\n",\
+             calR->green_cur,calR->red_cur,calR->ir_cur,calR->green_idac,calR->red_idac,calR->ir_idac,calR->green_led_step,calR->red_led_step,calR->ir_led_step,calR->state);
+}
+
+SPO2_CAL_SET_T PPG_spo2_agc(void)
+{
+    int32_t r_led_val;
+    int32_t amb_val;
+    int32_t ir_led_val;
+    int32_t green_led_val;
+
+    calReg.work = false;
+    if (!s_cal_state)
+    {
+        return calReg;
+    }
+
+    #ifdef INT_MODE
+    calReg.int_cnt ++;
+    if(calReg.int_cnt < 8)
+    {
+        return calReg;
+    }
+    calReg.int_cnt = 0;
+    hx3918_gpioint_cfg(false);
+    #endif
+
+    calReg.work = true;
+    read_data_packet(agc_buf);
+    amb_val = agc_buf[0];
+    green_led_val = agc_buf[2];
+    r_led_val = agc_buf[1];
+    ir_led_val = agc_buf[3];
+
+    TYHX_LOG("cal dat amb=%d,g=%d,r=%d,ir=%d\r\n", amb_val, green_led_val, r_led_val, ir_led_val);
+    PPG_Spo2_Calibration_Routine(&calReg, amb_val,green_led_val,r_led_val,ir_led_val);
+
+    if (calReg.state == sCalFinish)
+    {
+        hx3918_spo2_set_mode(CAL_OFF);
+    }
+    else
+    {
+        hx3918_spo2_updata_reg();
+    }
+    #if defined(INT_MODE)
+    hx3918_gpioint_cfg(true);
+    #endif
+    return  calReg;
+}
+
+
+void hx3918_spo2_cal_init(void) // 20200615 ericy afe cali offline
+{
+    uint16_t sample_rate = 100;                      /*config the data rate of chip alps2_fm ,uint is Hz*/
+    uint32_t prf_clk_num = 32000/sample_rate;        /*period in clk num, num = Fclk/fs */
+    uint8_t thres_int =0;    //thres int enable
+    uint8_t data_rdy_int =8;    //[3]:ps1_data2 [2]:ps1_data1 [1]:ps0_data2 [0]:ps0_data1
+#ifdef SAR_ALG_LIB
+               hx3918_set_cap_data_ready(0);
+#endif
+    hx3918_write_reg(0X18, (uint8_t)prf_clk_num);    // prf bit<7:0>6   default 0x00
+    hx3918_write_reg(0X19, (uint8_t)(prf_clk_num>>8)); // prf bit<15:8>  default 0x03
+    hx3918_write_reg(0x3d,0x00);     //bits<3:0> fifo data sel, 0000 = p1;0001= p2;0010=p3;0011=p4;bits<7> fifo enble
+    hx3918_write_reg(0X36, (thres_int<<4|data_rdy_int));   //default 0x0f
+
+    hx3918_write_reg(0X4d, 0X01);  //soft reset
+    hx3918_delay(5);
+    hx3918_write_reg(0X4d, 0X00);  //release
+    hx3918_delay(5);             //Delay for reset time
+  
+}
+
+void hx3918_spo2_cal_off(void) // 20200615 ericy afe cali offline
+{
+    uint16_t sample_rate = 25;                      /*config the data rate of chip alps2_fm ,uint is Hz*/
+    uint32_t prf_clk_num = 32000/sample_rate;        /*period in clk num, num = Fclk/fs */
+
+    hx3918_write_reg(0X18, (uint8_t)prf_clk_num);    // prf bit<7:0>6   default 0x00
+    hx3918_write_reg(0X19, (uint8_t)(prf_clk_num>>8)); // prf bit<15:8>  default 0x03
+    hx3918_write_reg(0x3d,0x80);     //bits<3:0> fifo data sel, 0000 = p1;0001= p2;0010=p3;0011=p4;bits<7> fifo enble
+
+    hx3918_write_reg(0X4d, 0X01);  //soft reset
+    hx3918_delay(5);
+    hx3918_write_reg(0X4d, 0X00);  //release
+    hx3918_delay(5);             //Delay for reset time
+#ifdef SAR_ALG_LIB
+    hx3918_prox_reg_init();
+#endif
+    read_fifo_first_flg = 1;
+}
+
+void hx3918_spo2_read_data(int32_t *buf) // 20200615 ericy read reg_data phase1 and phase3
+{
+    uint8_t  databuf1[6] = {0};
+    uint8_t  databuf2[6] = {0};
+    uint32_t P1 = 0,P2 = 0,P3 = 0,P4 =0 ;
+
+    hx3918_brust_read_reg(0x03, databuf1, 6);
+    hx3918_brust_read_reg(0x09, databuf2, 6);
+
+    P1 = ((databuf1[0])|(databuf1[1]<<8)|(databuf1[2]<<16));
+    P3 = ((databuf1[3])|(databuf1[4]<<8)|(databuf1[5]<<16));
+    P4 = ((databuf2[0])|(databuf2[1]<<8)|(databuf2[2]<<16));
+    P2 = ((databuf2[3])|(databuf2[4]<<8)|(databuf2[5]<<16));
+
+    buf[0] = P1;
+    buf[1] = P2;
+    buf[2] = P3;
+    buf[3] = P4;
+}
+
+void hx3918_spo2_low_power(void)
+{
+    uint16_t sample_rate = 10;                  /*config the data rate of chip alps2_fm ,uint is Hz*/
+    uint32_t prf_clk_num = 32000/sample_rate;   /*period in clk num, num = Fclk/fs */
+
+    uint8_t ps3_cp_avg_num_sel= 0;
+    uint8_t ps2_cp_avg_num_sel= 0;
+    uint8_t ps1_cp_avg_num_sel= 0;
+    uint8_t ps0_cp_avg_num_sel= 0;
+
+    uint8_t ps3_avg_num_sel_i2c=0;
+    uint8_t ps2_avg_num_sel_i2c=0;
+    uint8_t ps1_avg_num_sel_i2c=0;
+    uint8_t ps0_avg_num_sel_i2c=0;
+
+    uint8_t ps0_led_en_i2c=0;
+    uint8_t ps1_led_en_i2c=0;
+    uint8_t ps2_led_en_i2c=0;
+    uint8_t ps3_led_en_i2c=1;
+
+    uint8_t dccancel_ps0 =0;    //offset idac   BIT[9:0]  0 31.25nA, 1023 32uA, step 31.25nA
+    uint8_t dccancel_ps1 =0;    //offset idac   BIT[9:0]  0 31.25nA, 1023 32uA, step 31.25nA
+    uint8_t dccancel_ps2 =0;    //offset idac   BIT[9:0]  0 31.25nA, 1023 32uA, step 31.25nA
+    uint8_t dccancel_ps3 =0;    //offset idac   BIT[9:0]  0 31.25nA, 1023 32uA, step 31.25nA
+
+    uint8_t leddrive_ps0 =0;     //LEDDRIVE_PS0  0~255 = 0~200ma
+    uint8_t leddrive_ps1 =0;     //LEDDRIVE_PS1  0~255 = 0~200ma
+    uint8_t leddrive_ps2 =0;     //LEDDRIVE_PS2  0~255 = 0~200ma
+    uint8_t leddrive_ps3 =64;     //LEDDRIVE_PS3  0~255 = 0~200ma
+
+    uint8_t ps0_led_on_time=64;    /* 0 = 32clk2=8us ; 8 = 64clk=16us; 16=128clk=32us ; 32 = 256clk=64us ;
+                                     64 = 512clk=128us ; 128= 1024clk=256us; 256= 2048clk=512us*/
+    uint8_t ps1_led_on_time=0;    /* 0 = 32clk2=8us ; 8 = 64clk=16us; 16=128clk=32us ; 32 = 256clk=64us ;
+                                     64 = 512clk=128us ; 128= 1024clk=256us; 256= 2048clk=512us*/
+    uint8_t ps2_led_on_time=0;    /* 0 = 32clk2=8us ; 8 = 64clk=16us; 16=128clk=32us ; 32 = 256clk=64us ;
+                                     64 = 512clk=128us ; 128= 1024clk=256us; 256= 2048clk=512us*/
+    uint8_t ps3_led_on_time=64;    /* 0 = 32clk2=8us ; 8 = 64clk=16us; 16=128clk=32us ; 32 = 256clk=64us ;
+                                     64 = 512clk=128us ; 128= 1024clk=256us; 256= 2048clk=512us*/
+#ifdef SAR_ALG_LIB
+               hx3918_set_cap_data_ready(0);
+#endif
+    hx3918_write_reg(0X18, (uint8_t)prf_clk_num);    // prf bit<7:0>6   default 0x00
+    hx3918_write_reg(0X19, (uint8_t)(prf_clk_num>>8)); // prf bit<11:8>  default 0x03
+
+    hx3918_write_reg(0X1c, ps0_led_on_time);
+    hx3918_write_reg(0X1d, ps1_led_on_time);
+    hx3918_write_reg(0X1e, ps2_led_on_time); 
+    hx3918_write_reg(0X1f, ps3_led_on_time);
+    hx3918_write_reg(0X20, (ps3_cp_avg_num_sel<<6|ps2_cp_avg_num_sel<<4|ps1_cp_avg_num_sel<<2|ps0_cp_avg_num_sel) );
+    hx3918_write_reg(0X21, (ps3_avg_num_sel_i2c<<6|ps2_avg_num_sel_i2c<<4|ps1_avg_num_sel_i2c<<2|ps0_avg_num_sel_i2c));
+    hx3918_write_reg(0X23, (ps0_led_en_i2c<<7|ps1_led_en_i2c<<6|ps2_led_en_i2c<<5|ps3_led_en_i2c<<4|0x0f));
+    hx3918_write_reg(0X26, leddrive_ps0);
+    hx3918_write_reg(0X27, leddrive_ps1);
+    hx3918_write_reg(0X28, leddrive_ps2);
+    hx3918_write_reg(0X29, leddrive_ps3);
+    hx3918_write_reg(0X2c, dccancel_ps0);
+    hx3918_write_reg(0X2d, dccancel_ps1);
+    hx3918_write_reg(0X2e, dccancel_ps2);
+    hx3918_write_reg(0X2f, dccancel_ps3);
+
+    hx3918_write_reg(0X4d, 0X01);  //soft reset
+    hx3918_delay(5);
+    hx3918_write_reg(0X4d, 0X00);  //release
+    hx3918_delay(5);
+#ifdef SAR_ALG_LIB
+               hx3918_prox_reg_init();
+#endif
+    read_fifo_first_flg = 1;
+    AGC_LOG(" chip go to low power mode  \r\n" );
+}
+
+void hx3918_spo2_updata_reg(void)
+{
+    if (calReg.flag & CAL_FLG_LED_DR)
+    {
+        hx3918_write_reg(0X28, calReg.green_cur);
+        hx3918_write_reg(0X27, calReg.red_cur);
+        hx3918_write_reg(0X29, calReg.ir_cur);
+    }
+
+    if (calReg.flag & CAL_FLG_LED_DAC)
+    {
+        hx3918_write_reg(0X2e, (uint8_t)calReg.green_idac);
+        hx3918_write_reg(0X2d, (uint8_t)calReg.red_idac);
+        hx3918_write_reg(0X2f, (uint8_t)calReg.ir_idac);
+    }
+
+    if (calReg.flag & CAL_FLG_AMB_DAC)
+    {
+        hx3918_write_reg(0X2c, (uint8_t)calReg.amb_idac);
+    }
+
+    if (calReg.flag & CAL_FLG_RF)
+    {
+        hx3918_write_reg(0X1c, calReg.ontime); //3918 p1
+        hx3918_write_reg(0X1d, calReg.ontime); //3918 p1
+        hx3918_write_reg(0X1e, calReg.ontime); //3918 p2
+        hx3918_write_reg(0X1f, calReg.ontime); //3918 p3
+    }
+    hx3918_delay(10);
+}
+void hx3918_spo2_set_mode(uint8_t mode_cmd)
+{
+    switch (mode_cmd)
+    {
+        case PPG_INIT:
+            hx3918_spo2_ppg_init();
+            #if defined(TIMMER_MODE)
+            hx3918_ppg_timer_cfg(true);
+            #else
+            hx3918_gpioint_cfg(true);
+            #endif
+            s_ppg_state = 1;
+            AGC_LOG("ppg init mode\r\n");
+            break;
+
+        case PPG_OFF:
+            hx3918_ppg_off();
+            s_ppg_state = 0;
+            AGC_LOG("ppg off mode\r\n");
+            break;
+
+        case PPG_LED_OFF:
+            hx3918_spo2_low_power();
+            s_ppg_state = 0;
+            AGC_LOG("ppg led off mode\r\n");
+            break;
+
+        case CAL_INIT:
+            Init_Spo2_PPG_Calibration_Routine(&calReg);
+            hx3918_spo2_cal_init();
+            hx3918_spo2_updata_reg();
+            #if defined(TIMMER_MODE)
+            hx3918_agc_timer_cfg(true);
+            #endif
+            s_cal_state = 1;
+            AGC_LOG("cal init mode\r\n");
+            break;
+
+        case RECAL_INIT:
+            Restart_Spo2_PPG_Calibration_Routine(&calReg);
+            hx3918_spo2_cal_init();
+            hx3918_spo2_updata_reg();
+            #if defined(TIMMER_MODE)
+            hx3918_agc_timer_cfg(true);
+            #endif
+            s_cal_state = 1;
+            AGC_LOG("recal init mode\r\n");
+            break;
+
+        case CAL_OFF:
+            #if defined(TIMMER_MODE)
+            hx3918_agc_timer_cfg(false);
+            #endif
+            hx3918_spo2_cal_off();
+            s_cal_state = 0;
+            AGC_LOG("cal off mode\r\n");
+            break;
+
+        default:
+            break;
+    }
+}
+
+SENSOR_ERROR_T hx3918_spo2_enable(void)
+{
+    if (!hx3918_chip_check())
+    {
+        AGC_LOG("hx3690l check id failed!\r\n");
+        return SENSOR_OP_FAILED;
+    }
+    TYHX_LOG("hx3690l check id success!\r\n");
+
+    if (s_ppg_state)
+    {
+        AGC_LOG("ppg already on!\r\n");
+        return SENSOR_OP_FAILED;
+    }
+    
+    if(!tyhx_spo2_alg_open())
+    {
+        AGC_LOG("spo2 alg open fail,or dynamic ram not enough!\r\n");
+        return SENSOR_OP_FAILED;
+    }
+    spo2_wear_status = MSG_SPO2_INIT;
+    spo2_wear_status_pre = MSG_SPO2_INIT;
+    hx3918_spo2_set_mode(PPG_INIT);
+    AGC_LOG("hx3690l enable!\r\n");
+
+    return SENSOR_OK;
+}
+
+void hx3918_spo2_disable(void)
+{
+    #if defined(TIMMER_MODE)
+    hx3918_ppg_timer_cfg(false);
+    hx3918_agc_timer_cfg(false);
+    #elif defined(INT_MODE)
+    hx3918_gpioint_cfg(false);
+    #endif
+    hx3918_spo2_set_mode(PPG_OFF);
+    s_ppg_state = 0;
+    s_cal_state = 0;
+    tyhx_spo2_alg_close();
+    AGC_LOG("hx3690l disable!\r\n");
+}
+
+void hx3918_spo2_data_reset(void)
+{
+    s_ppg_state = 0;
+    s_cal_state = 0;
+    tyhx_spo2_alg_close();
+}
+
+hx3918_spo2_wear_msg_code_t hx3918_spo2_get_wear_status(void)
+{
+    return  spo2_wear_status;
+}
+
+SPO2_CAL_SET_T get_spo2_agc_status(void)
+{
+    SPO2_CAL_SET_T cal;
+    cal.flag = calReg.flag;
+    cal.int_cnt = calReg.int_cnt;
+    cal.green_cur = calReg.green_cur;
+    cal.red_cur = calReg.red_cur;
+    cal.ir_cur = calReg.ir_cur;
+    cal.green_idac = calReg.green_idac;
+    cal.red_idac = calReg.red_idac;
+    cal.ir_idac = calReg.ir_idac;
+    cal.amb_idac = calReg.amb_idac;
+    cal.ontime = calReg.ontime;
+    cal.green_led_step = calReg.green_led_step;
+    cal.red_led_step = calReg.red_led_step;
+    cal.ir_led_step = calReg.ir_led_step;
+    cal.state = calReg.state;
+    return cal;
+}
+
+uint8_t hx3918_spo2_read(ppg_sensor_data_t * s_dat)
+{
+    int32_t Red_src_data;
+    int32_t Ir_src_data;
+    int32_t Green_src_data;
+    int32_t Amb_data;
+    bool recal = false;
+    int32_t *green_buf = &(s_dat->green_data[0]);
+    int32_t *red_buf =  &(s_dat->red_data[0]);
+    int32_t *ir_buf =  &(s_dat->ir_data[0]);
+    int32_t *s_buf =  &(s_dat->s_buf[0]);
+    //int32_t *sar_lp_data  = &s_dat->sar_data;
+    s_dat->green_cur = calReg.green_cur;
+    s_dat->red_cur =  calReg.red_cur;
+    s_dat->ir_cur =  calReg.ir_cur;
+    uint8_t data_count = 0;
+    if (!s_ppg_state || s_cal_state)
+    {
+        return NULL;
+    }
+    data_count = hx3918_read_fifo_data(s_buf,4,1);
+    //*sar_lp_data = hx3918_read_sar_data();
+    s_dat->count =  data_count;
+       TYHX_LOG("\r\n spo2  ir data:   ");
+    for (uint8_t i=0; i<data_count; i++)
+    {
+        Amb_data = s_buf[i*4];
+        Green_src_data = s_buf[i*4+2];
+        Red_src_data = s_buf[i*4+1];
+        Ir_src_data = s_buf[i*4+3];
+
+        green_buf[i] = Green_src_data-260000;
+        red_buf[i] = Red_src_data-260000;
+        ir_buf[i] = Ir_src_data-260000;
+        if(spo2_wear_status==MSG_SPO2_WEAR)
+        {
+        
+                       TYHX_LOG("spo2  unwear data %d\r\n:     ",calReg.ir_idac);
+            if(hx3918_spo2_check_unwear())
+            {
+                return NULL;
+            }
+        }
+        else
+        {
+               TYHX_LOG("spo2  check wear data %d\r\n: ",Ir_src_data-Amb_data);
+            if(hx3918_spo2_check_wear(Ir_src_data-Amb_data))
+            {
+                return NULL;
+            }
+        }
+        
+        if (Green_src_data<100000 || Green_src_data>400000 || Red_src_data<100000 || Red_src_data>400000 || Ir_src_data<100000 || Ir_src_data>400000)
+        {
+            recal = true;
+            if(spo2_wear_status==MSG_SPO2_NO_WEAR)
+            {
+                recal = false;
+            }
+        }
+    }
+       TYHX_LOG("\r\n");
+    if (recal)
+    {
+        cal_delay--;
+        if (cal_delay <= 0)
+        {
+            cal_delay = CAL_DELAY_COUNT;
+            hx3918_spo2_set_mode(RECAL_INIT);
+        }
+    }
+    else
+    {
+        cal_delay = CAL_DELAY_COUNT;
+    }
+    return 1;
+}
+
+#ifdef SPO2_DATA_CALI
+static int32_t red_data_fifo[4] = {0};
+static int32_t ir_data_fifo[4] = {0};
+static int32_t red_dc_temp = 0;
+static int32_t ir_dc_temp = 0;
+static int32_t red_data_pre = 0;
+static int32_t ir_data_pre = 0;
+static int32_t red_jump_delta = 0;
+static int32_t ir_jump_delta = 0;
+static int32_t cali_data_cnt = 0;
+
+void hx3918_spo2_data_cali_init(void)
+{
+    int ii=0;
+    for(ii=0; ii<4; ii++)
+    {
+        red_data_fifo[ii] = 0;
+        ir_data_fifo[ii] = 0;
+    }
+    red_dc_temp = 0;
+    ir_dc_temp = 0;
+    red_data_pre = 0;
+    ir_data_pre = 0;
+    red_jump_delta = 0;
+    ir_jump_delta = 0;
+    cali_data_cnt = 0;
+}
+
+int32_t hx3918_red_data_cali(int32_t red_new_raw_data)
+{
+    uint8_t ii;
+    int32_t red_data_final;
+    int32_t red_data_cali;
+    hx3918_spo2_wear_msg_code_t touch_status;
+    touch_status = hx3918_spo2_get_wear_status();
+    if(touch_status == MSG_SPO2_NO_WEAR)
+    {
+        cali_data_cnt = 0;
+        red_data_cali = red_new_raw_data;
+        for(ii=0; ii<4; ii++)
+        {
+            red_data_fifo[ii] = 0;
+        }
+        red_dc_temp = 0;
+    }
+    else
+    {
+        for(ii=3; ii>0; ii--)
+        {
+            red_data_fifo[ii] = red_data_fifo[ii-1];
+        }
+        red_data_fifo[0] = red_new_raw_data;
+        if(cali_data_cnt>=25)
+        {
+            if ((((red_data_fifo[1] - red_data_fifo[2]) > SOP2_DEGLITCH_THRE) && ((red_data_fifo[1] - red_new_raw_data) > SOP2_DEGLITCH_THRE)) || \
+                    (((red_data_fifo[1] - red_data_fifo[2]) < -SOP2_DEGLITCH_THRE) && ((red_data_fifo[1] - red_new_raw_data) < -SOP2_DEGLITCH_THRE)))
+            {
+                red_new_raw_data = red_data_fifo[2];
+                red_data_fifo[1] = red_data_fifo[2];
+            }
+            else
+            {
+                red_new_raw_data = red_data_fifo[1];
+            }
+            if ((abs((red_new_raw_data - red_jump_delta) - red_data_pre) > SPO2_REMOVE_JUMP_THRE))
+            {
+                red_jump_delta = red_new_raw_data - red_data_pre;
+            }
+            red_data_cali = red_new_raw_data - red_jump_delta;
+            red_data_pre = red_data_cali;
+        }
+        else
+        {
+            red_data_cali = red_data_fifo[1];
+            red_data_pre = red_data_fifo[1];
+        }
+    }
+    if(cali_data_cnt<=30)
+    {
+        red_dc_temp = red_data_cali;
+        red_data_final = red_new_raw_data;
+    }
+    else
+    {
+        red_dc_temp = (red_dc_temp*31 + red_data_cali)>>5;
+        red_data_final = red_data_cali - red_dc_temp + 2608*50*hx3918_spo2_agc_red_idac;
+    }
+    return red_data_final;
+}
+int32_t hx3918_ir_data_cali(int32_t ir_new_raw_data)
+{
+    uint8_t ii;
+    int32_t ir_data_final;
+    int32_t ir_data_cali;
+    hx3918_spo2_wear_msg_code_t touch_status;
+    touch_status = hx3918_spo2_get_wear_status();
+    if(touch_status == MSG_SPO2_NO_WEAR)
+    {
+        cali_data_cnt = 0;
+        ir_data_cali = ir_new_raw_data;
+        for(ii=0; ii<4; ii++)
+        {
+            ir_data_fifo[ii] = 0;
+        }
+        ir_dc_temp = 0;
+    }
+    else
+    {
+        for(ii=3; ii>0; ii--)
+        {
+            ir_data_fifo[ii] = ir_data_fifo[ii-1];
+        }
+        ir_data_fifo[0] = ir_new_raw_data;
+        cali_data_cnt++;
+        if(cali_data_cnt>=25)
+        {
+            if ((((ir_data_fifo[1] - ir_data_fifo[2]) > SOP2_DEGLITCH_THRE) && ((ir_data_fifo[1] - ir_new_raw_data) > SOP2_DEGLITCH_THRE)) || \
+                    (((ir_data_fifo[1] - ir_data_fifo[2]) < -SOP2_DEGLITCH_THRE) && ((ir_data_fifo[1] - ir_new_raw_data) < -SOP2_DEGLITCH_THRE)))
+            {
+                ir_new_raw_data = ir_data_fifo[2];
+                ir_data_fifo[1] = ir_data_fifo[2];
+            }
+            else
+            {
+                ir_new_raw_data = ir_data_fifo[1];
+            }
+            if ((abs((ir_new_raw_data - ir_jump_delta) - ir_data_pre) > SPO2_REMOVE_JUMP_THRE))
+            {
+                ir_jump_delta = ir_new_raw_data - ir_data_pre;
+            }
+            ir_data_cali = ir_new_raw_data - ir_jump_delta;
+            ir_data_pre = ir_data_cali;
+        }
+        else
+        {
+            ir_data_cali = ir_data_fifo[1];
+            ir_data_pre = ir_data_fifo[1];
+        }
+    }
+    if(cali_data_cnt<=30)
+    {
+        ir_dc_temp = ir_data_cali;
+        ir_data_final = ir_new_raw_data;
+    }
+    else
+    {
+        ir_dc_temp = (ir_dc_temp*31 + ir_data_cali)>>5;
+        ir_data_final = ir_data_cali - ir_dc_temp + 2608*50*hx3918_spo2_agc_ir_idac;
+    }
+    return ir_data_final;
+}
+#endif
+
+#endif
diff --git a/2.sdk/sdk/gui/lv_drivers/indev/HX3918/hx3918_spo2_agc.h b/2.sdk/sdk/gui/lv_drivers/indev/HX3918/hx3918_spo2_agc.h
new file mode 100644 (file)
index 0000000..04f0c8a
--- /dev/null
@@ -0,0 +1,90 @@
+#ifndef _HX3918_SPO2_AGC_H_
+#define _HX3918_SPO2_AGC_H_
+#include <stdint.h>
+#include <stdbool.h>
+#include "hx3918.h"
+
+#define CAL_DELAY_COUNT (3)
+
+#define CAL_FLG_LED_DR     0x01
+#define CAL_FLG_LED_DAC    0x02 
+#define CAL_FLG_AMB_DAC    0x04
+#define CAL_FLG_RF         0x08
+
+#define SPO2_CAL_INIT_LED_GREEN 64
+#define SPO2_CAL_INIT_LED_RED 64
+#define SPO2_CAL_INIT_LED_IR 64
+
+
+typedef enum {    
+    sCalStart,
+       sCalLedCur,     
+    sCalLed,
+    sCalLed2,
+    sCalFinish, 
+} SPO2_STATE_T;
+
+typedef enum {
+       MSG_SPO2_NO_WEAR,
+       MSG_SPO2_WEAR,
+       MSG_SPO2_INIT
+} hx3918_spo2_wear_msg_code_t;
+
+typedef struct {
+  uint8_t                 red_offset_idac;
+  uint8_t                 ir_offset_idac; 
+  uint8_t                 green_offset_idac; 
+  uint16_t                spo2_start_cnt;
+} hx3918_spo2_agcpara_t;
+
+typedef struct {
+       uint8_t flag;
+       bool work;
+       uint8_t int_cnt;
+       uint8_t cur255_cnt;
+       uint8_t green_idac;
+       uint8_t red_idac;
+       uint8_t ir_idac;
+       uint8_t amb_idac;
+       uint16_t green_cur; 
+       uint16_t red_cur;     
+       uint16_t ir_cur;       
+       uint8_t ontime;
+       uint32_t green_led_step;
+       uint32_t red_led_step;
+       uint32_t ir_led_step;
+       uint8_t state;
+       uint8_t green_max_cur;
+       uint8_t red_max_cur;
+       uint8_t ir_max_cur;
+} SPO2_CAL_SET_T;
+
+
+void Init_Spo2_PPG_Calibration_Routine(SPO2_CAL_SET_T *calR);  
+void Restart_spo2_PPG_Calibration_Routine(SPO2_CAL_SET_T *calR);
+void PPG_Spo2_Calibration_Routine(SPO2_CAL_SET_T *calR, int32_t amb, int32_t green_led, int32_t r_led, int32_t ir_led);
+SPO2_CAL_SET_T PPG_spo2_agc(void);
+
+void hx3918_spo2_cal_init(void);
+void hx3918_spo2_cal_off(void);
+
+void read_spo2_data_packet(int32_t *buf);
+void read_spo2_ir_packet(int32_t *buf);
+void hx3918_spo2_read_data(int32_t *buf);
+
+void hx3918_spo2_low_power(void);
+void hx3918_spo2_normal_power(void);
+
+void hx3918_spo2_updata_reg(void);
+void hx3918_spo2_set_mode(uint8_t mode_cmd);
+SENSOR_ERROR_T hx3918_spo2_enable(void);
+void hx3918_spo2_disable(void);
+hx3918_spo2_wear_msg_code_t hx3918_spo2_get_wear_status(void);
+uint8_t hx3918_spo2_read(ppg_sensor_data_t * s_dat);
+uint8_t hx3918_spo2_read_data_packet(int32_t *s_buf);
+bool hx3918_spo2_check_unwear(void);
+bool hx3918_spo2_check_wear(int32_t infrared_data);
+SPO2_CAL_SET_T get_spo2_agc_status(void);
+void hx3918_spo2_data_reset(void);
+
+#endif
diff --git a/2.sdk/sdk/gui/lv_drivers/indev/HX3918/tyhx_hrs_alg.h b/2.sdk/sdk/gui/lv_drivers/indev/HX3918/tyhx_hrs_alg.h
new file mode 100644 (file)
index 0000000..7aea5f9
--- /dev/null
@@ -0,0 +1,117 @@
+#ifndef _TYHX_HRS_ALG_H_
+#define _TYHX_HRS_ALG_H_
+#endif
+
+#include <stdint.h>
+// /* portable 8-bit unsigned integer */
+// typedef unsigned char           uint8_t;
+// /* portable 8-bit signed integer */
+// typedef signed char             int8_t;
+// /* portable 16-bit unsigned integer */
+// typedef unsigned short int      uint16_t;
+// /* portable 16-bit signed integer */
+// typedef signed short int        int16_t;
+// /* portable 32-bit unsigned integer */
+// typedef unsigned int            uint32_t;
+// /* portable 32-bit signed integer */
+// typedef signed int              int32_t;
+
+#ifndef  bool
+#define  bool unsigned char
+#endif
+#ifndef  true
+#define  true  1
+#endif
+#ifndef  false
+#define  false  0
+#endif
+
+
+#ifdef HRS_ALG_LIB
+
+typedef enum {
+       NORMAL_MODE,
+       RIDE_MODE,
+       WALK_MODE,
+       JUMP_MODE,
+       ALLDAY_HR_MODE,
+       HIGH_POW_MODE
+} hrs_sports_mode_t;
+
+typedef enum {
+       MSG_HRS_ALG_NOT_OPEN,
+       MSG_HRS_ALG_OPEN,
+       MSG_HRS_READY,
+       MSG_HRS_ALG_TIMEOUT,
+} hrs_alg_msg_code_t;
+
+typedef enum {
+       MSG_LIVING_INITIAL,
+       MSG_LIVING_TRUE,
+       MSG_LIVING_FAIL
+} living_msg_code_t;
+
+typedef struct {
+       hrs_alg_msg_code_t  hrs_alg_status;
+    living_msg_code_t   living_status;
+       uint32_t            data_cnt;
+       uint8_t             hr_result;
+       uint16_t            cal_result;
+       uint8_t             hr_result_qual;
+    uint32_t            hr_result_std;
+} hrs_results_t;
+
+typedef struct {
+       uint32_t data_cnt;
+       uint8_t  motion_status;
+       uint32_t gsen_pow;
+       int8_t   up_clip;
+       int8_t   dn_clip;
+       uint8_t  runrun_cnt;
+} HRS_ALG_INFO_T;
+
+#ifdef BP_CUSTDOWN_ALG_LIB
+typedef enum {
+       MSG_BP_ALG_NOT_OPEN = 0x01,
+       MSG_BP_NO_TOUCH = 0x02,
+       MSG_BP_PPG_LEN_TOO_SHORT = 0x03,
+       MSG_BP_READY = 0x04,
+       MSG_BP_ALG_TIMEOUT = 0x05,
+       MSG_BP_SETTLE = 0x06
+} bp_msg_code_t;
+
+typedef struct {
+       uint8_t age;
+       uint8_t height;
+       uint8_t weight;
+       uint8_t gender;
+       uint8_t ref_sbp;
+       uint8_t ref_dbp;
+} bp_exinf_t;
+
+typedef struct {
+       bp_msg_code_t   bp_alg_status;
+       uint8_t         sbp;
+       uint8_t         dbp; 
+       uint32_t        data_cnt;
+       uint8_t         hr_result;
+       bool            object_flg;
+} bp_results_t;
+
+
+void tyhx_bp_set_exinf(uint8_t age, uint8_t height, uint8_t weight, uint8_t gender, uint8_t ref_sbp, uint8_t ref_dbp);
+void tyhx_bp_age_fn(uint8_t hr_result, bp_exinf_t body_s);
+void tyhx_restart_bp_cal(void);
+bp_results_t tyhx_alg_get_bp_results(void);
+#endif //BP_CUSTDOWN_ALG_LIB
+
+bool tyhx_hrs_alg_open(void);
+bool tyhx_hrs_alg_open_deep(void);
+void tyhx_hrs_alg_close(void);
+bool tyhx_hrs_alg_send_data(int32_t *new_raw_data,uint8_t dat_len, int16_t *gsen_data_x, int16_t *gsen_data_y, int16_t *gsen_data_z);
+bool tyhx_hrs_alg(int32_t new_raw_data, int16_t gsen_data_x, int16_t gsen_data_y, int16_t gsen_data_z);
+hrs_results_t tyhx_hrs_alg_get_results(void);
+void tyhx_hrs_set_alg_para(hrs_sports_mode_t sports_mode, uint16_t static_thre_val, uint8_t gsen_fun_lv_val);
+void tyhx_hrs_set_living(uint8_t mode, uint8_t qu_thre, uint8_t st_thre);
+HRS_ALG_INFO_T tyhx_get_hrs_alg_info(void);
+#endif //HRS_ALG_LIB
diff --git a/2.sdk/sdk/gui/lv_drivers/indev/HX3918/tyhx_hrv_alg.h b/2.sdk/sdk/gui/lv_drivers/indev/HX3918/tyhx_hrv_alg.h
new file mode 100644 (file)
index 0000000..37bd4d8
--- /dev/null
@@ -0,0 +1,64 @@
+#ifndef _TYHX_HRV_ALG_H_
+#define _TYHX_HRV_ALG_H_
+#endif
+       
+#include <stdint.h>
+
+// /* portable 8-bit unsigned integer */
+// typedef unsigned char           uint8_t;
+// /* portable 8-bit signed integer */
+// typedef signed char             int8_t;
+// /* portable 16-bit unsigned integer */
+// typedef unsigned short int      uint16_t;
+// /* portable 16-bit signed integer */
+// typedef signed short int        int16_t;
+// /* portable 32-bit unsigned integer */
+// typedef unsigned int            uint32_t;
+// /* portable 32-bit signed integer */
+// typedef signed int              int32_t;
+
+#ifndef  bool
+#define  bool unsigned char
+#endif
+#ifndef  true
+#define  true  1
+#endif
+#ifndef  false
+#define  false  0
+#endif
+
+#define HRV_GLITCH_THRES     20000 
+#define HRV_GSEN_POW_THRE    150
+
+#ifdef HRV_ALG_LIB
+
+typedef enum {
+    MSG_HRV_ALG_NOT_OPEN,
+    MSG_HRV_ALG_OPEN,
+    MSG_HRV_READY,
+    MSG_HRV_ALG_TIMEOUT,
+} hrv_alg_msg_code_t;
+
+typedef struct {
+    hrv_alg_msg_code_t  hrv_alg_status;
+    uint32_t    data_cnt;
+    uint8_t     hrv_result;
+    uint32_t    hrv_peak; 
+    uint8_t     spirit_pressure;
+    uint8_t     p_m;
+    uint8_t     screen_up;
+    uint8_t     motion;
+    uint8_t     signal_quality;
+} hrv_results_t;
+
+
+void tyhx_hrv_alg(int32_t new_raw_data);
+bool tyhx_hrv_alg_open(void);
+bool tyhx_hrv_alg_open_deep(void);
+void tyhx_hrv_alg_close(void);
+void kfft(double *pr,double *pi,int n,int k,double *fr,double *fi);
+
+hrv_results_t tyhx_hrv_alg_send_data(int32_t new_raw_data, int32_t green_data_als, int32_t infrared_data);
+hrv_results_t tyhx_hrv_alg_send_bufdata(int32_t *new_raw_data, uint8_t count, int16_t *gsen_data_x, int16_t *gsen_data_y, int16_t *gsen_data_z);
+#endif //HRV_ALG_LIB
+               
diff --git a/2.sdk/sdk/gui/lv_drivers/indev/HX3918/tyhx_spo2_alg.h b/2.sdk/sdk/gui/lv_drivers/indev/HX3918/tyhx_spo2_alg.h
new file mode 100644 (file)
index 0000000..dfe662a
--- /dev/null
@@ -0,0 +1,164 @@
+#ifndef _SPO2_ALG_H_
+#define _SPO2_ALG_H_
+#endif
+#include <stdint.h>
+
+//version:3.3.17
+
+//#include "tyhx_spo2_alg_para.h"
+
+
+// /* portable 8-bit unsigned integer */
+// typedef unsigned char           uint8_t;
+// /* portable 8-bit signed integer */
+// typedef signed char             int8_t;
+// /* portable 16-bit unsigned integer */
+// typedef unsigned short int      uint16_t;
+// /* portable 16-bit signed integer */
+// typedef signed short int        int16_t;
+// /* portable 32-bit unsigned integer */
+// typedef unsigned int            uint32_t;
+// /* portable 32-bit signed integer */
+// typedef signed int              int32_t;
+
+#ifndef bool
+#define bool unsigned char
+#endif
+
+#ifndef  true
+#define  true  1
+#endif
+#ifndef  false
+#define  false  0
+#endif
+
+
+#ifdef SPO2_ALG_LIB
+
+typedef enum {
+       MSG_SPO2_ALG_NOT_OPEN,
+       MSG_SPO2_ALG_OPEN,
+       MSG_SPO2_READY,
+       MSG_SPO2_ALG_TIMEOUT,
+    MSG_SPO2_END
+} spo2_alg_msg_code_t;
+
+typedef enum {
+       MSG_SPO2_LIVING_INITIAL,
+       MSG_SPO2_LIVING_TRUE,
+       MSG_SPO2_LIVING_FAIL
+} spo2_living_code_t;
+
+typedef enum {
+       SPO2_NORMAL_MODE,
+       SPO2_ALLDAY_MODE
+} spo2_mode_t;
+
+typedef struct {
+    spo2_alg_msg_code_t                spo2_alg_status;
+    spo2_living_code_t      spo2_living_status;
+    uint32_t           data_cnt;
+    uint8_t                    spo2_result;
+    uint8_t                    hr_result;
+    uint8_t                    block_cnt;
+    uint8_t                    ir_quality;
+    uint16_t           reliable_score_result;
+
+    uint8_t                    screen_up;
+    uint8_t                    motion;
+    uint8_t                    poor_signal;
+    
+    uint8_t         signal_snr;
+    uint32_t        signal_std;
+    
+} spo2_results_t;
+
+typedef struct {
+    uint8_t                    screen_up;
+    uint8_t                    motion;
+    uint8_t                    poor_signal;
+} spo2_gesture_recognize_t;
+
+typedef struct {
+       uint32_t data_cnt;
+       int32_t red_new_raw_data;
+       int32_t ir_new_raw_data;
+       int32_t green_new_raw_data;
+       int32_t ir_iir_data_filter_out;
+       int32_t ir_data_smooth;
+       int32_t red_iir_data_filter_out;
+       int32_t red_data_smooth;
+       uint8_t ir_offset_50;
+       uint8_t red_offset_50;
+       uint8_t green_offset_50;
+       int32_t ir_dc;
+       int32_t red_dc;
+       int32_t green_dc;
+       int32_t ir_data_o2_128;
+       int32_t red_data_o2_128;
+       int32_t green_data_o2_128;
+       int16_t red_ir_dc;
+       int16_t red_green_dc;
+       int16_t ir_green_dc;
+       int16_t ir_fft_snr;
+       int8_t  motion_status;
+       uint8_t xcorr_max;
+       int16_t COUNT_IN_judge;
+       uint8_t spo2_result;
+       uint8_t count_block;
+       int32_t SaO2_data_temp;
+} spo2_debug_t;
+
+typedef struct {
+         uint8_t       red_offset_idac;
+         uint8_t       ir_offset_idac; 
+         uint8_t       green_offset_idac; 
+         uint16_t      spo2_start_cnt;
+} spo2_agcpara_t;
+
+typedef struct {
+       uint8_t XCORR_MODE;
+       uint8_t QUICK_RESULT;
+} spo2_switch_t;
+
+typedef struct {
+       uint8_t  SPO2_LOW_XCORR_THRE;
+       uint8_t  SPO2_LOW_SNR_THRE;
+       uint8_t  COUNT_BLOCK_NUM;
+       uint32_t SPO2_BASE_LINE_INIT;
+       uint32_t SPO2_SLOPE;
+    uint16_t SPO2_GSEN_POW_THRE;
+} spo2_usuallyadjust_t;
+
+typedef struct {
+       uint16_t MEAN_NUM;
+       int32_t  SOP2_DEGLITCH_THRE;
+       int32_t  SPO2_REMOVE_JUMP_THRE;
+       uint16_t SPO2_LOW_CLIP_END_TIME;
+       uint16_t SPO2_LOW_CLIP_DN;
+       uint16_t SPO2_NORMAL_CLIP_DN;
+       uint16_t IR_AC_TOUCH_THRE;
+       uint16_t IR_FFT_POW_THRE;
+       uint8_t  SPO2_CALI;
+       uint8_t  SLOPE_PARA_MAX;
+       uint8_t  SLOPE_PARA_MIN;
+} spo2_barelychange_t;
+
+void tyhx_spo2_set_switch(uint8_t XCORR_MODE,uint8_t QUICK_RESULT);
+void tyhx_spo2_para_usuallyadjust(uint8_t SPO2_LOW_XCORR_THRE,uint8_t SPO2_LOW_SNR_THRE,uint8_t COUNT_BLOCK_NUM,uint32_t SPO2_BASE_LINE_INIT,uint32_t SPO2_SLOPE,uint16_t SPO2_GSEN_POW_THRE);
+void tyhx_spo2_para_barelychange(uint16_t MEAN_NUM,int32_t SOP2_DEGLITCH_THRE,int32_t SPO2_REMOVE_JUMP_THRE, \
+                                   uint16_t SPO2_LOW_CLIP_END_TIME,uint16_t SPO2_LOW_CLIP_DN,uint16_t SPO2_NORMAL_CLIP_DN, \
+                                   uint16_t IR_AC_TOUCH_THRE,uint16_t IR_FFT_POW_THRE,uint8_t SPO2_CALI,uint8_t SLOPE_PARA_MAX,uint8_t SLOPE_PARA_MIN);
+
+void tyhx_spo2_set_living(uint8_t living_mode, uint8_t qu_thre, uint8_t st_thre);
+void tyhx_spo2_set_mode(spo2_mode_t mode);
+bool tyhx_spo2_alg_send_data(int32_t *red_new_raw_data,int32_t *ir_new_raw_data,int32_t *green_new_raw_data,uint8_t R_LEDDAC,uint8_t IR_LEDDAC,uint8_t G_LEDDAC, int16_t *gsen_data_x, int16_t *gsen_data_y, int16_t *gsen_data_z, uint8_t dat_len);
+void tyhx_spo2_alg(int32_t red_new_raw_data , int32_t ir_new_raw_data, int32_t green_new_raw_data,uint8_t R_LEDDAC,uint8_t IR_LEDDAC,uint8_t G_LEDDAC);
+void tyhx_spo2_alg_close(void);
+bool tyhx_spo2_alg_open(void);
+bool tyhx_spo2_alg_open_deep(void);
+spo2_results_t tyhx_spo2_alg_get_results(void);
+spo2_debug_t tyhx_spo2_alg_debug_results(void);
+
+#endif 
+
index 881e753..2c9a283 100644 (file)
@@ -18,6 +18,9 @@
 #if USE_GH3018
 #include "../../lv_drivers/indev/gh3018.h"
 #endif
+#if USE_HX3918
+#include "../../lv_drivers/indev/HX3918/hx3918.h"
+#endif
 #if USE_ACNT180
 #include "../../lv_drivers/indev/ACNT180.h"
 #elif USE_ACNT117
@@ -94,6 +97,9 @@ void asl_pedometer_steps_clear(void)
 // heart sensor
 void mmi_hsensor_measure_value_clear(void)
 {
+#if USE_HX3918
+    hx3918_hr_bp_bo_value_clear();
+#endif
 #if USE_GH3018
     gh3018_hr_bp_bo_value_clear();
 #endif
@@ -101,8 +107,10 @@ void mmi_hsensor_measure_value_clear(void)
 
 void mmi_hsensor_hr_measure_start(void)
 {
-    mmi_hsensor_measure_value_clear();
-       
+    //mmi_hsensor_measure_value_clear();
+#if USE_HX3918
+    hx3918_measure_hr_start();
+#endif
 #if USE_GH3018
     gh3018_measure_hr_start();
 #endif
@@ -111,7 +119,9 @@ void mmi_hsensor_hr_measure_start(void)
 void mmi_hsensor_spo2_measure_start(void)
 {
     mmi_hsensor_measure_value_clear();
-
+#if USE_HX3918
+    hx3918_measure_bo_start();
+#endif
 #if USE_GH3018
     gh3018_measure_bo_start();
 #endif
@@ -119,6 +129,9 @@ void mmi_hsensor_spo2_measure_start(void)
 
 void mmi_hsensor_measure_stop(void)
 {
+#if USE_HX3918
+    hx3918_measure_stop();
+#endif
 #if USE_GH3018
     gh3018_measure_stop();
 #endif
@@ -126,6 +139,9 @@ void mmi_hsensor_measure_stop(void)
 
 void mmi_hsensor_measure_value_get(uint16_t *hr, uint16_t *bp_high, uint16_t *bp_low, uint16_t *bo)
 {
+#if USE_HX3918
+    hx3918_hr_bp_bo_value_get(hr, bp_high, bp_low, bo);
+#endif    
 #if USE_GH3018
     gh3018_hr_bp_bo_value_get(hr, bp_high, bp_low, bo);
 #endif
@@ -184,7 +200,11 @@ uint8_t asl_hr_bp_bo_sensor_id_get(void)
     return SensorHub_hr_bp_bo_sensor_id_get();
 #elif USE_GH3018
     return get_gh3018_id();
+#elif USE_HX3918
+    return get_hx3918_id();
+
 #else
+
     return 0;
 #endif
 }
@@ -197,6 +217,8 @@ void asl_hr_bp_bo_measure_start(uint8_t always)
     SensorHub_hr_bp_bo_measure_cmd(MEASURE_NORMAL_MODE, 0, always);
 #elif USE_GH3018
     gh3018_measure_hr_start();
+#elif USE_HX3918
+    hx3918_measure_hr_start();
 #else
     return;
 #endif
index a20200b..3d7f5a4 100644 (file)
@@ -36,7 +36,12 @@ enum {
     EM7128_ID,
     BD1662_ID,
     VCHR02_ID,
+#if USE_GH3018
     GH3018_ID,
+#endif  
+#if USE_HX3918
+    HX3918_ID,
+#endif
 #if USE_ACNT180
     ACNT180_ID,
 #endif
index 43ccbe3..45a5670 100644 (file)
@@ -335,6 +335,7 @@ set_property(TARGET modem PROPERTY IMPORTED_OBJECTS
   cust/ct1711/ct1711_drv.a
   cust/si24rx/ssp_host.a
   cust/si24rx/si24rx_drv.a
+  cust/HX3918/Gcc_lib_R5_hx3918_hrs_spo2_hrv_20231013_v02a.a
   cust/gh3018/lib/hbd_communicate_DS5_R5.lib
   cust/gh3018/lib/hbd_ctrl_DS5_R5.lib
   cust/gh3018/lib/common_cortexR5_armcc-5.06u4.lib
@@ -342,6 +343,7 @@ set_property(TARGET modem PROPERTY IMPORTED_OBJECTS
   cust/gh3018/lib/spo2_cortexR5_armcc-5.06u4.lib
   cust/gh3018/lib/nadt_DS5_R5.lib
   cust/gh3018/lib/hrv_DS5_R5.lib
+
   cust/rt_ringbuffer/lib/rt_ringbuffer.a
   softutil/fotadm/lib/lib_fotadm.a
   softutil/rsfota/redstone/lib/librsdl.a
@@ -456,6 +458,7 @@ set_property(TARGET modem PROPERTY IMPORTED_OBJECTS
   cust/ct1711/ct1711_drv.a
   cust/si24rx/ssp_host.a
   cust/si24rx/si24rx_drv.a
+  cust/HX3918/Gcc_lib_R5_hx3918_hrs_spo2_hrv_20231013_v02a.a
   cust/gh3018/lib/hbd_communicate_DS5_R5.lib
   cust/gh3018/lib/hbd_ctrl_DS5_R5.lib
   cust/gh3018/lib/common_cortexR5_armcc-5.06u4.lib
@@ -646,6 +649,7 @@ set_property(TARGET modem PROPERTY IMPORTED_OBJECTS
   cust/ct1711/ct1711_drv.a
   cust/si24rx/ssp_host.a
   cust/si24rx/si24rx_drv.a
+  cust/HX3918/Gcc_lib_R5_hx3918_hrs_spo2_hrv_20231013_v02a.a
   cust/gh3018/lib/hbd_communicate_DS5_R5.lib
   cust/gh3018/lib/hbd_ctrl_DS5_R5.lib
   cust/gh3018/lib/common_cortexR5_armcc-5.06u4.lib
index f2b2f13..4826a22 100644 (file)
 
 /****************heart rate***********/
 #ifndef USE_GH3018
-#define USE_GH3018               1
+#define USE_GH3018               0
+#endif
+
+#ifndef USE_HX3918
+#define USE_HX3918               1
 #endif
 /****************heart rate***********/
 
diff --git a/2.sdk/sdk/product/craneg_modem/cust/HX3918/Gcc_lib_R5F_hx3918_hrs_spo2_hrv_20230922_v02a.a b/2.sdk/sdk/product/craneg_modem/cust/HX3918/Gcc_lib_R5F_hx3918_hrs_spo2_hrv_20230922_v02a.a
new file mode 100644 (file)
index 0000000..edac74e
Binary files /dev/null and b/2.sdk/sdk/product/craneg_modem/cust/HX3918/Gcc_lib_R5F_hx3918_hrs_spo2_hrv_20230922_v02a.a differ
diff --git a/2.sdk/sdk/product/craneg_modem/cust/HX3918/Gcc_lib_R5_hx3918_hrs_spo2_hrv_20231013_v02a.a b/2.sdk/sdk/product/craneg_modem/cust/HX3918/Gcc_lib_R5_hx3918_hrs_spo2_hrv_20231013_v02a.a
new file mode 100644 (file)
index 0000000..666031d
Binary files /dev/null and b/2.sdk/sdk/product/craneg_modem/cust/HX3918/Gcc_lib_R5_hx3918_hrs_spo2_hrv_20231013_v02a.a differ
index cedb158..29db5ca 100644 (file)
@@ -37,6 +37,9 @@
 #if USE_GH3018
 #include "lv_drivers/indev/gh3018.h"
 #endif
+#if USE_HX3918
+#include "lv_drivers/indev/HX3918/hx3918.h"
+#endif
 #if USE_ACNT180
 #include "lv_drivers/indev/ACNT180.h"
 #elif USE_ACNT117
@@ -1299,6 +1302,9 @@ static void gui_main(void *param)
 #if USE_GH3018
     gh3018_init();
 #endif
+#if USE_HX3918
+    Hx3918_Init();
+#endif
 #if USE_ACNT180
     hal_acnt180_init();
 #elif USE_ACNT117