Cannot create label on screen

Description

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

Microblaze with Vitis

What LVGL version are you using?

V7.11.0

What do you want to achieve?

Create hello world on screen.

What have you tried so far?

I can change the screen color but I cannot create a text on top of it.

    lv_obj_t * scr1 = lv_scr_act();
    lv_obj_set_style_local_bg_color(scr1, LV_OBJ_PART_MAIN, 0, LV_COLOR_BLUE);

1.PNG
Adding Hello World text causes the screen to have horizontal dashes.

    lv_obj_t * scr1 = lv_scr_act();
    lv_obj_t *label1 =  lv_label_create(scr1, NULL);
    lv_label_set_text(label1, "Hello world!");
    lv_obj_set_style_local_bg_color(scr1, LV_OBJ_PART_MAIN, 0, LV_COLOR_BLUE);

2.PNG

I believe this line:

lv_obj_t * scr1 = lv_scr_act();

should be like this:

lv_obj_t * scr1 = (lv_scr_act(), NULL);

Thank you but sadly this did not solve my issue. The screen still wont show a label.

Ok :slight_smile:

Did you tried any example to confirm that you have pinout for you screen right? What platform are you using?

Not sure what example to try. I am using a nexys video fpga with vitis.

Hmm, I do not know this platform so I can not help you with it, sorry :frowning:

I find this, which should work so try it pls, maybe will work:

This gave me a fully white display.

There seems to be something wrong on the way between lvgl working buffer and your display.

It would be good if you can describe your current setup:
The resolution of your display (width, height, color depth).
The display type (‘dump’ or ‘smart’ display) and how it is connected to your hardware.
How did you setup lvgl (e.g. working buffer size, color depth)

The resolution of your display (width, height, color depth):
1280 X 1024; color depth 8
The display type (‘dump’ or ‘smart’ display) and how it is connected to your hardware
Not sure if its a dump or smart display. It is connected to an FPGA.
How did you setup lvgl (e.g. working buffer size, color depth)
Here are my changes to the config file:

/* Maximal horizontal and vertical resolution to support by the library.*/
#define LV_HOR_RES_MAX          (1280)
#define LV_VER_RES_MAX          (1024)

/* Color depth:
 * - 1:  1 byte per pixel
 * - 8:  RGB332
 * - 16: RGB565
 * - 32: ARGB8888
 */
#define LV_COLOR_DEPTH     8
/* 1: use custom malloc/free, 0: use the built-in `lv_mem_alloc` and `lv_mem_free` */
#define LV_MEM_CUSTOM      1
#if LV_MEM_CUSTOM == 0
/* Size of the memory used by `lv_mem_alloc` in bytes (>= 2kB)*/
#  define LV_MEM_SIZE    (32U * 1024U)

/* Compiler prefix for a big array declaration */
#  define LV_MEM_ATTR

/* Set an address for the memory pool instead of allocating it as an array.
 * Can be in external SRAM too. */
#  define LV_MEM_ADR          0xC0080000

/* Automatically defrag. on free. Defrag. means joining the adjacent free cells. */
#  define LV_MEM_AUTO_DEFRAG  1
#else       /*LV_MEM_CUSTOM*/
#  define LV_MEM_CUSTOM_INCLUDE "FreeRTOS.h"   /*Header for the dynamic memory function*/
#  define LV_MEM_CUSTOM_ALLOC   pvPortMalloc       /*Wrapper to malloc*/
#  define LV_MEM_CUSTOM_FREE    vPortFree         /*Wrapper to free*/
#endif     /*LV_MEM_CUSTOM*/

Here is my code for LVGL:

#define LV_TICK_PERIOD_MS 1
#define DISP_BUF_SIZE  (LV_HOR_RES_MAX * LV_VER_RES_MAX)
#define LAYER0_ADDRESS (0xc0000000)

static uint32_t * my_fb = (uint32_t *)LAYER0_ADDRESS;

void my_rounder_cb(lv_disp_drv_t * disp_drv, lv_area_t * area)
{
   area->y1 = area->y1 & 0x10;
   area->y2 = (area->y2 & 0x10) + 8;
}

void my_set_px_cb(lv_disp_drv_t * disp_drv, uint8_t * buf, lv_coord_t buf_w, lv_coord_t x, lv_coord_t y, lv_color_t color, lv_opa_t opa)
{
	buf += buf_w * (y >> 3) + x;
	if(lv_color_brightness(color) > 128) (*buf) |= (1 << (y % 8));
	else (*buf) &= ~(1 << (y % 8));
}

void CopyBuffer(const uint32_t *pSrc, uint32_t *pDst, uint16_t x, uint16_t y, uint16_t xsize, uint16_t ysize)
{
	uint32_t row;
	for(row = y; row < y + ysize; row++ ) {
		memcpy(&pDst[row * 480 + x], pSrc, xsize * 2);
		pSrc += xsize;
	}
}

static void disp_flush(lv_disp_drv_t * disp_drv, const lv_area_t * area, lv_color_t * color_p)
{
	CopyBuffer((const uint32_t *)color_p, my_fb, area->x1, area->y1, lv_area_get_width(area), lv_area_get_height(area));
    lv_disp_flush_ready(disp_drv);
}

void vApplicationTickHook(void)
{
	lv_tick_inc(1);
}

void LV_Task(void) {
	lv_task_handler();
}

static void lvgl_timer_callback(xTimerHandle pxTimer)
{
	lv_task_handler();
}

SemaphoreHandle_t xGuiSemaphore;

static lv_color_t buf[LV_HOR_RES_MAX * LV_VER_RES_MAX]; /*Declare a buffer*/
static lv_disp_buf_t disp_buf;
lv_disp_drv_t disp_drv;               /*Descriptor of a display driver*/

static void Lv_init()
{
	/* Initialize LVGL library */
    lv_init();
    printf("LVGL");

    lv_disp_buf_init(&disp_buf, buf, NULL, LV_HOR_RES_MAX * LV_VER_RES_MAX); /*Initialize the display buffer*/


    lv_disp_drv_init(&disp_drv);          /*Basic initialization*/
    disp_drv.flush_cb = disp_flush;    /*Set your driver function*/
    disp_drv.buffer = &disp_buf;          /*Assign the buffer to the display*/
    lv_disp_drv_register(&disp_drv);      /*Finally register the driver*/

    lv_obj_t * scr1 = lv_scr_act();
    lv_obj_t *label1 =  lv_label_create(scr1, NULL);
    lv_label_set_text(label1, "Hello world!");
    lv_obj_set_style_local_bg_color(scr1, LV_OBJ_PART_MAIN, 0, LV_COLOR_BLUE);

    vApplicationTickHook();
    lv_task_handler();

    xTimerHandle timerlvgl;

    timerlvgl = xTimerCreate("LVGL", pdMS_TO_TICKS(1000), pdTRUE, NULL, lvgl_timer_callback);

    xGuiSemaphore = xSemaphoreCreateMutex();

    xTimerStart(timerlvgl, 50);

    if (xTimerStart(timerlvgl, 0)!=pdPASS) {
        for(;;);
    }
}

My fault, it should be ‘dumb’ instead of ‘dump’ display.
A dumb display is one without any special display controller.
In this case your controller have to provide the RGB data, the H- and VSYNC and a clock signal.
The frame buffer is located within the microcontroller and the microcontrollers hardware is responsible to output the pixel data to the display.

A smart display has it’s on display controller with its own frame buffer.
In this case the microcontroller has to copy the display data to the display’s controller only in case something has changed.

So what do you have?
As far as I can see you have the lvgl’s working buffer (buf[]) setup and you have setup the frame buffer (my_fb with address 0xc00000000).
So you copy lvgl’s working buffer (buf[]) to the my_fb.
But how gets the display the data from my_fb?

Currently I am taking the address of LVGLs working buffer and copying the address to display it.
I got the display to show hello world but it is showing it many times very microscopic.
WIN_20210405_10_49_10_Pro
WIN_20210405_10_48_45_Pro
Here are the code edits:

#define LV_TICK_PERIOD_MS 1
#define DISP_BUF_SIZE  (LV_HOR_RES_MAX * LV_VER_RES_MAX)
#define LAYER0_ADDRESS (0xc0000000)

static uint32_t * my_fb = (uint32_t *)LAYER0_ADDRESS;

void my_rounder(struct _disp_drv_t * disp_drv, lv_area_t *a)
{
    a->x1 = a->x1 & ~(0x7);
    a->x2 = a->x2 |  (0x7);
}

void my_set_px_cb(struct _disp_drv_t * disp_drv, uint8_t * buf, lv_coord_t buf_w, lv_coord_t x, lv_coord_t y, lv_color_t color, lv_opa_t opa)
{
    buf += buf_w/8 * y;
    buf += x/8;
    if(lv_color_brightness(color) > 128) {(*buf) |= (1 << (7 - x % 8));}
    else {(*buf) &= ~(1 << (7 - x % 8));}
}

void CopyBuffer(const uint32_t *pSrc, uint32_t *pDst, uint16_t x, uint16_t y, uint16_t xsize, uint16_t ysize)
{
	uint32_t row;
	for(row = y; row < y + ysize; row++ ) {
		memcpy(&pDst[row * 480 + x], pSrc, xsize * 2);
		pSrc += xsize;
	}
}

static void disp_flush(lv_disp_drv_t * disp_drv, const lv_area_t * area, lv_color_t * color_p)
{

    CopyBuffer((const uint32_t *)color_p, my_fb, area->x1, area->y1, lv_area_get_width(area), lv_area_get_height(area));
    lv_disp_flush_ready(disp_drv);
}

void vApplicationTickHook(void)
{
	lv_tick_inc(1);
}

void LV_Task(void) {
	lv_task_handler();
}

static void lvgl_timer_callback(xTimerHandle pxTimer)
{
	lv_task_handler();
}

SemaphoreHandle_t xGuiSemaphore;

static lv_color_t buf[LV_HOR_RES_MAX * LV_VER_RES_MAX]; /*Declare a buffer*/
static lv_disp_buf_t disp_buf;
lv_disp_drv_t disp_drv;               /*Descriptor of a display driver*/

static void Lv_init()
{
	/* Initialize LVGL library */
    lv_init();
    printf("LVGL");

    lv_disp_buf_init(&disp_buf, buf, NULL, LV_HOR_RES_MAX * LV_VER_RES_MAX); /*Initialize the display buffer*/


    lv_disp_drv_init(&disp_drv);          /*Basic initialization*/
    disp_drv.buffer = &disp_buf;          /*Assign the buffer to the display*/
    lv_disp_drv_register(&disp_drv);      /*Finally register the driver*/
    disp_drv.flush_cb = disp_flush;    /*Set your driver function*/
    disp_drv.set_px_cb = my_set_px_cb;
    disp_drv.rounder_cb = my_rounder;

    lv_obj_t * scr1 = lv_scr_act();
    lv_obj_t *label1 =  lv_label_create(scr1, NULL);
    lv_label_set_text(label1, "Hello world!");

    vApplicationTickHook();
    lv_task_handler();

    xTimerHandle timerlvgl;

    timerlvgl = xTimerCreate("LVGL", pdMS_TO_TICKS(1000), pdTRUE, NULL, lvgl_timer_callback);

    xGuiSemaphore = xSemaphoreCreateMutex();

    xTimerStart(timerlvgl, 50);

    if (xTimerStart(timerlvgl, 0)!=pdPASS) {
        for(;;);
    }
}

I also changed the color depth to 32.

Your CopyBuffer function:

memcpy(&pDst[row * 480 + x], pSrc, xsize * 2);

Why do you multply with 480? I thought your horicontal resolution is 1280?

When you see the hello word multiple times it’s because of an incorrect copy within your flush function.

Changing it to 1280 gives the same result.
Are my_rounder and my_set_px_cb correct? Could those be an issue as well?

You have changed to color depth 32!?
So this is four bytes per pixel.
The number of bytes you copy within your CopyBuffer function is xsize * 2.
Shouldn’t it 4?

Changing the color depth to 8 and leaving the copy buffer at xsize * 2 gives the same result.
Any suggestions on how to flush?

???
If you have color depth 8-bit, means one byte per pixel, so it would be xsize * 1,
color depth 16-bit means two bytes per pixel, so it would be xsize * 2,
color depth 32-bit means four bytes per pixel, so it would be xsize * 4.
Or am i on the wrong track?

Do not change back and forth all the time.