#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