Skip to content

SPI TFT and XPT2046 touch screen controller driver for esp-idf

License

Notifications You must be signed in to change notification settings

nopnop2002/esp-idf-ili9340

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

esp-idf-ili9340

SPI TFT and XPT2046 touch screen controller driver for esp-idf.

Software requirements

ESP-IDF V5.0 or later.
ESP-IDF V4.4 release branch reached EOL in July 2024.

Note for ESP32-C6
ESP-IDF V5.1 is required when using ESP32-C6.

Installation

git clone https://github.com/nopnop2002/esp-idf-ili9340
cd esp-idf-ili9340/
idf.py set-target {esp32/esp32s2/esp32s3/esp32c2/esp32c3/esp32c6}
idf.py menuconfig
idf.py flash

Note for ESP32-S2/ESP32-C2
The tjpgd library is not included in the ESP32-S2/ESP32-C2 ROM.
However, you can use this IDF component registry.
JPEG files can be displayed.

Note for ESP32-C2
ESP32-C2 has less SRAM, so JPEG and PNG may not be displayed on higher resolution TFTs.

E (256560) decode_jpeg: Error allocating memory for line 251
E (260630) pngle_new: Error allocating memory for line 160

Note for ESP32-S2
ESP32-S2 has less SRAM, but some ESP32-S2 have PSRAM.
If your SoC has PSRAM, you can avoid running out of memory by enabling PSRAM.
config-psram

Configuration

You have to set this config value with menuconfig.

  • CONFIG_WIDTH
  • CONFIG_HEIGHT
  • CONFIG_OFFSETX
  • CONFIG_OFFSETY
  • CONFIG_MOSI_GPIO
  • CONFIG_SCLK_GPIO
  • CONFIG_CS_GPIO
  • CONFIG_DC_GPIO
  • CONFIG_RESET_GPIO
  • CONFIG_BL_GPIO
    GPIO of ESP32 cannot supply too much current.
    TFT backlight becomes brighter when powered by an external power source.

TFT MISO is not use.

config-menu


Tested TFT

  • M5Stack
  • Shenzhen Jingcal Intelligent 3.5" ST7796 320x480 (ESP32-3248S035)
  • Shenzhen Jingcal Intelligent 2.8" ILI9341 240x320 (ESP32-2432S028R)
  • 4.0" ST7796 320x480
  • 3.2" ILI9341 240x320
  • 2.8" ILI9341 240x320
  • 2.8" ST7789 240x320
  • 2.4" ILI9341 240x320
  • 2.4" ST7789 240x320
  • 2.2" ILI9340 240x320
  • 2.0" ILI9225 176x220
  • 1.8" ST7735 128x160
  • 1.77" ST7735 128x160
  • 1.44" ST7735 128x128
  • 0.96" ST7735 80x160

Generic Product

spi-tft

A note about RESET
Pull Up of the RESET pin may be required. I inserted a 100 ohm resistor between Vcc and RESET.

Shenzhen Jingcal Intelligent Product

They can use touch screens.
Shenzhen_Jingcal_Intelligent

ESP32-2432S032/ESP32-4827S043/ESP32-8048S043 doesn't work because it's an RGB panel, not SPI.


M5Stack

config-m5stack

M5Stick-1 M5Stack-2 M5Stick-3 M5Stick-4 M5Stick-5 M5Stick-6 M5Stick-7 M5Stick-8 M5Stick-9 M5Stick-10 M5Stick-11

BMP file
M5Stack-BMP

JPEG file(Cannot be displayed on ESP32S2)
M5Stack-JPEG

PNG file
M5Stack-PNG

PNG icon M5Stack-ICON


4.0" ST7796S 320x480

config-st7796

Left:4.0" Right:2.4" 4_0_st779s


Shenzhen Jingcal Intelligent 3.5" ST7796 320x480

Vendor part number is ESP32-3248S035.

config-ESP32-3248S035 ESP32-3248S035-1 ESP32-3248S035-2


3.2" ILI9341 240x320

2.8" ILI9341 240x320

2.4" ILI9341 240x320

config-ili9341

Left:3.2" Right:2.4" 3_2_ili9341

Left:2.8" Right:2.4" screen_2-8_240x320


2.8" ST7789 240x320

2.4" ST7789 240x320

config_st7789_2-4_240x320

Left:2.4" Right:2.8" screen_st7789_240x320


Shenzhen Jingcal Intelligent 2.8" ILI9341 240x320

Vendor part number is ESP32-2432S028R.

config-ESP32-2432S028R-1 ESP32-2432S028R-1 ESP32-2432S028R-2


2.2" ILI9340 240x320

config-ili9340

Left:2.2" Right:2.4" screen_2-2_240x320


2.0" ILI9225 176x220

config-ili9225

Left:2.0" Right:2.4" 2_0_ili9225


1.8" ST7735 128x160

config-st7735-128x160-1

Left:1.8" Right:2.4" 1_8_st7735


1.8" ST7735 128x160

config-st7735-128x160-2 screen_1-8_128x160-12 screen_1-8_128x160-13


1.8" ST7735 128x160

config-st7735-128x160-3 screen_1-8_128x160-21 screen_1-8_128x160-31


1.77" ST7735 128x160

config-st7735-128x160-4

Left:1.77" Right:1.8" screen_1-77_128x160


1.44" ST7735 128x160

config-st7735-128x160-5

Left:1.44" Right:2.0" screen_1-8_128x160-2


1.44" ST7735 128x128

config-st7735-128x128 screen_1-44_128x128-12 screen_1-44_128x128-13

GRAM Offset may be different


0.96" ST7735 80x160

config-st7735-80x160

Left:1.44" Right:0.96" screen_0-96_80x160-3


JPEG Decoder

The ESP-IDF component includes Tiny JPEG Decompressor.
The document of Tiny JPEG Decompressor is here.
This can reduce the image to 1/2 1/4 1/8.


PNG Decoder

The ESP-IDF component includes part of the miniz library, such as mz_crc32.
But it doesn't support all of the miniz.
The document of miniz library is here.

And I ported the pngle library from here.
This can reduce the image to any size.


Font File

This project uses the following as default fonts:

  • font/ILGH16XB.FNT // 8x16Dot Gothic
  • font/ILGH24XB.FNT // 12x24Dot Gothic
  • font/ILGH32XB.FNT // 16x32Dot Gothic
  • font/ILMH16XB.FNT // 8x16Dot Mincyo
  • font/ILMH24XB.FNT // 12x24Dot Mincyo
  • font/ILMH32XB.FNT // 16x32Dot Mincyo

From 0x00 to 0x7f, the characters image of Alphanumeric are stored.
From 0x80 to 0xff, the characters image of Japanese are stored.
Changing this file will change the font.

You can add your original fonts.
The format of the font file is the FONTX format.
Your font file is put in font directory.
Your font file is uploaded to SPIFFS partition using meke flash.

Please refer this page about FONTX format.


Font File Editor(FONTX Editor)

There is a font file editor.
This can be done on Windows 10.
Developer page is here.

fontx-editor-1

Convert from BDF font to FONTX font

step1)
download Font File Editor(FONTX Editor) from here.

step2)
download BDF font file from Internet.
I downloaded from here.
fontxedit.exe can ONLY import Monospaced bitmap fonts file.
Monospaced bitmap fonts can also be downloaded here.

step3)
import the BDF font file into your fontxedit.exe.
this tool can convert from BDF to FONTX.
fontx-editor-2

step4)
adjust font size.
fontx-editor-3

step5)
check font pattern.
when you have made any changes, press the apply button.
fontx-editor-4

step6)
save as .fnt file from your fontedit.exe.
fontx-editor-5

step7)
upload your font file to $HOME/esp-idf-ili9340/font directory.

step8)
add font to use

FontxFile fx32L[2];
InitFontx(fx32L,"/spiffs/LATIN32B.FNT",""); // 16x32Dot LATIN

Font file that From 0x00 to 0x7f, the characters image of Standard ASCII are stored.
M5Statck-Font-1

Font file that From 0x80 to 0xff, the characters image of Japanese are stored.
M5Statck-Font-2

Font file that From 0x80 to 0xff, the characters image of Latin are stored.
M5Statck-Font-3

u8g2 library contains many BDF fonts.
This is a 24x24 font converted from emoticons21.bdf.
bdf-font-1

This is a 16x16 font converted from Scroll-o-Sprites.bdf.
bdf-font-2

Convert from TTF font to FONTX font

step1)
Download WFONTX64.exe from here. Developer page is here.

step2)
Select ttf font.
Please note that if you select a proportional font, some fonts may not convert correctly.
If you select a proportional font, some fonts will need to be modified using fontxedit.exe.
Monospaced fonts can be converted correctly.
You can find Monospaced fonts here.
WFONTX64-1

step3)
Enter Height, Width, FontX2 name.
Specify half of Height for Width.
Specify your favorite font name in the FontX2 name field using up to 8 characters.
WFONTX64-2

step4)
Specify the file name to save.
WFONTX64-3

step5)
Specify the font style as required.
WFONTX64-4

step6)
Press the RUN button to convert TTF fonts to FONTX format.
WFONTX64-5

step7)
upload your font file to $HOME/esp-idf-ili9340/font directory.

step8)
add font to use

    FontxFile fx16G[2];
    FontxFile fx24G[2];
    FontxFile fx32G[2];
    //InitFontx(fx16G,"/spiffs/ILGH16XB.FNT",""); // 8x16Dot Gothic
    //InitFontx(fx24G,"/spiffs/ILGH24XB.FNT",""); // 12x24Dot Gothic
    //InitFontx(fx32G,"/spiffs/ILGH32XB.FNT",""); // 16x32Dot Gothic
    InitFontx(fx16G,"/spiffs/Gigi16.FNT",""); // 8x16Dot Gigi
    InitFontx(fx24G,"/spiffs/Gigi24.FNT",""); // 12x24Dot Gigi
    InitFontx(fx32G,"/spiffs/Gigi32.FNT",""); // 16x32Dot Gigi

ttf_font

How to add your color

Change here.

#define RED    rgb565(255,   0,   0) // 0xf800
#define GREEN  rgb565(  0, 255,   0) // 0x07e0
#define BLUE   rgb565(  0,   0, 255) // 0x001f
#define BLACK  rgb565(  0,   0,   0) // 0x0000
#define WHITE  rgb565(255, 255, 255) // 0xffff
#define GRAY   rgb565(128, 128, 128) // 0x8410
#define YELLOW rgb565(255, 255,   0) // 0xFFE0
#define CYAN   rgb565(  0, 156, 209) // 0x04FA
#define PURPLE rgb565(128,   0, 128) // 0x8010

XPT2046 Touch Screen

A library of XPT2046 Touch Screen is included in this project.
There is a TFT equipped with XPT2046.
XPT2046-3

XPT2046 shares the TFT and SPI bus.
Use the menu to enable XPT2046.
config-xpt2046-1

  • Touch position accuacy
    The coordinates read from XPT2046 are physical coordinates.
    Physical coordinates are converted to logical coordinates.
    Then draw using logical coordinates.
    In TouchPenTest, when you touch the screen, a circle is drawn at the touched position, but if you touch the same position as the previous time, it is not drawn.
    This value is the threshold that determines whether the touch location is the same as the previous touch location.
    Decreasing this value will make the position more accurate, but less responsive.
    Increasing this value will make the position more inaccurate but more responsive.

HR2046 Chip

There is a TFT equipped with HR2046.
XPT2046 and HR2046 are very similar. But HR2046 does not work properly.
XPT2046-2

Wirering for XPT2046

TFT ESP32 ESP32-S2/S3 ESP32-C2/C3
VCC -- 3.3V 3.3V 3V3
GND -- GND GND GND
CS -- GPIO14 GPIO34 GPIO2
RES -- GPIO33 GPIO41 GPIO4 (*1)
D/C -- GPIO27 GPIO40 GPIO3 (*1)
MOSI -- GPIO23 GPIO35 GPIO0 (*1) (*2)
SCK -- GPIO18 GPIO36 GPIO1 (*1) (*2)
LED -- 3.3V 3.3V 3.3V (*1) (*3)
MISO -- N/C N/C N/C
T_CLK -- GPIO18 GPIO36 GPIO1 (*1) (*2)
T_CS -- GPIO21 GPIO38 GPIO7 (*1) (*4)
T_DIN -- GPIO23 GPIO35 GPIO0 (*1) (*2)
T_OUT -- GPIO19 GPIO37 GPIO6 (*1) (*4)
T_IRQ -- GPIO22 GPIO39 GPIO8 (*1) (*4)

(*1) You can change it to any gpio using menuconfig. But some gpio's are input only.

(*2) These are shared by TFT and XPT2046.

(*3) It can be controlled using gpio. However, GPIO of ESP32 cannot supply too much current. TFT backlight becomes brighter when powered by an external power source.

(*4) I found that there are limits to the GPIOs that can be used as touch panel controls.

Check if XPT2046 works properly

You can check if XPT2046 works properly.
config-xpt2046-2

If you touch it at this time, the touched coordinates will be displayed.
If there is no touch for 10 seconds, it will end.
TouchPosition-1

Move the touch-pen vertically and horizontally to check the X and Y coordinates.
What you get here is the physical coordinates.
See here about physical coordinates.
TouchPosition-2

Using ESP32-3248S035

This module also has an XPT2046.
ESP32-3248S035-2 ESP32-3248S035-3

XPT2046 uses the same SPI bus as TFT.
XPT2046's SCLK and MOSI use the same GPIO as the TFT.
config-ESP32-3248S035-2

Using ESP32-2432S028R

This module also has an XPT2046.
ESP32-2432S028R-2 ESP32-2432S028R-3

XPT2046 uses a different SPI bus than TFT.
XPT2046's SCLK and MOSI use separate GPIOs from the TFT.
config-ESP32-2432S028R-2

Calibration

Keep touching the point.
XPT2046-1 XPT2046-2

Draw with touch

If there is no touch for 10 seconds, it will end.
TouchPen-1

Button with touch

You can only enter up to 15 characters.
If there is no touch for 10 seconds, it will end.
TouchKeyboard

Move with touch

If there is no touch for 10 seconds, it will end.
TouchMove-1 TouchMove-2

Menu with Touch

If there is no touch for 10 seconds, it will end.
TouchMenu-1 TouchMenu-2

Select with touch

If there is no touch for 10 seconds, it will end.
I borrowed the icon from here.
TouchIcon-1 TouchIcon-2

Save calibration data to NVS

Write calibration data to NVS.
Read calibration data from NVS when starting the firmware and use it.
If you use the same TFT, you don't need to calibrate again.
To clear the calibration data recorded in NVS, execute the following command.

idf.py erase_flash

config-xpt2046-4


SPI Clock speed

According to the datasheet, the minimum SPI clock cycles for each driver are as follows:
Maximum SPI clock frequency is the reciprocal of this.

Driver minimum SPI clock cycle maximum SPI clock frequency
ILI9225 100ns 10MHz
ILI9340 66ns 15MHz
ILI9341 100ns 10MHz
ST7735 66ns 15MHz
ST7796 66ns 15MHz

The SPI clock frequency used by this project is 10MHz.
Higher SPI clock frequencies can be specified using spi_clock_speed().
When using higher SPI clock frequencies, you need to be careful about the length of the wire cable.

    int speed = 15000000; // 15MHz
    spi_clock_speed(speed);
    spi_master_init(&dev, CONFIG_MOSI_GPIO, CONFIG_SCLK_GPIO, CONFIG_TFT_CS_GPIO, CONFIG_DC_GPIO,
        CONFIG_RESET_GPIO, CONFIG_BL_GPIO, XPT_MISO_GPIO, XPT_CS_GPIO, XPT_IRQ_GPIO, XPT_SCLK_GPIO, XPT_MOSI_GPIO);
    lcdInit(&dev, model, CONFIG_WIDTH, CONFIG_HEIGHT, CONFIG_OFFSETX, CONFIG_OFFSETY);

SPI BUS selection

config-spi-bus

The ESP32 series has three SPI BUSs.
SPI1_HOST is used for communication with Flash memory.
You can use SPI2_HOST and SPI3_HOST freely.
When you use SDSPI(SD Card via SPI), SDSPI uses SPI2_HOST BUS.
When using this module at the same time as SDSPI or other SPI device using SPI2_HOST, it needs to be changed to SPI3_HOST.
When you don't use SDSPI, both SPI2_HOST and SPI3_HOST will work.
Previously it was called HSPI_HOST / VSPI_HOST, but now it is called SPI2_HOST / SPI3_HOST.

Using Frame Buffer

config_framebuffer

When FrameBuffer is enabled, all output will be stored in the internal FrameBuffer and reflected to the device with lcdDrawFinish.
If you don't use FrameBuffer, lcdDrawFinish does nothing.
If your main purpose is to display text, it's well worth using FrameBuffer.
If your main purpose is to display images, there is no value in using FrameBuffer.
Enabling FrameBuffer does not make image display faster.
This is because image analysis takes time.

This option requires large RAM space.
If your SoC has PSRAM, you can avoid running out of memory by enabling PSRAM.
config-psram

Benchmarking using ESP32-S2@240 & 2.4 inch TFT

Disable Frame Buffer Enable Frame Buffer
FillTest 1390 1450
ColorBarTest 150 160
ArrowTest 330 160
LineTest 2670 180
CircleTest 2390 190
RoundRectTest 2430 180
DirectionTest 500 160
HorizontalTest 1110 170
VerticalTest 1100 180
FillRectTest 300 180
ColorTest 370 170
CodeTest 1760 180
BMPTest 3000 2810
JPEGTest 2760 2760
PNGTest 2940 2960
IconTest 740 870

Using SPI TFT Adapter

I purchased this adapter on AliExpress.
It comes with an ESP32 and costs $4.
14pin-adapter-1 14pin-adapter-2

However, this adapter's T_IRQ is not connected anywhere.
To use the touch panel, you need to add a jumper.
14pin-adapter-3

As a result, the GPIO will be:

TFT ESP32
VCC -- 3.3V
GND -- GND
CS -- GPIO15
RES -- GPIO04
D/C -- GPIO02
MOSI -- GPIO23
SCK -- GPIO18
LED -- 3.3V *1
MISO -- N/C
T_CLK -- GPIO18
T_CS -- GPIO05
T_DIN -- GPIO23
T_OUT -- GPIO19
T_IRQ -- GPIO21

(*1) BL_EN is directly connected to 3.3V, so it cannot control BackLight.

When not using the touch panel.
config-14pin-adapter-1

When using the touch panel.
config-14pin-adapter-2

14pin-adapter-4


Reference

A TFT shield like this can be used with ESP-IDF.
TFT-Shield

It can be attached directly to this ESP32.
tzt-d1-esp32s3

https://github.com/nopnop2002/esp-idf-parallel-tft