Playing around with yet another version of ILI9341_t3 library (ILI9341_t3n)

The problem we run into with the fonts is, they #include header files.

That is for example you use the fonts Ariel_bold, its header file starts off like:
Code:
#ifndef _ILI9341_t3_font_ArialBold_
#define _ILI9341_t3_font_ArialBold_

#include "ILI9341_t3.h"
So it includes the ili9341_t3 library, and you end up with lots of duplicates...

I could maybe should fix this case by including these font files as well, and Actually I do, but I renamed them, as having them in two different libraries with same name, sometimes it got the right one and other times not... But for other font's, like the ones you can get from Paul's github: https://github.com/PaulStoffregen/ILI9341_fonts

They are problematic, They start off with the same hard coded include: #include "ILI9341_t3.h"

At one point I suggested that maybe we could split off the font definition out of the main include file:
Code:
typedef struct {
	const unsigned char *index;
	const unsigned char *unicode;
	const unsigned char *data;
	unsigned char version;
	unsigned char reserved;
	unsigned char index1_first;
	unsigned char index1_last;
	unsigned char index2_first;
	unsigned char index2_last;
	unsigned char bits_index;
	unsigned char bits_width;
	unsigned char bits_height;
	unsigned char bits_xoffset;
	unsigned char bits_yoffset;
	unsigned char bits_delta;
	unsigned char line_space;
	unsigned char cap_height;
} ILI9341_t3_font_t;
Into it's own header file, that maybe again each ili93... like display driver would include, and/or maybe the font files don't reference a structure, but simply a set of bytes, and the internals to the display drivers could then cast...
 
Hi KurtE,

There are several SPI based LCDs that use almost identical setup and structure to the ILI9341; for example the ST7796S.

What is the practicality of seperating out the graphical and HAL layers from the device drivers and making the library "multi-use"?

Or is it more practical to fork the library and make the appropirate changes for a specific display?
 
Hello Kurt,

with new versions of SPIN and LI9341_t3n from GitHub I get following error message:

In file included from display_test.ino:8:0:
C:\Program Files (x86)\Arduino\hardware\teensy\avr\libraries\ILI9341_t3n-master/ILI9341_t3n.h: In member function 'uint32_t ILI9341_t3n::frameCount()':
C:\Program Files (x86)\Arduino\hardware\teensy\avr\libraries\ILI9341_t3n-master/ILI9341_t3n.h:354:32: error: '_dma_frame_count' was not declared in this scope
uint32_t frameCount() {return _dma_frame_count; }
^
Fehler beim Kompilieren.


This was the code to compile with Teensyduino 1.45 on Win10 for teensy 3.2, 24Mhz optimise speed
Code:
/***************************************************
  Display Test ILI9341 for teensy 3.2, 
 ***************************************************/

#include <Wire.h>
#include <SPI.h>
#include <SPIN.h>
#include <ILI9341_t3n.h>


#define TFT_DC  9
#define TFT_CS 10

ILI9341_t3n tft = ILI9341_t3n(TFT_CS, TFT_DC);      // display object

const byte HELLIGKEITOUT = 6;                       // PWM-PIN für Helligkeitssteuerung
uint8_t rotation = 3;                               // Displayorientierung 1 ist normal, 3 ist 180 Grad gedreht, init

void setup() {
  tft.begin();
  tft.fillScreen(ILI9341_BLACK);                    // Display löschen
  tft.setRotation(rotation);                        // Displayorientierung setzen (0 oder 180 Grad)
  pinMode(HELLIGKEITOUT, OUTPUT);                   // init PWM-Ausgang Helligkeitssteuerung
  analogWrite(HELLIGKEITOUT, 256);                  // PWM full
}

void loop(void) {
  tft.setTextSize(3);
  tft.setTextColor(ILI9341_WHITE);                    // Test columns
  tft.setCursor(0,50); tft.print("Test 1st column");
  tft.setCursor(5,90); tft.print("Test 6th column");
  tft.setTextSize(2);
  tft.setCursor(0,130); tft.print("Test from 1st column");
  tft.setCursor(5,150); tft.print("Test from 6th column");
  while(1);                                           // Lock out
}



Can you look please.
Thank you
Larry
 
Last edited:
Sorry,
I have not built for 3.2 for awhile now.

There were a few places where the #ifdef was not correct to exclude some frame buffer code from those boards like 3.2 which do not have enough memory for frame buffers...

Try syncing back up to the ili9341_t3n project.
 
one solution: library management with Git

with new versions of SPIN and LI9341_t3n from GitHub I get following error message:
This is why we always fork libraries critical to our project and then 'git clone' those forks into local working repos which are used to build our project. Then we are not at the mercy of updates which could unexpectedly change operation in a way that breaks our application. It puts us in the update driver seat. This doesn't directly address your question but it would prevent errors like the ones you mention from popping up at inopportune times. I'm just wrapping up an almost two-year long project and in the process of final documentation and then a Git "release". Then I can go catch all our forked libraries up to current versions for the next project... which might take a bit of doing. This project uses Teensy 3.2.

Also if you fork all libraries into your own Git account and clone from that, you can make library branches or roll back versions relatively easily if you find a new update has broken backwards compatibility. We've had to do that more than once on this project. But happily this approach has worked well.

SPIN and ILI9341_t3n look interesting. On Teensy 3.2 there is only one SPI instance... so I wonder why you are using SPIN with it.
 
Hi @bboyes - Sounds like you have been working on a pretty large project...

Yes if I were doing anything commercial I too would fork projects and keep versions that I used on a project, so I could selectively update and/or be able to go back to the sources that I used to release a project... But I am retired :D so I only do this for my own fun.

Why SPIN and ILI0341_t3n on T3.2 with only one SPI Instance? More back to history of this. These were originally done when I was doing testing for the Teensy 3.6 beta (and later 3.5 beta), which have more than one SPI instance, and I wanted to be able to test the other instances... I got tired of doing the approach of editing source code and change all instances of SPI to SPI1 or SPI2... So wanted a version of library that would work on all of them.

But at the time SPI and SPI1 and SPI2 were not derived from some common base class so I could not pass in pointers to which SPI object to use. They were all something like: spi_class, spi1_class, ... So I did a quick and dirty wrapper class SPIN, which first pass was real stupid, where all of the methods were virtual, and a created sub classes for each of the SPI objects, which each of the sub-classes called the underlying SPI. or SPI1. or ... functions, which worked for this purpose.
I also wanted to have some of the FIFO queue functions in here that Paul had put into the ili9341_t3 library as I was seeing versions of it popping up in several other libraries and wanted to not have to replicate them. Also again they may change depending on which object you are using, as SPI on 3.5/6 had different queue lengths depending on which SPI object you were using.

But then Paul later updated the I2C objects (Wire) to have one base class and be data driven, which I liked, so I redid my SPIN objects to do that, which worked well. Once that was working, we then moved these data objects (hardware) and code to use back into SPI, which now has must of the SPIN functionality. Actually I think it has some of the additional information like queue size still in tables, but may not yet use it. As for T3.2? I simply wanted to make sure everything works and if there are other features of the ili9341_t3n that the hardware could handle on T3.2 that you wish to use, you could.

So in a lot of ways, I would like to be able to remove SPIN and just use SPI, and may get there at some point, and maybe just have SPIN for FIFO handling..

Some of the things in the ili9341_t3n library that I don't think are yet in ili9341_t3 library? Some of these have (or had) PR requests back into main library but...

a) Can work using just one hardware CS pin (used on DC signal) - Needed on SPI1 on 3.6 as there was only 1 (unless you used SDCard adapter). Likewise you did not have to setup to use MISO pin (if you don't want to connect it up, some commands like readPixel and readRect won't work...

b) Frame buffer (The main thing you can not use as part of T3.2 as it does not have enough memory), and likewise the Asynchronous screen updates using DMA can not work either...

c) I integrated in some of the other Pull Requests that or issues I saw on the ili9341_t3 library that I don't believe ever made it into the mainline library. Things like:
1) being able to setup an offset and a clipping rectangle and have all of the primitives use them.
2) Opaque Text with fonts - Put support in to draw the characters with the background color set, which will set those bits not defined to background color in the same way the main font does... But I probably would not put this in to main one without clip rectangle as some of the font's define a large interline spacing which gets set to background color, which you may not want

I think many of the others were migrated back into ili9341_t3 library like drawRect with different pixel counts and some gradient fills and ...

Sorry for the long winded answer :D
 
Hi @mjs513 and @defragster and ...

Still not sure if should create new thread, or just resurrect one like this one...

@KurtE

Progress is still progress.

I found another ILI9341 library that has a ton of examples that look like a lot of fun. A couple work out of the box. But a couple I have questions on if I may. The sketch is calling writecommand and writedata from a function directly. What is the equivalent I can use?

EDIT: Never mind rolled my own...
I have it running now... Could be a little cleaner, but will push up changes.

As for writecommand and writedata, there are functions in the header file... Like writecommand_cont versus writecommand_last (likewise functions for writedata8_cont.... writedata16...)

@KurtE

Since we are beginning to digress from Bluetooth to Displays maybe its time to start a new thread on the changes to ILI9341 library?

Again not sure if this is the best place?

PacAman { [sp] github comment :) } works on FrankB's TFT C64/Teensy64 with T_3.6, using PS3 - with needed edits below.
I see PATIENCE allows it to connect - I was unplugging Dongle and retrying. Using the OLD MSI dongle as it was paired and the LED is on the wrong side to see blink.
Isn't this a Joystick game … buttons? - I compiled at 120 MHz ... doesn't help me play, even speed=SLOW., though I do okay in DEMO mode :)
Did anyone try VGA mode? I have that with FrankB's PCB here.
I personally have not tried VGA mode... I did awhile ago with Frank's board and his code worked then. But not sure if it makes sense for us to add it as an example app as it requires proprietary hardware to work.

Hi there. Can you share the ILI9341 library? Thanks.
Which one?
There is the Adafruit_ili9341 library which you can get a few different ways (our older version that Teensyduino installs) or from Arduino library manager.
ili9341_t3 - Installs with Teensyduino also up on github: https://github.com/PaulStoffregen/ILI9341_t3
my ili9341_t3n library which you can download from github: https://github.com/KurtE/ILI9341_t3n note it requires SPIN as well https://github.com/KurtE/ILI9341_t3n

@Frank B - Has his ili9341_dma that is up on github.

@KurtE and @defragster and others

In going through this https://github.com/Bodmer/TFT_ILI9341_ESP ILI9341 library there are some interesting functions that might be worth it to add to a ILI9341 library. Would simplify drawing strings:
Code:
           drawNumber(long long_num,int poX, int poY, int font),
		   drawNumber(long long_num,int poX, int poY),
           drawFloat(float floatNumber,int decimal,int poX, int poY, int font),
           drawFloat(float floatNumber,int decimal,int poX, int poY),
		   
		   // Handle char arrays
           drawString(const char *string, int poX, int poY, int font),
           drawString(const char *string, int poX, int poY),
           drawCentreString(const char *string, int dX, int poY, int font), // Deprecated, use setTextDatum() and drawString()
           drawRightString(const char *string, int dX, int poY, int font),  // Deprecated, use setTextDatum() and drawString()

		   // Handle String type
		   drawString(const String& string, int poX, int poY, int font),
		   drawString(const String& string, int poX, int poY),
           drawCentreString(const String& string, int dX, int poY, int font), // Deprecated, use setTextDatum() and drawString()
           drawRightString(const String& string, int dX, int poY, int font);  // Deprecated, use setTextDatum() and drawString()

What do you all think?
Maybe - My library has a lot of graphic primitives that I merged in earlier, which I think is still not merged into Paul's main one. Earlier I had Pull Requests outstanding to migrate some of the functionality into it like maybe support for other SPI ports. The ability to run without CS pin being a hardware CS pin...

Now back to playing
 
@KurtE

Just for reference I have been using your T4 WIP version for awhile now with the T3.6 and T4 and its working great. I have been playing around with those functions but I am a little handicapped in that I never worked with the displays before, only have a generic idea of how they work, steep learning curve for me. The one good thing about doing it is that I am learning.
 
@mjs513 - As I mentioned, I will probably go ahead and merge the current stuff into the master branch, and then maybe create a new WIP branch to try out some more DMA support.

I hear you about learning curve... I learned a lot on the T3.6 beta time frame, when I decided I wanted to try to get the stuff to work on all of the SPI Objects like SPI1 and SPI2.


Sometime I would like to get rid of the need for the SPIN library. I originally did it as the SPI, SPI1 and SPI2 were all different classes, so I had the virtual class to call off to the SPI code and SPI1 code and SPI2 code. I also had some table driven stuff in it which had things like which pins could be used for MOSI, MISO... But since then we rewrote SPI, with one class, table driven (same tables more or less)... The only thing left in SPIN that is not part of SPI is, some of the functions like:
waitFIfoNotFull, waitFifoEmpty...

Which I could simply move back into the ili9341_t3n library as that is what ili9341_t3 does...

Again now back to playing
 
VGA does require special hardware - would be cool if that became standard - except for the size of the display, no signs of port for T$ yet though.

That Pacman example was the first I looked at those libs: <ILI9341_t3n.h> and 'https://github.com/KurtE/SPIN'.
Took me a minute to figure out the pin movements to the Teensy64 board for alt MISO/MOSI and to find the extended constructor. Was this the necessary set of changes?
Indeed having SPIN internalized would be much cleaner and one less thing interposed to get working. Is it right that SPIN virtuality would be even more useful on T$ where the SPI has the FLEX option?

Code:
#define __C64__ 1

// Connection konfiguration of ILI9341 LCD TFT
#if defined(__MK66FX1M0__) 
[COLOR="#FF0000"]#if defined(__C64__) 
#define SCK       14
#define MISO      39
#define MOSI      28
#define TFT_RST 255
#define TFT_DC 20
#define TFT_CS 21
[/COLOR]#else
#define TFT_RST 8
#define TFT_DC 9
#define TFT_CS 10
#endif
#elif defined(__IMXRT1052__) || defined(__IMXRT1062__)
// On Teensy 4 beta with Paul's breakout out: 
// Using pins (MOSI, MISO, SCK which are labeled on Audio board breakout location 
// which are not in the Normal processor positions
// Also DC=10(CS), CS=9(BCLK) and RST 23(MCLK)
#define TFT_RST 23
#define TFT_DC 10
#define TFT_CS 9
#else
#error "This example App will only work with Teensy 3.6 or Teensy 4."
#endif

[COLOR="#FF0000"]#if defined(__C64__) 
ILI9341_t3n tft = ILI9341_t3n(TFT_CS, TFT_DC, TFT_RST, MOSI, SCK, MISO, &SPIN );
[/COLOR]#else
ILI9341_t3n tft = ILI9341_t3n(TFT_CS, TFT_DC, TFT_RST);
#endif

And in setup:
Code:
#if defined(__C64__) 
SPIN.setMOSI(MOSI);
SPIN.setMISO(MISO);
SPIN.setSCK(SCK);
#endif

And I have it with USB cord up so:
Code:
#if defined(__C64__) 
  tft.setRotation(0); // 0
#else
  tft.setRotation(2); // 180
#endif
 
Yes, have a post under way on other thread - speed change is good.
I saw and posted on the WINDOWS on Teensy - FrankB found it too - he noted the SPI RAM is not optimized.
 
@defragster - As I mentioned, would be great to get rid of need of SPIN. And earlier on, you HAD to include which SPIn object you were using. But later on I put in hack code to guess. That is if you specify the MISO, MOSI, SCK pins and they are not valid on the default SPIN object, it then walks the table to see if there is a SPI object that uses those pins, and then re-configures itself to use that SPI object.

As for SPIN and SPI using Flex IO, I have thought about it. It would be doable, But would slow things down. That is currently in SPIN, as SPI library is now one class to call, most of the code in SPIN compile away. That is:
Code:
class SPINClass {
public:
    // Initialize the SPI library
    inline void begin() {spi().begin(); }
    inline void usingInterrupt(uint8_t n) {spi().usingInterrupt((IRQ_NUMBER_t)n); }
    inline void usingInterrupt(IRQ_NUMBER_t interruptName) {spi().usingInterrupt(interruptName); }
    inline void notUsingInterrupt(IRQ_NUMBER_t interruptName) {spi().notUsingInterrupt(interruptName); }

    // Before using SPI.transfer() or asserting chip select pins,
    // this function is used to gain exclusive access to the SPI bus
    // and configure the correct settings.
    inline void beginTransaction(SPISettings settings)  {spi().beginTransaction(settings);}

    // Write to the SPI bus (MOSI pin) and also receive (MISO pin)
    inline uint8_t transfer(uint8_t data) {return spi().transfer(data);}
    inline uint16_t transfer16(uint16_t data) {return spi().transfer16(data);}
    inline void transfer(void *buf, size_t count) {spi().transfer(buf, count); }

    // After performing a group of transfers and releasing the chip select
    // signal, this function allows others to access the SPI bus
    inline void endTransaction(void)  {spi().endTransaction();}
    inline void end() {spi().end();}
...
Right now it simply inline calls the same functions through pointer to underlying object.

These would either have to convert back over to virtual function calls like it originally did or have more code in them like:

Code:
inline uint8_t transfer(uint8_t data) {return normal_spoi? spi().transfer(data) : flex_spi->transfer(data);}

At one point I thought about trying to make a version of the main SPI object that wrapped a flex_spi object, but again most of the commonly used functions are built to be as fast as possible:
Like the simple transfer:
Code:
	uint8_t transfer(uint8_t data) {
		// TODO: check for space in fifo?
		port().TDR = data;
		while (1) {
			uint32_t fifo = (port().FSR >> 16) & 0x1F;
			if (fifo > 0) return port().RDR;
		}
	}
So these functions would have to know it is flex IO and do something different.
 
Quick update: I went ahead and merged the T4 WIP branches into ili9341_t3n and SPIN, so can now use master branch
 
Just got ZIP of both those - will use that and see about T$ repro to match the Teensy64. It will be harder to wire than FrankB's dedicated PCB with #defines and software calls.

Funny - SPIN shows "Motivation: Teensy 3.4/3.5 Hardware" - and it was updated 12 minutes ago - but no code changes in 2 months - because the migrate to Master branch isn't a change :)

I finally grabbed two 10K resistors to test my ILI9488 for MISO Tri-State from this PJRC page - been sitting here …

<EDIT>: Something in Pacman is spewing '0' to SerMon.
Also this on Serial1?
HUB Callback (member)
status = 4
deferred getstatus, port = 2
HUB Callback (member)
status = 4
deferred getstatus, port = 2
HUB Callback (member)
status = 4
deferred getstatus, port = 2
HUB Callback (member)
status = 4
deferred getstatus, port = 2

And I see :: //#define USBHOST_PRINT_DEBUG
>> libraries\USBHost_T36\hub.cpp
Code:
void USBHub::status_change(const Transfer_t *transfer)
{
	println("HUB Callback (member)");
	println("status = ", changebits, HEX);
 
Last edited:
Just got ZIP of both those - will use that and see about T$ repro to match the Teensy64. It will be harder to wire than FrankB's dedicated PCB with #defines and software calls.

Funny - SPIN shows "Motivation: Teensy 3.4/3.5 Hardware" - and it was updated 12 minutes ago - but no code changes in 2 months - because the migrate to Master branch isn't a change :)

I finally grabbed two 10K resistors to test my ILI9488 for MISO Tri-State from this PJRC page - been sitting here …

<EDIT>: Something in Pacman is spewing '0' to SerMon.
Also this on Serial1?


And I see :: //#define USBHOST_PRINT_DEBUG
>> libraries\USBHost_T36\hub.cpp
Code:
void USBHub::status_change(const Transfer_t *transfer)
{
	println("HUB Callback (member)");
	println("status = ", changebits, HEX);

Interesting - when I hooked up my ILI9488 didn't have to do anything with the MISO - have to read your post again on that issue - remember you said you had to cut the MISO trace?

The spew comes from the KeyPadLoop function - there is a serial.println(buttons) line in it that you can comment out - I used that to verify the button mapping :)
 
@KurtE

Have a question for you - how the heck do you include GFX fonts with your library - couldn't figure that out. Keeps giving me an error on adafruit buttons....

EDIT: Will have to download your master branches and give those a test :) Later I am getting tired now.
 
@KurtE

Just downloaded the updated libraries and ran the graphicstest sketch with DC=9/CS=10 and DC=10/CS=9. In both cases it worked like a charm. So nice job - a lot of effort had to go into that one. Sorry I didn't test it earlier.
 
Confirmed the ILI9488 I got like Paul's doesn't tristate the MISO on the TFT half. So yes I needed to cut the trace for MISO on the Purple OSH board I used to connect it - making the TFT write only - unless the pin gets tristate in connection. Posted that on T4 beta thread.

Mike in post #169 is that 9341 or 9488 working now? Suppose on this thread it is 9341. Need to go read some old posts to see trouble note details, it seems we have 3 9488's between us - well we have a 4th rPi I know doesn't work with no D/C.
 
Thanks Mike, Actually was not too hard, other than remembering a few things...

All of the functions that output to the display go through the functions: writecommand_cont, writedata8_cont, writedata16_cont, writecommand_last, writedata8_last, ...

All of these functions call maybeUpdateTCR, where the TCR (Transmit Control Register) contains information about 8 bit versus 16 bit, which hardware CS pin (index) to use (We only have one) and if we should hold the CS as selected after the byte is output... I use this stuff for the obvious change 8 to 16 bit and it chooses if the DC should be asserted or not...

So now if we are not with DC on CS pin, it has to wait until current transmit completes, then change DC... Luckily pretty well contained. The only issue is if you had the CONT bit selected from before and then try to wait until queue empty, it hangs SPI. So needed to detect those cases and make sure it does not... Could simply not use the CONT bit, but then it might add in additional delays between bytes, so try to avoid that...
 
Mike - too many threads - not finding summary note on your issue T$ with 9341 or 9488 - or just programming?

Looking to put my OSH TFT PCB back on T$ breakout - remembering last time it turned it into a heater … assume it was not having valid VCC for display that time? Breakout brings 3v3 but not 5v ??? Without doing it that way I won't have USBHost connect.

Mike - that reminds me - when I hack the PJRC Purple OSH display board - I've been using 5V pin for power and they work - 9341 and 9488? It is supposed to have a supply built on it that probably takes it down to 3v3 - but I glossed over that ...

Hoping between Mike/Kurt/Frank a good shared PCB comes about for next T4 to break out all the bottom - would be really cool it if was PJRC certified like the last breakout … only more connectable.
 
@KurtE - can you point to a sample(s) in ...\libraries\ILI9341_t3n that will work and what wires to run into the T$ breakout from a breadboard?

I'm finding a mix of #define for pins … and pictureEmbed has a bad include
 
I have no breakout planned, the only board I'm awaiting to arrive soon is a board for the emulator.

That should be nice if anything glike your last work! - hopefully it works first time and fits the next T4 as needed. Did you see the Pacman port on USBHost thread? I'm playing - not very well yet ;) - that with Bluetooth PS3 joystick on Teensy64 v3 TFT board. It might work on the VGA C64 too but not tried it yet. Since I've not gotten to making my own boards - anything that brings USBHost out and other will be good to see how it is done. Really fun will be a good way to use those 8MB RAM chips you linked that I ordered.
 
Back
Top