mcu_ab568x/app/projects/AB5681F_240_32M/functions/func_heartrate.c
2025-05-30 18:03:10 +08:00

1060 lines
38 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 "include.h"
#include "func.h"
#include "app_variable.h"
#if TRACE_EN
#define TRACE(...) printf(__VA_ARGS__)
#else
#define TRACE(...)
#endif
#ifdef HEARTRATE_STYLE_V2
#define FUNC_HR_SIMULATE_DATA_EN 0
//组件ID;
enum {
COMPO_ID_NUM_HEARTRATE_MAX = 1,
COMPO_ID_NUM_HEARTRATE_CUR,
COMPO_ID_NUM_HEARTRATE_MIN,
COMPO_ID_TEXT_HEARTRATE_TIME,
COMPO_ID_PIC_BT_LEF,
COMPO_ID_PIC_BT_CEN,
COMPO_ID_PIC_BT_RIG,
COMPO_ID_CHART,
};
enum
{
CHART_ANIM_STA_IDLE,
CHART_ANIM_STA_START,
CHART_ANIM_STA_END,
};
//心率检测状态
enum {
HR_STA_IDLE, //空闲
HR_STA_WORKING, //检测中
HR_STA_UNWEAR, //未佩戴
};
#define HEARTRATE_TEXT_ITEM_CNT 2
typedef struct f_heartrate_t_ {
uint8_t cur_sta;
page_tp_move_t *ptm;
u32 tick;
u32 anic_tick;
s16 lef_x;
s16 cen_x;
s16 rig_x;
u8 sec;
} f_heartrate_t;
#if FUNC_HR_SIMULATE_DATA_EN
static const uint16_t total_hr_value[] = {10,20,30,40,50,60,70};
#endif
//创建心率窗体,创建窗体中不要使用功能结构体 func_cb.f_cb
compo_form_t *func_heartrate_form_create(void)
{
//新建窗体
u8 idx = 0;
component_t *compo;
compo_form_t *frm = compo_form_create(true);
//设置标题栏
compo_form_set_mode(frm, COMPO_FORM_MODE_SHOW_TITLE | COMPO_FORM_MODE_SHOW_TIME);
compo_form_set_title(frm, i18n[STR_HEART_RATE]);
compo_form_set_title_color(frm, make_color(255, 0, 0));
//设置内容
compo_form_add_image(frm, UI_BUF_HEART_RATE_HR_BIN, 45, 77);
// compo_form_add_image(frm, UI_BUF_HEART_RATE_HR_BG_BIN, GUI_SCREEN_CENTER_X, 133+46);
//7条横着的线
for (u8 i = 0; i < 8; i++)
{
compo_shape_t *shape_gray = compo_shape_create(frm, COMPO_SHAPE_TYPE_RECTANGLE);
compo_shape_set_color(shape_gray, make_color(43, 43, 43));
compo_shape_set_location(shape_gray, GUI_SCREEN_CENTER_X, 133 + i*13, GUI_SCREEN_WIDTH, 1);
}
//18条竖直线
for (u8 i = 0; i < 18; i++)
{
compo_shape_t *shape_gray_h = compo_shape_create(frm, COMPO_SHAPE_TYPE_RECTANGLE);
compo_shape_set_color(shape_gray_h, make_color(43, 43, 43));
compo_shape_set_location(shape_gray_h, 10+13*i, 179, 1, 92);
}
compo_form_add_image(frm, UI_BUF_HEART_RATE_UP_BIN, 23 + 8, 259+ 8);
compo_form_add_image(frm, UI_BUF_HEART_RATE_DOWN_BIN, 152 + 8, 259+ 8);
//创建文本
compo_textbox_t *txt_title = compo_textbox_create(frm, 6);
compo_textbox_set_align_center(txt_title, false);
#if defined(__LANGUAGE_SM_CHINESE__)
if(tjd_Get_Language_Current_Index() == LANGUAGE_TYPE_Chinese)
{
compo_textbox_set_pos(txt_title, 154, 72);
compo_textbox_set(txt_title, "次/分");
}
else
#endif
{
compo_textbox_set_pos(txt_title, 152, 72);
compo_textbox_set(txt_title, "BPM");
}
//测量心率值
compo_textbox_t *txt_val = compo_textbox_create(frm, 3);
compo_textbox_set_font(txt_val, UI_BUF_0FONT_FONT_NUM_38_BIN);
compo_setid(txt_val, COMPO_ID_NUM_HEARTRATE_CUR);
// compo_textbox_set_align_center(txt_val, false);
compo_textbox_set_pos(txt_val, 110, 77);
compo_textbox_set(txt_val, "---");
//心率值最大值
txt_val = compo_textbox_create(frm, 3);
compo_textbox_set_font(txt_val, UI_BUF_0FONT_FONT_BIN);
compo_setid(txt_val, COMPO_ID_NUM_HEARTRATE_MAX);
compo_textbox_set_align_center(txt_val, false);
compo_textbox_set_pos(txt_val, 45, 257);
compo_textbox_set(txt_val, "---");
//心率值最小值
txt_val = compo_textbox_create(frm, 3);
compo_textbox_set_font(txt_val, UI_BUF_0FONT_FONT_BIN);
compo_setid(txt_val, COMPO_ID_NUM_HEARTRATE_MIN);
compo_textbox_set_align_center(txt_val, false);
compo_textbox_set_pos(txt_val, 174, 257);
compo_textbox_set(txt_val, "---");
//创建动画
// compo_picturebox_t *animation = compo_picturebox_create(frm, UI_BUF_COMMON_HR_DT_BIN);
// compo_animation_set_pos(animation, GUI_SCREEN_CENTER_X, 144+34);
// compo_setid(animation, COMPO_ID_PIC_BT_LEF);
compo_picturebox_t *pic_lef = compo_picturebox_create(frm, UI_BUF_COMMON_HR_DT_1_BIN);
compo_setid(pic_lef, COMPO_ID_PIC_BT_LEF);
compo_picturebox_set_pos(pic_lef, GUI_SCREEN_WIDTH/4, 144+34);
compo_picturebox_set_visible(pic_lef, false); //触摸按下的效果图先设置不可见
compo_picturebox_t *pic_cen = compo_picturebox_create(frm, UI_BUF_COMMON_HR_DT_1_BIN);
compo_setid(pic_cen, COMPO_ID_PIC_BT_CEN);
compo_picturebox_set_pos(pic_cen, GUI_SCREEN_WIDTH/4 * 3, 144+34);
compo_picturebox_set_visible(pic_cen, false); //触摸按下的效果图先设置不可见
compo_picturebox_t *pic_rig = compo_picturebox_create(frm, UI_BUF_COMMON_HR_DT_1_BIN);
compo_setid(pic_rig, COMPO_ID_PIC_BT_RIG);
compo_picturebox_set_pos(pic_rig, GUI_SCREEN_WIDTH/4 * 5, 144+34);
compo_picturebox_set_visible(pic_rig, false); //触摸按下的效果图先设置不可见
// //心率详情
// compo_form_add_image(frm, UI_BUF_HEART_RATE_CHART_BG_BIN, 160, 580);
// //创建图表
// compo = (component_t *)compo_chartbox_create(frm, CHART_TYPE_BAR, 7);
// compo_chartbox_set_location((compo_chartbox_t *)compo, 180, 572, 230, 150);
// compo_chartbox_set_pixel((compo_chartbox_t *)compo, 2);
// compo_setid((compo_chartbox_t *)compo, COMPO_ID_CHART);
return frm;
}
// 刷新心率
static void func_heartrate_refresh(void)
{
compo_textbox_t *txt = NULL;
f_heartrate_t *f_heartrate = (f_heartrate_t *)func_cb.f_cb;
static char hr_buf[4];
memset(hr_buf, 0, sizeof(hr_buf));
if (SysVariable.heartRateModule.openStatus == true) {
reset_sleep_delay_all();
}else{
f_heartrate->cur_sta = HR_STA_IDLE;
}
//实时测量心率
if (SysVariable.heartRateModule.heart > 0) {
txt = (compo_textbox_t *)compo_getobj_byid(COMPO_ID_NUM_HEARTRATE_CUR);
snprintf(hr_buf, sizeof(hr_buf), "%d", SysVariable.heartRateModule.heart);
compo_textbox_set(txt, hr_buf);
}
if (SysVariable.heartRateModule.maxHeart)
{
txt = (compo_textbox_t *)compo_getobj_byid(COMPO_ID_NUM_HEARTRATE_MAX);
snprintf(hr_buf, sizeof(hr_buf), "%d", SysVariable.heartRateModule.maxHeart);
compo_textbox_set(txt, hr_buf);
}
if (SysVariable.heartRateModule.minHeart)
{
txt = (compo_textbox_t *)compo_getobj_byid(COMPO_ID_NUM_HEARTRATE_MIN);
snprintf(hr_buf, sizeof(hr_buf), "%d", SysVariable.heartRateModule.minHeart);
compo_textbox_set(txt, hr_buf);
}
}
//动画滚动
static void func_animation_roll(void)
{
f_heartrate_t *f_heartrate = (f_heartrate_t *)func_cb.f_cb;
compo_picturebox_t *pic_lef = compo_getobj_byid(COMPO_ID_PIC_BT_LEF);
compo_picturebox_t *pic_cen = compo_getobj_byid(COMPO_ID_PIC_BT_CEN);
compo_picturebox_t *pic_rig = compo_getobj_byid(COMPO_ID_PIC_BT_RIG);
#ifdef TJD_GUI_MEASUREMENT_ANIMATION_BEGIN_AT_START
if (SysVariable.heartRateModule.openStatus){
if (tick_check_expire(f_heartrate->anic_tick, 50)){
f_heartrate->anic_tick = tick_get();
f_heartrate->lef_x += 1;
f_heartrate->cen_x += 1;
f_heartrate->rig_x += 1;
if(f_heartrate->lef_x > (GUI_SCREEN_WIDTH / 4 * 5))
f_heartrate->lef_x = -GUI_SCREEN_WIDTH / 4 + 1;
if(f_heartrate->cen_x > (GUI_SCREEN_WIDTH / 4 * 5))
f_heartrate->cen_x = -GUI_SCREEN_WIDTH / 4 + 1;
if(f_heartrate->rig_x > (GUI_SCREEN_WIDTH / 4 * 5))
f_heartrate->rig_x = -GUI_SCREEN_WIDTH / 4 + 1;
}
}
#else
if (SysVariable.heartRateModule.heart > 0){
if ((SysVariable.heartRateModule.timeOutFlag == true) || (SysVariable.heartRateModule.measureEndFlag == true))
{
}
else{
if (tick_check_expire(f_heartrate->anic_tick, 100)){
f_heartrate->anic_tick = tick_get();
f_heartrate->lef_x -= 2;
f_heartrate->cen_x -= 2;
f_heartrate->rig_x -= 2;
if(f_heartrate->lef_x < (-GUI_SCREEN_WIDTH/4))
f_heartrate->lef_x = GUI_SCREEN_WIDTH/4*5;
if(f_heartrate->cen_x < (-GUI_SCREEN_WIDTH/4))
f_heartrate->cen_x = GUI_SCREEN_WIDTH/4*5;
if(f_heartrate->rig_x < (-GUI_SCREEN_WIDTH/4))
f_heartrate->rig_x = GUI_SCREEN_WIDTH/4*5;
}
}
}
#endif
compo_picturebox_set_pos(pic_lef, f_heartrate->lef_x, 144+34);
compo_picturebox_set_visible(pic_lef, true); //触摸按下的效果图先设置不可见
compo_picturebox_set_pos(pic_cen, f_heartrate->cen_x, 144+34);
compo_picturebox_set_visible(pic_cen, true); //触摸按下的效果图先设置不可见
compo_picturebox_set_pos(pic_rig, f_heartrate->rig_x, 144+34);
compo_picturebox_set_visible(pic_rig, true); //触摸按下的效果图先设置不可见
}
//心率功能事件处理
static void func_heartrate_process(void)
{
f_heartrate_t *f_heartrate = (f_heartrate_t *)func_cb.f_cb;
compo_page_move_process(f_heartrate->ptm);
#ifdef TJD_GUI_Remind_slip_wrist_Show
//脱腕检测
if (tick_check_expire(f_heartrate->tick, 100)){
f_heartrate->tick = tick_get();
if(++f_heartrate->sec > 30)
{
if(SysVariable.heartRateModule.is_farway_hand == true){
func_switch_to_assign_screen(FUNC_FARWAY_HAND, false);
func_cb.last = FUNC_HEARTRATE;
// func_switch_to(FUNC_FARWAY_HAND, FUNC_SWITCH_LR_ZOOM_RIGHT); //右滑界面
}
}
}
#endif
func_heartrate_refresh();
func_animation_roll();
func_process();
}
//心率功能消息处理
static void func_heartrate_message(size_msg_t msg)
{
f_heartrate_t *f_heartrate = (f_heartrate_t *)func_cb.f_cb;
switch (msg) {
case MSG_CTP_TOUCH:
compo_page_move_touch_handler(f_heartrate->ptm);
break;
case MSG_CTP_CLICK:
case MSG_CTP_SHORT_UP:
case MSG_CTP_SHORT_DOWN:
case MSG_CTP_LONG:
break;
case MSG_QDEC_BACKWARD:
if (func_cb.flag_sort) { //快捷应用状态下不滚动页面
func_message(msg);
} else {
// compo_page_move_set_by_pages(f_heartrate->ptm, -1);
}
break;
case MSG_QDEC_FORWARD:
if (func_cb.flag_sort) {
func_message(msg);
} else {
// compo_page_move_set_by_pages(f_heartrate->ptm, 1);
}
break;
default:
func_message(msg);
break;
}
}
//进入心率功能
static void func_heartrate_enter(void)
{
func_cb.f_cb = func_zalloc(sizeof(f_heartrate_t));
func_cb.frm_main = func_heartrate_form_create();
f_heartrate_t *f_heartrate = (f_heartrate_t *)func_cb.f_cb;
f_heartrate->ptm = (page_tp_move_t *)func_zalloc(sizeof(page_tp_move_t));
f_heartrate->lef_x = -GUI_SCREEN_WIDTH / 4 * 5 ;
f_heartrate->cen_x = -GUI_SCREEN_WIDTH / 4 * 3 ;
f_heartrate->rig_x = -GUI_SCREEN_WIDTH / 4;
bsp_sensor_hr_start(MeasureMode_Heart);
f_heartrate->cur_sta = HR_STA_WORKING;
}
//退出心率功能
static void func_heartrate_exit(void)
{
f_heartrate_t *f_heartrate = (f_heartrate_t *)func_cb.f_cb;
if (f_heartrate->ptm) {
func_free(f_heartrate->ptm);
}
if (HR_STA_IDLE != f_heartrate->cur_sta) {
bsp_sensor_hr_stop();
}
func_cb.last = FUNC_HEARTRATE;
}
//心率功能
void func_heartrate(void)
{
printf("%s\n", __func__);
func_heartrate_enter();
while (func_cb.sta == FUNC_HEARTRATE) {
func_heartrate_process();
func_heartrate_message(msg_dequeue());
}
func_heartrate_exit();
}
#else
#define FUNC_HR_SIMULATE_DATA_EN 0
#define HR_ANIM_BG_X (GUI_SCREEN_CENTER_X)
#define HR_ANIM_BG_Y (GUI_SCREEN_CENTER_Y - 10)
#define HR_ANIM_NUM_MAX (18)
#define HR_MEASURING_TIME (60)
#define HR_ANIM_TICK_SPEED_LOW (90)
#define HR_ANIM_TICK_SPEED_NORMAL (75)
#define HR_ANIM_TICK_SPEED_FAST (60)
#define HR_LOADING_BG_X (GUI_SCREEN_CENTER_X)
#define HR_LOADING_BG_Y (GUI_SCREEN_CENTER_Y - 25)
#define HR_LOADING_NUM_MAX (13)
#define HR_LOADING_TICK_SPEED (160)
#define HR_CURR_POS_X (19)
#define HR_CURR_POS_Y (207)
#define HR_CURR_UNIT_POS_X (HR_CURR_POS_X + 5)
#define HR_CURR_UNIT_POS_Y (232)
#define HR_RANGE_POS_X (10)
#define HR_RANGE_POS_Y (500)
#define HR_RANGE_UNIT_POS_X (HR_RANGE_POS_X + 2)
#define HR_RANGE_UNIT_POS_Y (525)
#define HR_CHART_POS_X (GUI_SCREEN_CENTER_X) // 图表X坐标
#define HR_CHART_POS_Y (400) // 图表Y坐标
#define HR_CHART_BAR_POS_Y (340) // 图表柱子Y坐标
#define HR_CHART_BAR_RADIUS (2) // 图表打点柱子圆角
#define HR_CHART_BAR_WIDTH (4) // 图表柱子宽度
#define HR_CHART_BAR_HEIGHT (92) // 图表柱子高度
#define HR_CHART_BAR_INIT_HEIGHT (115) // 图表默认高度数值
#define HR_CHART_BAR_COLUMN_MAX (24) // 图表打点数据每小时一根
//组件ID;
enum
{
COMPO_ID_PIC_BG = 1,
COMPO_ID_PIC_BG1,
COMPO_ID_PIC_BIG,
COMPO_ID_PIC_BIG1,
COMPO_ID_PIC_BIG2,
COMPO_ID_TITLE_TIME,
COMPO_ID_NUM_HEARTRATE_CUR,
COMPO_ID_NUM_HEARTRATE_CUR_UNIT,
COMPO_ID_NUM_HEARTRATE_LAST,
COMPO_ID_TEXT_HEARTRATE_CUR,
COMPO_ID_NUM_HEARTRATE_HISTORY,
COMPO_ID_NUM_HEARTRATE_HISTORY_UNIT,
COMPO_ID_NUM_HEARTRATE_HISTORY_MAX,
COMPO_ID_NUM_HEARTRATE_HISTORY_MIN,
/* 图表下方不允许放置ID */
COMPO_ID_CHART
};
typedef enum
{
HR_STA_IDLE = 0, // 空闲
HR_STA_WORKING, // 检测中
HR_STA_NOT_OUTPUT_VALUE, // 持续出值中
} heartrate_status_e;
typedef struct f_heartrate_t_ {
page_tp_move_t *ptm;
heartrate_status_e run_status;
u8 hr_history_max;
u8 hr_history_min;
u8 anim_index;
u8 anim_index1;
u8 anim_index2;
u32 anim_tick;
u8 loading_index;
u32 loading_tick;
u8 measuring_sec;
u32 measuring_tick;
u8 sec;
u32 tick;
u32 refresh_tick;
bool one_flag;
bool two_flag;
bool heart_flag;
} f_heartrate_t;
#if FUNC_HR_SIMULATE_DATA_EN
static const uint8_t record_max[24] = {88, 111, 98, 78, 60, 125, 126, 111, 111, 144, 109, 89, 98, 198, 78, 98, 135, 88, 111, 78, 89, 69, 99, 80};
static const uint8_t record_min[24] = {40, 72, 58, 62, 46, 80, 50, 80, 40, 80, 84, 78, 89, 68, 56, 51, 76, 48, 41, 66, 51, 60, 66, 60};
#endif
static uint8_t hr_max_record_data_get(uint8_t hour)
{
#if FUNC_HR_SIMULATE_DATA_EN
return record_max[hour] > 170 ? 170 : record_max[hour];
#else
return SysVariable.heartRateModule.recordMaxHeart[hour] > 170 ? 170 : SysVariable.heartRateModule.recordMaxHeart[hour];
#endif
}
static uint8_t hr_min_record_data_get(uint8_t hour)
{
#if FUNC_HR_SIMULATE_DATA_EN
return record_min[hour];
#else
return SysVariable.heartRateModule.recordMinHeart[hour];
#endif
}
static u32 func_hr_last_measure_time_get(void)
{
int time_min = (SysVariable.Rtc.hour * 3600 + SysVariable.Rtc.min * 60) - SysVariable.heartRateModule.heartMeasureTime;
/* 数据超出保护 */
if (time_min < 60)
time_min = 60;
return time_min / 60;
}
static void func_heartrate_data_init(void)
{
f_heartrate_t *f_heartrate = (f_heartrate_t *)func_cb.f_cb;
/* 初始化历史记录最小最大值 */
for (u8 i = 0; i < 24; i++)
{
if (hr_max_record_data_get(i) > f_heartrate->hr_history_max)
f_heartrate->hr_history_max = hr_max_record_data_get(i);
if ((hr_min_record_data_get(i) < f_heartrate->hr_history_min || f_heartrate->hr_history_min == 0) && hr_max_record_data_get(i))
f_heartrate->hr_history_min = hr_min_record_data_get(i);
}
}
static void func_heartrate_last_data_text_get(char *text_buf)
{
char last_buf[TEXTBOX_TEXT_BUF_LEN] = {0};
if (text_buf == NULL)
return;
if (SysVariable.heartRateModule.lastHeart && SysVariable.heartRateModule.maxHeart)
{
if (func_hr_last_measure_time_get() >= 60)
sprintf(last_buf, i18n[STR_HOURS_AGO], func_hr_last_measure_time_get() / 60);
else
sprintf(last_buf, i18n[STR_MINUTE_AGO], func_hr_last_measure_time_get());
#if defined(__LANGUAGE_SM_CHINESE__)
if (tjd_Get_Language_Current_Index() == LANGUAGE_TYPE_Chinese)
sprintf(text_buf, "%d次/分 %s", SysVariable.heartRateModule.lastHeart, last_buf);
else
#endif
sprintf(text_buf, "%dBPM %s", SysVariable.heartRateModule.lastHeart, last_buf);
}
else
{
#if defined(__LANGUAGE_SM_CHINESE__)
if (tjd_Get_Language_Current_Index() == LANGUAGE_TYPE_Chinese)
sprintf(text_buf, "---次/分");
else
#endif
sprintf(text_buf, "---BPM");
}
}
// 创建心率窗体,创建窗体中不要使用功能结构体 func_cb.f_cb
compo_form_t *func_heartrate_form_create(void)
{
char text_buf[TEXTBOX_TEXT_BUF_LEN] = {0};
/* 新建窗体 */
compo_form_t *frm = compo_form_create(true);
compo_picturebox_t *pic1;
pic1 = compo_picturebox_create_coordinate(frm,UI_BUF_HEART_RATE_HR_BIG_BIN,HR_LOADING_BG_X, HR_LOADING_BG_Y,COMPO_ID_PIC_BIG,true);
compo_picturebox_set_size(pic1,88,85);
compo_picturebox_set_visible(pic1,false);
pic1 = compo_picturebox_create_coordinate(frm,UI_BUF_HEART_RATE_HR_BIG_BIN,HR_LOADING_BG_X, HR_LOADING_BG_Y,COMPO_ID_PIC_BIG1,true);
compo_picturebox_set_size(pic1,88,85);
compo_picturebox_set_visible(pic1,false);
pic1 = compo_picturebox_create_coordinate(frm,UI_BUF_HEART_RATE_HR_BIG_BIN,HR_LOADING_BG_X, HR_LOADING_BG_Y,COMPO_ID_PIC_BIG2,true);
compo_picturebox_set_size(pic1,88,85);
compo_picturebox_set_visible(pic1,false);
pic1 = compo_picturebox_create_coordinate(frm,UI_BUF_HEART_RATE_HR_SMALL_BIN,HR_LOADING_BG_X, HR_LOADING_BG_Y,COMPO_ID_PIC_BG1,true);
compo_picturebox_set_visible(pic1,false);
/*=========================== 测量页面 ===========================*/
compo_picturebox_t *pic = compo_picturebox_create(frm, UI_BUF_HEART_RATE_HR_LOADING_BIN);
compo_picturebox_set_pos(pic, HR_LOADING_BG_X, HR_LOADING_BG_Y);
compo_picturebox_cut(pic, 0, HR_LOADING_NUM_MAX);
compo_setid(pic, COMPO_ID_PIC_BG);
/* 测量中 */
compo_textbox_t *txt_title = compo_textbox_create(frm, 20);
compo_textbox_set_forecolor(txt_title, make_color(212, 212, 212));
compo_textbox_set_align_center(txt_title, false);
compo_textbox_set_pos(txt_title, 19, 175);
sprintf(text_buf, "%s...", i18n[STR_MEASURING]);
compo_textbox_set(txt_title, text_buf);
compo_setid(txt_title, COMPO_ID_TEXT_HEARTRATE_CUR);
/* 当前测量心率值 */
compo_textbox_t *txt_val = compo_textbox_create(frm, 3);
compo_setid(txt_val, COMPO_ID_NUM_HEARTRATE_CUR);
compo_textbox_set_pos(txt_val, HR_CURR_POS_X, HR_CURR_POS_Y);
compo_textbox_set_font(txt_val, UI_BUF_0FONT_FONT_NUM_38_BIN);
compo_textbox_set_autosize(txt_val, true);
compo_textbox_set_align_center(txt_val, false);
compo_textbox_set(txt_val, "---");
/* 当前测量心率值单位 */
compo_textbox_t *txt_unit = compo_textbox_create(frm, 6);
compo_setid(txt_unit, COMPO_ID_NUM_HEARTRATE_CUR_UNIT);
compo_textbox_set_pos(txt_unit, HR_CURR_UNIT_POS_X + widget_text_get_area(txt_val->txt).wid, HR_CURR_UNIT_POS_Y);
compo_textbox_set_forecolor(txt_unit, make_color(142, 142, 142));
compo_textbox_set_align_center(txt_unit, false);
#if defined(__LANGUAGE_SM_CHINESE__)
if (tjd_Get_Language_Current_Index() == LANGUAGE_TYPE_Chinese)
compo_textbox_set(txt_unit, "次/分");
else
#endif
compo_textbox_set(txt_unit, "BPM");
/* 最后测量心率值单位 */
compo_textbox_t *txt_last = compo_textbox_create(frm, 100);
compo_setid(txt_last, COMPO_ID_NUM_HEARTRATE_LAST);
compo_textbox_set_align_center(txt_last, false);
compo_textbox_set_location(txt_last, 22, 264, 188, 28);
compo_textbox_set_autoroll_mode(txt_last, TEXT_AUTOROLL_MODE_SROLL_CIRC);
compo_textbox_set_forecolor(txt_last, make_color(169, 169, 169));
func_heartrate_last_data_text_get(text_buf);
compo_textbox_set(txt_last, text_buf);
/*=========================== 详细信息页面 ===========================*/
compo_form_add_image(frm, UI_BUF_HEART_RATE_HR_CHART_BG_BIN, HR_CHART_POS_X, HR_CHART_POS_Y);
/* 创建图表 */
for (u8 i = 0; i < HR_CHART_BAR_COLUMN_MAX; i++)
{
compo_shape_t *vol_bar = compo_radius_shape_create(frm, COMPO_SHAPE_TYPE_ROUNDED_RECTANGLE, HR_CHART_BAR_RADIUS);
compo_setid(vol_bar, COMPO_ID_CHART + i);
compo_shape_set_align_center(vol_bar, false);
compo_shape_set_color(vol_bar, make_color(255, 31, 14));
}
compo_textbox_t *txt_history_max = compo_textbox_create(frm, 6);
compo_setid(txt_history_max, COMPO_ID_NUM_HEARTRATE_HISTORY_MAX);
compo_textbox_set_font(txt_history_max, UI_BUF_0FONT_FONT_20_BIN);
compo_textbox_set_forecolor(txt_history_max, make_color(255, 31, 14));
compo_textbox_set_right_align(txt_history_max, true);
compo_textbox_set_align_center(txt_history_max, false);
compo_textbox_set_location(txt_history_max, 195, 337, 26, 18);
compo_textbox_t *txt_history_min = compo_textbox_create(frm, 6);
compo_setid(txt_history_min, COMPO_ID_NUM_HEARTRATE_HISTORY_MIN);
compo_textbox_set_font(txt_history_min, UI_BUF_0FONT_FONT_20_BIN);
compo_textbox_set_forecolor(txt_history_min, make_color(255, 31, 14));
compo_textbox_set_right_align(txt_history_min, true);
compo_textbox_set_align_center(txt_history_min, false);
compo_textbox_set_location(txt_history_min, 195, 430, 26, 18);
/* 范围 */
txt_title = compo_textbox_create(frm, 6);
compo_textbox_set_forecolor(txt_title, make_color(212, 212, 212));
compo_textbox_set_align_center(txt_title, false);
compo_textbox_set_pos(txt_title, 10, 472);
compo_textbox_set(txt_title, i18n[STR_RANGE]);
/* 当前测量心率值 */
txt_val = compo_textbox_create(frm, 8);
compo_setid(txt_val, COMPO_ID_NUM_HEARTRATE_HISTORY);
compo_textbox_set_pos(txt_val, HR_RANGE_POS_X, HR_RANGE_POS_Y);
compo_textbox_set_font(txt_val, UI_BUF_0FONT_FONT_NUM_38_BIN);
compo_textbox_set_autosize(txt_val, true);
compo_textbox_set_align_center(txt_val, false);
compo_textbox_set(txt_val, "00-000");
/* 当前测量心率值单位 */
txt_unit = compo_textbox_create(frm, 6);
compo_setid(txt_unit, COMPO_ID_NUM_HEARTRATE_HISTORY_UNIT);
compo_textbox_set_align_center(txt_unit, false);
compo_textbox_set_pos(txt_unit, HR_RANGE_UNIT_POS_X + widget_text_get_area(txt_val->txt).wid, HR_RANGE_UNIT_POS_Y);
compo_textbox_set_forecolor(txt_unit, make_color(142, 142, 142));
#if defined(__LANGUAGE_SM_CHINESE__)
if (tjd_Get_Language_Current_Index() == LANGUAGE_TYPE_Chinese)
compo_textbox_set(txt_unit, "次/分");
else
#endif
compo_textbox_set(txt_unit, "BPM");
txt_title = compo_textbox_create(frm, 6);
compo_textbox_set_forecolor(txt_title, make_color(152, 152, 152));
compo_textbox_set_align_center(txt_title, false);
compo_textbox_set_pos(txt_title, 16, 555);
compo_textbox_set(txt_title, i18n[STR_TODAY]);
/* 创建标题栏信息 */
memset(text_buf, 0, sizeof(text_buf));
if (SysVariable.deviceInfo.timeType == TIME_TYPE_12_HOUR)
sprintf(text_buf, "%02d:%02d%s", get_autoformat_hour(SysVariable.Rtc.hour), SysVariable.Rtc.min, SysVariable.Rtc.hour >= 12 ? "PM" : "AM");
else
sprintf(text_buf, "%02d:%02d", SysVariable.Rtc.hour, SysVariable.Rtc.min);
compo_textbox_t *txt_time = compo_textbox_create_for_page(frm, frm->page, 8);
compo_setid(txt_time, COMPO_ID_TITLE_TIME);
compo_textbox_set_align_center(txt_time, false);
compo_textbox_set_location(txt_time, 120, 9, 90, 30);
compo_textbox_set_right_align(txt_time, true);
compo_textbox_set(txt_time, text_buf);
return frm;
}
static void func_heartrate_anim_refresh(void)
{
f_heartrate_t *f_heartrate = (f_heartrate_t *)func_cb.f_cb;
compo_picturebox_t *compo_pic = compo_getobj_byid(COMPO_ID_PIC_BG);
compo_picturebox_t *compo_pic1 = compo_getobj_byid(COMPO_ID_PIC_BG1);
compo_picturebox_t *compo_pic_big = compo_getobj_byid(COMPO_ID_PIC_BIG);
compo_picturebox_t *compo_pic_big1 = compo_getobj_byid(COMPO_ID_PIC_BIG1);
compo_picturebox_t *compo_pic_big2 = compo_getobj_byid(COMPO_ID_PIC_BIG2);
/* 测量出值前加载动画 */
if (f_heartrate->run_status == HR_STA_WORKING)
{
if (compo_pic != NULL)
{
if (tick_check_expire(f_heartrate->loading_tick, HR_LOADING_TICK_SPEED))
{
f_heartrate->loading_tick = tick_get();
f_heartrate->loading_index = (f_heartrate->loading_index + 1) % HR_LOADING_NUM_MAX;
compo_picturebox_cut(compo_pic, f_heartrate->loading_index, HR_LOADING_NUM_MAX);
}
}
}
/* 测量心跳动画 */
if (f_heartrate->run_status == HR_STA_NOT_OUTPUT_VALUE)
{
compo_picturebox_set_visible(compo_pic,false);
u8 anim_speed = 200;
/* 动画速度取决与心率区间 */
if (SysVariable.heartRateModule.heart <= 70)
anim_speed = HR_ANIM_TICK_SPEED_LOW;
else if (SysVariable.heartRateModule.heart <= 120)
anim_speed = HR_ANIM_TICK_SPEED_NORMAL;
else if (SysVariable.heartRateModule.heart > 120)
anim_speed = HR_ANIM_TICK_SPEED_FAST;
if (tick_check_expire(f_heartrate->anim_tick, anim_speed))
{
f_heartrate->anim_tick = tick_get();
/* 除首次从第一张播放起,第二遍从跳动开始循环播放 */
if(f_heartrate->anim_index <= HR_ANIM_NUM_MAX )
{
f_heartrate->anim_index++;
}
else
f_heartrate->anim_index = 0;
if (f_heartrate->anim_index == 6)
{
compo_picturebox_set_visible(compo_pic_big1, true);
f_heartrate->one_flag=true;
}
if (f_heartrate->anim_index == 12)
{
compo_picturebox_set_visible(compo_pic_big2, true);
f_heartrate->two_flag=true;
}
if(f_heartrate->anim_index1 <= HR_ANIM_NUM_MAX &&f_heartrate->one_flag==true )
{
f_heartrate->anim_index1++;
}
else
f_heartrate->anim_index1 = 0;
if (f_heartrate->anim_index2 <= HR_ANIM_NUM_MAX &&f_heartrate->two_flag==true)
{
f_heartrate->anim_index2++;
}
else
{
f_heartrate->anim_index2=0;
}
if(f_heartrate->anim_index%6==0)
{
f_heartrate->heart_flag = !f_heartrate->heart_flag;
}
if (f_heartrate->heart_flag == true)
{
compo_picturebox_set_size(compo_pic1, 148, 142);
}
else
{
compo_picturebox_set_size(compo_pic1, 136, 132);
}
compo_picturebox_set_alpha(compo_pic_big, 255 - (f_heartrate->anim_index * 6));
compo_picturebox_set_size(compo_pic_big, 88 + (f_heartrate->anim_index * 6), 85 + (f_heartrate->anim_index * 6));
compo_picturebox_set_alpha(compo_pic_big1, 255 - (f_heartrate->anim_index1 * 6));
compo_picturebox_set_size(compo_pic_big1, 88 + (f_heartrate->anim_index1 * 6), 85 + (f_heartrate->anim_index1 * 6));
compo_picturebox_set_alpha(compo_pic_big2, 255 - (f_heartrate->anim_index2 * 6));
compo_picturebox_set_size(compo_pic_big2, 88 + (f_heartrate->anim_index2 * 6), 85 + (f_heartrate->anim_index2 * 6));
}
}
}
// 刷新心率
static void func_heartrate_refresh(void)
{
f_heartrate_t *f_heartrate = (f_heartrate_t *)func_cb.f_cb;
char text_buf[TEXTBOX_TEXT_BUF_LEN] = {0};
compo_textbox_t *txt_time = compo_getobj_byid(COMPO_ID_TITLE_TIME);
compo_textbox_t *compo_hr_val = compo_getobj_byid(COMPO_ID_NUM_HEARTRATE_CUR);
compo_textbox_t *compo_hr_unit = compo_getobj_byid(COMPO_ID_NUM_HEARTRATE_CUR_UNIT);
compo_textbox_t *compo_hr_txt = compo_getobj_byid(COMPO_ID_TEXT_HEARTRATE_CUR);
compo_textbox_t *compo_hr_last = compo_getobj_byid(COMPO_ID_NUM_HEARTRATE_LAST);
compo_textbox_t *compo_history_txt = compo_getobj_byid(COMPO_ID_NUM_HEARTRATE_HISTORY);
compo_textbox_t *compo_history_unit = compo_getobj_byid(COMPO_ID_NUM_HEARTRATE_HISTORY_UNIT);
compo_textbox_t *compo_history_max = compo_getobj_byid(COMPO_ID_NUM_HEARTRATE_HISTORY_MAX);
compo_textbox_t *compo_history_min = compo_getobj_byid(COMPO_ID_NUM_HEARTRATE_HISTORY_MIN);
compo_picturebox_t *compo_pic = compo_getobj_byid(COMPO_ID_PIC_BG);
compo_picturebox_t *compo_pic1 = compo_getobj_byid(COMPO_ID_PIC_BG1);
compo_picturebox_t *compo_pic_big = compo_getobj_byid(COMPO_ID_PIC_BIG);
compo_picturebox_t *compo_pic_big1 = compo_getobj_byid(COMPO_ID_PIC_BIG1);
compo_picturebox_t *compo_pic_big2 = compo_getobj_byid(COMPO_ID_PIC_BIG2);
if (SysVariable.heartRateModule.openStatus == true || f_heartrate->run_status != HR_STA_IDLE) {
reset_sleep_delay_all();
}
/* 测量过程tick检测 */
if (tick_check_expire(f_heartrate->measuring_tick, 1000) &&
(f_heartrate->run_status == HR_STA_WORKING || f_heartrate->run_status == HR_STA_NOT_OUTPUT_VALUE))
{
f_heartrate->measuring_tick = tick_get();
if (f_heartrate->measuring_sec > 0)
f_heartrate->measuring_sec--;
if ((SysVariable.heartRateModule.timeOutFlag == true) || (SysVariable.heartRateModule.measureEndFlag == true)) {
/* 测量结束 */
bsp_sensor_hr_stop();
/* 更新结束数据显示 */
memset(text_buf, 0, sizeof(text_buf));
func_heartrate_last_data_text_get(text_buf);
compo_textbox_set(compo_hr_last, text_buf);
compo_textbox_set(compo_hr_txt, i18n[STR_CURRENT]);
//compo_picturebox_cut(compo_pic, 0, HR_ANIM_NUM_MAX);
compo_picturebox_set_visible(compo_pic_big1,false);
compo_picturebox_set_visible(compo_pic_big2,false);
compo_picturebox_set_visible(compo_pic1,true);
compo_picturebox_set_visible(compo_pic_big,false);
f_heartrate->run_status = HR_STA_IDLE;
sys_cb.motor_flag = 1;
set_func_motor(80, 5, 0, 1);
} else if (f_heartrate->measuring_sec == HR_MEASURING_TIME - 15) {
/* 测量出值阶段 */
f_heartrate->anim_index = 0;
f_heartrate->anim_tick = tick_get();
f_heartrate->run_status = HR_STA_NOT_OUTPUT_VALUE;
compo_picturebox_set_visible(compo_pic,false);
compo_picturebox_set_visible(compo_pic1,true);
compo_picturebox_set_visible(compo_pic_big,true);
}
}
/* 动画刷新 */
func_heartrate_anim_refresh();
/* 更新数据 */
if (tick_check_expire(f_heartrate->refresh_tick, 100))
{
func_heartrate_data_init();
// 更新图表数据
u16 chart_offser_x[HR_CHART_BAR_COLUMN_MAX / 6] = { 0, 3, 7, 10};
u16 temp_max = f_heartrate->hr_history_max < HR_CHART_BAR_INIT_HEIGHT ? HR_CHART_BAR_INIT_HEIGHT : f_heartrate->hr_history_max;
u16 bar_hei_uint = (HR_CHART_BAR_HEIGHT * 10) / (temp_max - f_heartrate->hr_history_min);
if (f_heartrate->hr_history_max)
{
/* 由于平台不支持浮点运算故将单位系数放大10倍后续计算后恢复 */
for (u8 i = 0; i < HR_CHART_BAR_COLUMN_MAX; i++)
{
if (hr_max_record_data_get(i) && hr_min_record_data_get(i))
{
u16 chart_y = ((hr_min_record_data_get(i) - f_heartrate->hr_history_min) * bar_hei_uint) / 10;
u16 height = ((hr_max_record_data_get(i) - hr_min_record_data_get(i)) * bar_hei_uint) / 10;
if (height == 0)
height = 1;
compo_shape_t *hr_bar = compo_getobj_byid(COMPO_ID_CHART + i);
compo_shape_set_location(hr_bar, (21 + chart_offser_x[i / 6]) + (i * 8), (HR_CHART_BAR_POS_Y + (HR_CHART_BAR_HEIGHT - height)) - chart_y, HR_CHART_BAR_WIDTH, height);
}
}
}
memset(text_buf, 0, sizeof(text_buf));
sprintf(text_buf, "%d", temp_max);
compo_textbox_set(compo_history_max, text_buf);
memset(text_buf, 0, sizeof(text_buf));
sprintf(text_buf, "%d", f_heartrate->hr_history_min);
compo_textbox_set(compo_history_min, text_buf);
// 更新历史范围值
memset(text_buf, 0, sizeof(text_buf));
sprintf(text_buf, "%d-%d", f_heartrate->hr_history_min, f_heartrate->hr_history_max);
compo_textbox_set(compo_history_txt, text_buf);
compo_textbox_set_pos(compo_history_unit, HR_RANGE_UNIT_POS_X + widget_text_get_area(compo_history_txt->txt).wid, HR_RANGE_UNIT_POS_Y);
// 更新测量数据
if (SysVariable.heartRateModule.heart > 0 && f_heartrate->run_status != HR_STA_WORKING)
{
sprintf(text_buf, "%d", SysVariable.heartRateModule.heart);
compo_textbox_set(compo_hr_val, text_buf);
compo_textbox_set_pos(compo_hr_unit, HR_CURR_UNIT_POS_X + widget_text_get_area(compo_hr_val->txt).wid, HR_CURR_UNIT_POS_Y);
}
}
/* 更新标题时间 */
static u32 tick = 0;
memset(text_buf, 0, sizeof(text_buf));
if (tick_check_expire(tick, 500))
{
if (txt_time)
{
tick = tick_get();
if (SysVariable.deviceInfo.timeType == TIME_TYPE_12_HOUR)
sprintf(text_buf, "%02d:%02d%s", get_autoformat_hour(SysVariable.Rtc.hour), SysVariable.Rtc.min, SysVariable.Rtc.hour >= 12 ? "PM" : "AM");
else
sprintf(text_buf, "%02d:%02d", SysVariable.Rtc.hour, SysVariable.Rtc.min);
compo_textbox_set(txt_time, text_buf);
}
}
}
//心率功能事件处理
static void func_heartrate_process(void)
{
f_heartrate_t *f_heartrate = (f_heartrate_t *)func_cb.f_cb;
compo_page_move_process(f_heartrate->ptm);
#ifdef TJD_GUI_Remind_slip_wrist_Show
//脱腕检测
if (tick_check_expire(f_heartrate->tick, 100)) {
f_heartrate->tick = tick_get();
if(++f_heartrate->sec > 30)
{
if(SysVariable.heartRateModule.is_farway_hand == true){
func_switch_to_assign_screen(FUNC_FARWAY_HAND, false);
func_cb.last = FUNC_HEARTRATE;
}
}
}
#endif
func_heartrate_refresh();
func_process();
}
//心率功能消息处理
static void func_heartrate_message(size_msg_t msg)
{
f_heartrate_t *f_heartrate = (f_heartrate_t *)func_cb.f_cb;
switch (msg) {
case MSG_CTP_TOUCH:
compo_page_move_touch_handler(f_heartrate->ptm);
break;
case MSG_CTP_CLICK:
case MSG_CTP_SHORT_UP:
case MSG_CTP_SHORT_DOWN:
case MSG_CTP_LONG:
break;
case MSG_QDEC_BACKWARD:
if (func_cb.flag_sort) { //快捷应用状态下不滚动页面
func_message(msg);
} else {
compo_page_move_set_by_pages(f_heartrate->ptm, -1);
}
break;
case MSG_QDEC_FORWARD:
if (func_cb.flag_sort) {
func_message(msg);
} else {
compo_page_move_set_by_pages(f_heartrate->ptm, 1);
}
break;
default:
func_message(msg);
break;
}
}
//进入心率功能
static void func_heartrate_enter(void)
{
func_cb.f_cb = func_zalloc(sizeof(f_heartrate_t));
func_cb.frm_main = func_heartrate_form_create();
f_heartrate_t *f_heartrate = (f_heartrate_t *)func_cb.f_cb;
f_heartrate->ptm = (page_tp_move_t *)func_zalloc(sizeof(page_tp_move_t));
page_move_info_t info = {
.title_used = false,
.page_size = GUI_SCREEN_HEIGHT,
.page_count = 2,
.jump_perc = 10,
.quick_jump_perc = 100,
.up_over_perc = 0,
.down_over_perc = 0,
};
compo_page_move_init(f_heartrate->ptm, func_cb.frm_main->page_body, &info);
f_heartrate->run_status = HR_STA_WORKING;
f_heartrate->measuring_sec = HR_MEASURING_TIME;
f_heartrate->heart_flag = false;
f_heartrate->one_flag = false;
f_heartrate->two_flag = false;
func_heartrate_data_init();
bsp_sensor_hr_start(MeasureMode_Heart);
}
//退出心率功能
static void func_heartrate_exit(void)
{
f_heartrate_t *f_heartrate = (f_heartrate_t *)func_cb.f_cb;
if (f_heartrate->ptm) {
func_free(f_heartrate->ptm);
}
bsp_sensor_hr_stop();
}
//心率功能
void func_heartrate(void)
{
printf("%s\n", __func__);
func_heartrate_enter();
while (func_cb.sta == FUNC_HEARTRATE) {
func_heartrate_process();
func_heartrate_message(msg_dequeue());
}
func_heartrate_exit();
}
#endif