mirror of
https://github.com/lvgl/lvgl.git
synced 2025-01-14 06:42:58 +08:00
Merge pull request #597 from stheil/master
lv_chart: Use circular buffer to avoid memcopy for every new data point
This commit is contained in:
commit
1efd06ef56
@ -58,8 +58,6 @@ static lv_signal_func_t ancestor_signal;
|
||||
*/
|
||||
lv_obj_t * lv_chart_create(lv_obj_t * par, const lv_obj_t * copy)
|
||||
{
|
||||
|
||||
|
||||
LV_LOG_TRACE("chart create started");
|
||||
|
||||
/*Create the ancestor basic object*/
|
||||
@ -153,6 +151,8 @@ lv_chart_series_t * lv_chart_add_series(lv_obj_t * chart, lv_color_t color)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ser->start_point = 0;
|
||||
|
||||
uint16_t i;
|
||||
lv_coord_t * p_tmp = ser->points;
|
||||
for(i = 0; i < ext->point_cnt; i++) {
|
||||
@ -179,8 +179,11 @@ void lv_chart_clear_serie(lv_obj_t * chart, lv_chart_series_t * serie)
|
||||
return;
|
||||
for(uint32_t i = 0; i < ext->point_cnt; i++)
|
||||
{
|
||||
serie->points[i] = -1;
|
||||
serie->points[i] = LV_CHART_POINT_DEF;
|
||||
}
|
||||
|
||||
serie->start_point = 0;
|
||||
|
||||
}
|
||||
|
||||
/*=====================
|
||||
@ -254,6 +257,28 @@ void lv_chart_set_point_count(lv_obj_t * chart, uint16_t point_cnt)
|
||||
if(point_cnt < 1) point_cnt = 1;
|
||||
|
||||
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_mem_assert(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_mem_assert(ser->points);
|
||||
if(ser->points == NULL) return;
|
||||
@ -265,7 +290,11 @@ void lv_chart_set_point_count(lv_obj_t * chart, uint16_t point_cnt)
|
||||
}
|
||||
}
|
||||
|
||||
ser->start_point = 0;
|
||||
}
|
||||
|
||||
ext->point_cnt = point_cnt;
|
||||
|
||||
lv_chart_refresh(chart);
|
||||
}
|
||||
|
||||
@ -323,6 +352,7 @@ void lv_chart_init_points(lv_obj_t * chart, lv_chart_series_t * ser, lv_coord_t
|
||||
for(i = 0; i < ext->point_cnt; i++) {
|
||||
ser->points[i] = y;
|
||||
}
|
||||
ser->start_point = 0;
|
||||
lv_chart_refresh(chart);
|
||||
}
|
||||
|
||||
@ -336,27 +366,24 @@ void lv_chart_set_points(lv_obj_t * chart, lv_chart_series_t * ser, lv_coord_t *
|
||||
{
|
||||
lv_chart_ext_t * ext = lv_obj_get_ext_attr(chart);
|
||||
memcpy(ser->points, y_array, ext->point_cnt * (sizeof(lv_coord_t)));
|
||||
ser->start_point = 0;
|
||||
lv_chart_refresh(chart);
|
||||
}
|
||||
|
||||
/**
|
||||
* Shift all data right and set the most right data on a data line
|
||||
* Shift all data left and set the rightmost data on a data line
|
||||
* @param chart pointer to chart object
|
||||
* @param ser pointer to a data series on 'chart'
|
||||
* @param y the new value of the most right data
|
||||
* @param y the new value of the rightmost data
|
||||
*/
|
||||
void lv_chart_set_next(lv_obj_t * chart, lv_chart_series_t * ser, lv_coord_t y)
|
||||
{
|
||||
lv_chart_ext_t * ext = lv_obj_get_ext_attr(chart);
|
||||
|
||||
uint16_t i;
|
||||
for(i = 0; i < ext->point_cnt - 1; i++) {
|
||||
ser->points[i] = ser->points[i + 1];
|
||||
}
|
||||
ser->points[ser->start_point] = y; /*This was the place of the former left most value, after shifting it is the rightmost*/
|
||||
ser->start_point = (ser->start_point + 1) % ext->point_cnt;
|
||||
|
||||
ser->points[ext->point_cnt - 1] = y;
|
||||
lv_chart_refresh(chart);
|
||||
|
||||
}
|
||||
|
||||
/*=====================
|
||||
@ -582,6 +609,8 @@ static void lv_chart_draw_lines(lv_obj_t * chart, const lv_area_t * mask)
|
||||
lv_coord_t x_ofs = chart->coords.x1;
|
||||
lv_coord_t y_ofs = chart->coords.y1;
|
||||
int32_t y_tmp;
|
||||
lv_coord_t p_prev;
|
||||
lv_coord_t p_act;
|
||||
lv_chart_series_t * ser;
|
||||
lv_opa_t opa_scale = lv_obj_get_opa_scale(chart);
|
||||
lv_style_t style;
|
||||
@ -595,7 +624,9 @@ static void lv_chart_draw_lines(lv_obj_t * chart, const lv_area_t * mask)
|
||||
|
||||
p1.x = 0 + x_ofs;
|
||||
p2.x = 0 + x_ofs;
|
||||
y_tmp = (int32_t)((int32_t) ser->points[0] - ext->ymin) * h;
|
||||
|
||||
p_prev = ser->start_point;
|
||||
y_tmp = (int32_t)((int32_t) ser->points[p_prev] - ext->ymin) * h;
|
||||
y_tmp = y_tmp / (ext->ymax - ext->ymin);
|
||||
p2.y = h - y_tmp + y_ofs;
|
||||
|
||||
@ -605,12 +636,16 @@ static void lv_chart_draw_lines(lv_obj_t * chart, const lv_area_t * mask)
|
||||
|
||||
p2.x = ((w * i) / (ext->point_cnt - 1)) + x_ofs;
|
||||
|
||||
y_tmp = (int32_t)((int32_t) ser->points[i] - ext->ymin) * h;
|
||||
p_act = (ser->start_point + i) % ext->point_cnt;
|
||||
|
||||
y_tmp = (int32_t)((int32_t) ser->points[p_act] - ext->ymin) * h;
|
||||
y_tmp = y_tmp / (ext->ymax - ext->ymin);
|
||||
p2.y = h - y_tmp + y_ofs;
|
||||
|
||||
if(ser->points[i - 1] >= 0 && ser->points[i] >= 0)
|
||||
if(ser->points[p_prev] != LV_CHART_POINT_DEF && ser->points[p_act] != LV_CHART_POINT_DEF)
|
||||
lv_draw_line(&p1, &p2, mask, &style, opa_scale);
|
||||
|
||||
p_prev = p_act;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -631,6 +666,7 @@ static void lv_chart_draw_points(lv_obj_t * chart, const lv_area_t * mask)
|
||||
lv_coord_t x_ofs = chart->coords.x1;
|
||||
lv_coord_t y_ofs = chart->coords.y1;
|
||||
int32_t y_tmp;
|
||||
lv_coord_t p_act;
|
||||
lv_chart_series_t * ser;
|
||||
uint8_t series_cnt = 0;
|
||||
lv_style_t style_point;
|
||||
@ -651,14 +687,14 @@ static void lv_chart_draw_points(lv_obj_t * chart, const lv_area_t * mask)
|
||||
cir_a.x1 = ((w * i) / (ext->point_cnt - 1)) + x_ofs;
|
||||
cir_a.x2 = cir_a.x1 + style_point.body.radius;
|
||||
cir_a.x1 -= style_point.body.radius;
|
||||
|
||||
y_tmp = (int32_t)((int32_t) ser->points[i] - ext->ymin) * h;
|
||||
p_act = (ser->start_point + i) % ext->point_cnt;
|
||||
y_tmp = (int32_t)((int32_t) ser->points[p_act] - ext->ymin) * h;
|
||||
y_tmp = y_tmp / (ext->ymax - ext->ymin);
|
||||
cir_a.y1 = h - y_tmp + y_ofs;
|
||||
cir_a.y2 = cir_a.y1 + style_point.body.radius;
|
||||
cir_a.y1 -= style_point.body.radius;
|
||||
|
||||
if(ser->points[i] >= 0)
|
||||
if(ser->points[p_act] != LV_CHART_POINT_DEF)
|
||||
lv_draw_rect(&cir_a, mask, &style_point, lv_obj_get_opa_scale(chart));
|
||||
}
|
||||
series_cnt++;
|
||||
@ -695,6 +731,7 @@ static void lv_chart_draw_cols(lv_obj_t * chart, const lv_area_t * mask)
|
||||
col_a.y2 = chart->coords.y2;
|
||||
|
||||
lv_coord_t x_act;
|
||||
printf("\n", y_tmp);
|
||||
|
||||
/*Go through all points*/
|
||||
for(i = 0; i < ext->point_cnt; i ++) {
|
||||
@ -709,12 +746,14 @@ static void lv_chart_draw_cols(lv_obj_t * chart, const lv_area_t * mask)
|
||||
col_a.x2 = col_a.x1 + col_w;
|
||||
x_act += col_w;
|
||||
|
||||
y_tmp = (int32_t)((int32_t) ser->points[i] - ext->ymin) * h;
|
||||
lv_coord_t p_act = (ser->start_point + i) % ext->point_cnt;
|
||||
y_tmp = (int32_t)((int32_t) ser->points[p_act] - ext->ymin) * h;
|
||||
y_tmp = y_tmp / (ext->ymax - ext->ymin);
|
||||
printf("ytmp:%d\n", y_tmp);
|
||||
col_a.y1 = h - y_tmp + chart->coords.y1;
|
||||
|
||||
mask_ret = lv_area_intersect(&col_mask, mask, &col_a);
|
||||
if(mask_ret != false && ser->points[i] >= 0) {
|
||||
if(mask_ret != false && ser->points[p_act] != LV_CHART_POINT_DEF) {
|
||||
lv_draw_rect(&chart->coords, &col_mask, &rects, lv_obj_get_opa_scale(chart));
|
||||
}
|
||||
}
|
||||
|
@ -36,6 +36,7 @@ typedef struct
|
||||
{
|
||||
lv_coord_t * points;
|
||||
lv_color_t color;
|
||||
uint16_t start_point;
|
||||
} lv_chart_series_t;
|
||||
|
||||
/*Data of chart */
|
||||
|
Loading…
x
Reference in New Issue
Block a user