LittleVGL PNG Image Files vs C Array Issues, other graphics

They’re called monitor_flush and mouse_read, respectively.

Hi Gabor, Thank you.

I will start with questions on replacing PC display with our own display drivers. In the simulator main found the code that calls the initialization and flush functions. Copy/paste is below. I can see in the porting document these are functions to focus on. I can see where to replace our GM320240U init function in the monitor_init. What I am confused about, is how is it that our display is registered in place of the PC in monitor_flush and insuring disp_drv is referencing the embedded display rather than the PC? Maybe I misunderstood a step. Thank you again.

/**
 * Initialize the Hardware Abstraction Layer (HAL) for the Littlev graphics library
 */
static void hal_init(void)
{
    /* Use the 'monitor' driver which creates window on PC's monitor to simulate a display*/
    monitor_init();

    /*Create a display buffer*/
    static lv_disp_buf_t disp_buf1;
    static lv_color_t buf1_1[480*32];
    lv_disp_buf_init(&disp_buf1, buf1_1, NULL, 480*32);

    /*Create a display*/
    lv_disp_drv_t disp_drv;
    lv_disp_drv_init(&disp_drv);            /*Basic initialization*/
    disp_drv.buffer = &disp_buf1;
    disp_drv.flush_cb = monitor_flush;    /*Used when `LV_VDB_SIZE != 0` in lv_conf.h (buffered drawing)*/
    //    disp_drv.hor_res = 200;
    //    disp_drv.ver_res = 100;
    lv_disp_drv_register(&disp_drv);
...

/**
 * Flush a buffer to the marked area
 * @param drv pointer to driver where this function belongs
 * @param area an area where to copy `color_p`
 * @param color_p an array of pixel to copy to the `area` part of the screen
 */
void monitor_flush(lv_disp_drv_t * disp_drv, const lv_area_t * area, lv_color_t * color_p)
{
    lv_coord_t hres = disp_drv->rotated == 0 ? disp_drv->hor_res : disp_drv->ver_res;
    lv_coord_t vres = disp_drv->rotated == 0 ? disp_drv->ver_res : disp_drv->hor_res;

//    printf("x1:%d,y1:%d,x2:%d,y2:%d\n", area->x1, area->y1, area->x2, area->y2);

    /*Return if the area is out the screen*/
    if(area->x2 < 0 || area->y2 < 0 || area->x1 > hres - 1 || area->y1 > vres - 1) {

        lv_disp_flush_ready(disp_drv);
        return;
    }

#if MONITOR_DOUBLE_BUFFERED
    monitor.tft_fb_act = (uint32_t *)color_p;

    monitor.sdl_refr_qry = true;

    /*IMPORTANT! It must be called to tell the system the flush is ready*/
    lv_disp_flush_ready(disp_drv);
#else

    int32_t y;
#if LV_COLOR_DEPTH != 24 && LV_COLOR_DEPTH != 32    /*32 is valid but support 24 for backward compatibility too*/
    int32_t x;
    for(y = area->y1; y <= area->y2 && y < disp_drv->ver_res; y++) {
        for(x = area->x1; x <= area->x2; x++) {
            monitor.tft_fb[y * disp_drv->hor_res + x] = lv_color_to32(*color_p);
            color_p++;
        }

    }
#else
    uint32_t w = lv_area_get_width(area);
    for(y = area->y1; y <= area->y2 && y < disp_drv->ver_res; y++) {
        memcpy(&monitor.tft_fb[y * MONITOR_HOR_RES + area->x1], color_p, w * sizeof(lv_color_t));
        color_p += w;
    }
#endif

    monitor.sdl_refr_qry = true;

    /*IMPORTANT! It must be called to tell the system the flush is ready*/
    lv_disp_flush_ready(disp_drv);
#endif
}

Hi gabor more info if it helps. The sample graphics we are replacing with yours pulls the test graphics from a flash location to the RAM address the LCD needs it to be. How do we link that to littlevgl where your function puts it directly through the display buffer variables. You can see my message above. I could not see where we give littlevgl the control when we register it and the correct memory location to put the graphics screen into.
(copy/paste of old function that we want to replace littleVGL with)

void LCD_PutPixmapFromNAND(short cx, short cy, Image * image)
{
//	unsigned char bydata;
	unsigned short int idata = 0;
	int i;
	int counter = 0;
	U16 addr1 = image->bkim_offset % NAND_PAGE_SIZE;
	U32 addr2 = image->bkim_offset / NAND_PAGE_SIZE;
	uint16_t x2, y2, x, y;	
//	U32 dwSum=0;
	
	  Assert( cx < LCD_WIDTH );
	  Assert( cy < LCD_HEIGHT );
	  Assert( image->bkim_width > 0 );
	  Assert( image->bkim_height > 0 );

	x=cx;
	y=cy;
	  // Compute bottom right point.
	  x2 = x + image->bkim_width - 1;
	  y2 = y + image->bkim_height - 1;

	  // More sanity check.
	  Assert( x2 < LCD_WIDTH );
	  Assert( y2 < LCD_HEIGHT );

	  // Set up draw area. 
	 LCD_SetLimits( x, y, x2, y2 );
	//LCD_SetLimits( control->x,0x74, x2, 0x9c );
	  // we need access to the display SRAM now
	LCD_SelectRegister( LCD_SRAMWRITE );			
	//LCD_DuplicatePixel( BLUE, control->bkim_size/2 );			
	if( xSemaphoreTake(xNANDMutex, portMAX_DELAY) != pdTRUE )
	{
		System_ErrorLogAdd(E13);
		AddCoreEvent(E_Error_Any);
		*pMDBSPECStatusReg |= MB_GENERIC_ERROR;
	}
	nf_select(0);		
	do 
   {
		addr1 = (image->bkim_offset + counter) % NAND_PAGE_SIZE;
		addr2 = (image->bkim_offset + counter) / NAND_PAGE_SIZE;					   
	   		
		addr1/=2;
		nf_open_page_read(addr2, addr1);
	   for ( i = 0; i < (1024 - addr1); i++ )		//(2048 - addr1)/2
	   {		   	   		   
			idata = nf_rd_data();	
			counter++;				
		  *LCD_PARAM_ADDR = idata;						
			counter++;	
			if (counter >= image->bkim_size)
			{
				if( xSemaphoreGive(xNANDMutex) != pdTRUE )
				{
					System_ErrorLogAdd(E13);
					AddCoreEvent(E_Error_Any);
					*pMDBSPECStatusReg |= MB_GENERIC_ERROR;
				}
				return;			
			}				
					
		}
		
	}while(counter < image->bkim_size);
	
	if( xSemaphoreGive(xNANDMutex) != pdTRUE )
	{
		System_ErrorLogAdd(E13);
		AddCoreEvent(E_Error_Any);
		*pMDBSPECStatusReg |= MB_GENERIC_ERROR;
	}
}

LittlevGL call these functions from lv_task_handler. It’s usually in the main while(1) in the example projects. All lvgl things happen in lv_task_handler: input device handling, drawing, animations, sending events (e.g. LV_EVENT_CLICKED), etc.

You disp_flush function should have the same prototype as monitor_flush:

void my_disp_flush(lv_disp_drv_t * disp_drv, const lv_area_t * area, lv_color_t * color_p)

my_disp_flush will be called from lv_task_handler to ask you to copy the rendered image to the display. Note that the rendered image is not necessarily the whole display. E.g. if you press a button, only that button will be redrawn and only its “image” will be sent to my_disp_flush.
The coordinates of where you should place the image are shown in the area parameter.

It’s up to you how to display the rendered image. In the simulator, it’s a copy to the frame buffer. But on an embedded hardware it could be sending the pixels via SPI or parallel port depending on your display.

Hi Gabor, Thank you. The reason I went back to your monitor code is the lv_port_disp_template function in the 6.0 download would not compile with our embedded compiler. I have made some changes to try to get it to compile but for example the disp_flush function in the template has parameter called disp_drv but the lv_disp_flush_ready tried to pass a disp variable that did not exist instead of the disp_drv parameter. Also in the init function there was a disp_drv.gpu_blend init call but there is no gpu_blend defined in the data structure disp_drv. I was worried that may be that could have been why it was not working yet I was using the wrong version of the template that is compatible with the lv lib that we have working on the PC. so I wanted to switch to your monitor code in the pc simulator and replace the windows specific code with our touchscreen, freeRTOS specific drivers in hope that would work. I am still learning your system so I appreciate your time and patience. That is why I was trying to use your hal_init function rather then the lv_port_disp_init function as the template. Do you recommend I go back to your templates, and if so which version should I download that would be best for touchscreen? Or is it Ok that I keep pushing to use your simulator files as the template?
Also we were using your online PNG to binary converter to generate C arrays. We needed the color format to be Format24bppRgb. Can we configure your online converter to generate the array and data structure we need?
Thank you again.

Hi,

I’ve just checked the port templates and they were a little bit outdated. I’ve just updated them.

Also we were using your online PNG to binary converter to generate C arrays. We needed the color format to be Format24bppRgb. Can we configure your online converter to generate the array and data structure we need?

lvgl can handle 32-bit colors instead of 24-bit. If you select 24-bit images with no transparency the upper bytes of the pixels will be set to 0xFF.
So lvgl needs 4 bytes/pixel even in case of 24 bit images. Therefore there is no 24 bit output format.