diff --git a/README.md b/README.md index 28ad925d..6174f9bb 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,104 @@ # lvgl_rtt lvgl package for RT-Thread + + + +两个提高LVGL速度的诀窍,第一,把缓存放在AXI SRAM里面而不是SDRAM里面,第二,使用MDMA复制数据。 + +感谢 “ART-Pi DIY 开源硬件群(1016035998)” 里的 **斌**,**阿达 \^_^**,**Mzx**,**手把手** 的讨论。 + + + +需制作成选项的: + +```C +#define LV_USE_CUSTOM_DMA2D 1 +// 使用时在 stm32h7xx_hal_conf.h 里打开 `#define HAL_DMA2D_MODULE_ENABLED ` 的注释 + +#define LV_USE_AXI_SRAM +// 是否使用 AXI SRAM + +#define LV_USE_INDEV +#define LV_USE_TOUCH +#define LV_TOUCH_NAME "gt1151" + +/* 1: Enable file system (might be required for images */ +#define LV_USE_FILESYSTEM 1 + +/*1: Show CPU usage and FPS count in the right bottom corner*/ +#define LV_USE_PERF_MONITOR 0 + +/* Color depth: + * - 1: 1 byte per pixel + * - 8: RGB332 + * - 16: RGB565 + * - 32: ARGB8888 + */ +#define LV_COLOR_DEPTH 16 + +/* Maximal horizontal and vertical resolution to support by the library.*/ +#define LV_HOR_RES_MAX (480) +#define LV_VER_RES_MAX (320) + +/* Dot Per Inch: used to initialize default sizes. + * E.g. a button with width = LV_DPI / 2 -> half inch wide + * (Not so important, you can adjust it to modify default sizes and spaces)*/ +#define LV_DPI 130 +``` + +更改 lcd_port.h 里的 LCD 驱动参数 + + + + + +```C +rt_size_t touch_gt1151_readpoint(struct rt_touch_device *touch, void *data_buf, rt_size_t touch_num) +{ + RT_ASSERT(touch_num == 1); // only support 1 touch point + + struct gt1151_object *object = (struct gt1151_object *)touch->config.user_data; + + uint8_t status; + uint8_t buf[8]; + uint16_t x = 0, y = 0; + + struct rt_touch_data *pdata = (struct rt_touch_data *)data_buf; + + gt1151_read_regs(object, GT1151_STATUS, &status, 1); + + if (status < 0x80) // no data get + return 0; + + else if (status == 0x80) { // no data get + LOG_D("status: %x", status); + gt1151_clear_status(object); + return 0; + } + else { + gt1151_clear_status(object); + + LOG_D("status: %x", status); + + gt1151_read_regs(object, GT1151_STATUS, buf, 8); + + x = ((uint16_t)buf[3] << 8) + buf[2]; + y = ((uint16_t)buf[5] << 8) + buf[4]; + + if (x > GT1151_TOUCH_WIDTH - 1) x = GT1151_TOUCH_WIDTH; + if (y > GT1151_TOUCH_HEIGHT - 1) y = GT1151_TOUCH_HEIGHT; + + pdata->x_coordinate = x; + pdata->y_coordinate = y; + pdata->track_id = 1; + pdata->event = RT_TOUCH_EVENT_DOWN; + pdata->timestamp = rt_touch_get_ts(); + + status = 0; + + LOG_D("\t x: %d, y: %d", x, y); + } + return 1; +} +``` + diff --git a/SConscript b/SConscript new file mode 100644 index 00000000..ee48c38b --- /dev/null +++ b/SConscript @@ -0,0 +1,24 @@ +import os +from building import * + +cwd = GetCurrentDir() + +# init src and inc +src = [] +inc = [] + +# add lvgl_rtt common include +inc += [cwd] +inc += [cwd + '/inc'] + +# define LVGL_RTT group +objs = DefineGroup('lvgl_rtt', src, depend = ['PKG_USING_LVGL_RTT'], CPPPATH = inc) + +list = os.listdir(cwd) +if GetDepend('PKG_USING_LVGL_RTT'): + for d in list: + path = os.path.join(cwd, d) + if os.path.isfile(os.path.join(path, 'SConscript')): + objs = objs + SConscript(os.path.join(d, 'SConscript')) + +Return('objs') \ No newline at end of file diff --git a/docs/lvgl task tick.md b/docs/lvgl task tick.md new file mode 100644 index 00000000..e69de29b diff --git a/examples/SConscript b/examples/SConscript new file mode 100644 index 00000000..028e6f5d --- /dev/null +++ b/examples/SConscript @@ -0,0 +1,8 @@ +from building import * + +cwd = GetCurrentDir() +src = Glob('*.c') + +group = DefineGroup('lvgl_rtt_example', src, depend = ['LVGL_RTT_USING_EXAMPLE']) + +Return('group') \ No newline at end of file diff --git a/examples/lv_test_theme.c b/examples/lv_test_theme.c new file mode 100644 index 00000000..a1f43765 --- /dev/null +++ b/examples/lv_test_theme.c @@ -0,0 +1,692 @@ +/** + * @file lv_demo_widgets.c + * + */ + +/********************* + * INCLUDES + *********************/ +#include "../lvgl/lvgl.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ +static void controls_create(lv_obj_t * parent); +static void visuals_create(lv_obj_t * parent); +static void selectors_create(lv_obj_t * parent); +static void slider_event_cb(lv_obj_t * slider, lv_event_t e); +static void ta_event_cb(lv_obj_t * ta, lv_event_t e); +static void kb_event_cb(lv_obj_t * ta, lv_event_t e); +static void bar_anim(lv_task_t * t); +static void arc_anim(lv_obj_t * arc, lv_anim_value_t value); +static void linemeter_anim(lv_obj_t * linemeter, lv_anim_value_t value); +static void gauge_anim(lv_obj_t * gauge, lv_anim_value_t value); +static void table_event_cb(lv_obj_t * table, lv_event_t e); +#if LV_USE_THEME_MATERIAL +static void color_chg_event_cb(lv_obj_t * sw, lv_event_t e); +#endif +#if LV_DEMO_WIDGETS_SLIDESHOW +static void tab_content_anim_create(lv_obj_t * parent); +static void tab_changer_task_cb(lv_task_t * task); +#endif + +/********************** + * STATIC VARIABLES + **********************/ +static lv_obj_t * tv; +static lv_obj_t * t1; +static lv_obj_t * t2; +static lv_obj_t * t3; +static lv_obj_t * kb; + +static lv_style_t style_box; + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +void lv_demo_widgets(void) +{ + tv = lv_tabview_create(lv_scr_act(), NULL); + + t1 = lv_tabview_add_tab(tv, "Controls"); + t2 = lv_tabview_add_tab(tv, "Visuals"); + t3 = lv_tabview_add_tab(tv, "Selectors"); + + + lv_style_init(&style_box); + lv_style_set_value_align(&style_box, LV_STATE_DEFAULT, LV_ALIGN_OUT_TOP_LEFT); + lv_style_set_value_ofs_y(&style_box, LV_STATE_DEFAULT, - LV_DPX(10)); + lv_style_set_margin_top(&style_box, LV_STATE_DEFAULT, LV_DPX(30)); + + controls_create(t1); + visuals_create(t2); + selectors_create(t3); + +} + +/********************** + * STATIC FUNCTIONS + **********************/ + + +static void controls_create(lv_obj_t * parent) +{ + lv_page_set_scrl_layout(parent, LV_LAYOUT_PRETTY_TOP); + + lv_disp_size_t disp_size = lv_disp_get_size_category(NULL); + lv_coord_t grid_w = lv_page_get_width_grid(parent, disp_size <= LV_DISP_SIZE_SMALL ? 1 : 2, 1); + +#if LV_DEMO_WIDGETS_SLIDESHOW == 0 + static const char * btns[] = {"Cancel", "Ok", ""}; + + lv_obj_t * m = lv_msgbox_create(lv_scr_act(), NULL); + lv_msgbox_add_btns(m, btns); + lv_obj_t * btnm = lv_msgbox_get_btnmatrix(m); + lv_btnmatrix_set_btn_ctrl(btnm, 1, LV_BTNMATRIX_CTRL_CHECK_STATE); +#endif + + lv_obj_t * h = lv_cont_create(parent, NULL); + lv_cont_set_layout(h, LV_LAYOUT_PRETTY_MID); + lv_obj_add_style(h, LV_CONT_PART_MAIN, &style_box); + lv_obj_set_drag_parent(h, true); + + lv_obj_set_style_local_value_str(h, LV_CONT_PART_MAIN, LV_STATE_DEFAULT, "Basics"); + + lv_cont_set_fit2(h, LV_FIT_NONE, LV_FIT_TIGHT); + lv_obj_set_width(h, grid_w); + lv_obj_t * btn = lv_btn_create(h, NULL); + lv_btn_set_fit2(btn, LV_FIT_NONE, LV_FIT_TIGHT); + lv_obj_set_width(btn, lv_obj_get_width_grid(h, disp_size <= LV_DISP_SIZE_SMALL ? 1 : 2, 1)); + lv_obj_t * label = lv_label_create(btn, NULL); + lv_label_set_text(label ,"Button"); + + btn = lv_btn_create(h, btn); + lv_btn_toggle(btn); + label = lv_label_create(btn, NULL); + lv_label_set_text(label ,"Button"); + + lv_switch_create(h, NULL); + + lv_checkbox_create(h, NULL); + + lv_coord_t fit_w = lv_obj_get_width_fit(h); + + lv_obj_t * slider = lv_slider_create(h, NULL); + lv_slider_set_value(slider, 40, LV_ANIM_OFF); + lv_obj_set_event_cb(slider, slider_event_cb); + lv_obj_set_width_margin(slider, fit_w); + + /*Use the knobs style value the display the current value in focused state*/ + lv_obj_set_style_local_margin_top(slider, LV_SLIDER_PART_BG, LV_STATE_DEFAULT, LV_DPX(25)); + lv_obj_set_style_local_value_font(slider, LV_SLIDER_PART_KNOB, LV_STATE_DEFAULT, lv_theme_get_font_small()); + lv_obj_set_style_local_value_ofs_y(slider, LV_SLIDER_PART_KNOB, LV_STATE_FOCUSED, - LV_DPX(25)); + lv_obj_set_style_local_value_opa(slider, LV_SLIDER_PART_KNOB, LV_STATE_DEFAULT, LV_OPA_TRANSP); + lv_obj_set_style_local_value_opa(slider, LV_SLIDER_PART_KNOB, LV_STATE_FOCUSED, LV_OPA_COVER); + lv_obj_set_style_local_transition_time(slider, LV_SLIDER_PART_KNOB, LV_STATE_DEFAULT, 300); + lv_obj_set_style_local_transition_prop_5(slider, LV_SLIDER_PART_KNOB, LV_STATE_DEFAULT, LV_STYLE_VALUE_OFS_Y); + lv_obj_set_style_local_transition_prop_6(slider, LV_SLIDER_PART_KNOB, LV_STATE_DEFAULT, LV_STYLE_VALUE_OPA); + + slider = lv_slider_create(h, slider); + lv_slider_set_type(slider, LV_SLIDER_TYPE_RANGE); + lv_slider_set_value(slider, 70, LV_ANIM_OFF); + lv_slider_set_left_value(slider, 30, LV_ANIM_OFF); + lv_obj_set_style_local_value_ofs_y(slider, LV_SLIDER_PART_INDIC, LV_STATE_DEFAULT, - LV_DPX(25)); + lv_obj_set_style_local_value_font(slider, LV_SLIDER_PART_INDIC, LV_STATE_DEFAULT, lv_theme_get_font_small()); + lv_obj_set_style_local_value_opa(slider, LV_SLIDER_PART_INDIC, LV_STATE_DEFAULT, LV_OPA_COVER); + lv_obj_set_event_cb(slider, slider_event_cb); + lv_event_send(slider, LV_EVENT_VALUE_CHANGED, NULL); /*To refresh the text*/ + if(lv_obj_get_width(slider) > fit_w) lv_obj_set_width(slider, fit_w); + + h = lv_cont_create(parent, h); + lv_cont_set_fit(h, LV_FIT_NONE); + lv_obj_set_style_local_value_str(h, LV_CONT_PART_MAIN, LV_STATE_DEFAULT, "Text input"); + + lv_obj_t * ta = lv_textarea_create(h, NULL); + lv_cont_set_fit2(ta, LV_FIT_PARENT, LV_FIT_NONE); + lv_textarea_set_text(ta, ""); + lv_textarea_set_placeholder_text(ta, "E-mail address"); + lv_textarea_set_one_line(ta, true); + lv_textarea_set_cursor_hidden(ta, true); + lv_obj_set_event_cb(ta, ta_event_cb); + + ta = lv_textarea_create(h, ta); + lv_textarea_set_pwd_mode(ta, true); + lv_textarea_set_placeholder_text(ta, "Password"); + + ta = lv_textarea_create(h, NULL); + lv_cont_set_fit2(ta, LV_FIT_PARENT, LV_FIT_NONE); + lv_textarea_set_text(ta, ""); + lv_textarea_set_placeholder_text(ta, "Message"); + lv_textarea_set_cursor_hidden(ta, true); + lv_obj_set_event_cb(ta, ta_event_cb); + lv_cont_set_fit4(ta, LV_FIT_PARENT, LV_FIT_PARENT, LV_FIT_NONE, LV_FIT_PARENT); + +#if LV_DEMO_WIDGETS_SLIDESHOW + tab_content_anim_create(parent); +#endif +} + +static void visuals_create(lv_obj_t * parent) +{ + lv_page_set_scrl_layout(parent, LV_LAYOUT_PRETTY_TOP); + + lv_disp_size_t disp_size = lv_disp_get_size_category(NULL); + + lv_coord_t grid_h_chart = lv_page_get_height_grid(parent, 1, 1); + lv_coord_t grid_w_chart = lv_page_get_width_grid(parent, disp_size <= LV_DISP_SIZE_LARGE ? 1 : 2, 1); + + lv_obj_t * chart = lv_chart_create(parent, NULL); + lv_obj_add_style(chart, LV_CHART_PART_BG, &style_box); + if(disp_size <= LV_DISP_SIZE_SMALL) { + lv_obj_set_style_local_text_font(chart, LV_CHART_PART_SERIES_BG, LV_STATE_DEFAULT, lv_theme_get_font_small()); + + } + lv_obj_set_drag_parent(chart, true); + lv_obj_set_style_local_value_str(chart, LV_CONT_PART_MAIN, LV_STATE_DEFAULT, "Line chart"); + lv_obj_set_width_margin(chart, grid_w_chart); + lv_obj_set_height_margin(chart, grid_h_chart); + lv_chart_set_div_line_count(chart, 3, 0); + lv_chart_set_point_count(chart, 8); + lv_chart_set_type(chart, LV_CHART_TYPE_LINE); + if(disp_size > LV_DISP_SIZE_SMALL) { + lv_obj_set_style_local_pad_left(chart, LV_CHART_PART_BG, LV_STATE_DEFAULT, 4 * (LV_DPI / 10)); + lv_obj_set_style_local_pad_bottom(chart, LV_CHART_PART_BG, LV_STATE_DEFAULT, 3 * (LV_DPI / 10)); + lv_obj_set_style_local_pad_right(chart, LV_CHART_PART_BG, LV_STATE_DEFAULT, 2 * (LV_DPI / 10)); + lv_obj_set_style_local_pad_top(chart, LV_CHART_PART_BG, LV_STATE_DEFAULT, 2 * (LV_DPI / 10)); + lv_chart_set_y_tick_length(chart, 0, 0); + lv_chart_set_x_tick_length(chart, 0, 0); + lv_chart_set_y_tick_texts(chart, "600\n500\n400\n300\n200", 0, LV_CHART_AXIS_DRAW_LAST_TICK); + lv_chart_set_x_tick_texts(chart, "Jan\nFeb\nMar\nApr\nMay\nJun\nJul\nAug", 0, LV_CHART_AXIS_DRAW_LAST_TICK); + } + lv_chart_series_t * s1 = lv_chart_add_series(chart, LV_THEME_DEFAULT_COLOR_PRIMARY); + lv_chart_series_t * s2 = lv_chart_add_series(chart, LV_THEME_DEFAULT_COLOR_SECONDARY); + + lv_chart_set_next(chart, s1, 10); + lv_chart_set_next(chart, s1, 90); + lv_chart_set_next(chart, s1, 30); + lv_chart_set_next(chart, s1, 60); + lv_chart_set_next(chart, s1, 10); + lv_chart_set_next(chart, s1, 90); + lv_chart_set_next(chart, s1, 30); + lv_chart_set_next(chart, s1, 60); + lv_chart_set_next(chart, s1, 10); + lv_chart_set_next(chart, s1, 90); + + lv_chart_set_next(chart, s2, 32); + lv_chart_set_next(chart, s2, 66); + lv_chart_set_next(chart, s2, 5); + lv_chart_set_next(chart, s2, 47); + lv_chart_set_next(chart, s2, 32); + lv_chart_set_next(chart, s2, 32); + lv_chart_set_next(chart, s2, 66); + lv_chart_set_next(chart, s2, 5); + lv_chart_set_next(chart, s2, 47); + lv_chart_set_next(chart, s2, 66); + lv_chart_set_next(chart, s2, 5); + lv_chart_set_next(chart, s2, 47); + + lv_obj_t * chart2 = lv_chart_create(parent, chart); + lv_chart_set_type(chart2, LV_CHART_TYPE_COLUMN); + lv_obj_set_style_local_value_str(chart2, LV_CONT_PART_MAIN, LV_STATE_DEFAULT, "Column chart"); + + s1 = lv_chart_add_series(chart2, LV_THEME_DEFAULT_COLOR_PRIMARY); + s2 = lv_chart_add_series(chart2, LV_THEME_DEFAULT_COLOR_SECONDARY); + + lv_chart_set_next(chart2, s1, 10); + lv_chart_set_next(chart2, s1, 90); + lv_chart_set_next(chart2, s1, 30); + lv_chart_set_next(chart2, s1, 60); + lv_chart_set_next(chart2, s1, 10); + lv_chart_set_next(chart2, s1, 90); + lv_chart_set_next(chart2, s1, 30); + lv_chart_set_next(chart2, s1, 60); + lv_chart_set_next(chart2, s1, 10); + lv_chart_set_next(chart2, s1, 90); + + lv_chart_set_next(chart2, s2, 32); + lv_chart_set_next(chart2, s2, 66); + lv_chart_set_next(chart2, s2, 5); + lv_chart_set_next(chart2, s2, 47); + lv_chart_set_next(chart2, s2, 32); + lv_chart_set_next(chart2, s2, 32); + lv_chart_set_next(chart2, s2, 66); + lv_chart_set_next(chart2, s2, 5); + lv_chart_set_next(chart2, s2, 47); + lv_chart_set_next(chart2, s2, 66); + lv_chart_set_next(chart2, s2, 5); + lv_chart_set_next(chart2, s2, 47); + + lv_coord_t grid_w_meter; + if(disp_size <= LV_DISP_SIZE_SMALL) grid_w_meter = lv_page_get_width_grid(parent, 1, 1); + else if(disp_size <= LV_DISP_SIZE_MEDIUM) grid_w_meter = lv_page_get_width_grid(parent, 2, 1); + else grid_w_meter = lv_page_get_width_grid(parent, 3, 1); + + lv_coord_t meter_h = lv_page_get_height_fit(parent); + lv_coord_t meter_size = LV_MATH_MIN(grid_w_meter, meter_h); + + lv_obj_t * lmeter = lv_linemeter_create(parent, NULL); + lv_obj_set_drag_parent(lmeter, true); + lv_linemeter_set_value(lmeter, 50); + lv_obj_set_size(lmeter, meter_size, meter_size); + lv_obj_add_style(lmeter, LV_LINEMETER_PART_MAIN, &style_box); + lv_obj_set_style_local_value_str(lmeter, LV_LINEMETER_PART_MAIN, LV_STATE_DEFAULT, "Line meter"); + + lv_obj_t * label = lv_label_create(lmeter, NULL); + lv_obj_align(label, lmeter, LV_ALIGN_CENTER, 0, 0); + lv_obj_set_style_local_text_font(label, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_theme_get_font_title()); + + lv_anim_t a; + lv_anim_init(&a); + lv_anim_set_var(&a, lmeter); + lv_anim_set_exec_cb(&a, (lv_anim_exec_xcb_t)linemeter_anim); + lv_anim_set_values(&a, 0, 100); + lv_anim_set_time(&a, 4000); + lv_anim_set_playback_time(&a, 1000); + lv_anim_set_repeat_count(&a, LV_ANIM_REPEAT_INFINITE); + lv_anim_start(&a); + + + lv_obj_t * gauge = lv_gauge_create(parent, NULL); + lv_obj_set_drag_parent(gauge, true); + lv_obj_set_size(gauge, meter_size, meter_size); + lv_obj_add_style(gauge, LV_GAUGE_PART_MAIN, &style_box); + lv_obj_set_style_local_value_str(gauge, LV_GAUGE_PART_MAIN, LV_STATE_DEFAULT, "Gauge"); + + label = lv_label_create(gauge, label); + lv_obj_align(label, gauge, LV_ALIGN_CENTER, 0, grid_w_meter / 3); + + lv_anim_set_var(&a, gauge); + lv_anim_set_exec_cb(&a, (lv_anim_exec_xcb_t)gauge_anim); + lv_anim_start(&a); + + lv_obj_t * arc = lv_arc_create(parent, NULL); + lv_obj_set_drag_parent(arc, true); + lv_arc_set_bg_angles(arc, 0, 360); + lv_arc_set_rotation(arc, 270); + lv_arc_set_angles(arc, 0, 0); + lv_obj_set_size(arc, meter_size, meter_size); + lv_obj_add_style(arc, LV_ARC_PART_BG, &style_box); + lv_obj_set_style_local_value_str(arc, LV_ARC_PART_BG, LV_STATE_DEFAULT, "Arc"); + + label = lv_label_create(arc, label); + lv_obj_align(label, arc, LV_ALIGN_CENTER, 0, 0); + + lv_anim_set_var(&a, arc); + lv_anim_set_exec_cb(&a, (lv_anim_exec_xcb_t)arc_anim); + lv_anim_set_values(&a, 0, 360); + lv_anim_set_repeat_count(&a, LV_ANIM_REPEAT_INFINITE); + lv_anim_start(&a); + + /*Create a bar and use the backgrounds value style property to display the current value*/ + lv_obj_t * bar_h = lv_cont_create(parent, NULL); + lv_cont_set_fit2(bar_h, LV_FIT_NONE, LV_FIT_TIGHT); + lv_obj_add_style(bar_h, LV_CONT_PART_MAIN, &style_box); + lv_obj_set_style_local_value_str(bar_h, LV_CONT_PART_MAIN, LV_STATE_DEFAULT, "Bar"); + + if(disp_size <= LV_DISP_SIZE_SMALL) lv_obj_set_width(bar_h, lv_page_get_width_grid(parent, 1, 1)); + else if(disp_size <= LV_DISP_SIZE_MEDIUM) lv_obj_set_width(bar_h, lv_page_get_width_grid(parent, 2, 1)); + else lv_obj_set_width(bar_h, lv_page_get_width_grid(parent, 3, 2)); + + lv_obj_t * bar = lv_bar_create(bar_h, NULL); + lv_obj_set_width(bar, lv_obj_get_width_fit(bar_h)); + lv_obj_set_style_local_value_font(bar, LV_BAR_PART_BG, LV_STATE_DEFAULT, lv_theme_get_font_small()); + lv_obj_set_style_local_value_align(bar, LV_BAR_PART_BG, LV_STATE_DEFAULT, LV_ALIGN_OUT_BOTTOM_MID); + lv_obj_set_style_local_value_ofs_y(bar, LV_BAR_PART_BG, LV_STATE_DEFAULT, LV_DPI / 20); + lv_obj_set_style_local_margin_bottom(bar, LV_BAR_PART_BG, LV_STATE_DEFAULT, LV_DPI / 7); + lv_obj_align(bar, NULL, LV_ALIGN_CENTER, 0, 0); + + lv_obj_t * led_h = lv_cont_create(parent, NULL); + lv_cont_set_layout(led_h, LV_LAYOUT_PRETTY_MID); + if(disp_size <= LV_DISP_SIZE_SMALL) lv_obj_set_width(led_h, lv_page_get_width_grid(parent, 1, 1)); + else if(disp_size <= LV_DISP_SIZE_MEDIUM) lv_obj_set_width(led_h, lv_page_get_width_grid(parent, 2, 1)); + else lv_obj_set_width(led_h, lv_page_get_width_grid(parent, 3, 1)); + + lv_obj_set_height(led_h, lv_obj_get_height(bar_h)); + lv_obj_add_style(led_h, LV_CONT_PART_MAIN, &style_box); + lv_obj_set_drag_parent(led_h, true); + lv_obj_set_style_local_value_str(led_h, LV_CONT_PART_MAIN, LV_STATE_DEFAULT, "LEDs"); + + lv_obj_t * led = lv_led_create(led_h, NULL); + lv_coord_t led_size = lv_obj_get_height_fit(led_h); + lv_obj_set_size(led, led_size, led_size); + lv_led_off(led); + + led = lv_led_create(led_h, led); + lv_led_set_bright(led, (LV_LED_BRIGHT_MAX - LV_LED_BRIGHT_MIN) / 2 + LV_LED_BRIGHT_MIN); + + led = lv_led_create(led_h, led); + lv_led_on(led); + + if(disp_size == LV_DISP_SIZE_MEDIUM) { + lv_obj_add_protect(led_h, LV_PROTECT_POS); + lv_obj_align(led_h, bar_h, LV_ALIGN_OUT_BOTTOM_MID, 0, lv_obj_get_style_margin_top(led_h, LV_OBJ_PART_MAIN) + lv_obj_get_style_pad_inner(parent, LV_PAGE_PART_SCROLLABLE)); + } + + lv_task_create(bar_anim, 100, LV_TASK_PRIO_LOW, bar); +} + + +static void selectors_create(lv_obj_t * parent) +{ + lv_page_set_scrl_layout(parent, LV_LAYOUT_PRETTY_MID); + + lv_disp_size_t disp_size = lv_disp_get_size_category(NULL); + lv_coord_t grid_h = lv_page_get_height_grid(parent, 1, 1); + lv_coord_t grid_w; + if(disp_size <= LV_DISP_SIZE_SMALL) grid_w = lv_page_get_width_grid(parent, 1, 1); + else grid_w = lv_page_get_width_grid(parent, 2, 1); + + lv_obj_t * cal = lv_calendar_create(parent, NULL); + lv_obj_set_drag_parent(cal, true); + if(disp_size > LV_DISP_SIZE_MEDIUM) { + lv_obj_set_size(cal, LV_MATH_MIN(grid_h, grid_w), LV_MATH_MIN(grid_h, grid_w)); + } else { + lv_obj_set_size(cal, grid_w, grid_w); + if(disp_size <= LV_DISP_SIZE_SMALL) { + lv_obj_set_style_local_text_font(cal, LV_CALENDAR_PART_BG, LV_STATE_DEFAULT, lv_theme_get_font_small()); + } + } + + static lv_calendar_date_t hl[] = { + {.year = 2020, .month = 1, .day = 5}, + {.year = 2020, .month = 1, .day = 9}, + }; + + + lv_obj_t * btn; + lv_obj_t * h = lv_cont_create(parent, NULL); + lv_obj_set_drag_parent(h, true); + if(disp_size <= LV_DISP_SIZE_SMALL) { + lv_cont_set_fit2(h, LV_FIT_NONE, LV_FIT_TIGHT); + lv_obj_set_width(h, lv_page_get_width_fit(parent)); + lv_cont_set_layout(h, LV_LAYOUT_COLUMN_MID); + } else if(disp_size <= LV_DISP_SIZE_MEDIUM) { + lv_obj_set_size(h, lv_obj_get_width(cal), lv_obj_get_height(cal)); + lv_cont_set_layout(h, LV_LAYOUT_PRETTY_TOP); + } else { + lv_obj_set_click(h, false); + lv_obj_set_style_local_bg_opa(h, LV_CONT_PART_MAIN, LV_STATE_DEFAULT, LV_OPA_TRANSP); + lv_obj_set_style_local_border_opa(h, LV_CONT_PART_MAIN, LV_STATE_DEFAULT, LV_OPA_TRANSP); + lv_obj_set_style_local_pad_left(h, LV_CONT_PART_MAIN, LV_STATE_DEFAULT, 0); + lv_obj_set_style_local_pad_right(h, LV_CONT_PART_MAIN, LV_STATE_DEFAULT, 0); + lv_obj_set_style_local_pad_top(h, LV_CONT_PART_MAIN, LV_STATE_DEFAULT, 0); + lv_obj_set_size(h, LV_MATH_MIN(grid_h, grid_w), LV_MATH_MIN(grid_h, grid_w)); + lv_cont_set_layout(h, LV_LAYOUT_PRETTY_TOP); + } + + + lv_obj_t * roller = lv_roller_create(h, NULL); + lv_obj_add_style(roller, LV_CONT_PART_MAIN, &style_box); + lv_obj_set_style_local_value_str(roller, LV_CONT_PART_MAIN, LV_STATE_DEFAULT, "Roller"); + lv_roller_set_auto_fit(roller, false); + lv_roller_set_align(roller, LV_LABEL_ALIGN_CENTER); + lv_roller_set_visible_row_count(roller, 4); + lv_obj_set_width(roller, lv_obj_get_width_grid(h, disp_size <= LV_DISP_SIZE_SMALL ? 1 : 2, 1)); + + lv_obj_t * dd = lv_dropdown_create(h, NULL); + lv_obj_add_style(dd, LV_CONT_PART_MAIN, &style_box); + lv_obj_set_style_local_value_str(dd, LV_CONT_PART_MAIN, LV_STATE_DEFAULT, "Dropdown"); + lv_obj_set_width(dd, lv_obj_get_width_grid(h, disp_size <= LV_DISP_SIZE_SMALL ? 1 : 2, 1)); + lv_dropdown_set_options(dd, "Alpha\nBravo\nCharlie\nDelta\nEcho\nFoxtrot\nGolf\nHotel\nIndia\nJuliette\nKilo\nLima\nMike\nNovember\n" + "Oscar\nPapa\nQuebec\nRomeo\nSierra\nTango\nUniform\nVictor\nWhiskey\nXray\nYankee\nZulu"); + + lv_obj_t * list = lv_list_create(parent, NULL); + lv_list_set_scroll_propagation(list, true); + lv_obj_set_size(list, grid_w, grid_h); + + const char * txts[] = {LV_SYMBOL_SAVE, "Save", LV_SYMBOL_CUT, "Cut", LV_SYMBOL_COPY, "Copy", + LV_SYMBOL_OK, "This is a quite long text to scroll on the list", LV_SYMBOL_EDIT, "Edit", LV_SYMBOL_WIFI, "Wifi", + LV_SYMBOL_BLUETOOTH, "Bluetooth", LV_SYMBOL_GPS, "GPS", LV_SYMBOL_USB, "USB", + LV_SYMBOL_SD_CARD, "SD card", LV_SYMBOL_CLOSE, "Close", NULL}; + + uint32_t i; + for(i = 0; txts[i] != NULL; i += 2) { + btn = lv_list_add_btn(list, txts[i], txts[i + 1]); + lv_btn_set_checkable(btn, true); + + /*Make a button disabled*/ + if(i == 4) { + lv_btn_set_state(btn, LV_BTN_STATE_DISABLED); + } + } + + lv_calendar_set_highlighted_dates(cal, hl, 2); + + + static lv_style_t style_cell4; + lv_style_init(&style_cell4); + lv_style_set_bg_opa(&style_cell4, LV_STATE_DEFAULT, LV_OPA_50); + lv_style_set_bg_color(&style_cell4, LV_STATE_DEFAULT, LV_COLOR_GRAY); + + lv_obj_t * page = lv_page_create(parent ,NULL); + lv_obj_set_size(page, grid_w, grid_h); + lv_coord_t table_w_max = lv_page_get_width_fit(page); + lv_page_set_scroll_propagation(page, true); + + lv_obj_t * table1 = lv_table_create(page, NULL); + lv_obj_add_style(table1, LV_TABLE_PART_CELL4, &style_cell4); + /*Clean the background style of the table because it is placed on a page*/ + lv_obj_clean_style_list(table1, LV_TABLE_PART_BG); + lv_obj_set_drag_parent(table1, true); + lv_obj_set_event_cb(table1, table_event_cb); + lv_table_set_col_cnt(table1, disp_size > LV_DISP_SIZE_SMALL ? 3 : 2); + if(disp_size > LV_DISP_SIZE_SMALL) { + lv_table_set_col_width(table1, 0, LV_MATH_MAX(30, 1 * table_w_max / 5)); + lv_table_set_col_width(table1, 1, LV_MATH_MAX(60, 2 * table_w_max / 5)); + lv_table_set_col_width(table1, 2, LV_MATH_MAX(60, 2 * table_w_max / 5)); + } else { + lv_table_set_col_width(table1, 0, LV_MATH_MAX(30, 1 * table_w_max / 4 - 1)); + lv_table_set_col_width(table1, 1, LV_MATH_MAX(60, 3 * table_w_max / 4 - 1)); + } + + lv_table_set_cell_value(table1, 0, 0, "#"); + lv_table_set_cell_value(table1, 1, 0, "1"); + lv_table_set_cell_value(table1, 2, 0, "2"); + lv_table_set_cell_value(table1, 3, 0, "3"); + lv_table_set_cell_value(table1, 4, 0, "4"); + lv_table_set_cell_value(table1, 5, 0, "5"); + lv_table_set_cell_value(table1, 6, 0, "6"); + + lv_table_set_cell_value(table1, 0, 1, "NAME"); + lv_table_set_cell_value(table1, 1, 1, "Mark"); + lv_table_set_cell_value(table1, 2, 1, "Jacob"); + lv_table_set_cell_value(table1, 3, 1, "John"); + lv_table_set_cell_value(table1, 4, 1, "Emily"); + lv_table_set_cell_value(table1, 5, 1, "Ivan"); + lv_table_set_cell_value(table1, 6, 1, "George"); + + if(disp_size > LV_DISP_SIZE_SMALL) { + lv_table_set_cell_value(table1, 0, 2, "CITY"); + lv_table_set_cell_value(table1, 1, 2, "Moscow"); + lv_table_set_cell_value(table1, 2, 2, "New York"); + lv_table_set_cell_value(table1, 3, 2, "Oslo"); + lv_table_set_cell_value(table1, 4, 2, "London"); + lv_table_set_cell_value(table1, 5, 2, "Texas"); + lv_table_set_cell_value(table1, 6, 2, "Athen"); + } +} + +static void slider_event_cb(lv_obj_t * slider, lv_event_t e) +{ + if(e == LV_EVENT_VALUE_CHANGED) { + if(lv_slider_get_type(slider) == LV_SLIDER_TYPE_NORMAL) { + static char buf[16]; + lv_snprintf(buf, sizeof(buf), "%d", lv_slider_get_value(slider)); + lv_obj_set_style_local_value_str(slider, LV_SLIDER_PART_KNOB, LV_STATE_DEFAULT, buf); + } else { + static char buf[32]; + lv_snprintf(buf, sizeof(buf), "%d-%d", lv_slider_get_left_value(slider), lv_slider_get_value(slider)); + lv_obj_set_style_local_value_str(slider, LV_SLIDER_PART_INDIC, LV_STATE_DEFAULT, buf); + } + + } + +} + +static void ta_event_cb(lv_obj_t * ta, lv_event_t e) +{ + if(e == LV_EVENT_RELEASED) { + if(kb == NULL) { + lv_obj_set_height(tv, LV_VER_RES / 2); + kb = lv_keyboard_create(lv_scr_act(), NULL); + lv_obj_set_event_cb(kb, kb_event_cb); + + lv_indev_wait_release(lv_indev_get_act()); + } + lv_textarea_set_cursor_hidden(ta, false); + lv_page_focus(t1, lv_textarea_get_label(ta), LV_ANIM_ON); + lv_keyboard_set_textarea(kb, ta); + } else if(e == LV_EVENT_DEFOCUSED) { + lv_textarea_set_cursor_hidden(ta, true); + } +} + + +static void kb_event_cb(lv_obj_t * _kb, lv_event_t e) +{ + lv_keyboard_def_event_cb(kb, e); + + if(e == LV_EVENT_CANCEL) { + if(kb) { + lv_obj_set_height(tv, LV_VER_RES); + lv_obj_del(kb); + kb = NULL; + } + } +} + + +static void bar_anim(lv_task_t * t) +{ + static uint32_t x = 0; + lv_obj_t * bar = t->user_data; + + static char buf[64]; + lv_snprintf(buf, sizeof(buf), "Copying %d/%d", x, lv_bar_get_max_value(bar)); + lv_obj_set_style_local_value_str(bar, LV_BAR_PART_BG, LV_STATE_DEFAULT, buf); + + lv_bar_set_value(bar, x, LV_ANIM_OFF); + x++; + if(x > lv_bar_get_max_value(bar)) x = 0; +} + +static void arc_anim(lv_obj_t * arc, lv_anim_value_t value) +{ + lv_arc_set_end_angle(arc, value); + + static char buf[64]; + lv_snprintf(buf, sizeof(buf), "%d", value); + lv_obj_t * label = lv_obj_get_child(arc, NULL); + lv_label_set_text(label, buf); + lv_obj_align(label, arc, LV_ALIGN_CENTER, 0, 0); + +} + +static void linemeter_anim(lv_obj_t * linemeter, lv_anim_value_t value) +{ + lv_linemeter_set_value(linemeter, value); + + static char buf[64]; + lv_snprintf(buf, sizeof(buf), "%d", value); + lv_obj_t * label = lv_obj_get_child(linemeter, NULL); + lv_label_set_text(label, buf); + lv_obj_align(label, linemeter, LV_ALIGN_CENTER, 0, 0); +} + +static void gauge_anim(lv_obj_t * gauge, lv_anim_value_t value) +{ + lv_gauge_set_value(gauge, 0, value); + + static char buf[64]; + lv_snprintf(buf, sizeof(buf), "%d", value); + lv_obj_t * label = lv_obj_get_child(gauge, NULL); + lv_label_set_text(label, buf); + lv_obj_align(label, gauge, LV_ALIGN_IN_TOP_MID, 0, lv_obj_get_y(label)); +} + +static void table_event_cb(lv_obj_t * table, lv_event_t e) +{ + if(e == LV_EVENT_CLICKED) { + uint16_t row; + uint16_t col; + lv_res_t r = lv_table_get_pressed_cell(table, &row, &col); + if(r == LV_RES_OK && col && row) { /*Skip the first row and col*/ + if(lv_table_get_cell_type(table, row, col) == 1) { + lv_table_set_cell_type(table, row, col, 4); + } else { + lv_table_set_cell_type(table, row, col, 1); + } + } + } +} + +#if LV_USE_THEME_MATERIAL +static void color_chg_event_cb(lv_obj_t * sw, lv_event_t e) +{ + if(LV_THEME_DEFAULT_INIT != lv_theme_material_init) return; + if(e == LV_EVENT_VALUE_CHANGED) { + uint32_t flag = LV_THEME_MATERIAL_FLAG_LIGHT; + if(lv_switch_get_state(sw)) flag = LV_THEME_MATERIAL_FLAG_DARK; + + LV_THEME_DEFAULT_INIT(lv_theme_get_color_primary(), lv_theme_get_color_secondary(), + flag, + lv_theme_get_font_small(), lv_theme_get_font_normal(), lv_theme_get_font_subtitle(), lv_theme_get_font_title()); + } +} +#endif + +#if LV_DEMO_WIDGETS_SLIDESHOW + +static void tab_content_anim_create(lv_obj_t * parent) +{ + lv_anim_t a; + lv_obj_t * scrl = lv_page_get_scrl(parent); + lv_coord_t y_start = lv_obj_get_style_pad_top(parent, LV_PAGE_PART_BG); + lv_coord_t anim_h = lv_obj_get_height(scrl) - lv_obj_get_height_fit(parent); + uint32_t anim_time = lv_anim_speed_to_time(LV_DPI, 0, anim_h); + + lv_anim_init(&a); + lv_anim_set_var(&a, scrl); + lv_anim_set_exec_cb(&a, (lv_anim_exec_xcb_t)lv_obj_set_y); + lv_anim_set_values(&a, y_start, y_start - anim_h); + lv_anim_set_time(&a, anim_time); + lv_anim_set_playback_time(&a, anim_time); + lv_anim_set_playback_delay(&a, 200); + lv_anim_set_repeat_count(&a, LV_ANIM_REPEAT_INFINITE); + lv_anim_set_repeat_delay(&a, 200); + lv_anim_start(&a); +} +static void tab_changer_task_cb(lv_task_t * task) +{ + uint16_t act = lv_tabview_get_tab_act(tv); + act++; + if(act >= 3) act = 0; + + lv_tabview_set_tab_act(tv, act, LV_ANIM_ON); + + switch(act) { + case 0: + tab_content_anim_create(t1); + break; + case 1: + tab_content_anim_create(t2); + break; + case 2: + tab_content_anim_create(t3); + break; + } +} +#endif diff --git a/examples/lv_test_theme.h b/examples/lv_test_theme.h new file mode 100644 index 00000000..8517fe03 --- /dev/null +++ b/examples/lv_test_theme.h @@ -0,0 +1,44 @@ +/** + * @file lv_test_theme.h + * + */ + +#ifndef LV_TEST_THEME_H +#define LV_TEST_THEME_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include "../lvgl/lvgl.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +/** + * Create a test screen with a lot objects and apply the given theme on them + * @param th pointer to a theme + */ +void lv_demo_widgets(); + +/********************** + * MACROS + **********************/ + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /*LV_TEST_THEME_H*/ diff --git a/examples/lvgl_fs_test.c b/examples/lvgl_fs_test.c index bceebd49..a2656ad6 100644 --- a/examples/lvgl_fs_test.c +++ b/examples/lvgl_fs_test.c @@ -1,4 +1,5 @@ #include "lvgl.h" +#include long lv_tell(lv_fs_file_t *fd) { @@ -34,4 +35,4 @@ void lvgl_fs_test(void) rt_kprintf("READ(%d): %s",rsize , rbuf); lv_fs_close(&fd); -} \ No newline at end of file +} diff --git a/examples/lvgl_rtt_example.c b/examples/lvgl_rtt_example.c new file mode 100644 index 00000000..b72d7fe8 --- /dev/null +++ b/examples/lvgl_rtt_example.c @@ -0,0 +1,24 @@ +#include "lv_test_theme.h" + +#include + +static void lvgl_demo_run(void *p) +{ + lv_demo_widgets(); +} + +static int lvgl_rtt_demo_init(void) +{ + rt_thread_t thread = RT_NULL; + + /* littleGL demo gui thread */ + thread = rt_thread_create("lv_demo", lvgl_demo_run, RT_NULL, 1024 * 10, 5, 10); + if(thread == RT_NULL) + { + return RT_ERROR; + } + rt_thread_startup(thread); + + return RT_EOK; +} +INIT_APP_EXPORT(lvgl_rtt_demo_init); diff --git a/inc/lv_conf.h b/lv_conf.h similarity index 96% rename from inc/lv_conf.h rename to lv_conf.h index da494b7c..448d5ff2 100644 --- a/inc/lv_conf.h +++ b/lv_conf.h @@ -14,14 +14,19 @@ /* clang-format off */ #include +#include /*==================== Graphical settings *====================*/ /* Maximal horizontal and vertical resolution to support by the library.*/ -#define LV_HOR_RES_MAX (480) -#define LV_VER_RES_MAX (320) +#ifndef LV_HOR_RES_MAX +#define LV_HOR_RES_MAX (800) +#endif +#ifndef LV_VER_RES_MAX +#define LV_VER_RES_MAX (480) +#endif /* Color depth: * - 1: 1 byte per pixel @@ -29,7 +34,9 @@ * - 16: RGB565 * - 32: ARGB8888 */ +#ifndef LV_COLOR_DEPTH #define LV_COLOR_DEPTH 16 +#endif /* Swap the 2 bytes of RGB565 color. * Useful if the display has a 8 bit interface (e.g. SPI)*/ @@ -48,12 +55,14 @@ /* Default display refresh period. * Can be changed in the display driver (`lv_disp_drv_t`).*/ -#define LV_DISP_DEF_REFR_PERIOD 30 /*[ms]*/ +#define LV_DISP_DEF_REFR_PERIOD 20 /*[ms]*/ /* Dot Per Inch: used to initialize default sizes. * E.g. a button with width = LV_DPI / 2 -> half inch wide * (Not so important, you can adjust it to modify default sizes and spaces)*/ -#define LV_DPI 130 /*[px]*/ +#ifndef LV_DPI +#define LV_DPI 217 /*[px]*/ +#endif /* The the real width of the display changes some default values: * default object sizes, layout of examples, etc. @@ -77,7 +86,7 @@ typedef int16_t lv_coord_t; * The graphical objects and other related data are stored here. */ /* 1: use custom malloc/free, 0: use the built-in `lv_mem_alloc` and `lv_mem_free` */ -#define LV_MEM_CUSTOM 0 +#define LV_MEM_CUSTOM 1 #if LV_MEM_CUSTOM == 0 /* Size of the memory used by `lv_mem_alloc` in bytes (>= 2kB)*/ # define LV_MEM_SIZE (32U * 1024U) @@ -92,9 +101,9 @@ typedef int16_t lv_coord_t; /* Automatically defrag. on free. Defrag. means joining the adjacent free cells. */ # define LV_MEM_AUTO_DEFRAG 1 #else /*LV_MEM_CUSTOM*/ -# define LV_MEM_CUSTOM_INCLUDE /*Header for the dynamic memory function*/ -# define LV_MEM_CUSTOM_ALLOC malloc /*Wrapper to malloc*/ -# define LV_MEM_CUSTOM_FREE free /*Wrapper to free*/ +# define LV_MEM_CUSTOM_INCLUDE /*Header for the dynamic memory function*/ +# define LV_MEM_CUSTOM_ALLOC rt_malloc /*Wrapper to malloc*/ +# define LV_MEM_CUSTOM_FREE rt_free /*Wrapper to free*/ #endif /*LV_MEM_CUSTOM*/ /* Use the standard memcpy and memset instead of LVGL's own functions. @@ -189,11 +198,11 @@ typedef void * lv_group_user_data_t; #endif /*LV_USE_GROUP*/ /* 1: Enable GPU interface*/ -#define LV_USE_GPU 1 /*Only enables `gpu_fill_cb` and `gpu_blend_cb` in the disp. drv- */ +#define LV_USE_GPU 0 /*Only enables `gpu_fill_cb` and `gpu_blend_cb` in the disp. drv- */ #define LV_USE_GPU_STM32_DMA2D 0 /*If enabling LV_USE_GPU_STM32_DMA2D, LV_GPU_DMA2D_CMSIS_INCLUDE must be defined to include path of CMSIS header of target processor e.g. "stm32f769xx.h" or "stm32f429xx.h" */ -#define LV_GPU_DMA2D_CMSIS_INCLUDE +#define LV_GPU_DMA2D_CMSIS_INCLUDE /*1: Use PXP for CPU off-load on NXP RTxxx platforms */ #define LV_USE_GPU_NXP_PXP 0 @@ -209,7 +218,9 @@ e.g. "stm32f769xx.h" or "stm32f429xx.h" */ #define LV_USE_GPU_NXP_VG_LITE 0 /* 1: Enable file system (might be required for images */ +#ifndef LV_USE_FILESYSTEM #define LV_USE_FILESYSTEM 1 +#endif #if LV_USE_FILESYSTEM /*Declare the type of the user data of file system drivers (can be e.g. `void *`, `int`, `struct`)*/ typedef void * lv_fs_drv_user_data_t; @@ -219,7 +230,9 @@ typedef void * lv_fs_drv_user_data_t; #define LV_USE_USER_DATA 0 /*1: Show CPU usage and FPS count in the right bottom corner*/ -#define LV_USE_PERF_MONITOR 0 +#ifndef LV_USE_PERF_MONITOR +#define LV_USE_PERF_MONITOR 1 +#endif /*1: Use the functions and types from the older API if possible */ #define LV_USE_API_EXTENSION_V6 1 @@ -298,10 +311,10 @@ typedef void * lv_img_decoder_user_data_t; /* 1: use a custom tick source. * It removes the need to manually update the tick with `lv_tick_inc`) */ -#define LV_TICK_CUSTOM 0 +#define LV_TICK_CUSTOM 1 #if LV_TICK_CUSTOM == 1 -#define LV_TICK_CUSTOM_INCLUDE "Arduino.h" /*Header for the system time function*/ -#define LV_TICK_CUSTOM_SYS_TIME_EXPR (millis()) /*Expression evaluating to current system time in ms*/ +#define LV_TICK_CUSTOM_INCLUDE /*Header for the system time function*/ +#define LV_TICK_CUSTOM_SYS_TIME_EXPR (rt_tick_get()) /*Expression evaluating to current system time in ms*/ #endif /*LV_TICK_CUSTOM*/ typedef void * lv_disp_drv_user_data_t; /*Type of user data in the display driver*/ diff --git a/lvgl/SConscript b/lvgl/SConscript new file mode 100644 index 00000000..785f4e2a --- /dev/null +++ b/lvgl/SConscript @@ -0,0 +1,27 @@ +import os +from building import * +import rtconfig + +cwd = GetCurrentDir() + +src = [] + +src += Glob('./src/lv_core/*.c') +src += Glob('./src/lv_draw/*.c') +src += Glob('./src/lv_font/*.c') +src += Glob('./src/lv_gpu/*.c') +src += Glob('./src/lv_hal/*.c') +src += Glob('./src/lv_misc/*.c') +src += Glob('./src/lv_themes/*.c') +src += Glob('./src/lv_widgets/*.c') + +CCFLAGS = '' + +if rtconfig.CROSS_TOOL == 'gcc': + CCFLAGS += ' -std=c99 -w' +elif rtconfig.CROSS_TOOL == 'keil': + CCFLAGS += ' --c99 --gnu -g -W' + +group = DefineGroup('lvgl', src, depend = ['PKG_USING_LVGL_RTT'], CCFLAGS = CCFLAGS) + +Return('group') \ No newline at end of file diff --git a/lvgl/src/lv_gpu/lv_gpu_stm32_dma2d.c b/lvgl/src/lv_gpu/lv_gpu_stm32_dma2d.c index d94e87ab..685c2921 100644 --- a/lvgl/src/lv_gpu/lv_gpu_stm32_dma2d.c +++ b/lvgl/src/lv_gpu/lv_gpu_stm32_dma2d.c @@ -76,6 +76,7 @@ void lv_gpu_stm32_dma2d_init(void) /* Delay after setting peripheral clock */ volatile uint32_t temp = RCC->AHB1ENR; + (void)temp; /* set output colour mode */ DMA2D->OPFCCR = LV_DMA2D_COLOR_FORMAT; diff --git a/port/SConscript b/port/SConscript new file mode 100644 index 00000000..328d06fb --- /dev/null +++ b/port/SConscript @@ -0,0 +1,8 @@ +from building import * + +cwd = GetCurrentDir() +src = Glob('*.c') + +group = DefineGroup('lvgl_rtt_port', src, depend = ['PKG_USING_LVGL_RTT']) + +Return('group') \ No newline at end of file diff --git a/port/lv_port_disp.c b/port/lv_port_disp.c index 7bb9c3d7..95e0b4f5 100644 --- a/port/lv_port_disp.c +++ b/port/lv_port_disp.c @@ -4,17 +4,30 @@ */ /*Copy this file as "lv_port_disp.c" and set this value to "1" to enable content*/ -#if 0 +#if 1 /********************* * INCLUDES *********************/ -#include "lv_port_disp_template.h" +#include "lv_port_disp.h" +#if LV_USE_GPU_STM32_DMA2D + #include "../lvgl/src/lv_gpu/lv_gpu_stm32_dma2d.h" +#endif + +#include +#include +#include +#if defined BSP_USING_LCD +#include "lcd_port.h" +#elif #error "ART-PI not select BSP_USING_LCD" +#endif /********************* * DEFINES *********************/ - +#ifdef LV_USE_AXI_SRAM +#define DISPLAY_BUFFER_LINES 40 // 缓存的行数 +#endif /********************** * TYPEDEFS **********************/ @@ -25,6 +38,11 @@ static void disp_init(void); static void disp_flush(lv_disp_drv_t * disp_drv, const lv_area_t * area, lv_color_t * color_p); + +#if LV_USE_GPU_STM32_DMA2D +static void disp_wait_cb(struct _disp_drv_t * disp_drv); +#endif + #if LV_USE_GPU static void gpu_blend(lv_disp_drv_t * disp_drv, lv_color_t * dest, const lv_color_t * src, uint32_t length, lv_opa_t opa); static void gpu_fill(lv_disp_drv_t * disp_drv, lv_color_t * dest_buf, lv_coord_t dest_width, @@ -34,7 +52,7 @@ static void gpu_fill(lv_disp_drv_t * disp_drv, lv_color_t * dest_buf, lv_coord_t /********************** * STATIC VARIABLES **********************/ - +static struct drv_lcd_device *lcd; /********************** * MACROS **********************/ @@ -73,24 +91,17 @@ void lv_port_disp_init(void) * whole frame to display. This way you only need to change the frame buffer's address instead of * copying the pixels. * */ - - /* Example for 1) */ - static lv_disp_buf_t draw_buf_dsc_1; - static lv_color_t draw_buf_1[LV_HOR_RES_MAX * 10]; /*A buffer for 10 rows*/ - lv_disp_buf_init(&draw_buf_dsc_1, draw_buf_1, NULL, LV_HOR_RES_MAX * 10); /*Initialize the display buffer*/ - - /* Example for 2) */ - static lv_disp_buf_t draw_buf_dsc_2; - static lv_color_t draw_buf_2_1[LV_HOR_RES_MAX * 10]; /*A buffer for 10 rows*/ - static lv_color_t draw_buf_2_1[LV_HOR_RES_MAX * 10]; /*An other buffer for 10 rows*/ - lv_disp_buf_init(&draw_buf_dsc_2, draw_buf_2_1, draw_buf_2_1, LV_HOR_RES_MAX * 10); /*Initialize the display buffer*/ - - /* Example for 3) */ - static lv_disp_buf_t draw_buf_dsc_3; - static lv_color_t draw_buf_3_1[LV_HOR_RES_MAX * LV_VER_RES_MAX]; /*A screen sized buffer*/ - static lv_color_t draw_buf_3_1[LV_HOR_RES_MAX * LV_VER_RES_MAX]; /*An other screen sized buffer*/ - lv_disp_buf_init(&draw_buf_dsc_3, draw_buf_3_1, draw_buf_3_2, LV_HOR_RES_MAX * LV_VER_RES_MAX); /*Initialize the display buffer*/ - + static lv_disp_buf_t draw_buf_dsc; + +#ifdef LV_USE_AXI_SRAM + static lv_color_t draw_buf_1[LV_HOR_RES_MAX * DISPLAY_BUFFER_LINES]; /*A buffer for 40 rows in AXI SRAM*/ + static lv_color_t draw_buf_2[LV_HOR_RES_MAX * DISPLAY_BUFFER_LINES]; /*An other buffer for 40 rows in AXI SRAM*/ + lv_disp_buf_init(&draw_buf_dsc, draw_buf_1, draw_buf_2, LV_HOR_RES_MAX * DISPLAY_BUFFER_LINES); /*Initialize the display buffer*/ +#else + lv_color_t *draw_buf_1 = (lv_color_t *)rt_malloc(LV_HOR_RES_MAX * LV_VER_RES_MAX * sizeof(lv_color_t)); + lv_color_t *draw_buf_2 = (lv_color_t *)rt_malloc(LV_HOR_RES_MAX * LV_VER_RES_MAX * sizeof(lv_color_t)); + lv_disp_buf_init(&draw_buf_dsc, draw_buf_1, draw_buf_2, LV_HOR_RES_MAX * LV_VER_RES_MAX); +#endif /*----------------------------------- * Register the display in LVGL @@ -102,25 +113,19 @@ void lv_port_disp_init(void) /*Set up the functions to access to your display*/ /*Set the resolution of the display*/ - disp_drv.hor_res = 480; - disp_drv.ver_res = 320; + disp_drv.hor_res = lcd->lcd_info.width; + disp_drv.ver_res = lcd->lcd_info.height; /*Used to copy the buffer's content to the display*/ disp_drv.flush_cb = disp_flush; - /*Set a display buffer*/ - disp_drv.buffer = &draw_buf_dsc_1; - -#if LV_USE_GPU - /*Optionally add functions to access the GPU. (Only in buffered mode, LV_VDB_SIZE != 0)*/ - - /*Blend two color array using opacity*/ - disp_drv.gpu_blend_cb = gpu_blend; - - /*Fill a memory array with a color*/ - disp_drv.gpu_fill_cb = gpu_fill; +#if LV_USE_GPU_STM32_DMA2D + disp_drv.wait_cb = disp_wait_cb; #endif + /*Set a display buffer*/ + disp_drv.buffer = &draw_buf_dsc; + /*Finally register the driver*/ lv_disp_drv_register(&disp_drv); } @@ -133,63 +138,120 @@ void lv_port_disp_init(void) static void disp_init(void) { /*You code here*/ + rt_err_t ret; + lcd = (struct drv_lcd_device *)rt_device_find("lcd"); + RT_ASSERT(lcd); + + ret = rt_device_open((rt_device_t)lcd, RT_DEVICE_FLAG_RDWR); + RT_ASSERT(ret == RT_EOK); + +#if LV_USE_GPU_STM32_DMA2D + lv_gpu_stm32_dma2d_init(); +#elif LV_USE_CUSTOM_DMA2D + __HAL_RCC_DMA2D_CLK_ENABLE(); + NVIC_EnableIRQ(DMA2D_IRQn); +#endif } /* Flush the content of the internal buffer the specific area on the display * You can use DMA or any hardware acceleration to do this operation in the background but * 'lv_disp_flush_ready()' has to be called when finished. */ +#if LV_USE_CUSTOM_DMA2D == 0 static void disp_flush(lv_disp_drv_t * disp_drv, const lv_area_t * area, lv_color_t * color_p) { /*The most simple case (but also the slowest) to put all pixels to the screen one-by-one*/ + lv_color_t *buf = (lv_color_t *)lcd->front_buf; + +#if LV_USE_GPU_STM32_DMA2D + buf = buf + area->y1 * disp_drv->hor_res + area->x1; + lv_coord_t w = (area->x2 - area->x1 + 1); + lv_coord_t h = (area->y2 - area->y1 + 1); + lv_gpu_stm32_dma2d_copy(buf, disp_drv->hor_res, color_p, w, w, h); +#else int32_t x; int32_t y; for(y = area->y1; y <= area->y2; y++) { for(x = area->x1; x <= area->x2; x++) { - /* Put a pixel to the display. For example: */ - /* put_px(x, y, *color_p)*/ + *(buf + y*disp_drv->hor_res + x) = *color_p; color_p++; } } +#endif /* IMPORTANT!!! * Inform the graphics library that you are ready with the flushing*/ lv_disp_flush_ready(disp_drv); } +#else +DMA2D_HandleTypeDef hdma2d; +static lv_disp_drv_t *disp_drv_p; +static void disp_flush(lv_disp_drv_t *disp_drv, const lv_area_t *area, lv_color_t *color_p) +{ + /*The most simple case (but also the slowest) to put all pixels to the screen one-by-one*/ + uint8_t *p = (uint8_t *)lcd->front_buf; + + int16_t w = (area->x2 - area->x1 + 1); + int16_t h = (area->y2 - area->y1 + 1); + + disp_drv_p = disp_drv; + /*##-1- Configure the DMA2D Mode, Color Mode and output offset #############*/ + hdma2d.Init.Mode = DMA2D_M2M; + hdma2d.Init.ColorMode = DMA2D_OUTPUT_RGB565; + hdma2d.Init.OutputOffset = (LV_HOR_RES_MAX - w); + + /*##-3- Foreground Configuration ###########################################*/ + hdma2d.LayerCfg[1].AlphaMode = DMA2D_NO_MODIF_ALPHA; + hdma2d.LayerCfg[1].InputAlpha = 0xFF; + hdma2d.LayerCfg[1].InputColorMode = DMA2D_INPUT_RGB565 ; + hdma2d.LayerCfg[1].InputOffset = 0; + + hdma2d.Instance = DMA2D; + + /*##-4- DMA2D Initialization ###############################################*/ + if (HAL_DMA2D_Init(&hdma2d) != HAL_OK) + { + /* Initialization Error */ + Error_Handler(); + } + if (HAL_DMA2D_ConfigLayer(&hdma2d, 1) != HAL_OK) + { + /* Initialization Error */ + Error_Handler(); + } -/*OPTIONAL: GPU INTERFACE*/ -#if LV_USE_GPU + /*##-5- Start DMA2D transfer ###############################################*/ -/* If your MCU has hardware accelerator (GPU) then you can use it to blend to memories using opacity - * It can be used only in buffered mode (LV_VDB_SIZE != 0 in lv_conf.h)*/ -static void gpu_blend(lv_disp_drv_t * disp_drv, lv_color_t * dest, const lv_color_t * src, uint32_t length, lv_opa_t opa) -{ - /*It's an example code which should be done by your GPU*/ - uint32_t i; - for(i = 0; i < length; i++) { - dest[i] = lv_color_mix(dest[i], src[i], opa); + if (HAL_DMA2D_Start_IT(&hdma2d, (uint32_t)color_p, (uint32_t)(p) + 2 * (LV_HOR_RES_MAX * area->y1 + area->x1), w, h) != HAL_OK) + { + /* Initialization Error */ + Error_Handler(); } } - -/* If your MCU has hardware accelerator (GPU) then you can use it to fill a memory with a color - * It can be used only in buffered mode (LV_VDB_SIZE != 0 in lv_conf.h)*/ -static void gpu_fill(lv_disp_drv_t * disp_drv, lv_color_t * dest_buf, lv_coord_t dest_width, - const lv_area_t * fill_area, lv_color_t color) +void DMA2D_IRQHandler(void) { - /*It's an example code which should be done by your GPU*/ - int32_t x, y; - dest_buf += dest_width * fill_area->y1; /*Go to the first line*/ - - for(y = fill_area->y1; y <= fill_area->y2; y++) { - for(x = fill_area->x1; x <= fill_area->x2; x++) { - dest_buf[x] = color; - } - dest_buf+=dest_width; /*Go to the next line*/ - } + rt_enter_critical(); + /* USER CODE BEGIN DMA2D_IRQn 0 */ + lv_disp_flush_ready(disp_drv_p); + /* USER CODE END DMA2D_IRQn 0 */ + HAL_DMA2D_IRQHandler(&hdma2d); + /* USER CODE BEGIN DMA2D_IRQn 1 */ + + /* USER CODE END DMA2D_IRQn 1 */ + rt_exit_critical(); } +#endif -#endif /*LV_USE_GPU*/ +#if LV_USE_GPU_STM32_DMA2D +/** OPTIONAL: Called periodically while lvgl waits for operation to be completed. + * For example flushing or GPU + * User can execute very simple tasks here or yield the task */ +static void disp_wait_cb(struct _disp_drv_t * disp_drv) +{ + rt_thread_mdelay(1); +} +#endif #else /* Enable this file at the top */ diff --git a/port/lv_port_disp.h b/port/lv_port_disp.h index eeca802b..41408524 100644 --- a/port/lv_port_disp.h +++ b/port/lv_port_disp.h @@ -4,7 +4,7 @@ */ /*Copy this file as "lv_port_disp.h" and set this value to "1" to enable content*/ -#if 0 +#if 1 #ifndef LV_PORT_DISP_TEMPL_H #define LV_PORT_DISP_TEMPL_H @@ -16,7 +16,7 @@ extern "C" { /********************* * INCLUDES *********************/ -#include "lvgl/lvgl.h" +#include "lvgl.h" /********************* * DEFINES @@ -29,7 +29,7 @@ extern "C" { /********************** * GLOBAL PROTOTYPES **********************/ - +void lv_port_disp_init(void); /********************** * MACROS **********************/ diff --git a/port/lv_port_fs.c b/port/lv_port_fs.c index e39cefac..9c0e98a1 100644 --- a/port/lv_port_fs.c +++ b/port/lv_port_fs.c @@ -2,9 +2,9 @@ * @file lv_port_fs_templ.c * */ - +#include "lv_conf.h" /*Copy this file as "lv_port_fs.c" and set this value to "1" to enable content*/ -#if 1 +#if LV_USE_FILESYSTEM /********************* * INCLUDES @@ -202,51 +202,6 @@ static lv_fs_res_t fs_tell (lv_fs_drv_t * drv, void * file_p, uint32_t * pos_p) return res; } -///** -// * Initialize a 'fs_read_dir_t' variable for directory reading -// * @param rddir_p pointer to a 'fs_read_dir_t' variable -// * @param path path to a directory -// * @return LV_FS_RES_OK or any error from lv_fs_res_t enum -// */ -//static lv_fs_res_t fs_dir_open (lv_fs_drv_t * drv, void * rddir_p, const char *path) -//{ -// lv_fs_res_t res = LV_FS_RES_NOT_IMP; -// -// /* Add your code here*/ -// -// return res; -//} -// -///** -// * Read the next filename form a directory. -// * The name of the directories will begin with '/' -// * @param rddir_p pointer to an initialized 'fs_read_dir_t' variable -// * @param fn pointer to a buffer to store the filename -// * @return LV_FS_RES_OK or any error from lv_fs_res_t enum -// */ -//static lv_fs_res_t fs_dir_read (lv_fs_drv_t * drv, void * rddir_p, char *fn) -//{ -// lv_fs_res_t res = LV_FS_RES_NOT_IMP; -// -// /* Add your code here*/ -// -// return res; -//} -// -///** -// * Close the directory reading -// * @param rddir_p pointer to an initialized 'fs_read_dir_t' variable -// * @return LV_FS_RES_OK or any error from lv_fs_res_t enum -// */ -//static lv_fs_res_t fs_dir_close (lv_fs_drv_t * drv, void * rddir_p) -//{ -// lv_fs_res_t res = LV_FS_RES_NOT_IMP; -// -// /* Add your code here*/ -// -// return res; -//} - #else /* Enable this file at the top */ /* This dummy typedef exists purely to silence -Wpedantic. */ diff --git a/port/lv_port_fs.h b/port/lv_port_fs.h index efeb99ef..2c2e95af 100644 --- a/port/lv_port_fs.h +++ b/port/lv_port_fs.h @@ -29,7 +29,7 @@ extern "C" { /********************** * GLOBAL PROTOTYPES **********************/ - +int lv_port_fs_init(void); /********************** * MACROS **********************/ diff --git a/port/lv_port_indev.c b/port/lv_port_indev.c index 1910b74e..5e27df7f 100644 --- a/port/lv_port_indev.c +++ b/port/lv_port_indev.c @@ -2,69 +2,26 @@ * @file lv_port_indev_templ.c * */ - +#include "lv_conf.h" /*Copy this file as "lv_port_indev.c" and set this value to "1" to enable content*/ -#if 0 +#if LV_USE_INDEV /********************* * INCLUDES *********************/ -#include "lv_port_indev_template.h" +#include "lv_port_indev.h" -/********************* - * DEFINES - *********************/ -/********************** - * TYPEDEFS - **********************/ - -/********************** - * STATIC PROTOTYPES - **********************/ +#ifdef LV_USE_TOUCH +#include static void touchpad_init(void); static bool touchpad_read(lv_indev_drv_t * indev_drv, lv_indev_data_t * data); -static bool touchpad_is_pressed(void); -static void touchpad_get_xy(lv_coord_t * x, lv_coord_t * y); - -static void mouse_init(void); -static bool mouse_read(lv_indev_drv_t * indev_drv, lv_indev_data_t * data); -static bool mouse_is_pressed(void); -static void mouse_get_xy(lv_coord_t * x, lv_coord_t * y); - -static void keypad_init(void); -static bool keypad_read(lv_indev_drv_t * indev_drv, lv_indev_data_t * data); -static uint32_t keypad_get_key(void); - -static void encoder_init(void); -static bool encoder_read(lv_indev_drv_t * indev_drv, lv_indev_data_t * data); -static void encoder_handler(void); -static void button_init(void); -static bool button_read(lv_indev_drv_t * indev_drv, lv_indev_data_t * data); -static int8_t button_get_pressed_id(void); -static bool button_is_pressed(uint8_t id); +static rt_device_t touch_dev; +#endif /* LV_USE_TOUCH */ -/********************** - * STATIC VARIABLES - **********************/ -lv_indev_t * indev_touchpad; -lv_indev_t * indev_mouse; -lv_indev_t * indev_keypad; -lv_indev_t * indev_encoder; -lv_indev_t * indev_button; - -static int32_t encoder_diff; -static lv_indev_state_t encoder_state; -/********************** - * MACROS - **********************/ - -/********************** - * GLOBAL FUNCTIONS - **********************/ void lv_port_indev_init(void) { @@ -85,7 +42,7 @@ void lv_port_indev_init(void) /*------------------ * Touchpad * -----------------*/ - +#ifdef LV_USE_TOUCH /*Initialize your touchpad if you have*/ touchpad_init(); @@ -93,81 +50,9 @@ void lv_port_indev_init(void) lv_indev_drv_init(&indev_drv); indev_drv.type = LV_INDEV_TYPE_POINTER; indev_drv.read_cb = touchpad_read; - indev_touchpad = lv_indev_drv_register(&indev_drv); - - /*------------------ - * Mouse - * -----------------*/ - - /*Initialize your touchpad if you have*/ - mouse_init(); - - /*Register a mouse input device*/ - lv_indev_drv_init(&indev_drv); - indev_drv.type = LV_INDEV_TYPE_POINTER; - indev_drv.read_cb = mouse_read; - indev_mouse = lv_indev_drv_register(&indev_drv); - - /*Set cursor. For simplicity set a HOME symbol now.*/ - lv_obj_t * mouse_cursor = lv_img_create(lv_disp_get_scr_act(NULL), NULL); - lv_img_set_src(mouse_cursor, LV_SYMBOL_HOME); - lv_indev_set_cursor(indev_mouse, mouse_cursor); - - /*------------------ - * Keypad - * -----------------*/ - - /*Initialize your keypad or keyboard if you have*/ - keypad_init(); - - /*Register a keypad input device*/ - lv_indev_drv_init(&indev_drv); - indev_drv.type = LV_INDEV_TYPE_KEYPAD; - indev_drv.read_cb = keypad_read; - indev_keypad = lv_indev_drv_register(&indev_drv); - - /* Later you should create group(s) with `lv_group_t * group = lv_group_create()`, - * add objects to the group with `lv_group_add_obj(group, obj)` - * and assign this input device to group to navigate in it: - * `lv_indev_set_group(indev_keypad, group);` */ - - /*------------------ - * Encoder - * -----------------*/ - - /*Initialize your encoder if you have*/ - encoder_init(); - - /*Register a encoder input device*/ - lv_indev_drv_init(&indev_drv); - indev_drv.type = LV_INDEV_TYPE_ENCODER; - indev_drv.read_cb = encoder_read; - indev_encoder = lv_indev_drv_register(&indev_drv); - - /* Later you should create group(s) with `lv_group_t * group = lv_group_create()`, - * add objects to the group with `lv_group_add_obj(group, obj)` - * and assign this input device to group to navigate in it: - * `lv_indev_set_group(indev_encoder, group);` */ + lv_indev_drv_register(&indev_drv); +#endif /* LV_USE_TOUCH */ - /*------------------ - * Button - * -----------------*/ - - /*Initialize your button if you have*/ - button_init(); - - /*Register a button input device*/ - lv_indev_drv_init(&indev_drv); - indev_drv.type = LV_INDEV_TYPE_BUTTON; - indev_drv.read_cb = button_read; - indev_button = lv_indev_drv_register(&indev_drv); - - /*Assign buttons to points on the screen*/ - static const lv_point_t btn_points[2] = { - {10, 10}, /*Button 0 -> x:10; y:10*/ - {40, 100}, /*Button 1 -> x:40; y:100*/ - }; - lv_indev_set_button_points(indev_button, btn_points); } /********************** @@ -175,7 +60,7 @@ void lv_port_indev_init(void) **********************/ - +#ifdef LV_USE_TOUCH /*------------------ * Touchpad * -----------------*/ @@ -184,6 +69,9 @@ void lv_port_indev_init(void) static void touchpad_init(void) { /*Your code comes here*/ + touch_dev = rt_device_find(LV_TOUCH_NAME); + RT_ASSERT(touch_dev != RT_NULL); + rt_device_open(touch_dev, RT_DEVICE_FLAG_RDONLY); } /* Will be called by the library to read the touchpad */ @@ -193,8 +81,10 @@ static bool touchpad_read(lv_indev_drv_t * indev_drv, lv_indev_data_t * data) static lv_coord_t last_y = 0; /*Save the pressed coordinates and the state*/ - if(touchpad_is_pressed()) { - touchpad_get_xy(&last_x, &last_y); + struct rt_touch_data touch_data; + if (rt_device_read(touch_dev, 0, &touch_data, 1) == 1) { + last_x = touch_data.x_coordinate; + last_y = touch_data.y_coordinate; data->state = LV_INDEV_STATE_PR; } else { data->state = LV_INDEV_STATE_REL; @@ -207,221 +97,9 @@ static bool touchpad_read(lv_indev_drv_t * indev_drv, lv_indev_data_t * data) /*Return `false` because we are not buffering and no more data to read*/ return false; } +#endif /* LV_USE_TOUCH */ -/*Return true is the touchpad is pressed*/ -static bool touchpad_is_pressed(void) -{ - /*Your code comes here*/ - - return false; -} - -/*Get the x and y coordinates if the touchpad is pressed*/ -static void touchpad_get_xy(lv_coord_t * x, lv_coord_t * y) -{ - /*Your code comes here*/ - - (*x) = 0; - (*y) = 0; -} - - -/*------------------ - * Mouse - * -----------------*/ - -/* Initialize your mouse */ -static void mouse_init(void) -{ - /*Your code comes here*/ -} - -/* Will be called by the library to read the mouse */ -static bool mouse_read(lv_indev_drv_t * indev_drv, lv_indev_data_t * data) -{ - /*Get the current x and y coordinates*/ - mouse_get_xy(&data->point.x, &data->point.y); - - /*Get whether the mouse button is pressed or released*/ - if(mouse_is_pressed()) { - data->state = LV_INDEV_STATE_PR; - } else { - data->state = LV_INDEV_STATE_REL; - } - - /*Return `false` because we are not buffering and no more data to read*/ - return false; -} - -/*Return true is the mouse button is pressed*/ -static bool mouse_is_pressed(void) -{ - /*Your code comes here*/ - - return false; -} - -/*Get the x and y coordinates if the mouse is pressed*/ -static void mouse_get_xy(lv_coord_t * x, lv_coord_t * y) -{ - /*Your code comes here*/ - - (*x) = 0; - (*y) = 0; -} - -/*------------------ - * Keypad - * -----------------*/ - -/* Initialize your keypad */ -static void keypad_init(void) -{ - /*Your code comes here*/ -} - -/* Will be called by the library to read the mouse */ -static bool keypad_read(lv_indev_drv_t * indev_drv, lv_indev_data_t * data) -{ - static uint32_t last_key = 0; - - /*Get the current x and y coordinates*/ - mouse_get_xy(&data->point.x, &data->point.y); - - /*Get whether the a key is pressed and save the pressed key*/ - uint32_t act_key = keypad_get_key(); - if(act_key != 0) { - data->state = LV_INDEV_STATE_PR; - - /*Translate the keys to LVGL control characters according to your key definitions*/ - switch(act_key) { - case 1: - act_key = LV_KEY_NEXT; - break; - case 2: - act_key = LV_KEY_PREV; - break; - case 3: - act_key = LV_KEY_LEFT; - break; - case 4: - act_key = LV_KEY_RIGHT; - break; - case 5: - act_key = LV_KEY_ENTER; - break; - } - - last_key = act_key; - } else { - data->state = LV_INDEV_STATE_REL; - } - - data->key = last_key; - - /*Return `false` because we are not buffering and no more data to read*/ - return false; -} - -/*Get the currently being pressed key. 0 if no key is pressed*/ -static uint32_t keypad_get_key(void) -{ - /*Your code comes here*/ - - return 0; -} - -/*------------------ - * Encoder - * -----------------*/ - -/* Initialize your keypad */ -static void encoder_init(void) -{ - /*Your code comes here*/ -} - -/* Will be called by the library to read the encoder */ -static bool encoder_read(lv_indev_drv_t * indev_drv, lv_indev_data_t * data) -{ - - data->enc_diff = encoder_diff; - data->state = encoder_state; - - /*Return `false` because we are not buffering and no more data to read*/ - return false; -} - -/*Call this function in an interrupt to process encoder events (turn, press)*/ -static void encoder_handler(void) -{ - /*Your code comes here*/ - - encoder_diff += 0; - encoder_state = LV_INDEV_STATE_REL; -} - - -/*------------------ - * Button - * -----------------*/ - -/* Initialize your buttons */ -static void button_init(void) -{ - /*Your code comes here*/ -} - -/* Will be called by the library to read the button */ -static bool button_read(lv_indev_drv_t * indev_drv, lv_indev_data_t * data) -{ - - static uint8_t last_btn = 0; - - /*Get the pressed button's ID*/ - int8_t btn_act = button_get_pressed_id(); - - if(btn_act >= 0) { - data->state = LV_INDEV_STATE_PR; - last_btn = btn_act; - } else { - data->state = LV_INDEV_STATE_REL; - } - - /*Save the last pressed button's ID*/ - data->btn_id = last_btn; - - /*Return `false` because we are not buffering and no more data to read*/ - return false; -} - -/*Get ID (0, 1, 2 ..) of the pressed button*/ -static int8_t button_get_pressed_id(void) -{ - uint8_t i; - - /*Check to buttons see which is being pressed (assume there are 2 buttons)*/ - for(i = 0; i < 2; i++) { - /*Return the pressed button's ID*/ - if(button_is_pressed(i)) { - return i; - } - } - - /*No button pressed*/ - return -1; -} - -/*Test if `id` button is pressed or not*/ -static bool button_is_pressed(uint8_t id) -{ - - /*Your code comes here*/ - - return false; -} - -#else /* Enable this file at the top */ +#else /* LV_USE_INDEV */ /* This dummy typedef exists purely to silence -Wpedantic. */ typedef int keep_pedantic_happy; diff --git a/port/lv_port_indev.h b/port/lv_port_indev.h index ca0274e8..b39c38f7 100644 --- a/port/lv_port_indev.h +++ b/port/lv_port_indev.h @@ -5,7 +5,7 @@ */ /*Copy this file as "lv_port_indev.h" and set this value to "1" to enable content*/ -#if 0 +#if 1 #ifndef LV_PORT_INDEV_TEMPL_H #define LV_PORT_INDEV_TEMPL_H @@ -17,7 +17,7 @@ extern "C" { /********************* * INCLUDES *********************/ -#include "lvgl/lvgl.h" +#include "lvgl.h" /********************* * DEFINES @@ -30,7 +30,7 @@ extern "C" { /********************** * GLOBAL PROTOTYPES **********************/ - +void lv_port_indev_init(void); /********************** * MACROS **********************/ diff --git a/port/lvgl_rtt_port.c b/port/lvgl_rtt_port.c new file mode 100644 index 00000000..f69439ad --- /dev/null +++ b/port/lvgl_rtt_port.c @@ -0,0 +1,69 @@ +#include "lvgl.h" +#include "lv_port_disp.h" +#include "lv_port_indev.h" +#include "lv_port_fs.h" + +#include + +/* not needed, define LV_TICK_CUSTOM in lv_conf.h +#define LVGL_TICK_INTERVAL 5 + +static void lvgl_tick(void *args) +{ + lv_tick_inc(LVGL_TICK_INTERVAL); +} + +static void lvgl_tick_init(void) +{ + rt_timer_t lv_timer = rt_timer_create("lvgl.timer", lvgl_tick, RT_NULL, LVGL_TICK_INTERVAL, RT_IPC_FLAG_FIFO); + if (lv_timer == RT_NULL) + return ; + + rt_timer_start(lv_timer); +} + */ + +static void lvgl_task(void *args) +{ + while (1) + { + rt_thread_mdelay(10); + lv_task_handler(); + } +} + +static int lvgl_task_init(void) +{ + rt_err_t ret = RT_EOK; + rt_thread_t tid = RT_NULL; + + /* littleGL demo gui thread */ + tid = rt_thread_create("lvgl.task", lvgl_task, RT_NULL, 1024 * 6, 5, 10); + if (tid == RT_NULL) + { + return RT_ERROR; + } + ret = rt_thread_startup(tid); + + return ret; +} + +static int lvgl_rtt_port_init(void) +{ + lv_init(); + lv_port_disp_init(); + +#if LV_USE_INDEV + lv_port_indev_init(); +#endif + +#if LV_USE_FILESYSTEM + lv_port_fs_init(); +#endif + + lvgl_task_init(); + // lvgl_tick_init(); // not needed, define LV_TICK_CUSTOM in lv_conf.h + + return RT_EOK; +} +INIT_APP_EXPORT(lvgl_rtt_port_init);