Highly optimized ILI9341 (320x240 TFT color display) library

Paul, thanks for your time and dedication to the cause as ever, Adafruit's libraries both work fine with the Adafruit_ILI9341 library showing better speeds. The results of each, corrupted output aside, are shown below.

I have wired the reset pin and changed the ILI9341_t3 constructor to:

Code:
// For the Adafruit shield, these are the default.
#define TFT_RST  8
#define TFT_DC  9
#define TFT_CS 10

// Use hardware SPI (on Uno, #13, #12, #11) and the above for CS/DC
ILI9341_t3 tft = ILI9341_t3(TFT_CS, TFT_DC, TFT_RST);

Is that the correct syntax for specifying the reset and do I need to do anything else as I am still getting the corruption?

Results:

Begin Adafruit_ILI9340 Test!
Benchmark Time (microseconds)
Screen fill 1945672
Text 148299
Lines 1488543
Horiz/Vert Lines 161468
Rectangles (outline) 104783
Rectangles (filled) 4040175
Circles (filled) 686411
Circles (outline) 649668
Triangles (outline) 472213
Triangles (filled) 1379234
Rounded rects (outline) 267230
Rounded rects (filled) 4434364
Done!

ILI9341 Test!
Display Power Mode: 0x9C
MADCTL Mode: 0x48
Pixel Format: 0x5
Image Format: 0x9C
Self Diagnostic: 0x0
Benchmark Time (microseconds)
Screen fill 1194090
Text 83368
Lines 809350
Horiz/Vert Lines 98596
Rectangles (outline) 63663
Rectangles (filled) 2479508
Circles (filled) 400018
Circles (outline) 352556
Triangles (outline) 256761
Triangles (filled) 834986
Rounded rects (outline) 150474
Rounded rects (filled) 2714640
Done!

ILI9341_t3 Test!
Display Power Mode: 0xCE
MADCTL Mode: 0x24
Pixel Format: 0x2
Image Format: 0xCE
Self Diagnostic: 0xE0
Benchmark Time (microseconds)
Screen fill 280114
Text 19429
Lines 73327
Horiz/Vert Lines 23146
Rectangles (outline) 14671
Rectangles (filled) 581718
Circles (filled) 95539
Circles (outline) 95510
Triangles (outline) 17807
Triangles (filled) 197552
Rounded rects (outline) 39902
Rounded rects (filled) 637639
Done!
 
Did you try with the reset line installed and used? As I mentioned, I had better luck with the 2.2" when I did that earlier. Maybe later I will tyr to hook it back up and see. My guess is that it is an initialization timing issue...
 
Did you try with the reset line installed and used? As I mentioned, I had better luck with the 2.2" when I did that earlier. Maybe later I will tyr to hook it back up and see. My guess is that it is an initialization timing issue...

Kurt, thanks for your time. I did try the reset line, see the code section of my last post. I seem to have got it working now but I had some intermittent issues. May have been a breadboard issue as I stripped it all down and rebuilt it and it seems fine now.

Can you look at my last post and see if I have it correct with regard to the reset?
 
ILI9341_t3: YFY! It works. Speeding up the LCD text draws was my next task and Boom! It's done with no effort with Paul's library. Thanks, anyone who contributed. I'm using a T3 with the 2.3" color LCD over SPI. It was sad how slow it ran with the Adafruit driver, about 1/3 second to redraw about half the screen with medium size text. Now, 50mS.

Next up is to get decent fonts up instead of the "minecraft" 5x7 horror. I see several projects for this but everything I've tried so far requires more Arduino/T3/C brains or less lazyness on my part. There is Adafruit_mfGFX from pkourany (https://github.com/pkourany/Adafruit_mfGFX_Library), and ILI9341_due from marekburiak with a port of gText and some fast SPI DMA drivers for Arduino Due (http://marekburiak.github.io/ILI9341_due/). And gText for Arduino itself. Then I see comments on this forum about some work on fonts, how far has that gone? I've tried the options I've mentioned but nothing just builds for the T3 with teensyduino 1.20. What thinks ye the best place to start?
 
Text overwrite problem

Hi all -
It appears there is a problem with text overwrite - if the background is transparent, then the old text is not overwritten properly. If you do set a separate text BG color, then things work as expected. The problem looks to be in drawChar, the "if (fgcolor == bgcolor)" code doesn't properly overwrite previous characters.

I made a quick small test program to confirm. The top line will print correctly, the lower one will get mangled with the old and new text:

Code example here (Using Teensy 3.1, :


#include "SPI.h"
#include "ILI9341_t3.h"

// For the Adafruit shield, these are the default.
#define TFT_DC 9
#define TFT_CS 10



#define XOFFSET 10

// Use hardware SPI (on Uno, #13, #12, #11) and the above for CS/DC
ILI9341_t3 tft = ILI9341_t3(TFT_CS, TFT_DC);



void setup() {
tft.begin();
tft.fillScreen(ILI9341_BLACK);
tft.setTextSize(3);
tft.setRotation(3);


tft.setCursor(0, 0);
tft.setTextColor(ILI9341_WHITE,ILI9341_BLUE );
tft.println("Test Text");

tft.setCursor(0, 120);
tft.setTextColor(ILI9341_WHITE );
tft.println("Test Text");

delay(3000);

tft.setCursor(0, 0);
tft.setTextColor(ILI9341_WHITE,ILI9341_BLUE );
tft.println("Overwrite Text");

tft.setCursor(0, 120);
tft.setTextColor(ILI9341_WHITE);
tft.println("Overwrite Text");

Serial.begin(9600);

}


void loop(void) {

}

IMG_1239.JPG
 
I think you can say that is by design. That is as you said transparent. So it only sets the high bits and leaves the other bits as it found them. If you wish for it to be filled in, then set the background color. Hint, set the background color as it also speeds up the drawing.

Kurt
 
Hey Kurt - thanks for the quick reply -

Ah I get it - Since I am am using ILI9341_BLACK as my background, then when I set the text color I should do it this way:

tft.setTextColor(ILI9341_WHITE,ILI9341_BLACK);

Ok that works -
 
Last edited:
ILI9341 not working with color display, Teensy3.1 + purple board

Sorry to annoy you guys, this must be really, really silly but I can't get this to work.
I am trying the optimized library with the color display, teensy 3.1 and the purple board.

The display is lit, but it does not show anything.

This is what I see from the serial port

ILI9341 Test!
Display Power Mode: 0x0
MADCTL Mode: 0x0
Pixel Format: 0x0
Image Format: 0x0
Self Diagnostic: 0x0
Benchmark Time (microseconds)
Screen fill 280110
Text 19592
Lines 73325
Horiz/Vert Lines 23153
Rectangles (outline) 14667
Rectangles (filled) 581724
Circles (filled) 95757
Circles (outline) 96128
Triangles (outline) 17804
Triangles (filled) 197581
Rounded rects (outline) 40183
Rounded rects (filled) 637588
Done!

Any ideas where to look ? :(

I have two of the color display board, and I get the same values/messages from the serial port (including Display Power Mode 0x0 ...)

Thanks,
 
I am trying the optimized library with the color display, teensy 3.1 and the purple board.

The display is lit, but it does not show anything.

We can't see how you built this (and what went wrong). You must post photos if you want useful help.
 
Hi Paul, thank you.
everything works when I put it on the breadboard.

I might have done something wrong with the purple board... (i ordered a batch of 3 from OshPark, and 3 sets of components from DigiKey)
I will build another purple board, then keep debugging.
 
Paul,
the purple board has the RST signal connected to pin 8 of Teensy 3.1

So I guess I will have to add the RST control to the graphicstest program.

Sorry if this is already documented and I missed it.
May I recommend to update graphicstest in your library distribution with a comment about the Purple Board ? It may save some time to the next noob :)
 
Opps, yes, you're right. RST is connected to pin 8 instead of VCC.

Does adding this in setup(), before starting the display, make it work?

Code:
pinMode(8, OUTPUT);
digitalWrite(8, HIGH);
 
Hi Paul,
tried that, did not work.

This is how I made it work:

#define TFT_DC 9
#define TFT_CS 10
#define TFT_RST 8 // for the purple board

//#define TFT_DC 20
//#define TFT_CS 21

// Use hardware SPI (on Uno, #13, #12, #11) and the above for CS/DC
ILI9341_t3 tft = ILI9341_t3(TFT_CS, TFT_DC, TFT_RST);

Since I figured out that ILI9341_t3 had an optional RST argument.

Love your products, and the community that you are building around them.
 
I've added a link on the OSH Park shared PCB page, to this thread. Hopefully that will help anyone else who hits this issue.

I also created a revised copy of the PCB and ordered 3 from OSH Park.
 
Paul,
can you please check the DC plug of the PCB?
I did not ordered mines from Mouser, I already had some (maybe they are not the right ones).
When I connect the power, my walwart unit shorts. I am not an expert of pinouts of DC plugs though, again I may have the wrong ones - but I am suspicious because the pinout is identical ....
 
You are probably right. With the DC power jack from Mouser, the board shorts always. Terminal 1a and 3c from the power jack are connected together on the pcb. 1a is the tip of the plug and 3c is the sleeve.
 
Streaming Write

Hello,

I modified the T3 ILI9341 library a bit to support streaming writes. The purpose was to transfer as much data as possible over USB and stream it to the display.

Code:
void setup() {
  tft.begin();
  Serial.begin(115200);
  tft.setRotation(1);
  tft.setAddrWindow(0, 0, ILI9341_TFTHEIGHT - 1, ILI9341_TFTWIDTH - 1);
}

I added a new method streamWrite(uint16_t* Buffer, uint32_t Size) that uses the ILI9341 "Write Continue" command. This saves the call to set the window rect each time a new data block gets written to TFT memory.

Code:
void ILI9341_t3::streamWrite(uint16_t* Buffer, unsigned int Size) {
	SPI.beginTransaction(SPISettings(SPICLOCK, MSBFIRST, SPI_MODE0));
	writecommand_cont(0x3C); // Write Continue Command
	for (unsigned int i = 0; i < Size / sizeof(uint16_t); i++) {
		writedata16_cont(*Buffer++);
	}
	SPI.endTransaction();
}

Once the end is reached, the window rect will reset:

Code:
int i = 0;
void loop(void) {
  char Buffer[320];
  unsigned short int Count = Serial.readBytes(Buffer, 320);[COLOR="#FF0000"] // How much can/should we read at once here??[/COLOR]

  if (Count > 0) { [COLOR="#FF0000"]// Todo: Assumes Count % 2 == 0[/COLOR]
    i += Count;
    tft.streamWrite((uint16_t*) Buffer, Count);
  }
  if (i >= ILI9341_TFTWIDTH * ILI9341_TFTHEIGHT * 2) {
    i = 0;
    tft.setAddrWindow(0, 0, ILI9341_TFTHEIGHT-1, ILI9341_TFTWIDTH-1);
  }
}

You can see the streaming in action:


However there is an anoying issue. Everytime the TFT memory gets written, there is a brightness flickering (see video). I don't know how to get rid of it. Any ideas? There are about 5 frames per second, this is pretty slow but I think this is a limitation of the USB bus. I measured about 920KB/s USB transfer at maximum, this sould be close to maximum transfer rate.

Are there any suggestions for improvement? Should we add this "streamWrite" to the ILI9341 library?

Update:
Please also take a look at https://www.youtube.com/watch?v=gJxs3Rm0aTU It shows an µProcessor generated animated graph with refresh rate of 33 ms.
 
Last edited:
Hi Paul,

I am using a different display with my teensy3.1. My question is one of compatibility. I am using the 2.8" TFT from buydisplay.com http://www.buydisplay.com/default/spi-serial-2-8-inch-320x240-tft-lcd-display-module-ili9341-arduino-stm32

This display also runs off of the ILI9341 chip. as long as I wire it correctly I should be able to use the same code libraries right ?

Thanks,

Brian

Brian,
I am in the process of playing with one of the buydisplay.com displays. The ILI9341 library works great ! and after trying a dozen different SD cards, the SD library works also.. 1-2 mb SD cards appear to be the only cards I have found to work so far.

I have not gotten the the touch pad working with the XPT2046 driver IC or the built in font IC and Flash ram but still working on it.
Look forward to seeing if there are others out there trying their display and hopefully share there success stories.

I had issues for a few hours. I ordered a few of the 4-wire SPI and got one of them configured for 3-Wire SPI and nothing was working. After reading the manual and seeing the jumper settings I found I pick the wrong display to start with. So if you have issues, make to verify what version you received.

Best of luck.
 
Hi Guys,

I modified the optimized library to work with vertical text scroll, I needed this to make the library work with bitlash and other projects when I need the screen to act like a terminal.

You can select partial of the screen to be "scrollable" with the "setScrollTextArea" function.

I think I already saw someone here asking about it, so I'm sharing the modified version. Let me know if you find issues.

https://github.com/vitormhenrique/ILI9341_t3

Check it working:

 
@vitormhenrique

Thanks for the modified lib. I thought it had a couple of bugs
but I was coding badly......so far it works great. I'm using the
whole 320 x 240 for a scroll area with a black background and
yellow text to emulate a simple terminal and it looks great!
 
Last edited:
Thanks! :)

I actually will change and document some stuff, currently the enableScroll is setting the background area to whatever it has or a default black, i did not like that, because if you enable and disable the text scroll on the middle of your code it is going to "erase" your screen, or part of if.

You also need to set the scroll area before do anything with the screen, otherwise the text warp will be messed up.

I did not had many time to test it, and this was my first attempt to modify a library, so I bet there are few issues.

Let me know if you have any idea of improvements (horizontal scroll maybe?)

Vitor Henrique
 
using teensy 3.1, teensyduino 1.20, arduino 1.0.6

When the horizontal scroll area is exceeded sometimes a character is lost.
Check out my convoluted test code below. However I have tried many different scroll area
sizes with different background and text colors with different text sizes and this is
the only issue so far. Using the code below....when the number gets past 99
it works ok. For my simple terminal emulation projects this is not an issue and
I'm delighted with your modified lib. :)


#include "SPI.h"
#include <ILI9341_t3.h>

// For the Adafruit shield, these are the default.
#define TFT_DC 9
#define TFT_CS 10
#define baklite 23

// Use hardware SPI (on Uno, #13, #12, #11) and the above for CS/DC
ILI9341_t3 tft = ILI9341_t3(TFT_CS, TFT_DC);

// If using the breakout, change pins as desired
//Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC, TFT_MOSI, TFT_CLK, TFT_RST, TFT_MISO);

void setup()
{
//Serial.begin(9600);
pinMode(2,INPUT_PULLUP);
SPI.setSCK(14);
analogWrite(baklite,175);

tft.begin();
tft.setRotation(3);
tft.fillScreen(ILI9341_BLACK);
tft.enableScroll();
tft.setScrollTextArea(0,0,320,240,ILI9341_WHITE);
tft.setTextSize(3);
tft.setCursor(0, 0);
tft.setTextColor(ILI9341_BLACK);
}


void loop(void)
{
for(int i=0;i<1000;i++)
{
tft.print("This is line---");
tft.println(i);
delay(100);
while(!digitalRead (2));
}

delay(2000);
tft.fillScreen(ILI9341_BLACK);
tft.setCursor(0, 0);
}
 
Last edited:
Dear Forumers, would welcome suggestions on how to fix this.

I am using the Color Display with Paul's audio shield. Also, I am accessing correctly the optional EEPROM that I installed in the shield.
Everything seems to be working fine, but I hear an annoying buzz from the audio shield.

The buzz starts when I perform the first

tft.fillScreen(ILI9341_BLACK);

Per Paul's instructions, I am using the following settings for the color shield:

vvvvv
....
#define TFT_DC 20
#define TFT_CS 21
ILI9341_t3 tft = ILI9341_t3(TFT_CS, TFT_DC);

void setup() {
SPI.setMOSI(7);
SPI.setSCK(14);
tft.begin();

...
^^^^^^

The code below reads from EEPROM the different waveforms stored, displays them and plays them back in the color shield.
I get the expected behavior, except for the annoying buzzing.

***************************************************
Feb 7th 2015: hardware completed, experimented with ILI9341 graphics
Feb 14th 2015: display waveforms from ROM, play back through Audio Shield

****************************************************/

#include "Audio.h"
#include "SPI.h"
#include "ILI9341_t3.h"
#include "MIDI.h"
#include "Wire.h"
#include "flash_spi.h"
#include "SD.h"


#define FLASHSIZE 16777216
#define PAGE 256 //dimension of 1 EEPROM page (in bytes)

unsigned char buf2[PAGE]; // we are using this buffer for reading from the EEPROM
int16_t buf[PAGE];
int page = 0;

// Set DC and CS, no conflict with Paul's Audio Adapter
#define TFT_DC 20
#define TFT_CS 21

// Use hardware SPI and the above for CS/DC. Reset is tied to 3.3V, no need for a 3rd pin
ILI9341_t3 tft = ILI9341_t3(TFT_CS, TFT_DC);
uint16_t screenWidth, screenHeight;

//Audio Shield
float maxFREQ = 1200;

AudioSynthWaveform waveform1;
AudioOutputI2S i2s1;
AudioConnection patchCord1(waveform1, 0, i2s1, 0);
AudioConnection patchCord2(waveform1, 0, i2s1, 1);

AudioControlSGTL5000 audioShield;

void setup() {

// Needed when using ILI9341 with the audio shield
SPI.setMOSI(7);
SPI.setSCK(14);

// Set Up TFT Screen

tft.begin();

tft.fillScreen(ILI9341_BLACK); // reset screen
tft.setRotation(3); // Set orientation
tft.setTextSize(1);
screenWidth = tft.width();
screenHeight = tft.height();
tft.setCursor(0, 0);
// tft.setTextColor(ILI9341_YELLOW);

tft.setCursor(0, 0);
drawWaveBox(ILI9341_YELLOW);

// Initialize EEPROM
flash_init();

// Initialize Audio Shield
AudioMemory(18);
audioShield.enable();
audioShield.volume(.7);
// Arbitrary Waveform, this is where we play the waveforms from the EEPROM
waveform1.begin(0.45, 440, WAVEFORM_ARBITRARY);
}



void loop(void) {
int i;

page=0;

while(1) {
flash_read_pages(buf2, page, 1);
for (int i=0; i<PAGE; i++) {
buf = (int16_t) buf2;
}
drawWave(buf, page, ILI9341_RED);
waveform1.arbitraryWaveform(buf, 440);
delay(1000);
while(1);
drawWave(buf, page, ILI9341_BLACK);
page++;
if ((int) page / 16 == 16) page = 0;
}
}
 
Back
Top