329 lines
9.3 KiB
C
329 lines
9.3 KiB
C
#include "product_test.h"
|
||
#include "pt_hr.h"
|
||
#include "sensor_hub.h"
|
||
#include "health_manager.h"
|
||
#if (PT_HR_ENABLE &&TCFG_SENSOR_HUB)
|
||
/*****************************************************/
|
||
// PT_SENSOR_CONFIG
|
||
/*****************************************************/
|
||
#define PT_HR_MODE_HEART_RATE (0)
|
||
#define PT_HR_MODE_SPO2 (1)
|
||
|
||
#define SPO2_CHECK_DATA_LEN (4*1) // 四轴数据
|
||
#define HR_SENSOR_CHECK_DATA_LEN (3*1) // 三轴数据
|
||
#define HR_THR_IR (1000) // 红外阈值
|
||
#define HR_THR_RED (1000) // 红光阈值
|
||
#define HR_THR_GREEN (1000) // 绿光阈值
|
||
#define HR_THR_ALS (270000) // ALS参数阈值
|
||
|
||
static u8 pt_hr_busy = 0; // 忙碌标记
|
||
static u8 pt_hr_res = 0; // 测试结果
|
||
static u8 pt_hr_id[4] = {0};
|
||
/*****************************************************/
|
||
// PT_SENSOR_DEBUG
|
||
/*****************************************************/
|
||
#define PT_HRSNESOR_DEBUG 1 // DEBUG
|
||
#define PT_HRSENSOR_ERR_DEBUG 1 // DEBUG
|
||
#define PT_HRSENSOR_DEBUG_TEST 0 // DEBUG
|
||
|
||
#if PT_HRSNESOR_DEBUG
|
||
#define pt_log_i(format, ...) printf("[PT_SENSOR(INFO)]@FUNC<%s>"format"\n", __func__, ##__VA_ARGS__)
|
||
#else
|
||
#define pt_log_i(format, ...)
|
||
#endif
|
||
#if PT_HRSENSOR_ERR_DEBUG
|
||
#define pt_log_e(format, ...) printf("[PT_SENSOR(ERROR)]@FUNC<%s>"format"\n", __func__, ##__VA_ARGS__)
|
||
#else
|
||
#define pt_log_e(format, ...)
|
||
#endif
|
||
|
||
//***********************************************************//
|
||
// 获取传感器数据
|
||
// @ func: pt_xxx_data_get
|
||
// @ return: len 数据长度
|
||
// 0 获取不到数据
|
||
//***********************************************************//
|
||
static int pt_hr_data_get(void *data_buf, int data_len, int mode)
|
||
{
|
||
if (PT_HR_MODE_HEART_RATE == mode) {
|
||
return sensor_hub_get_data(SENSOR_DRV_HR, 0, data_buf, data_len);
|
||
} else if (PT_HR_MODE_SPO2 == mode) {
|
||
return sensor_hub_get_data(SENSOR_DRV_SPO2, 0, data_buf, data_len);
|
||
}
|
||
return 0;
|
||
}
|
||
//***********************************************************//
|
||
// 校验数据是否合法
|
||
// @ func: pt_hr_data_check
|
||
// @ return: PT_E_OK(0) 数据正常
|
||
// other 数据异常
|
||
// @ note: 根据sensor厂提供的数据手册/量产测试说明进行修改
|
||
//***********************************************************//
|
||
static int pt_hr_data_check(void *data_buf, int data_len, int mode)
|
||
{
|
||
int *sensor_buf = data_buf;
|
||
|
||
switch (mode) {
|
||
case PT_HR_MODE_HEART_RATE:
|
||
int als_data = 0;
|
||
int hrm_data = 0;
|
||
|
||
for (int i = 0; i < data_len; i += 3) {
|
||
hrm_data = sensor_buf[3 * i];
|
||
als_data = sensor_buf[3 * i + 1];
|
||
|
||
u8 check1 = ((hrm_data - als_data) < HR_THR_GREEN) ? 0 : 1;
|
||
u8 check2 = (als_data < HR_THR_ALS) ? 0 : 1;
|
||
pt_log_i("[%d]hrm:%d als:%d check_result(%d,%d)\n", i, hrm_data, als_data, check1, check2);
|
||
//0值判断
|
||
if ((!hrm_data) && (!als_data)) {
|
||
return PT_E_MOD_ERROR;
|
||
}
|
||
//阈值判断
|
||
if (((hrm_data - als_data) > HR_THR_GREEN) || (als_data > HR_THR_ALS)) {
|
||
return PT_E_MOD_ERROR;
|
||
}
|
||
}
|
||
break;
|
||
case PT_HR_MODE_SPO2 :
|
||
int ir_data = 0;
|
||
int ir_als = 0;
|
||
int red_data = 0;
|
||
int red_als = 0;
|
||
|
||
for (int i = 0; i < data_len; i += 4) {
|
||
red_data = sensor_buf[4 * i];
|
||
red_als = sensor_buf[4 * i + 1];
|
||
ir_data = sensor_buf[4 * i + 2];
|
||
ir_als = sensor_buf[4 * i + 3];
|
||
u8 check1 = (red_data - red_als < HR_THR_RED) ? 0 : 1;
|
||
u8 check2 = (ir_data - ir_als < HR_THR_IR) ? 0 : 1;
|
||
u8 check3 = (red_als < HR_THR_ALS) ? 0 : 1;
|
||
u8 check4 = (ir_als < HR_THR_ALS) ? 0 : 1;
|
||
pt_log_i("[%d]red_als(%d %d)ir_als(%d %d) check_result(%d:%d:%d:%d)\n", i, red_data, red_als, ir_data, ir_als, check1, check2, check3, check4);
|
||
//0值判断
|
||
if (((!red_data) && (!red_als) && (!ir_data) && (!ir_als))) {
|
||
return PT_E_MOD_ERROR;
|
||
}
|
||
//阈值判断
|
||
if (check1 + check2 + check3 + check4) {
|
||
return PT_E_MOD_ERROR;
|
||
}
|
||
}
|
||
break;
|
||
default:
|
||
pt_log_e("mode%d err", mode);
|
||
return PT_E_MOD_ERROR;
|
||
}
|
||
return PT_E_OK;
|
||
}
|
||
//***********************************************************//
|
||
// 心率模式测试
|
||
// @ func: pt_hr_hrmode_test
|
||
// @ return: PT_E_OK(0) 数据正常
|
||
// other 数据异常
|
||
//***********************************************************//
|
||
static int pt_hr_hrmode_test(void)
|
||
{
|
||
int err = PT_E_OK;
|
||
|
||
u16 sensor_data_point = HR_SENSOR_CHECK_DATA_LEN;
|
||
u16 sensor_data_len = sizeof(u32) * sensor_data_point;
|
||
u32 *sensor_buf = NULL;
|
||
if (!sensor_buf) {
|
||
sensor_buf = (u32 *)zalloc(sensor_data_len);
|
||
ASSERT(sensor_buf);
|
||
}
|
||
sensor_hub_enable(SENSOR_DRV_HR, 1);
|
||
sensor_hub_cbuf_enable(SENSOR_DRV_HR, 0, 1);
|
||
os_time_dly(6);
|
||
// 获取hr数据
|
||
if (!pt_hr_data_get(sensor_buf, sensor_data_len, PT_HR_MODE_HEART_RATE)) { //数据为空
|
||
pt_log_e("SENSOR_read_buf_len\n");
|
||
err = PT_E_MOD_ERROR;
|
||
} else {
|
||
// 判断数据是否正常
|
||
err = pt_hr_data_check(sensor_buf, sensor_data_len, PT_HR_MODE_HEART_RATE);
|
||
if (err) {
|
||
pt_log_e("pt_data_check err");
|
||
}
|
||
}
|
||
sensor_hub_enable(SENSOR_DRV_HR, 0);
|
||
sensor_hub_cbuf_enable(SENSOR_DRV_HR, 0, 0);
|
||
if (sensor_buf) {
|
||
free(sensor_buf);
|
||
sensor_buf = NULL;
|
||
}
|
||
|
||
return err;
|
||
}
|
||
//***********************************************************//
|
||
// 血氧模式测试
|
||
// @ func: pt_hr_spo2mode_test
|
||
// @ return: PT_E_OK(0) 数据正常
|
||
// other 数据异常
|
||
//***********************************************************//
|
||
static int pt_hr_spo2mode_test(void)
|
||
{
|
||
int err = PT_E_OK;
|
||
|
||
u16 sensor_data_point = SPO2_CHECK_DATA_LEN;
|
||
u16 sensor_data_len = sizeof(u32) * sensor_data_point;
|
||
u32 *sensor_buf = NULL;
|
||
|
||
if (!sensor_buf) {
|
||
sensor_buf = (u32 *)zalloc(sensor_data_len);
|
||
ASSERT(sensor_buf);
|
||
}
|
||
sensor_hub_enable(SENSOR_DRV_SPO2, 1);
|
||
sensor_hub_cbuf_enable(SENSOR_DRV_SPO2, 0, 1);
|
||
os_time_dly(6);
|
||
// 获取hr数据
|
||
if (!pt_hr_data_get(sensor_buf, sensor_data_len, PT_HR_MODE_SPO2)) { //数据为空
|
||
pt_log_e("SENSOR_read_buf_len\n");
|
||
err = PT_E_MOD_ERROR;
|
||
} else {
|
||
// 判断数据是否正常
|
||
err = pt_hr_data_check(sensor_buf, sensor_data_len, PT_HR_MODE_SPO2);
|
||
if (err) {
|
||
pt_log_e("pt_data_check err");
|
||
}
|
||
}
|
||
sensor_hub_enable(SENSOR_DRV_SPO2, 0);
|
||
sensor_hub_cbuf_enable(SENSOR_DRV_SPO2, 0, 0);
|
||
if (sensor_buf) {
|
||
free(sensor_buf);
|
||
sensor_buf = NULL;
|
||
}
|
||
|
||
return err;
|
||
}
|
||
//***********************************************************//
|
||
// 心率传感器模块测试
|
||
// @ func: pt_hr_test
|
||
// @ note: 根据项目需要增删
|
||
//***********************************************************//
|
||
static int pt_hr_test(int priv)
|
||
{
|
||
u32 result = PT_E_OK;
|
||
//心率测试
|
||
result = pt_hr_hrmode_test();
|
||
if (result != PT_E_OK) {
|
||
pt_log_e("pt_hr_hrmode_test err");
|
||
}
|
||
//血氧测试
|
||
result = pt_hr_spo2mode_test();
|
||
if (result != PT_E_OK) {
|
||
pt_log_e("pt_hr_spo2mode_test err");
|
||
}
|
||
|
||
pt_hr_busy = 0;
|
||
pt_hr_res = result;
|
||
|
||
return 0;
|
||
}
|
||
|
||
int pt_hr_init(void)
|
||
{
|
||
sensor_info_t *info = sensor_hub_get_info(SENSOR_DRV_HR);
|
||
if (!info) { //设备是否注册
|
||
pt_log_e("pt_hrsensor_dev_not_find\n");
|
||
return PT_E_NO_DEV;
|
||
}
|
||
if (info->state == SENSOR_STATE_OFFLINE) { //设备是否在线
|
||
pt_log_e("pt_hrsensor_state_error\n");
|
||
return PT_E_DEV_ID;
|
||
}
|
||
|
||
return PT_E_OK;
|
||
}
|
||
|
||
int pt_hr_start(void)
|
||
{
|
||
if (pt_hr_busy) {
|
||
return PT_E_MOD_RUN;
|
||
}
|
||
pt_hr_res = PT_E_MOD_RUN;
|
||
int msg[3] = {0};
|
||
msg[0] = (int)pt_hr_test;
|
||
msg[1] = 1;
|
||
msg[2] = (int)0;
|
||
do {
|
||
int os_err = os_taskq_post_type("app_core", Q_CALLBACK, 3, msg);
|
||
if (os_err == OS_ERR_NONE) {
|
||
break;
|
||
}
|
||
if (os_err != OS_Q_FULL) {
|
||
pt_hr_res = PT_E_SYS_ERROR;
|
||
return PT_E_SYS_ERROR;
|
||
}
|
||
os_time_dly(1);
|
||
} while (1);
|
||
pt_hr_busy = 1;
|
||
|
||
return 0;
|
||
}
|
||
|
||
int pt_hr_stop(void)
|
||
{
|
||
if (pt_hr_busy) {
|
||
return PT_E_MOD_CANT_STOP;
|
||
}
|
||
if (pt_hr_res == PT_E_MOD_RUN) {
|
||
pt_hr_res = PT_E_MOD_STOP_NO_END;
|
||
}
|
||
return 0;
|
||
}
|
||
|
||
int pt_hr_ioctrl(u32 order, int len, void *param)
|
||
{
|
||
u32 result = 0;
|
||
switch (PT_ORDER_C_GET(order)) {
|
||
case PT_N_C_START:
|
||
|
||
result = pt_hr_start();
|
||
break;
|
||
case PT_N_C_STOP:
|
||
result = pt_hr_stop();
|
||
break;
|
||
case PT_N_C_GETINFO:
|
||
|
||
u8 info[8];
|
||
memcpy(&info[0], &result, 4);
|
||
memcpy(&info[4], &pt_hr_id, 4);
|
||
product_test_push_data(order, sizeof(info), (u8 *)info);
|
||
return 0;
|
||
|
||
case PT_N_C_GET_RESULT:
|
||
result = pt_hr_res;
|
||
|
||
break;
|
||
default:
|
||
result = PT_E_PARAM;
|
||
break;
|
||
}
|
||
product_test_push_data(order, 4, (u8 *)&result);
|
||
return result;
|
||
}
|
||
|
||
REGISTER_PT_MODULE(hr) = {
|
||
.module = PT_M_HR,
|
||
.attr = PT_ATTR_SELF,
|
||
.init = pt_hr_init,
|
||
.ioctrl = pt_hr_ioctrl,
|
||
};
|
||
|
||
|
||
#if PT_HRSENSOR_DEBUG_TEST
|
||
int pt_hrsensor_fast_test(void)
|
||
{
|
||
pt_hr_init();
|
||
pt_hr_start();
|
||
pt_hr_test(NULL);
|
||
pt_hr_stop();
|
||
return 0;
|
||
}
|
||
#endif
|
||
#endif /* #if PT_HR_ENABLE */
|
||
|