Screen

[中文]

Screen is a very important display device as many information from various applications needs to be displayed to users. Both ESP32 and ESP32-S2 chips support screens driven by I2C interface, 8080 parallel interface, SPI interface and etc. The supported types of screen controllers are listed in the following table:

Controller

Max Resolution

Type

NT35510

480 x 865

Color

ILI9806

480 x 865

Color

RM68120

480 x 865

Color

ILI9486

320 x 480

Color

ILI9341

240 x 320

Color

ST7789

240 x 320

Color

ST7796

320 x 480

Color

SSD1351

128 x 128

Color

SSD1306

128 x 64

Mono

SSD1307

128 x 39

Mono

SSD1322

480 x 128

Gray

Note

The 8080 parallel interface is implemented via the LCD mode in the I2S of ESP32, so sometimes it is called I2S interface in this document.

Screen Driver Structure

../_images/screen_driver_structure.png

Screen Driver Structure Diagram

In order to be more in line with the actual situation where a screen controller has multiple interfaces, the screen driver is divided into two parts: the interface driver and the controller driver.

  • The interface driver: conduct basic reads and writes of commands and data

  • The controller driver: display information on screen via interfaces

A controller driver can be designed to switch between different interfaces in hardware level by calling corresponding interface drivers.

Screen Types

A discussion about screen types will help us to have a clear understanding of drivers. Here, we use colors that can be displayed on the screen to classify screens, rather than the panel material of them such as OLED, LCD and etc. In general, the colors displayed on screen determines the BPP (Bits Per Pixel), and the differences in BPP lead to differences in how the program handles it. Here, we list some ways in which GRAM is mapped to pixel points in below:

../_images/screen_driver_RGB565.png

BPP = 16 GRAM Structure

../_images/screen_driver_mono.png

BPP = 1 GRAM Structure

../_images/screen_driver_gray.png

BPP = 4 GRAM Structure

From above figures, we can see that there are mainly two types of mapping:

  • When BPP >= 8, it is usually a color screen that supports RGB888, RGB666, RGB565 and other codings.

  • When BPP < 8, it is usually a mono screen that may either be black-and-white or gray.

When BPP < 8, a byte is mapped to multiple pixels, so a single pixel cannot be controlled directly. In this case, draw_pixel() is not supported in the driver, and the parameters of set_window() are also limited. When BPP >= 8, each single pixel can be accessed easily.

Attention

For color screens, the driver only supports RGB565 color coding.

Interface Driver

A screen controller usually has multiple interfaces. On ESP32, three kinds of interfaces as 8080 parallel interface, SPI and I2C are typically used to connect to the screen. You can choose one of them as the interface when creating interface drivers via scr_interface_create().

Note

Please remember to select corresponding parameter types when creating different interfaces using scr_interface_create(), e.g., select i2s_lcd_config_t for I2S interface; select scr_interface_spi_config_t for SPI interface.

To facilitate the use of these interfaces in the driver, all interfaces are defined in display/screen/screen_utility/interface_drv_def.h, which can be called easily by less parameters.

Note

Most screens use big-endian order to store data, while ESP32 uses small-endian mode. You can switch between them in the interface driver you used, based on swap_data configurations. Please note: when using the SPI interface, the received data must be stored in RAM because the IDF’s SPI driver itself does not support this swapping function and an additional program in the interface driver will do the work, which require the data to be writable.

Controller Driver

Some common functions of the screen are abstracted using scr_driver_t in this section according to display and other functions of different screen controllers, in order to port these common functions to different GUI libraries easily. For some non-generic functions of the screen, you need to call its specific functions.

Not all screens have implemented these common functions, since different screen controller has their own functions. For example, for screens with BPP < 8, the function draw_pixel() is not supported. And calling an unsupported function will return ESP_ERR_NOT_SUPPORTED.

Display Direction

The screen display direction set here is implemented entirely by the screen hardware, and this feature varies from one screen controller to another. There are 8 possible display directions. A display can be rotated by 0°, 90°, 180° or 270° and can also be viewed from the top or bottom, with 0° and top view as its default direction. These 8 (4 × 2) directions can also be represented as a combination of 3 binary switches: X-mirroring, Y-mirroring and X/Y swapping.

The total 8 combinations of display directions are listed in the following table. If the direction of your display is not correct, please check the configuration switches below to make it work properly.

original

0 [SCR_DIR_LRTB]

mirror_y

SCR_MIRROR_Y [SCR_DIR_LRBT]

mirror_x

SCR_MIRROR_X [SCR_DIR_RLTB]

mirror_xy

SCR_MIRROR_X| SCR_MIRROR_Y [SCR_DIR_RLBT]

swap_xy

SCR_SWAP_XY [SCR_DIR_TBLR]

swap_xy_mirror_y

SCR_SWAP_XY| SCR_MIRROR_Y [SCR_DIR_BTLR]

swap_xy_mirror_x

SCR_SWAP_XY| SCR_MIRROR_X [SCR_DIR_TBRL]

swap_xy_mirror_xy

SCR_SWAP_XY| SCR_MIRROR_X| SCR_MIRROR_Y [SCR_DIR_BTRL]

The implementations of display directions are not exactly the same for different screen controllers, and are usually divided into the following cases:

  • For color screens, 8 directions are supported.

  • For mono screens, e.g., SSD1306, only the first 4 directions defined in scr_dir_t are supported, which means they do not support X/Y swapping.

Note

The display direction is also related to the screen panel you used, and you may encounter two types of abnormal cases:

  • The display direction is set to SCR_DIR_LRTB, but the screen does not show as what listed in the above table. This may be because the alignment on the screen panel is mirrored in the X/Y direction, in which case you need to adjust the rotation to get the desired direction.

  • After rotated, the screen does not show anything any more. This may be because the resolution of the screen panel is smaller than that of the screen controller, making the display area not falling completely on the screen panel, in which case you need to set a proper offset for the display area.

Offset of the Display Area

In some small screens, the resolution of the display area is usually smaller than that of the controller window. Please refer to the following figure:

../_images/screen_offset.png

In this figure, Controller window is the window for screen controller, with its resolution as 240 × 320; Panel window is the window for screen panel, with its resolution as 135 × 240, which is the display area. From this figure, we can see that the display area is shifted by 52 pixels horizontally and by 40 pixels vertically.

When the screen is rotated 90° anticlockwise, the display area is shifted by 40 pixels horizontally and by 53 pixels vertically, as shown in the figure below:

../_images/screen_offset_rotate.png

The screen controller driver will help you to change the offset value automatically according to the rotation of the screen to maintain a proper display. All you need to do is to properly configure the screen offset and the screen panel size in scr_controller_config_t when it is in SCR_DIR_LRTB direction.

Note

  • This only supports screens with BPP >= 8.

  • When the resolution of your screen controller is configurable and you find something wrong with the offset, it may be because the selected resolution does not match the actual one, and you should make modifications accordingly, for example, set the ILI9806_RESOLUTION_VER in ili9806.c as the actual resolution for ILI9806.

Application Example

Initialize the Screen

scr_driver_t g_lcd; // A screen driver
esp_err_t ret = ESP_OK;

/** Initialize 16bit 8080 interface */
i2s_lcd_config_t i2s_lcd_cfg = {
    .data_width  = 16,
    .pin_data_num = {
        1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16
    },
    .pin_num_cs = 45,
    .pin_num_wr = 34,
    .pin_num_rs = 33,
    .clk_freq = 20000000,
    .i2s_port = I2S_NUM_0,
    .buffer_size = 32000,
    .swap_data = false,
};
scr_interface_driver_t *iface_drv;
scr_interface_create(SCREEN_IFACE_8080, &i2s_lcd_cfg, &iface_drv);

/** Find screen driver for ILI9806 */
ret = scr_find_driver(SCREEN_CONTROLLER_ILI9806, &g_lcd);
if (ESP_OK != ret) {
    ESP_LOGE(TAG, "screen find failed");
    return;
}

/** Configure screen controller */
scr_controller_config_t lcd_cfg = {
    .interface_drv = iface_drv,
    .pin_num_rst = -1,      // The reset pin is not connected
    .pin_num_bckl = -1,     // The backlight pin is not connected
    .rst_active_level = 0,
    .bckl_active_level = 1,
    .offset_hor = 0,
    .offset_ver = 0,
    .width = 480,
    .height = 854,
    .rotate = SCR_DIR_LRBT,
};

/** Initialize ILI9806 screen */
g_lcd.init(&lcd_cfg);

Note

By default, only the driver of ILI9341 screen is enabled. If you need to use other drivers, please go to menuconfig -> Component config -> LCD Drivers -> Select Screen Controller to enable the corresponding screen drivers.

Display Images

/** Draw a red point at position (10, 20) */
lcd.draw_pixel(10, 20, COLOR_RED);

/** Draw a bitmap */
lcd.draw_bitmap(0, 0, width_of_pic, height_of_pic, pic_data);

Obtain Screen Information

scr_info_t lcd_info;
lcd.get_info(&lcd_info);
ESP_LOGI(TAG, "Screen name:%s | width:%d | height:%d", lcd_info.name, lcd_info.width, lcd_info.height);

API Reference

Header File

Functions

esp_err_t scr_find_driver(scr_controller_t controller, scr_driver_t *out_screen)

Find a screen driver.

Return

  • ESP_OK on success

  • ESP_ERR_INVALID_ARG Arguments is NULL.

  • ESP_ERR_NOT_FOUND Screen controller was not found.

Parameters
  • controller: Screen controller to initialize

  • out_screen: Pointer to a screen driver

Structures

struct scr_controller_config_t

configuration of screen controller

Public Members

scr_interface_driver_t *interface_drv

Interface driver for screen

int8_t pin_num_rst

Pin to hardreset LCD

int8_t pin_num_bckl

Pin for control backlight

uint8_t rst_active_level

Reset pin active level

uint8_t bckl_active_level

Backlight active level

uint16_t width

Screen width

uint16_t height

Screen height

uint16_t offset_hor

Offset of horizontal

uint16_t offset_ver

Offset of vertical

scr_dir_t rotate

Screen rotate direction

struct scr_info_t

Information of screen.

Public Members

uint16_t width

Current screen width, it may change when apply to rotate

uint16_t height

Current screen height, it may change when apply to rotate

scr_dir_t dir

Current screen direction

scr_color_type_t color_type

Color type of the screen, See scr_color_type_t struct

uint8_t bpp

Bits per pixel

const char *name

Name of the screen

struct scr_driver_t

Define a screen common function.

Public Members

esp_err_t (*init)(const scr_controller_config_t *lcd_conf)

Initialize screen.

Return

  • ESP_OK on success

  • ESP_FAIL Driver not installed

Parameters

esp_err_t (*deinit)(void)

Deinitialize screen.

Return

  • ESP_OK on success

  • ESP_FAIL Deinitialize failed

  • ESP_ERR_NOT_SUPPORTED unsupported

esp_err_t (*set_direction)(scr_dir_t dir)

Set screen direction of rotation.

Note

Not all screens support eight directions, it depends on the screen controller.

Return

  • ESP_OK on success

  • ESP_FAIL Failed

Parameters
  • dir: Pointer to a scr_dir_t structure. You can set the direction in two ways, for example, set it to “SCR_DIR_LRBT” or “SCR_MIRROR_Y”, They are the same, depending on which expression you want to use

esp_err_t (*set_window)(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1)

Set screen window.

Note

When the BPP of the screen controller is less than 8, the coordinate value is limited to a multiple of some number

Return

  • ESP_OK on success

  • ESP_FAIL Failed

Parameters
  • x0: Starting point in X direction

  • y0: Starting point in Y direction

  • x1: End point in X direction

  • y1: End point in Y direction

esp_err_t (*write_ram_data)(uint16_t color)

Write a RAM data.

Return

  • ESP_OK on success

  • ESP_FAIL Failed

Parameters
  • color: New color of a pixel

esp_err_t (*draw_pixel)(uint16_t x, uint16_t y, uint16_t color)

Draw one pixel in screen with color.

Return

  • ESP_OK on success

  • ESP_FAIL Failed

Parameters
  • x: X co-ordinate of set orientation

  • y: Y co-ordinate of set orientation

  • color: New color of the pixel

esp_err_t (*draw_bitmap)(uint16_t x, uint16_t y, uint16_t w, uint16_t h, uint16_t *bitmap)

Fill the pixels on LCD screen with bitmap.

Return

  • ESP_OK on success

  • ESP_FAIL Failed

Parameters
  • x: Starting point in X direction

  • y: Starting point in Y direction

  • w: width of image in bitmap array

  • h: height of image in bitmap array

  • bitmap: pointer to bitmap array

esp_err_t (*get_info)(scr_info_t *info)

Get screen information.

Return

  • ESP_OK on success

  • ESP_FAIL Failed

Parameters

Macros

COLOR_BLACK
COLOR_NAVY
COLOR_DARKGREEN
COLOR_DARKCYAN
COLOR_MAROON
COLOR_PURPLE
COLOR_OLIVE
COLOR_LIGHTGREY
COLOR_DARKGREY
COLOR_BLUE
COLOR_GREEN
COLOR_CYAN
COLOR_RED
COLOR_MAGENTA
COLOR_YELLOW
COLOR_WHITE
COLOR_ORANGE
COLOR_GREENYELLOW
COLOR_PINK
COLOR_SILVER
COLOR_GRAY
COLOR_LIME
COLOR_TEAL
COLOR_FUCHSIA
COLOR_ESP_BKGD

Enumerations

enum scr_dir_t

Define all screen direction.

Values:

SCR_DIR_LRTB

From left to right then from top to bottom, this consider as the original direction of the screen

SCR_DIR_LRBT

From left to right then from bottom to top

SCR_DIR_RLTB

From right to left then from top to bottom

SCR_DIR_RLBT

From right to left then from bottom to top

SCR_DIR_TBLR

From top to bottom then from left to right

SCR_DIR_BTLR

From bottom to top then from left to right

SCR_DIR_TBRL

From top to bottom then from right to left

SCR_DIR_BTRL

From bottom to top then from right to left

SCR_DIR_MAX
SCR_MIRROR_X = 0x40

Mirror X-axis

SCR_MIRROR_Y = 0x20

Mirror Y-axis

SCR_SWAP_XY = 0x80

Swap XY axis

enum scr_color_type_t

The types of colors that can be displayed on the screen.

Values:

SCR_COLOR_TYPE_MONO

The screen is monochrome

SCR_COLOR_TYPE_GRAY

The screen is gray

SCR_COLOR_TYPE_RGB565

The screen is colorful

enum scr_controller_t

All supported screen controllers.

Values:

SCREEN_CONTROLLER_ILI9341
SCREEN_CONTROLLER_ILI9342
SCREEN_CONTROLLER_ILI9806
SCREEN_CONTROLLER_ILI9486
SCREEN_CONTROLLER_ILI9488
SCREEN_CONTROLLER_NT35510
SCREEN_CONTROLLER_RM68120
SCREEN_CONTROLLER_ST7789
SCREEN_CONTROLLER_ST7796
SCREEN_CONTROLLER_SSD1351
SCREEN_CONTROLLER_SSD1963
SCREEN_CONTROLLER_SSD1306
SCREEN_CONTROLLER_SSD1307
SCREEN_CONTROLLER_SSD1322

Header File

Functions

esp_err_t scr_interface_create(scr_interface_type_t type, void *config, scr_interface_driver_t **out_driver)

Create screen interface driver.

Return

  • ESP_OK on success

  • ESP_ERR_INVALID_ARG Arguments is NULL.

  • ESP_FAIL Initialize failed

  • ESP_ERR_NO_MEM: Cannot allocate memory.

Parameters
  • type: Type of screen interface

  • config: configuration of interface driver

  • out_driver: Pointer to a screen interface driver

esp_err_t scr_interface_delete(const scr_interface_driver_t *driver)

Delete screen interface driver.

Return

  • ESP_OK on success

  • ESP_ERR_INVALID_ARG Arguments is NULL.

Parameters
  • driver: screen interface driver to delete

Structures

struct scr_interface_spi_config_t

SPI interface configuration.

Public Members

spi_bus_handle_t spi_bus

Handle of spi bus

int8_t pin_num_cs

SPI Chip Select Pin

int8_t pin_num_dc

Pin to select Data or Command for LCD

int clk_freq

SPI clock frequency

bool swap_data

Whether to swap data

struct scr_interface_i2c_config_t

I2C interface configuration.

Public Members

i2c_bus_handle_t i2c_bus

Handle of i2c bus

uint32_t clk_speed

I2C clock frequency for master mode, (no higher than 1MHz for now)

uint16_t slave_addr

I2C slave address

struct scr_interface_driver_t

Define common function for screen interface driver.

Public Members

scr_interface_type_t type

Interface bus type, see scr_interface_type_t struct

esp_err_t (*write_command)(void *handle, const uint8_t *cmd, uint32_t length)

Function to write command

esp_err_t (*write_data)(void *handle, uint16_t data)

Function to write a data

esp_err_t (*write)(void *handle, const uint8_t *data, uint32_t length)

Function to write a block data

esp_err_t (*read)(void *handle, uint8_t *data, uint32_t length)

Function to read a block data

esp_err_t (*bus_acquire)(void *handle)

Function to acquire interface bus

esp_err_t (*bus_release)(void *handle)

Function to release interface bus

Enumerations

enum scr_interface_type_t

Type of screen interface.

Values:

SCREEN_IFACE_I2C

I2C interface

SCREEN_IFACE_8080

8080 parallel interface

SCREEN_IFACE_SPI

SPI interface