今天我们继续来学习高云开发板的代码,我们拿着开发板自然是要开发的,所以看代码是非常重要的,何况这种FPGA开发板上面没啥外设的,基本上都是接口,写这种评测报告嘛,其实光拍板子也是拍不出什么引人入胜的图片。我看很多大神都是讲协议讲代码的,所以咱们也继续讲代码好了。

讲完前面几篇代码解读,这篇就看起来有点用了,毕竟能点屏幕,至少像个玩具了。不过为了玩这个屏幕还是需要了解点相关知识的。

代码是这个位置,直接打开这个工程就好,这个demo说明上说是驱动屏幕出一些图案,我们可以先烧录试试。

这里有个小插曲,可能有些宝宝也会遇到。就是首先我们打开的是个LVDS屏幕的代码,它代码里面居然有个hdmi的东西,所以我们正常人肯定看了会受不了,直接把它从硬盘上删除才解恨。
不过删完后在编译,我晕,居然IDE闪退了,这就后悔了……

试了好多次都是闪退,又不想重新去下载代码。仔细观察后发现,原来路径里面中文,虽然我们是ubunt但是对方的IDE可能是windows开发的,所以这个bug还是有可能有的。
如图把demo程序移动到外面,然后就可以编译了。

搞完以后还要在project配置里面把这个几个复用脚给沟上,大概意思是这几个脚是要配置才能用于其他功能的。
折腾一圈总算可以烧录到板子上了。
接着进入正题。想看懂代码首先我们需要了解lvds的规范,如果里百度一大圈发现,找的到似乎又找不到,看完还是然并卵。所以我写这个代码解读不是要大家去看代码而是看我打的字。
这是个行业套路,比如我们上班会调屏幕,这样供应商会把所有的技术资料给我们,然后我们根本不需要去百度什么lvds规范。
但是像这个学习板的屏幕我们也是没有拿到技术资料的,那这些技术资料需不需要呢,我只能说如果要从零开始写这个程序肯定是需要的。大家知道如果你做这行就能了解到细节,不做那对你就是套路。
我公司的资料也是不能写在这里的,所以我也是网上随便百度了一些资料。

这个表是每个屏幕必须有的,无论是FPGA还是SOC去点屏幕都需要这些参数。这个是天马的屏幕,上面还有水印,不过我是百度出来的下载到的,按照商业习惯都是应该要保密的。举个例子说明一下,比如屏幕是1024*600的,那实际上线路上会传输跟多的像素,比如1100 * 700这么大的图,然后多余的不部分可能会分布在上下左右,这个叫水平和竖直消隐。像素传输的时候也是按照从左到右的再从上到下方式扫描,FPGA程序需要按照屏幕的要求传输比实际图形更大的这些像素过去。

这个图可以看到VS和HS这两个信号,一般这两个信号是低电平有效的,一个表示帧同步,一个表示行同步,下面还有一个信号叫DE表示数据有效,也就是有效的图形的像素被传输的时候DE就有效了。

然后这个图表达了像素的信息具体是怎么传输的,比如RGB的颜色分别用几个bit表示,然后每个bit又是在线路上怎么传输的,具体时序应该都会写得非常清楚。
注意,上面几张图片都不是我们调的屏幕的的文档,因为我没有那个文档,所以也没法截图,当然屏幕的文档没有我们肯定是没法调屏幕的。这里我讲讲大体方法就好,屏幕各种各样,只要能了解到它每个bit的那么底层,就能把代码写出来了。

我们的屏幕应该用的VESA这种格式传数据的,这个格式可以百度到,比如两个LVDS通道来传输一个屏幕的图像时,一路LVDS是10条线,其中一对是clk,剩下4对分布是数据。这个clk是个7bit的数据组成的图案,1100011这样先高中间低再高,是7个bit拼成的波形。下面每对数据一次传7个bit,8对线就是7*8=56个bit,一路lvds是4对数据线,两路组成56个bit,所以一路是28bit,一个像素有个24个bit分布代表红绿蓝三色的亮度,还有4个bit是控制位,就是前面说的vs hs de的信号,还有一个xx是保留的bit。从这样的图可以看出屏幕显示一个像素需要按照这样的时序来接收电平的变化。
有了以上的知识,我们可以继续解读代码了。

顶层代码有一个25m的外部时钟输入,输出有一个led灯,pwd是无用的,代码里面给它赋值常高,里面有些注释hdmi什么的这些应该是为了给小白制造恐慌用的,反正看注释你就输了。
lvds它定义了一路的时钟,和4路的数据,这说明它是单路的lvds。这里的lvds的知识有点多,我可能无法说细,如果有疑问就多百度,或者在下面回帖问我。

接着顶层的代码要从下往上看,它调用了很多ddio_lvds的模块,我们看这个模块里面是什么,其中最主要的是OVIDEO源语,这个可以查高云的手册,它是个7位的串化解串源语。
正如我们前面理论说的,一路lvds有4个数据线,每个数据线传一个像素需要送7个bit,所以这里会有串化解串操作。

数一数一共四个ddio_lvds调用,所以一次可以传送28个bit。这里一次指的是一个像素时钟周期,也有表示位pclk的,前面的屏幕参数里面提到的时钟周期一般都是指这个时钟。

我们再放大了看看,这里有个fclk一个pclk,这两个clk相差3.5倍,至于为什么相差3.5这要您数学好一点了。上面理论提到的1100011也在这里有。fclk实际上是串化解串的时候移位用的,pclk就是一个发送像素的周期。大家算一下发送两个像素,正好就移位了7个bit,根据屏幕的规格书算一下,算明白了这里也就理解了。

接着是colorbar的生成逻辑,看接口能看出来,大概是在屏幕上哪个坐标,生成什么颜色的像素。这个像素是24bit的。

有了前面几次的代码解读基础,这次也不用解释那么细了,主要看懂这个模块是根据屏幕坐标的输入,输出颜色就好,看上图的代码就是判断坐标的大小,生成条状的颜色,如果横竖都变化,是不是就会变成弧形了,这又是个数学问题,咱们也不深究了。

lcd驱动这块,我们看接口可以看到,有关于vs hs de的信号的生成,颜色的生成,大概要按照前面理论说的拼出vesa的格式的那个28个bit吧。然后按照消隐的要求控制hs vs de的电平就好。

点开这个lcd_driver的模块代码,别的我们可以看不懂,但这个计数的代码总不能看不懂吧,反正就是它数这个pclk,数出来这行是第几个像素,列又是第几个像素,然后减去左边和上面的消隐区,就是实际显示图形的像素坐标,对吧。

看到这坨代码的时候其实也没必要惊慌,因为这些H_BACK,V_SYNC就是消隐那些概念里面的东西,你百度一下里面就懂了,然后又是数学的计算,我数学没及格所以就没一笔一划的看了。

最后再放大了看一下这块,就是怎么算出显示图像的坐标的,根据这个坐标调用lcd_display就能获取到颜色的24个bit了。这里问大家一下,为什么不直接在这里调用lcd_display呢?作者是在顶层调用lcd_display,然后再用一些引脚把数据传入传出,看上去是挺麻烦的,这里我觉得可能是一种代码习惯,就是把模块尽量的平行化布局,不要用复杂的树行结构,理解这种思路以后可能对写大的工程有所帮助。
嗯,看来学习别人的代码的确可以得到不少书本上没有的东西。关于这些套路大家慢慢体会吧,FPGA这个行业被迫讨饭的多少都是被坑了的。