LVGL 显示设备适配
在main函数中我们调用了lv_port_disp_init(),此处分析其接口函数;
源码分析
static void disp_init(void)
{
/*
*初始化anyka3760e sdk
*/
sdk_run_config config = {0};
config.mem_trace_flag = SDK_RUN_NORMAL;
ak_sdk_init(&config);
/*安装fb*/
system("insmod /usr/modules/ak_fb.ko");
/*安装tde*/
system("insmod /usr/modules/ak_gui.ko");
/*You code here*/
fbfd = open(FBDEV_PATH, O_RDWR|O_EXCL);
if(fbfd == -1)
{
perror("Error: cannot open framebuffer device");
return;
}
if(ioctl(fbfd, FBIOGET_FSCREENINFO, &finfo) == -1)
{
perror("Error reading fixed information");
return;
}
// Get variable screen information
if(ioctl(fbfd, FBIOGET_VSCREENINFO, &vinfo) == -1)
{
perror("Error reading variable information");
return;
}
vinfo.xres = LV_HOR_RES_MAX;
vinfo.yres = LV_VER_RES_MAX;
#ifdef LCD_FORMAT_24
vinfo.bits_per_pixel = 24;
vinfo.red.offset = 16;
vinfo.red.length = 8 ;
vinfo.green.offset = 8;
vinfo.green.length = 8 ;
vinfo.blue.offset = 0;
vinfo.blue.length = 8;
#else
vinfo.bits_per_pixel = 16;
vinfo.red.offset = 11;
vinfo.red.length = 5 ;
vinfo.green.offset = 5;
vinfo.green.length = 6 ;
vinfo.blue.offset = 0;
vinfo.blue.length = 5 ;
#endif
ioctl(fbfd, FBIOPUT_VSCREENINFO, &vinfo);
int bpp = vinfo.bits_per_pixel;
screensize = vinfo.xres*vinfo.yres*bpp/8;
extern void *osal_fb_mmap_viraddr(int fb_len, int fb_fd);
fbp = (unsigned char*)osal_fb_mmap_viraddr(screensize*2,fbfd);
FB_BUFFER = FB_BUFFER_A;
FB_BUFFER_SET;
fbp_phyaddres = finfo.smem_start;
printf("fb buffer 1:%p,2:%p ,phy:%lu ,2:%lu \n",fbp,fbp + screensize,fbp_phyaddres,fbp_phyaddres + screensize);
gui_buffer = (unsigned char*)ak_mem_dma_alloc(MODULE_ID_VO, LV_HOR_RES_MAX*LV_VER_RES_MAX*4);
ak_mem_dma_vaddr2paddr(gui_buffer, (unsigned long *)&gui_phyaddres);
ak_tde_open();
printf("The framebuffer device was mapped to memory successfully.\n");
}
void lv_port_disp_init(void)
{
/*初始化fb设备*/
disp_init();
/*
*用一个屏幕大小(argb8888)的内存块用于lvgl内部画图
*
*/
static lv_disp_buf_t draw_buf_dsc_3;
lv_color_t* draw_buf1 = (lv_color_t*)ak_mem_alloc(MODULE_ID_VO, LV_HOR_RES_MAX*LV_VER_RES_MAX*4);
lv_disp_buf_init(&draw_buf_dsc_3,draw_buf1, NULL, LV_HOR_RES_MAX*LV_VER_RES_MAX);
/*
*初始化显示设备
*/
lv_disp_drv_t disp_drv;
lv_disp_drv_init(&disp_drv);
disp_drv.hor_res = LV_HOR_RES_MAX;
disp_drv.ver_res = LV_VER_RES_MAX;
/*
* 注册显示设备回调函数,在lvgl将控件准备好后通知此函数将画布填充到lcd上面
*/
disp_drv.flush_cb = disp_flush;
/*Set a display buffer*/
disp_drv.buffer = &draw_buf_dsc_3;
#if LV_USE_GPU
disp_drv.gpu_blend_cb = gpu_blend;
/*Fill a memory array with a color*/
disp_drv.gpu_fill_cb = gpu_fill;
#endif
/*
* 真正将显示服务注册到lvgl内核中
*/
lv_disp_drv_register(&disp_drv);
}
static void fb_flush_to_fb(void)
{
FB_BUFFER_GET;
FB_BUFFER = FB_BUFFER == FB_BUFFER_A?FB_BUFFER_B:FB_BUFFER_A;
if((system_bg_enable == true)&&(system_bg_addres != NULL))
{
bg_flush_to_fb();
}
gui_flush_to_fb();
FB_BUFFER_SET;
}
static void disp_flush(lv_disp_drv_t * disp_drv, const lv_area_t * area, lv_color_t * color_p)
{
if(color_p == NULL)
{
goto pos_flush;
}
if(area->x2 < 0 ||area->y2 < 0 || area->x1 > (int32_t)vinfo.xres - 1 ||area->y1 > (int32_t)vinfo.yres - 1)
{
lv_disp_flush_ready(disp_drv);
return;
}
int32_t act_x1 = area->x1 < 0 ? 0 : area->x1;
int32_t act_y1 = area->y1 < 0 ? 0 : area->y1;
lv_coord_t src_w = lv_area_get_width(area);
lv_coord_t src_h = lv_area_get_height(area);
int disp_row_byte = LV_HOR_RES_MAX*4;
int draw_row_byte = src_w*4;
unsigned char* dst = gui_buffer + act_y1*disp_row_byte + act_x1*4;
unsigned char* src = (unsigned char*)color_p;
for(int h = 0 ; h < src_h ; h++)
{
memcpy(dst,src,draw_row_byte);
dst += disp_row_byte;
src += draw_row_byte;
}
if(lv_disp_flush_is_last(disp_drv) == true)
{
pos_flush:
fb_flush_to_fb();
ak_sleep_ms(1);
}
lv_disp_flush_ready(disp_drv);
}
#endif