Display Drivers

ESPP contains a few different display drivers in the display_drivers component, corresponding to common display drivers on espressif development boards.

API Reference

Header File

Classes

class Gc9a01

Display driver for the GC9A01 display controller.

This code is modified from https://github.com/lvgl/lvgl_esp32_drivers/blob/master/lvgl_tft/GC9A01.c

See also: https://github.com/espressif/esp-bsp/blob/master/components/lcd/esp_lcd_gc9a01/esp_lcd_gc9a01.c

SmartKnob Config

  static constexpr std::string_view dev_kit = "Smartknob-HA";
  int clock_speed = 80 * 1000 * 1000;
  gpio_num_t mosi = GPIO_NUM_6;
  gpio_num_t sclk = GPIO_NUM_5;
  gpio_num_t spics = GPIO_NUM_15;
  gpio_num_t reset = GPIO_NUM_4;
  gpio_num_t dc_pin = (gpio_num_t)DC_PIN_NUM;
  gpio_num_t backlight = GPIO_NUM_7;
  size_t width = 240;
  size_t height = 240;
  size_t pixel_buffer_size = width * 50;
  bool backlight_on_value = true;
  bool reset_value = false;
  bool invert_colors = true;
  int offset_x = 0;
  int offset_y = 0;
  bool mirror_x = true;
  bool mirror_y = true;
  auto rotation = espp::DisplayRotation::LANDSCAPE;

Gc9a01 Example

    // create the spi host
    spi_bus_config_t buscfg;
    memset(&buscfg, 0, sizeof(buscfg));
    buscfg.mosi_io_num = mosi;
#ifdef CONFIG_DISPLAY_QUAD_SPI
    buscfg.miso_io_num = miso;
    buscfg.data2_io_num = data2;
    buscfg.data3_io_num = data3;
#else
    buscfg.miso_io_num = -1;
    buscfg.quadwp_io_num = -1;
    buscfg.quadhd_io_num = -1;
#endif
    buscfg.sclk_io_num = sclk;
    buscfg.max_transfer_sz = (int)(pixel_buffer_size * sizeof(lv_color_t));
    // create the spi device
    spi_device_interface_config_t devcfg;
    memset(&devcfg, 0, sizeof(devcfg));
    devcfg.mode = 0;
    devcfg.clock_speed_hz = clock_speed;
    devcfg.input_delay_ns = 0;
    devcfg.spics_io_num = spics;
    devcfg.queue_size = spi_queue_size;
#ifdef CONFIG_DISPLAY_QUAD_SPI
    devcfg.flags = SPI_DEVICE_HALFDUPLEX;
    devcfg.command_bits = 8;
    devcfg.address_bits = 24;
#endif
#ifndef CONFIG_T_ENCODER_PRO
    devcfg.pre_cb = lcd_spi_pre_transfer_callback;
#endif
    devcfg.post_cb = lcd_spi_post_transfer_callback;
    esp_err_t ret;
    // Initialize the SPI bus
    ret = spi_bus_initialize(spi_num, &buscfg, SPI_DMA_CH_AUTO);
    ESP_ERROR_CHECK(ret);
    // Attach the LCD to the SPI bus
    ret = spi_bus_add_device(spi_num, &devcfg, &spi);
    ESP_ERROR_CHECK(ret);

    // initialize the controller
    DisplayDriver::initialize(espp::display_drivers::Config{
        .write_command = write_command,
        .lcd_send_lines = lcd_send_lines,
        .reset_pin = reset,
#ifndef CONFIG_T_ENCODER_PRO
        .data_command_pin = dc_pin,
#endif
        .reset_value = reset_value,
        .invert_colors = invert_colors,
        .offset_x = offset_x,
        .offset_y = offset_y,
        .mirror_x = mirror_x,
        .mirror_y = mirror_y,
    });
    // initialize the display / lvgl
    auto display = std::make_shared<Display>(
        Display::LvglConfig{.width = width,
                            .height = height,
                            .flush_callback = DisplayDriver::flush,
                            .rotation_callback = DisplayDriver::rotate,
                            .rotation = rotation},
#if DISPLAY_IS_OLED
        Display::OledConfig{.set_brightness_callback = DisplayDriver::set_brightness,
                            .get_brightness_callback = DisplayDriver::get_brightness},
#else
        Display::LcdConfig{.backlight_pin = backlight, .backlight_on_value = backlight_on_value},
#endif
        Display::DynamicMemoryConfig{.pixel_buffer_size = pixel_buffer_size,
                                     .double_buffered = true});

    display->set_brightness(1.0f);

    // initialize the gui
    Gui gui({});
    size_t iterations = 0;
    while (true) {
      auto label = fmt::format("Iterations: {}", iterations);
      gui.set_label(label);
      gui.set_meter(iterations % 100);
      iterations++;
      std::this_thread::sleep_for(100ms);
    }

Public Static Functions

static inline void initialize(const display_drivers::Config &config)

Store the config data and send the initialization commands to the display controller.

Parameters:

config – display_drivers::Config structure

static inline void rotate(const DisplayRotation &rotation)

Set the display rotation.

Parameters:

rotation – New display rotation.

static inline void flush(lv_display_t *disp, const lv_area_t *area, uint8_t *color_map)

Flush the pixel data for the provided area to the display.

Parameters:
  • *disp – Pointer to the LVGL display.

  • *area – Pointer to the structure describing the pixel area.

  • *color_map – Pointer to array of colors to flush to the display.

static inline void set_drawing_area(const lv_area_t *area)

Set the drawing area for the display, resets the cursor to the starting position of the area.

Parameters:

*area – Pointer to lv_area_t strcuture with start/end x/y coordinates.

static inline void set_drawing_area(size_t xs, size_t ys, size_t xe, size_t ye)

Set the drawing area for the display, resets the cursor to the starting position of the area.

Parameters:
  • xs – Starting x coordinate of the area.

  • ys – Starting y coordinate of the area.

  • xe – Ending x coordinate of the area.

  • ye – Ending y coordinate of the area.

static inline void fill(lv_display_t *disp, const lv_area_t *area, uint8_t *color_map, uint32_t flags = 0)

Fill the display area with the provided color map.

Parameters:
  • *disp – Pointer to the LVGL display.

  • *area – Pointer to the structure describing the pixel area.

  • *color_map – Pointer to array of colors to fill the display with.

  • flags – uint32_t user data / flags to pass to the lcd_write transfer function.

static inline void clear(size_t x, size_t y, size_t width, size_t height, uint16_t color = 0x0000)

Clear the display area, filling it with the provided color.

Parameters:
  • x – X coordinate of the upper left corner of the display area.

  • y – Y coordinate of the upper left corner of the display area.

  • width – Width of the display area to clear.

  • height – Height of the display area to clear.

  • color – 16 bit color (default 0x0000) to fill with.

static inline void send_commands(std::span<const display_drivers::DisplayInitCmd<>> commands)

Send the provided commands to the display controller.

Parameters:

commands – Array of display_drivers::LcdInitCmd structures.

static inline void set_offset(int x, int y)

Set the offset (upper left starting coordinate) of the display.

Note

This modifies internal variables that are used when sending coordinates / filling parts of the display.

Parameters:
  • x – New starting x coordinate (so writing to x address 0 later will actually write to this offset).

  • y – New starting y coordinate (so writing to y address 0 later will actually write to this offset).

static inline void get_offset(int &x, int &y)

Get the offset (upper left starting coordinate) of the display.

Note

This returns internal variables that are used when sending coordinates / filling parts of the display.

Parameters:
  • x – Reference variable that will be filled with the currently configured starting x coordinate that was provided in the config or set by set_offset().

  • y – Reference variable that will be filled with the currently configured starting y coordinate that was provided in the config or set by set_offset().

static inline void get_offset_rotated(int &x, int &y)

Get the offset (upper left starting coordinate) of the display after rotation.

Note

This returns internal variables that are used when sending coordinates / filling parts of the display.

Parameters:
  • x – Reference variable that will be filled with the currently configured starting x coordinate that was provided in the config or set by set_offset(), updated for the current rotation.

  • y – Reference variable that will be filled with the currently configured starting y coordinate that was provided in the config or set by set_offset(), updated for the current rotation.

Header File

Classes

class Ili9341

Display driver for the ILI9341 display controller.

This code is modified from https://github.com/lvgl/lvgl_esp32_drivers/blob/master/lvgl_tft/ili9341.c and https://github.com/espressif/esp-dev-kits/blob/master/esp32-s2-hmi-devkit-1/components/screen/controller_driver/ili9341/ili9341.c

See also: https://github.com/espressif/esp-bsp/blob/master/components/lcd/esp_lcd_ili9341/esp_lcd_ili9341.c

WROVER-KIT ILI9341 Config

  static constexpr std::string_view dev_kit = "ESP-WROVER-DevKit";
  int clock_speed = 20 * 1000 * 1000;
  gpio_num_t mosi = GPIO_NUM_23;
  gpio_num_t sclk = GPIO_NUM_19;
  gpio_num_t spics = GPIO_NUM_22;
  gpio_num_t reset = GPIO_NUM_18;
  gpio_num_t dc_pin = (gpio_num_t)DC_PIN_NUM;
  gpio_num_t backlight = GPIO_NUM_5;
  size_t width = 320;
  size_t height = 240;
  size_t pixel_buffer_size = 16384;
  bool backlight_on_value = false;
  bool reset_value = false;
  bool invert_colors = false;
  int offset_x = 0;
  int offset_y = 0;
  bool mirror_x = false;
  bool mirror_y = false;
  auto rotation = espp::DisplayRotation::LANDSCAPE;

ili9341 Example

    // create the spi host
    spi_bus_config_t buscfg;
    memset(&buscfg, 0, sizeof(buscfg));
    buscfg.mosi_io_num = mosi;
#ifdef CONFIG_DISPLAY_QUAD_SPI
    buscfg.miso_io_num = miso;
    buscfg.data2_io_num = data2;
    buscfg.data3_io_num = data3;
#else
    buscfg.miso_io_num = -1;
    buscfg.quadwp_io_num = -1;
    buscfg.quadhd_io_num = -1;
#endif
    buscfg.sclk_io_num = sclk;
    buscfg.max_transfer_sz = (int)(pixel_buffer_size * sizeof(lv_color_t));
    // create the spi device
    spi_device_interface_config_t devcfg;
    memset(&devcfg, 0, sizeof(devcfg));
    devcfg.mode = 0;
    devcfg.clock_speed_hz = clock_speed;
    devcfg.input_delay_ns = 0;
    devcfg.spics_io_num = spics;
    devcfg.queue_size = spi_queue_size;
#ifdef CONFIG_DISPLAY_QUAD_SPI
    devcfg.flags = SPI_DEVICE_HALFDUPLEX;
    devcfg.command_bits = 8;
    devcfg.address_bits = 24;
#endif
#ifndef CONFIG_T_ENCODER_PRO
    devcfg.pre_cb = lcd_spi_pre_transfer_callback;
#endif
    devcfg.post_cb = lcd_spi_post_transfer_callback;
    esp_err_t ret;
    // Initialize the SPI bus
    ret = spi_bus_initialize(spi_num, &buscfg, SPI_DMA_CH_AUTO);
    ESP_ERROR_CHECK(ret);
    // Attach the LCD to the SPI bus
    ret = spi_bus_add_device(spi_num, &devcfg, &spi);
    ESP_ERROR_CHECK(ret);

    // initialize the controller
    DisplayDriver::initialize(espp::display_drivers::Config{
        .write_command = write_command,
        .lcd_send_lines = lcd_send_lines,
        .reset_pin = reset,
#ifndef CONFIG_T_ENCODER_PRO
        .data_command_pin = dc_pin,
#endif
        .reset_value = reset_value,
        .invert_colors = invert_colors,
        .offset_x = offset_x,
        .offset_y = offset_y,
        .mirror_x = mirror_x,
        .mirror_y = mirror_y,
    });
    // initialize the display / lvgl
    auto display = std::make_shared<Display>(
        Display::LvglConfig{.width = width,
                            .height = height,
                            .flush_callback = DisplayDriver::flush,
                            .rotation_callback = DisplayDriver::rotate,
                            .rotation = rotation},
#if DISPLAY_IS_OLED
        Display::OledConfig{.set_brightness_callback = DisplayDriver::set_brightness,
                            .get_brightness_callback = DisplayDriver::get_brightness},
#else
        Display::LcdConfig{.backlight_pin = backlight, .backlight_on_value = backlight_on_value},
#endif
        Display::DynamicMemoryConfig{.pixel_buffer_size = pixel_buffer_size,
                                     .double_buffered = true});

    display->set_brightness(1.0f);

    // initialize the gui
    Gui gui({});
    size_t iterations = 0;
    while (true) {
      auto label = fmt::format("Iterations: {}", iterations);
      gui.set_label(label);
      gui.set_meter(iterations % 100);
      iterations++;
      std::this_thread::sleep_for(100ms);
    }

Public Static Functions

static inline void initialize(const display_drivers::Config &config)

Store the config data and send the initialization commands to the display controller.

Parameters:

config – display_drivers::Config structure

static inline void rotate(const DisplayRotation &rotation)

Set the display rotation.

Parameters:

rotation – New display rotation.

static inline void flush(lv_display_t *disp, const lv_area_t *area, uint8_t *color_map)

Flush the pixel data for the provided area to the display.

Parameters:
  • *disp – Pointer to the LVGL display.

  • *area – Pointer to the structure describing the pixel area.

  • *color_map – Pointer to array of colors to flush to the display.

static inline void set_drawing_area(const lv_area_t *area)

Set the drawing area for the display, resets the cursor to the starting position of the area.

Parameters:

*area – Pointer to lv_area_t strcuture with start/end x/y coordinates.

static inline void set_drawing_area(size_t xs, size_t ys, size_t xe, size_t ye)

Set the drawing area for the display, resets the cursor to the starting position of the area.

Parameters:
  • xs – Starting x coordinate of the area.

  • ys – Starting y coordinate of the area.

  • xe – Ending x coordinate of the area.

  • ye – Ending y coordinate of the area.

static inline void fill(lv_display_t *disp, const lv_area_t *area, uint8_t *color_map, uint32_t flags = 0)

Fill the display area with the provided color map.

Parameters:
  • *disp – Pointer to the LVGL display.

  • *area – Pointer to the structure describing the pixel area.

  • *color_map – Pointer to array of colors to flush to the display.

  • flags – uint32_t user data / flags to pass to the lcd_write transfer function.

static inline void clear(size_t x, size_t y, size_t width, size_t height, uint16_t color = 0x0000)

Clear the display area, filling it with the provided color.

Parameters:
  • x – X coordinate of the upper left corner of the display area.

  • y – Y coordinate of the upper left corner of the display area.

  • width – Width of the display area to clear.

  • height – Height of the display area to clear.

  • color – 16 bit color (default 0x0000) to fill with.

static inline void send_commands(std::span<const display_drivers::DisplayInitCmd<>> commands)

Send the provided commands to the display controller.

Parameters:

commands – Array of display_drivers::LcdInitCmd structures.

static inline void set_offset(int x, int y)

Set the offset (upper left starting coordinate) of the display.

Note

This modifies internal variables that are used when sending coordinates / filling parts of the display.

Parameters:
  • x – New starting x coordinate (so writing to x address 0 later will actually write to this offset).

  • y – New starting y coordinate (so writing to y address 0 later will actually write to this offset).

static inline void get_offset(int &x, int &y)

Get the offset (upper left starting coordinate) of the display.

Note

This returns internal variables that are used when sending coordinates / filling parts of the display.

Parameters:
  • x – Reference variable that will be filled with the currently configured starting x coordinate that was provided in the config or set by set_offset().

  • y – Reference variable that will be filled with the currently configured starting y coordinate that was provided in the config or set by set_offset().

static inline void get_offset_rotated(int &x, int &y)

Get the offset (upper left starting coordinate) of the display after rotation.

Note

This returns internal variables that are used when sending coordinates / filling parts of the display.

Parameters:
  • x – Reference variable that will be filled with the currently configured starting x coordinate that was provided in the config or set by set_offset(), updated for the current rotation.

  • y – Reference variable that will be filled with the currently configured starting y coordinate that was provided in the config or set by set_offset(), updated for the current rotation.

Header File

Classes

class Ssd1351

Display driver for the SSD1351 128x128 RGB OLED display controller.

This code is modified from https://github.com/adafruit/Adafruit-SSD1351-library/blob/master/Adafruit_SSD1351.cpp and https://github.com/lvgl/lvgl_esp32_drivers/blob/master/lvgl_tft/ssd1306.c and https://github.com/rdagger/micropython-ssd1351/blob/master/ssd1351.py and https://github.com/Bodmer/TFT_eSPI/blob/master/TFT_Drivers/SSD1351_Defines.h

Datasheet can be found here: https://cdn-shop.adafruit.com/datasheets/SSD1351-Revision+1.3.pdf

Byte90 Ssd1351 Config

  static constexpr std::string_view dev_kit = "ALXV Labs Byte90";
  int clock_speed = 20 * 1000 * 1000;
  constexpr gpio_num_t mosi = GPIO_NUM_9;
  constexpr gpio_num_t miso = GPIO_NUM_NC;
  constexpr gpio_num_t sclk = GPIO_NUM_7;
  constexpr gpio_num_t spics = GPIO_NUM_44;
  constexpr gpio_num_t reset = GPIO_NUM_1;
  constexpr gpio_num_t dc_pin = (gpio_num_t)DC_PIN_NUM;
  constexpr size_t width = 128;
  constexpr size_t height = 128;
  constexpr size_t pixel_buffer_size = width * height * sizeof(uint16_t);

  bool reset_value = false;
  bool invert_colors = false;
  int offset_x = 0;
  int offset_y = 0;
  bool mirror_x = false;
  bool mirror_y = true;
  auto rotation = espp::DisplayRotation::LANDSCAPE;

ssd1351 Example

    // create the spi host
    spi_bus_config_t buscfg;
    memset(&buscfg, 0, sizeof(buscfg));
    buscfg.mosi_io_num = mosi;
#ifdef CONFIG_DISPLAY_QUAD_SPI
    buscfg.miso_io_num = miso;
    buscfg.data2_io_num = data2;
    buscfg.data3_io_num = data3;
#else
    buscfg.miso_io_num = -1;
    buscfg.quadwp_io_num = -1;
    buscfg.quadhd_io_num = -1;
#endif
    buscfg.sclk_io_num = sclk;
    buscfg.max_transfer_sz = (int)(pixel_buffer_size * sizeof(lv_color_t));
    // create the spi device
    spi_device_interface_config_t devcfg;
    memset(&devcfg, 0, sizeof(devcfg));
    devcfg.mode = 0;
    devcfg.clock_speed_hz = clock_speed;
    devcfg.input_delay_ns = 0;
    devcfg.spics_io_num = spics;
    devcfg.queue_size = spi_queue_size;
#ifdef CONFIG_DISPLAY_QUAD_SPI
    devcfg.flags = SPI_DEVICE_HALFDUPLEX;
    devcfg.command_bits = 8;
    devcfg.address_bits = 24;
#endif
#ifndef CONFIG_T_ENCODER_PRO
    devcfg.pre_cb = lcd_spi_pre_transfer_callback;
#endif
    devcfg.post_cb = lcd_spi_post_transfer_callback;
    esp_err_t ret;
    // Initialize the SPI bus
    ret = spi_bus_initialize(spi_num, &buscfg, SPI_DMA_CH_AUTO);
    ESP_ERROR_CHECK(ret);
    // Attach the LCD to the SPI bus
    ret = spi_bus_add_device(spi_num, &devcfg, &spi);
    ESP_ERROR_CHECK(ret);

    // initialize the controller
    DisplayDriver::initialize(espp::display_drivers::Config{
        .write_command = write_command,
        .lcd_send_lines = lcd_send_lines,
        .reset_pin = reset,
#ifndef CONFIG_T_ENCODER_PRO
        .data_command_pin = dc_pin,
#endif
        .reset_value = reset_value,
        .invert_colors = invert_colors,
        .offset_x = offset_x,
        .offset_y = offset_y,
        .mirror_x = mirror_x,
        .mirror_y = mirror_y,
    });
    // initialize the display / lvgl
    auto display = std::make_shared<Display>(
        Display::LvglConfig{.width = width,
                            .height = height,
                            .flush_callback = DisplayDriver::flush,
                            .rotation_callback = DisplayDriver::rotate,
                            .rotation = rotation},
#if DISPLAY_IS_OLED
        Display::OledConfig{.set_brightness_callback = DisplayDriver::set_brightness,
                            .get_brightness_callback = DisplayDriver::get_brightness},
#else
        Display::LcdConfig{.backlight_pin = backlight, .backlight_on_value = backlight_on_value},
#endif
        Display::DynamicMemoryConfig{.pixel_buffer_size = pixel_buffer_size,
                                     .double_buffered = true});

    display->set_brightness(1.0f);

    // initialize the gui
    Gui gui({});
    size_t iterations = 0;
    while (true) {
      auto label = fmt::format("Iterations: {}", iterations);
      gui.set_label(label);
      gui.set_meter(iterations % 100);
      iterations++;
      std::this_thread::sleep_for(100ms);
    }

Public Types

enum class Command : uint8_t

Enum for Command values used by the SSD1351 display controller.

Values:

enumerator caset

Column address set.

enumerator raset

Row address set.

enumerator ramwr

RAM write.

enumerator ramrd

RAM read.

enumerator madctl

Memory data access control.

enumerator STARTLINE

Vertical Scroll by RAM.

enumerator DISPLAYOFFSET

Vertical Scroll by row (locked)

enumerator DISPLAYALLOFF

All pixels off.

enumerator DISPLAYALLON

All pixels on (all pixels have GS63)

enumerator NORMALDISPLAY

Normal display mode.

enumerator INVERTDISPLAY

Inverted display mode.

enumerator FUNCTIONSELECT

See datasheet.

enumerator DISPLAYOFF

Sleep Mode On.

enumerator DISPLAYON

Sleep Mode Off.

enumerator PRECHARGE

See datasheet.

enumerator DISPLAYENHANCE

Not currently used.

enumerator CLOCKDIV

See datasheet.

enumerator SETVSL

See datasheet.

enumerator SETGPIO

See datasheet.

enumerator PRECHARGE2

See datasheet.

enumerator SETGRAY

Not currently used.

enumerator USELUT

Not currently used.

enumerator PRECHARGELEVEL

Not currently used.

enumerator VCOMH

See datasheet.

enumerator CONTRASTABC

See datasheet.

enumerator CONTRASTMASTER

See datasheet.

enumerator MUXRATIO

See datasheet.

enumerator HORIZSCROLL

Not currently used.

enumerator STOPSCROLL

Not currently used.

enumerator STARTSCROLL

Not currently used.

enumerator nop0

No operation (0)

enumerator nop1

No operation (1)

enumerator COMMANDLOCK

Command lock and MCU protection status.

Public Static Functions

static inline void initialize(const display_drivers::Config &config)

Store the config data and send the initialization commands to the display controller.

Parameters:

config – display_drivers::Config structure

static inline void rotate(const DisplayRotation &rotation)

Set the display rotation.

Parameters:

rotation – New display rotation.

static inline void flush(lv_display_t *disp, const lv_area_t *area, uint8_t *color_map)

Flush the pixel data for the provided area to the display.

Parameters:
  • *disp – Pointer to the LVGL display.

  • *area – Pointer to the structure describing the pixel area.

  • *color_map – Pointer to array of colors to flush to the display.

static inline void set_drawing_area(const lv_area_t *area)

Set the drawing area for the display, resets the cursor to the starting position of the area.

Parameters:

*area – Pointer to lv_area_t strcuture with start/end x/y coordinates.

static inline void set_drawing_area(size_t xs, size_t ys, size_t xe, size_t ye)

Set the drawing area for the display, resets the cursor to the starting position of the area.

Parameters:
  • xs – Starting x coordinate of the area.

  • ys – Starting y coordinate of the area.

  • xe – Ending x coordinate of the area.

  • ye – Ending y coordinate of the area.

static inline void fill(lv_display_t *disp, const lv_area_t *area, uint8_t *color_map, uint32_t flags = 0)

Fill the display area with the provided color map.

Parameters:
  • *disp – Pointer to the LVGL display.

  • *area – Pointer to the structure describing the pixel area.

  • *color_map – Pointer to array of colors to flush to the display.

  • flags – uint32_t user data / flags to pass to the lcd_write transfer function.

static inline void clear(size_t x, size_t y, size_t width, size_t height, uint16_t color = 0x0000)

Clear the display area, filling it with the provided color.

Parameters:
  • x – X coordinate of the upper left corner of the display area.

  • y – Y coordinate of the upper left corner of the display area.

  • width – Width of the display area to clear.

  • height – Height of the display area to clear.

  • color – 16 bit color (default 0x0000) to fill with.

static inline void send_commands(std::span<const display_drivers::DisplayInitCmd<>> commands)

Send the provided commands to the display controller.

Parameters:

commands – Array of display_drivers::LcdInitCmd structures.

static inline void set_offset(int x, int y)

Set the offset (upper left starting coordinate) of the display.

Note

This modifies internal variables that are used when sending coordinates / filling parts of the display.

Parameters:
  • x – New starting x coordinate (so writing to x address 0 later will actually write to this offset).

  • y – New starting y coordinate (so writing to y address 0 later will actually write to this offset).

static inline void get_offset(int &x, int &y)

Get the offset (upper left starting coordinate) of the display.

Note

This returns internal variables that are used when sending coordinates / filling parts of the display.

Parameters:
  • x – Reference variable that will be filled with the currently configured starting x coordinate that was provided in the config or set by set_offset().

  • y – Reference variable that will be filled with the currently configured starting y coordinate that was provided in the config or set by set_offset().

static inline void get_offset_rotated(int &x, int &y)

Get the offset (upper left starting coordinate) of the display after rotation.

Note

This returns internal variables that are used when sending coordinates / filling parts of the display.

Parameters:
  • x – Reference variable that will be filled with the currently configured starting x coordinate that was provided in the config or set by set_offset(), updated for the current rotation.

  • y – Reference variable that will be filled with the currently configured starting y coordinate that was provided in the config or set by set_offset(), updated for the current rotation.

static inline void set_brightness(const float brightness)

Set the display brightness.

Parameters:

brightness – Brightness value in range [0.0, 1.0].

static inline float get_brightness()

Get the current display brightness.

Returns:

Current brightness value in range [0.0, 1.0].

Public Static Attributes

static constexpr int DEFAULT_MADCTL = OLED_CMD_COLOR_DEPTH_65K2 | OLED_CMD_COM_SPLIT

Default MADCTL value.

Header File

Classes

class St7789

Display driver for the ST7789 display controller.

This code is modified from https://github.com/lvgl/lvgl_esp32_drivers/blob/master/lvgl_tft/st7789.c and https://github.com/Bodmer/TFT_eSPI/blob/master/TFT_Drivers/ST7789_Defines.h

See also: https://github.com/espressif/esp-who/blob/master/components/screen/controller_driver/st7789/st7789.c or https://github.com/espressif/tflite-micro-esp-examples/blob/master/components/screen/controller_driver/st7789/st7789.c or https://esphome.io/api/st7789v_8h_source.html or https://github.com/mireq/esp32-st7789-demo/blob/master/components/st7789/include/st7789.h or https://github.com/mireq/esp32-st7789-demo/blob/master/components/st7789/st7789.c

TTGO St7789 Config

  static constexpr std::string_view dev_kit = "TTGO T-Display";
  int clock_speed = 60 * 1000 * 1000;
  gpio_num_t mosi = GPIO_NUM_19;
  gpio_num_t sclk = GPIO_NUM_18;
  gpio_num_t spics = GPIO_NUM_5;
  gpio_num_t reset = GPIO_NUM_23;
  gpio_num_t dc_pin = (gpio_num_t)DC_PIN_NUM;
  gpio_num_t backlight = GPIO_NUM_4;
  size_t width = 240;
  size_t height = 135;
  size_t pixel_buffer_size = 12800;
  bool backlight_on_value = false;
  bool reset_value = false;
  bool invert_colors = false;
  int offset_x = 40;
  int offset_y = 53;
  bool mirror_x = false;
  bool mirror_y = false;
  auto rotation = espp::DisplayRotation::PORTRAIT;

ESP32-S3-BOX St7789 Config

  static constexpr std::string_view dev_kit = "ESP32-S3-BOX";
  int clock_speed = 60 * 1000 * 1000;
  gpio_num_t mosi = GPIO_NUM_6;
  gpio_num_t sclk = GPIO_NUM_7;
  gpio_num_t spics = GPIO_NUM_5;
  gpio_num_t reset = GPIO_NUM_48;
  gpio_num_t dc_pin = (gpio_num_t)DC_PIN_NUM;
  gpio_num_t backlight = GPIO_NUM_45;
  size_t width = 320;
  size_t height = 240;
  size_t pixel_buffer_size = width * 50;
  bool backlight_on_value = true;
  bool reset_value = false;
  bool invert_colors = true;
  int offset_x = 0;
  int offset_y = 0;
  bool mirror_x = true;
  bool mirror_y = true;
  auto rotation = espp::DisplayRotation::LANDSCAPE;

st7789 Example

    // create the spi host
    spi_bus_config_t buscfg;
    memset(&buscfg, 0, sizeof(buscfg));
    buscfg.mosi_io_num = mosi;
#ifdef CONFIG_DISPLAY_QUAD_SPI
    buscfg.miso_io_num = miso;
    buscfg.data2_io_num = data2;
    buscfg.data3_io_num = data3;
#else
    buscfg.miso_io_num = -1;
    buscfg.quadwp_io_num = -1;
    buscfg.quadhd_io_num = -1;
#endif
    buscfg.sclk_io_num = sclk;
    buscfg.max_transfer_sz = (int)(pixel_buffer_size * sizeof(lv_color_t));
    // create the spi device
    spi_device_interface_config_t devcfg;
    memset(&devcfg, 0, sizeof(devcfg));
    devcfg.mode = 0;
    devcfg.clock_speed_hz = clock_speed;
    devcfg.input_delay_ns = 0;
    devcfg.spics_io_num = spics;
    devcfg.queue_size = spi_queue_size;
#ifdef CONFIG_DISPLAY_QUAD_SPI
    devcfg.flags = SPI_DEVICE_HALFDUPLEX;
    devcfg.command_bits = 8;
    devcfg.address_bits = 24;
#endif
#ifndef CONFIG_T_ENCODER_PRO
    devcfg.pre_cb = lcd_spi_pre_transfer_callback;
#endif
    devcfg.post_cb = lcd_spi_post_transfer_callback;
    esp_err_t ret;
    // Initialize the SPI bus
    ret = spi_bus_initialize(spi_num, &buscfg, SPI_DMA_CH_AUTO);
    ESP_ERROR_CHECK(ret);
    // Attach the LCD to the SPI bus
    ret = spi_bus_add_device(spi_num, &devcfg, &spi);
    ESP_ERROR_CHECK(ret);

    // initialize the controller
    DisplayDriver::initialize(espp::display_drivers::Config{
        .write_command = write_command,
        .lcd_send_lines = lcd_send_lines,
        .reset_pin = reset,
#ifndef CONFIG_T_ENCODER_PRO
        .data_command_pin = dc_pin,
#endif
        .reset_value = reset_value,
        .invert_colors = invert_colors,
        .offset_x = offset_x,
        .offset_y = offset_y,
        .mirror_x = mirror_x,
        .mirror_y = mirror_y,
    });
    // initialize the display / lvgl
    auto display = std::make_shared<Display>(
        Display::LvglConfig{.width = width,
                            .height = height,
                            .flush_callback = DisplayDriver::flush,
                            .rotation_callback = DisplayDriver::rotate,
                            .rotation = rotation},
#if DISPLAY_IS_OLED
        Display::OledConfig{.set_brightness_callback = DisplayDriver::set_brightness,
                            .get_brightness_callback = DisplayDriver::get_brightness},
#else
        Display::LcdConfig{.backlight_pin = backlight, .backlight_on_value = backlight_on_value},
#endif
        Display::DynamicMemoryConfig{.pixel_buffer_size = pixel_buffer_size,
                                     .double_buffered = true});

    display->set_brightness(1.0f);

    // initialize the gui
    Gui gui({});
    size_t iterations = 0;
    while (true) {
      auto label = fmt::format("Iterations: {}", iterations);
      gui.set_label(label);
      gui.set_meter(iterations % 100);
      iterations++;
      std::this_thread::sleep_for(100ms);
    }

Public Static Functions

static inline void initialize(const display_drivers::Config &config)

Store the config data and send the initialization commands to the display controller.

Parameters:

config – display_drivers::Config structure

static inline void rotate(const DisplayRotation &rotation)

Set the display rotation.

Parameters:

rotation – New display rotation.

static inline void flush(lv_display_t *disp, const lv_area_t *area, uint8_t *color_map)

Flush the pixel data for the provided area to the display.

Parameters:
  • *disp – Pointer to the LVGL display.

  • *area – Pointer to the structure describing the pixel area.

  • *color_map – Pointer to array of colors to flush to the display.

static inline void set_drawing_area(const lv_area_t *area)

Set the drawing area for the display, resets the cursor to the starting position of the area.

Parameters:

*area – Pointer to lv_area_t strcuture with start/end x/y coordinates.

static inline void set_drawing_area(size_t xs, size_t ys, size_t xe, size_t ye)

Set the drawing area for the display, resets the cursor to the starting position of the area.

Parameters:
  • xs – Starting x coordinate of the area.

  • ys – Starting y coordinate of the area.

  • xe – Ending x coordinate of the area.

  • ye – Ending y coordinate of the area.

static inline void fill(lv_display_t *disp, const lv_area_t *area, uint8_t *color_map, uint32_t flags = 0)

Fill the display area with the provided color map.

Parameters:
  • *disp – Pointer to the LVGL display.

  • *area – Pointer to the structure describing the pixel area.

  • *color_map – Pointer to array of colors to flush to the display.

  • flags – uint32_t user data / flags to pass to the lcd_write transfer function.

static inline void clear(size_t x, size_t y, size_t width, size_t height, uint16_t color = 0x0000)

Clear the display area, filling it with the provided color.

Parameters:
  • x – X coordinate of the upper left corner of the display area.

  • y – Y coordinate of the upper left corner of the display area.

  • width – Width of the display area to clear.

  • height – Height of the display area to clear.

  • color – 16 bit color (default 0x0000) to fill with.

static inline void send_commands(std::span<const display_drivers::DisplayInitCmd<>> commands)

Send the provided commands to the display controller.

Parameters:

commands – Array of display_drivers::LcdInitCmd structures.

static inline void set_offset(int x, int y)

Set the offset (upper left starting coordinate) of the display.

Note

This modifies internal variables that are used when sending coordinates / filling parts of the display.

Parameters:
  • x – New starting x coordinate (so writing to x address 0 later will actually write to this offset).

  • y – New starting y coordinate (so writing to y address 0 later will actually write to this offset).

static inline void get_offset(int &x, int &y)

Get the offset (upper left starting coordinate) of the display.

Note

This returns internal variables that are used when sending coordinates / filling parts of the display.

Parameters:
  • x – Reference variable that will be filled with the currently configured starting x coordinate that was provided in the config or set by set_offset().

  • y – Reference variable that will be filled with the currently configured starting y coordinate that was provided in the config or set by set_offset().

static inline void get_offset_rotated(int &x, int &y)

Get the offset (upper left starting coordinate) of the display after rotation.

Note

This returns internal variables that are used when sending coordinates / filling parts of the display.

Parameters:
  • x – Reference variable that will be filled with the currently configured starting x coordinate that was provided in the config or set by set_offset(), updated for the current rotation.

  • y – Reference variable that will be filled with the currently configured starting y coordinate that was provided in the config or set by set_offset(), updated for the current rotation.

Header File

Classes

class Sh8601

Display driver for the SH8601 display controller.

This code is based off this datasheet: https://dl.espressif.com/AE/esp-iot-solution/SH8601A0_DataSheet_Preliminary_V0.0_UCS__191107_1_.pdf

SmartKnob Config

  static constexpr std::string_view dev_kit = "Lilygo T-Encoder-Pro";
  int clock_speed = 80 * 1000 * 1000;
  constexpr gpio_num_t mosi = GPIO_NUM_11;
  constexpr gpio_num_t miso = GPIO_NUM_13;
  constexpr gpio_num_t data2 = GPIO_NUM_7;
  constexpr gpio_num_t data3 = GPIO_NUM_14;
  constexpr gpio_num_t sclk = GPIO_NUM_12;
  constexpr gpio_num_t spics = GPIO_NUM_10;
  constexpr gpio_num_t reset = GPIO_NUM_4;
  constexpr gpio_num_t enable = GPIO_NUM_3;
  constexpr size_t width = 390;
  constexpr size_t height = 390;
  constexpr size_t pixel_buffer_size = width * height / 10;

  bool reset_value = false;
  bool invert_colors = false;
  int offset_x = 0;
  int offset_y = 0;
  bool mirror_x = false;
  bool mirror_y = false;
  auto rotation = espp::DisplayRotation::LANDSCAPE;

Sh8601 Example

    // create the spi host
    spi_bus_config_t buscfg;
    memset(&buscfg, 0, sizeof(buscfg));
    buscfg.mosi_io_num = mosi;
#ifdef CONFIG_DISPLAY_QUAD_SPI
    buscfg.miso_io_num = miso;
    buscfg.data2_io_num = data2;
    buscfg.data3_io_num = data3;
#else
    buscfg.miso_io_num = -1;
    buscfg.quadwp_io_num = -1;
    buscfg.quadhd_io_num = -1;
#endif
    buscfg.sclk_io_num = sclk;
    buscfg.max_transfer_sz = (int)(pixel_buffer_size * sizeof(lv_color_t));
    // create the spi device
    spi_device_interface_config_t devcfg;
    memset(&devcfg, 0, sizeof(devcfg));
    devcfg.mode = 0;
    devcfg.clock_speed_hz = clock_speed;
    devcfg.input_delay_ns = 0;
    devcfg.spics_io_num = spics;
    devcfg.queue_size = spi_queue_size;
#ifdef CONFIG_DISPLAY_QUAD_SPI
    devcfg.flags = SPI_DEVICE_HALFDUPLEX;
    devcfg.command_bits = 8;
    devcfg.address_bits = 24;
#endif
#ifndef CONFIG_T_ENCODER_PRO
    devcfg.pre_cb = lcd_spi_pre_transfer_callback;
#endif
    devcfg.post_cb = lcd_spi_post_transfer_callback;
    esp_err_t ret;
    // Initialize the SPI bus
    ret = spi_bus_initialize(spi_num, &buscfg, SPI_DMA_CH_AUTO);
    ESP_ERROR_CHECK(ret);
    // Attach the LCD to the SPI bus
    ret = spi_bus_add_device(spi_num, &devcfg, &spi);
    ESP_ERROR_CHECK(ret);

    // initialize the controller
    DisplayDriver::initialize(espp::display_drivers::Config{
        .write_command = write_command,
        .lcd_send_lines = lcd_send_lines,
        .reset_pin = reset,
#ifndef CONFIG_T_ENCODER_PRO
        .data_command_pin = dc_pin,
#endif
        .reset_value = reset_value,
        .invert_colors = invert_colors,
        .offset_x = offset_x,
        .offset_y = offset_y,
        .mirror_x = mirror_x,
        .mirror_y = mirror_y,
    });
    // initialize the display / lvgl
    auto display = std::make_shared<Display>(
        Display::LvglConfig{.width = width,
                            .height = height,
                            .flush_callback = DisplayDriver::flush,
                            .rotation_callback = DisplayDriver::rotate,
                            .rotation = rotation},
#if DISPLAY_IS_OLED
        Display::OledConfig{.set_brightness_callback = DisplayDriver::set_brightness,
                            .get_brightness_callback = DisplayDriver::get_brightness},
#else
        Display::LcdConfig{.backlight_pin = backlight, .backlight_on_value = backlight_on_value},
#endif
        Display::DynamicMemoryConfig{.pixel_buffer_size = pixel_buffer_size,
                                     .double_buffered = true});

    display->set_brightness(1.0f);

    // initialize the gui
    Gui gui({});
    size_t iterations = 0;
    while (true) {
      auto label = fmt::format("Iterations: {}", iterations);
      gui.set_label(label);
      gui.set_meter(iterations % 100);
      iterations++;
      std::this_thread::sleep_for(100ms);
    }

Public Static Functions

static inline void initialize(const display_drivers::Config &config)

Store the config data and send the initialization commands to the display controller.

Parameters:

config – display_drivers::Config structure

static inline void rotate(const DisplayRotation &rotation)

Set the display rotation.

Parameters:

rotation – New display rotation.

static inline void flush(lv_display_t *disp, const lv_area_t *area, uint8_t *color_map)

Flush the pixel data for the provided area to the display.

Parameters:
  • *disp – Pointer to the LVGL display.

  • *area – Pointer to the structure describing the pixel area.

  • *color_map – Pointer to array of colors to flush to the display.

static inline void set_drawing_area(const lv_area_t *area)

Set the drawing area for the display, resets the cursor to the starting position of the area.

Parameters:

area – Pointer to lv_area_t strcuture with start/end x/y coordinates.

static inline void set_drawing_area(size_t xs, size_t ys, size_t xe, size_t ye)

Set the drawing area for the display, resets the cursor to the starting position of the area.

Parameters:
  • xs – Starting x coordinate of the area.

  • ys – Starting y coordinate of the area.

  • xe – Ending x coordinate of the area.

  • ye – Ending y coordinate of the area.

static inline void set_offset(int x, int y)

Set the offset (upper left starting coordinate) of the display.

Note

This modifies internal variables that are used when sending coordinates / filling parts of the display.

Parameters:
  • x – New starting x coordinate (so writing to x address 0 later will actually write to this offset).

  • y – New starting y coordinate (so writing to y address 0 later will actually write to this offset).

static inline void get_offset(int &x, int &y)

Get the offset (upper left starting coordinate) of the display.

Note

This returns internal variables that are used when sending coordinates / filling parts of the display.

Parameters:
  • x – Reference variable that will be filled with the currently configured starting x coordinate that was provided in the config or set by set_offset().

  • y – Reference variable that will be filled with the currently configured starting y coordinate that was provided in the config or set by set_offset().

static inline void get_offset_rotated(int &x, int &y)

Get the offset (upper left starting coordinate) of the display after rotation.

Note

This returns internal variables that are used when sending coordinates / filling parts of the display.

Parameters:
  • x – Reference variable that will be filled with the currently configured starting x coordinate that was provided in the config or set by set_offset(), updated for the current rotation.

  • y – Reference variable that will be filled with the currently configured starting y coordinate that was provided in the config or set by set_offset(), updated for the current rotation.