From: p15692025051 <846603105@qq.com> Date: Mon, 16 Oct 2023 06:56:27 +0000 (+0800) Subject: hx3918驱动添加 X-Git-Url: http://git.snicker.com.cn/?a=commitdiff_plain;h=dbf2d7a100d34e91415c1430e16262899fd3808a;p=mirrors%2FASR3603_Z5.git hx3918驱动添加 --- diff --git a/2.sdk/sdk/gui/lv_drivers/CMakeLists.txt b/2.sdk/sdk/gui/lv_drivers/CMakeLists.txt index 7f13748b..07b070e8 100644 --- a/2.sdk/sdk/gui/lv_drivers/CMakeLists.txt +++ b/2.sdk/sdk/gui/lv_drivers/CMakeLists.txt @@ -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 index 00000000..b6ed219d --- /dev/null +++ b/2.sdk/sdk/gui/lv_drivers/indev/HX3918/hx3918.c @@ -0,0 +1,1647 @@ + + + +#include "lv_drv_conf.h" +#if USE_HX3918 + +#include +#include +#include +#include +#include +#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= 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>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>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 sizeof(gsen_fifo_x_tmp)) + gsen_fifo_count = sizeof(gsen_fifo_x_tmp); + for(int i = 0;i sizeof(gsen_fifo_y)) + count = sizeof(gsen_fifo_y); + + for(int i = 0;i count)//移位 + { + for(int i = 0;i>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 +#include + +#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 index 00000000..49c1d901 --- /dev/null +++ b/2.sdk/sdk/gui/lv_drivers/indev/HX3918/hx3918_check_touch.c @@ -0,0 +1,285 @@ +#include +#include +#include +#include +#include + +//#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; iicheck_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]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 index 00000000..ee6a48e6 --- /dev/null +++ b/2.sdk/sdk/gui/lv_drivers/indev/HX3918/hx3918_check_touch.h @@ -0,0 +1,17 @@ +#ifndef _hx3918_CHECK_TOUCH_H_ +#define _hx3918_CHECK_TOUCH_H_ + +#include +#include +#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 index 00000000..26428882 --- /dev/null +++ b/2.sdk/sdk/gui/lv_drivers/indev/HX3918/hx3918_factory_test.c @@ -0,0 +1,498 @@ +#include +#include +#include +#include +#include + +#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 index 00000000..a15cfb4e --- /dev/null +++ b/2.sdk/sdk/gui/lv_drivers/indev/HX3918/hx3918_factory_test.h @@ -0,0 +1,41 @@ +#ifndef _hx3918_FACTORY_TEST_H_ +#define _hx3918_FACTORY_TEST_H_ + +#include +#include + +#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 index 00000000..bddbf9d3 --- /dev/null +++ b/2.sdk/sdk/gui/lv_drivers/indev/HX3918/hx3918_hrs_agc.c @@ -0,0 +1,753 @@ +#include +#include +#include +#include +#include + +//#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; i400000) + { + 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 index 00000000..f6579013 --- /dev/null +++ b/2.sdk/sdk/gui/lv_drivers/indev/HX3918/hx3918_hrs_agc.h @@ -0,0 +1,68 @@ +#ifndef _hx3918_agc_H_ +#define _hx3918_agc_H_ +#include +#include +#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 index 00000000..3cf83f33 --- /dev/null +++ b/2.sdk/sdk/gui/lv_drivers/indev/HX3918/hx3918_hrv_agc.c @@ -0,0 +1,969 @@ +#include +#include +#include +#include +#include + +//#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; i350000) + { + 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 index 00000000..fc2f8827 --- /dev/null +++ b/2.sdk/sdk/gui/lv_drivers/indev/HX3918/hx3918_hrv_agc.h @@ -0,0 +1,80 @@ +#ifndef _HX3918_HRV_AGC_H_ +#define _HX3918_HRV_AGC_H_ +#include +#include +#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 index 00000000..cbd0815e --- /dev/null +++ b/2.sdk/sdk/gui/lv_drivers/indev/HX3918/hx3918_prox.c @@ -0,0 +1,851 @@ +/***************************************************************************** + * @file hx90xx.c + * @author + * @date + * @Emial + * @brief HX3918 module +******************************************************************************/ + +#include +#include +#include +#include + +#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<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 index 00000000..6069fdde --- /dev/null +++ b/2.sdk/sdk/gui/lv_drivers/indev/HX3918/hx3918_prox.h @@ -0,0 +1,138 @@ +/** + ****************************************************************************** + * @file : hx3918_PROX.h + * @version : v1.0 + * @brief : +*/ +#ifndef __HX3918_PROX_H_ +#define __HX3918_PROX_H_ + +#include +#include + + + + +#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 index 00000000..03e0109b --- /dev/null +++ b/2.sdk/sdk/gui/lv_drivers/indev/HX3918/hx3918_spo2_agc.c @@ -0,0 +1,993 @@ +#include +#include +#include +#include +#include + +#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; i400000 || 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 index 00000000..04f0c8a3 --- /dev/null +++ b/2.sdk/sdk/gui/lv_drivers/indev/HX3918/hx3918_spo2_agc.h @@ -0,0 +1,90 @@ +#ifndef _HX3918_SPO2_AGC_H_ +#define _HX3918_SPO2_AGC_H_ +#include +#include +#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 index 00000000..7aea5f90 --- /dev/null +++ b/2.sdk/sdk/gui/lv_drivers/indev/HX3918/tyhx_hrs_alg.h @@ -0,0 +1,117 @@ +#ifndef _TYHX_HRS_ALG_H_ +#define _TYHX_HRS_ALG_H_ +#endif + +#include +// /* 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 index 00000000..37bd4d84 --- /dev/null +++ b/2.sdk/sdk/gui/lv_drivers/indev/HX3918/tyhx_hrv_alg.h @@ -0,0 +1,64 @@ +#ifndef _TYHX_HRV_ALG_H_ +#define _TYHX_HRV_ALG_H_ +#endif + +#include + +// /* 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 index 00000000..dfe662a7 --- /dev/null +++ b/2.sdk/sdk/gui/lv_drivers/indev/HX3918/tyhx_spo2_alg.h @@ -0,0 +1,164 @@ +#ifndef _SPO2_ALG_H_ +#define _SPO2_ALG_H_ +#endif +#include + +//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 + diff --git a/2.sdk/sdk/gui/lv_watch/app_adaptor/app_adaptor_sensor_interface.c b/2.sdk/sdk/gui/lv_watch/app_adaptor/app_adaptor_sensor_interface.c index 881e753e..2c9a283a 100644 --- a/2.sdk/sdk/gui/lv_watch/app_adaptor/app_adaptor_sensor_interface.c +++ b/2.sdk/sdk/gui/lv_watch/app_adaptor/app_adaptor_sensor_interface.c @@ -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 diff --git a/2.sdk/sdk/gui/lv_watch/app_adaptor/app_sensor_task.h b/2.sdk/sdk/gui/lv_watch/app_adaptor/app_sensor_task.h index a20200bf..3d7f5a46 100644 --- a/2.sdk/sdk/gui/lv_watch/app_adaptor/app_sensor_task.h +++ b/2.sdk/sdk/gui/lv_watch/app_adaptor/app_sensor_task.h @@ -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 diff --git a/2.sdk/sdk/product/craneg_modem/CMakeLists.txt b/2.sdk/sdk/product/craneg_modem/CMakeLists.txt index 43ccbe35..45a56708 100644 --- a/2.sdk/sdk/product/craneg_modem/CMakeLists.txt +++ b/2.sdk/sdk/product/craneg_modem/CMakeLists.txt @@ -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 diff --git a/2.sdk/sdk/product/craneg_modem/config/watch/lv_drv_conf.h b/2.sdk/sdk/product/craneg_modem/config/watch/lv_drv_conf.h index f2b2f13d..4826a227 100644 --- a/2.sdk/sdk/product/craneg_modem/config/watch/lv_drv_conf.h +++ b/2.sdk/sdk/product/craneg_modem/config/watch/lv_drv_conf.h @@ -565,7 +565,11 @@ /****************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 index 00000000..edac74ec 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 index 00000000..666031d0 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 diff --git a/2.sdk/sdk/product/craneg_modem/lv_gui_main.c b/2.sdk/sdk/product/craneg_modem/lv_gui_main.c index cedb1581..29db5ca6 100644 --- a/2.sdk/sdk/product/craneg_modem/lv_gui_main.c +++ b/2.sdk/sdk/product/craneg_modem/lv_gui_main.c @@ -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