Object creation issue

What MCU/Processor/Board and compiler are you using?

STM32F103RCT6 (RAM 48 KB, custom board)
display: 128*160, RGB565(16 bit), ST7735/ST7789 lcd driver, SPI comm.

IDE: STM32CubeIDE

What LVGL version are you using?

the latest one (v8.0)

What do you want to achieve?

To create objects.
When I add an example in main code, objects doesn’t show up.
I’ve tested several examples, I could just watch some pixels’ color was changed.

The changed color on specific area was scrolling when I tested lv_example_label_1().
I guess it scrolls some text, but it isn’t created.
Instead, light-pink one is moving. I added the gif file below.

I wonder if it is a problem of spi communication size or my lcd_flush fuction.
However, I cannot find the cause.
If anyone knows, let me know.

Code to reproduce

main processing function

void App_Start(void)
{

		lv_init();
		LCD_Init(); // lcd init func
		HAL_Delay(1000);
	        lv_config_main(); // lvgl configuration func

		lv_example_label_1();
}

void lv_config_main(void)
{
    static lv_disp_draw_buf_t disp_buf;
    static lv_color_t buf_1[LV_HOR_RES_MAX*10];
    lv_disp_draw_buf_init(&disp_buf, buf_1, NULL, LV_HOR_RES_MAX * 10);
    
    static lv_disp_drv_t disp_drv;
    lv_disp_drv_init(&disp_drv);
    disp_drv.draw_buf = &disp_buf;	

    LCD_flush(&disp_drv, &area, &my_color); // I've added it for testing and print data change
    disp_drv.flush_cb = LCD_flush;	
    lv_disp_t * disp_ex;
    disp_ex = lv_disp_drv_register(&disp_drv);

}

flush function

void LCD_flush(lv_disp_drv_t * drv, const lv_area_t * area,  lv_color_t * color_map)
{
	int16_t x, y;

	lv_color_t color = *color_map;
	    for(x = area->x1; x <= area->x2; x++) {
	        for(y = area->y1; y <= area->y2; y++) {
	        	LCD_DrawPaint((uint16_t)x, (uint16_t)y, (uint16_t)color.full);
	        }
	    }
	lv_disp_flush_ready(drv);
	DEV_Digital_Write(DEV_CS_PIN, 1);
}

display driver function for drawing

void LCD_DrawPaint(uint16_t x, uint16_t y, uint16_t Color)
{
	LCD_SetCursor(x, y);
	LCD_WriteData_Word(Color);
}

void LCD_SetCursor(uint16_t X, uint16_t Y)
{
	LCD_Write_Command(0x2a);
	LCD_WriteData_Byte(X >> 8);
	LCD_WriteData_Byte(X);
	LCD_WriteData_Byte(X >> 8);
	LCD_WriteData_Byte(X);

	LCD_Write_Command(0x2b);
	LCD_WriteData_Byte(Y >> 8);
	LCD_WriteData_Byte(Y);
	LCD_WriteData_Byte(Y >> 8);
	LCD_WriteData_Byte(Y);

	LCD_Write_Command(0x2C);
}

static void LCD_Write_Command(uint8_t data)
{
	DEV_Digital_Write(DEV_CS_PIN, 0);   // it makes GPIO pin set/reset
	DEV_Digital_Write(DEV_DC_PIN, 0);
	DEV_SPI_WRITE(data);
}

static void LCD_WriteData_Byte(uint8_t data)
{
	DEV_Digital_Write(DEV_CS_PIN, 0); 
	DEV_Digital_Write(DEV_DC_PIN, 1);
	DEV_SPI_WRITE(data);
	DEV_Digital_Write(DEV_CS_PIN,1);
}

// spi function
void DEV_SPI_WRite(uint8_t _dat)
{
	HAL_SPI_Transmit(&hspi1, (uint8_t *)&_dat, 1, 500);
}

example code that I used

void lv_example_label_1(void)
{
    lv_obj_t * label1 = lv_label_create(lv_scr_act(), NULL);
    lv_label_set_long_mode(label1, LV_LABEL_LONG_WRAP);     /*Break the long lines*/
    lv_label_set_recolor(label1, true);                      /*Enable re-coloring by commands in the text*/
    lv_label_set_text(label1, "#0000ff Re-color# #ff00ff words# #ff0000 of a# label, align the lines to the center"
                              "and  wrap long text automatically.");
    lv_obj_set_width(label1, 150);  /*Set smaller width to make the lines wrap*/
    lv_obj_set_style_text_align(label1, LV_PART_MAIN, LV_STATE_DEFAULT, LV_TEXT_ALIGN_CENTER);
    lv_obj_align(label1, NULL, LV_ALIGN_CENTER, 0, -40);


    lv_obj_t * label2 = lv_label_create(lv_scr_act(), NULL);
    lv_label_set_long_mode(label2, LV_LABEL_LONG_SCROLL_CIRCULAR);     /*Circular scroll*/
    lv_obj_set_width(label2, 150);
    lv_label_set_text(label2, "It is a circularly scrolling text. ");
    lv_obj_align(label2, NULL, LV_ALIGN_CENTER, 0, 40);
}

Screenshot and/or video

Do this one:

void LCD_flush(lv_disp_drv_t * drv, const lv_area_t * area,  lv_color_t * color_p)
{
    int16_t x, y;

    for (x = area->x1; x <= area->x2; x++)  {
        for (y = area->y1; y <= area->y2; y++)  {
            LCD_DrawPaint ((uint16_t) x, (uint16_t) y, (*color_p).full);
            color_p++;
        }
    }

    lv_disp_flush_ready (drv);
    DEV_Digital_Write (DEV_CS_PIN, 1);
}

I changed your variable name from color_map to color_p, as the name color_map can be misinterpretated.

The result looks like this:

That’s quite a bit more than before :wink:

Maybe there is a mismatch between the resolution setting in lvgl and in display?

What have you configured in lvgl? 128 (hor) x 160 (vert)? And did you setup the display appropriately?
And check whether the color depth is really the same.

I set the resolution as 128*160.
When I’ve changed the LV_COLOR_16_SWAP as 0, the color is changed as black-ish.
I’m not sure if it is meaningful or not.

LCD_driver.h (LCD_flush() is declared in it)

#define LCD_WIDTH   128 //LCD width
#define LCD_HEIGHT  160 //LCD height

lv_conf.h

/* Maximal horizontal and vertical resolution to support by the library.*/
#define LV_HOR_RES_MAX 128
#define LV_VER_RES_MAX 160
/*====================
   COLOR SETTINGS
 *====================*/

/*Color depth: 1 (1 byte per pixel), 8 (RGB332), 16 (RGB565), 32 (ARGB8888)*/
#define LV_COLOR_DEPTH     16

/*Swap the 2 bytes of RGB565 color. Useful if the display has a 8 bit interface (e.g. SPI)*/
#define LV_COLOR_16_SWAP   0

The display setup is fine, I think, there was no problem when I didn’t import lvgl.
I’ll re-check display driver’s datasheet again, though.
It feels good to see things get better and better :smile:

When I tested with mush simple example, lv_example_line_1(),
Maybe I’m going to find what is the problem.

I changed the number of points with 2 for drawing a line, and changed color with red.
The result is below.

I guess the resolution value wasn’t reflected, they were repeated in small region.
When debugging, I watched that value was in buffer, though.
Anyway, I keep trying! :joy:

void lv_example_line_1(void)
{
    /*Create an array for the points of the line*/
    static lv_point_t line_points[] = { {5, 5}, {70, 70}};

    /*Create style*/
    static lv_style_t style_line;
    lv_style_init(&style_line);
    lv_style_set_line_width(&style_line, 8);
    lv_style_set_line_color(&style_line, lv_color_red());
    lv_style_set_line_rounded(&style_line, true);

    /*Create a line and apply the new style*/
    lv_obj_t * line1;
    line1 = lv_line_create(lv_scr_act(), NULL);
    lv_line_set_points(line1, line_points, 2);     /*Set the points*/
    lv_obj_add_style(line1, LV_PART_MAIN, LV_STATE_DEFAULT, &style_line);     /*Set the points*/
    lv_obj_align(line1, NULL, LV_ALIGN_CENTER, 0, 0);
}

#endif

Instead of calling your code (the lv_example_label_1), can you include this one, and call lv_ex_canvas_test.

This function should just paint a red rectangle (50 x 50) onto your display.

#define CANVAS_WIDTH  50
#define CANVAS_HEIGHT  50

void lv_ex_canvas_test (void)
{
    static lv_color_t  cbuf[LV_CANVAS_BUF_SIZE_TRUE_COLOR (CANVAS_WIDTH, CANVAS_HEIGHT)];

    lv_obj_t* canvas = lv_canvas_create (lv_scr_act(), NULL);

    lv_canvas_set_buffer (canvas, cbuf, CANVAS_WIDTH, CANVAS_HEIGHT, LV_IMG_CF_TRUE_COLOR);

    lv_canvas_set_palette (canvas, 1, LV_COLOR_RED);
    lv_obj_align          (canvas, NULL, LV_ALIGN_IN_TOP_LEFT, 0, 0);
    lv_canvas_fill_bg     (canvas, LV_COLOR_RED, LV_OPA_TRANSP);
}

The swap does not really mean something here.
With a wrong ‘swap’ you would see only a wrong coloring. But the display should be ‘readable’.

Found the problem: Do this one:
The outer loop should run the vertical and the inner loop the horizontal

void LCD_flush(lv_disp_drv_t * drv, const lv_area_t * area,  lv_color_t * color_p)
{
    int16_t x, y;

    for (y = area->y1; y <= area->y2; y++)  {
       for (x = area->x1; x <= area->x2; x++)  {
            LCD_DrawPaint ((uint16_t) x, (uint16_t) y, (*color_p).full);
            color_p++;
        }
    }

    lv_disp_flush_ready (drv);
    DEV_Digital_Write (DEV_CS_PIN, 1);
}

I changed it because it didn’t work well when I ran the horizontal loop first :rofl:
After re-checking the lcd driver’s document, and watching your reply, I finally know what was the problem :laughing: :laughing: :laughing:

When testing to draw a line, I can watch the result!!
The text scrolling also works, the rate is quite slow and I should resizing it, though.

There are still a lot of problems I should solve for my project, but thanks to you, I was able to make progress,
Thanks really. :heart_eyes:

ezgif.com-gif-maker (4)

It is very slow because you send every single pixel to the display with LCD_SetCursor.
That costs a lot of time.

It will get much quicker if you setup a receiving window to the display and just transfer every single pixel one after another (without setting the cursor again and again)

But that’s more to learn for you :wink:

There is still a lot to learn :rofl:
I’m going to try to apply it and I’ll run to here if I meet other problems lol

I’ve found related thread that you mentioned: My ILI9341 display working very slow

Should I create the new function to replace LCD_DrawPaint() in double-loop?
Is it necessary to run the loop again even if the function like fillRect() mentioned has x, y, w, h and color?
It has x1 to x2 and y1 to y2, just changes the color.

I still can’t get it,
If there is any document that you can refer to, or if you let us know a little, I’d be grateful :smile:

I’m not 100% sure, but as far as I remember, you setup the display controller with the area window.
With the x start, y start position and x last, and y last position (that’s the same - the area - as you get with the flush function).
And than you feed all the data (all the pixel data from color_p) per SPI into the display.

Currently if you set only one pixel the overhead (setting the cursor, initiate the SPI transfer etc.) is very large.
Take a look on what to do for one pixel (two bytes) in your case (all the functions which are called).
When using the optimized way, the overhead for setting a bunch of pixels is the same as for only one pixel.
And that saves a lot of time.

I think there were some questions and examples about this within the forum in the past.

I found this thread: Stm32f4 and st7789 using with LittleVgl
Search for ST7789_Send_Data

Did you have a good weekend? :smile:
After I recharged over the weekend, I was able to work again from Monday to read your comments carefully.
Your reply was very helpful
Now the window fills up quickly
Thank you! :laughing:

Now I’m going to create a event & callback function to work with the touch screen :joy:
Thank you again :slight_smile:

1 Like

Today I recover from weekend :grinning:

Good to hear about progress :+1:

But there is still one thing which should be fixed:
On the left and the top of the display there are still some pixel rows and colums which are not written correctly.

Yes, I should correct it :rofl:
I’m putting my priorities behind now, but I’ll try to fix them sooner :grinning: