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

Wow, thanks for the explanation and help. I haven’t dug into the code enough yet, and usually only really understand about 25% of most of this stuff anyway. I did not realize that it was reading, then writing the entire screen ( I’m assuming that’s basically what’s going on ) .

Thanks for the link on increasing the SPI buss speed, I actually almost did that yesterday, but I chickened out, as I read somewhere the max buss speed was 30000000 in a 3.2, so I elected to leave it there.

I have a few teensy 4s laying around, only reason I wasn’t using one of them was I thought the 3.2 woukd be enough, and the power consumption of the 4. But I’ll give both options a try tonight.
 
#elif F_CPU == 144000000
// config divisors: 144 MHz core, 48 MHz bus, 28.8 MHz flash, USB = 144 / 3
SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIV1(0) | SIM_CLKDIV1_OUTDIV2(0) | SIM_CLKDIV1_OUTDIV4(4); //SIM_CLKDIV1_OUTDIV2(0) war auf 2!!
SIM_CLKDIV2 = SIM_CLKDIV2_USBDIV(2);

Added that line to my set up()
Sped it up a lot! Though it’s still not where I would like, I think it’s fast enough to work for what I want. That said, I think I’m going to try out the teensy 4, looks like it will be more than enough.

Thanks for the help, and the great library!
 
A quick FYI - I was asked again about the quick and dirty gauge program I did, to show how one might do it.

Was asked if there was a way to get quicker movement of needle. The answer is to limit how much data has to be transferred.

So I did a quick and dirty version 2 of it, where the display needle code keeps bounding rectangle of where it will draw, and I union the old rectangle with the new rectangle and then set a clipping rectangle before calling updateScreen.

Note: I don't have the ability yet in updateScreenAsync to make use of clipping rectangle...

I also put in elapsed millis displays of the old run up and run down of tach along with the clipped output timings....
Code:
CS:10, DC:9 RST:8 MOSI:11, SCLK:13 MISO:12
_t3n::begin mosi:11 miso:12 SCLK:13 CS:10 DC:9
   T4 setup CS/DC

_t3n::begin - completed

center(160, 120) offset(40 0)
Press any key to continue

elapsed full updateScreen 3293
DMA Init buf size: 960 sub frames:80
elapsed full updateScreenAsync 3337
elapsed clip updateScreen 308
elapsed clip updateScreen 312
Press any key to continue
So about 10 times faster... You might want to give it a try...
 

Attachments

  • ILI9341_t3n_gauge_pictureEmbed-200110a.zip
    67.3 KB · Views: 75
A quick FYI - I was asked again about the quick and dirty gauge program I did, to show how one might do it.

Was asked if there was a way to get quicker movement of needle. The answer is to limit how much data has to be transferred.

So I did a quick and dirty version 2 of it, where the display needle code keeps bounding rectangle of where it will draw, and I union the old rectangle with the new rectangle and then set a clipping rectangle before calling updateScreen.

Note: I don't have the ability yet in updateScreenAsync to make use of clipping rectangle...

I also put in elapsed millis displays of the old run up and run down of tach along with the clipped output timings....
Code:
CS:10, DC:9 RST:8 MOSI:11, SCLK:13 MISO:12
_t3n::begin mosi:11 miso:12 SCLK:13 CS:10 DC:9
   T4 setup CS/DC

_t3n::begin - completed

center(160, 120) offset(40 0)
Press any key to continue

elapsed full updateScreen 3293
DMA Init buf size: 960 sub frames:80
elapsed full updateScreenAsync 3337
elapsed clip updateScreen 308
elapsed clip updateScreen 312
Press any key to continue
So about 10 times faster... You might want to give it a try...


Thanks Kurt - this is super helpful. Will keep following this thread for updates.
I'll try clean up the image to remove the background for a clean background, this way we will have less data to push in the screen update
 
Here are my test results with the SPI speed increased:
Code:
CS:10, DC:9 RST:255 MOSI:11, SCLK:13 MISO:12
_t3n::begin mosi:11 miso:12 SCLK:13 CS:10 DC:9
   T4 setup CS/DC
_t3n::begin - completed
center(160, 120) offset(40 0)
Press any key to continue
elapsed full updateScreen 2822
DMA Init buf size: 960 sub frames:80
elapsed full updateScreenAsync 2859
elapsed clip updateScreen 285
elapsed clip updateScreen 288

I still need to clean the image and also want to try add another smaller ring gauge next to it and see the how it performs
 
Whats the use of tft.setClipRect(); at the end of the last two for loops?
Code:
for (int percent = 75; percent >= 0; percent--) {
    int16_t min_x = g_needle_rect_min_x;
    int16_t min_y = g_needle_rect_min_y;
    int16_t max_x = g_needle_rect_max_x;
    int16_t max_y = g_needle_rect_max_y;
    tft.writeRect(g_offset_x, g_offset_y, 240, 240, (const uint16_t*)defi);
    drawNeedle(percent, COLOR_YELLOW);
    min_x = min(min_x, g_needle_rect_min_x);
    min_y = min(min_y, g_needle_rect_min_y);
    max_x = max(max_x, g_needle_rect_max_x);
    max_y = max(max_y, g_needle_rect_max_y);
    tft.setClipRect(min_x, min_y, max_x - min_x + 1, max_y - min_y +1);
    tft.updateScreen();
   [B] tft.setClipRect();[/B]
  }

I commented both of them out and almost doubled the speed:
Code:
CS:10, DC:9 RST:255 MOSI:11, SCLK:13 MISO:12
_t3n::begin mosi:11 miso:12 SCLK:13 CS:10 DC:9
   T4 setup CS/DC
_t3n::begin - completed
center(160, 120) offset(40 0)
Press any key to continue
elapsed full updateScreen 2822
DMA Init buf size: 960 sub frames:80
elapsed full updateScreenAsync 2860
elapsed clip updateScreen 165
elapsed clip updateScreen 160
Press any key to continue


Also, I'm unable to print a string in the last two for loops - I am trying to display the percent number right below the boost text. It counts up and down in the first two loops, but not in the ones where we use setClipRect (it never updates, just sticks to the last value which was 0)
 
setClipRect(); - clears out the clip rectangle. i.e. the whole screen is now available to be drawn to...

Note: the ways I am setting the clip rectangle just around the update screen, allows all of the graphic primitives to work on the frame buffer. If it is on while doing things like drawing the background image, those portions outside of the rectangle will not be updated, which could be fine, if you do all of the math up front to know where you will output... But I did this quick and dirty.

So to get the boost area to output, you might change the code to after you display the needle, you change the clip rectangle to the area where the boost is displayed and call updateScreen again, then clear the clip rectangle...
 
So do I need to set the clip, update the display and then clear it again as a sequence for each item on the display that I would like to clip?

I’ve tried many variations of setting the function but never get it to display the string
 
@joey120373

ran a couple tests timing tests on the first scroll area using a T3.6 (don't have a T3.2 handy) with the delay(100) removed:
Code:
[B]No-FrameBuffer:  3.316 seconds
With FrameBuffer: 0.918 seconds.[/B]
This is using SPI Clock of 30Mhz. As @Chris O. pointed out SPI clock is going to be the biggest driver. The obvious answer is that data transfer.

The way scroll text area works is that it first reads the pixels and then redraws the scrollarea so it is time consuming.

By way of comparison on a T4 running at 600Mhz and the default 30Mhz SPI clock:
Code:
[B]With FrameBuffer: 0.842 seconds.[/B]
with a 60 Mhz SPI clock
Code:
[B]With FrameBuffer: 0.432 seconds.[/B]

NOTE: If you can increase the SPI Clock for the T3.2 you should see a large improvement in screen update times.

Framebuffer example:
Code:
/***************************************************
  This is our GFX example for the Adafruit ILI9341 Breakout and Shield
  ----> http://www.adafruit.com/products/1651

  Check out the links above for our tutorials and wiring diagrams
  These displays use SPI to communicate, 4 or 5 pins are required to
  interface (RST is optional)
  Adafruit invests time and resources providing this open source code,
  please support Adafruit and open-source hardware by purchasing
  products from Adafruit!

  Written by Limor Fried/Ladyada for Adafruit Industries.
  MIT license, all text above must be included in any redistribution
 ****************************************************/


#include <SPI.h>
#include <ILI9341_t3n.h>
#include <ili9341_t3n_font_ComicSansMS.h>

// For the Adafruit shield, these are the default.
#define ILI9341_RST 8
#define ILI9341_DC 9
#define ILI9341_CS 10

// Use hardware SPI (on Uno, #13, #12, #11) and the above for CS/DC
ILI9341_t3n tft = ILI9341_t3n(ILI9341_CS, ILI9341_DC, ILI9341_RST);

// 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);
 
  tft.begin();
  tft.setRotation(3);
  tft.useFrameBuffer(true);

  tft.fillScreen(ILI9341_BLACK);
  while (!Serial) ; 
  tft.setTextColor(ILI9341_WHITE);  tft.setTextSize(1);
  tft.enableScroll();
  tft.setScrollTextArea(0,0,120,240);
  tft.setScrollBackgroundColor(ILI9341_GREEN);

  tft.setCursor(180, 100);

  tft.setFont(ComicSansMS_12);
  tft.print("Fixed text");

  tft.setCursor(0, 0);
  tft.useFrameBuffer(true);

  tft.setTextColor(ILI9341_BLACK); 
  uint32_t timer = millis();
  for(int i=0;i<20;i++){
    tft.print("  this is line ");
    tft.println(i);
    tft.updateScreen();
  }
  Serial.println(millis()-timer);

  tft.fillScreen(ILI9341_BLACK);
  tft.setScrollTextArea(40,50,120,120);
  tft.setScrollBackgroundColor(ILI9341_GREEN);
  tft.setFont(ComicSansMS_10);

  tft.setTextSize(1);
  tft.setCursor(40, 50);
  
  timer = millis();
  for(int i=0;i<20;i++){
    tft.print("  this is line ");
    tft.println(i);
    tft.updateScreen();
  }
  Serial.println(millis()-timer);


}



void loop(void) {


}

I cant seem to reproduce your results using a T4, I am running the code you posted, and when i use the default :
#elif defined(__IMXRT1052__) || defined(__IMXRT1062__) // Teensy 4.x
#define ILI9341_SPICLOCK 30000000u
#define ILI9341_SPICLOCK_READ 2000000
in the ILI9341_T3n .H file
I get ~1014 ms for the timer results,
When i increase the ILI9341_SPICLOCK to 60000000u, it does improve to
715 ms for each timing result, however i cant get the 432ms results You posted
using arduino v 1.8.9
and Teensyloader v 1.47

results are better than the T3.2, however i was realy hoping to duplicate the results you were able to get. Wondering if I'm still missing something?
Increasing the SPICLOCK to 80000000u, ( as posted elsewhere in this forum ) did not improve the numbers, nor did bumping up the SPICLOCK_READ.

Also, the T4 seems to have quit working all together when trying to run the graphics test example, The Serial still reports, but nothing on the TFT, even with the SPICLOCK settings back to default. Im hoping this is simply due to the fact that i am using jumper wires for the connections rather than a PCB ( My teensy3.2 is mounted on an adapter board for the adafruit display ).
Seems odd though that the scroll test works fine, where the graphics test is now inop.

Thanks, Joe
 
Got the graphics test working, I didn't notice the DC and CS pins are swapped in the example code, so that is working again.
 
Got the graphics test working, I didn't notice the DC and CS pins are swapped in the example code, so that is working again.
Just reran the sketch and got the exact same results as I Posted prior: 432Mhz using:
Code:
#elif defined(__IMXRT1052__) || defined(__IMXRT1062__) // Teensy 4.x
#define ILI9341_SPICLOCK 60000000u 
#define ILI9341_SPICLOCK_READ 2000000

I am using Arduinio IDE 1.8.9 with Teensduino 1.49. Try upgrading to 1.49 and see what happens. Not sure why you can not duplicate.
 
Quick update: to make it easier to try different SPI clock speeds, I now allow those two values to be passed in on the begin method. If they are not passed in, they will use the ones in the #defines mentioned above.

I also updated graphic test to remove the use of SPIN, plus put the DC=9, CS=10 as more people use it that way.

But on my T4 without changing begin you see: Note: I should comment out in the code some of the diagnostic prints at the top...
Code:
ILI9341 Test!

_t3n::begin mosi:11 miso:12 SCLK:13 CS:10 DC:9 SPI clocks: 30000000 2000000
   T4 setup CS/DC
_t3n::begin - completed
After TFT Begin
15
Display Power Mode: 0xFF
MADCTL Mode: 0x7F
Pixel Format: 0xFF
Image Format: 0xFF
Self Diagnostic: 0x7F
Benchmark                Time (microseconds)
Screen fill              205275
Text                     10298
Lines                    68189
Horiz/Vert Lines         17269
Rectangles (outline)     11083
Rectangles (filled)      421422
Circles (filled)         67787
Circles (outline)        56926
Triangles (outline)      16071
Triangles (filled)       145332
Rounded rects (outline)  24778
Rounded rects (filled)   464363

With: tft.begin(60000000u );
Code:
LI9341 Test!
_t3n::begin mosi:11 miso:12 SCLK:13 CS:10 DC:9 SPI clocks: 60000000 2000000
  T4 setup CS/DC
_t3n::begin - completed
After TFT Begin
15
Display Power Mode: 0x0
MADCTL Mode: 0x0
Pixel Format: 0x0
Image Format: 0x0
Self Diagnostic: 0x0
Benchmark                Time (microseconds)
Screen fill              102858
Text                     6650
Lines                    42973
Horiz/Vert Lines         8920
Rectangles (outline)     5779
Rectangles (filled)      211465
Circles (filled)         39006
Circles (outline)        37577
Triangles (outline)      9872
Triangles (filled)       76736
Rounded rects (outline)  15265
Rounded rects (filled)   235913
 
How safe is it to run the SPI clock at 60Mhz?

Not sure, it works on the one tried, which is a T4 plugged into breadboard, as well as the PJRC ILI9341 display plugged into same breadboard with jumper wires and it appears to be working.
Would be better with both plugged into circuit board with good contacts and short paths...

But your millage may differ.
 
Thanks guys, I will update my teensy loader,
I did find one interesting thing,
Running the same scroll test code, with the timing reports, I went ahead and swapped the DC and CS pins to match the call outs in the graphics test, where DC = 10 and CS = 9.

I was surprised to see an improvement in the reported loop times. It went from 715ms to 645 or so. On the T4 pinout, pin 10 is labeled as as the hardware CS pin for that spi port ?
Wasn’t expecting that.

I’ll update teensy loader, as well as the library, and try it again. As is I think perfectly workable for my needs but some extra overhead will be nice.
 
My results with DC=10 and CS=9



ILI9341 Test!

_t3n::begin mosi:11 miso:12 SCLK:13 CS:9 DC:10 SPI clocks: 60000000 2000000
T4 setup CS/DC

_t3n::begin - completed

After TFT Begin

13

Display Power Mode: 0x0

MADCTL Mode: 0x0

Pixel Format: 0x0

Image Format: 0x0

Self Diagnostic: 0x0

Benchmark Time (microseconds)

Screen fill 102485

Text 5110

Lines 32712

Horiz/Vert Lines 8439

Rectangles (outline) 5417

Rectangles (filled) 210256

Circles (filled) 33265

Circles (outline) 30030

Triangles (outline) 7927

Triangles (filled) 71847

Rounded rects (outline) 12729

Rounded rects (filled) 231703

Hit key to continue

My results after updating teensyduino and the ILI9341_t3n library.
Also able to duplicate the results on the scroll test mentioned earier.
Bad news, appear to have damaged the SPI port on my T4, After letting it run all night, before the updates, the screen was flickering white when i woke up. I installed the updates, and the program runns, but the screen stays white to flickering white. Screen tests ok with my T3.2, and I get the same results when loading example sketch using the ILI9341_t3 library, so i don't think the library update is the problem, think one of the hardware SPI pins on my T4 went bad.
Ill try moving the DC, RST and CS pins around and see if i can narrow it down, but ill have to wait till tomorrow after work to get another T4 set up.
 
...
Bad news, appear to have damaged the SPI port on my T4, After letting it run all night, before the updates, the screen was flickering white when i woke up. I installed the updates, and the program runns, but the screen stays white to flickering white. Screen tests ok with my T3.2, and I get the same results when loading example sketch using the ILI9341_t3 library, so i don't think the library update is the problem, think one of the hardware SPI pins on my T4 went bad.
Ill try moving the DC, RST and CS pins around and see if i can narrow it down, but ill have to wait till tomorrow after work to get another T4 set up.

I had an ili9341 go white - it was a display failure. YMMV: Mine came back closing J1 - AFAIK that bypasses the 5V part - so then it could only run at 3.3V?
 
I have 2 displays, first thing I did was swap out a known good one, no go.
Both displays work fine on my t3.2 board, so pretty sure one or more of the SPI pins 13-12 or 11 got damaged somehow, as I tried alternate pins for the DC, CS and reset.
 
Sorry not sure what is going on.

If it were me, I would double check all wiring...

I might check out wiring using the HiLow test that @defragster and I sort of kept evolving:
Code:
void setup() {
  Serial.begin(115200);
  while (!Serial && millis() < 4000 );
  Serial.println("Compile Time:: " __FILE__ " " __DATE__ " " __TIME__);

  testForShorts();
  
}

uint32_t cnt = 0;
void loop() {
  cnt++;
    allPinTest( cnt );
}

uint32_t pinLast[NUM_DIGITAL_PINS];
void allPinTest( uint32_t cnt ) {
  uint32_t ii, SET;
  Serial.print("PULLDOWN Start Vals:\n  ");
  SET = 0;
  Serial.print("PULLDOWN :: TEST to 3.3V\n  ");
  for ( ii = 0; ii < NUM_DIGITAL_PINS; ii++) {
    pinMode( ii, INPUT_PULLDOWN );
    delayMicroseconds( 5 );
    pinLast[ii] = digitalReadFast( ii );
    if (pinLast[ii]) {
      Serial.print("\nd#=");
      Serial.print( ii );
      Serial.print( " val=" );
    }
    Serial.print( pinLast[ii] );
    Serial.print(',');
  }
  Serial.println();
  Serial.println();
  while ( 1 ) {
    uint32_t jj, dd = 0, cc = 0, ee=4;
    cc = 0;
    for ( ii = 0; ii < NUM_DIGITAL_PINS; ii++) {
      jj = digitalReadFast( ii );
      if ( jj != pinLast[ii] ) {
        dd = 1;
        cc++;
        pinLast[ii] = jj;
        Serial.print("d#=");
        Serial.print( ii );
        if ( pinLast[ii] ) Serial.print( "\t" );
        Serial.print( " val=" );
        Serial.print( pinLast[ii] );
        Serial.print(',');
      }
      if ( cc > 1 && ee ) {
        Serial.println(">>> MULTI CHANGE !!");
        ee--;
      }
      if ( Serial.available() ) {
        while ( Serial.available() ) Serial.read();
        if ( 0 == SET ) {
          SET = 1;
          Serial.print("PULLUP :: TEST TO GND\n  ");
        }
        else {
          SET = 0;
          Serial.print("PULLDOWN :: TEST to 3.3V\n  ");
        }
        for ( ii = 0; ii < NUM_DIGITAL_PINS; ii++) {
          if ( 0 == SET )
            pinMode( ii, INPUT_PULLDOWN );
          else
            pinMode( ii, INPUT_PULLUP );
          delayMicroseconds( 20 );
          pinLast[ii] = digitalReadFast( ii );
          if (SET != pinLast[ii]) {
            Serial.print("d#=");
            Serial.print( ii );
            Serial.print( " val=" );
            Serial.println( pinLast[ii] );
          }
        }
      }
    }
    if ( dd ) {
      dd = 0;
      Serial.println();
      delay( 50 );
    }
  }
}

void testForShorts() {
  uint32_t ii;
  Serial.print("Quick Test for Shorts to adjacent pin");
  Serial.println("First pull pins down and see if the next one follows");
  for ( ii = 0; ii < NUM_DIGITAL_PINS-1; ii++) {
    pinMode( ii+1, INPUT_PULLDOWN );
    pinMode( ii, OUTPUT);
    digitalWrite(ii, HIGH);
    delayMicroseconds( 5 );
    if (digitalRead(ii+1)) {
      Serial.printf("%d:%d ", ii, ii+1);
    }
  }
  Serial.println("\n Now try Pull up and see if setting low follow");
  for ( ii = 0; ii < NUM_DIGITAL_PINS-1; ii++) {
    pinMode( ii+1, INPUT_PULLUP );
    pinMode( ii, OUTPUT);
    digitalWrite(ii, LOW);
    delayMicroseconds( 5 );
    if (!digitalRead(ii+1)) {
      Serial.printf("%d:%d ", ii, ii+1);
    }
  }
  Serial.println();  
}

If you have the begin method still trying to run at 60mhz, I would probably remove that....
 
Thanks KurtE I’ll give it a shot, I did try setting the clock back to 30000000 but no luck there either. I’m not too worried about it, I have 3 more T4s and just added another to my oshpark order yesterday.
Thanks
 
What's the method with this library to use custom front? Is there some type of font generator I can use online to create the required files?
I've searched the thread but it comes across as a rather complex process.
 
I actually came across FrankB's set of Google fonts. I tired one but when I use it, it does not come up on the display..
No errors when compiling (I did have to edit his .c and .h files a bunch though).

Attached for reference: View attachment Rubik_Regular.zip
 
In your .h try changing
Code:
ILI9341_fonts.h
to
Code:
#if __has_include(<RA8875.h>)
	#include "RA8875.h"
#elif __has_include(<ILI9488_t3.h>)
	#include "ILI9488_t3.h"
#elif __has_include(<ILI9341_t3n.h>)
	#include "ILI9341_t3n.h"
#elif __has_include(<ILI9341_t3.h>)
	#include "ILI9341_t3.h"
#elif __has_include(<ST7735_t3.h>)
	#include "ST7735_t3.h"
#elif __has_include(<HX8357_t3n.h>)
	#include "HX8357_t3n.h"
#endif
the ili9341_fonts.h is already in library. The header I gave you links the font back to the driver.
 
Back
Top