Highly optimized ILI9341 (320x240 TFT color display) library

I'm using the following functions from ILI9341_t3 in my code
Code:
   void writecommand_cont(uint8_t c);
   void writedata8_cont(uint8_t c);
   void writedata16_cont(uint16_t d);
   void writecommand_last(uint8_t c);
   void writedata8_last(uint8_t c);
   void writedata16_last(uint16_t d);

I modded the library and moved the functions from protected to public. I got this working by hacking the library but want to do it properly.

I've been trying to make my own class and inheriting from ILI9341_t3 but after a day and half I thought I'd ask here for help. Thanks.
 
Hi All...

K, so recently I've bitten the bullet to update Arduino IDE (to 1.6.5) and Teensyduino to 1.24... which kinda messed everything up..

But getting things working bit by bit, but after a gazillion years of messing around I can't get Adafruit SPI FRAM module working with the 'new' ILI9341_t3 library.

I was using the TFT library perfectly fine @120Mhz but have never been able to get it working with the FRAM. Pretty sure its a CS / transaction issue, I CAN get the SPI FRAM working if I use 72Mhz Optimised setting but this unfortunately does not allow for true hardware SPI as is needed for full speed ILI9341_t3 funcionality (critical for my application)

Anyone managed to get SPI FRAM working with this library yet?

Using the Capicitance Touch Screen sheild from Adafruit (with SD CARD). I am running SdFat library instead of the usual SD card library.

Thanks for any help (My code is 80,000 lines large so obviously can't post it here but I can try to strip back if absolutely necessary).

Cheers

Andy
 
can't get Adafruit SPI FRAM module working with the 'new' ILI9341_t3 library.

Maybe start a new thread about the FRAM.

A link to Adafruit's product page and tutorial and github library would be nice to include (saves me quite a bit of time and guesswork). Also consider a photo or diagram of how you've connected it.

Thanks for any help (My code is 80,000 lines large so obviously can't post it here but I can try to strip back if absolutely necessary).

If the library examples work alone, but not in combination with ILI9341_t3, then yeah, you'll need to put some work into trimming this down to a moderately sized (but complete) program to demonstrate the problem.

Of course, if any of the library's examples reproduce the problem, just mentioning which example to run is fine. A link to the code download or github page is good.
 
Playing with an ILI9341 based display at the moment, trying to get power consumption of the whole board I'm designing down.

A quick browse of the data-sheet yielded a sleep mode on the chip, which seems to drop power consumption quite significantly when not in use. (See pages 100 & 101 of the datasheet (http://www.adafruit.com/datasheets/ILI9341.pdf)).

I've added functions to the library for entering and exiting sleep mode; they're very simple.

Code:
	void enterSleepMode();
	void exitSleepMode();

Code:
void ILI9341_t3::enterSleepMode() {
	SPI.beginTransaction(SPISettings(SPICLOCK, MSBFIRST, SPI_MODE0));
	writecommand_last(ILI9341_SLPIN);
	SPI.endTransaction();	
}

void ILI9341_t3::exitSleepMode() {
	SPI.beginTransaction(SPISettings(SPICLOCK, MSBFIRST, SPI_MODE0));
	writecommand_last(ILI9341_SLPOUT);
	SPI.endTransaction();
}

The datasheet notes though "It will be necessary to wait 5msec before sending next to command, this is to allow time for the supply voltages and clock circuits to stabilize." (after issuing SLPIN command). How should this be dealt with in the library? Just a 5ms delay?

I've never submitted any additions to open-source libraries before, so I'm not sure what needs to be done to have these added to the official release? IE, what the usual process is for doing this sort of stuff.
 
Last edited:
Hiya, Thanks for that, very handy..

From my tests, it saves around 10mA (@~4.91v) which all adds up.. Currently, I just fade the Backlight down when inactivity detected (PIR) which scrubs serious amounts of juice, I must admit, when I first started using LCD / TFT screens I was amazed at how much energy the backlight consumes..

Thanks again for the effort!, all working great for me - All you need to do now is figure out the drawImage() function from the IlI9341_due library so I can draw full colour (565) bitmaps from PROGMEM, then i'll be even more happy ;)

Cheers

Andy (My original issue above still exists, but need to start a clear proggy to allow others to reproduce, for time being, stuck @72Mhz, but at least I can still work on my project with everything working)..
 
Added multi fonts and gradient fill

Hi all,
thanks so much for all the work done on this library, it has meant a big improvement to a couple projects for me. Just thought some folks might be interested in a few added functions I needed to pretty up my project, I've added reference to the Adafruit_mfGFX library so that you can create custom fonts and font sizes as described by pkourany. Also I got bored with a single coloured background so created a simple gradient function fillGrad() which fills the screen with a two colour gradient. Check it out here if you are interested... http://github.com/mahatmajman/ILI9341_t3.
Once again thanks for all your hard work Paul, the speed gains with this library are fantastic!
 
In search for a fast ILI9341 lib for Teensy that is (a) fast, (b) supports multiple fonts and (c) rotation, I tried several options but neither one works sufficiently.
Marek's Arduino derivative comes close and except for some (really unneccessary, to express it kind) signature changes to existing Adafruit methods, it works fine. Quite slow on Teensy, though, at twice the speed of an 8 MHz Arduino nano.

Paul's t3 lib is amazingly fast and "correct" but only supports the small standard font.
mahatmajman, your derivative comes closest, based on Paul's t3 lib, it is fast and the multi-font support works well... except: rotation does not work correctly:
If the display is rotated 90 or 270 degrees ("setRotation(1) resp. (3)"), the clipping is done wrong. Instead of clipping text at X position 320+, it is clipped at 240+.

Demonstration code attached.

All the ILI9341 libs really feel like loose ends, add a gradient here, change a signature there, remove Teensy SPI code here, add Due code there, attaching different font libraries etc.
As my application kept growing, which led me to Teensy in the first place, looking back I spent almost half the time on choosing and adapting an appropriate library while using wrappers where necessary to be prepared for the next surprise.
Anyway, thank you very much for your efforts, Teensy and ILI9341 represent an amazing environment!

Comparing Paul's t3 and mahatmajman's t3 lib, I noticed that the latter uses the Adafruit GFX as a base class instead of "Print".
Surprisingly, all other graphical functions I tried appear to work right.

Ideas, anyone?

Frank


Code:
#include <Wire.h>
#include <SPI.h>                   // required for TFTs


#define sclk 13  // Don't change
#define mosi 11  // Don't change
#define TFT_CS   10
#define TFT_DC   9
#define TFT_RST  8  // you could connect this to the Arduino reset


// use Paul Stoffregen -> mahatmajman T3 lib
#include <Adafruit_mfGFX.h>
//#include <Adafruit_GFX.h>
#include <ILI9341_t3.h>

ILI9341_t3 display = ILI9341_t3(TFT_CS, TFT_DC, TFT_RST);


void setup()
{
  display.begin();

  display.setRotation(3);
}


void loop() {
  // put your main code here, to run repeatedly:

  display.fillRect(0, 0, 320, 320, display.color565(0,0,0));
  delay(500);
  
  display.drawFastVLine(240, 0, 240, display.color565(255,0,0));
  display.setTextWrap(false);
  display.setTextColor(display.color565(0, 255, 0));

  display.setCursor(10, 10);
  display.println("hello, this is a very long text, hopefully long enough to reach the right border");

  display.setCursor(10, 220);
  display.println("this text should be printed in the lower part of the TFT");

  delay(1000);
}
 
A patch? No way, of course I will roll my own library fork ;-)
"t4" seems to be a good name to confuse everyone.

Seriously, I am looking into it but my C++ is rusty and i am new to the Arduino/Teensy library world.
The sample code might allow to dig up the root cause quickly for the people who know the ILI libs already, at least that was I was hoping for when posting.

Frank
 
Update:
When using Marek Buriak's Due variant on Teensy, activation of "ILI_USE_SPI_TRANSACTION" in the config file almost doubles the speed.
Still about 8 times slower than the Teensy optimized t3 libraries but now it is close to "good enough".

Frank
 
Got a complex question.

I want to run an ILI9341 and 50ish APA102's on a custom dashboard for my electric gocart. I would like to avoid bitbanging the APA's i'm actually doing a lot of other things so I would like to run it with SPI hardware, I don't want to tie up the micro. I was looking at FastLED but i'm not sure if there is a way to set a CS pin with FastLED and use a buffer like the 74AHCT125 to disable the lines going to the APA102's when they are not being written to.

I also don't know if the ILI9341 library will share the SPI pins well, I have some APA's on order but it will be about a week or 2 before they arrive and i'm just trying to get some PCB planning done while im waiting. I intend to add the APA's to my breadboard prototype but its nice to have a clear idea of what im doing before I add more wires to the spaghetti.

Here is a shot of my wip pcb. I have an ILI9341 w/touch, a VID6606 driving (2) VID29-02p steppers for the needles.
The outer rows of APA's will be the tick marks and the inner rows will be the numbers.

rEcfbdx.png


Im slowly adding things to the PCB(and learning Kicad since Eagle pcb limits suck...), doing code and building the gocart. The dash will be the last thing I finish but like all projects it takes planning.
 
Last edited:
YMMV - but I saw somebody ran at least 4 of the ILI9341's on the same SPI with unique CS's - so the pins do share to some devices using that driver.
 
Ok, think I have a plan for running the APA's and ILI9341 together.

I can use a 74AHCT125 as a switch, took this idea from a post I saw a while back about using the Adafruit RA8875 breakout.

When the CS for the LCD goes low the Outputs go high-impedance OFF-state and when CS goes High it enables the D and C outputs allowing me to send data to the APA's.

fdPu6vs.png


Edit....
R3 needs to be lower(500ish).
 
Last edited:
When the CS for the LCD goes low the Outputs go high-impedance OFF-state and when CS goes High it enables the D and C outputs allowing me to send data to the APA's.

Isn't the output enable of the 74AHCT125 an inverse input, so that the outputs are enabled with the OE_ input is LOW?
 
Isn't the output enable of the 74AHCT125 an inverse input, so that the outputs are enabled with the OE_ input is LOW?

Yes.
The CS goes low, which enables output 3 and R3 pull-up does its thing. Which in turn pulls inputs 10 and 13 high. Which disables outputs 8 and 11.

When CS goes high, output 3 is disabled. R4 pulls inputs 10 and 13 low causing outputs 10 and 13 to enable.


Edit..
I may end up adding some 10K pull-downs on 8 and 11 to prevent any funny business. Will see what happens when I get parts in.
 
Last edited:
Another strategy might involve using AND gates, like a 74HCT08.

If you run the ILI9341's CS signal to an input on each gate, then the gate's output (driving the LEDs) is forced low when the ILI9341 is selected. Otherwise, each gate passes the signal the signals on its other input. If you have more than two CS-based SPI device, you can combine their CS signals with an unused AND gate, so when either device is selected, the LEDs do not hear communication.

Using gates instead of tri-state buffers avoids the need for the resistors and the uncertainty of their slow timing. A gate will also drive the LED control signals with a strong signal at all times, rather than leave them floating, which could be more susceptible to noise (especially on a very long strip that acts like an antenna to relatively low frequencies).
 
Last edited:
However, beware trying this with a SD card.

Some SD cards require up to 8 extra clocks *after* chip select is de-asserted. Bill's SdFat library and my rewrite of the Arduino SD library do this. The old Arduino SD library does not, but even that is likely to change eventually.

With a SD card, you'd really need to dedicate a pin for actually enabling the buffers or gates, rather than trying to use the CS signals that already exist for the other device(s).
 
Another strategy might involve using AND gates, like a 74HCT08.

If you run the ILI9341's CS signal to an input on each gate, then the gate's output (driving the LEDs) is forced low when the ILI9341 is selected. Otherwise, each gate passes the signal the signals on its other input. If you have more than two CS-based SPI device, you can combine their CS signals with an unused AND gate, so when either device is selected, the LEDs do not hear communication.

Using gates instead of tri-state buffers avoids the need for the resistors and the uncertainty of their slow timing. A gate will also drive the LED control signals with a strong signal at all times, rather than leave them floating, which could be more susceptible to noise (especially on a very long strip that acts like an antenna to relatively low frequencies).

Ah yes, I seem to have forgotten KISS. Thanks Paul :)
 
Paul, what approach did you end up taking to encoding the fonts? Did you write it up anywhere? I glanced at the code briefly. I remember you writing that you were thinking of breaking the glyphs into rectangles and it looks like you may have done something like that...
 
So far, I'm just storing bitmaps with some extra bits to indicate duplicate lines. I put a few extra reserved bits into the format, so it can be gracefully extended later with other encoding schemes.

No, of course there's no documentation! Well, execpt the ASCII art in the generated code. ;)

But I will publish the source code for the software that generates the data from .TTF files, probably later today or tomorrow. It reads .BDF files. At least BDF is a really well documented and fairly human readable format.
 
I've committed the first, very rough font drawing code! It's all on github, if anyone wants to play with it now. (think: early adopter....)

arial18.jpg
(click for full size - enough to clearly see the TFT's pixels)

Code:
void setup() {
  tft.begin();
  tft.fillScreen(ILI9341_BLACK);
  tft.setTextColor(ILI9341_YELLOW);
  //tft.setTextSize(2);
  tft.println("Waiting for Arduino Serial Monitor...");
  Serial.begin(9600);
  //while (!Serial) ; // wait for Arduino Serial Monitor
  Serial.println("ILI9341 Test!"); 

  tft.setFont(Arial18);
  tft.println("Arial 18! {good}");
}

I'll be making numerous improvements and speedups, and probably bug fixes, over the next few days. I also plan to convert lots of fonts. Unlike mfGFX, the fonts aren't compiled into your sketch unless you actually use them, so the library can have a huge collection of fonts and only the ones you actually use are built into your program's code.

This font drawing support proper descenders (the letter "g" extends below the line), special tall symbols that extend above a capital letter, and even characters that extend backwards into the previously drawn character, as happens with large italic and ornate fonts. I'm pretty excited to finally have this working. It's still slow, doesn't yet work with more than 32 horizontal pixels, or clip vertically, but I'll be adding those features and improving performance soon.
 
Last edited:
Ah, this is exciting! Paul, thank you for the description.

Your initial scheme for encoding glyphs will be an excellent benchmark for anyone who wants to experiment with other compression schemes. A few ideas come to mind. I hope someone will be inspired...


  • Run-length encoding - encode each column as alternating transparent gaps and 'black' spans
  • Anti-aliasing - for the first and last pixel of each span, allocate a small unsigned integer indicating what percentage of the pixel is covered or equivalently, the alpha blending coefficient
  • Font bitmap compression - encode each glyph as a list of regions from a bitmap generated to have all the unique parts of the glyphs selected for the application; the naive encoding would have an image of each individual glyph; a more sophisticated encoding would have smaller parts such as stems, serifs, bowls, etc. and not have many copies of identical parts.
  • Bezier curves - Bitmaps represented with Bezier curves where each partial stroke is bounded by two curves. The curves are represented by forward difference parameters. For each pair of curves, the fill operation would be horizontal or vertical line segments bounded on either end by one of the curves.

By the way, years ago I was inspired by a paper (pdf) of John Hobby's on automatically generating 'hints' for outline fonts.

Don't know when I'll find time to work on this, but I'm slowly making progress converting my polling-based Morse code interaction library into a more efficient interrupt-based library.
 
Does anyone have any opinions about which fonts should come included with the library?

The good news is only the fonts you actually use get compiled into your program. The bad news is they do add quite a bit of bulk to the library's total file size. Each font takes about 600K to 800K, if I store a wide variety of sizes. I'd like to keep the entire library under 10 megabytes, so that probably means only a dozen or so fonts. Or maybe enlarging the download size is ok?

So far, I have 4: Arial, ArialBold, ArialItalic and ArialBoldItalic.
 
Does anyone have any opinions about which fonts should come included with the library?

The good news is only the fonts you actually use get compiled into your program. The bad news is they do add quite a bit of bulk to the library's total file size. Each font takes about 600K to 800K, if I store a wide variety of sizes. I'd like to keep the entire library under 10 megabytes, so that probably means only a dozen or so fonts. Or maybe enlarging the download size is ok?

So far, I have 4: Arial, ArialBold, ArialItalic and ArialBoldItalic.

- A short "how to add own fonts" could be included
- something like ds digital http://www.dafont.com/de/theme.php?cat=302
- nice monospaced + proportional fonts
 
Back
Top