> ## Documentation Index
> Fetch the complete documentation index at: https://docs.kode.diy/llms.txt
> Use this file to discover all available pages before exploring further.

# Display

> Learn to program it and create incredible interfaces with LVGL.

# Features

The Kode Dot has the **best screen in a maker device on the market.** It is a **2.13-inch AMOLED touch screen** with the following features:

| Feature      | Description      |
| ------------ | ---------------- |
| Size         | 2.13 inches      |
| Resolution   | 410x502 pixels   |
| Color depth  | 16 bits (RGB565) |
| Driver       | CO5300 - QSPI    |
| Touch driver | CST820 - I2C     |

The screen is completely programmable with **existing Arduino and ESP-IDF libraries** and compatible with **LVGL.**

## Connection diagram

### Screen driver

The screen driver is the **CO5300** and works using the **QuadSPI bus.** This driver is connected to the ESP32-S3 in the following way:

| CO5300      | ESP32-S3 |
| ----------- | -------- |
| Chip Select | GPIO9    |
| Clock       | GPIO17   |
| Data 0      | GPIO15   |
| Data 1      | GPIO14   |
| Data 2      | GPIO16   |
| Data 3      | GPIO10   |
| Reset       | GPIO8    |

<Note>The QuadSPI bus is of the same family as the SPI bus, but has double the bandwidth.</Note>

### Touch driver

The touch driver is the **CST820** and works using the **I2C bus.** This driver is connected to the ESP32-S3 in the following way:

| CST820    | ESP32-S3 |
| --------- | -------- |
| SDA       | GPIO48   |
| SCL       | GPIO47   |
| Interrupt | EXP15    |
| Reset     | GPIO8    |

<Tip>The touch driver has the address 0x15 on the I2C bus.</Tip>

<Note>The interrupt pin is connected to EXP15 of the IO expander. See [IO expander](/en/kode-dot/io-expander) for more information.</Note>

<Warning>The reset pin of the touch driver and the screen driver are connected to the same pin of the ESP32-S3.</Warning>

## Recommended libraries

### Arduino

* [Arduino\_GFX](https://github.com/moononournation/Arduino_GFX)
* [bb\_captouch](https://github.com/bitbank2/bb_captouch)
* [ESP32\_IO\_Expander](https://github.com/esp-arduino-libs/ESP32_IO_Expander)

### ESP-IDF

* [esp\_lcd\_co5300](https://components.espressif.com/components/kodediy/esp_lcd_co5300)
* [esp\_lcd\_touch\_cst820](https://components.espressif.com/components/kodediy/esp_lcd_touch_cst820)
* [esp\_io\_expander\_tca95xx\_16bit](https://components.espressif.com/components/espressif/esp_io_expander_tca95xx_16bit)

## Example code

### Basic example

This is the most basic code to test the screen, only printing a **¡Hola mundo!** on the screen.

```cpp display_test.ino lines icon="microchip" theme={null}
/**
 * Simple display demo with Arduino_GFX: initializes the panel and draws “Hello World!”.
 * Uses ESP32-S3 QSPI bus, 410x502 resolution, and max brightness.
 * Renders large text roughly centered on a blue background.
*/
/* ───────── KODE | docs.kode.diy ───────── */

#include <Arduino_GFX_Library.h>

#define DSP_HOR_RES 410
#define DSP_VER_RES 502
#define DSP_SCLK 17
#define DSP_SDIO0 15
#define DSP_SDIO1 14
#define DSP_SDIO2 16
#define DSP_SDIO3 10
#define DSP_RST 8
#define DSP_CS 9

/* Objects to handle the graphics bus and display */
static Arduino_DataBus *gfxBus;
static Arduino_CO5300 *gfx;

void setup() {
  Serial.begin(115200);
  delay(100);
  Serial.println("Simple Display Demo");

  /* ─── Display configuration ───
     QSPI bus: CS, SCLK, D0, D1, D2, D3 */
  gfxBus = new Arduino_ESP32QSPI(DSP_CS, DSP_SCLK, DSP_SDIO0, DSP_SDIO1, DSP_SDIO2, DSP_SDIO3);
  /* Panel constructor: bus, RST, rotation offset (0), x/y offset (0,0),
     width/height, backlight pin (22), options (0,0,0) */
  gfx = new Arduino_CO5300(gfxBus, DSP_RST, 0, 0, DSP_HOR_RES, DSP_VER_RES, 22, 0, 0, 0);

  if (!gfx->begin()) {
    Serial.println("Error: display init failed");
    while (true) /* halt on failure */ ;
  }

  gfx->setRotation(0);
  gfx->setBrightness(255);
  gfx->displayOn();
  Serial.println("Display initialized");

  /* Print Hello World! */
  gfx->fillScreen(BLUE);
  gfx->setTextSize(4);
  gfx->setTextColor(ORANGE);
  gfx->setCursor(65, 250);
  gfx->print("Hello World!");
}

void loop() {
  delay(1000);
}
```

### LVGL example

This code implements **LVGL 9.3** and allows you to test the screen **printing a text, using an example or using a demo.** By default, the **music demo of LVGL** is used.

```cpp lvgl_test.ino lines icon="microchip" theme={null}
/**
 * Example of using LVGL with Arduino on Kode Dot.
 * Sets up the display, touch panel, and draws a simple label.
 * More info: https://docs.lvgl.io/master/integration/framework/arduino.html
 */
/* ───────── KODE | docs.kode.diy ───────── */

#include <lvgl.h>
#include <Arduino_GFX_Library.h>
#include <Wire.h>
#include <bb_captouch.h>

/*To use the built-in examples and demos of LVGL uncomment the includes below respectively.
 *You also need to copy lvgl/examples to lvgl/src/examples. Similarly for the demos lvgl/demos to lvgl/src/demos.
 *Note that the lv_examples library is for LVGL v7 and you shouldn't install it for this version (since LVGL v8)
 *as the examples and demos are now part of the main LVGL library. */

// #include <examples/lv_examples.h>
// #include <demos/lv_demos.h>

/* Display resolution and rotation */
#define DSP_HOR_RES 410
#define DSP_VER_RES 502
#define DSP_ROTATION LV_DISPLAY_ROTATION_0

/* LVGL draw buffer size */
#define DRAW_BUF_SIZE (DSP_HOR_RES * DSP_VER_RES / 10 * (LV_COLOR_DEPTH / 8))
static uint8_t *lv_buf1;
static uint8_t *lv_buf2;

/* Objects to handle display bus and panel */
static Arduino_DataBus *gfxBus;
static Arduino_CO5300 *gfx;
static BBCapTouch touch;

/* Callback for LVGL to push rendered image to the display */
void my_disp_flush(lv_display_t *disp, const lv_area_t *area, uint8_t *px_map) {
  uint32_t w = lv_area_get_width(area);
  uint32_t h = lv_area_get_height(area);

  gfx->startWrite();
  gfx->writeAddrWindow(area->x1, area->y1, w, h);
  gfx->writePixels((uint16_t *)px_map, w * h);
  gfx->endWrite();

  /* Tell LVGL flushing is done */
  lv_display_flush_ready(disp);
}

/* Read data from the touch panel */
void my_touchpad_read(lv_indev_t *indev, lv_indev_data_t *data) {
  TOUCHINFO ti;
  if (touch.getSamples(&ti) && ti.count > 0) {
    data->state = LV_INDEV_STATE_PRESSED;
    data->point.x = ti.x[0];
    data->point.y = ti.y[0];
  } else {
    data->state = LV_INDEV_STATE_RELEASED;
  }
}

/* Use Arduino's millis() as LVGL tick source */
static uint32_t my_tick(void) {
  return millis();
}

void setup() {
  Serial.begin(115200);
  Serial.println("LVGL with Arduino on Kode Dot");

  /* ─── Display configuration ─── */
  gfxBus = new Arduino_ESP32QSPI(9, 17, 15, 14, 16, 10);
  gfx = new Arduino_CO5300(gfxBus, 8, 0, 0, DSP_HOR_RES, DSP_VER_RES, 22, 0, 0, 0);
  if (!gfx->begin()) {
    Serial.println("Display initialization failed");
    while (true) delay(1000);
  }
  gfx->setRotation(0);
  gfx->setBrightness(255);
  gfx->fillScreen(BLACK);
  Serial.println("Display initialized");

  /* ─── Touch panel configuration ─── */
  if (touch.init(48, 47, -1, -1, 400000) == CT_SUCCESS) {
    touch.setOrientation(0, DSP_HOR_RES, DSP_VER_RES);
    Serial.printf("Touch OK. Type=%d\n", touch.sensorType());
  } else {
    Serial.println("Touch initialization failed");
  }

  /* ─── Initialize LVGL ─── */
  lv_init();
  lv_tick_set_cb(my_tick); /* Set tick source */

  lv_display_t *disp = lv_display_create(DSP_HOR_RES, DSP_VER_RES);
  lv_display_set_flush_cb(disp, my_disp_flush);

  /* Allocate buffers in PSRAM */
  lv_buf1 = (uint8_t *)heap_caps_malloc(DRAW_BUF_SIZE, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT);
  lv_buf2 = (uint8_t *)heap_caps_malloc(DRAW_BUF_SIZE, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT);
  lv_display_set_buffers(disp, lv_buf1, lv_buf2, DRAW_BUF_SIZE, LV_DISPLAY_RENDER_MODE_PARTIAL);

  /* Configure input device as a pointer (touch) */
  lv_indev_t *indev = lv_indev_create();
  lv_indev_set_type(indev, LV_INDEV_TYPE_POINTER);
  lv_indev_set_read_cb(indev, my_touchpad_read);

  /* *******************
   * Create a simple label 
  ******************** */
  lv_obj_t *label = lv_label_create(lv_screen_active());
  lv_label_set_text(label, "Hello Arduino, I'm LVGL!");
  lv_obj_align(label, LV_ALIGN_CENTER, 0, 0);

  /* *******************
   * Try an example. See all the examples
   *  - Online: https://docs.lvgl.io/master/examples.html
   *  - Source codes: https://github.com/lvgl/lvgl/tree/master/examples
  ******************** */
  //  lv_example_btn_1();

  /* *******************
   * Or try out a demo. Don't forget to enable the demos in lv_conf.h. E.g. LV_USE_DEMO_WIDGETS
  ******************** */
  //    lv_demo_music();
}

void loop() {
  lv_timer_handler(); /* Let LVGL handle the GUI */
  delay(5);
}
```

## Download of examples

You can test the example codes using the Arduino IDE or the ESP-IDF IDE or download the codes in our drive:

[Examples of screen code](https://drive.google.com/drive/folders/1dw2ThNCUiHljMfDs-s67guQxr_ILJ5BL)
