New library for Mega and low cost HX8357B/C and ILI9481 480 x 320 displays

I have posted a new version of the TFT_HX8357 library for the Mega on my GitHub repository. The display supported by the library is 16 bit with 480 x 320 pixels and is available at low cost from a number of sources for example from Banggood:

3.2" HX8357B display

HX8357C based 3.0" display

Or from AliExpress

The main changes the to the TFT_HX8357 library are:

  • improved performance (clear 480 x 320 screen in just 40ms)
  • the addition of the 48 different Free Fonts from the new Adafruit_GFX library
  • support for ILI9481 controller

New features also include justification options to centre, left, right, top bottom, basline justify text and numbers. See the example sketches.

At the moment the library only supports the Mega, I have a Due on order and might consider adding support for that board if there is sufficient interest.

Sometimes the vendors supply a different controller, probably an ILI9481, even though the advert states HX8357B, so the library also supports that controller by selecting the HX8357B with the MIRROR option in the User_Setup.h file (which can be found inside the library folder).

Please report any bugs via GitHub by raising an "issue".

Excellent. Downloading now, can't wait to give it a try.

KrisKasprzak: Excellent. Downloading now, can't wait to give it a try.

Bear in mind that it is NOT written to be compatible with the Adafruit HX8357D displays. Those displays use the iteration "D" controller and 8 bit or SPI interfaces.

A Due version of the same library for the same displays is available here.

Thanks for sharing!

Do you have performance numbers, old versus new (for both MEGA and DUE)?

Hi,

This is the Adafruit graphics test results for Mega:

TFT_HX8357 Mega Test 480 x 320
Benchmark,                Time (microseconds)
Screen fill,              223692
Text,                     44972
Lines,                    215852
Horiz/Vert Lines,         19424
Rectangles (outline),     12116
Rectangles (filled),      553988
Circles (filled),         190972
Circles (outline),        194816
Triangles (outline),      50052
Triangles (filled),       283928
Rounded rects (outline),  68892
Rounded rects (filled),   629600
Done!

And for Due:

TFT_HX8357_Due Test 480 x 320
Benchmark                Time (microseconds)
Screen fill,              57357
Text,                     27948
Lines,                    281204
Horiz/Vert Lines,         6763
Rectangles (outline),     5266
Rectangles (filled),      140249
Circles (filled),         146173
Circles (outline),        237888
Triangles (outline),      56086
Triangles (filled),       121190
Rounded rects (outline),  69925
Rounded rects (filled),   190308
Done!

The average is that with this library the Due is 1.85 x faster. Line drawing is 25% slower because the Due ports and bits happen to be badly mapped to the 16 bit bus to the TFT. So it burns up the processing power manipulating all those bits:

    TFT Mega    Due
    D15 PA7 D.6
    D14 PA6 D.3
    D13 PA5 D.2
    D12 PA4 D.1
    D11 PA3 D.0
    D10 PA2 A.15
    D9  PA1 A.14
    D8  PA0 B.26

    D7  PC7 D.9
    D6  PC6 A.7
    D5  PC5 D.10
    D4  PC4 C.1
    D3  PC3 C.2
    D2  PC2 C.3
    D1  PC1 C.4
    D0  PC0 C.5

    RS  PD7 C.6
    WR  PG2 C.7
    CS  PG1 C.8
    RST PG0 C.9

Filled rectangles are about 4x faster (12ms to clear 480 x 320 screen) simply because the Due can toggle pins faster. In fact it can toggle the write strobe line faster than the display driver chip can handle, so it has to be slowed down.

OK, do you also have the timings for your library? assuming the above are the Adafruit timings?

Those are the timings for my TFT_HX8357 and TFT_HX8257_Due libraries when running a graphicstest sketch. That sketch was originally created by Adafruit but has been used for performance testing.

I have also just tried a version of the UTFT_480x320 demo under UTFT and running on the Due. Under UTFT the demo completed in 5000ms (delays between tests set to zero), with my library the Due completed the test in 1700ms.

The Mega took 6280ms to run the same UTFT Demo using my library, but around 3s of that was calculating the 30,000 random numbers for the random position and colour pixel test. Taking out all those random numbers and drawing the 10000 pixels at specified locations brought the execution time down to 3450ms.

I assume the Due must be using the built in hardware random number generator as there was almost no speed difference when the random numbers were taken out, viz still around 1700ms.

As noted above the bad mapping of bits is reducing the performance significantly for individual pixel windowing intensive graphics like drawing oblique lines. As a test I ran the UTFT Demo on my library on the Due with all the bit manipulations commented out leaving just some port writes to emulate writing 16 bits in one instruction. The test then completes in around 1100ms. So the Due is spending around 1/3rd of the time just sorting the bits for the write.

Similarly running the "graphicstest" sketch gave these results which shows what could potentially be achieved with a better port mapping. I am not sure if you are familiar with that test sketch and the results are slightly misleading as the screen fill test is for 5 screen fills, thus the actualy clear screen time is less than 12ms, which is comparable to the TFT screen refresh rate (typically 70Hz, viz 14ms).

HX8357 Test!
Benchmark                Time (microseconds)
Screen fill              56941
Text                     12587
Lines                    107758
Horiz/Vert Lines         5486
Rectangles (outline)     3709
Rectangles (filled)      138869
Circles (filled)         69322
Circles (outline)        82700
Triangles (outline)      23280
Triangles (filled)       82524
Rounded rects (outline)  27005
Rounded rects (filled)   167939
Done!

These are the TFT_HX8357_Due library results if the screen area for the graphicstest is reduced to 320x240. Clearly the results are halved due to the smaller screen area, apart from the text (since the same number of characters are drawn).

Benchmark                Time (microseconds)
Screen fill              28660
Text                     28914
Lines                    142017
Horiz/Vert Lines         3657
Rectangles (outline)     3426
Rectangles (filled)      59774
Circles (filled)         72488
Circles (outline)        125375
Triangles (outline)      31395
Triangles (filled)       61585
Rounded rects (outline)  40116
Rounded rects (filled)   86047
Done!

I have also just tried a version of the UTFT_480x320 demo under UTFT and running on the Due. Under UTFT the demo completed in 5000ms (delays between tests set to zero), with my library the Due completed the test in 1700ms.

That is impressive! well done

@rowboteer,

I only have an ILI9481. So I do not have a HX8357B or HX8357C to test.

I note that you can configure the Panel characteristics in the initialisation method. e.g.

/*
    writecommand(0xB0); writedata(0x00); //unlock
    writecommand(0xC0); writedata(0x14); //GS_PANEL=1 REV_PANEL=1 for ILI9481
    writecommand(0xE9); writedata(0x08); //SS_PANEL=1 BGR_PANEL=0 for HX8357-B
    writecommand(0xCC); writedata(0x08); //SS_PANEL=1 BGR_PANEL=0 for HX8357-C
    writecommand(0xB0); writedata(0x03); //lock again 
*/

Of course the registers are different for each variant but conditionals in the initialisation are a fact of life.

Since the ILI9481 ignores the MY, MX bits and the HX8357 ignores the SS and GS bits in MADCTL, you could duplicate the MY, MX as GS, SS and eliminate the conditional in the setRotation().

Untested. Just a thought.

David.

@David

Yes the init and rotate code for the ILI9481 is a bit of a blind hack that fixed a bug in the rotation for that was reported on Github. I now have a ILI9481 display to test any changes and hence can streamline the code, however due to other commitments development will slow down for a while.

This librairie running very well with the MCUfriend ili9481. But what about the touchscreen?

If you have a Mcufriend Mega2560 shield, most are 16-bit parallel and will work with Rowboteer's library just fine.

They generally have an XPT2046 Touch Controller chip and connects to digital#3 - 7. At this location, you have no choice but to bit-bash the SPI using these pins. The UTouch library will do the bit-bash for you.

Since the target displays are the blue HX8357 / ILI9481 shields that do not have a Touch Panel, you need to use a third party library and third party examples.

David.

If you are having trouble getting UTouch working then you might like to try the library here.

First try the "TFT_Touch_Raw" example with your pin settings. This sketch outputs the raw 12 bit ADC touch x,y values to the Serial port for viewing in the IDE Serial Monitor window at 38400 baud. Nothing will get displayed on the screen but you will know if the touch screen is working.

The other examples are for a 320 x 240 screen based on the ILI9341 TFT library and they would need to be modified to use your chosen graphics library and display size.

After some tries, i finally used the Rowboteer's librairie that's working very well for the touchscreen with:

define HRES 480

define VRES 320

define DOUT 3 /* Data out pin (T_DO) of touch screen */

define DIN 4 /* Data in pin (T_DIN) of touch screen */

define DCS 5 /* Chip select pin (T_CS) of touch screen */

define DCLK 6 /* Clock pin (T_CLK) of touch screen */

it's giving: touch.setCal(3673,387,725,3467,480,320,0) ;) thanks a lot.

@Rigolo I am pleased you have it working. Thanks for posting your working setup. Good luck with your project.

I'm trying to put up more 2 icons 96x96 on the screen but It's still unworking. The mega is look like get stuck.

Hello

I have TFT ILI9481 buy this TFT use Arduino MEGA with library use HX8357

I have this problem.

My video TFT FLASHES

My TFT flashes with this code;

#include <TFT_HX8357.h> 
#include "Free_Fonts.h"

TFT_HX8357 tft = TFT_HX8357();    


void setup() {

  tft.begin();

  tft.setRotation(1);
  


}

void loop() {


  int xpos =  0;
  int ypos = 40;

  // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
  // Select different fonts to draw on screen using the print class
  // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

   tft.fillScreen(TFT_BLACK); // Clear screen to navy background

  header("Draw free fonts using print class");

  // For comaptibility with Adafruit_GFX library the text background is not plotted when using the print class
  // even if we specify it.
  tft.setTextColor(TFT_YELLOW, TFT_BLACK);
  tft.setCursor(xpos, ypos);    // Set cursor near top left corner of screen

  tft.setFreeFont(GLCD);     // Select the orginal small GLCD font by using NULL or GLCD
  tft.println();             // Move cursor down a line
  tft.print("Original GLCD font");    // Print the font name onto the TFT screen
  tft.println();
  tft.println();

  tft.setFreeFont(FSB9);   // Select Free Serif 9 point font, could use:
  // tft.setFreeFont(&FreeSerif9pt7b);
  tft.println();          // Free fonts plot with the baseline (imaginary line the letter A would sit on)
  // as the datum, so we must move the cursor down a line from the 0,0 position
  tft.print("Serif Bold 9pt");  // Print the font name onto the TFT screen

  tft.setFreeFont(FSB12);       // Select Free Serif 12 point font
  tft.println();                // Move cursor down a line
  tft.print("Serif Bold 12pt"); // Print the font name onto the TFT screen

  tft.setFreeFont(FSB18);       // Select Free Serif 12 point font
  tft.println();                // Move cursor down a line
  tft.print("Serif Bold 18pt"); // Print the font name onto the TFT screen

  tft.setFreeFont(FSB24);       // Select Free Serif 24 point font
  tft.println();                // Move cursor down a line
  tft.print("Serif Bold 24pt"); // Print the font name onto the TFT screen


 // delay(2000);


}



// Print the header for a display screen
void header(char *string)
{

 
  tft.setTextSize(1);
  tft.setTextColor(TFT_YELLOW, TFT_BLACK);
  tft.fillRect(0, 0, 480, 30, TFT_BLUE);
  tft.setTextDatum(TC_DATUM);
  tft.drawString(string, 239, 2, 4); // Font 4 for fast drawing with background
}

If I put final to loop this code

delay(2000);

No flashes. But this can not be put each instruction

delay(2000);

I believe fillScreen be problem in library, I try other libraries for example UTFT and this will not happen. Any solution? Thanks and regards.

@ Rowboteer.

Thank you very much for your great work on this library. Please pardon my ignorance but is there somewhere a list of the functions contained in the library similar to this? http://www.rinkydinkelectronics.com/library.php?id=51. Not that I expect you to draft one. Just curious.

All I am trying to do is display a bmp on the display with a Mega similar to this display. It looks similar to the ones relevant to this thread and it has a IL9481 graphics controller https://www.robotics.org.za/index.php?route=product/product&product_id=1347&search=lcd by reading the bmp off the SD Card but I simply do not have enough knowledge to get the code right. I am not sure what function to use and how to use it.

Kindest Regards