Display Drivers#

There are a wide variety of displays, controllers and communication protocols that may potentially be able to be used with Tempe. There is, however, a limit to the hardware which the Tempe developers have access to. This means that you may need to implement a driver for your display. Fortunately, there is just one method that you need to implement for a display driver.

Implementing Display Drivers#

To get the full advantage of Tempe, a device needs to be capable of updating just a rectangular region of the screen. To implement a driver for the display, this is all you need to provide.

The Display protocol is simply the following:

class Display:

    def blit(self, buffer, x, y, w, h):
        """Send a buffer of pixels to the rectangle (x, y, w, h).

        The buffer will consist of w * h 16-bit pixels exactly and so
        will have a size of 2 * w * h bytes.
        """
        ...

If you are lucky you have a device driver which already supports this sort of windowed transfer (and doesn’t need a full-screen framebuffer). In this case you can simply wrap the device to make the API match:

class MyDisplay:

    def __init__(self, my_display):
        self._display = my_display

    def blit(self, buffer, x, y, w, h):
        """Send a buffer of pixels to the rectangle (x, y, w, h).

        The buffer will consist of w * h 16-bit pixels exactly and so
        will have a size of 2 * w * h bytes.
        """
        self._display.blitmethod(buffer, x, y, w, h)

Failing this, you may need to read the datasheet for your display and work out how to initialize it and perform these operations.

Currently Supported Displays#

FileDisplay#

The Tempe library comes with a simple FileDisplay that writes raw RGB565 bytes to a file. This is used for testing and to produce images for documentation. There is a CPython script in the ci directory that uses Pillow to convert these to PNG files.

ST7789#

The tempe_displays library has a base class for devices which use the ST7789 controller, and a subclass ST7789_SPI which talks to the controller using SPI. These classes are not complete: you will need to subclass and fill in missing functionality for your particular device: for the base device you will need to supply write methods, and for the SPI device you will need to provide appropriate initialization for the device (which may depend on physical properties of the hardware, such as gammma curve adjustments). Consult your hardware documentation.

Pimoroni ST7789 SPI Displays#

This is a family of similar displays of various sizes that use the ST7789 controller and SPI to communicate with it. The PimoroniDisplay class, if given the size of the screen should be able to work out which device it is and configure it appropriately. Some displays, such as the round breakout garden display and the original Pico Display Pack are centered in the ST7789 memory space, and should have the centered parameter set to True.

Since starting the display requires some time waiting for commands to complete, they have an asynchrononous inititiaization method.

The PimoroniDisplay classes know the standard pin layouts for these boards, and so these can usually be initialized something like:

async def init_display()
    display = PimoroniDisplay(size=(320, 240))
    await display.init(rotation=270)
    display.backlight_pin(1)
    return display