前序
自从入手树莓派一代,一直闲置着。现在树莓派都二代了,再不玩玩就彻底吃灰了。可惜的是树莓派没接显示器总归不好玩。
我手头有一个Atmel A5(SAMA5D3)的ARM板子,自带TFT-LCD电容触摸液晶屏和USB接口,刚好作为树莓派1代的显示器,两者之间用 USB传输图像数据(不求性能,能显示就行)。
准备就绪就缺实现方案了,突然想起RoboPeak有一个树莓派的液晶屏在卖,而且开源树莓派端的驱动和协议,那我就充分发挥开源优势,在这个基础上改。
这就涉及到两个USB驱动:
- ARM液晶屏的USB gadget驱动:项目在这里
- 树莓派的USB HOST驱动:首先刷RoboPeak的树莓派固件,重新编译树莓派的Linux kernel, 编译修改原来的RoboPeak的开源树莓派驱动。最后改好的驱动项目在这里
在研究kernel的USB gadget驱动过程中发现了一个USB协议详解网站,当然USB协议文档也必不可少,开发驱动的话单单看第9章就行了。
实现原理
这里只说gadget驱动,host驱动用RoboPeak原来的rpusbdisp,单单改了分辨率(改成液晶屏的分辨率800X480),当然现在驱动刚刚能用,还有很多要完善。
在USB协议层上有一个interface,两个endpoint,一个OUT传输Robopeak液晶屏的图像协议,另一个IN传输触摸屏的输入。
- OUT endpoint
根据RoboPeak的rpusbdisp的协议,我只实现图片拷贝的bitblt命令就行了,这个是host驱动检测到画面有更新后拷贝图片给gadget驱动。我只要介绍到图片数据(颜色深度16位,565格式的真彩色)拷贝到当前的framebuffer就可以了,我这里直接霸王硬上弓拷贝的framebuffer的base memory里。
当然一幅800480的图片传输数据就有700多K(800480*2=768000),为了压缩数据,RoboPeak的协议里检测到gadget驱动版本大于1.04会采用新的压缩数据方法。简单来说就是分成128字节的段,每个段有一个head字节,表示当前端是否是重复的颜色数据(一般的桌面背景很多重复颜色数据),这样简单的压缩一下传输的数据一下子就下降了很多。
- IN endpoint
标准的中断数据,由于这个ARM板子是pixcir的芯片,支持电容屏和多点触摸。我在pixcir的驱动里做了一个HOOK函数获取触摸位置再发送给host。
好了,具体的细节看代码吧:)。