Files
AC707N/SDK/apps/watch/product_test/pt_hr.c
T
2025-12-03 11:12:34 +08:00

329 lines
9.3 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#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 */