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 |
The QuadSPI bus is of the same family as the SPI bus, but has double the bandwidth.
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 |
The touch driver has the address 0x15 on the I2C bus.
The interrupt pin is connected to EXP15 of the IO expander. See
IO expander for more information.
The reset pin of the touch driver and the screen driver are connected to the same pin of the ESP32-S3.
Recommended libraries
Arduino
ESP-IDF
Example code
Basic example
This is the most basic code to test the screen, only printing a ¡Hola mundo! on the screen.
/**
* 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.
/**
* 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