这个屏幕其实是很久以前买的了,是一个叫做LITE ARRAY的公司产的EL屏幕,网上也找不到什么数据手册。样子倒是确实非常接近Plannar的EL320.256-FD6,使用起来是否一样……之后就知道啦。屏幕有效区域尺寸为4.8英寸,屏幕显示比例为5:4。

驱动

由于没有资料,只能想办法套其它屏幕的资料。经过测量,可以得出以下的引脚定义:

1-2: 高压DCDC输入
3-4: 逻辑供电输入
5,7: 浮空
6,8,10,12,14,16: 接地
9,11,13,15: 输入信号

所有的输入信号经过了一层74HC14D,倒是方便了使用3.3V IO直接驱动。对比一下EL320.256-FD6的数据手册,不难发现电源部分的定义是相同的,只是少了两个信号。考虑到屏幕板上有FPGA和RAM,屏幕应该为自刷新屏幕,有可能接上电源就能够显示了。结果确实如此:

1615776292027-2021-03-14 22.44.33.jpg

那么下一步就是要怎么把数据写进去了。我这里选择了使用树莓派4平台进行驱动,树莓派4的GPIO用来驱动这个屏幕应该是完全没有问题的。使用树莓派而不是单片机应该会在之后播放Bad Apple的时候提供一些便利。在进行了一些简单的尝试后,结论是:只要按照正常非自刷新屏幕的HVsync接口时序写数据进去就可以了。

1615776755790-2021-03-14 22.52.15.jpg

以下是驱动代码(暴力bitbang)供参考:

    digitalWrite(PIN_VCLK, 1);
    for (int y = 0; y < SCR_HEIGHT + 1; y++) {
        digitalWrite(PIN_HS, 0);
        for (int x = 0; x < 4; x++) {
            digitalWrite(PIN_VCLK, 0);
            digitalWrite(PIN_VCLK, 0);
            digitalWrite(PIN_VCLK, 1);
            digitalWrite(PIN_VCLK, 1);
        }
        digitalWrite(PIN_HS, 1);
        for (int x = 0; x < SCR_STRIDE; x++) {
            uint8_t d = *rdptr++;
            digitalWrite(PIN_VS, (y == 0) ? (((x > 10) && (x < 20)) ? 0 : 1) : 1);
            for (int b = 0; b < 8; b++) {
                digitalWrite(PIN_VID, d & 0x01);
                d >>= 1;
                digitalWrite(PIN_VCLK, 0);
                digitalWrite(PIN_VCLK, 0);
                digitalWrite(PIN_VCLK, 1);
            }
        }    
    }

    digitalWrite(PIN_VS, 0);
    digitalWrite(PIN_HS, 0);
    digitalWrite(PIN_VCLK, 0);

播放Bad Apple

要播放BA,这里有几个不同的思路:

  • 预先处理视频,转码为可以直接发送至EL屏幕的二进制文件
  • 使用FFMPEG API等,直接解码视频播放并发送至EL屏幕
  • 使用一般播放器播放视频,将主显示器内容串流到EL屏幕上

我这里是用了方法3。在树莓派上,采集当前显示内容的最好方法是直接使用VideoCore用户库提供的函数,直接获得GPU混成之后的最终帧缓冲区,这样才可以正常捕捉硬件加速的内容(如硬件视频解码、3D内容等)。代码的话可以直接参考fbcp。

这里设计两个线程,一个线程负责截图、缩放、抖动、二值化、双缓冲管理以及FPS限制,而另外一个线程负责把二值化之后的图像缓冲区通过GPIO发送出去。两个线程之间使用semaphore来保证同步。抖动算法用的也就是标准的Floyd-Steinberg dithering,对于没有灰度的屏幕而言还是相当有必要的。因为只是为了快速写完,没有太多注意性能问题,毕竟只是个demo嘛。

完整的源代码可以参考:https://gist.github.com/zephray/2f6ebda28fa699461af784afe6515468

1615828905949-el1.jpg

视频演示:https://www.bilibili.com/video/BV1k54y187E9/

其它

这个屏幕有个有意思的设计,屏幕本身是有双缓冲设计的。不像一般的自刷新屏幕,写入显示内存的东西会及时的显示出来,这个屏幕需要至少给一个场同步信号之后才会交换前后缓冲。这种做法可以避免让用户看见屏幕图像慢慢写入的过程,但是因为输入的Vsync信号只是切换前后缓冲区的信号,这个信号是和屏幕自刷新是完全异步的,并不能避免图像撕裂的问题。当然这里另外一个猜测是,这么设计也有可能只是为了避免雪花现象,即当写入和读取同时发生的时候,SRAM只能允许其中一个完成,通常而言是写入。这种情况就会造成屏幕上短暂的白点(或者黑点),通常就被称为雪花现象。这种其实在现代的屏幕控制器上都已经不存在了。

用树莓派写这类以前一般用单片机做的事情体验确实也很奇妙,一方面是熟悉的GPIO,而另外一方面是方便的多的文件IO、网络、多线程能力。当然因为Linux的原因,实时性是肯定很难保证的,也就不适用于很多嵌入式场景,但是只是对于这种玩玩做做demo的用途,似乎确实是蛮方便的。

这次点屏其实也是跟风,看罗老师玩我也就跟着把自己吃灰已久的EL拿出来耍了耍。罗老师点屏的传送门:http://7400.me/2021/03/06/Sharp_LJ64H052/ 他的屏幕可就不像我的这个这么好伺候了。