Graphics library for NodeMCU (ESP8266), ESP32 and serial+parallel TFT displays

If it looks like this

It should work with any Mcufriend-style libraries (if you configure the data bus pins)
It appears to have a separate hardware-reset chip.

Regular Mcufriend-style shields have a LCD_RST pin on A4.
This is unnecessary if you have a reset-chip.

Bodmer's TFT_eSPI library runs some parallel chips e.g. ILI9341
You need a small hardware mod on a TTGO D1 R32 board and software tweak.

MCUFRIEND_kbv library supports ILI9325, ILI9328, HX8347D and many others.
You need a small hardware mod on a TTGO D1 R32 board and software tweak.

It is fairly pointless using a Parallel shield with ESP32.
You can use SPI modules with ESP32, ESP8266 and still have pins spare.

David.

Thanks for inserting the board photo, David. I was just thinking if it's a good idea or better leave it as a link.

And indeed, I've used your MCU_friend_kbv library with great success with my LCD and Arduino Due! But I thought it's only for Arduino boards, do you also support EPS32?
I understand it's pointless, but I already have this LCD and could start working on the project isntead of just sitting on my hands for a month until a more fitting LCD arrives from China.

I read the rotation examples for the Sprites but cannot seems to find the answer.
Say I want to create a dial with two individually rotated needles (Based on bmp images on spiffs)
Think clockhands as an example.

How can I push both images (and correctly rotated) into the single Sprite?
pushRotated seems to rotate the whole Sprite if I am not mistaken.

Guys, is it possible to load BPM (i.e. in 16bits format 565) into SPIFFS and then read only a part of that bitmap and put that small part on the display/spring?
For example i have 100x100 pixels BMP stored in flash. Now i need to take a small part using function like:

partBMP(flie_name, startX, startY, width, height) - i'm telling where to start (startX, startY) within the BMP 'file_name' and how big part i need (width, height).

Please tell me how to implement it.
By this i can easily replace just part of the display content and shift that part easily i the direction i need.

@Mac_che: Study the Rotated_Sprite_2 example. You just need to print the "needle" twice at different angles.

@bogus105: Answered here.

I have updated the TFT_eSPI library to support this fast 320x420 4" ST7796 based RPi display. Typically this is available for $15 or less with or without XPT2046 based touch screen.

This display is fitted with a bespoke SPI serial to parallel converter that is much better than many RPi displays on the market. The SPI transmit data can be clocked into the display reliably at up to 125MHz which is the data sheet limit for parallel data with the ST7796. The chip converts the SPI data to 16 bit parallel and writes it into the display at up to 30Mbytes/sec. This neatly gets around the speed limits of typical SPI interfaces on these screens and permits 50fps whole screen update rate.

The TFT_eSPI library can be used with the ESP32 SPI with an 80MHz clock (maximum for ESP32). For a 320 x 480 display this gives good performance for a SPI interface:

ESP32 RPi ST7796 80MHZ SPI
Benchmark,                Time (microseconds)
Screen fill,              180556 (clear screen = 36 ms = ~28 fps)
Text,                     13699
Lines,                    166066
Horiz/Vert Lines,         16290
Rectangles (outline),     9376
Rectangles (filled),      440312
Circles (filled),         102275
Circles (outline),        101998
Triangles (outline),      34580
Triangles (filled),       164103
Rounded rects (outline),  43216
Rounded rects (filled),   490934

Total = 1.7634s

Although the ESP8266 can clock the SPI at 80MHz, it does not have the signal drive strength to maintain the correct clock phase relationship with the data. This limits the ESP8266 to 40MHz SPI clock with this display:

ESP8266 RPi ST7796 40MHZ SPI
Benchmark,                Time (microseconds)
Screen fill,              317434 (clear screen = 63 ms = ~18 fps)
Text,                     20888
Lines,                    270627
Horiz/Vert Lines,         27145
Rectangles (outline),     16004
Rectangles (filled),      768065
Circles (filled),         173822
Circles (outline),        163897
Triangles (outline),      55797
Triangles (filled),       293139
Rounded rects (outline),  70044
Rounded rects (filled),   863555

Total = 3.0404s

Wiring is as per image here.

Hi guys.
I'm a newbie to ESP32 and also Bodmer's tft_espi library, but have been trawling through the examples trying to get the font type and size I want.
Firstly I must say the use of sprites is fantastic for flicker free dynamic text.
Now looking at smooth fonts.
I converted Arial font using the various links Bodmer provides in the examples and can get it onto the display using sprite. Not sure if doing it 100% correctly, but it's working.
Anyway, wondering if I can scale the smooth font.
Img.setTextSize() isn't doing anything. Tried it at several positions in the code. Ended up just converting the font again in a bigger size.
So is this the way to go? Or am I missing something?
Using a 2.2" TFT ILI9341.
Any tips?

Thanks in advance

Matt

Scaling does not work on smooth fonts. You have to create and load a larger size font.

Many thanks Bodmer. That's what I figured.
Top job on the library by the way.
A tad confusing for a novice like me but great examples and with those I've been able to piece stuff together as I'd like.

Matt

While I'm here, may as well ask.... No chance of a user manual I suppose.
The examples are great but I find that I usually delete a lot of the clever stuff just to get to the bare bones.
Maybe just me being lazy.....

A user manual is on my "to do" list but somehow never moves to the top of the list!

I know where you're coming from.
Until then, I'll keep trawling the examples

Is there a neat way of blinking/flashing some text? I can't find any examples online.

Use a loop with a delay, swap the foreground and background colors and redraw the text

The TFT_eSPI library has been updated to allow the ESP32 to use DMA for SPI transfers to the TFT. The "DMA Test" examples now run on the ESP32 (as well as the STM32 processors).

Using DMA generally only gives modest performance improvements and is actually slower for small pixel block updates of the screen. To update just 1 pixel would be 10x slower because it takes time to setup the DMA transaction parameters and initiate the transfer.

The "Flash_Jpg_DMA" draws the image on a 240x320 screen (40MHz SPI) in 103ms without DMA and 76ms with DMA, this is because the Jpeg decoding can carry on while the image tiles are rendered to the screen.

The functions specific to DMA are:

  bool     initDMA(void);     // Initialise the DMA engine and attach to SPI bus - typically used in setup()
  void     deInitDMA(void);   // De-initialise the DMA engine and detach from SPI bus - typically not used
  
           // Push an image to the TFT using DMA, buffer is optional and grabs (double buffers) a copy of the image
           // Use the buffer if the image data will get over-written or destroyed while DMA is in progress
           // If swapping colour bytes is defined, and the double buffer option is NOT used then the bytes
           // in the original data image will be swapped by the function before DMA is initiated.
           // The function will wait for the last DMA to complete if it is called while a previous DMA is still
           // in progress, this simplifies the sketch and helps avoid "gotchas".
  void     pushImageDMA(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t* data, uint16_t* buffer = nullptr);

           // Push a block of pixels into a window set up using setAddrWindow()
  void     pushPixelsDMA(uint16_t* image, uint32_t len);

           // Check if the DMA is complete - use while(tft.dmaBusy); for a blocking wait
  bool     dmaBusy(void); // returns true if DMA is still in progress
  void     dmaWait(void); // wait until DMA is complete

Good job bodmer, thanks for the time!. In the first ESP32-ILI9341 setup, I got these errors:

C:\Users\StarX\Documents\Arduino\libraries\TFT_eSPI\Processors/TFT_eSPI_ESP32.c: In member function 'bool TFT_eSPI::initDMA()':

C:\Users\StarX\Documents\Arduino\libraries\TFT_eSPI\Processors/TFT_eSPI_ESP32.c:674:3: error: 'spi_bus_config_t' has no non-static data member named 'flags'

   };

C:\Users\StarX\Documents\Arduino\libraries\TFT_eSPI\Processors/TFT_eSPI_ESP32.c:690:3: error: 'spi_device_interface_config_t' has no non-static data member named 'input_delay_ns'

   };

Error compilando para la tarjeta DOIT ESP32 DEVKIT V1

In the TFT_eSPI_ESP32.c file, I commented three lines, and the errors disappeared (.flags = 0, .intr_flags = 0 and .input_delay_ns = 0,):

bool TFT_eSPI::initDMA(void)
{
  if (DMA_Enabled) return false;

  esp_err_t ret;
  spi_bus_config_t buscfg = {
    .mosi_io_num = TFT_MOSI,
    .miso_io_num = TFT_MISO,
    .sclk_io_num = TFT_SCLK,
    .quadwp_io_num = -1,
    .quadhd_io_num = -1,
    .max_transfer_sz = TFT_WIDTH * TFT_HEIGHT * 2 + 8 // TFT screen size
    //.flags = 0,
    //.intr_flags = 0
  };
  spi_device_interface_config_t devcfg = {
    .command_bits = 0,
    .address_bits = 0,
    .dummy_bits = 0,
    .mode = TFT_SPI_MODE,
    .duty_cycle_pos = 0,
    .cs_ena_pretrans = 0,
    .cs_ena_posttrans = 0,
    .clock_speed_hz = SPI_FREQUENCY,
    //.input_delay_ns = 0,
    .spics_io_num = TFT_CS,
    .flags = 0,
    .queue_size = 7,
    .pre_cb = dc_callback, //Callback to handle D/C line
    .post_cb = 0
  };

Results:

Width = 240, height = 320
86 ms

Is the correction that simple or should an extra configuration line be added in the library?

@TFTLCDCyg

I do not get those error messages myself.

If I do edit out those lines out that you mention then I do get error messages and the sketch will not compile.

Clearly we have different setups but I am not sure what the difference is.

The parameters you have a problem with are in the ESP32 IDF 3.2 documents for the SPI DMA API.

Incidentally, you will get slightly better performance if you change the sketch line:

tft.setSwapBytes(true);

to:

TJpgDec.setSwapBytes(true);

As then the byte swapping needed is done while DMA is in progress.

I just upgraded from pre-v2.x to the latest ( 2.2.8 ) and I get the exact same error as @TFTLCDCyg. I tried with the default user setup as well as my normal custom user setup file. I will go edit out those lines and try it.

Incidentally, this is with any of the examples or my own projects, so it's something inherent with the new upgrade.

Let me know if there is anything I can do to help you figure out why this error occurs. I am running v1.8.2. of the Arduino core.

Well, editing those lines also worked for me. I am using v1.04 of the ESP32 board manager. I don't use PlatformIO at all. I guess I could try to set that up and see if that makes a difference. I am not sure if you have tried this under the Arduino IDE lately.

The new version works flawless once you make those edits! I am getting 117fps @40MHz, 128fps @50Mhz and @60MHz (no increase at 60MHz) with the Boing ball demo on my ESP32D module. I can use 80MHz no problem when DMA is not used. I am guessing the speed restriction must have to do with DMA mode?

@JimDrew @TFTLCDCyg

I tried compiling the library with Arduino IDE 1.8.1 and I get the reported errors.

Arduino IDE 1.8.5 worked fine with no reported errors.

Currently I am using 1.8.11 with no reported errors.

All these were using ESP32 board package 1.0.4

I conclude this problem only occurs on older versions of the IDE that are >~3 years old so I do not propose to change the library.