Hi @Muzgog ,
Here is a quick ‘proof of concept’ example for you…
You can add historic entries to the table by calling the function add_history_data( )
from anywhere in your code. I have created a define to limit the size of the table #define MAX_HISTORIC_ITEMS
(see the table_example.h file below). Once the maximum number of entries is reached the oldest is lost and the newest added at the bottom…
C code file(table_example.c):
/*
* table_example.c
*
* Created on: 29 Jun 2023
* Author: PeterB
*/
#include <stddef.h>
#include <stdlib.h>
#include <stdio.h>
#include "lvgl.h"
#include "table_example.h"
static history_list_t historic_list = { NULL, NULL, NULL, 0 };
static lv_obj_t * table;
static history_data_t *get_historic_by_idx( uint32_t idx ) {
history_entry_t *temp_ptr = historic_list.begin;
for( uint32_t i = 0; i < idx; i++ ) {
if( temp_ptr != NULL ) temp_ptr = temp_ptr->next; else break;
}
return &temp_ptr->data;
}
static void add_history_data( history_data_t in_data ) {
history_entry_t *temp_ptr;
historic_list.history_data = lv_mem_alloc( sizeof(history_entry_t) ); // Allocate a new entry.
if (historic_list.begin == NULL) { // Deals with the first entry
historic_list.begin = historic_list.history_data;
historic_list.history_data->prev = NULL;
} else {
historic_list.end->next = historic_list.history_data; // Do this after the first
historic_list.history_data->prev = historic_list.end;
}
historic_list.end = historic_list.history_data;
historic_list.history_data->next = NULL;
memcpy( &historic_list.end->data, &in_data, sizeof(in_data) ); // Save input to history entry
if( ++historic_list.number_of_entries > MAX_HISTORIC_ITEMS ) { // Limit the number of entries
temp_ptr = historic_list.begin->next;
lv_mem_free( historic_list.begin );
historic_list.begin = temp_ptr;
historic_list.begin->prev = NULL;
historic_list.number_of_entries--;
}
lv_obj_invalidate(table);
return;
}
static void table_cb(lv_event_t * e) {
lv_obj_t *obj = lv_event_get_target(e);
lv_obj_draw_part_dsc_t *dsc = lv_event_get_draw_part_dsc(e);
history_data_t *temp_data;
/*If the cells are drawn...*/
if(dsc->part == LV_PART_ITEMS) {
if( (lv_table_get_row_cnt( obj )-1) < historic_list.number_of_entries ) {
lv_table_set_row_cnt(table, historic_list.number_of_entries + 1); // +1 for header row
}
uint32_t row = dsc->id / lv_table_get_col_cnt(obj);
uint32_t col = dsc->id - row * lv_table_get_col_cnt(obj);
/*Make the texts in the first cell centre aligned with a blue background*/
if(row == 0) {
dsc->label_dsc->align = LV_TEXT_ALIGN_CENTER;
dsc->rect_dsc->bg_color = lv_color_mix(lv_palette_main(LV_PALETTE_BLUE), dsc->rect_dsc->bg_color, LV_OPA_20);
dsc->rect_dsc->bg_opa = LV_OPA_COVER;
} else {
dsc->label_dsc->align = LV_TEXT_ALIGN_CENTER;
temp_data = get_historic_by_idx( row - 1 );
int *temp_val_p;
switch( col ) {
case 0:
temp_val_p = &temp_data->oil;
break;
case 1:
temp_val_p = &temp_data->battery;
break;
case 2:
temp_val_p = &temp_data->performance;
break;
}
printf( "row: %d\r\n", row);
fflush( stdout );
if(*temp_val_p < 30) {
dsc->label_dsc->color = lv_palette_main(LV_PALETTE_RED);
} else if(*temp_val_p >= 30 && *temp_val_p <= 70) {
dsc->label_dsc->color = lv_palette_main(LV_PALETTE_AMBER);
} else {
dsc->label_dsc->color = lv_palette_main(LV_PALETTE_GREEN);
}
lv_table_set_cell_value_fmt(table, row, col, "%d", *temp_val_p );
}
}
}
void timer_cb( lv_timer_t * timer ) {
history_data_t new_data;
new_data.oil = rand() % 100;
new_data.battery = rand() % 100;
new_data.performance = rand() % 100;
add_history_data( new_data );
}
void create_table(lv_obj_t * parent) {
table = lv_table_create(parent);
lv_table_set_col_cnt(table, 3);
lv_table_set_row_cnt(table, 1);
lv_obj_align(table, LV_ALIGN_CENTER, 0, 0);
/*Setup columns*/
lv_table_set_cell_value( table, 0, 0, "Oil level" );
lv_table_set_col_width(table, 0, 140);
lv_table_set_cell_value( table, 0, 1, "Battery level" );
lv_table_set_col_width(table, 1, 140);
lv_table_set_cell_value( table, 0, 2, "Performance" );
lv_table_set_col_width(table, 2, 140);
lv_obj_set_size( table, 420, 500 );
lv_obj_update_layout( table );
lv_obj_add_event_cb(table, table_cb, LV_EVENT_DRAW_PART_BEGIN, NULL);
/* A timer to generate some random table data */
lv_timer_create( timer_cb, 2000, NULL );
}
C Header File(table_example.h):
/*
* table_example.h
*
* Created on: 30 Jun 2023
* Author: PeterB
*/
#ifndef TABLE_EXAMPLE_H_
#define TABLE_EXAMPLE_H_
#define MAX_HISTORIC_ITEMS 10
typedef struct _history_data {
int oil;
int battery;
int performance;
} history_data_t;
typedef struct history_entry_t history_entry_t;
struct history_entry_t {
history_entry_t *next;
history_entry_t *prev;
history_data_t data;
};
typedef struct _history_list {
history_entry_t *begin;
history_entry_t *end;
history_entry_t *history_data;
uint32_t number_of_entries;
} history_list_t;
void create_table(lv_obj_t * parent);
#endif /* TABLE_EXAMPLE_H_ */
To use the example create the c code file and the header file and add them to your project and call create_table(lv_scr_act());
Here’s a screen shot:
I hope this helps…
Kind Regards,
Pete