From f23873e3f50f2003d4a01e6f758f7d78765c9462 Mon Sep 17 00:00:00 2001 From: pete-pjb Date: Mon, 15 Jun 2020 17:15:05 +0100 Subject: [PATCH 1/6] Added Functions to extend chart functionality as follows: /** * Set the index of the x-axis start point in the data array * @param chart pointer to a chart object * @param ser pointer to a data series on 'chart' * @param id the index of the x point in the data array */ void lv_chart_set_x_start_point(lv_obj_t * chart, lv_chart_series_t * ser, uint16_t id); /** * Set an external array of data points to use for the chart * NOTE: It is the users responsibility to make sure the point_cnt matches the external array size. * @param chart pointer to a chart object * @param ser pointer to a data series on 'chart' * @param array external array of points for chart */ void lv_chart_set_ext_array(lv_obj_t * chart, lv_chart_series_t * ser, lv_coord_t array[], uint16_t point_cnt ); /** * Set an individual point value in the chart series directly based on index * @param chart pointer to a chart object * @param ser pointer to a data series on 'chart' * @param value value to assign to array point * @param id the index of the x point in the array */ void lv_chart_set_point_id(lv_obj_t * chart, lv_chart_series_t * ser, lv_coord_t value, uint16_t id); /** * get the current index of the x-axis start point in the data array * @param chart pointer to a chart object * @param ser pointer to a data series on 'chart' * @return the index of the current x start point in the data array */ uint16_t lv_chart_get_x_start_point(lv_obj_t * chart, lv_chart_series_t * ser); /** * Get an individual point value in the chart series directly based on index * @param chart pointer to a chart object * @param ser pointer to a data series on 'chart' * @param id the index of the x point in the array * @return value of array point at index id */ lv_coord_t lv_chart_get_point_id(lv_obj_t * chart, lv_chart_series_t * ser, uint16_t id); --- src/lv_widgets/lv_chart.c | 161 +++++++++++++++++++++++++++++--------- src/lv_widgets/lv_chart.h | 46 ++++++++++- 2 files changed, 171 insertions(+), 36 deletions(-) diff --git a/src/lv_widgets/lv_chart.c b/src/lv_widgets/lv_chart.c index 35e421b01..f3e82b4cd 100644 --- a/src/lv_widgets/lv_chart.c +++ b/src/lv_widgets/lv_chart.c @@ -303,43 +303,44 @@ void lv_chart_set_point_count(lv_obj_t * chart, uint16_t point_cnt) if(point_cnt < 1) point_cnt = 1; _LV_LL_READ_BACK(ext->series_ll, ser) { - if(ser->start_point != 0) { - lv_coord_t * new_points = lv_mem_alloc(sizeof(lv_coord_t) * point_cnt); - LV_ASSERT_MEM(new_points); - if(new_points == NULL) return; + if( !ser->ext_buf_assigned ) { + if(ser->start_point != 0) { + lv_coord_t * new_points = lv_mem_alloc(sizeof(lv_coord_t) * point_cnt); + LV_ASSERT_MEM(new_points); + if(new_points == NULL) return; - if(point_cnt >= point_cnt_old) { - for(i = 0; i < point_cnt_old; i++) { - new_points[i] = - ser->points[(i + ser->start_point) % point_cnt_old]; /*Copy old contents to new array*/ - } - for(i = point_cnt_old; i < point_cnt; i++) { - new_points[i] = def; /*Fill up the rest with default value*/ - } - } - else { - for(i = 0; i < point_cnt; i++) { - new_points[i] = - ser->points[(i + ser->start_point) % point_cnt_old]; /*Copy old contents to new array*/ - } - } - - /*Switch over pointer from old to new*/ - lv_mem_free(ser->points); - ser->points = new_points; - } - else { - ser->points = lv_mem_realloc(ser->points, sizeof(lv_coord_t) * point_cnt); - LV_ASSERT_MEM(ser->points); - if(ser->points == NULL) return; - /*Initialize the new points*/ - if(point_cnt > point_cnt_old) { - for(i = point_cnt_old - 1; i < point_cnt; i++) { - ser->points[i] = def; - } - } - } + if(point_cnt >= point_cnt_old) { + for(i = 0; i < point_cnt_old; i++) { + new_points[i] = + ser->points[(i + ser->start_point) % point_cnt_old]; /*Copy old contents to new array*/ + } + for(i = point_cnt_old; i < point_cnt; i++) { + new_points[i] = def; /*Fill up the rest with default value*/ + } + } + else { + for(i = 0; i < point_cnt; i++) { + new_points[i] = + ser->points[(i + ser->start_point) % point_cnt_old]; /*Copy old contents to new array*/ + } + } + /*Switch over pointer from old to new*/ + lv_mem_free(ser->points); + ser->points = new_points; + } + else { + ser->points = lv_mem_realloc(ser->points, sizeof(lv_coord_t) * point_cnt); + LV_ASSERT_MEM(ser->points); + if(ser->points == NULL) return; + /*Initialize the new points*/ + if(point_cnt > point_cnt_old) { + for(i = point_cnt_old - 1; i < point_cnt; i++) { + ser->points[i] = def; + } + } + } + } ser->start_point = 0; } @@ -540,6 +541,64 @@ void lv_chart_set_secondary_y_tick_texts(lv_obj_t * chart, const char * list_of_ ext->secondary_y_axis.options = options; } +/** + * Set the index of the x-axis start point in the data array + * @param chart pointer to a chart object + * @param ser pointer to a data series on 'chart' + * @param id the index of the x point in the data array + */ +void lv_chart_set_x_start_point(lv_obj_t * chart, lv_chart_series_t * ser, uint16_t id) +{ + LV_ASSERT_OBJ(chart, LV_OBJX_NAME); + LV_ASSERT_NULL(ser); + + if(chart == NULL || ser == NULL) return; + lv_chart_ext_t * ext = lv_obj_get_ext_attr(chart); + if(ext == NULL) return; + if( id >= ext->point_cnt ) return; + ser->start_point = id; +} + +/** + * Set an external array of data points to use for the chart + * NOTE: It is the users responsibility to make sure the point_cnt matches the external array size. + * @param chart pointer to a chart object + * @param ser pointer to a data series on 'chart' + * @param array external array of points for chart + * @param point_cnt number of external points in the array + */ +void lv_chart_set_ext_array(lv_obj_t * chart, lv_chart_series_t * ser, lv_coord_t array[], uint16_t point_cnt) +{ + LV_ASSERT_OBJ(chart, LV_OBJX_NAME); + LV_ASSERT_NULL(ser); + + if(chart == NULL || ser == NULL) return; + lv_chart_ext_t * ext = lv_obj_get_ext_attr(chart); + if( !ser->ext_buf_assigned && ser->points ) lv_mem_free(ser->points); + ser->ext_buf_assigned = true; + ser->points = array; + ext->point_cnt = point_cnt; +} + +/** + * Set an individual point y value in the chart series directly based on index + * @param chart pointer to a chart object + * @param ser pointer to a data series on 'chart' + * @param value value to assign to array point + * @param id the index of the x point in the array + */ +void lv_chart_set_point_id(lv_obj_t * chart, lv_chart_series_t * ser, lv_coord_t value, uint16_t id) +{ + LV_ASSERT_OBJ(chart, LV_OBJX_NAME); + LV_ASSERT_NULL(ser); + + if(chart == NULL || ser == NULL) return; + lv_chart_ext_t * ext = lv_obj_get_ext_attr(chart); + if(ext == NULL) return; + if( id >= ext->point_cnt ) return; + ser->points[id] = value; +} + /*===================== * Getter functions *====================*/ @@ -570,6 +629,38 @@ uint16_t lv_chart_get_point_count(const lv_obj_t * chart) return ext->point_cnt; } +/** + * Get the current index of the x-axis start point in the data array + * @param chart pointer to a chart object + * @param ser pointer to a data series on 'chart' + * @return the index of the current x start point in the data array + */ +uint16_t lv_chart_get_x_start_point(lv_obj_t * chart, lv_chart_series_t * ser) +{ + LV_ASSERT_OBJ(chart, LV_OBJX_NAME); + LV_ASSERT_NULL(ser); + + return(ser->start_point); +} + +/** + * Get an individual point y value in the chart series directly based on index + * @param chart pointer to a chart object + * @param ser pointer to a data series on 'chart' + * @param id the index of the x point in the array + * @return value of array point at index id + */ +lv_coord_t lv_chart_get_point_id(lv_obj_t * chart, lv_chart_series_t * ser, uint16_t id) +{ + LV_ASSERT_OBJ(chart, LV_OBJX_NAME); + LV_ASSERT_NULL(serie); + + lv_chart_ext_t * ext = lv_obj_get_ext_attr(chart); + if( id >= ext->point_cnt ) id = 0; + return(ser->points[id]); + +} + /*===================== * Other functions *====================*/ diff --git a/src/lv_widgets/lv_chart.h b/src/lv_widgets/lv_chart.h index 77534cc8c..c1ff2b524 100644 --- a/src/lv_widgets/lv_chart.h +++ b/src/lv_widgets/lv_chart.h @@ -56,13 +56,14 @@ typedef struct { lv_coord_t * points; lv_color_t color; uint16_t start_point; + uint8_t ext_buf_assigned : 1; } lv_chart_series_t; /** Data of axis */ enum { LV_CHART_AXIS_SKIP_LAST_TICK = 0x00, /**< don't draw the last tick */ LV_CHART_AXIS_DRAW_LAST_TICK = 0x01, /**< draw the last tick */ - LV_CHART_AXIS_INVERSE_LABELS_ORDER = 0x02 /**< draw tick labels in an inversed order*/ + LV_CHART_AXIS_INVERSE_LABELS_ORDER = 0x02 /**< draw tick labels in an inverted order*/ }; typedef uint8_t lv_chart_axis_options_t; @@ -260,6 +261,32 @@ void lv_chart_set_secondary_y_tick_texts(lv_obj_t * chart, const char * list_of_ void lv_chart_set_y_tick_texts(lv_obj_t * chart, const char * list_of_values, uint8_t num_tick_marks, lv_chart_axis_options_t options); +/** + * Set the index of the x-axis start point in the data array + * @param chart pointer to a chart object + * @param ser pointer to a data series on 'chart' + * @param id the index of the x point in the data array + */ +void lv_chart_set_x_start_point(lv_obj_t * chart, lv_chart_series_t * ser, uint16_t id); + +/** + * Set an external array of data points to use for the chart + * NOTE: It is the users responsibility to make sure the point_cnt matches the external array size. + * @param chart pointer to a chart object + * @param ser pointer to a data series on 'chart' + * @param array external array of points for chart + */ +void lv_chart_set_ext_array(lv_obj_t * chart, lv_chart_series_t * ser, lv_coord_t array[], uint16_t point_cnt ); + +/** + * Set an individual point value in the chart series directly based on index + * @param chart pointer to a chart object + * @param ser pointer to a data series on 'chart' + * @param value value to assign to array point + * @param id the index of the x point in the array + */ +void lv_chart_set_point_id(lv_obj_t * chart, lv_chart_series_t * ser, lv_coord_t value, uint16_t id); + /*===================== * Getter functions *====================*/ @@ -278,6 +305,23 @@ lv_chart_type_t lv_chart_get_type(const lv_obj_t * chart); */ uint16_t lv_chart_get_point_count(const lv_obj_t * chart); +/** + * get the current index of the x-axis start point in the data array + * @param chart pointer to a chart object + * @param ser pointer to a data series on 'chart' + * @return the index of the current x start point in the data array + */ +uint16_t lv_chart_get_x_start_point(lv_obj_t * chart, lv_chart_series_t * ser); + +/** + * Get an individual point value in the chart series directly based on index + * @param chart pointer to a chart object + * @param ser pointer to a data series on 'chart' + * @param id the index of the x point in the array + * @return value of array point at index id + */ +lv_coord_t lv_chart_get_point_id(lv_obj_t * chart, lv_chart_series_t * ser, uint16_t id); + /*===================== * Other functions *====================*/ From fe5663908c70b3df40e8d8b82b90c61b660b1eb1 Mon Sep 17 00:00:00 2001 From: pete-pjb Date: Mon, 15 Jun 2020 17:29:33 +0100 Subject: [PATCH 2/6] Fix unused variable --- src/lv_widgets/lv_chart.c | 3 +-- src/lv_widgets/lv_chart.h | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/lv_widgets/lv_chart.c b/src/lv_widgets/lv_chart.c index f3e82b4cd..cdea00cc2 100644 --- a/src/lv_widgets/lv_chart.c +++ b/src/lv_widgets/lv_chart.c @@ -631,11 +631,10 @@ uint16_t lv_chart_get_point_count(const lv_obj_t * chart) /** * Get the current index of the x-axis start point in the data array - * @param chart pointer to a chart object * @param ser pointer to a data series on 'chart' * @return the index of the current x start point in the data array */ -uint16_t lv_chart_get_x_start_point(lv_obj_t * chart, lv_chart_series_t * ser) +uint16_t lv_chart_get_x_start_point(lv_chart_series_t * ser) { LV_ASSERT_OBJ(chart, LV_OBJX_NAME); LV_ASSERT_NULL(ser); diff --git a/src/lv_widgets/lv_chart.h b/src/lv_widgets/lv_chart.h index c1ff2b524..85e66afe1 100644 --- a/src/lv_widgets/lv_chart.h +++ b/src/lv_widgets/lv_chart.h @@ -307,11 +307,10 @@ uint16_t lv_chart_get_point_count(const lv_obj_t * chart); /** * get the current index of the x-axis start point in the data array - * @param chart pointer to a chart object * @param ser pointer to a data series on 'chart' * @return the index of the current x start point in the data array */ -uint16_t lv_chart_get_x_start_point(lv_obj_t * chart, lv_chart_series_t * ser); +uint16_t lv_chart_get_x_start_point(lv_chart_series_t * ser); /** * Get an individual point value in the chart series directly based on index From 832dbd644b21352a46298de8328d4aef47773e4e Mon Sep 17 00:00:00 2001 From: pete-pjb Date: Tue, 16 Jun 2020 09:31:37 +0100 Subject: [PATCH 3/6] Remove redundant assert --- src/lv_widgets/lv_chart.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/lv_widgets/lv_chart.c b/src/lv_widgets/lv_chart.c index cdea00cc2..8e6c37fb1 100644 --- a/src/lv_widgets/lv_chart.c +++ b/src/lv_widgets/lv_chart.c @@ -636,7 +636,6 @@ uint16_t lv_chart_get_point_count(const lv_obj_t * chart) */ uint16_t lv_chart_get_x_start_point(lv_chart_series_t * ser) { - LV_ASSERT_OBJ(chart, LV_OBJX_NAME); LV_ASSERT_NULL(ser); return(ser->start_point); From ad215c5b4b7f35ddbf0a6eb525b21aae1e6e576b Mon Sep 17 00:00:00 2001 From: PeterB Date: Tue, 16 Jun 2020 16:24:37 +0100 Subject: [PATCH 4/6] Finalise changes for new Chart Functions --- src/lv_widgets/lv_chart.c | 6 +++--- src/lv_widgets/lv_chart.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/lv_widgets/lv_chart.c b/src/lv_widgets/lv_chart.c index 8e6c37fb1..d32f6565d 100644 --- a/src/lv_widgets/lv_chart.c +++ b/src/lv_widgets/lv_chart.c @@ -739,9 +739,9 @@ static lv_res_t lv_chart_signal(lv_obj_t * chart, lv_signal_t sign, void * param lv_chart_ext_t * ext = lv_obj_get_ext_attr(chart); if(sign == LV_SIGNAL_CLEANUP) { - lv_coord_t ** datal; - _LV_LL_READ(ext->series_ll, datal) { - lv_mem_free(*datal); + lv_chart_series_t * ser; + _LV_LL_READ(ext->series_ll, ser) { + if(!ser->ext_buf_assigned) lv_mem_free(ser->points); } _lv_ll_clear(&ext->series_ll); diff --git a/src/lv_widgets/lv_chart.h b/src/lv_widgets/lv_chart.h index 85e66afe1..f9181abb2 100644 --- a/src/lv_widgets/lv_chart.h +++ b/src/lv_widgets/lv_chart.h @@ -79,7 +79,7 @@ typedef struct { typedef struct { /*No inherited ext*/ /*Ext. of ancestor*/ /*New data for this type */ - lv_ll_t series_ll; /*Linked list for the data line pointers (stores lv_chart_dl_t)*/ + lv_ll_t series_ll; /*Linked list for the data line pointers (stores lv_chart_series_t)*/ lv_coord_t ymin; /*y min value (used to scale the data)*/ lv_coord_t ymax; /*y max value (used to scale the data)*/ uint8_t hdiv_cnt; /*Number of horizontal division lines*/ From ae748cfffab87e3f6a78e26e5d855e77ca46197f Mon Sep 17 00:00:00 2001 From: pete-pjb Date: Tue, 16 Jun 2020 18:04:36 +0100 Subject: [PATCH 5/6] Fix initialisation problem. Found that new structure parmaeter ext_buf_assigned needs to be initialised to false in lv_chart_add_series() as sometimes is set true depending on what was previously in the heap where it was allocated. --- src/lv_widgets/lv_chart.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/lv_widgets/lv_chart.c b/src/lv_widgets/lv_chart.c index d32f6565d..1b7963b0c 100644 --- a/src/lv_widgets/lv_chart.c +++ b/src/lv_widgets/lv_chart.c @@ -191,6 +191,7 @@ lv_chart_series_t * lv_chart_add_series(lv_obj_t * chart, lv_color_t color) } ser->start_point = 0; + ser->ext_buf_assigned = false; uint16_t i; lv_coord_t * p_tmp = ser->points; From 4a953b9d9da0a90059950165f115c826f2763532 Mon Sep 17 00:00:00 2001 From: pete-pjb Date: Tue, 16 Jun 2020 18:24:05 +0100 Subject: [PATCH 6/6] Free memory for series_ll --- src/lv_widgets/lv_chart.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/lv_widgets/lv_chart.c b/src/lv_widgets/lv_chart.c index 1b7963b0c..fb9c5c1c2 100644 --- a/src/lv_widgets/lv_chart.c +++ b/src/lv_widgets/lv_chart.c @@ -743,6 +743,7 @@ static lv_res_t lv_chart_signal(lv_obj_t * chart, lv_signal_t sign, void * param lv_chart_series_t * ser; _LV_LL_READ(ext->series_ll, ser) { if(!ser->ext_buf_assigned) lv_mem_free(ser->points); + lv_mem_free(ser); } _lv_ll_clear(&ext->series_ll);