You are getting the hang of things though. Good job staying with it. You will really see the potential once you start really digging your heels in. There is a whole world of things that LVGL is able to do that the other frameworks are not able to do. Those other 2 frameworks you mentioned are really display driver suites more than anything else. They provide a couple of very basic rendering functions but that’s about it. The amount of code you would need to write to handle things like doing the rotation would make for a pretty large job. While LVGL is far from needing a small amount of code to do something it is able to get the job done and offer the greatest flexibility and control over what is taking place.
For the sake of simple interest, I inserted your pseudo-code into the simulator.
At first there were difficulties with compiling the code, in some places the ptr links &
were set incorrectly, in some places the semicolon ;
was forgotten, in some places I had to change the descriptors
render_pitch_label(&layer, large_len, label_height, &label_desc, -y, width, height);
You had descriptors set for the label as for the line desc
.
I haven’t understood some of the code yet, and temporarily commented it out.
In the function convert_coords(&desc.p1, width, height);
I couldn’t set the coordinates of the points, the error was as follows:
cannot convert ‘lv_point_precise_t*’ to ‘lv_point_t*’
As a result, I managed to compile the example code, but it never ran, due to a simulator or SDL2 error:
*** [execute] Error 3221225477
The Internet says there is insufficient memory or no access to memory, I tried to reduce the buffers in the code, but nothing helps.
In general, I understood the idea of the code, and I will try to apply some places to my working code
Here is the code with some changes below:
#include "lvgl.h"
#include "math.h"
#include "app_hal.h"
#ifdef ARDUINO
#include <Arduino.h>
void setup() {
lv_init();
hal_setup();
}
void loop() {
hal_loop(); /* Do not use while loop in this function */
}
#else
// option suggested on the forum
// https://forum.lvgl.io/t/drawing-with-primitives-and-the-functionality-of-the-lvgl-library/21539/19
#define DISPLAY_WIDTH (480)
#define DISPLAY_HEIGHT (480)
// lv_obj_t *screen = lv_screen_active();
void convert_coords(lv_point_t *p, int32_t width, int32_t height)
{
p->x = width / 2 + p->x;
p->y = height / 2 + p->y;
}
void render_pitch_label(lv_layer_t *layer, int32_t large_len, int32_t label_height,
lv_draw_label_dsc_t *desc, int32_t y, int32_t width, int32_t height)
{
lv_area_t coords;
lv_point_t point;
point.x = (large_len / 2) + 3;
point.y = -(y - (label_height / 2));
convert_coords(&point, width, height);
coords.x1 = point.x;
coords.y1 = point.y;
point.x = (large_len / 2) + 43;
point.y = -(y + (label_height / 2));
convert_coords(&point, width, height);
coords.x2 = point.x;
coords.y2 = point.y;
lv_draw_label(layer, desc, &coords);
}
lv_obj_t *create_pitch(lv_obj_t *canvas, lv_draw_buf_t *buf, bool flip_text)
{
int32_t pitch_step = DISPLAY_HEIGHT / 80;
int32_t width = DISPLAY_WIDTH / 2;
// 360 degrees.
int32_t height = pitch_step * 360;
if (canvas == NULL) {
// canvas = lv_canvas_create(screen);
canvas = lv_canvas_create(lv_screen_active());
lv_obj_set_style_width(canvas, width, LV_PART_MAIN);
lv_obj_set_style_height(canvas, height, LV_PART_MAIN);
lv_obj_set_style_transform_pivot_x(canvas, width / 2, LV_PART_MAIN);
lv_obj_set_style_transform_pivot_y(canvas, height / 2, LV_PART_MAIN);
lv_obj_center(canvas);
}
lv_canvas_set_draw_buf(canvas, buf);
lv_canvas_fill_bg(canvas, lv_color_hex(0x000000), 0);
int32_t large_len = DISPLAY_WIDTH / 10;
int32_t small_len = large_len / 2;
int32_t large_step = pitch_step * 10;
int32_t small_step = large_step / 2;
lv_layer_t layer;
lv_canvas_init_layer(canvas, &layer);
lv_draw_line_dsc_t desc;
lv_draw_line_dsc_init(&desc);
// set the color and the width of the line
desc.color = lv_color_hex(0xFFFFFF);
desc.width = 3;
desc.opa = 255;
lv_draw_label_dsc_t label_desc;
lv_draw_label_dsc_init(&label_desc);
int32_t label_height = lv_font_get_line_height(&lv_font_montserrat_14);
label_desc.font = &lv_font_montserrat_14;
label_desc.color = lv_color_hex(0xFFFFFF);
label_desc.opa = 255;
char label[5];
for (int32_t y=0;y<=height / 2;y+=large_step) {
if (flip_text) {
label_desc.text = (const char *)itoa((int)(-y / 10), label, 10);
} else {
label_desc.text = (const char *)itoa((int)(y / 10), label, 10);
}
render_pitch_label(&layer, large_len, label_height, &label_desc, -y, width, height);
desc.p1.x = -(large_len / 2);
desc.p1.y = y;
desc.p2.x = large_len / 2;
desc.p2.y = y;
// convert_coords(&desc.p1, width, height);
// convert_coords(&desc.p2, width, height);
lv_draw_line(&layer, &desc);
if (y != 0 && y != height / 2) {
if (flip_text) {
label_desc.text = (const char *)itoa((int)(y / 10), label, 10);
} else {
label_desc.text = (const char *)itoa((int)(-y / 10), label, 10);
}
render_pitch_label(&layer, large_len, label_height, &label_desc, y, width, height);
desc.p1.x = -(large_len / 2);
desc.p1.y = -y;
desc.p2.x = large_len / 2;
desc.p2.y = -y;
// convert_coords(&desc.p1, width, height);
// convert_coords(&desc.p2, width, height);
lv_draw_line(&layer, &desc);
}
// small ticks
if (y != height / 2) {
desc.p1.x = -(small_len / 2);
desc.p1.y = y + small_step;
desc.p2.x = small_len / 2;
desc.p2.y = y + small_step;
// convert_coords(&desc.p1, width, height);
// convert_coords(&desc.p2, width, height);
lv_draw_line(&layer, &desc);
desc.p1.x = -(small_len / 2);
desc.p1.y = -(y + small_step);
desc.p2.x = small_len / 2;
desc.p2.y = -(y + small_step);
// convert_coords(&desc.p1, width, height);
// convert_coords(&desc.p2, width, height);
lv_draw_line(&layer, &desc);
}
}
lv_canvas_finish_layer(canvas, &layer);
return canvas;
}
lv_obj_t *create_horizon(void)
{
// int32_t size = sqrt((DISPLAY_WIDTH * DISPLAY_WIDTH) + (DISPLAY_HEIGHT * DISPLAY_HEIGHT));
int32_t size = DISPLAY_WIDTH * DISPLAY_WIDTH;
lv_draw_buf_t *horizon_buf = lv_draw_buf_create(size, size, LV_COLOR_FORMAT_ARGB8888, 0);
// lv_obj_t *canvas = lv_canvas_create(screen);
lv_obj_t *canvas = lv_canvas_create(lv_screen_active());
lv_obj_set_style_width(canvas, size, LV_PART_MAIN);
lv_obj_set_style_height(canvas, size, LV_PART_MAIN);
lv_obj_set_style_transform_pivot_x(canvas, size / 2, LV_PART_MAIN);
lv_obj_set_style_transform_pivot_y(canvas, size / 2, LV_PART_MAIN);
lv_obj_center(canvas);
lv_canvas_set_draw_buf(canvas, horizon_buf);
lv_canvas_fill_bg(canvas, lv_color_hex(0x000000), 0);
lv_draw_rect_dsc_t desc;
lv_draw_rect_dsc_init(&desc);
desc.bg_opa = 255;
desc.bg_color = lv_color_hex(0x895129);
desc.border_color = lv_color_hex(0xFFFFFF);
desc.border_width = 4;
desc.border_opa = 255;
desc.border_side = LV_BORDER_SIDE_TOP;
lv_area_t coords;
coords.x1 = 0;
coords.y1 = size / 2;
coords.x2 = size;
coords.y2 = size;
lv_layer_t layer;
lv_canvas_init_layer(canvas, &layer);
lv_draw_rect(&layer, &desc, &coords);
lv_canvas_finish_layer(canvas, &layer);
return canvas;
}
lv_obj_t *horizon_canvas = create_horizon();
// lv_draw_buf_t *pitch_buf1 = lv_draw_buf_create(DISPLAY_WIDTH / 2, DISPLAY_HEIGHT / 80 * 360, LV_COLOR_FORMAT_ARGB8888, 0);
// lv_draw_buf_t *pitch_buf2 = lv_draw_buf_create(DISPLAY_WIDTH / 2, DISPLAY_HEIGHT / 80 * 360, LV_COLOR_FORMAT_ARGB8888, 0);
// lv_obj_t *pitch_canvas = create_horizon(NULL, pitch_buf2, true);
// create_horizon(pitch_canvas, pitch_buf1, false);
void set_roll(int16_t roll)
{
if (roll < 0) roll += 360;
if (roll < 0) roll = 0;
else if (roll > 360) roll = 360;
lv_obj_set_style_transform_rotation(horizon_canvas, roll * 10, LV_PART_MAIN);
// lv_obj_set_style_transform_rotation(pitch_canvas, roll * 10, LV_PART_MAIN);
// if (roll > 180) {
// lv_canvas_set_draw_buf(pitch_canvas, pitch_buf2);
// } else {
// lv_canvas_set_draw_buf(pitch_canvas, pitch_buf1);
// }
}
void set_pitch(int16_t pitch)
{
int32_t pitch_step = DISPLAY_HEIGHT / 80;
int32_t y = pitch_step * pitch;
lv_obj_set_style_y(horizon_canvas, y, LV_PART_MAIN);
// lv_obj_set_style_y(pitch_canvas, y, LV_PART_MAIN);
// if (pitch > 180 || pitch < -180) {
// lv_canvas_set_draw_buf(pitch_canvas, pitch_buf2);
// } else {
// lv_canvas_set_draw_buf(pitch_canvas, pitch_buf1);
// }
}
int main(void)
{
lv_init();
hal_setup();
set_roll(45);
set_pitch(30);
hal_loop();
}
#endif /*ARDUINO*/
OK so the convert coords function is to convert the coordinates from a system that looks like this
(0, -200)
(-200, 0) (0, 0) (200, 0)
(0, 200)
where 0, 0 is in the center of the display instead of at the top left of the display. This makes it a little bit easier because everything you are doing is from the center of the display. It makes it easier when rendering the pitch lines because the lines are a mirror when it is done that way. The convert coords function converts the coordinates above so 0, 0 is positioned at the top left which is how LVGL handles rendering coordinates.
the lv_point_precise_t error is easy to fix. all you have to do is change the the parameter for the convert coords function from lv_point_t *p
to lv_point_precise_t *p
.
I also said it was pseudo code and had not been tested. That means there is going to be errors in it more than likely. It was to show the idea and not be code that actually runs.
Yes, it is clear that the idea itself is embedded in the code, but I managed to run part of the code on my simulator:
// #define ARDUINO
#include "lvgl.h"
#include "math.h"
#include "app_hal.h"
#ifdef ARDUINO
#include <Arduino.h>
void setup() {
lv_init();
hal_setup();
}
void loop() {
hal_loop(); /* Do not use while loop in this function */
}
#else
#define DISPLAY_WIDTH (100)
#define DISPLAY_HEIGHT (100)
// lv_obj_t *screen = lv_screen_active();
// lv_obj_t *canvas = lv_canvas_create(lv_screen_active());
// lv_obj_t *canvas;
void convert_coords(lv_point_t *p, int32_t width, int32_t height)
{
p->x = width / 2 + p->x;
p->y = height / 2 + p->y;
}
void render_pitch_label(lv_layer_t *layer, int32_t large_len, int32_t label_height,
lv_draw_label_dsc_t *desc, int32_t y, int32_t width, int32_t height)
{
lv_area_t coords;
lv_point_t point;
point.x = (large_len / 2) + 3;
point.y = -(y - (label_height / 2));
convert_coords(&point, width, height);
coords.x1 = point.x;
coords.y1 = point.y;
point.x = (large_len / 2) + 43;
point.y = -(y + (label_height / 2));
convert_coords(&point, width, height);
coords.x2 = point.x;
coords.y2 = point.y;
lv_draw_label(layer, desc, &coords);
}
lv_obj_t *create_pitch(lv_obj_t *canvas, lv_draw_buf_t *buf, bool flip_text)
{
int32_t pitch_step = DISPLAY_HEIGHT / 80;
int32_t width = DISPLAY_WIDTH / 2;
// 360 degrees.
int32_t height = pitch_step * 360;
if (canvas == NULL) {
// canvas = lv_canvas_create(screen);
// canvas = lv_canvas_create(lv_screen_active());
lv_obj_set_style_width(canvas, width, LV_PART_MAIN);
lv_obj_set_style_height(canvas, height, LV_PART_MAIN);
lv_obj_set_style_transform_pivot_x(canvas, width / 2, LV_PART_MAIN);
lv_obj_set_style_transform_pivot_y(canvas, height / 2, LV_PART_MAIN);
lv_obj_center(canvas);
}
lv_canvas_set_draw_buf(canvas, buf);
lv_canvas_fill_bg(canvas, lv_color_hex(0x000000), 0);
int32_t large_len = DISPLAY_WIDTH / 10;
int32_t small_len = large_len / 2;
int32_t large_step = pitch_step * 10;
int32_t small_step = large_step / 2;
lv_layer_t layer;
lv_canvas_init_layer(canvas, &layer);
lv_draw_line_dsc_t desc;
lv_draw_line_dsc_init(&desc);
// set the color and the width of the line
desc.color = lv_color_hex(0xFFFFFF);
desc.width = 3;
desc.opa = 255;
lv_draw_label_dsc_t label_desc;
lv_draw_label_dsc_init(&label_desc);
int32_t label_height = lv_font_get_line_height(&lv_font_montserrat_14);
label_desc.font = &lv_font_montserrat_14;
label_desc.color = lv_color_hex(0xFFFFFF);
label_desc.opa = 255;
char label[5];
for (int32_t y=0;y<=height / 2;y+=large_step) {
if (flip_text) {
label_desc.text = (const char *)itoa((int)(-y / 10), label, 10);
} else {
label_desc.text = (const char *)itoa((int)(y / 10), label, 10);
}
render_pitch_label(&layer, large_len, label_height, &label_desc, -y, width, height);
desc.p1.x = -(large_len / 2);
desc.p1.y = y;
desc.p2.x = large_len / 2;
desc.p2.y = y;
// convert_coords(&desc.p1, width, height);
// convert_coords(&desc.p2, width, height);
lv_draw_line(&layer, &desc);
if (y != 0 && y != height / 2) {
if (flip_text) {
label_desc.text = (const char *)itoa((int)(y / 10), label, 10);
} else {
label_desc.text = (const char *)itoa((int)(-y / 10), label, 10);
}
render_pitch_label(&layer, large_len, label_height, &label_desc, y, width, height);
desc.p1.x = -(large_len / 2);
desc.p1.y = -y;
desc.p2.x = large_len / 2;
desc.p2.y = -y;
// convert_coords(&desc.p1, width, height);
// convert_coords(&desc.p2, width, height);
lv_draw_line(&layer, &desc);
}
// small ticks
if (y != height / 2) {
desc.p1.x = -(small_len / 2);
desc.p1.y = y + small_step;
desc.p2.x = small_len / 2;
desc.p2.y = y + small_step;
// convert_coords(&desc.p1, width, height);
// convert_coords(&desc.p2, width, height);
lv_draw_line(&layer, &desc);
desc.p1.x = -(small_len / 2);
desc.p1.y = -(y + small_step);
desc.p2.x = small_len / 2;
desc.p2.y = -(y + small_step);
// convert_coords(&desc.p1, width, height);
// convert_coords(&desc.p2, width, height);
lv_draw_line(&layer, &desc);
}
}
lv_canvas_finish_layer(canvas, &layer);
return canvas;
}
// lv_obj_t *create_horizon(void)
void create_horizon(int16_t roll)
{
int32_t size = sqrt((DISPLAY_WIDTH * DISPLAY_WIDTH) + (DISPLAY_HEIGHT * DISPLAY_HEIGHT));
// int32_t size = DISPLAY_WIDTH * DISPLAY_WIDTH;
// lv_draw_buf_t *horizon_buf = lv_draw_buf_create(size, size, LV_COLOR_FORMAT_ARGB8888, 0);
LV_DRAW_BUF_DEFINE_STATIC(horizon_buf, DISPLAY_WIDTH, DISPLAY_HEIGHT, LV_COLOR_FORMAT_ARGB8888);
LV_DRAW_BUF_INIT_STATIC(horizon_buf);
// lv_obj_t *canvas = lv_canvas_create(screen);
lv_obj_t *canvas = lv_canvas_create(lv_screen_active());
// canvas = lv_canvas_create(lv_screen_active());
lv_canvas_set_draw_buf(canvas, &horizon_buf);
lv_obj_set_style_width(canvas, size, LV_PART_MAIN);
lv_obj_set_style_height(canvas, size, LV_PART_MAIN);
// canvas is visible
lv_canvas_fill_bg(canvas, lv_color_hex3(0xccc), LV_OPA_COVER);
// canvas layer is transparent
// lv_canvas_fill_bg(canvas, lv_color_hex3(0xccc), LV_OPA_TRANSP);
// lv_canvas_fill_bg(canvas, lv_color_hex(0x000000), 0);
// canvas in the center of the display
lv_obj_center(canvas);
// lv_obj_set_pos(canvas, 0, 0); // X->, Y-⌄
lv_draw_rect_dsc_t desc_rect;
lv_draw_rect_dsc_init(&desc_rect);
desc_rect.bg_opa = 255;
desc_rect.bg_color = lv_color_hex(0x895129);
desc_rect.border_color = lv_color_hex(0xFFFFFF);
desc_rect.border_width = 4;
desc_rect.border_opa = 255;
desc_rect.border_side = LV_BORDER_SIDE_TOP;
lv_area_t coords;
coords.x1 = 0;
coords.y1 = size / 2;
coords.x2 = size;
coords.y2 = size;
lv_layer_t layer;
lv_canvas_init_layer(canvas, &layer);
lv_draw_rect(&layer, &desc_rect, &coords);
lv_obj_set_style_transform_pivot_x(canvas, size / 2, LV_PART_MAIN);
lv_obj_set_style_transform_pivot_y(canvas, size / 2, LV_PART_MAIN);
// lv_obj_set_style_transform_rotation(canvas, 10 * 10, LV_PART_MAIN);
lv_obj_set_style_transform_rotation(canvas, roll * 10, LV_PART_MAIN);
lv_canvas_finish_layer(canvas, &layer);
// return canvas;
}
// lv_obj_t *horizon_canvas = create_horizon();
// lv_draw_buf_t *pitch_buf1 = lv_draw_buf_create(DISPLAY_WIDTH / 2, DISPLAY_HEIGHT / 80 * 360, LV_COLOR_FORMAT_ARGB8888, 0);
// lv_draw_buf_t *pitch_buf2 = lv_draw_buf_create(DISPLAY_WIDTH / 2, DISPLAY_HEIGHT / 80 * 360, LV_COLOR_FORMAT_ARGB8888, 0);
// lv_obj_t *pitch_canvas = create_horizon(NULL, pitch_buf2, true);
// create_horizon(pitch_canvas, pitch_buf1, false);
void set_roll(int16_t roll)
{
if (roll < 0) roll += 360;
if (roll < 0) roll = 0;
else if (roll > 360) roll = 360;
create_horizon(roll);
// lv_obj_set_style_transform_rotation(canvas, roll * 10, LV_PART_MAIN);
// lv_obj_set_style_transform_rotation(pitch_canvas, roll * 10, LV_PART_MAIN);
// if (roll > 180) {
// lv_canvas_set_draw_buf(pitch_canvas, pitch_buf2);
// } else {
// lv_canvas_set_draw_buf(pitch_canvas, pitch_buf1);
// }
}
void set_pitch(int16_t pitch)
{
int32_t pitch_step = DISPLAY_HEIGHT / 80;
int32_t y = pitch_step * pitch;
// lv_obj_set_style_y(horizon_canvas, y, LV_PART_MAIN);
// lv_obj_set_style_y(pitch_canvas, y, LV_PART_MAIN);
// if (pitch > 180 || pitch < -180) {
// lv_canvas_set_draw_buf(pitch_canvas, pitch_buf2);
// } else {
// lv_canvas_set_draw_buf(pitch_canvas, pitch_buf1);
// }
}
int main(void)
{
lv_init();
hal_setup();
// create_horizon();
// lv_obj_t *pitch_canvas = create_pitch(NULL, pitch_buf1, true);
// create_pitch(pitch_canvas, pitch_buf2, true);
set_roll(45);
// set_pitch(30);
hal_loop();
}
#endif /*ARDUINO*/
In general, some of the ideas used in your code for rendering with a minimum of code are very interesting.
But I don’t know for what reason, on the simulator I can’t run the code with canvas sizes larger than 100*100
.
The simulator just freezes, without errors and information why this happens
Another reason for the freeze is the declaration of the buffer sizes in a format that I have not seen before:
// lv_draw_buf_t *pitch_buf1 = lv_draw_buf_create(DISPLAY_WIDTH / 2, DISPLAY_HEIGHT / 80 * 360, LV_COLOR_FORMAT_ARGB8888, 0);
I took examples from the code from the lvgl website:
LV_DRAW_BUF_DEFINE_STATIC(horizon_buf, DISPLAY_WIDTH, DISPLAY_HEIGHT, LV_COLOR_FORMAT_ARGB8888);
LV_DRAW_BUF_INIT_STATIC(horizon_buf);
Also, as I understand, you took this pseudocode from the GPT chat, because I have not seen such function constructs before:
lv_obj_t *create_pitch(lv_obj_t *canvas, lv_draw_buf_t *buf, bool flip_text)
Although I understand that they have a place to be and are used by professional programmers
I use the traditional form of declaring functions:
void create_horizon(void){}
Also, to my regret, I do not yet know how to solve the problem of animating all moving parts.
The code you proposed, in part:
void set_roll(int16_t roll)
{
if (roll < 0) roll += 360;
if (roll < 0) roll = 0;
else if (roll > 360) roll = 360;
create_horizon(roll);
}
set_roll(45);
It simply won’t work, because it’s not used in an infinite loop, but in the main loop.
As far as I understand, to make something move in LVGL, you need to use timers or animation:
lv_timer_create
lv_anim_t
I don’t understand yet how to use lv_refr_now(NULL)
, I hope I’ll be able to learn its functionality soon.
In any case, our discussion gave me a lot of knowledge and practice, and I hope that in the future, whoever needs it, it will also be useful
Played around with the code a bit more
void create_pitch(int16_t pitch, bool flip_text)
{
// lv_draw_buf_t *pitch_buf1 = lv_draw_buf_create(DISPLAY_WIDTH / 2, DISPLAY_HEIGHT / 80 * 360, LV_COLOR_FORMAT_ARGB8888, 0);
// lv_draw_buf_t *pitch_buf2 = lv_draw_buf_create(DISPLAY_WIDTH / 2, DISPLAY_HEIGHT / 80 * 360, LV_COLOR_FORMAT_ARGB8888, 0);
LV_DRAW_BUF_DEFINE_STATIC(pitch_buf1, DISPLAY_WIDTH, DISPLAY_HEIGHT, LV_COLOR_FORMAT_ARGB8888);
// LV_DRAW_BUF_DEFINE_STATIC(pitch_buf1, DISPLAY_WIDTH / 2, DISPLAY_HEIGHT / 80 * 360, LV_COLOR_FORMAT_ARGB8888);
LV_DRAW_BUF_INIT_STATIC(pitch_buf1);
LV_DRAW_BUF_DEFINE_STATIC(pitch_buf2, DISPLAY_WIDTH / 2, DISPLAY_HEIGHT / 80 * 360, LV_COLOR_FORMAT_ARGB8888);
LV_DRAW_BUF_INIT_STATIC(pitch_buf2);
lv_obj_t * canvas_pitch = lv_canvas_create(lv_screen_active());
lv_canvas_set_draw_buf(canvas_pitch, &pitch_buf1);
lv_obj_center(canvas_pitch);
lv_obj_set_pos(canvas_pitch, 0, 0); // X->, Y-⌄
int32_t pitch_step = DISPLAY_HEIGHT / 80;
int32_t width = DISPLAY_WIDTH / 2;
// 360 degrees.
int32_t height = pitch_step * 360;
if (canvas_pitch == NULL) {
// canvas = lv_canvas_create(screen);
// canvas = lv_canvas_create(lv_screen_active());
lv_obj_set_style_width(canvas_pitch, width, LV_PART_MAIN);
lv_obj_set_style_height(canvas_pitch, height, LV_PART_MAIN);
lv_obj_set_style_transform_pivot_x(canvas_pitch, width / 2, LV_PART_MAIN);
lv_obj_set_style_transform_pivot_y(canvas_pitch, height / 2, LV_PART_MAIN);
lv_obj_center(canvas_pitch);
}
// lv_canvas_set_draw_buf(canvas, buf);
lv_canvas_set_draw_buf(canvas_pitch, &pitch_buf1);
lv_canvas_fill_bg(canvas_pitch, lv_color_hex(0x000000), 0);
int32_t large_len = DISPLAY_WIDTH / 5;
int32_t small_len = large_len / 2;
int32_t large_step = pitch_step * 10;
int32_t small_step = large_step / 2;
lv_layer_t layer;
lv_canvas_init_layer(canvas_pitch, &layer);
lv_draw_line_dsc_t desc;
lv_draw_line_dsc_init(&desc);
// set the color and the width of the line
desc.color = lv_color_hex(0xFFFFFF);
desc.width = 3;
desc.opa = 255;
lv_draw_label_dsc_t label_desc;
lv_draw_label_dsc_init(&label_desc);
int32_t label_height = lv_font_get_line_height(&lv_font_montserrat_14);
label_desc.font = &lv_font_montserrat_14;
label_desc.color = lv_color_hex(0xFFFFFF);
label_desc.opa = 255;
char label[5];
for (int32_t y=0;y<=height / 2;y+=large_step) {
if (flip_text) {
label_desc.text = (const char *)itoa((int)(-y / 10), label, 10);
} else {
label_desc.text = (const char *)itoa((int)(y / 10), label, 10);
}
render_pitch_label(&layer, large_len, label_height, &label_desc, -y, width, height);
desc.p1.x = -(large_len / 2);
desc.p1.y = y;
desc.p2.x = large_len / 2;
desc.p2.y = y;
convert_coords(&desc.p1, width, height);
convert_coords(&desc.p2, width, height);
lv_draw_line(&layer, &desc);
if (y != 0 && y != height / 2) {
if (flip_text) {
label_desc.text = (const char *)itoa((int)(y / 10), label, 10);
} else {
label_desc.text = (const char *)itoa((int)(-y / 10), label, 10);
}
render_pitch_label(&layer, large_len, label_height, &label_desc, y, width, height);
desc.p1.x = -(large_len / 2);
desc.p1.y = -y;
desc.p2.x = large_len / 2;
desc.p2.y = -y;
convert_coords(&desc.p1, width, height);
convert_coords(&desc.p2, width, height);
lv_draw_line(&layer, &desc);
}
// small ticks
if (y != height / 2) {
desc.p1.x = -(small_len / 2);
desc.p1.y = y + small_step;
desc.p2.x = small_len / 2;
desc.p2.y = y + small_step;
convert_coords(&desc.p1, width, height);
convert_coords(&desc.p2, width, height);
lv_draw_line(&layer, &desc);
desc.p1.x = -(small_len / 2);
desc.p1.y = -(y + small_step);
desc.p2.x = small_len / 2;
desc.p2.y = -(y + small_step);
convert_coords(&desc.p1, width, height);
convert_coords(&desc.p2, width, height);
lv_draw_line(&layer, &desc);
}
}
lv_canvas_finish_layer(canvas_pitch, &layer);
// return canvas;
}
create_pitch(20, false);
The code is of course spontaneous, so the buffers for the two canvases are different and overlap each other, and all this is just a prank
Somehow I managed to write code so that several layers do not conflict and perform rotations statically without overflowing the buffers.
If you had some time, I could send you a project for the simulator
GitHub - lvgl/lv_platformio: PlatformIO project example for LVGL
You could look at the code in action and maybe you could animate it
The code I gave you was not for use. It was to give you ideas on how to go about things…