diff options
| author | jacqueline <me@jacqueline.id.au> | 2023-06-01 15:41:47 +1000 |
|---|---|---|
| committer | jacqueline <me@jacqueline.id.au> | 2023-06-01 15:41:47 +1000 |
| commit | dd27c3530432ea0b09f01e604bf577f31d8ef841 (patch) | |
| tree | bbf86cf81a78f0ff0b07f31f1c390db473f26fd3 /lib/lvgl/examples/widgets/chart | |
| parent | 6fd588e970470b15936187980829916d0dbe77bb (diff) | |
| download | tangara-fw-dd27c3530432ea0b09f01e604bf577f31d8ef841.tar.gz | |
convert lvgl from submodule to a plain old directory
Diffstat (limited to 'lib/lvgl/examples/widgets/chart')
20 files changed, 1450 insertions, 0 deletions
diff --git a/lib/lvgl b/lib/lvgl deleted file mode 160000 -Subproject 0732400e7b564dd0e7dc4a924619d8e19c5b23a diff --git a/lib/lvgl/examples/widgets/chart/index.rst b/lib/lvgl/examples/widgets/chart/index.rst new file mode 100644 index 00000000..d07f0969 --- /dev/null +++ b/lib/lvgl/examples/widgets/chart/index.rst @@ -0,0 +1,49 @@ + +Line Chart +"""""""""" + +.. lv_example:: widgets/chart/lv_example_chart_1 + :language: c + + +Faded area line chart with custom division lines +""""""""""""""""""""""""""""""""""""""""""""""""""" + +.. lv_example:: widgets/chart/lv_example_chart_2 + :language: c + +Axis ticks and labels with scrolling +"""""""""""""""""""""""""""""""""""" + +.. lv_example:: widgets/chart/lv_example_chart_3 + :language: c + +Show the value of the pressed points +"""""""""""""""""""""""""""""""""""""" + +.. lv_example:: widgets/chart/lv_example_chart_4 + :language: c + +Display 1000 data points with zooming and scrolling +"""""""""""""""""""""""""""""""""""""""""""""""""""" + +.. lv_example:: widgets/chart/lv_example_chart_5 + :language: c + +Show cursor on the clicked point +""""""""""""""""""""""""""""""""""" + +.. lv_example:: widgets/chart/lv_example_chart_6 + :language: c + +Scatter chart +""""""""""""""""""""""""""""""""""" + +.. lv_example:: widgets/chart/lv_example_chart_7 + :language: c + +Stacked area chart +""""""""""""""""""""""""""""""""""" + +.. lv_example:: widgets/chart/lv_example_chart_8 + :language: diff --git a/lib/lvgl/examples/widgets/chart/lv_example_chart_1.c b/lib/lvgl/examples/widgets/chart/lv_example_chart_1.c new file mode 100644 index 00000000..a946e188 --- /dev/null +++ b/lib/lvgl/examples/widgets/chart/lv_example_chart_1.c @@ -0,0 +1,44 @@ +#include "../../lv_examples.h" +#if LV_USE_CHART && LV_BUILD_EXAMPLES + +void lv_example_chart_1(void) +{ + /*Create a chart*/ + lv_obj_t * chart; + chart = lv_chart_create(lv_scr_act()); + lv_obj_set_size(chart, 200, 150); + lv_obj_center(chart); + lv_chart_set_type(chart, LV_CHART_TYPE_LINE); /*Show lines and points too*/ + + /*Add two data series*/ + lv_chart_series_t * ser1 = lv_chart_add_series(chart, lv_palette_main(LV_PALETTE_RED), LV_CHART_AXIS_PRIMARY_Y); + lv_chart_series_t * ser2 = lv_chart_add_series(chart, lv_palette_main(LV_PALETTE_GREEN), LV_CHART_AXIS_SECONDARY_Y); + + /*Set the next points on 'ser1'*/ + lv_chart_set_next_value(chart, ser1, 10); + lv_chart_set_next_value(chart, ser1, 10); + lv_chart_set_next_value(chart, ser1, 10); + lv_chart_set_next_value(chart, ser1, 10); + lv_chart_set_next_value(chart, ser1, 10); + lv_chart_set_next_value(chart, ser1, 10); + lv_chart_set_next_value(chart, ser1, 10); + lv_chart_set_next_value(chart, ser1, 30); + lv_chart_set_next_value(chart, ser1, 70); + lv_chart_set_next_value(chart, ser1, 90); + + /*Directly set points on 'ser2'*/ + ser2->y_points[0] = 90; + ser2->y_points[1] = 70; + ser2->y_points[2] = 65; + ser2->y_points[3] = 65; + ser2->y_points[4] = 65; + ser2->y_points[5] = 65; + ser2->y_points[6] = 65; + ser2->y_points[7] = 65; + ser2->y_points[8] = 65; + ser2->y_points[9] = 65; + + lv_chart_refresh(chart); /*Required after direct set*/ +} + +#endif diff --git a/lib/lvgl/examples/widgets/chart/lv_example_chart_1.py b/lib/lvgl/examples/widgets/chart/lv_example_chart_1.py new file mode 100644 index 00000000..ec7afc34 --- /dev/null +++ b/lib/lvgl/examples/widgets/chart/lv_example_chart_1.py @@ -0,0 +1,26 @@ +# Create a chart +chart = lv.chart(lv.scr_act()) +chart.set_size(200, 150) +chart.center() +chart.set_type(lv.chart.TYPE.LINE) # Show lines and points too + +# Add two data series +ser1 = chart.add_series(lv.palette_main(lv.PALETTE.RED), lv.chart.AXIS.PRIMARY_Y) +ser2 = chart.add_series(lv.palette_main(lv.PALETTE.GREEN), lv.chart.AXIS.SECONDARY_Y) +print(ser2) +# Set next points on ser1 +chart.set_next_value(ser1,10) +chart.set_next_value(ser1,10) +chart.set_next_value(ser1,10) +chart.set_next_value(ser1,10) +chart.set_next_value(ser1,10) +chart.set_next_value(ser1,10) +chart.set_next_value(ser1,10) +chart.set_next_value(ser1,30) +chart.set_next_value(ser1,70) +chart.set_next_value(ser1,90) + +# Directly set points on 'ser2' +ser2.y_points = [90, 70, 65, 65, 65, 65, 65, 65, 65, 65] +chart.refresh() # Required after direct set + diff --git a/lib/lvgl/examples/widgets/chart/lv_example_chart_2.c b/lib/lvgl/examples/widgets/chart/lv_example_chart_2.c new file mode 100644 index 00000000..a10f6f9e --- /dev/null +++ b/lib/lvgl/examples/widgets/chart/lv_example_chart_2.c @@ -0,0 +1,130 @@ +#include "../../lv_examples.h" +#if LV_USE_CHART && LV_DRAW_COMPLEX && LV_BUILD_EXAMPLES + +static lv_obj_t * chart1; +static lv_chart_series_t * ser1; +static lv_chart_series_t * ser2; + +static void draw_event_cb(lv_event_t * e) +{ + lv_obj_t * obj = lv_event_get_target(e); + + /*Add the faded area before the lines are drawn*/ + lv_obj_draw_part_dsc_t * dsc = lv_event_get_draw_part_dsc(e); + if(dsc->part == LV_PART_ITEMS) { + if(!dsc->p1 || !dsc->p2) return; + + /*Add a line mask that keeps the area below the line*/ + lv_draw_mask_line_param_t line_mask_param; + lv_draw_mask_line_points_init(&line_mask_param, dsc->p1->x, dsc->p1->y, dsc->p2->x, dsc->p2->y, + LV_DRAW_MASK_LINE_SIDE_BOTTOM); + int16_t line_mask_id = lv_draw_mask_add(&line_mask_param, NULL); + + /*Add a fade effect: transparent bottom covering top*/ + lv_coord_t h = lv_obj_get_height(obj); + lv_draw_mask_fade_param_t fade_mask_param; + lv_draw_mask_fade_init(&fade_mask_param, &obj->coords, LV_OPA_COVER, obj->coords.y1 + h / 8, LV_OPA_TRANSP, + obj->coords.y2); + int16_t fade_mask_id = lv_draw_mask_add(&fade_mask_param, NULL); + + /*Draw a rectangle that will be affected by the mask*/ + lv_draw_rect_dsc_t draw_rect_dsc; + lv_draw_rect_dsc_init(&draw_rect_dsc); + draw_rect_dsc.bg_opa = LV_OPA_20; + draw_rect_dsc.bg_color = dsc->line_dsc->color; + + lv_area_t a; + a.x1 = dsc->p1->x; + a.x2 = dsc->p2->x - 1; + a.y1 = LV_MIN(dsc->p1->y, dsc->p2->y); + a.y2 = obj->coords.y2; + lv_draw_rect(dsc->draw_ctx, &draw_rect_dsc, &a); + + /*Remove the masks*/ + lv_draw_mask_free_param(&line_mask_param); + lv_draw_mask_free_param(&fade_mask_param); + lv_draw_mask_remove_id(line_mask_id); + lv_draw_mask_remove_id(fade_mask_id); + } + /*Hook the division lines too*/ + else if(dsc->part == LV_PART_MAIN) { + if(dsc->line_dsc == NULL || dsc->p1 == NULL || dsc->p2 == NULL) return; + + /*Vertical line*/ + if(dsc->p1->x == dsc->p2->x) { + dsc->line_dsc->color = lv_palette_lighten(LV_PALETTE_GREY, 1); + if(dsc->id == 3) { + dsc->line_dsc->width = 2; + dsc->line_dsc->dash_gap = 0; + dsc->line_dsc->dash_width = 0; + } + else { + dsc->line_dsc->width = 1; + dsc->line_dsc->dash_gap = 6; + dsc->line_dsc->dash_width = 6; + } + } + /*Horizontal line*/ + else { + if(dsc->id == 2) { + dsc->line_dsc->width = 2; + dsc->line_dsc->dash_gap = 0; + dsc->line_dsc->dash_width = 0; + } + else { + dsc->line_dsc->width = 2; + dsc->line_dsc->dash_gap = 6; + dsc->line_dsc->dash_width = 6; + } + + if(dsc->id == 1 || dsc->id == 3) { + dsc->line_dsc->color = lv_palette_main(LV_PALETTE_GREEN); + } + else { + dsc->line_dsc->color = lv_palette_lighten(LV_PALETTE_GREY, 1); + } + } + } +} + +static void add_data(lv_timer_t * timer) +{ + LV_UNUSED(timer); + static uint32_t cnt = 0; + lv_chart_set_next_value(chart1, ser1, lv_rand(20, 90)); + + if(cnt % 4 == 0) lv_chart_set_next_value(chart1, ser2, lv_rand(40, 60)); + + cnt++; +} + +/** + * Add a faded area effect to the line chart and make some division lines ticker + */ +void lv_example_chart_2(void) +{ + /*Create a chart1*/ + chart1 = lv_chart_create(lv_scr_act()); + lv_obj_set_size(chart1, 200, 150); + lv_obj_center(chart1); + lv_chart_set_type(chart1, LV_CHART_TYPE_LINE); /*Show lines and points too*/ + + lv_chart_set_div_line_count(chart1, 5, 7); + + lv_obj_add_event_cb(chart1, draw_event_cb, LV_EVENT_DRAW_PART_BEGIN, NULL); + lv_chart_set_update_mode(chart1, LV_CHART_UPDATE_MODE_CIRCULAR); + + /*Add two data series*/ + ser1 = lv_chart_add_series(chart1, lv_palette_main(LV_PALETTE_RED), LV_CHART_AXIS_PRIMARY_Y); + ser2 = lv_chart_add_series(chart1, lv_palette_main(LV_PALETTE_BLUE), LV_CHART_AXIS_SECONDARY_Y); + + uint32_t i; + for(i = 0; i < 10; i++) { + lv_chart_set_next_value(chart1, ser1, lv_rand(20, 90)); + lv_chart_set_next_value(chart1, ser2, lv_rand(30, 70)); + } + + lv_timer_create(add_data, 200, NULL); +} + +#endif diff --git a/lib/lvgl/examples/widgets/chart/lv_example_chart_2.py b/lib/lvgl/examples/widgets/chart/lv_example_chart_2.py new file mode 100644 index 00000000..ad2c8794 --- /dev/null +++ b/lib/lvgl/examples/widgets/chart/lv_example_chart_2.py @@ -0,0 +1,76 @@ +def draw_event_cb(e): + + obj = e.get_target() + + # Add the faded area before the lines are drawn + dsc = lv.obj_draw_part_dsc_t.__cast__(e.get_param()) + if dsc.part != lv.PART.ITEMS: + return + if not dsc.p1 or not dsc.p2: + return + + # Add a line mask that keeps the area below the line + line_mask_param = lv.draw_mask_line_param_t() + line_mask_param.points_init(dsc.p1.x, dsc.p1.y, dsc.p2.x, dsc.p2.y, lv.DRAW_MASK_LINE_SIDE.BOTTOM) + # line_mask_id = line_mask_param.draw_mask_add(None) + line_mask_id = lv.draw_mask_add(line_mask_param, None) + # Add a fade effect: transparent bottom covering top + h = obj.get_height() + fade_mask_param = lv.draw_mask_fade_param_t() + coords = lv.area_t() + obj.get_coords(coords) + fade_mask_param.init(coords, lv.OPA.COVER, coords.y1 + h // 8, lv.OPA.TRANSP,coords.y2) + fade_mask_id = lv.draw_mask_add(fade_mask_param,None) + + # Draw a rectangle that will be affected by the mask + draw_rect_dsc = lv.draw_rect_dsc_t() + draw_rect_dsc.init() + draw_rect_dsc.bg_opa = lv.OPA._20 + draw_rect_dsc.bg_color = dsc.line_dsc.color + + a = lv.area_t() + a.x1 = dsc.p1.x + a.x2 = dsc.p2.x - 1 + a.y1 = min(dsc.p1.y, dsc.p2.y) + coords = lv.area_t() + obj.get_coords(coords) + a.y2 = coords.y2 + dsc.draw_ctx.rect(draw_rect_dsc, a) + + # Remove the masks + lv.draw_mask_remove_id(line_mask_id) + lv.draw_mask_remove_id(fade_mask_id) + + +def add_data(timer): + # LV_UNUSED(timer); + cnt = 0 + chart1.set_next_value(ser1, lv.rand(20, 90)) + + if cnt % 4 == 0: + chart1.set_next_value(ser2, lv.rand(40, 60)) + + cnt +=1 + +# +# Add a faded area effect to the line chart +# + +# Create a chart1 +chart1 = lv.chart(lv.scr_act()) +chart1.set_size(200, 150) +chart1.center() +chart1.set_type(lv.chart.TYPE.LINE) # Show lines and points too + +chart1.add_event_cb(draw_event_cb, lv.EVENT.DRAW_PART_BEGIN, None) +chart1.set_update_mode(lv.chart.UPDATE_MODE.CIRCULAR) + +# Add two data series +ser1 = chart1.add_series(lv.palette_main(lv.PALETTE.RED), lv.chart.AXIS.PRIMARY_Y) +ser2 = chart1.add_series(lv.palette_main(lv.PALETTE.BLUE), lv.chart.AXIS.SECONDARY_Y) + +for i in range(10): + chart1.set_next_value(ser1, lv.rand(20, 90)) + chart1.set_next_value(ser2, lv.rand(30, 70)) + +timer = lv.timer_create(add_data, 200, None) diff --git a/lib/lvgl/examples/widgets/chart/lv_example_chart_3.c b/lib/lvgl/examples/widgets/chart/lv_example_chart_3.c new file mode 100644 index 00000000..b5111502 --- /dev/null +++ b/lib/lvgl/examples/widgets/chart/lv_example_chart_3.c @@ -0,0 +1,76 @@ +#include "../../lv_examples.h" +#if LV_USE_CHART && LV_BUILD_EXAMPLES + +static void draw_event_cb(lv_event_t * e) +{ + lv_obj_draw_part_dsc_t * dsc = lv_event_get_draw_part_dsc(e); + if(!lv_obj_draw_part_check_type(dsc, &lv_chart_class, LV_CHART_DRAW_PART_TICK_LABEL)) return; + + if(dsc->id == LV_CHART_AXIS_PRIMARY_X && dsc->text) { + const char * month[] = {"Jan", "Febr", "March", "Apr", "May", "Jun", "July", "Aug", "Sept", "Oct", "Nov", "Dec"}; + lv_snprintf(dsc->text, dsc->text_length, "%s", month[dsc->value]); + } +} + +/** + * Add ticks and labels to the axis and demonstrate scrolling + */ +void lv_example_chart_3(void) +{ + /*Create a chart*/ + lv_obj_t * chart; + chart = lv_chart_create(lv_scr_act()); + lv_obj_set_size(chart, 200, 150); + lv_obj_center(chart); + lv_chart_set_type(chart, LV_CHART_TYPE_BAR); + lv_chart_set_range(chart, LV_CHART_AXIS_PRIMARY_Y, 0, 100); + lv_chart_set_range(chart, LV_CHART_AXIS_SECONDARY_Y, 0, 400); + lv_chart_set_point_count(chart, 12); + lv_obj_add_event_cb(chart, draw_event_cb, LV_EVENT_DRAW_PART_BEGIN, NULL); + + /*Add ticks and label to every axis*/ + lv_chart_set_axis_tick(chart, LV_CHART_AXIS_PRIMARY_X, 10, 5, 12, 3, true, 40); + lv_chart_set_axis_tick(chart, LV_CHART_AXIS_PRIMARY_Y, 10, 5, 6, 2, true, 50); + lv_chart_set_axis_tick(chart, LV_CHART_AXIS_SECONDARY_Y, 10, 5, 3, 4, true, 50); + + /*Zoom in a little in X*/ + lv_chart_set_zoom_x(chart, 800); + + /*Add two data series*/ + lv_chart_series_t * ser1 = lv_chart_add_series(chart, lv_palette_lighten(LV_PALETTE_GREEN, 2), LV_CHART_AXIS_PRIMARY_Y); + lv_chart_series_t * ser2 = lv_chart_add_series(chart, lv_palette_darken(LV_PALETTE_GREEN, 2), + LV_CHART_AXIS_SECONDARY_Y); + + /*Set the next points on 'ser1'*/ + lv_chart_set_next_value(chart, ser1, 31); + lv_chart_set_next_value(chart, ser1, 66); + lv_chart_set_next_value(chart, ser1, 10); + lv_chart_set_next_value(chart, ser1, 89); + lv_chart_set_next_value(chart, ser1, 63); + lv_chart_set_next_value(chart, ser1, 56); + lv_chart_set_next_value(chart, ser1, 32); + lv_chart_set_next_value(chart, ser1, 35); + lv_chart_set_next_value(chart, ser1, 57); + lv_chart_set_next_value(chart, ser1, 85); + lv_chart_set_next_value(chart, ser1, 22); + lv_chart_set_next_value(chart, ser1, 58); + + lv_coord_t * ser2_array = lv_chart_get_y_array(chart, ser2); + /*Directly set points on 'ser2'*/ + ser2_array[0] = 92; + ser2_array[1] = 71; + ser2_array[2] = 61; + ser2_array[3] = 15; + ser2_array[4] = 21; + ser2_array[5] = 35; + ser2_array[6] = 35; + ser2_array[7] = 58; + ser2_array[8] = 31; + ser2_array[9] = 53; + ser2_array[10] = 33; + ser2_array[11] = 73; + + lv_chart_refresh(chart); /*Required after direct set*/ +} + +#endif diff --git a/lib/lvgl/examples/widgets/chart/lv_example_chart_3.py b/lib/lvgl/examples/widgets/chart/lv_example_chart_3.py new file mode 100644 index 00000000..0afe6fe1 --- /dev/null +++ b/lib/lvgl/examples/widgets/chart/lv_example_chart_3.py @@ -0,0 +1,52 @@ +def draw_event_cb(e): + + dsc = lv.obj_draw_part_dsc_t.__cast__(e.get_param()) + if dsc.part == lv.PART.TICKS and dsc.id == lv.chart.AXIS.PRIMARY_X: + month = ["Jan", "Febr", "March", "Apr", "May", "Jun", "July", "Aug", "Sept", "Oct", "Nov", "Dec"] + # dsc.text is defined char text[16], I must therefore convert the Python string to a byte_array + dsc.text = bytes(month[dsc.value],"ascii") +# +# Add ticks and labels to the axis and demonstrate scrolling +# + +# Create a chart +chart = lv.chart(lv.scr_act()) +chart.set_size(200, 150) +chart.center() +chart.set_type(lv.chart.TYPE.BAR) +chart.set_range(lv.chart.AXIS.PRIMARY_Y, 0, 100) +chart.set_range(lv.chart.AXIS.SECONDARY_Y, 0, 400) +chart.set_point_count(12) +chart.add_event_cb(draw_event_cb, lv.EVENT.DRAW_PART_BEGIN, None) + +# Add ticks and label to every axis +chart.set_axis_tick(lv.chart.AXIS.PRIMARY_X, 10, 5, 12, 3, True, 40) +chart.set_axis_tick(lv.chart.AXIS.PRIMARY_Y, 10, 5, 6, 2, True, 50) +chart.set_axis_tick(lv.chart.AXIS.SECONDARY_Y, 10, 5, 3, 4,True, 50) + +# Zoom in a little in X +chart.set_zoom_x(800) + +# Add two data series +ser1 = lv.chart.add_series(chart, lv.palette_lighten(lv.PALETTE.GREEN, 2), lv.chart.AXIS.PRIMARY_Y) +ser2 = lv.chart.add_series(chart, lv.palette_darken(lv.PALETTE.GREEN, 2), lv.chart.AXIS.SECONDARY_Y) + +# Set the next points on 'ser1' +chart.set_next_value(ser1, 31) +chart.set_next_value(ser1, 66) +chart.set_next_value(ser1, 10) +chart.set_next_value(ser1, 89) +chart.set_next_value(ser1, 63) +chart.set_next_value(ser1, 56) +chart.set_next_value(ser1, 32) +chart.set_next_value(ser1, 35) +chart.set_next_value(ser1, 57) +chart.set_next_value(ser1, 85) +chart.set_next_value(ser1, 22) +chart.set_next_value(ser1, 58) + +# Directly set points on 'ser2' +ser2.y_points = [92,71,61,15,21,35,35,58,31,53,33,73] + +chart.refresh() # Required after direct set + diff --git a/lib/lvgl/examples/widgets/chart/lv_example_chart_4.c b/lib/lvgl/examples/widgets/chart/lv_example_chart_4.c new file mode 100644 index 00000000..8508ef18 --- /dev/null +++ b/lib/lvgl/examples/widgets/chart/lv_example_chart_4.c @@ -0,0 +1,86 @@ +#include "../../lv_examples.h" +#if LV_USE_CHART && LV_BUILD_EXAMPLES + + +static void event_cb(lv_event_t * e) +{ + lv_event_code_t code = lv_event_get_code(e); + lv_obj_t * chart = lv_event_get_target(e); + + if(code == LV_EVENT_VALUE_CHANGED) { + lv_obj_invalidate(chart); + } + if(code == LV_EVENT_REFR_EXT_DRAW_SIZE) { + lv_coord_t * s = lv_event_get_param(e); + *s = LV_MAX(*s, 20); + } + else if(code == LV_EVENT_DRAW_POST_END) { + int32_t id = lv_chart_get_pressed_point(chart); + if(id == LV_CHART_POINT_NONE) return; + + LV_LOG_USER("Selected point %d", (int)id); + + lv_chart_series_t * ser = lv_chart_get_series_next(chart, NULL); + while(ser) { + lv_point_t p; + lv_chart_get_point_pos_by_id(chart, ser, id, &p); + + lv_coord_t * y_array = lv_chart_get_y_array(chart, ser); + lv_coord_t value = y_array[id]; + + char buf[16]; + lv_snprintf(buf, sizeof(buf), LV_SYMBOL_DUMMY"$%d", value); + + lv_draw_rect_dsc_t draw_rect_dsc; + lv_draw_rect_dsc_init(&draw_rect_dsc); + draw_rect_dsc.bg_color = lv_color_black(); + draw_rect_dsc.bg_opa = LV_OPA_50; + draw_rect_dsc.radius = 3; + draw_rect_dsc.bg_img_src = buf; + draw_rect_dsc.bg_img_recolor = lv_color_white(); + + lv_area_t a; + a.x1 = chart->coords.x1 + p.x - 20; + a.x2 = chart->coords.x1 + p.x + 20; + a.y1 = chart->coords.y1 + p.y - 30; + a.y2 = chart->coords.y1 + p.y - 10; + + lv_draw_ctx_t * draw_ctx = lv_event_get_draw_ctx(e); + lv_draw_rect(draw_ctx, &draw_rect_dsc, &a); + + ser = lv_chart_get_series_next(chart, ser); + } + } + else if(code == LV_EVENT_RELEASED) { + lv_obj_invalidate(chart); + } +} + +/** + * Show the value of the pressed points + */ +void lv_example_chart_4(void) +{ + /*Create a chart*/ + lv_obj_t * chart; + chart = lv_chart_create(lv_scr_act()); + lv_obj_set_size(chart, 200, 150); + lv_obj_center(chart); + + lv_obj_add_event_cb(chart, event_cb, LV_EVENT_ALL, NULL); + lv_obj_refresh_ext_draw_size(chart); + + /*Zoom in a little in X*/ + lv_chart_set_zoom_x(chart, 800); + + /*Add two data series*/ + lv_chart_series_t * ser1 = lv_chart_add_series(chart, lv_palette_main(LV_PALETTE_RED), LV_CHART_AXIS_PRIMARY_Y); + lv_chart_series_t * ser2 = lv_chart_add_series(chart, lv_palette_main(LV_PALETTE_GREEN), LV_CHART_AXIS_PRIMARY_Y); + uint32_t i; + for(i = 0; i < 10; i++) { + lv_chart_set_next_value(chart, ser1, lv_rand(60, 90)); + lv_chart_set_next_value(chart, ser2, lv_rand(10, 40)); + } +} + +#endif diff --git a/lib/lvgl/examples/widgets/chart/lv_example_chart_4.py b/lib/lvgl/examples/widgets/chart/lv_example_chart_4.py new file mode 100644 index 00000000..3b8d0633 --- /dev/null +++ b/lib/lvgl/examples/widgets/chart/lv_example_chart_4.py @@ -0,0 +1,73 @@ +def event_cb(e): + code = e.get_code() + chart = e.get_target() + + if code == lv.EVENT.VALUE_CHANGED: + chart.invalidate() + + if code == lv.EVENT.REFR_EXT_DRAW_SIZE: + e.set_ext_draw_size(20) + + elif code == lv.EVENT.DRAW_POST_END: + id = lv.chart.get_pressed_point(chart) + if id == lv.CHART_POINT.NONE: + return + # print("Selected point ", id) + for i in range(len(series)): + p = lv.point_t() + chart.get_point_pos_by_id(series[i], id, p) + value = series_points[i][id] + buf = lv.SYMBOL.DUMMY + "$" + str(value) + + draw_rect_dsc = lv.draw_rect_dsc_t() + draw_rect_dsc.init() + draw_rect_dsc.bg_color = lv.color_black() + draw_rect_dsc.bg_opa = lv.OPA._50 + draw_rect_dsc.radius = 3 + draw_rect_dsc.bg_img_src = buf + draw_rect_dsc.bg_img_recolor = lv.color_white() + + a = lv.area_t() + coords = lv.area_t() + chart.get_coords(coords) + a.x1 = coords.x1 + p.x - 20 + a.x2 = coords.x1 + p.x + 20 + a.y1 = coords.y1 + p.y - 30 + a.y2 = coords.y1 + p.y - 10 + + clip_area = lv.area_t.__cast__(e.get_param()) + lv.draw_rect(a, clip_area, draw_rect_dsc) + + elif code == lv.EVENT.RELEASED: + chart.invalidate() + +# +# Add ticks and labels to the axis and demonstrate scrolling +# + +# Create a chart +chart = lv.chart(lv.scr_act()) +chart.set_size(200, 150) +chart.center() + +chart.add_event_cb(event_cb, lv.EVENT.ALL, None) +chart.refresh_ext_draw_size() + +# Zoom in a little in X +chart.set_zoom_x(800) + +# Add two data series +ser1 = chart.add_series(lv.palette_main(lv.PALETTE.RED), lv.chart.AXIS.PRIMARY_Y) +ser2 = chart.add_series(lv.palette_main(lv.PALETTE.GREEN), lv.chart.AXIS.PRIMARY_Y) + +ser1_p = [] +ser2_p = [] +for i in range(10): + ser1_p.append(lv.rand(60,90)) + ser2_p.append(lv.rand(10,40)) +ser1.y_points = ser1_p +ser2.y_points = ser2_p + +series = [ser1,ser2] +series_points=[ser1_p,ser2_p] + diff --git a/lib/lvgl/examples/widgets/chart/lv_example_chart_5.c b/lib/lvgl/examples/widgets/chart/lv_example_chart_5.c new file mode 100644 index 00000000..c175e37c --- /dev/null +++ b/lib/lvgl/examples/widgets/chart/lv_example_chart_5.c @@ -0,0 +1,99 @@ +#include "../../lv_examples.h" +#if LV_USE_CHART && LV_USE_SLIDER && LV_BUILD_EXAMPLES + +static lv_obj_t * chart; +/* Source: https://github.com/ankur219/ECG-Arrhythmia-classification/blob/642230149583adfae1e4bd26c6f0e1fd8af2be0e/sample.csv*/ +static const lv_coord_t ecg_sample[] = { + -2, 2, 0, -15, -39, -63, -71, -68, -67, -69, -84, -95, -104, -107, -108, -107, -107, -107, -107, -114, -118, -117, + -112, -100, -89, -83, -71, -64, -58, -58, -62, -62, -58, -51, -46, -39, -27, -10, 4, 7, 1, -3, 0, 14, 24, 30, 25, 19, + 13, 7, 12, 15, 18, 21, 13, 6, 9, 8, 17, 19, 13, 11, 11, 11, 23, 30, 37, 34, 25, 14, 15, 19, 28, 31, 26, 23, 25, 31, + 39, 37, 37, 34, 30, 32, 22, 29, 31, 33, 37, 23, 13, 7, 2, 4, -2, 2, 11, 22, 33, 19, -1, -27, -55, -67, -72, -71, -63, + -49, -18, 35, 113, 230, 369, 525, 651, 722, 730, 667, 563, 454, 357, 305, 288, 274, 255, 212, 173, 143, 117, 82, 39, + -13, -53, -78, -91, -101, -113, -124, -131, -131, -131, -129, -128, -129, -125, -123, -123, -129, -139, -148, -153, + -159, -166, -183, -205, -227, -243, -248, -246, -254, -280, -327, -381, -429, -473, -517, -556, -592, -612, -620, + -620, -614, -604, -591, -574, -540, -497, -441, -389, -358, -336, -313, -284, -222, -167, -114, -70, -47, -28, -4, 12, + 38, 52, 58, 56, 56, 57, 68, 77, 86, 86, 80, 69, 67, 70, 82, 85, 89, 90, 89, 89, 88, 91, 96, 97, 91, 83, 78, 82, 88, 95, + 96, 105, 106, 110, 102, 100, 96, 98, 97, 101, 98, 99, 100, 107, 113, 119, 115, 110, 96, 85, 73, 64, 69, 76, 79, + 78, 75, 85, 100, 114, 113, 105, 96, 84, 74, 66, 60, 75, 85, 89, 83, 67, 61, 67, 73, 79, 74, 63, 57, 56, 58, 61, 55, + 48, 45, 46, 55, 62, 55, 49, 43, 50, 59, 63, 57, 40, 31, 23, 25, 27, 31, 35, 34, 30, 36, 34, 42, 38, 36, 40, 46, 50, + 47, 32, 30, 32, 52, 67, 73, 71, 63, 54, 53, 45, 41, 28, 13, 3, 1, 4, 4, -8, -23, -32, -31, -19, -5, 3, 9, 13, 19, + 24, 27, 29, 25, 22, 26, 32, 42, 51, 56, 60, 57, 55, 53, 53, 54, 59, 54, 49, 26, -3, -11, -20, -47, -100, -194, -236, + -212, -123, 8, 103, 142, 147, 120, 105, 98, 93, 81, 61, 40, 26, 28, 30, 30, 27, 19, 17, 21, 20, 19, 19, 22, 36, 40, + 35, 20, 7, 1, 10, 18, 27, 22, 6, -4, -2, 3, 6, -2, -13, -14, -10, -2, 3, 2, -1, -5, -10, -19, -32, -42, -55, -60, + -68, -77, -86, -101, -110, -117, -115, -104, -92, -84, -85, -84, -73, -65, -52, -50, -45, -35, -20, -3, 12, 20, 25, + 26, 28, 28, 30, 28, 25, 28, 33, 42, 42, 36, 23, 9, 0, 1, -4, 1, -4, -4, 1, 5, 9, 9, -3, -1, -18, -50, -108, -190, + -272, -340, -408, -446, -537, -643, -777, -894, -920, -853, -697, -461, -251, -60, 58, 103, 129, 139, 155, 170, 173, + 178, 185, 190, 193, 200, 208, 215, 225, 224, 232, 234, 240, 240, 236, 229, 226, 224, 232, 233, 232, 224, 219, 219, + 223, 231, 226, 223, 219, 218, 223, 223, 223, 233, 245, 268, 286, 296, 295, 283, 271, 263, 252, 243, 226, 210, 197, + 186, 171, 152, 133, 117, 114, 110, 107, 96, 80, 63, 48, 40, 38, 34, 28, 15, 2, -7, -11, -14, -18, -29, -37, -44, -50, + -58, -63, -61, -52, -50, -48, -61, -59, -58, -54, -47, -52, -62, -61, -64, -54, -52, -59, -69, -76, -76, -69, -67, + -74, -78, -81, -80, -73, -65, -57, -53, -51, -47, -35, -27, -22, -22, -24, -21, -17, -13, -10, -11, -13, -20, -20, + -12, -2, 7, -1, -12, -16, -13, -2, 2, -4, -5, -2, 9, 19, 19, 14, 11, 13, 19, 21, 20, 18, 19, 19, 19, 16, 15, 13, 14, + 9, 3, -5, -9, -5, -3, -2, -3, -3, 2, 8, 9, 9, 5, 6, 8, 8, 7, 4, 3, 4, 5, 3, 5, 5, 13, 13, 12, 10, 10, 15, 22, 17, + 14, 7, 10, 15, 16, 11, 12, 10, 13, 9, -2, -4, -2, 7, 16, 16, 17, 16, 7, -1, -16, -18, -16, -9, -4, -5, -10, -9, -8, + -3, -4, -10, -19, -20, -16, -9, -9, -23, -40, -48, -43, -33, -19, -21, -26, -31, -33, -19, 0, 17, 24, 9, -17, -47, + -63, -67, -59, -52, -51, -50, -49, -42, -26, -21, -15, -20, -23, -22, -19, -12, -8, 5, 18, 27, 32, 26, 25, 26, 22, + 23, 17, 14, 17, 21, 25, 2, -45, -121, -196, -226, -200, -118, -9, 73, 126, 131, 114, 87, 60, 42, 29, 26, 34, 35, 34, + 25, 12, 9, 7, 3, 2, -8, -11, 2, 23, 38, 41, 23, 9, 10, 13, 16, 8, -8, -17, -23, -26, -25, -21, -15, -10, -13, -13, + -19, -22, -29, -40, -48, -48, -54, -55, -66, -82, -85, -90, -92, -98, -114, -119, -124, -129, -132, -146, -146, -138, + -124, -99, -85, -72, -65, -65, -65, -66, -63, -64, -64, -58, -46, -26, -9, 2, 2, 4, 0, 1, 4, 3, 10, 11, 10, 2, -4, + 0, 10, 18, 20, 6, 2, -9, -7, -3, -3, -2, -7, -12, -5, 5, 24, 36, 31, 25, 6, 3, 7, 12, 17, 11, 0, -6, -9, -8, -7, -5, + -6, -2, -2, -6, -2, 2, 14, 24, 22, 15, 8, 4, 6, 7, 12, 16, 25, 20, 7, -16, -41, -60, -67, -65, -54, -35, -11, 30, + 84, 175, 302, 455, 603, 707, 743, 714, 625, 519, 414, 337, 300, 281, 263, 239, 197, 163, 136, 109, 77, 34, -18, -50, + -66, -74, -79, -92, -107, -117, -127, -129, -135, -139, -141, -155, -159, -167, -171, -169, -174, -175, -178, -191, + -202, -223, -235, -243, -237, -240, -256, -298, -345, -393, -432, -475, -518, -565, -596, -619, -623, -623, -614, + -599, -583, -559, -524, -477, -425, -383, -357, -331, -301, -252, -198, -143, -96, -57, -29, -8, 10, 31, 45, 60, 65, + 70, 74, 76, 79, 82, 79, 75, 62, + }; + +static void slider_x_event_cb(lv_event_t * e) +{ + lv_obj_t * obj = lv_event_get_target(e); + int32_t v = lv_slider_get_value(obj); + lv_chart_set_zoom_x(chart, v); +} + +static void slider_y_event_cb(lv_event_t * e) +{ + lv_obj_t * obj = lv_event_get_target(e); + int32_t v = lv_slider_get_value(obj); + lv_chart_set_zoom_y(chart, v); +} + +/** + * Display 1000 data points with zooming and scrolling. + * See how the chart changes drawing mode (draw only vertical lines) when + * the points get too crowded. + */ +void lv_example_chart_5(void) +{ + /*Create a chart*/ + chart = lv_chart_create(lv_scr_act()); + lv_obj_set_size(chart, 200, 150); + lv_obj_align(chart, LV_ALIGN_CENTER, -30, -30); + lv_chart_set_range(chart, LV_CHART_AXIS_PRIMARY_Y, -1000, 1000); + + /*Do not display points on the data*/ + lv_obj_set_style_size(chart, 0, LV_PART_INDICATOR); + + lv_chart_series_t * ser = lv_chart_add_series(chart, lv_palette_main(LV_PALETTE_RED), LV_CHART_AXIS_PRIMARY_Y); + + uint32_t pcnt = sizeof(ecg_sample) / sizeof(ecg_sample[0]); + lv_chart_set_point_count(chart, pcnt); + lv_chart_set_ext_y_array(chart, ser, (lv_coord_t *)ecg_sample); + + lv_obj_t * slider; + slider = lv_slider_create(lv_scr_act()); + lv_slider_set_range(slider, LV_IMG_ZOOM_NONE, LV_IMG_ZOOM_NONE * 10); + lv_obj_add_event_cb(slider, slider_x_event_cb, LV_EVENT_VALUE_CHANGED, NULL); + lv_obj_set_size(slider, 200, 10); + lv_obj_align_to(slider, chart, LV_ALIGN_OUT_BOTTOM_MID, 0, 20); + + slider = lv_slider_create(lv_scr_act()); + lv_slider_set_range(slider, LV_IMG_ZOOM_NONE, LV_IMG_ZOOM_NONE * 10); + lv_obj_add_event_cb(slider, slider_y_event_cb, LV_EVENT_VALUE_CHANGED, NULL); + lv_obj_set_size(slider, 10, 150); + lv_obj_align_to(slider, chart, LV_ALIGN_OUT_RIGHT_MID, 20, 0); +} + +#endif diff --git a/lib/lvgl/examples/widgets/chart/lv_example_chart_5.py b/lib/lvgl/examples/widgets/chart/lv_example_chart_5.py new file mode 100644 index 00000000..f0d58323 --- /dev/null +++ b/lib/lvgl/examples/widgets/chart/lv_example_chart_5.py @@ -0,0 +1,89 @@ +# Source: https://github.com/ankur219/ECG-Arrhythmia-classification/blob/642230149583adfae1e4bd26c6f0e1fd8af2be0e/sample.csv +ecg_sample = [ + -2, 2, 0, -15, -39, -63, -71, -68, -67, -69, -84, -95, -104, -107, -108, -107, -107, -107, -107, -114, -118, -117, + -112, -100, -89, -83, -71, -64, -58, -58, -62, -62, -58, -51, -46, -39, -27, -10, 4, 7, 1, -3, 0, 14, 24, 30, 25, 19, + 13, 7, 12, 15, 18, 21, 13, 6, 9, 8, 17, 19, 13, 11, 11, 11, 23, 30, 37, 34, 25, 14, 15, 19, 28, 31, 26, 23, 25, 31, + 39, 37, 37, 34, 30, 32, 22, 29, 31, 33, 37, 23, 13, 7, 2, 4, -2, 2, 11, 22, 33, 19, -1, -27, -55, -67, -72, -71, -63, + -49, -18, 35, 113, 230, 369, 525, 651, 722, 730, 667, 563, 454, 357, 305, 288, 274, 255, 212, 173, 143, 117, 82, 39, + -13, -53, -78, -91, -101, -113, -124, -131, -131, -131, -129, -128, -129, -125, -123, -123, -129, -139, -148, -153, + -159, -166, -183, -205, -227, -243, -248, -246, -254, -280, -327, -381, -429, -473, -517, -556, -592, -612, -620, + -620, -614, -604, -591, -574, -540, -497, -441, -389, -358, -336, -313, -284, -222, -167, -114, -70, -47, -28, -4, 12, + 38, 52, 58, 56, 56, 57, 68, 77, 86, 86, 80, 69, 67, 70, 82, 85, 89, 90, 89, 89, 88, 91, 96, 97, 91, 83, 78, 82, 88, 95, + 96, 105, 106, 110, 102, 100, 96, 98, 97, 101, 98, 99, 100, 107, 113, 119, 115, 110, 96, 85, 73, 64, 69, 76, 79, + 78, 75, 85, 100, 114, 113, 105, 96, 84, 74, 66, 60, 75, 85, 89, 83, 67, 61, 67, 73, 79, 74, 63, 57, 56, 58, 61, 55, + 48, 45, 46, 55, 62, 55, 49, 43, 50, 59, 63, 57, 40, 31, 23, 25, 27, 31, 35, 34, 30, 36, 34, 42, 38, 36, 40, 46, 50, + 47, 32, 30, 32, 52, 67, 73, 71, 63, 54, 53, 45, 41, 28, 13, 3, 1, 4, 4, -8, -23, -32, -31, -19, -5, 3, 9, 13, 19, + 24, 27, 29, 25, 22, 26, 32, 42, 51, 56, 60, 57, 55, 53, 53, 54, 59, 54, 49, 26, -3, -11, -20, -47, -100, -194, -236, + -212, -123, 8, 103, 142, 147, 120, 105, 98, 93, 81, 61, 40, 26, 28, 30, 30, 27, 19, 17, 21, 20, 19, 19, 22, 36, 40, + 35, 20, 7, 1, 10, 18, 27, 22, 6, -4, -2, 3, 6, -2, -13, -14, -10, -2, 3, 2, -1, -5, -10, -19, -32, -42, -55, -60, + -68, -77, -86, -101, -110, -117, -115, -104, -92, -84, -85, -84, -73, -65, -52, -50, -45, -35, -20, -3, 12, 20, 25, + 26, 28, 28, 30, 28, 25, 28, 33, 42, 42, 36, 23, 9, 0, 1, -4, 1, -4, -4, 1, 5, 9, 9, -3, -1, -18, -50, -108, -190, + -272, -340, -408, -446, -537, -643, -777, -894, -920, -853, -697, -461, -251, -60, 58, 103, 129, 139, 155, 170, 173, + 178, 185, 190, 193, 200, 208, 215, 225, 224, 232, 234, 240, 240, 236, 229, 226, 224, 232, 233, 232, 224, 219, 219, + 223, 231, 226, 223, 219, 218, 223, 223, 223, 233, 245, 268, 286, 296, 295, 283, 271, 263, 252, 243, 226, 210, 197, + 186, 171, 152, 133, 117, 114, 110, 107, 96, 80, 63, 48, 40, 38, 34, 28, 15, 2, -7, -11, -14, -18, -29, -37, -44, -50, + -58, -63, -61, -52, -50, -48, -61, -59, -58, -54, -47, -52, -62, -61, -64, -54, -52, -59, -69, -76, -76, -69, -67, + -74, -78, -81, -80, -73, -65, -57, -53, -51, -47, -35, -27, -22, -22, -24, -21, -17, -13, -10, -11, -13, -20, -20, + -12, -2, 7, -1, -12, -16, -13, -2, 2, -4, -5, -2, 9, 19, 19, 14, 11, 13, 19, 21, 20, 18, 19, 19, 19, 16, 15, 13, 14, + 9, 3, -5, -9, -5, -3, -2, -3, -3, 2, 8, 9, 9, 5, 6, 8, 8, 7, 4, 3, 4, 5, 3, 5, 5, 13, 13, 12, 10, 10, 15, 22, 17, + 14, 7, 10, 15, 16, 11, 12, 10, 13, 9, -2, -4, -2, 7, 16, 16, 17, 16, 7, -1, -16, -18, -16, -9, -4, -5, -10, -9, -8, + -3, -4, -10, -19, -20, -16, -9, -9, -23, -40, -48, -43, -33, -19, -21, -26, -31, -33, -19, 0, 17, 24, 9, -17, -47, + -63, -67, -59, -52, -51, -50, -49, -42, -26, -21, -15, -20, -23, -22, -19, -12, -8, 5, 18, 27, 32, 26, 25, 26, 22, + 23, 17, 14, 17, 21, 25, 2, -45, -121, -196, -226, -200, -118, -9, 73, 126, 131, 114, 87, 60, 42, 29, 26, 34, 35, 34, + 25, 12, 9, 7, 3, 2, -8, -11, 2, 23, 38, 41, 23, 9, 10, 13, 16, 8, -8, -17, -23, -26, -25, -21, -15, -10, -13, -13, + -19, -22, -29, -40, -48, -48, -54, -55, -66, -82, -85, -90, -92, -98, -114, -119, -124, -129, -132, -146, -146, -138, + -124, -99, -85, -72, -65, -65, -65, -66, -63, -64, -64, -58, -46, -26, -9, 2, 2, 4, 0, 1, 4, 3, 10, 11, 10, 2, -4, + 0, 10, 18, 20, 6, 2, -9, -7, -3, -3, -2, -7, -12, -5, 5, 24, 36, 31, 25, 6, 3, 7, 12, 17, 11, 0, -6, -9, -8, -7, -5, + -6, -2, -2, -6, -2, 2, 14, 24, 22, 15, 8, 4, 6, 7, 12, 16, 25, 20, 7, -16, -41, -60, -67, -65, -54, -35, -11, 30, + 84, 175, 302, 455, 603, 707, 743, 714, 625, 519, 414, 337, 300, 281, 263, 239, 197, 163, 136, 109, 77, 34, -18, -50, + -66, -74, -79, -92, -107, -117, -127, -129, -135, -139, -141, -155, -159, -167, -171, -169, -174, -175, -178, -191, + -202, -223, -235, -243, -237, -240, -256, -298, -345, -393, -432, -475, -518, -565, -596, -619, -623, -623, -614, + -599, -583, -559, -524, -477, -425, -383, -357, -331, -301, -252, -198, -143, -96, -57, -29, -8, 10, 31, 45, 60, 65, + 70, 74, 76, 79, 82, 79, 75, 62, +] + +def slider_x_event_cb(e): + + slider = e.get_target() + v = slider.get_value() + chart.set_zoom_x(v) + +def slider_y_event_cb(e): + + slider = e.get_target() + v = slider.get_value() + chart.set_zoom_y(v) + + +# +# Display 1000 data points with zooming and scrolling. +# See how the chart changes drawing mode (draw only vertical lines) when +# the points get too crowded. + +# Create a chart +chart = lv.chart(lv.scr_act()) +chart.set_size(200, 150) +chart.align(lv.ALIGN.CENTER, -30, -30) +chart.set_range(lv.chart.AXIS.PRIMARY_Y, -1000, 1000) + +# Do not display points on the data +chart.set_style_size(0, lv.PART.INDICATOR) + +ser = chart.add_series(lv.palette_main(lv.PALETTE.RED), lv.chart.AXIS.PRIMARY_Y) + +pcnt = len(ecg_sample) +chart.set_point_count(pcnt) +chart.set_ext_y_array(ser, ecg_sample) + +slider = lv.slider(lv.scr_act()) +slider.set_range(lv.IMG_ZOOM.NONE, lv.IMG_ZOOM.NONE * 10) +slider.add_event_cb(slider_x_event_cb, lv.EVENT.VALUE_CHANGED, None) +slider.set_size(200,10) +slider.align_to(chart, lv.ALIGN.OUT_BOTTOM_MID, 0, 20) + +slider = lv.slider(lv.scr_act()) +slider.set_range(lv.IMG_ZOOM.NONE, lv.IMG_ZOOM.NONE * 10) +slider.add_event_cb(slider_y_event_cb, lv.EVENT.VALUE_CHANGED, None) +slider.set_size(10, 150) +slider.align_to(chart, lv.ALIGN.OUT_RIGHT_MID, 20, 0) + diff --git a/lib/lvgl/examples/widgets/chart/lv_example_chart_6.c b/lib/lvgl/examples/widgets/chart/lv_example_chart_6.c new file mode 100644 index 00000000..463ab670 --- /dev/null +++ b/lib/lvgl/examples/widgets/chart/lv_example_chart_6.c @@ -0,0 +1,87 @@ +#include "../../lv_examples.h" +#if LV_USE_CHART && LV_BUILD_EXAMPLES + +static lv_obj_t * chart; +static lv_chart_series_t * ser; +static lv_chart_cursor_t * cursor; + +static void event_cb(lv_event_t * e) +{ + static int32_t last_id = -1; + lv_event_code_t code = lv_event_get_code(e); + lv_obj_t * obj = lv_event_get_target(e); + + if(code == LV_EVENT_VALUE_CHANGED) { + last_id = lv_chart_get_pressed_point(obj); + if(last_id != LV_CHART_POINT_NONE) { + lv_chart_set_cursor_point(obj, cursor, NULL, last_id); + } + } + else if(code == LV_EVENT_DRAW_PART_END) { + lv_obj_draw_part_dsc_t * dsc = lv_event_get_draw_part_dsc(e); + if(!lv_obj_draw_part_check_type(dsc, &lv_chart_class, LV_CHART_DRAW_PART_CURSOR)) return; + if(dsc->p1 == NULL || dsc->p2 == NULL || dsc->p1->y != dsc->p2->y || last_id < 0) return; + + lv_coord_t * data_array = lv_chart_get_y_array(chart, ser); + lv_coord_t v = data_array[last_id]; + char buf[16]; + lv_snprintf(buf, sizeof(buf), "%d", v); + + lv_point_t size; + lv_txt_get_size(&size, buf, LV_FONT_DEFAULT, 0, 0, LV_COORD_MAX, LV_TEXT_FLAG_NONE); + + lv_area_t a; + a.y2 = dsc->p1->y - 5; + a.y1 = a.y2 - size.y - 10; + a.x1 = dsc->p1->x + 10; + a.x2 = a.x1 + size.x + 10; + + lv_draw_rect_dsc_t draw_rect_dsc; + lv_draw_rect_dsc_init(&draw_rect_dsc); + draw_rect_dsc.bg_color = lv_palette_main(LV_PALETTE_BLUE); + draw_rect_dsc.radius = 3; + + lv_draw_rect(dsc->draw_ctx, &draw_rect_dsc, &a); + + lv_draw_label_dsc_t draw_label_dsc; + lv_draw_label_dsc_init(&draw_label_dsc); + draw_label_dsc.color = lv_color_white(); + a.x1 += 5; + a.x2 -= 5; + a.y1 += 5; + a.y2 -= 5; + lv_draw_label(dsc->draw_ctx, &draw_label_dsc, &a, buf, NULL); + } +} + +/** + * Show cursor on the clicked point + */ +void lv_example_chart_6(void) +{ + chart = lv_chart_create(lv_scr_act()); + lv_obj_set_size(chart, 200, 150); + lv_obj_align(chart, LV_ALIGN_CENTER, 0, -10); + + lv_chart_set_axis_tick(chart, LV_CHART_AXIS_PRIMARY_Y, 10, 5, 6, 5, true, 40); + lv_chart_set_axis_tick(chart, LV_CHART_AXIS_PRIMARY_X, 10, 5, 10, 1, true, 30); + + lv_obj_add_event_cb(chart, event_cb, LV_EVENT_ALL, NULL); + lv_obj_refresh_ext_draw_size(chart); + + cursor = lv_chart_add_cursor(chart, lv_palette_main(LV_PALETTE_BLUE), LV_DIR_LEFT | LV_DIR_BOTTOM); + + ser = lv_chart_add_series(chart, lv_palette_main(LV_PALETTE_RED), LV_CHART_AXIS_PRIMARY_Y); + uint32_t i; + for(i = 0; i < 10; i++) { + lv_chart_set_next_value(chart, ser, lv_rand(10, 90)); + } + + lv_chart_set_zoom_x(chart, 500); + + lv_obj_t * label = lv_label_create(lv_scr_act()); + lv_label_set_text(label, "Click on a point"); + lv_obj_align_to(label, chart, LV_ALIGN_OUT_TOP_MID, 0, -5); +} + +#endif diff --git a/lib/lvgl/examples/widgets/chart/lv_example_chart_6.py b/lib/lvgl/examples/widgets/chart/lv_example_chart_6.py new file mode 100644 index 00000000..acc4e11c --- /dev/null +++ b/lib/lvgl/examples/widgets/chart/lv_example_chart_6.py @@ -0,0 +1,88 @@ +class ExampleChart_6(): + + def __init__(self): + self.last_id = -1 + # + # Show cursor on the clicked point + # + + chart = lv.chart(lv.scr_act()) + chart.set_size(200, 150) + chart.align(lv.ALIGN.CENTER, 0, -10) + + chart.set_axis_tick(lv.chart.AXIS.PRIMARY_Y, 10, 5, 6, 5, True, 40) + chart.set_axis_tick(lv.chart.AXIS.PRIMARY_X, 10, 5, 10, 1, True, 30) + + chart.add_event_cb(self.event_cb, lv.EVENT.ALL, None) + chart.refresh_ext_draw_size() + + self.cursor = chart.add_cursor(lv.palette_main(lv.PALETTE.BLUE), lv.DIR.LEFT | lv.DIR.BOTTOM) + + self.ser = chart.add_series(lv.palette_main(lv.PALETTE.RED), lv.chart.AXIS.PRIMARY_Y) + + self.ser_p = [] + for i in range(10): + self.ser_p.append(lv.rand(10,90)) + self.ser.y_points = self.ser_p + + newser = chart.get_series_next(None) + # print("length of data points: ",len(newser.points)) + chart.set_zoom_x(500) + + label = lv.label(lv.scr_act()) + label.set_text("Click on a point") + label.align_to(chart, lv.ALIGN.OUT_TOP_MID, 0, -5) + + + def event_cb(self,e): + + code = e.get_code() + chart = e.get_target() + + if code == lv.EVENT.VALUE_CHANGED: + # print("last_id: ",self.last_id) + self.last_id = chart.get_pressed_point() + if self.last_id != lv.CHART_POINT.NONE: + p = lv.point_t() + chart.get_point_pos_by_id(self.ser, self.last_id, p) + chart.set_cursor_point(self.cursor, None, self.last_id) + + elif code == lv.EVENT.DRAW_PART_END: + # print("EVENT.DRAW_PART_END") + dsc = lv.obj_draw_part_dsc_t.__cast__(e.get_param()) + # if dsc.p1 and dsc.p2: + # print("p1, p2", dsc.p1,dsc.p2) + # print("p1.y, p2.y", dsc.p1.y, dsc.p2.y) + # print("last_id: ",self.last_id) + if dsc.part == lv.PART.CURSOR and dsc.p1 and dsc.p2 and dsc.p1.y == dsc.p2.y and self.last_id >= 0: + + v = self.ser_p[self.last_id] + + # print("value: ",v) + value_txt = str(v) + size = lv.point_t() + lv.txt_get_size(size, value_txt, lv.font_default(), 0, 0, lv.COORD.MAX, lv.TEXT_FLAG.NONE) + + a = lv.area_t() + a.y2 = dsc.p1.y - 5 + a.y1 = a.y2 - size.y - 10 + a.x1 = dsc.p1.x + 10 + a.x2 = a.x1 + size.x + 10 + + draw_rect_dsc = lv.draw_rect_dsc_t() + draw_rect_dsc.init() + draw_rect_dsc.bg_color = lv.palette_main(lv.PALETTE.BLUE) + draw_rect_dsc.radius = 3 + + lv.draw_rect(a, dsc.clip_area, draw_rect_dsc) + + draw_label_dsc = lv.draw_label_dsc_t() + draw_label_dsc.init() + draw_label_dsc.color = lv.color_white() + a.x1 += 5 + a.x2 -= 5 + a.y1 += 5 + a.y2 -= 5 + lv.draw_label(a, dsc.clip_area, draw_label_dsc, value_txt, None) + +example_chart_6 = ExampleChart_6() diff --git a/lib/lvgl/examples/widgets/chart/lv_example_chart_7.c b/lib/lvgl/examples/widgets/chart/lv_example_chart_7.c new file mode 100644 index 00000000..506f8875 --- /dev/null +++ b/lib/lvgl/examples/widgets/chart/lv_example_chart_7.c @@ -0,0 +1,66 @@ +#include "../../lv_examples.h" +#if LV_USE_CHART && LV_BUILD_EXAMPLES + +static void draw_event_cb(lv_event_t * e) +{ + lv_obj_draw_part_dsc_t * dsc = lv_event_get_draw_part_dsc(e); + if(dsc->part == LV_PART_ITEMS) { + lv_obj_t * obj = lv_event_get_target(e); + lv_chart_series_t * ser = lv_chart_get_series_next(obj, NULL); + uint32_t cnt = lv_chart_get_point_count(obj); + /*Make older value more transparent*/ + dsc->rect_dsc->bg_opa = (LV_OPA_COVER * dsc->id) / (cnt - 1); + + /*Make smaller values blue, higher values red*/ + lv_coord_t * x_array = lv_chart_get_x_array(obj, ser); + lv_coord_t * y_array = lv_chart_get_y_array(obj, ser); + /*dsc->id is the tells drawing order, but we need the ID of the point being drawn.*/ + uint32_t start_point = lv_chart_get_x_start_point(obj, ser); + uint32_t p_act = (start_point + dsc->id) % cnt; /*Consider start point to get the index of the array*/ + lv_opa_t x_opa = (x_array[p_act] * LV_OPA_50) / 200; + lv_opa_t y_opa = (y_array[p_act] * LV_OPA_50) / 1000; + + dsc->rect_dsc->bg_color = lv_color_mix(lv_palette_main(LV_PALETTE_RED), + lv_palette_main(LV_PALETTE_BLUE), + x_opa + y_opa); + } +} + +static void add_data(lv_timer_t * timer) +{ + LV_UNUSED(timer); + lv_obj_t * chart = timer->user_data; + lv_chart_set_next_value2(chart, lv_chart_get_series_next(chart, NULL), lv_rand(0, 200), lv_rand(0, 1000)); +} + +/** + * A scatter chart + */ +void lv_example_chart_7(void) +{ + lv_obj_t * chart = lv_chart_create(lv_scr_act()); + lv_obj_set_size(chart, 200, 150); + lv_obj_align(chart, LV_ALIGN_CENTER, 0, 0); + lv_obj_add_event_cb(chart, draw_event_cb, LV_EVENT_DRAW_PART_BEGIN, NULL); + lv_obj_set_style_line_width(chart, 0, LV_PART_ITEMS); /*Remove the lines*/ + + lv_chart_set_type(chart, LV_CHART_TYPE_SCATTER); + + lv_chart_set_axis_tick(chart, LV_CHART_AXIS_PRIMARY_X, 5, 5, 5, 1, true, 30); + lv_chart_set_axis_tick(chart, LV_CHART_AXIS_PRIMARY_Y, 10, 5, 6, 5, true, 50); + + lv_chart_set_range(chart, LV_CHART_AXIS_PRIMARY_X, 0, 200); + lv_chart_set_range(chart, LV_CHART_AXIS_PRIMARY_Y, 0, 1000); + + lv_chart_set_point_count(chart, 50); + + lv_chart_series_t * ser = lv_chart_add_series(chart, lv_palette_main(LV_PALETTE_RED), LV_CHART_AXIS_PRIMARY_Y); + uint32_t i; + for(i = 0; i < 50; i++) { + lv_chart_set_next_value2(chart, ser, lv_rand(0, 200), lv_rand(0, 1000)); + } + + lv_timer_create(add_data, 100, chart); +} + +#endif diff --git a/lib/lvgl/examples/widgets/chart/lv_example_chart_7.py b/lib/lvgl/examples/widgets/chart/lv_example_chart_7.py new file mode 100644 index 00000000..23f17e14 --- /dev/null +++ b/lib/lvgl/examples/widgets/chart/lv_example_chart_7.py @@ -0,0 +1,77 @@ +#!/opt/bin/lv_micropython -i +import utime as time +import lvgl as lv +import display_driver + +def draw_event_cb(e): + dsc = e.get_draw_part_dsc() + if dsc.part == lv.PART.ITEMS: + obj = e.get_target() + ser = obj.get_series_next(None) + cnt = obj.get_point_count() + # print("cnt: ",cnt) + # Make older value more transparent + dsc.rect_dsc.bg_opa = (lv.OPA.COVER * dsc.id) // (cnt - 1) + + # Make smaller values blue, higher values red + # x_array = chart.get_x_array(ser) + # y_array = chart.get_y_array(ser) + # dsc->id is the tells drawing order, but we need the ID of the point being drawn. + start_point = chart.get_x_start_point(ser) + # print("start point: ",start_point) + p_act = (start_point + dsc.id) % cnt # Consider start point to get the index of the array + # print("p_act", p_act) + x_opa = (x_array[p_act] * lv.OPA._50) // 200 + y_opa = (y_array[p_act] * lv.OPA._50) // 1000 + + dsc.rect_dsc.bg_color = lv.palette_main(lv.PALETTE.RED).color_mix( + lv.palette_main(lv.PALETTE.BLUE), + x_opa + y_opa) + +def add_data(timer,chart): + # print("add_data") + x = lv.rand(0,200) + y = lv.rand(0,1000) + chart.set_next_value2(ser, x, y) + # chart.set_next_value2(chart.gx, y) + x_array.pop(0) + x_array.append(x) + y_array.pop(0) + y_array.append(y) + +# +# A scatter chart +# + +chart = lv.chart(lv.scr_act()) +chart.set_size(200, 150) +chart.align(lv.ALIGN.CENTER, 0, 0) +chart.add_event_cb(draw_event_cb, lv.EVENT.DRAW_PART_BEGIN, None) +chart.set_style_line_width(0, lv.PART.ITEMS) # Remove the lines + +chart.set_type(lv.chart.TYPE.SCATTER) + +chart.set_axis_tick(lv.chart.AXIS.PRIMARY_X, 5, 5, 5, 1, True, 30) +chart.set_axis_tick(lv.chart.AXIS.PRIMARY_Y, 10, 5, 6, 5, True, 50) + +chart.set_range(lv.chart.AXIS.PRIMARY_X, 0, 200) +chart.set_range(lv.chart.AXIS.PRIMARY_Y, 0, 1000) + +chart.set_point_count(50) + +ser = chart.add_series(lv.palette_main(lv.PALETTE.RED), lv.chart.AXIS.PRIMARY_Y) + +x_array = [] +y_array = [] +for i in range(50): + x_array.append(lv.rand(0, 200)) + y_array.append(lv.rand(0, 1000)) + +ser.x_points = x_array +ser.y_points = y_array + +# Create an `lv_timer` to update the chart. + +timer = lv.timer_create_basic() +timer.set_period(100) +timer.set_cb(lambda src: add_data(timer,chart)) diff --git a/lib/lvgl/examples/widgets/chart/lv_example_chart_8.c b/lib/lvgl/examples/widgets/chart/lv_example_chart_8.c new file mode 100644 index 00000000..ca2c8f8c --- /dev/null +++ b/lib/lvgl/examples/widgets/chart/lv_example_chart_8.c @@ -0,0 +1,131 @@ +#include "../../lv_examples.h" +#if LV_USE_CHART && LV_DRAW_COMPLEX && LV_BUILD_EXAMPLES + +/* A struct is used to keep track of the series list because later we need to draw to the series in the reverse order to which they were initialised. */ +typedef struct { + lv_obj_t * obj; + lv_chart_series_t * series_list[3]; +} stacked_area_chart_t; + +static stacked_area_chart_t stacked_area_chart; + +/** + * Callback which draws the blocks of colour under the lines + **/ +static void draw_event_cb(lv_event_t * e) +{ + lv_obj_t * obj = lv_event_get_target(e); + + /*Add the faded area before the lines are drawn*/ + lv_obj_draw_part_dsc_t * dsc = lv_event_get_draw_part_dsc(e); + if(dsc->part == LV_PART_ITEMS) { + if(!dsc->p1 || !dsc->p2) + return; + + /*Add a line mask that keeps the area below the line*/ + lv_draw_mask_line_param_t line_mask_param; + lv_draw_mask_line_points_init(&line_mask_param, dsc->p1->x, dsc->p1->y, dsc->p2->x, dsc->p2->y, + LV_DRAW_MASK_LINE_SIDE_BOTTOM); + int16_t line_mask_id = lv_draw_mask_add(&line_mask_param, NULL); + + /*Draw a rectangle that will be affected by the mask*/ + lv_draw_rect_dsc_t draw_rect_dsc; + lv_draw_rect_dsc_init(&draw_rect_dsc); + draw_rect_dsc.bg_opa = LV_OPA_COVER; + draw_rect_dsc.bg_color = dsc->line_dsc->color; + + lv_area_t a; + a.x1 = dsc->p1->x; + a.x2 = dsc->p2->x; + a.y1 = LV_MIN(dsc->p1->y, dsc->p2->y); + a.y2 = obj->coords.y2 - + 13; /* -13 cuts off where the rectangle draws over the chart margin. Without this an area of 0 doesn't look like 0 */ + lv_draw_rect(dsc->draw_ctx, &draw_rect_dsc, &a); + + /*Remove the mask*/ + lv_draw_mask_free_param(&line_mask_param); + lv_draw_mask_remove_id(line_mask_id); + } +} + +/** + * Helper function to round a fixed point number + **/ +static int32_t round_fixed_point(int32_t n, int8_t shift) +{ + /* Create a bitmask to isolates the decimal part of the fixed point number */ + int32_t mask = 1; + for(int32_t bit_pos = 0; bit_pos < shift; bit_pos++) { + mask = (mask << 1) + 1; + } + + int32_t decimal_part = n & mask; + + /* Get 0.5 as fixed point */ + int32_t rounding_boundary = 1 << (shift - 1); + + /* Return either the integer part of n or the integer part + 1 */ + return (decimal_part < rounding_boundary) ? (n & ~mask) : ((n >> shift) + 1) << shift; +} + +/** + * Stacked area chart + */ +void lv_example_chart_8(void) +{ + /*Create a stacked_area_chart.obj*/ + stacked_area_chart.obj = lv_chart_create(lv_scr_act()); + lv_obj_set_size(stacked_area_chart.obj, 200, 150); + lv_obj_center(stacked_area_chart.obj); + lv_chart_set_type(stacked_area_chart.obj, LV_CHART_TYPE_LINE); + lv_chart_set_div_line_count(stacked_area_chart.obj, 5, 7); + lv_obj_add_event_cb(stacked_area_chart.obj, draw_event_cb, LV_EVENT_DRAW_PART_BEGIN, NULL); + + /* Set range to 0 to 100 for percentages. Draw ticks */ + lv_chart_set_range(stacked_area_chart.obj, LV_CHART_AXIS_PRIMARY_Y, 0, 100); + lv_chart_set_axis_tick(stacked_area_chart.obj, LV_CHART_AXIS_PRIMARY_Y, 3, 0, 5, 1, true, 30); + + /*Set point size to 0 so the lines are smooth */ + lv_obj_set_style_size(stacked_area_chart.obj, 0, LV_PART_INDICATOR); + + /*Add some data series*/ + stacked_area_chart.series_list[0] = lv_chart_add_series(stacked_area_chart.obj, lv_palette_main(LV_PALETTE_RED), + LV_CHART_AXIS_PRIMARY_Y); + stacked_area_chart.series_list[1] = lv_chart_add_series(stacked_area_chart.obj, lv_palette_main(LV_PALETTE_BLUE), + LV_CHART_AXIS_PRIMARY_Y); + stacked_area_chart.series_list[2] = lv_chart_add_series(stacked_area_chart.obj, lv_palette_main(LV_PALETTE_GREEN), + LV_CHART_AXIS_PRIMARY_Y); + + for(int point = 0; point < 10; point++) { + /* Make some random data */ + uint32_t vals[3] = {lv_rand(10, 20), lv_rand(20, 30), lv_rand(20, 30)}; + + int8_t fixed_point_shift = 5; + uint32_t total = vals[0] + vals[1] + vals[2]; + uint32_t draw_heights[3]; + uint32_t int_sum = 0; + uint32_t decimal_sum = 0; + + /* Fixed point cascade rounding ensures percentages add to 100 */ + for(int32_t series_index = 0; series_index < 3; series_index++) { + decimal_sum += (((vals[series_index] * 100) << fixed_point_shift) / total); + int_sum += (vals[series_index] * 100) / total; + + int32_t modifier = (round_fixed_point(decimal_sum, fixed_point_shift) >> fixed_point_shift) - int_sum; + + /* The draw heights are equal to the percentage of the total each value is + the cumulative sum of the previous percentages. + The accumulation is how the values get "stacked" */ + draw_heights[series_index] = int_sum + modifier; + + /* Draw to the series in the reverse order to which they were initialised. + Without this the higher values will draw on top of the lower ones. + This is because the Z-height of a series matches the order it was initialised */ + lv_chart_set_next_value(stacked_area_chart.obj, stacked_area_chart.series_list[3 - series_index - 1], + draw_heights[series_index]); + } + } + + lv_chart_refresh(stacked_area_chart.obj); +} + +#endif diff --git a/lib/lvgl/examples/widgets/chart/lv_example_chart_8.py b/lib/lvgl/examples/widgets/chart/lv_example_chart_8.py new file mode 100644 index 00000000..20996b3a --- /dev/null +++ b/lib/lvgl/examples/widgets/chart/lv_example_chart_8.py @@ -0,0 +1,124 @@ +import display_driver +import lvgl as lv + +# A class is used to keep track of the series list because later we +# need to draw to the series in the reverse order to which they were initialised. +class StackedAreaChart: + def __init__(self): + self.obj = None + self.series_list = [None, None, None] + +stacked_area_chart = StackedAreaChart() + +# +# Callback which draws the blocks of colour under the lines +# +def draw_event_cb(e): + + obj = e.get_target() + cont_a = lv.area_t() + obj.get_coords(cont_a) + + #Add the faded area before the lines are drawn + dsc = e.get_draw_part_dsc() + if dsc.part == lv.PART.ITEMS: + if not dsc.p1 or not dsc.p2: + return + + # Add a line mask that keeps the area below the line + line_mask_param = lv.draw_mask_line_param_t() + line_mask_param.points_init(dsc.p1.x, dsc.p1.y, dsc.p2.x, dsc.p2.y, lv.DRAW_MASK_LINE_SIDE.BOTTOM) + line_mask_id = lv.draw_mask_add(line_mask_param, None) + + #Draw a rectangle that will be affected by the mask + draw_rect_dsc = lv.draw_rect_dsc_t() + draw_rect_dsc.init() + draw_rect_dsc.bg_opa = lv.OPA.COVER + draw_rect_dsc.bg_color = dsc.line_dsc.color + + a = lv.area_t() + a.x1 = dsc.p1.x + a.x2 = dsc.p2.x + a.y1 = min(dsc.p1.y, dsc.p2.y) + a.y2 = cont_a.y2 - 13 # -13 cuts off where the rectangle draws over the chart margin. Without this an area of 0 doesn't look like 0 + dsc.draw_ctx.rect(draw_rect_dsc, a) + + # Remove the mask + lv.draw_mask_free_param(line_mask_param) + lv.draw_mask_remove_id(line_mask_id) + + +# +# Helper function to round a fixed point number +# +def round_fixed_point(n, shift): + # Create a bitmask to isolates the decimal part of the fixed point number + mask = 1 + for bit_pos in range(shift): + mask = (mask << 1) + 1 + + decimal_part = n & mask + + # Get 0.5 as fixed point + rounding_boundary = 1 << (shift - 1) + + # Return either the integer part of n or the integer part + 1 + if decimal_part < rounding_boundary: + return (n & ~mask) + return ((n >> shift) + 1) << shift + + +# +# Stacked area chart +# +def lv_example_chart_8(): + + #Create a stacked_area_chart.obj + stacked_area_chart.obj = lv.chart(lv.scr_act()) + stacked_area_chart.obj.set_size(200, 150) + stacked_area_chart.obj.center() + stacked_area_chart.obj.set_type( lv.chart.TYPE.LINE) + stacked_area_chart.obj.set_div_line_count(5, 7) + stacked_area_chart.obj.add_event_cb( draw_event_cb, lv.EVENT.DRAW_PART_BEGIN, None) + + # Set range to 0 to 100 for percentages. Draw ticks + stacked_area_chart.obj.set_range(lv.chart.AXIS.PRIMARY_Y,0,100) + stacked_area_chart.obj.set_axis_tick(lv.chart.AXIS.PRIMARY_Y, 3, 0, 5, 1, True, 30) + + #Set point size to 0 so the lines are smooth + stacked_area_chart.obj.set_style_size(0, lv.PART.INDICATOR) + + # Add some data series + stacked_area_chart.series_list[0] = stacked_area_chart.obj.add_series(lv.palette_main(lv.PALETTE.RED), lv.chart.AXIS.PRIMARY_Y) + stacked_area_chart.series_list[1] = stacked_area_chart.obj.add_series(lv.palette_main(lv.PALETTE.BLUE), lv.chart.AXIS.PRIMARY_Y) + stacked_area_chart.series_list[2] = stacked_area_chart.obj.add_series(lv.palette_main(lv.PALETTE.GREEN), lv.chart.AXIS.PRIMARY_Y) + + for point in range(10): + # Make some random data + vals = [lv.rand(10, 20), lv.rand(20, 30), lv.rand(20, 30)] + + fixed_point_shift = 5 + total = vals[0] + vals[1] + vals[2] + draw_heights = [0, 0, 0] + int_sum = 0 + decimal_sum = 0 + + # Fixed point cascade rounding ensures percentages add to 100 + for series_index in range(3): + decimal_sum += int(((vals[series_index] * 100) << fixed_point_shift) // total) + int_sum += int((vals[series_index] * 100) / total) + + modifier = (round_fixed_point(decimal_sum, fixed_point_shift) >> fixed_point_shift) - int_sum + + # The draw heights are equal to the percentage of the total each value is + the cumulative sum of the previous percentages. + # The accumulation is how the values get "stacked" + draw_heights[series_index] = int(int_sum + modifier) + + # Draw to the series in the reverse order to which they were initialised. + # Without this the higher values will draw on top of the lower ones. + # This is because the Z-height of a series matches the order it was initialised + stacked_area_chart.obj.set_next_value( stacked_area_chart.series_list[3 - series_index - 1], draw_heights[series_index]) + + stacked_area_chart.obj.refresh() + +lv_example_chart_8() diff --git a/lib/lvgl/examples/widgets/chart/lv_example_chart_9.c b/lib/lvgl/examples/widgets/chart/lv_example_chart_9.c new file mode 100644 index 00000000..c94b564f --- /dev/null +++ b/lib/lvgl/examples/widgets/chart/lv_example_chart_9.c @@ -0,0 +1,46 @@ +#include "../../lv_examples.h" +#if LV_USE_CHART && LV_DRAW_COMPLEX && LV_BUILD_EXAMPLES + + +static void add_data(lv_timer_t * t) +{ + lv_obj_t * chart = t->user_data; + lv_chart_series_t * ser = lv_chart_get_series_next(chart, NULL); + + lv_chart_set_next_value(chart, ser, lv_rand(10, 90)); + + uint16_t p = lv_chart_get_point_count(chart); + uint16_t s = lv_chart_get_x_start_point(chart, ser); + lv_coord_t * a = lv_chart_get_y_array(chart, ser); + + a[(s + 1) % p] = LV_CHART_POINT_NONE; + a[(s + 2) % p] = LV_CHART_POINT_NONE; + a[(s + 2) % p] = LV_CHART_POINT_NONE; + + lv_chart_refresh(chart); +} + +/** + * Circular line chart with gap + */ +void lv_example_chart_9(void) +{ + /*Create a stacked_area_chart.obj*/ + lv_obj_t * chart = lv_chart_create(lv_scr_act()); + lv_chart_set_update_mode(chart, LV_CHART_UPDATE_MODE_CIRCULAR); + lv_obj_set_size(chart, 200, 150); + lv_obj_center(chart); + + lv_chart_set_point_count(chart, 30); + lv_chart_series_t * ser = lv_chart_add_series(chart, lv_palette_main(LV_PALETTE_RED), LV_CHART_AXIS_PRIMARY_Y); + /*Prefill with data*/ + uint32_t i; + for(i = 0; i < 30; i++) { + lv_chart_set_next_value(chart, ser, lv_rand(10, 90)); + } + + lv_timer_create(add_data, 300, chart); + +} + +#endif diff --git a/lib/lvgl/examples/widgets/chart/lv_example_chart_9.py b/lib/lvgl/examples/widgets/chart/lv_example_chart_9.py new file mode 100644 index 00000000..37b16b39 --- /dev/null +++ b/lib/lvgl/examples/widgets/chart/lv_example_chart_9.py @@ -0,0 +1,31 @@ +import display_driver +import lvgl as lv + +def add_data(t): + chart.set_next_value(ser, lv.rand(10, 90)) + + p = chart.get_point_count() + s = chart.get_x_start_point(ser) + a = chart.get_y_array(ser) + + a[(s + 1) % p] = lv.CHART_POINT.NONE + a[(s + 2) % p] = lv.CHART_POINT.NONE + a[(s + 3) % p] = lv.CHART_POINT.NONE + chart.refresh() + +# +# Circular line chart with gap +# +chart = lv.chart(lv.scr_act()) + +chart.set_update_mode(lv.chart.UPDATE_MODE.CIRCULAR) +chart.set_size(200, 150) +chart.center() + +chart.set_point_count(30) +ser = chart.add_series(lv.palette_main(lv.PALETTE.RED), lv.chart.AXIS.PRIMARY_Y) +#Prefill with data +for i in range(0, 30): + chart.set_next_value(ser, lv.rand(10, 90)) + +lv.timer_create(add_data, 200, None) |
