wmm300提交
authorp15692025051 <846603105@qq.com>
Tue, 28 Nov 2023 09:08:27 +0000 (17:08 +0800)
committerp15692025051 <846603105@qq.com>
Tue, 28 Nov 2023 09:08:27 +0000 (17:08 +0800)
2.sdk/sdk/gui/lv_drivers/indev/WMM300/alg_example.c [new file with mode: 0644]
2.sdk/sdk/gui/lv_drivers/indev/WMM300/alg_port.c [new file with mode: 0644]
2.sdk/sdk/gui/lv_drivers/indev/WMM300/whale_algo.h [new file with mode: 0644]
2.sdk/sdk/gui/lv_drivers/indev/WMM300/whale_sport.h [new file with mode: 0644]

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 (file)
index 0000000..dedd355
--- /dev/null
@@ -0,0 +1,429 @@
+#include "lv_drv_conf_CUSTOM.h"
+#if USE_WMM300
+#include "whale_algo.h"
+#include <stdio.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <math.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"
+
+/************************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 (file)
index 0000000..590264c
--- /dev/null
@@ -0,0 +1,124 @@
+
+#include "lv_drv_conf_CUSTOM.h"
+#if USE_WMM300
+#include "whale_algo.h"
+
+#include "../../../lvgl/hal/hal.h"
+#include <stdio.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <math.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"
+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 (file)
index 0000000..e1a1191
--- /dev/null
@@ -0,0 +1,213 @@
+
+#ifndef _WHALE_ALGO_H
+#define _WHALE_ALGO_H
+
+#include <stdint.h>
+#include <stdbool.h>
+#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 (file)
index 0000000..386c7e6
--- /dev/null
@@ -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 */