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