Using ILI9488


I bought a 3.95" TFT LCD touch screen with ILI9488 (probably a wrong decision) and Arduino Mega 2560. I am trying (unsuccessfully) to make it work.
I am using UTFT library (and URTouch in the future) but it doesn't have my controller configuration.
When I used the ILI9481 configuration a got a mirrored text.

From what I saw, there is a configuration file (init file) for the controller and another printing file (initlcd.h and setxy.h). These are the only two references to the controller I found in the library, so I guess that if I had a file that compatible for ILI9488 or manipulate the existing file, it will be fine.

Does anyone have those files for ILI9488 or can tell me how to manipulate the existing files (for ILI9481) so it will be compatible for my ILI9488?

Thanks a lot!

The ILI9488 is very similar to the ILI9486.

Report back with your problem(s). I will show you which bit(s) control those features in initlcd.h


Unfortunately, with the ILI9486 configuration I only see dark screen with faded stripes.

This is the init line in my code (The UTFT_Demo_320X240.ino):

UTFT myGLCD(CTE40,38,39,40,41);

And in the setup function:


Thank you


Please post a link to your actual display shield. Make sure that the photos match your device.
Or post a photo of the item on your desk.

UTFT has three 320x480 controllers. Try each constructor. Take notes about each problem.
e.g. UTFT_Demo_480x320.ino sketch

UTFT myGLCD(ILI9481, 38, 39, 40, 41);
UTFT myGLCD(ILI9486, 38, 39, 40, 41);
UTFT myGLCD(R61581, 38, 39, 40, 41);

Please do NOT use gobbledygook “model” names like CTE40. If you want help, you can at least use the proper controller names.

MCUFRIEND_kbv supports eleven different 320x480 controllers
TFT_HX8357 supports several different 320x480 controllers.


Sorry for taking me so long.
I tried all the three options (the first and the third ones gave me reversed text and the secont one blank screen with faded stripes).

My link board is this:

The model on the board:
3.95" TFTLCD for arduino mega 2560(ili9488)

Your link does not work for me.

Try with this modified library: 3.95-2560-R61581 — Яндекс.Диск

More info here: Mega 2560 R3 + 3.95 TFT LCD Touch — Community «Arduino для автомобиля» on DRIVE2

Constructor: myGLCD (R61581,38,39,40,41);

It worked!
Thank you very much!
What's the difference between this library and the previous one?

UTFT supports known "models" of screen from known display sellers.

Please note that may Ebay, AliExpress, Mcufriend, ... adverts and descriptions are often mendacious.
I would be fairly confident that you do NOT have an ILI9488.

Life is much easier if we could see a photo of the actual pcb. We can pick up a few clues from the components, copper traces, printed legends.

All the same, everything is a bit of guesswork. But with accurate answers, I could probably identify the controller.

Your screen is clearly "MIPI compatible controller" because it obeys the setxy() commands.
All "MIPI" screens obey the basic User commands.
The Manufacturer commands differ between makes and model of the actual controller Silicon chip.

0x36 is the User Memory Access command. You will see that the "new" initlcd.h sets bit6 (MX) which controls the X writing direction.

As long as you get a correct picture in a single orientation, UTFT will do ecverything in software. e.g. Landscape.

Mr Karlsen is only prepared to support certain screen sellers. TFTLCDCyg's ZIP obviously works for your screen. It seems to be hacked from UTFT v2.8.1. The current UTFT is v2.8.2

Personally, I would be much happier with accurately determining the actual controller mounted on your screen (not visible from the pcb). It is possible to do this by observing the behaviour of different Manufacturer commands. Incidentally the 0x36 User command has some differences too.
UTFT was not written by me. You would need to ask Mr Karlsen for any official changes to UTFT.


David you're right. Many TFT makers get generic chips and they make hundred of shields, but the little differences, it result in big differences in the registers of startup.

You should find that the ILI9481, R61581, ILI9486/8 all behave slightly differently with User command 0x36.
Compare the datasheets for Bit #0, #1 in the argument (i.e. FLIP_GS, FLIP_SS)

Of course there are tens of other 320x480 controllers that might appear on the Ebay market.
You need to test Manufacturer commands for further diagnosis.

Not only controllers that differ. The physical TFT panel varies too. e.g. directions, colour inversion, ...

Remember that this is Mr Karlsen's library. I have no intention of hacking it. Just offering advice.


Whilst the subject of the ILI9488 display is fresh in peoples minds, I have hit a problem with reading on a 16 bit parallel bus.

I'm using the memory in the display to take a snapshot with an OV7670 camera. Works great on an ILI9486 controller but that returns 16 bits per read.

Writes are fine in RGB565 mode on the ILI9488 but all reads (apparently) are in RGB888 but I can't find any information on how those 24 bits are allocated to the 16 bit data bus.

Has someone with more Ilitek foo than me determined how to read display RAM specifically on a ILI9488 ?

Yes, you read 3 bytes for every pixel. And use uint16_t color = tft.color565(r, g, b);

Most MIPI controllers read 24-bits even if they can write 16-bit 565. The ILI9486 is the exception rather than the rule.


Thanks for confirming what I’d just sussed out by trial and error.
Data reads are [r1, g1] [b1, r2] [g2, b2] so 3 reads for 2 pixels, each colour value is left justified (e.g. red is written as 5 bits, read back as the top 5 of the 8 bits

// write in 565
rrrrrggggggbbbbb      < write first word
rrrrrggggggbbbbb      < write second word

// read back in 888
rrrrr000gggggg00      < read first 2 colours of 1st pixel
bbbbb000rrrrr000      < read last colour of 1st pixel, 1st colour of 2nd pixel
gggggg00bbbbb000      < read remaining 2 colours of 2nd pixel

Very irritating when you can’t edit a message for 5 minutes due to the ‘number of posts’ limit!!

Yes, that is correct. The ILI9486 and ILI9488 datasheets have nice coloured diagrams showing read and write sequences.

It takes a little while to see how it works in each interface.


Still got an issue, even after handling the rgb888 to rgb565 conversion!! The contrast is way off as though the colours are getting saturated somehow (I’ve even tried converting all logic to 32 bit to ensure I don’t get any overflows with the shifts!!).

This is with the 9486

and with the 9488

The code that is used to read from the LCD is:

// assumes read pointers already set with LCD_setAddrWindowRead()
LCD_readImageRGB565 (uint8_t *p_buff, uint32_t pixelNum)
   volatile uint16_t* p_lcdAddr = (volatile uint16_t*) (getDrawAddress ());

   for (uint32_t x = 0; x < pixelNum; x++)
#if defined (ILI9486)
      uint16_t data = *p_lcdAddr;
      p_buff[x * 2 + 1] = data >> 8;
      p_buff[x * 2 + 0] = data & 0x00ff;
      uint16_t f = *p_lcdAddr;
      uint16_t s = *p_lcdAddr;
      uint16_t t = *p_lcdAddr;
      uint16_t data = LCD_color565 (f >> 8, f & 0xff, s >> 8);
      p_buff[x * 2 + 1] = data >> 8;
      p_buff[x * 2 + 0] = data & 0x00ff;

               data = LCD_color565 (s & 0xff, t >> 8, t & 0xff);
      p_buff[x * 2 + 3] = data >> 8;
      p_buff[x * 2 + 2] = data & 0x00ff;

Clearing the screen down to a single colour and reading back, I get sensible values but in a more complex example (i.e. with a picture) you can see it ain’t right!!

I feel I must be missing something obvious but it’s not obvious to me at the moment!!

What TFT library are you using?

If your library can be configured for ILI9486 and ILI9488, the library readPixel(x, y) method will do the appropriate conversions.

If you are trying to do the low-level read yourself, it is just a question of following the coloured timing diagrams in the datasheet.

What hardware do you have?
I have only tested the MCUFRIEND_kbv library with SSD1963 on a readable 8080-16 data bus.
And the SSD1963 reads 565 and not 888.
I own many read-write 8080-8 displays, several write-only 8080-16 displays, only a SSD1963 read-write 8080-16.

You can do a simple hardware mod to the "ColdTears 40-pin Adapter for Due" shield to make it readable.
Most "Adapter for Mega" shields can not be modified.


Edit. It looks as if your TFT controller is on an external address bus. Most Arduino style electronics are bashed by GPIO. Your conditional code looks fine to me. (assuming the uint16_t f = *p_lcdAddr; statement strobes the LCD_RD pin appropriately)

I really appreciate your assistance in an area that is rapidly diverging from the main thread (and from the hardware platform as well!!). My excuse it that I’ve been feeding back bug reports/fixes to libraries like Bodmers, fixes which will probably apply to most of the Adafruit derivatives (check for issues raised by g8ecj - that’s me!)

I’m using an stm32f4 which includes an FSMC (Flexible Simple Memory Controller) so all the hardware is handled for me!!

I’ll play with the timing in case the 9488 is vastly different to the 9486.

Again, many thanks.

What hardware are you using?

I do not have any FSMC chips. I do have a DISCOVERY-429I somewhere which has FMC.

If your hardware is controlling the TFT Data Bus with 8080-16, you have to do 3 16-bit reads for 2 pixels.
And your code "looks" fine to me.

The obvious thing to do is read a block of GRAM and examine what you have got.

I have never cloned Bodmer's GitHub repositories. Simply installed as regular Arduino Libraries.