Highly optimized ILI9341 (320x240 TFT color display) library

ILI9341_t3 inheritance from Adafruit_GFX

I've refactored the ILI9341_t3 library to inherit from Adafruit_GFX instead of Print on my fork here:
https://github.com/leighmurray/ILI9341_t3
I did this because the Adafruit_GFX_Button implementation in the ILI9341_t3.cpp file wasn't up to date, and it seemed to make more sense to make ILI9341_t3 inherit from Adafruit_GFX (given that so many of the ILI9341_t3 functions are direct copies from that library anyway) so that we will continue to benefit from any updates in the Adafruit_GFX library rather than having local copies of all their functions, and any class that relies on the display being an Adafruit_GFX object.
I did my best to make sure there were no breaking changes, but there might be if anyone was relying on the globally defined "WIDTH" and "HEIGHT" constants. There's also the teensy implementation of "drawCircleHelper" which would be nice to be merged into the Adafruit_GFX library if it is faster for devices other than Teensy, and then remove it from the ILI9341_t3 library.
Thoughts? I'd can submit a pull request if anyone agrees with this implementation moving forward.
 
Hopefully this will be an easy one....

I'm getting several low level errors trying to run demosauce.ino using a 2.8" TFT II9341 display

I have the Teensy 4.1
Arudino 1.8.12
Teensydunio 1.53

Library just pulled from here https://github.com/PaulStoffregen/ILI9341_t3

errors, and a whole bunch more...

Anyone have any ideas?



Code:
In file included from C:\Users\Administrator\Documents\Arduino\__Tone\__Tone.ino:32:0:

C:\Program Files (x86)\Arduino\libraries\ILI9341_t3/ILI9341_t3.h: In member function 'void ILI9341_t3::waitFifoNotFull()':

C:\Program Files (x86)\Arduino\libraries\ILI9341_t3/ILI9341_t3.h:305:9: error: 'KINETISK_SPI0' was not declared in this scope

    sr = KINETISK_SPI0.SR;
 
Sounds like you have an old version of that library on your machine. You should either remove it from your setup and use the one installed by Teensyduino, or should sync up again.

Or maybe see some additional information, like how you building... That is it should not be touching KINETISK_SPI0, there was code merged in during the T4 beta back in Aug 2019.

So something is wrong as for example it says that it is using KINESISK_SPI0 on line 305 of ILI9341_t3.h
https://github.com/PaulStoffregen/ILI9341_t3/blob/master/ILI9341_t3.h#L305
Which is:
Code:
boolean wrap; // If set, 'wrap' text at right edge of display
 
Feature request: setScrollArea

Hi,

I was wondering why both the default t3 (maintained by paul) and the t3n library dont have a setscrollarea routine available. The ili9341 allows the user to assign an area (based on Y coordinates) for scrolling. In our bat-detector project we use this for instance to show a scrolling waterfall graph whilst having above/below information on settings/user controls.
So everytime I follow the upgrades of these libraries I simply add the following code:
in ili9341_t3.h (or t3n.h)
in the public available routines add:
void setScrollarea(uint16_t top, uint16_t bottom);

in the ili9341_t3.cpp
void ILI9341_t3::setScrollarea(uint16_t bottom, uint16_t top)
{
beginSPITransaction(_clock);
writecommand_cont(0x33);
writedata16_last(bottom);
writedata16_last(ILI9341_TFTHEIGHT-top-bottom);
writedata16_last(top);
endSPITransaction();
}

This works completely as planned and allows the user to decide which part of the screen is allowed to scroll.

cheers
Cor
 
@CorBee - You can always submit a Pull Request to the libraries to have it incorporated.

The only interesting thing would be to to see what impact that would have if you are using a frame buffer in ili9341_t3n
 
Hi Kurt.

Thanks but I have no experience with pull requests and the extra work this demands. So Ive now changed the way I use this by simply creating a small routine that uses SPI to send the command with parameters to the ILI9341 and that works.

kind regards
Cor
 
I decided to adapt the class definition, that way I keep the current logic of the ILI9341_t3 library but can add additional functionality.

Code:
#ifndef _ILI9341_T3_EXT_H
#define _ILI9341_T3_EXT_H

#include "ILI9341_t3.h" //baseclass

class ILI9341_t3_ext: public ILI9341_t3 {
  public:
    ILI9341_t3_ext(uint8_t _CS, uint8_t _DC, uint8_t _RST, uint8_t _MOSI, uint8_t _SCLK, uint8_t _MISO); // constructor
    void setScrollarea(uint16_t top, uint16_t bottom);
  private:
};

//constructor points directly to default ILI9341_t3 
ILI9341_t3_ext::ILI9341_t3_ext(uint8_t _CS, uint8_t _DC, uint8_t _RST, uint8_t _MOSI, uint8_t _SCLK, uint8_t _MISO):
    ILI9341_t3(_CS, _DC, _RST, _MOSI, _SCLK, _MISO)
    {
      }

//additional routine to scroll pixels in an area
void ILI9341_t3_ext::setScrollarea(uint16_t top, uint16_t bottom)
{
	beginSPITransaction(_clock);
	writecommand_cont(0x33);
	writedata16_last(top); //section
	writedata16_last(ILI9341_TFTHEIGHT-top-bottom); //difference
	writedata16_last(bottom); //section 
	endSPITransaction();
}


#endif
 
I decided to adapt the class definition, that way I keep the current logic of the ILI9341_t3 library but can add additional functionality.

Code:
#ifndef _ILI9341_T3_EXT_H
#define _ILI9341_T3_EXT_H

#include "ILI9341_t3.h" //baseclass

class ILI9341_t3_ext: public ILI9341_t3 {
  public:
    ILI9341_t3_ext(uint8_t _CS, uint8_t _DC, uint8_t _RST, uint8_t _MOSI, uint8_t _SCLK, uint8_t _MISO); // constructor
    void setScrollarea(uint16_t top, uint16_t bottom);
  private:
};

...
For what it is worth, I added it to my ILI9341_t3n library. However I changed the name to: setScrollMargins as the Adafruit_ili9341 library has this functionality
and that is the name they gave it.

Warning: I did nothing to make it play nice with Frame Buffers.
 
Hi Kurt,

Thanks for adding it, Ill see if I can switch from ILI9341_t3 to t3n without much fuzz. As I am using a T3.6 that needs a lot of memory to keep data from incoming sounds buffers are not a real mandatory feature.

regards
Cor
 
I see you used the basic concept from Adafruit, that has a flaw according to me.
uint16_t middle = _height - top + bottom;

The display is sectioned in 3 parts, top, middle and bottom. The sum of top, middle and bottom should equal ILI9341_TFTHEIGHT.
In the example from adafruit this is not the case, if height is 320 and you want 40 pixels on the top and 50 at the bottom "still" section the middle will be 320-40+50= 330 ...
The correct calcuation is middle=height-top-bottom.
 
I see you used the basic concept from Adafruit, that has a flaw according to me.
uint16_t middle = _height - top + bottom;

The display is sectioned in 3 parts, top, middle and bottom. The sum of top, middle and bottom should equal ILI9341_TFTHEIGHT.
In the example from adafruit this is not the case, if height is 320 and you want 40 pixels on the top and 50 at the bottom "still" section the middle will be 320-40+50= 330 ...
The correct calcuation is middle=height-top-bottom.

They obviously meant to have brackets but forgot about them

uint16_t middle = _height - (top + bottom);
 
They obviously meant to have brackets but forgot about them

uint16_t middle = _height - (top + bottom);

Yep - and they had an open issue on it for awhile now... Pointed it out to LadyAda and she said will issue a PR so I did...
 
The issue was open for over a year, not many people use this feature so thats why it probably wasnt solved yet. Thanks for adding the PR at the adafruit-github.
 
Newbie trying to use your optimized ILI9341_t3 library....
Maybe the install instructions were not clear to me.

There exists already an Adafruit_ILI9341 library in my Arduino/libraries directory. So I moved it aside and, as per install directions, renamed ILI9341_t3 to Adafruit_ILI9341 and placed it in Arduino/libraries.

#include <Adafruit_ILI9341.h> was failing now — of course it cannot find it.

The install directions mentioned making sure Adafruit_ILI9341 directory contained Adafruit_ILI9341.cpp and Adafruit_ILI9341.

I took that to mean I should copy the original Adafruit_ILI9341 directory into the newly renamed Adafruit_ILI9341 (was ILI9341_t3) directory.

I did this and pulled both the .cpp and .h files out of the original Adafruit_ILI9341 (sub)directory so they were at the top level, peers of ILI9341_t3.cpp and ILI9341_t3.h.

At this point I ran into a couple issues:

1) the compiler claimed setFont() was not declared. To this issue I tried setFontAdafruit() in its place with no luck either.

Commenting setFont() out entirely and I ran into 2):

Code:
In file included from /Users/calhoun/Documents/Arduino/libraries/Adafruit_ILI9341/ILI9341_t3.cpp:51:0:
/Users/calhoun/Documents/Arduino/libraries/Adafruit_ILI9341/ILI9341_t3.h: In member function 'void ILI9341_t3::waitFifoNotFull()':
/Users/calhoun/Documents/Arduino/libraries/Adafruit_ILI9341/ILI9341_t3.h:458:9: error: 'KINETISK_SPI0' was not declared in this scope
    sr = KINETISK_SPI0.SR;
         ^

Which appears to be what a poster earlier in this thread saw as well.

Since I was on 1.5.3 of Teensyduino, I pulled down Beta 9 of 1.5.4.

And still no love.

Of course, as I say above, I may simply be misunderstanding the install directions for th optimized ILI9341_t3 library.
 
Note the ILI9341_t3 library is not 100% compatible with the Adafruit library. A lot of it is the same.
Also for which Teensy?

What you typically do, is to:
Replace the header file in your code:
So instead of: #include <Adafruit_ILI9341.h>
You do: #include <ILI9341_t3.h>

Also the class name and as such your constructor are different. Sometimes the easiest way to see the difference is to open up an example sketch in both projects, like graphictest.

So for example the tft object is defined with the different class name.
Code:
#define TFT_DC  9
#define TFT_CS 10

ILI9341_t3 tft = ILI9341_t3(TFT_CS, TFT_DC);

Note with this library on T3.x both the CS and DC pins must be hardware CS pins. On T4.x that is not a requirement.
 
Note the ILI9341_t3 library is not 100% compatible with the Adafruit library. A lot of it is the same.
Also for which Teensy?

What you typically do, is to:
Replace the header file in your code:
So instead of: #include <Adafruit_ILI9341.h>
You do: #include <ILI9341_t3.h>

Also the class name and as such your constructor are different. Sometimes the easiest way to see the difference is to open up an example sketch in both projects, like graphictest.

Thank you. I have the Teensy 4.0. I should have mentioned it.

I had done what you had suggested (#include <ILI9341_t3.h>, change the class name) but still ran into issues.

Your reply helped: suggesting that setting up the directory structure is not as esoteric as I had thought but rather that I should focus on how I am calling the new library.

While I thought I had dutifully followed graphicstest.ino I just now noticed that the include uses the double-quotes rather than the greater-than-less-than brackets.

#include "ILI9341_t3.h"

And that made the difference.

Now I just have to figure out how to get my custom font moved over to the new style your library expects....
 
For what it is worth, I have my own version of the library: ILI9341_t3n
https://github.com/KurtE/ILI9341_t3n

Which has some additional capabilities. This include using the ILI9341_t3 fonts and/or the GFX fonts. Which could make things easier.
The readme in the project tries to mention some of the different capabilities.
 
Thanks, Kurt.

I was able to get your library to compile. fillScreen() and fillRect() worked. Somewhere though, perhaps when my code called drawChar(), everything seemed to come to a halt. I am not sure why though.

You example for GFX fonts used println() rather than drawChar() and may have differed in other more subtle ways from my code. So I don't know why it was otherwise not a drop-in replacement for me.

I may have to look around for a way to go from bitmap—>ILI9341_t3 font or GFX—>ILI9341_t3 font.
 
Trying to create a 1-bit off-screen bit (canvas) for pre-rendering fonts but don't see support in either ILI9341_t3 or ILI9341_t3n

I tried declaring GFXcanvas1 but this required including AdafruitGFX.h ... and then an error about multiple declarations.

It made me think that in trying to mix AdafruitGFX and ILI9341_t3(n) I was tilting at windmills.

Anyone have a solution?
 
Sorry been busy on some other things.

I know that ILI9341_t3n should support all of the functions like drawChar in addition to to print and println as the class is derived from class Print.

Yes there can be subtle differences in things like alignment of characters. For example if you set the cursor to position 100, 100 where should the character start drawing? Should that be from the top of the character, or to where the part where most upper case characters go up and only some lower case characters extend below... And everyone has differences of opinion. So yes I can understand some subtle differences. Also there are some differences in font setups. Example with GFX, a font character may extend outside of what it's bounding box says.... Our code for this is different as I added support to be able to draw these fonts opaque, which I don't think Adafruit ever picked up.

There are several example sketches for this library showing the different types of fonts and the like the ILI_Ada_FontTest4

However as they are different code bases, there can be issues. Like is there a specific font that is not working or crashes, then maybe if you shared a simple sketch that shows it, along with font (or link to font), we might be able to take a look and see.

Sorry the libraries don't support the current Adafruit canvas stuff, that was added a lot later than when Paul forked the ILI9341_t3 library code, which the _t3n was derived from. However we do have frame buffer code. You can turn on a frame buffer and then all graphic primitives will draw to the underlying memory and then you can do an updateScreen call. There are also other code and tricks in all of this, like the ability to set a clip rectangle so only portions of screen touched...
 
I can try to create a sample project to show this issue — but what I found was that drawChar() appeared not to use the font specified in setFont(). It appears to always fall back to the default Adafruit font. Other calls like println() and drawFontChar() (?) did work as expected. Perhaps this is a known limitation since drawFontChar() appears to have been introduced in this library.

I like the idea of the frame buffer. Perhaps I can take advantage of that. I was hoping to create smaller (not full screen) bitmaps and blit from those. I suppose of you are exposing the frame buffer though I can try to write my own custom blitters.

Thanks for the help.
 
Hi,

Thanks to KurtE for adding the setscrollmargins function, this works completely as planned in our TeensyBat project. I am currently looking for an example that uses this library with a framebuffer located in PSRAM.

Looking through the examples I havent seen one (maybe missed it) but I saw the library now has a function:
Code:
void	setFrameBuffer(uint16_t *frame_buffer);
Would a standard PSRAM on the T4.1 be fast enough for this purpose ? If nobody has tested this I might dive into that and see what comes up.

regards
Cor
 
Back
Top