可绘画的LCD显示屏
本帖最后由 辛一_e1e 于 2022-3-27 12:39 编辑
首先承认有点标题党了,实现功能还不全。
先上视频,在LCD屏幕绘制了两个长方形,一个实心的,一个空心的,其中空心的边框宽度可调,而且绘图的颜色还可以通过按钮调整,现在支持红、绿、蓝和白,四种颜色。
整体的硬件设计还是基于上一个帖子的软核PicoRV32,在OPEN AHB INTERFACE的地方,我挂载了128Kbits的BSRAM用于显存。
这128Kbits的显存,本质上是一颗双端口的BSRAM。为什么需要双端口呢?因为为了达到FPGA加速的目的,使得CPU和自定义的LCD驱动IP共同使用这颗显存。
- ahb2bram ahb2bram(
- .clk_i(clk50),
- .reset_i(~sys_rstn),
- .hrdata_o(hrdata),
- .hresp_o(hresp),
- .hready_o(hready),
- .haddr_i(haddr),
- .hwrite_i(hwrite),
- .hsize_i(hsize),
- .hburst_i(hburst),
- .hwdata_i(hwdata),
- .hsel_i(hsel),
- .htrans_i(htrans),
- .lcd_clk_i(clk10),
- .lcd_rd_i(lcd_rd),
- .lcd_addr_i(lcd_addr),
- .lcd_data_o(lcd_data)
- );
复制代码
在这个系统中,CPU主要负责图形的“渲染”,这个在大型系统中常常是GPU来做的。在我这里说的有点夸张了,其实就是画个长方形,CPU根据顶点数据,以及图形类型,把对应的显存地址填入1或者0。
- void draw_rectangle(uint8_t top_x, uint8_t top_y, uint8_t btm_x, uint8_t btm_y, uint8_t type)
- {
- uint8_t i,j;
- uint8_t calc_x;
- uint8_t calc_y;
- calc_x = top_x/32;
- calc_y = top_y/32;
-
- for(i=0; i
- for(j=0; j
- {
- if(j>=calc_x && j<=calc_y && i>=top_y && i<=btm_y)
- PCIO_AHBSRAM->SRAM[i*X_MAX+j] = RGB;
- }
- }
复制代码
硬件的原理就是,CPU访问AHB总线,发出读写命令。自定义的AHB2SRAM模块,会将总线地址转换成显存地址,将数据保存起来。
一套流程下来,要绘制的图形就保存在了显存中,只要不掉电,就不会丢失。
另外一边,LCD驱动IP只负责从显存中取数据,就可以完完整整的将图形显示在LCD屏幕上了。
- VGAMod VGAMod
- (
- .nRST(sys_rstn),
- .PixelClk(clk10),
- .lcd_rd_o(lcd_rd),
- .lcd_addr_o(lcd_addr),
- .lcd_data_i(lcd_data),
- .LCD_DE(LCD_DE),
- .LCD_HSYNC(LCD_HSYNC),
- .LCD_VSYNC(LCD_VSYNC),
- .LCD_B(LCD_B_t),
- .LCD_G(LCD_G_t),
- .LCD_R(LCD_R_t)
- );
复制代码
受限于资源,此文实现的系统只有128Kbits的显存,C程序中显存的驱动写的有点别扭,显存是按照最小32bit访问的,而LCD像素地址是需要对应到1bit,因此之间的地址映射需要除以32。
对于480x272 RGB565的LCD屏幕来说,如果想达到显存地址和像素地址一一对应,最少需要2040Kbits。后续可以考虑将显存挂载到FPGA内部的PSRAM中,PSRAM有64Mbits的大小,能够缓存多张图片,可以实现图片叠加,图片增强等一系列操作,感觉把LVGL移植上去,也不是不行哦。
写到这里,又想到一个充分利用128Kbits显存的办法。大概就是FPGA内部生成一个256色的颜色查找表LUT。C驱动这边给显存中不是直接存放颜色数值,而是存放这个查找表的地址8bit。如果不需要这么多的颜色的话,可以缩小到8色,对应查找表的地址只要3bit。480*272*3/1024,大于只要383Kbits,大大降低了资源使用,还方便了驱动的编写。这个方案后续尝试一下吧。
|