From: p15692025051 <846603105@qq.com> Date: Tue, 28 Nov 2023 09:08:27 +0000 (+0800) Subject: wmm300提交 X-Git-Url: http://git.snicker.com.cn/?a=commitdiff_plain;h=1acdf641fabf19ceafe81a3475e9b469840c3972;p=mirrors%2FASR3603_Z5.git wmm300提交 --- diff --git a/2.sdk/sdk/gui/lv_drivers/indev/WMM300/alg_example.c b/2.sdk/sdk/gui/lv_drivers/indev/WMM300/alg_example.c new file mode 100644 index 00000000..dedd355d --- /dev/null +++ b/2.sdk/sdk/gui/lv_drivers/indev/WMM300/alg_example.c @@ -0,0 +1,429 @@ +#include "lv_drv_conf_CUSTOM.h" +#if USE_WMM300 +#include "whale_algo.h" +#include +#include +#include +#include +#include + + +#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" + +/************************simware add start***********************************/ +static uint32_t wmm300_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 wmm300_hisr_ref; +static void * wmm300_process_timer = NULL; +static void * wmm300_millisecond_timer = NULL; +static whale_algo_plat_if_t plat_if; +static unsigned char is_WMM300 = 0;//是否存在IC +static unsigned char is_open_WMM300 = 0; //是否打开测试 +static unsigned char s_WMM300_heart_rate = 0x0;//心律 +static unsigned char s_WMM300_high_blood = 0x0;//血压/高压 +static unsigned char s_WMM300_low_blood = 0x0;//血压/低压 +static unsigned char s_WMM300_blood_oxygen = 0x0;//血氧 +static unsigned char s_WMM300_HRV = 0x0;//hrv +unsigned char s_WMM300_wear_status = 1;//佩戴状态 +#define HEART_RATE_BUFF_LEN 10 +unsigned char s_WMM300_heart_rate_buff[HEART_RATE_BUFF_LEN]={0}; +unsigned short s_WMM300_heart_rate_buff_count = 0; +uint32_t WMM300_run_mode = NULL_MODE; +uint32_t WMM300_jobs_mode = NULL_MODE; +int ir_wear = 0;//红外佩戴状态 +int cap_wear = 1;//电容佩戴状态 +char is_open_sar = 1;//是否打开sar检测 +activity_data_t act_data; +static void acc_process(void); +void WMM300_close(void); +static void wmm300_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 wmm300_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 wmm300_hisr_callback(void) +{ + sensor_task_send_message(WMM300_ID,SENSOR_MSG_PROCESS_DATA); +} + +static void wmm300_create_hisr(void) +{ + OS_Create_HISR(&wmm300_hisr_ref,"icm_hisr", wmm300_hisr_callback, HISR_PRIORITY_2); +} + + + +/* Timer0_0 is configured to free run @1MHz from BootROM. */ +static void DelayInUs(unsigned int us) +{ + unsigned long startTime, endTime; + Timer0_Switch(1); + startTime = GetTimer0CNT(); + do + { + endTime = GetTimer0CNT(); + } + while(Timer0IntervalInMicro(startTime, endTime) < us); +} +void WMM300_test(uint32_t mode) +{ + s_WMM300_heart_rate = 0x0; + s_WMM300_heart_rate_buff_count = 0; + s_WMM300_high_blood = 0x0; + s_WMM300_low_blood = 0x0; + s_WMM300_HRV = 0; + //s_WMM300_wear_status = 0; + s_WMM300_blood_oxygen = 0x0; + WMM300_LOG("WMM300_test1:%d!!!!\n\n",mode); + if(mode <= close_MODE) + { + if(whale_algo_enable(mode) == WHALE_ALGO_OK) + { + is_open_WMM300 = 1; + WMM300_LOG("wmm300_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 + WMM300_LOG("wmm300_init:error!!!!\n\n"); + }else if(mode == 255) + { + + } + WMM300_LOG("WMM300_test2:%d!!!!\n\n",mode); +} +static void wmm300_process_timer_callback(void) +{ + OS_Activate_HISR(&wmm300_hisr_ref); +} +extern unsigned int WMM300_millisecond; +static void wmm300_millisecond_timer_callback(void) +{ + WMM300_millisecond+=50; + if(WMM300_millisecond > 0xffff0000) + WMM300_millisecond = 0; +} +static void wmm300_start(void) +{ + Timer0_Switch(1); + WMM300_LOG("wmm300_start:WMM300_run_mode:%d\n",WMM300_run_mode); + hal_wmm300_int_init(); + WMM300_restart(); + if(wmm300_process_timer == NULL ) + uos_timer_create(&wmm300_process_timer); + //每500ms轮询一次数据 + uos_timer_start(wmm300_process_timer, MS_TO_TICKS(500), MS_TO_TICKS(500), wmm300_process_timer_callback, NULL); + if(wmm300_millisecond_timer == NULL ) + uos_timer_create(&wmm300_millisecond_timer); + //计时器 + uos_timer_start(wmm300_millisecond_timer, MS_TO_TICKS(50), MS_TO_TICKS(50), wmm300_millisecond_timer_callback, NULL); + WMM300_millisecond = 0; + + + WMM300_test(WMM300_run_mode); + WMM300_jobs_mode = WMM300_run_mode; + WMM300_run_mode = NULL_MODE; + + // hal_gh30x_int_init(); + // wmm300_en_gpio_enable(false); + // DelayInUs(10*1000); + // wmm300_en_gpio_enable(true); + // DelayInUs(50*1000); + // int ret = gh30x_module_init(); + + +} + +static void wmm300_stop(void) +{ + WMM300_LOG("[%s][%d]: \n", __FUNCTION__, __LINE__); + + //wmm300_en_gpio_enable(false); + WMM300_close(); + //WMM300_LOG("WMM300_irq_cb: 1111111111111!!!!!!!!\r\n"); + WMM300_run_mode = NULL_MODE; + WMM300_jobs_mode = NULL_MODE; + uos_timer_stop(wmm300_process_timer); + uos_timer_stop(wmm300_millisecond_timer); + Timer0_Switch(0); + +} +void wmm300_process_data(uint32_t *process_data) +{ + Timer0_Switch(1); + acc_process(); + unsigned char value = 0; + if (whale_algo_process()) { + if (get_activity_data(&act_data)) { + // 存储睡眠活动数据 + } + } + + if (whale_algo_get_result(WMM300_jobs_mode, &value) == WHALE_ALGO_UPDATED) { + //log_len = sprintf(str_buf, "value: %d\n", hr_result.rate); + //port_log(str_buf, log_len); + WMM300_LOG("WMM300_jobs_mode:%d value: %d\n",WMM300_jobs_mode,value); + switch (WMM300_jobs_mode) + { + case WHALE_ALGO_TYPE_HR_CONTINUS: + s_WMM300_heart_rate = value; + break; + case WHALE_ALGO_TYPE_SPO2: + s_WMM300_blood_oxygen = value; + break; + case WHALE_ALGO_TYPE_STRESS: + s_WMM300_low_blood = value; + break; + case WHALE_ALGO_TYPE_WEAR: + s_WMM300_wear_status = value; + break; + default: + break; + } + // s_WMM300_heart_rate = hr; + // s_WMM300_blood_oxygen = bo; + // s_WMM300_high_blood = bp_high ; + // s_WMM300_low_blood = bp_low ; + // WHALE_ALGO_TYPE_HR_CONTINUS, // 连续心率 + // WHALE_ALGO_TYPE_SPO2, // 血氧 + // WHALE_ALGO_TYPE_STRESS, // 压力 + // WHALE_ALGO_TYPE_WRIST, // 转腕 + // WHALE_ALGO_TYPE_WEAR, // 穿戴 + // WHALE_ALGO_TYPE_PEDOMETER, // 计步 + // WHALE_ALGO_TYPE_SLEEP, // 睡眠 + } +} +void hal_wmm300_int_init(void) +{ + // code implement by user + // must register func hal_gh30x_int_handler as callback + Timer0_Switch(1); + mfp_config(wmm300_mfp_cfgs); + wmm300_en_gpio_init(); + WMM300_LOG("WMM300 ID : %d\n",whale_check_chip()); + +} +void Wmm300_Init(void) +{ + Timer0_Switch(1); + static bool register_dev_flag = false; + if(!register_dev_flag) + { + register_dev_flag = true; + sensor_drv_t sensor_drv; + sensor_drv.sensor_name = "wmm300"; + sensor_drv.sensor_start = wmm300_start; + sensor_drv.sensor_stop = wmm300_stop; + sensor_drv.sensor_process_data = wmm300_process_data; + sensor_drv_register(WMM300_ID,&sensor_drv); + } + wmm300_create_hisr(); + hal_wmm300_int_init(); + WMM300_restart(); + memset(&plat_if, 0, sizeof(plat_if)); + + plat_if.sys.log = port_log; // 算法库日志输出函数(便于调试,可用空函数替换) + plat_if.sys.get_tick = port_get_millisecond; // 获取以毫秒为单位的系统时间戳函数 + plat_if.sys.get_rtc_timestamp = port_get_rtc; // 获取以秒为单位的UNIX时间戳函数 + plat_if.sys.delay_ms = port_delay_ms; // 以毫秒为单位的系统延迟函数 + plat_if.sys.malloc = port_malloc; // malloc动态内存分配函数 + plat_if.sys.free = port_free; // free动态内存释放函数 + plat_if.sys.charge_state = port_charge_state; // 获取设备充电状态 + + plat_if.ppg_ctrl.i2c_read = port_afe_read; // 模组I2C通信读数据函数 + plat_if.ppg_ctrl.i2c_write = port_afe_write; // 模组I2C通信写数据函数 + plat_if.ppg_ctrl.pwr_1v8 = port_afe_pwr_lv8; // 模组1.8v电源控制函数 + plat_if.ppg_ctrl.pwr_vled = port_afe_pwr_vled; // 模组vled电源控制函数 + + whale_algo_init(&plat_if); + + +} + + +static bool is_measuring_flag = false; +void wmm300_measure_hr_start(void) +{ + sys_pm_wakeup_no_lcd(); + + + WMM300_run_mode = WHALE_ALGO_TYPE_HR_CONTINUS; + WMM300_LOG("wmm300_measure_hr_start :WMM300_run_mode:%d!!!!!!!!\n",WMM300_run_mode); + sensor_task_send_message(WMM300_ID,SENSOR_MSG_START); +} + +void wmm300_measure_bo_start(void) +{ + sys_pm_wakeup_no_lcd(); + + + WMM300_run_mode = WHALE_ALGO_TYPE_SPO2 ; + WMM300_LOG("wmm300_measure_bo_start :WMM300_run_mode:%d!!!!!!!!\n",WMM300_run_mode); + sensor_task_send_message(WMM300_ID,SENSOR_MSG_START); +} +void WMM300_restart(void) +{ + wmm300_en_gpio_enable(false); + port_delay_ms(50); + wmm300_en_gpio_enable(true); + port_delay_ms(50); +} +void wmm300_measure_stop(void) +{ + WMM300_LOG("wmm300_measure_stop !!!!!!!!\n"); + WMM300_run_mode = close_MODE; + sensor_task_send_message(WMM300_ID,SENSOR_MSG_STOP); +} +void WMM300_close(void) +{ + WMM300_LOG("WMM300_close !!!!!!!!\n"); + watch_set_sleep_lcd_only(false); + is_measuring_flag = false; + //asl_hr_bp_bo_measure_finish_flag_set(); + //wmm300_hrs_disable + + whale_algo_disable(WMM300_jobs_mode); + + WMM300_restart(); + +} + +static void wmm300_hr_bp_bo_value_update(uint16_t hr, uint16_t bp_high, uint16_t bp_low, uint16_t bo) +{ + WMM300_LOG("[@CHENG_DEBUG][%s][%d]: %d,%d,%d,%d\n", __FUNCTION__, __LINE__, hr, bp_high, bp_low, bo); + s_WMM300_heart_rate = hr; + s_WMM300_blood_oxygen = bo; + s_WMM300_high_blood = bp_high ; + s_WMM300_low_blood = bp_low ; + + +} +unsigned char wmm300_result_get_wear_status(void) +{ + + return s_WMM300_wear_status ; +} +uint16_t get_wmm300_hr_value(void) +{ + return s_WMM300_heart_rate; +} + +uint16_t get_wmm300_b0_value(void) +{ + return s_WMM300_blood_oxygen; +} + +void wmm300_hr_bp_bo_value_get(uint16_t *hr, uint16_t *bp_high, uint16_t *bp_low, uint16_t *bo) +{ + if(hr != NULL) + *hr = s_WMM300_heart_rate; + if(bp_high != NULL) + *bp_high = s_WMM300_high_blood; + if(bp_low != NULL) + *bp_low = s_WMM300_low_blood; + if(bo != NULL) + *bo = s_WMM300_blood_oxygen; +} + +void wmm300_hr_bp_bo_value_clear(void) +{ + s_WMM300_heart_rate = 0x0; + s_WMM300_heart_rate_buff_count = 0; + s_WMM300_high_blood = 0x0; + s_WMM300_low_blood = 0x0; + s_WMM300_HRV = 0; + //s_WMM300_wear_status = 0; + s_WMM300_blood_oxygen = 0x0; + //memset(&wmm300_hr_bp_bo_value, 0, sizeof(wmm300_hr_bp_bo_value)); + +} + + + + + + + + + + + + + + +/********************************************************************/ +/********************************************************************/ + + + + + +static void acc_process(void) +{ + + + sensor_data_acc_t *acc_data = port_malloc(25 * sizeof(sensor_data_acc_t)); + + if (acc_data) { + for (uint16_t i=0; i<25; i++) { + acc_data[i].x = -3785; + acc_data[i].y = -1492; + acc_data[i].z = 901; + } + + whale_algo_push_data(WHALE_DATA_TYPE_ACC, acc_data, 1); + + port_free(acc_data); + } +} + + + + + + + + + + + + +#endif \ No newline at end of file diff --git a/2.sdk/sdk/gui/lv_drivers/indev/WMM300/alg_port.c b/2.sdk/sdk/gui/lv_drivers/indev/WMM300/alg_port.c new file mode 100644 index 00000000..590264c6 --- /dev/null +++ b/2.sdk/sdk/gui/lv_drivers/indev/WMM300/alg_port.c @@ -0,0 +1,124 @@ + +#include "lv_drv_conf_CUSTOM.h" +#if USE_WMM300 +#include "whale_algo.h" + +#include "../../../lvgl/hal/hal.h" +#include +#include +#include +#include +#include + +#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" +unsigned int WMM300_millisecond = 0; +// 获取以毫秒为单位的系统时间戳函数 +uint32_t port_get_millisecond(void) +{ + return WMM300_millisecond; // 系统心跳频率为1000hz +} + +// 获取以秒为单位的UNIX时间戳函数 +uint32_t port_get_rtc(void) +{ + unsigned int time= 0; + Hal_Rtc_Gettime_Count(&time); + return time; +} + +// 以毫秒为单位的系统延迟函数 +extern void UOS_SleepMs (uint32_t ms); +void port_delay_ms(uint32_t ms) +{ + UOS_SleepMs(1); +} + +// malloc动态内存分配函数 +void *port_malloc(uint32_t size) +{ + if (size) + return malloc(size); + else + return NULL; +} + +// free动态内存释放函数 +void port_free(void *ptr) +{ + free(ptr); +} + +// 算法库日志输出函数(便于调试) +void port_log(const char *log, uint32_t len) +{ +#if WMM300_DEBUG + WMM300_LOG( "WMM300:%s",log); +#endif + //HAL_UART_Transmit(&huart3, (uint8_t *)log, len, 1000); // 串口输出log +} + +bool port_charge_state(void) +{ + + + // 返回设备充电状态:true - 在充电;false - 未在充电; + if(HAL_CHG_DISCONNECTED / HAL_CHG_CONNECTED == Hal_Charger_Get_Status()) + return true; + else + return false; +} + +#define AFE_ADDR (0x3A >>1) + +// 模组I2C通信读数据函数:先写寄存器 data[0],再读取 len 长度的数据到 &data[0]; +int port_afe_read(unsigned char *data, uint32_t len) +{ + // HAL_I2C_Master_Transmit(&hi2c3, AFE_ADDR, data[0], 1, 100); + // HAL_I2C_Master_Receive(&hi2c3, AFE_ADDR, data, len, 100); + // if(-1 == i2c_read_regs(I2C_MASTER_CI2C1, AFE_ADDR, (uint16_t)data[0],(void *)data,len,0)) + // { + // cplog_printf("read-------->>>i2c receive failed! AFE_ADDR:%d\r\n",AFE_ADDR); + // return -1; + // } + if(-1 == i2c_write_bytes(I2C_MASTER_CI2C1, AFE_ADDR, (void *)data, (size_t)(1),0)) + { + cplog_printf("read-------->>>i2c transmit failed! \r\n"); + return -1; + } + + if(-1 == i2c_read_bytes(I2C_MASTER_CI2C1, AFE_ADDR, (void *)data, (size_t)len,0)) + { + cplog_printf("read-------->>>i2c receive failed! \r\n"); + return -1; + } + return 0; +} + +// 模组I2C通信写数据函数 +int port_afe_write(unsigned char *data, uint32_t len) +{ + //return HAL_I2C_Master_Transmit(&hi2c3, AFE_ADDR, data, len, 100) == HAL_OK; + if(-1 == i2c_write_regs(I2C_MASTER_CI2C1, AFE_ADDR, (uint16_t)data[0], (void *)&data,len,0)) + { + cplog_printf("write-------->>>i2c transmit failed! \r\n"); + return -1; + } + return 0; +} + +// 模组1.8v电源控制函数 +void port_afe_pwr_lv8(bool en) +{ + // +} + +// 模组vled电源控制函数 +void port_afe_pwr_vled(bool en) +{ + // +} +#endif \ No newline at end of file diff --git a/2.sdk/sdk/gui/lv_drivers/indev/WMM300/whale_algo.h b/2.sdk/sdk/gui/lv_drivers/indev/WMM300/whale_algo.h new file mode 100644 index 00000000..e1a11919 --- /dev/null +++ b/2.sdk/sdk/gui/lv_drivers/indev/WMM300/whale_algo.h @@ -0,0 +1,213 @@ + +#ifndef _WHALE_ALGO_H +#define _WHALE_ALGO_H + +#include +#include +#define WMM300_DEBUG 1 +#if WMM300_DEBUG +#define WMM300_LOG(msg, ...) cplog_printf( msg, ##__VA_ARGS__)//printf( msg, ##__VA_ARGS__)// +//#define WMM300_LOG(msg, ...) printf( msg, ##__VA_ARGS__)//printf( msg, ##__VA_ARGS__)// +#else +#define WMM300_LOG(msg, ...) + +#endif +typedef struct { + void (*log)(const char *log, uint32_t len); // log输出 + void* (*malloc)(uint32_t size); // 动态分配内存 + void (*free)(void *ptr); // 释放内存 + uint32_t (*get_tick)(void); // 获取ms级时间戳 + uint32_t (*get_rtc_timestamp)(void); // 获取秒级时间戳 + void (*delay_ms)(uint32_t ms); // ms级延时 + bool (*charge_state)(void); // 获取设备充电状态(返回值:true - 在充电;false - 未在充电;) +} whale_algo_system_t; + +typedef struct { + int (*i2c_read)(uint8_t *data, uint32_t len); // I2C读取接口 + int (*i2c_write)(uint8_t *data, uint32_t len); // I2C写入接口 + void (*pwr_1v8)(bool en); // ppg模组1.8v电源开关 + void (*pwr_vled)(bool en); // ppg模组led电源开关 +} whale_algo_ppg_control_t; + +typedef struct +{ + whale_algo_system_t sys; + whale_algo_ppg_control_t ppg_ctrl; +} whale_algo_plat_if_t; + +typedef enum { + WHALE_DATA_TYPE_ACC, +} WHALE_DATA_TYPE_T; + +typedef struct { + int16_t x; + int16_t y; + int16_t z; +} sensor_data_acc_t; + +typedef enum { + WHALE_ALGO_TYPE_HR_CONTINUS, // 连续心率 + WHALE_ALGO_TYPE_SPO2, // 血氧 + WHALE_ALGO_TYPE_STRESS, // 压力 + WHALE_ALGO_TYPE_WRIST, // 转腕 + WHALE_ALGO_TYPE_WEAR, // 穿戴 + WHALE_ALGO_TYPE_PEDOMETER, // 计步 + WHALE_ALGO_TYPE_SLEEP, // 睡眠 + NULL_MODE,//空闲模式 + close_MODE//关闭模式 +} WHALE_ALGO_TYPE_T; + +typedef enum { + WHALE_ALGO_OK = 0, + WHALE_ALGO_ERROR, + + WHALE_ALGO_UPDATED = WHALE_ALGO_OK, + WHALE_ALGO_NOT_READY, +} WHALE_ALGO_ERROR_T; + +// 手势检测定义 +typedef enum { + WRIST_DO_NOTHING = 0, // 未做手势 + WRIST_UP_TRUE = 0x01, // 抬腕 + WRIST_DOWN_TRUE = 0x02, // 落腕 + WRIST_FLIP_TRUE = 0x04, // 转腕 +} WRIST_RESULT_T; + +// 性别定义 +#define MALE (1) // 男性 +#define FEMALE (0) // 女性 + +// 睡眠模式定义 +typedef enum { + SLEEP_MODE_LIGHT = 4, // 浅睡 + SLEEP_MODE_DEEP = 5, // 深睡 + SLEEP_MODE_WAKE_UP = 7, // 清醒 + SLEEP_MODE_REM = 8, // REM阶段 +} SLEEP_MODE_T; + +// 心率结果 +typedef struct { + uint8_t rate; +} whale_algo_result_hr_t; + +// 血氧结果 +typedef struct { + uint8_t value; +} whale_algo_result_spo2_t; + +// 压力结果 +typedef struct { + uint8_t value; +} whale_algo_result_stress_t; + +// 手势检测 +typedef struct { + WRIST_RESULT_T state; +} whale_algo_result_wrist_t; + +// 佩戴检测 +typedef struct { + bool is_wear; +} whale_algo_result_wear_t; + +// 计步结果 +typedef struct { + uint32_t steps; +} whale_algo_result_ped_t; + +// 用户信息,睡眠计算用 +typedef struct { + uint8_t gender; /* User gender, male:1, female:0 */ + uint8_t height; /* User height, unit cm */ + uint8_t weight; /* User weight, unit kg */ + uint8_t age; /* User age */ +} person_info_t; + +// 活动数据,睡眠计算用 +typedef struct { + uint8_t data[8]; +} activity_data_t; + +// 睡眠阶段数据 +typedef struct { + int16_t start; + int16_t stop; + int16_t mode; +} sleep_stage_t; + +// 睡眠结果数据 +typedef struct { + bool has_sleep; // 是否睡觉 + int16_t sleep_start; // 起始睡眠时间 + int16_t sleep_end; // 结束睡眠时间 + int16_t deep_sleep_len; // 深睡时长(分钟) + int16_t light_sleep_len; // 浅睡时长(分钟) + int16_t wake_up_len; // 清醒时长(分钟) + int16_t rem_sleep_len; // REM(快速动眼)时长(分钟) + int16_t sleep_stage_count; // 睡眠分期个数 + sleep_stage_t *stage_sleep; // 睡眠分期 +} whale_algo_result_sleep_t; + +void whale_algo_init(whale_algo_plat_if_t *_plat_if); +// 500ms 轮询执行 +bool whale_algo_process(void); +void whale_algo_push_data(WHALE_DATA_TYPE_T type, void *data, uint16_t sample_count); + +void get_sleep_result(person_info_t *info, activity_data_t *data, uint32_t length, whale_algo_result_sleep_t *result); // 离线计算 +bool get_activity_data(activity_data_t *data); + +WHALE_ALGO_ERROR_T whale_algo_enable(WHALE_ALGO_TYPE_T algo_type); +void whale_algo_disable(WHALE_ALGO_TYPE_T algo_type); +WHALE_ALGO_ERROR_T whale_algo_get_result(WHALE_ALGO_TYPE_T algo_type, void *result); +char *whale_algo_get_fw_ver(void); + +// 计步清零 +void whale_steps_clear(void); + +// 读取佩戴检测原始数据 +void whale_read_wear(uint16_t *amb, uint16_t *ir); +// 读取心率原始数据,采样率为25hz; 返回值:实际读取数据个数; +uint8_t whale_read_ppg(uint16_t *ppg_data); +// 读取血氧原始数据,采样率为50hz; 返回值:实际读取数据个数; +uint8_t whale_read_spo2(int32_t *red_data, int32_t *ir_data, int32_t *green_data); + +/* 该接口仅用于测试硬件 +* index: 1 - TX1(绿灯); 2 - TX2(红外灯); 4 - TX4(红灯); 0 - 熄灭所有灯; +* 返回:true - 成功; false - 失败; +* 说明:1. 返回false,请检查通信总线;2. 返回true,灯不亮,请检查led接线; +*/ +bool whale_test_ppg_led(uint8_t index); + +/* 读取模组Chip ID,并验证是否正确; +* 返回:true - ID正确; false - ID错误; +* 说明:返回false,请检查电源供电和通信总线,可通过逻辑分析仪抓取信号进行排查; +* 模组I2C的7位地址是0x3A,chip ID的寄存器地址为0xF8,读出来的值为0x0008。 +*/ +bool whale_check_chip(void); + +uint32_t port_get_millisecond(void); +uint32_t port_get_rtc(void); +void port_delay_ms(uint32_t ms); +void *port_malloc(uint32_t size); +void port_free(void *ptr); +void port_log(const char *log, uint32_t len); +bool port_charge_state(void); +int port_afe_read(uint8_t *data, uint32_t len); +int port_afe_write(uint8_t *data, uint32_t len); +void port_afe_pwr_lv8(bool en); +void port_afe_pwr_vled(bool en); + +void Wmm300_Init(void); +void wmm300_measure_hr_start(void); +void wmm300_measure_bo_start(void); +void WMM300_restart(void); +void wmm300_measure_stop(void); +void WMM300_close(void); +static void wmm300_hr_bp_bo_value_update(uint16_t hr, uint16_t bp_high, uint16_t bp_low, uint16_t bo); +uint16_t get_wmm300_hr_value(void); +uint16_t get_wmm300_b0_value(void); +void wmm300_hr_bp_bo_value_get(uint16_t *hr, uint16_t *bp_high, uint16_t *bp_low, uint16_t *bo); + +void wmm300_hr_bp_bo_value_clear(void); +unsigned char wmm300_result_get_wear_status(void); +#endif /* _WHALE_ALGO_H */ diff --git a/2.sdk/sdk/gui/lv_drivers/indev/WMM300/whale_sport.h b/2.sdk/sdk/gui/lv_drivers/indev/WMM300/whale_sport.h new file mode 100644 index 00000000..386c7e6b --- /dev/null +++ b/2.sdk/sdk/gui/lv_drivers/indev/WMM300/whale_sport.h @@ -0,0 +1,65 @@ +#ifndef _WHALE_ALGO_SPORT_H +#define _WHALE_ALGO_SPORT_H + +#include "whale_algo.h" + +typedef enum { + WHALE_SPORT_TYPE_RUN = 1, // 跑步 + WHALE_SPORT_TYPE_WALK, // 健走 + WHALE_SPORT_TYPE_SKIP_ROPE, // 跳绳 + WHALE_SPORT_TYPE_INDOOR_FITNESS, // 室内健身 +} WHALE_SPORT_TYPE_T; + +// 跑步、健走的输出结果 +typedef struct { + uint16_t colorie; // 卡路里 (单位: 千卡) + uint16_t distance; // 距离 (单位: ç±³) + uint16_t avg_cadence; // 步频 (单位: æ­¥/分钟) + uint16_t avg_stride; // 步幅 (单位: 厘米) + uint16_t avg_pace; // 配速 (单位: 秒/公里) +} whale_sport_result_normal_t; + +// 跳绳的输出结果 +typedef struct { + uint16_t count; // 跳绳计数 + uint16_t cnt_per_min; // 每分钟个数 + uint16_t colorie; // 消耗的卡路里 (千卡) +} whale_sport_result_skip_rope_t; + +typedef enum { + FITNESS_TYPE_NORMAL = 0, // 非健身 + FITNESS_TYPE_BENCH_PRESS, // 卧推 + FITNESS_TYPE_SQUAT, // 深蹲 + FITNESS_TYPE_DEADLIFT, // 硬拉 + FITNESS_TYPE_SIT_UPS, // 仰卧起坐 + FITNESS_TYPE_CRUNCH, // 卷腹 + FITNESS_TYPE_DUMBBELLS_SIDE_LIFT, // 侧平举 + FITNESS_TYPE_DUMBBELLS_FORWARD_FLAT_LIFT, // 前平举 + FITNESS_TYPE_DUMBBELLS_PUSH_UP, // 推举 + FITNESS_TYPE_DUMBBELLS_CURLS_LIFT, // 弯举 + FITNESS_TYPE_OPEN_CLOSE_JUMP, // 开合跳 + FITNESS_TYPE_HIGH_PULL_DOWN, // 高位下拉 +} fitness_type_t; + +// 室内健身的输出结果 +typedef struct { + fitness_type_t type; // 健身类型 + uint32_t count; // 计数 (例如:深蹲次数) + uint16_t colorie; // 消耗的卡路里 (千卡) +} whale_sport_result_fitness_t; + +#pragma anon_unions +typedef struct { + union { + whale_sport_result_normal_t normal_result; // 跑步、健走的输出结果 + whale_sport_result_skip_rope_t skip_rope_result; // 跳绳的输出结果 + whale_sport_result_fitness_t fitness_result; // 室内健身的输出结果 + }; +} whale_sport_result_t; + +WHALE_ALGO_ERROR_T whale_sport_enable(WHALE_SPORT_TYPE_T algo_type); +void whale_sport_disable(WHALE_SPORT_TYPE_T algo_type); +WHALE_ALGO_ERROR_T whale_sport_get_result(WHALE_SPORT_TYPE_T algo_type, whale_sport_result_t *result); +void whale_sport_set_info(person_info_t *info); + +#endif /* _WHALE_ALGO_SPORT_H */