#LetsDriveLCD [-5] – LAEL320.256-6C



I got this screen a while ago. It was produced by a company called LITE ARRAY, but I couldn't find the datasheet online. It looks similar to the EL320.256-FD6 made by Plannar, but I will need to find out if it's indeed compatible or not. The active display area is about 4.8" diagonally, with an aspect ratio of 5:4.


As I don't have the datasheet, I kind of have to guess. By just probing around, I can get the following pinout:

1-2: High-voltage DCDC input
3-4: Logic power supply
5,7: No connection
6,8,10,12,14,16: Ground
9,11,13,15: Input digital signal

All the input signals are buffered by 74HC14Ds on board, making it easy to drive them with 3.3V signal. Comparing to the EL320.256-FD6, the pinout of all the power supplies matches. Considering there are RAMs and FPGA on the board, the screen is likely a self-refresh screen. It's possible it would display something simply by connecting the power supply. It turned out to be true:

1615776292027-2021-03-14 22.44.33.jpg

Next issue is about how to get the data into the screen. I used an Raspberry Pi 4 to drive it, should be more than enough. By using an RPi 4, it should make playing back videos easier. After some trial and error, the conclusion is that, just use it as a more common non-self-refresh EL screen with HVsync interface.

1615776755790-2021-03-14 22.52.15.jpg

Bitbanging code for reference:

    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);

Playing back Bad Apple

To play Bad Apple on it, there are several possible approaches:

I am using the last approach. On Raspberry Pi, one good way to capture the screen is to use the function provided by VideoCore user library. It provides a pointer to the GPU framebuffer, making it possible to capture hardware accelerated contents like 3D games or hardware decoded video. fbcp is a good reference.

I have 2 threads here. One thread for taking screenshot, resizing, dithering, binarizing, double-buffering management, and FPS limit. Another thread for pushing images to the screen over GPIO. Two threads are synchronized using semaphores, and the dithering is just a common Floyd-Steinberg dithering. As a demo, I didn't pay much attention to the optimization.

Full source code: https://gist.github.com/zephray/2f6ebda28fa699461af784afe6515468


Video demo: https://www.bilibili.com/video/BV1k54y187E9/


One interesting design about this screen is that it actually utilizes double buffering. One a typical self-refresh screen, the RAM for host access is the RAM for display. So if the writing process is visible on the screen if the host is slow or not synchronized to the refresh. On this EL screen, that's not visible as all host writes happens on the back buffer. It swaps buffer during Vsync. Of course, as input Vsync is async to the internal clock/ refresh timing, it does not prevent tearing (unless it has triple buffering). Another guess is that it's designed in this way solely to avoid contention between RAM read and write, which was a common issue in older LCD/ EL display controller designs.

One of my friend also got an EL screen recently (but much larger), check it out: http://7400.me/2021/03/06/Sharp_LJ64H052/