I’m programming a graphic that uses a scale as the x-axis to show the passing time with LVGL. The HH:MM:SS format is working, but all the ticks show the same values. With that in mind, I would like to print the time, incrementing it correctly every second. What should I do in my code to achieve this? Please suggest any improvements and help.
LVGL version: latest master.
Example output required:
Actual output:
#include <time.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <string.h>
#include "lvgl/lvgl.h"
#include "lvgl/src/drivers/display/fb/lv_linux_fbdev.h"
#include "lv_conf.h"
#define WIDTH 800
#define HEIGHT 480
typedef struct {
int hours;
int minutes;
int seconds;
} DataValue;
static lv_obj_t *scale;
static lv_obj_t *needle_line;
DataValue timer = {0};
uint32_t my_tick_get(void){
struct timespec ts;
clock_gettime(CLOCK_MONOTONIC, &ts);
return (uint32_t)(ts.tv_sec * 1000 + ts.tv_nsec / 1000000);
}
static void time_tick_cb(lv_timer_t *t) {
DataValue *data = (DataValue *) lv_timer_get_user_data(t);
int total_seconds = data->hours * 3600 + data->minutes * 60 + data->seconds;
total_seconds = (total_seconds + 1) % (24 * 3600);
data->hours = total_seconds / 3600;
data->minutes = (total_seconds % 3600) / 60;
data->seconds = total_seconds % 60;
int start = total_seconds - 15;
int end = total_seconds + 15;
if(start < 0) start = 0;
if(end > 24 * 3600) end = 24 * 3600;
lv_scale_set_range(scale, start, end);
lv_scale_set_line_needle_value(scale, needle_line, 50, total_seconds);
}
static void update_scale(lv_event_t *e){
lv_draw_task_t * draw_task = lv_event_get_draw_task(e);
lv_draw_dsc_base_t * base_dsc = (lv_draw_dsc_base_t *)lv_draw_task_get_draw_dsc(draw_task);
lv_draw_label_dsc_t * label_draw_dsc = lv_draw_task_get_label_dsc(draw_task);
DataValue *data = (DataValue *)lv_event_get_user_data(e);
if (data == NULL) return;
if(base_dsc->part == LV_PART_INDICATOR){
if(label_draw_dsc){
label_draw_dsc->rotation = 0;
if(label_draw_dsc->text_local) lv_free((void *)label_draw_dsc->text);
char buffer[20];
snprintf(buffer, sizeof(buffer), "%02d:%02d:%02d", data->hours, data->minutes, data->seconds);
label_draw_dsc->text = lv_strdup(buffer);
label_draw_dsc->text_local = 1;
lv_area_t area;
lv_draw_task_get_area(draw_task, &area);
lv_point_t size;
lv_text_get_size(&size, label_draw_dsc->text, label_draw_dsc->font, 0, 0, 1000, LV_TEXT_FLAG_NONE);
label_draw_dsc->align = LV_TEXT_ALIGN_CENTER;
label_draw_dsc->flag = LV_TEXT_FLAG_EXPAND;
int32_t new_w = size.x;
int32_t old_w = lv_area_get_width(&area);
/* Distribute the new size equally on both sides */
area.x1 -= (new_w - old_w) / 2;
area.x2 += ((new_w - old_w) + 1) / 2; /* +1 for rounding */
}
}
}
static lv_obj_t* create_screen(void){
lv_init();
lv_tick_set_cb(my_tick_get);
lv_display_t *disp = lv_linux_fbdev_create();
if (!disp) {
fprintf(stderr, "Error creating display!\n");
exit(EXIT_FAILURE);
}
lv_linux_fbdev_set_file(disp, "/dev/fb0");
lv_display_set_resolution(disp, WIDTH, HEIGHT);
lv_display_set_default(disp);
lv_obj_t *scr = lv_scr_act();
lv_scr_load(scr);
lv_obj_set_style_bg_color(scr, lv_color_hex(0xFFFFFF), LV_PART_MAIN);
lv_obj_set_style_bg_opa(scr, LV_OPA_COVER, LV_PART_MAIN);
return scr;
}
void screen_clean_up(void *scr){
lv_obj_delete(scr);
}
int main(void){
lv_obj_t *scr = create_screen();
scale = lv_scale_create(scr);
lv_obj_set_size(scale, lv_pct(80), 100);
lv_scale_set_mode(scale, LV_SCALE_MODE_HORIZONTAL_BOTTOM);
lv_obj_center(scale);
lv_scale_set_label_show(scale, true);
lv_scale_set_total_tick_count(scale, 31);
lv_scale_set_major_tick_every(scale, 5);
lv_obj_set_style_length(scale, 5, LV_PART_ITEMS);
lv_obj_set_style_length(scale, 10, LV_PART_INDICATOR);
lv_obj_add_event_cb(scale, update_scale, LV_EVENT_DRAW_TASK_ADDED, &timer);
lv_obj_add_flag(scale, LV_OBJ_FLAG_SEND_DRAW_TASK_EVENTS);
lv_timer_create(time_tick_cb, 1000, &timer);
while (1) {
lv_timer_handler();
usleep(5000);
}
return 0;
}