Running a EL640-400 TFEL display off the RPi native DPI/VGA interface

Following several somewhat successful tries to bit-bang VGA signals for TFEL displays I have moved to the integrated native display parallel interface (DPI) of Raspberry Pi models 2 and later [1][2].

By using this GPIO drive mode it is possible to offload framebuffer output to the hardware, which brings speed and saves a huge amount of CPU resources compared to bit-banging. This interface is frequently used for outputting VGA signals, since it is one of the original display signal output methods of the Broadcom CPU for driving parallel TFTs or LCDs. Obtaining analog VGA from it requires a resistor ladder DAC board [3], which combines the individual digital bit signals to analog multi-level RGB signals. In the case of a TFEL display this is not necessary, since the control circuit accepts digital level VGA. However, the clock mode is a bit unusual compared to the common configurations (as explained in previous posts: required is a 640×400 pixels, >70 Hz, monochrome signal).

To use this interface the GPIO has to be (partially) reconfigured to make the CPU output up to 24 bit of parallel RGB signals together with the standard VGA HSYNC, VSYNC and pixel clock. This requires additional lines at the end of the /boot/config.txt file [4, “dpi_timings”]:

dtoverlay=dpi24
framebuffer_width=640
framebuffer_height=400
overscan_left=0
overscan_right=0
overscan_top=0
overscan_bottom=0
enable_dpi_lcd=1
display_default_lcd=1
dpi_group=2
dpi_mode=87
dpi_output_format=0x000013
dpi_timings=640 1 0 4 0 400 0 0 1 0 0 0 0 75 0 19200000 5

Okay, enough with the codes. Let’s translate into clear text.

  • Enable dpi 24 bit mode, 640×400 pixels framebuffer
  • No overscan (transmit image no larger than screen)
  • Display monitor timing (DMT) group of modes (2)
  • Custom mode definition (87)
  • Format:
    • Color order RGB
    • Output format 3 (16 bit 565, see Fig. 3 below)
  • Timing:
    • 640 pixels line width, 400 lines
    • Inverted hsync, 4 pixels duration
    • Normal vsync, 1 pixel duration
    • No front/back padding on H/V sync pulses
    • 75 Hz repetition rate
    • Pixel clock 19.2 MHz (640x400x75)
    • Aspect ratio type 5 (16:10)

Since the dpi_format bitmask specification provided by raspberrypi.org is pretty much useless if you are trying to construct a mode format by hand, I have translated it into a graphic form:

Fig. 1: dpi_format – Bitmask in table form for easy reading.

I did encounter some problems when setting up the pixel clock rate. The internal PLL of the Pi, which is used to generate the clock frequency from the 19.2MHz base clock, seems to be limited to discrete steps (4.8, 6.4, 9.6, 19.2, 38.4, …MHz). Matching these steps requires a bit of twiddling with the repetition rate depending on the chosen resolution. Here, the next lower repetition rate would be 37.5 Hz (too low and fractional) and the next higher one would be 150 Hz (too high for the display).

Next, the display is connected to the GPIO port:

  • VSYNC to GPIO 1
  • HSYNC to GPIO 2
  • PCLK to GPIO 0
  • VID to GPIO 11 (blue MSB in the given config)
  • GND to any GND on the Pi
  • VDD 5V (can be taken from the Pi, but is better supplied externally)
  • VS 12V from an additional power supply line (don’t forget the GND)

I am not using the second pixel input, since the Pi is outputting color values of each pixel in sync to the PCLK signal – never two consecutive pixels at the same time. The power supply driving the display VS rail should be capable of delivering at least 20% more current than the maximum stated in the datasheet of the specific display model – it varies over screen type and brightness.

After a reboot, the Pi should send a clear and flicker-free picture at 75 Hz repetition rate. Since the picture is coming from the actual graphics card, any desktop environment will also show up if so configured – a huge benefit compared to my bit-banging program, which only read the linux console fb.

Fig. 2: TFEL running off the RPi hardware-VGA. No flickering, very crisp picture (although the camera glitched out on me and it might not look like much ;-)

My configuration is not the only way to do it: the Pi outputs RGB as 565-bit (meaning 5, 6 and 5 bits per RGB color), 666-bit or 888-bit (full 24-bit color) as selected in the format configuration, and the distribution over IO pins is flexible to a degree:

GPIO pin mappings vs. DPI mappings (adapted from [2]).
Fig. 3: GPIO special function mapping vs. used pins for each DPI configuration (adapted from [2]).

Since the TFEL display only supports monochrome output anyways – except for software dithering – the framebuffer content can be of any arbitrary color. If the content is black-and-white only, all color bits are used. In consequence all of the RGB pins will carry the same signal, which allows a selection of “least impact” on the more important GPIO secondary functions, such as SPI. In theory, it should also be possible to reactivate groups of unused RGB signal pins to their primary functionality by adding another dtoverlay after setting up the DPI, or by setting the corresponding gpio mode configuration registers using C code or something else. In that case, only specific bits of the framebuffer color codes are sent to the GPIO. Unfortunately, the loss of hardware I2C interfaces cannot be avoided by either method, since both I2C#0 and I2C#1 are used for the high-speed clock and sync signals.

Links

[1] https://de.wikipedia.org/wiki/Display_Serial_Interface
[2] https://www.raspberrypi.org/documentation/hardware/raspberrypi/dpi/README.md
[3] https://github.com/PiSupply/Gert-VGA-666
[4] https://www.raspberrypi.org/documentation/configuration/config-txt/video.md

Leave a Reply

Your email address will not be published. Required fields are marked *