diff --git a/Kconfig b/Kconfig index 2988031d0..fafcfd422 100644 --- a/Kconfig +++ b/Kconfig @@ -371,6 +371,7 @@ menu "LVGL configuration" menu "Others" config LV_USE_PERF_MONITOR bool "Show CPU usage and FPS count." + depends on LV_USE_MONITOR choice prompt "Performance monitor position." @@ -400,6 +401,7 @@ menu "LVGL configuration" config LV_USE_MEM_MONITOR bool "Show the used memory and the memory fragmentation." depends on !LV_MEM_CUSTOM + depends on LV_USE_MONITOR choice prompt "Memory monitor position." @@ -994,6 +996,10 @@ menu "LVGL configuration" bool "Enable API to take snapshot" default y if !LV_CONF_MINIMAL + config LV_USE_MONITOR + bool "Enable Monitor component" + default n + config LV_USE_MONKEY bool "Enable Monkey test" default n diff --git a/lv_conf_template.h b/lv_conf_template.h index fadd96ec5..b5a51658c 100644 --- a/lv_conf_template.h +++ b/lv_conf_template.h @@ -278,14 +278,17 @@ * Others *-----------*/ -/*1: Show CPU usage and FPS count*/ +/*1: Show CPU usage and FPS count + * Requires `LV_USE_MONITOR = 1`*/ #define LV_USE_PERF_MONITOR 0 #if LV_USE_PERF_MONITOR #define LV_USE_PERF_MONITOR_POS LV_ALIGN_BOTTOM_RIGHT + #define LV_USE_PERF_MONITOR_LOG_MDOE 0 #endif /*1: Show the used memory and the memory fragmentation - * Requires `LV_USE_BUILTIN_MALLOC = 1`*/ + * Requires `LV_USE_BUILTIN_MALLOC = 1` + * Requires `LV_USE_MONITOR = 1`*/ #define LV_USE_MEM_MONITOR 0 #if LV_USE_MEM_MONITOR #define LV_USE_MEM_MONITOR_POS LV_ALIGN_BOTTOM_LEFT @@ -692,6 +695,9 @@ /*1: Enable API to take snapshot for object*/ #define LV_USE_SNAPSHOT 0 +/*1: Enable Monitor component*/ +#define LV_USE_MONITOR 1 + /*1: Enable Monkey test*/ #define LV_USE_MONKEY 0 diff --git a/lvgl.h b/lvgl.h index 918b33bfc..b159f913a 100644 --- a/lvgl.h +++ b/lvgl.h @@ -80,6 +80,7 @@ extern "C" { #include "src/others/gridnav/lv_gridnav.h" #include "src/others/fragment/lv_fragment.h" #include "src/others/imgfont/lv_imgfont.h" +#include "src/others/monitor/lv_monitor.h" #include "src/others/msg/lv_msg.h" #include "src/others/ime/lv_ime_pinyin.h" #include "src/others/file_explorer/lv_file_explorer.h" diff --git a/src/core/lv_refr.c b/src/core/lv_refr.c index cb4a7b980..34fe02567 100644 --- a/src/core/lv_refr.c +++ b/src/core/lv_refr.c @@ -18,10 +18,7 @@ #include "../draw/lv_draw.h" #include "../font/lv_font_fmt_txt.h" #include "../others/snapshot/lv_snapshot.h" - -#if LV_USE_PERF_MONITOR || LV_USE_MEM_MONITOR - #include "../widgets/label/lv_label.h" -#endif +#include "../others/monitor/lv_monitor.h" /********************* * DEFINES @@ -30,23 +27,6 @@ /********************** * TYPEDEFS **********************/ -typedef struct { - uint32_t perf_last_time; - uint32_t elaps_sum; - uint32_t frame_cnt; - uint32_t fps_sum_cnt; - uint32_t fps_sum_all; -#if LV_USE_LABEL - lv_obj_t * perf_label; -#endif -} perf_monitor_t; - -typedef struct { - uint32_t mem_last_time; -#if LV_USE_LABEL - lv_obj_t * mem_label; -#endif -} mem_monitor_t; /********************** * STATIC PROTOTYPES @@ -62,27 +42,12 @@ static uint32_t get_max_row(lv_disp_t * disp, lv_coord_t area_w, lv_coord_t area static void draw_buf_flush(lv_disp_t * disp); static void call_flush_cb(lv_disp_t * disp, const lv_area_t * area, lv_color_t * color_p); -#if LV_USE_PERF_MONITOR - static void perf_monitor_init(perf_monitor_t * perf_monitor); -#endif -#if LV_USE_MEM_MONITOR - static void mem_monitor_init(mem_monitor_t * mem_monitor); -#endif - /********************** * STATIC VARIABLES **********************/ -static uint32_t px_num; + static lv_disp_t * disp_refr; /*Display being refreshed*/ -#if LV_USE_PERF_MONITOR - static perf_monitor_t perf_monitor; -#endif - -#if LV_USE_MEM_MONITOR - static mem_monitor_t mem_monitor; -#endif - /********************** * MACROS **********************/ @@ -101,11 +66,8 @@ static lv_disp_t * disp_refr; /*Display being refreshed*/ */ void _lv_refr_init(void) { -#if LV_USE_PERF_MONITOR - perf_monitor_init(&perf_monitor); -#endif -#if LV_USE_MEM_MONITOR - mem_monitor_init(&mem_monitor); +#if LV_USE_MONITOR + _lv_monitor_builtin_init(); #endif } @@ -311,99 +273,8 @@ void _lv_disp_refr_timer(lv_timer_t * tmr) lv_disp_send_event(disp_refr, LV_EVENT_REFR_START, NULL); -#if LV_USE_PERF_MONITOR && LV_USE_LABEL - volatile uint32_t elaps = lv_tick_elaps(disp_refr->last_render_start_time); -#endif disp_refr->last_render_start_time = start; -#if LV_USE_PERF_MONITOR && LV_USE_LABEL - lv_obj_t * perf_label = perf_monitor.perf_label; - if(perf_label == NULL) { - perf_label = lv_label_create(lv_layer_sys()); - lv_obj_set_style_bg_opa(perf_label, LV_OPA_50, 0); - lv_obj_set_style_bg_color(perf_label, lv_color_black(), 0); - lv_obj_set_style_text_color(perf_label, lv_color_white(), 0); - lv_obj_set_style_pad_top(perf_label, 3, 0); - lv_obj_set_style_pad_bottom(perf_label, 3, 0); - lv_obj_set_style_pad_left(perf_label, 3, 0); - lv_obj_set_style_pad_right(perf_label, 3, 0); - lv_obj_set_style_text_align(perf_label, LV_TEXT_ALIGN_RIGHT, 0); - lv_label_set_text(perf_label, "?"); - lv_obj_align(perf_label, LV_USE_PERF_MONITOR_POS, 0, 0); - perf_monitor.perf_label = perf_label; - } - - if(lv_tick_elaps(perf_monitor.perf_last_time) < 300) { - if(px_num > 5000) { - perf_monitor.elaps_sum += elaps; - perf_monitor.frame_cnt ++; - } - } - else { - perf_monitor.perf_last_time = lv_tick_get(); - uint32_t fps_limit; - uint32_t fps; - - if(disp_refr->refr_timer) { - fps_limit = 1000 / disp_refr->refr_timer->period; - } - else { - fps_limit = 1000 / 33; - } - - if(perf_monitor.elaps_sum == 0) { - perf_monitor.elaps_sum = 1; - } - if(perf_monitor.frame_cnt == 0) { - fps = fps_limit; - } - else { - fps = (1000 * perf_monitor.frame_cnt) / perf_monitor.elaps_sum; - } - perf_monitor.elaps_sum = 0; - perf_monitor.frame_cnt = 0; - if(fps > fps_limit) { - fps = fps_limit; - } - - perf_monitor.fps_sum_all += fps; - perf_monitor.fps_sum_cnt ++; - uint32_t cpu = 100 - lv_timer_get_idle(); - lv_label_set_text_fmt(perf_label, "%"LV_PRIu32" FPS\n%"LV_PRIu32"%% CPU", fps, cpu); - } -#endif - -#if LV_USE_MEM_MONITOR && LV_USE_BUILTIN_MALLOC && LV_USE_LABEL - lv_obj_t * mem_label = mem_monitor.mem_label; - if(mem_label == NULL) { - mem_label = lv_label_create(lv_layer_sys()); - lv_obj_set_style_bg_opa(mem_label, LV_OPA_50, 0); - lv_obj_set_style_bg_color(mem_label, lv_color_black(), 0); - lv_obj_set_style_text_color(mem_label, lv_color_white(), 0); - lv_obj_set_style_pad_top(mem_label, 3, 0); - lv_obj_set_style_pad_bottom(mem_label, 3, 0); - lv_obj_set_style_pad_left(mem_label, 3, 0); - lv_obj_set_style_pad_right(mem_label, 3, 0); - lv_label_set_text(mem_label, "?"); - lv_obj_align(mem_label, LV_USE_MEM_MONITOR_POS, 0, 0); - mem_monitor.mem_label = mem_label; - } - - if(lv_tick_elaps(mem_monitor.mem_last_time) > 300) { - mem_monitor.mem_last_time = lv_tick_get(); - lv_mem_monitor_t mon; - lv_mem_monitor(&mon); - uint32_t used_size = mon.total_size - mon.free_size;; - uint32_t used_kb = used_size / 1024; - uint32_t used_kb_tenth = (used_size - (used_kb * 1024)) / 102; - lv_label_set_text_fmt(mem_label, - "%"LV_PRIu32 ".%"LV_PRIu32 " kB used (%d %%)\n" - "%d%% frag.", - used_kb, used_kb_tenth, mon.used_pct, - mon.frag_pct); - } -#endif - /*Refresh the screen's layout if required*/ lv_obj_update_layout(disp_refr->act_scr); if(disp_refr->prev_scr) lv_obj_update_layout(disp_refr->prev_scr); @@ -478,23 +349,6 @@ refr_finish: REFR_TRACE("finished"); } -#if LV_USE_PERF_MONITOR -void lv_refr_reset_fps_counter(void) -{ - perf_monitor.fps_sum_all = 0; - perf_monitor.fps_sum_cnt = 0; -} - -uint32_t lv_refr_get_fps_avg(void) -{ - if(perf_monitor.fps_sum_cnt == 0) { - return 0; - } - return perf_monitor.fps_sum_all / perf_monitor.fps_sum_cnt; -} -#endif - - /********************** * STATIC FUNCTIONS **********************/ @@ -541,8 +395,6 @@ static void lv_refr_join_area(void) */ static void refr_invalid_areas(void) { - px_num = 0; - if(disp_refr->inv_p == 0) return; /*Find the last area which will be drawn*/ @@ -570,7 +422,7 @@ static void refr_invalid_areas(void) disp_refr->last_part = 0; refr_area(&disp_refr->inv_areas[i]); - px_num += lv_area_get_size(&disp_refr->inv_areas[i]); + lv_area_get_size(&disp_refr->inv_areas[i]); } } @@ -1237,25 +1089,3 @@ static void call_flush_cb(lv_disp_t * disp, const lv_area_t * area, lv_color_t * disp->flush_cb(disp, &offset_area, color_p); } - -#if LV_USE_PERF_MONITOR -static void perf_monitor_init(perf_monitor_t * _perf_monitor) -{ - LV_ASSERT_NULL(_perf_monitor); - _perf_monitor->elaps_sum = 0; - _perf_monitor->fps_sum_all = 0; - _perf_monitor->fps_sum_cnt = 0; - _perf_monitor->frame_cnt = 0; - _perf_monitor->perf_last_time = 0; - _perf_monitor->perf_label = NULL; -} -#endif - -#if LV_USE_MEM_MONITOR -static void mem_monitor_init(mem_monitor_t * _mem_monitor) -{ - LV_ASSERT_NULL(_mem_monitor); - _mem_monitor->mem_last_time = 0; - _mem_monitor->mem_label = NULL; -} -#endif diff --git a/src/core/lv_refr.h b/src/core/lv_refr.h index 112f23ced..21a5e545b 100644 --- a/src/core/lv_refr.h +++ b/src/core/lv_refr.h @@ -78,19 +78,6 @@ void _lv_inv_area(lv_disp_t * disp, const lv_area_t * area_p); */ lv_disp_t * _lv_refr_get_disp_refreshing(void); -#if LV_USE_PERF_MONITOR -/** - * Reset FPS counter - */ -void lv_refr_reset_fps_counter(void); - -/** - * Get the average FPS - * @return the average FPS - */ -uint32_t lv_refr_get_fps_avg(void); -#endif - /** * Called periodically to handle the refreshing * @param timer pointer to the timer itself diff --git a/src/lv_conf_internal.h b/src/lv_conf_internal.h index 66bc107ec..5e6288340 100644 --- a/src/lv_conf_internal.h +++ b/src/lv_conf_internal.h @@ -856,7 +856,8 @@ * Others *-----------*/ -/*1: Show CPU usage and FPS count*/ +/*1: Show CPU usage and FPS count + * Requires `LV_USE_MONITOR = 1`*/ #ifndef LV_USE_PERF_MONITOR #ifdef CONFIG_LV_USE_PERF_MONITOR #define LV_USE_PERF_MONITOR CONFIG_LV_USE_PERF_MONITOR @@ -872,10 +873,18 @@ #define LV_USE_PERF_MONITOR_POS LV_ALIGN_BOTTOM_RIGHT #endif #endif + #ifndef LV_USE_PERF_MONITOR_LOG_MDOE + #ifdef CONFIG_LV_USE_PERF_MONITOR_LOG_MDOE + #define LV_USE_PERF_MONITOR_LOG_MDOE CONFIG_LV_USE_PERF_MONITOR_LOG_MDOE + #else + #define LV_USE_PERF_MONITOR_LOG_MDOE 0 + #endif + #endif #endif /*1: Show the used memory and the memory fragmentation - * Requires `LV_USE_BUILTIN_MALLOC = 1`*/ + * Requires `LV_USE_BUILTIN_MALLOC = 1` + * Requires `LV_USE_MONITOR = 1`*/ #ifndef LV_USE_MEM_MONITOR #ifdef CONFIG_LV_USE_MEM_MONITOR #define LV_USE_MEM_MONITOR CONFIG_LV_USE_MEM_MONITOR @@ -2326,6 +2335,19 @@ #endif #endif +/*1: Enable Monitor component*/ +#ifndef LV_USE_MONITOR + #ifdef _LV_KCONFIG_PRESENT + #ifdef CONFIG_LV_USE_MONITOR + #define LV_USE_MONITOR CONFIG_LV_USE_MONITOR + #else + #define LV_USE_MONITOR 0 + #endif + #else + #define LV_USE_MONITOR 1 + #endif +#endif + /*1: Enable Monkey test*/ #ifndef LV_USE_MONKEY #ifdef CONFIG_LV_USE_MONKEY diff --git a/src/others/monitor/lv_monitor.c b/src/others/monitor/lv_monitor.c new file mode 100644 index 000000000..e0557ee2a --- /dev/null +++ b/src/others/monitor/lv_monitor.c @@ -0,0 +1,212 @@ +/** + * @file lv_monitor.c + * + */ + +/********************* + * INCLUDES + *********************/ + +#include "lv_monitor.h" + +#if LV_USE_MONITOR + +#include "../../misc/lv_assert.h" +#include LV_COLOR_EXTERN_INCLUDE + +/********************* + * DEFINES + *********************/ +#define MY_CLASS &lv_monitor_class + +/********************** + * TYPEDEFS + **********************/ +typedef struct { + uint32_t elaps_sum; + uint32_t frame_cnt; + lv_disp_t * disp; +} perf_info_t; + +/********************** + * STATIC PROTOTYPES + **********************/ +static void lv_monitor_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj); +static void lv_monitor_event(const lv_obj_class_t * class_p, lv_event_t * e); +static void lv_monitor_timer_cb(lv_timer_t * timer); +static void monitor_async_cb(void * user_data); + +#if LV_USE_PERF_MONITOR + static void perf_monitor_init(void); +#endif + +#if LV_USE_MEM_MONITOR && LV_USE_BUILTIN_MALLOC + static void mem_monitor_init(void); +#endif + +/********************** + * STATIC VARIABLES + **********************/ +const lv_obj_class_t lv_monitor_class = { + .base_class = &lv_label_class, + .constructor_cb = lv_monitor_constructor, + .width_def = LV_SIZE_CONTENT, + .height_def = LV_SIZE_CONTENT, + .event_cb = lv_monitor_event, + .instance_size = sizeof(lv_monitor_t), +}; + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +lv_obj_t * lv_monitor_create(void) +{ + LV_LOG_INFO("begin"); + lv_obj_t * obj = lv_obj_class_create_obj(MY_CLASS, lv_layer_sys()); + lv_obj_class_init_obj(obj); + return obj; +} + +void lv_monitor_set_refr_time(lv_obj_t * obj, uint32_t time) +{ + LV_ASSERT_OBJ(obj, MY_CLASS); + lv_monitor_t * monitor = (lv_monitor_t *)obj; + lv_timer_set_period(monitor->timer, time); +} + +void _lv_monitor_builtin_init(void) +{ + lv_async_call(monitor_async_cb, NULL); +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +static void lv_monitor_constructor(const lv_obj_class_t * class_p, lv_obj_t * obj) +{ + LV_UNUSED(class_p); + lv_monitor_t * monitor = (lv_monitor_t *)obj; + monitor->timer = lv_timer_create(lv_monitor_timer_cb, 1000, obj); + lv_obj_set_style_bg_opa(obj, LV_OPA_50, 0); + lv_obj_set_style_bg_color(obj, lv_color_black(), 0); + lv_obj_set_style_text_color(obj, lv_color_white(), 0); + lv_obj_set_style_pad_top(obj, 3, 0); + lv_obj_set_style_pad_bottom(obj, 3, 0); + lv_obj_set_style_pad_left(obj, 3, 0); + lv_obj_set_style_pad_right(obj, 3, 0); + lv_label_set_text(obj, "?"); +} + +static void lv_monitor_timer_cb(lv_timer_t * timer) +{ + lv_obj_t * obj = lv_timer_get_user_data(timer); + lv_obj_send_event(obj, LV_EVENT_REFRESH, NULL); +} + +static void lv_monitor_event(const lv_obj_class_t * class_p, lv_event_t * e) +{ + LV_UNUSED(class_p); + lv_obj_event_base(MY_CLASS, e); +} + +#if LV_USE_PERF_MONITOR + +static void perf_monitor_refr_finish_cb(lv_event_t * e) +{ + lv_obj_t * monitor = lv_event_get_user_data(e); + perf_info_t * info = lv_obj_get_user_data(monitor); + info->elaps_sum += lv_tick_elaps(info->disp->last_render_start_time); + info->frame_cnt++; +} + +static void perf_monitor_event_cb(lv_event_t * e) +{ + lv_obj_t * monitor = lv_event_get_current_target_obj(e); + perf_info_t * info = lv_obj_get_user_data(monitor); + uint32_t cpu = 100 - lv_timer_get_idle(); + uint32_t avg_time = info->frame_cnt ? info->elaps_sum / info->frame_cnt : 0; + +#if LV_USE_PERF_MONITOR_LOG_MDOE + LV_LOG("Performance: %" LV_PRIu32" FPS / %" LV_PRIu32" ms / %" LV_PRIu32 "%% CPU\n", + info->frame_cnt, + avg_time, + cpu); +#else + lv_label_set_text_fmt( + monitor, + "%" LV_PRIu32" FPS / %" LV_PRIu32" ms\n%" LV_PRIu32 "%% CPU", + info->frame_cnt, + avg_time, + cpu + ); +#endif /*LV_USE_PERF_MONITOR_LOG_MDOE*/ + info->elaps_sum = 0; + info->frame_cnt = 0; +} + +static void perf_monitor_init(void) +{ + perf_info_t * info = lv_malloc(sizeof(perf_info_t)); + LV_ASSERT_MALLOC(info); + + lv_memzero(info, sizeof(perf_info_t)); + info->disp = lv_disp_get_default(); + + lv_obj_t * monitor = lv_monitor_create(); + lv_monitor_set_refr_time(monitor, 1000); + lv_obj_align(monitor, LV_USE_PERF_MONITOR_POS, 0, 0); + lv_obj_set_style_text_align(monitor, LV_TEXT_ALIGN_RIGHT, 0); + lv_obj_set_user_data(monitor, info); + lv_obj_add_event(monitor, perf_monitor_event_cb, LV_EVENT_REFRESH, NULL); + lv_disp_add_event(info->disp, perf_monitor_refr_finish_cb, LV_EVENT_REFR_FINISH, monitor); + +#if LV_USE_PERF_MONITOR_LOG_MDOE + /*Reduce rendering performance consumption*/ + lv_obj_add_flag(monitor, LV_OBJ_FLAG_HIDDEN); +#endif +} +#endif + +#if LV_USE_MEM_MONITOR && LV_USE_BUILTIN_MALLOC +static void mem_monitor_event_cb(lv_event_t * e) +{ + lv_obj_t * monitor = lv_event_get_current_target_obj(e); + lv_mem_monitor_t mon; + lv_mem_monitor(&mon); + uint32_t used_size = mon.total_size - mon.free_size;; + uint32_t used_kb = used_size / 1024; + uint32_t used_kb_tenth = (used_size - (used_kb * 1024)) / 102; + lv_label_set_text_fmt(monitor, + "%"LV_PRIu32 ".%"LV_PRIu32 " kB used (%d %%)\n" + "%d%% frag.", + used_kb, used_kb_tenth, mon.used_pct, + mon.frag_pct); +} + +static void mem_monitor_init(void) +{ + lv_obj_t * monitor = lv_monitor_create(); + lv_obj_add_event(monitor, mem_monitor_event_cb, LV_EVENT_REFRESH, NULL); + lv_obj_align(monitor, LV_USE_MEM_MONITOR_POS, 0, 0); + lv_monitor_set_refr_time(monitor, 300); +} +#endif + +static void monitor_async_cb(void * user_data) +{ + LV_UNUSED(user_data); +#if LV_USE_PERF_MONITOR + perf_monitor_init(); +#endif +#if LV_USE_MEM_MONITOR && LV_USE_BUILTIN_MALLOC + mem_monitor_init(); +#endif +} + +#endif /*LV_USE_MONITOR*/ diff --git a/src/others/monitor/lv_monitor.h b/src/others/monitor/lv_monitor.h new file mode 100644 index 000000000..57c2ba995 --- /dev/null +++ b/src/others/monitor/lv_monitor.h @@ -0,0 +1,77 @@ +/** + * @file lv_monitor.h + * + */ + +#ifndef LV_MONITOR_H +#define LV_MONITOR_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ + +#include "../../../lvgl.h" + +#if LV_USE_MONITOR + +#if LV_USE_LABEL == 0 +#error "lv_monitor: lv_label is required. Enable it in lv_conf.h (LV_USE_LABEL 1) " +#endif + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ +typedef struct { + lv_label_t label; + lv_timer_t * timer; +} lv_monitor_t; + +extern const lv_obj_class_t lv_monitor_class; + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Create a monitor object (on lv_layer_sys). + * @return pointer to the new monitor object + */ +lv_obj_t * lv_monitor_create(void); + +/** + * Check if a given flag or any of the flags are set on an object. + * @param obj pointer to a monitor object + * @param time monitor refresh interval + */ +void lv_monitor_set_refr_time(lv_obj_t * obj, uint32_t time); + +/** + * Initialize built-in monitors, such as performance and memory monitors. + */ +void _lv_monitor_builtin_init(void); + +/********************** + * MACROS + **********************/ + +#else + +#if LV_USE_PERF_MONITOR || LV_USE_MEM_MONITOR +#warning "lv_monitor: lv_monitor is required. Enable it in lv_conf.h (LV_USE_MONITOR 1)" +#endif + +#endif /*LV_USE_MONITOR*/ + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*LV_MONITOR_H*/