ILI9488_t3 - Support for the ILI9488 on T3.x and beyond...

An hour of runtime on T$ 9488 DemoSauce :: Running with proper display colors - Anim count 182 - so it seems somehow 64M on T$ is a wrong number - and 30M is okay.

Trying now with 72M - either a better multiple or will fail same or worse? Started fine - looks good and faster than 30M … Anim# 60 and counting ...

@mjs513 - wonder what sketch is causing the 45K memory issue? Will look for github update with removed mic analog etc.

<edit>: Update here since this is not critical - sometime before 120 Anim#'s the T$ screen was white at 72 MHz - it made it over 90 before I walked away. So nearly functional - but not a simple multiple problem at/above where it works on T_3.6 @60M.
 
Last edited:
I just deleted mic/backlight lines and then changed analogRead(micpin) to random(0,1023). Works better and more consistently.

Know there was a lot of discussion on the other thread about SPI speed over 30M. I just couldn't find the right post - I remember it clearly, but too much over there.

@KurtE and @defragster,
I pushed up a new branch for framebuffer that I am working on. No DMA stuff though - do it need to get that incorporated as well for framebuffer to work?

EDIT: Just a major issue - Keep getting a 45K memory overflow using the ILI9488 480x320 display.

Sounds great - I noticed the new branch and did some command line stuff to make sure that everything was up to date in my fork... I usually try to avoid doing the GUI merge from branch as to avoid adding to history about the merge/sync...

Sort of hard core - Also sort of dangerous

Code:
C:\Users\kurte\Documents\Arduino\libraries\ILI9488_t3>git fetch upstream

C:\Users\kurte\Documents\Arduino\libraries\ILI9488_t3>git checkout Framebuffer-WIP
Switched to branch 'Framebuffer-WIP'
Your branch is up to date with 'upstream/Framebuffer-WIP'.

C:\Users\kurte\Documents\Arduino\libraries\ILI9488_t3>git reset --hard upstream/Framebuffer-WIP
HEAD is now at 25a31af Kludge for T3.6 (need real que size

C:\Users\kurte\Documents\Arduino\libraries\ILI9488_t3>git push origin Framebuffer-WIP --force
Everything up-to-date
Some of the things like --hard and --force will overwrite anything you might have checked out and changed... So I usually to be careful!

Memory overflow:
Two ways to fix:

For static allocation: DMAMEM uint16_t frame_buffer[320*240];

Or just let the dynamic memory work: which calls malloc(320*480*2);

Both allocate from the other memory area on current chip 256K (more or less) and on T4 B2 should be 512K (more or less).

Again with caveats of this upper memory has cache stuff enabled, which if we actually get to using DMA can cause problems where the DMA will go directly from the actual memory and not take what was written to it that is currently in cache... More in T4 thread. Also ways to say flush the cache now (on 16 byte boundaries), which is why you will see some of Frank's posting do something like: buffer_allocated = malloc(320*480*2 + 16);
and frame_buffer = (buffer_allocated +15) & 0xfffffff0;

Or some other way to make sure his frame buffer stated on 16 byte boundary.
 
@defragster - sounds like you are having fun. Remember there were some problems at the higher speeds with SPI with the 1052. Really wish I could find what Paul and manitou was writing about it.

@KurtE - thanks for the explanation - need to look at what its actual doing now that you explained it to me ;)
 
Good completion of Anim# 200 on T$ with :: ILI9488_SPICLOCK 36000000. Will have to compare numbers to see if that adds usably to perf numbers after it runs some more with no white out. [T_3.6 is good @ Anim# 2136]

Don't recall where valid clock rates of SPI fell on T$ - that goes to my 'speed' note before. And not sure what clock results from given request, it scales down in code on T_3.x's. Odd T_3.6 at 60M okay - maybe the T$ intra-transfer timing triggers something - and maybe just in one transition case?

And anything 1052 is subject to change with 1062 as it does I/O faster and the memory map will double and shift.

It is good that it is working, and at reasonable speeds. Showing the one SPI clock by the other shows which tasks are SPI xfer bound to some degree.

I see 2nd branch for RAM hogging buffer version is open - have not looked at that. @mjs513 - seems you ran the DemoSauce I posted that you updated with mic removal that helped T_3.6 display? Hope that makes it to github.
 
@KurtE and @defragster

Ok commented out DMAMEM and setFrameBuffer and ran my digitizer sketch (usbhost_view.ino, just my test version) did something but the screen updates aren't right.

Kurt - what did you mean "Or just let the dynamic memory work: which calls malloc(320*480*2);" setFrameBuffer wants frame_buffer specified. Think I am confused and don't want to go down the wrong path until I know I am on the right path :) I know makes no sense. Think I am just tired
 
Hi @mjs513 - the setFrameBuffer allows you to specify a frame buffer memory to use.

If you have not done so and do the useFrameBuffer(true)

Call, and no buffer has been specified, the code will call off to malloc to allocate it.

Currently the heap is fully contained in that second memory (same space as DMAMEM...)
I get confussed on which memory name is which...
But the configure_cache function in startup.c - sets up how the different parts of memory work. (I think the DMAMEM/malloc) stuff is the REGION(3) code...
 
defragster said:
I see 2nd branch for RAM hogging buffer version is open - have not looked at that. @mjs513 - seems you ran the DemoSauce I posted that you updated with mic removal that helped T_3.6 display? Hope that makes it to github.
Just updated both branches with the updated demosauce sketch
 
Hi @mjs513 - the setFrameBuffer allows you to specify a frame buffer memory to use.

If you have not done so and do the useFrameBuffer(true)

Call, and no buffer has been specified, the code will call off to malloc to allocate it.

Currently the heap is fully contained in that second memory (same space as DMAMEM...)
I get confussed on which memory name is which...
But the configure_cache function in startup.c - sets up how the different parts of memory work. (I think the DMAMEM/malloc) stuff is the REGION(3) code...

Thanks Kurt. That's exactly what I did. Now that I know I didn't mess that up I must have not incorporated something correctly. tft.print's work fine but when it updates the data (joystick in mycase) its jibberish. Now to go sort that out - think I am going to make coffee first:)

Hopefully will have that updated by tonight - after this going to punt on DMA at least for now.
 
@KurtE and @defragster

Ok. Issued fixed - forgot to change some lines to use write16bitcolor. Pushed an update to framebuffer branch - you can probably give digitizer4 and go and see if it works for you.

NOTE: Only tested on T$...…

@KurtE:
Assuming these types of lines need to be changed as well:
Code:
			writedata16_cont(palette[((*pixels)>>7)&0x1]);
			writedata16_cont(palette[((*pixels)>>6)&0x1]);
			writedata16_cont(palette[((*pixels)>>5)&0x1]);
			writedata16_cont(palette[((*pixels)>>4)&0x1]);
			writedata16_cont(palette[((*pixels)>>3)&0x1]);
			writedata16_cont(palette[((*pixels)>>2)&0x1]);
			writedata16_cont(palette[((*pixels)>>1)&0x1]);
			writedata16_cont(palette[(*pixels++)&0x1]);
 
Pulled in master (un buff) DemoSauce and running on T_3.6 and T$ - does look better on T_3.6 with expected 'mic' data.

Set T$ SPI to 36 MHz - tried 48 and it also went white in some time.

Just did a replace of 9341_ for 9488_ in EXAMPLES folder - 107 occurrences. Worked for 'PictureEmbed' - with reset to #8.

It looks like this :: View attachment master_9488_t3_examples.zip
 
@defragster - added updated examples in the framebuffer branch - when we do the merge the master will update

@KurtE - tried running you clip test sketch but for some reason I can't get it to run. Can you give it a try... Probably not seeing something obvious.
 
Good work @mjs513 :) I'll switch to that branch assuming it is stable enough to work with. It seems like T$ Faults are not bugging you now?

@KurtE - you made a note about Updated Touch work? Is that represented in any of these examples?
 
Last edited by a moderator:
Hi @mjs513 and @defragster - sorry been playing around with some other stuff...

I hacked up the color display sketch that showed the different colors, to change every several second alternating between turning on/off useFrameBuffer...
Code:
//=============================================================================
//=============================================================================

#include <ILI9488_t3.h>
#include <ILI9488_t3_font_Arial.h>
#include <ILI9488_t3_font_ArialBold.h>
#define TFT_RST 8
#define TFT_DC 9
#define TFT_CS 10
ILI9488_t3 tft = ILI9488_t3(TFT_CS, TFT_DC, TFT_RST);
//=============================================================================
// Setup
//=============================================================================
void setup()
{
  tft.begin();
  tft.setRotation(3); // 180
  delay(100);

  tft.fillScreen(ILI9488_BLACK);
  delay(250);
  tft.fillScreen(ILI9488_RED);
  delay(250);
  tft.fillScreen(ILI9488_BLUE);
  delay(250);
  tft.fillScreen(ILI9488_GREEN);
  delay(250);
  tft.fillScreen(ILI9488_BLACK);


}

void drawColor(uint16_t x, uint16_t y, const char *psz, uint16_t color)
{
  tft.setFontAdafruit();
  tft.setTextColor(color);
  tft.setTextSize(2);
  tft.setCursor(x, y);
  tft.print(psz);
  tft.drawRect(x + 100, y, 50, 50, color);
  tft.fillRect(x + 110, y + 10, 30, 30, color);
  tft.drawLine(x + 100, y + 70, x + 200, y + 70, color);
  tft.drawLine(x + 220, y, x + 220, y + 70, color);
  tft.drawLine(x + 100, y + 70, x + 220, y, color);
  tft.drawCircle(x + 50, y + 50, 28, color);
  tft.fillCircle(x + 50, y + 50, 20, color);
  tft.setFont(Arial_12_Bold);
  tft.setCursor(x + 160, y + 50);
  tft.print(psz);
}


//=============================================================================
// Loop
//=============================================================================
bool use_frame_buffer = false;
void loop()
{
  tft.useFrameBuffer(use_frame_buffer);
  tft.setFont(Arial_18_Bold);
  tft.setCursor(0, 150);
  if (use_frame_buffer) {
    tft.fillScreen(ILI9488_GREENYELLOW);
  } else {
    tft.fillScreen(ILI9488_BLACK);
  }
  drawColor(0, 0, "Red", ILI9488_RED);
  drawColor(0, 80, "Green", ILI9488_GREEN);
  drawColor(0, 160, "Blue", ILI9488_BLUE);
  drawColor(0, 240, "White", ILI9488_WHITE);

  drawColor(240, 0, "Yellow", ILI9488_YELLOW);
  drawColor(240, 80, "Orange", ILI9488_ORANGE);
  drawColor(240, 160, "Cyan", ILI9488_CYAN);
  drawColor(240, 240, "Pink", ILI9488_PINK);
  if (use_frame_buffer) {
    tft.updateScreen();
    use_frame_buffer = false;
  } else {
    use_frame_buffer = true;
  }
  delay(2500);
}
Will take a look at the other test program and see what happens...
 
defragster said:
Good work @mjs513 I'll switch to that branch assuming it is stable enough to work with. It seems like T$ Faults are not bugging you now?
Well no, still getting faults - just try uncommenting one of the things I commented out as not working :(. Not going to really push it until I see the same behavior on new board.

@KurtE - you made a note about Updated Touch work? Is that represented in any of these examples?
Just as a side can't get touch working no matter what I tried. Have some tristate buffers coming that I am going to test.
 
Hi @mjs513 and @defragster - sorry been playing around with some other stuff...

I hacked up the color display sketch that showed the different colors, to change every several second alternating between turning on/off useFrameBuffer...
….
Will take a look at the other test program and see what happens...
Cool - glad I got it incorporated correctly. Do we the readcommand8 function?
 
@mjs513 - Made a few fixes - Did PR

Here is a quick and dirty update for the test program, so far specific to T4 (currently in breadboard)...
 
@KurtE - you think its ready to be merged into master branch?

EDIT: Just updated the master - the two branches should match.

EDIT2: Your test sketch now runs fine :)
 
Last edited:
Indeed the latest KurtE sketch runs fine T_3.6 on Teensy36 and T$!

Except I'm not seeing any buffering? What am I missing? I see all updates in real time and no diff if 'tft.updateScreen();' is removed?

Code:
//=============================================================================
//=============================================================================

#include <ILI9488_t3.h>
#include <ILI9488_t3_font_Arial.h>
#include <ILI9488_t3_font_ArialBold.h>


#ifdef __MK66FX1M0__
#define __C64__ 1
#else
#endif

// Connection konfiguration of ILI9341 LCD TFT
#if defined(__C64__)
#define SCK       14
#define MISO      39
#define MOSI      28
#define TFT_RST 255
#define TFT_DC 20
#define TFT_CS 21
ILI9488_t3 tft = ILI9488_t3(TFT_CS, TFT_DC, TFT_RST, MOSI, SCK, MISO );
#else
#define TFT_RST 8
#define TFT_DC 9
#define TFT_CS 10
ILI9488_t3 tft = ILI9488_t3(TFT_CS, TFT_DC, TFT_RST);
#endif
//=============================================================================
// Setup
//=============================================================================
bool use_frame_buffer = true;
void setup()
{
	while (!Serial && millis() < 4000 );
	Serial.println("\n" __FILE__ " " __DATE__ " " __TIME__);

	tft.begin();
	tft.setRotation(3); // 180
	delay(100);

	tft.fillScreen(ILI9488_BLACK);
	delay(250);
	tft.fillScreen(ILI9488_RED);
	delay(250);
	tft.fillScreen(ILI9488_BLUE);
	delay(250);
	tft.fillScreen(ILI9488_GREEN);
	delay(250);
	tft.fillScreen(ILI9488_BLACK);

	tft.useFrameBuffer(use_frame_buffer);

}

int ii = 0;
void drawColor(uint16_t x, uint16_t y, const char *psz, uint16_t color)
{
	static uint16_t cLast = ILI9488_WHITE;
	tft.setFontAdafruit();
	tft.setTextColor(color);
	tft.setTextSize(2);
	tft.setCursor(x, y);
	if ( 0 == ii % 10 ) tft.print(psz);
	if ( 1 == ii % 10 ) tft.drawRect(x + 100, y, 50, 50, color);
	if ( 2 == ii % 10 ) tft.fillRect(x + 110, y + 10, 30, 30, cLast);
	if ( 7 == ii % 10 ) tft.drawLine(x + 100, y + 70, x + 200, y + 70, color);
	if ( 4 == ii % 10 ) tft.drawLine(x + 220, y, x + 220, y + 70, color);
	if ( 5 == ii % 10 ) tft.drawLine(x + 100, y + 70, x + 220, y, color);
	if ( 6 == ii % 10 ) tft.drawCircle(x + 50, y + 50, 28, color);
	if ( 3 == ii % 10 ) tft.fillCircle(x + 50, y + 50, 20, cLast);
	tft.setFont(Arial_12_Bold);
	tft.setCursor(x + 160, y + 50);
	if ( 8 == ii % 10 ) tft.print(psz);
	if ( 9 == ii % 10 ) tft.fillCircle(x + 50, y + 50, 20, color);
	if ( 9 == ii % 10 ) tft.fillRect(x + 110, y + 10, 30, 30, color);
	cLast = color;
}


//=============================================================================
// Loop
//=============================================================================
void loop()
{
	tft.setFont(Arial_18_Bold);
	tft.setCursor(0, 150);
	if ( !(ii % 10) ) {
		if (use_frame_buffer) {
			tft.fillScreen(ILI9488_LIGHTGREY);
		} else {
			tft.fillScreen(ILI9488_BLACK);
		}
	}
	drawColor(0, 0, "Red", ILI9488_RED);
	drawColor(0, 80, "Green", ILI9488_GREEN);
	drawColor(0, 160, "Blue", ILI9488_BLUE);
	drawColor(0, 240, "White", ILI9488_WHITE);

	drawColor(240, 0, "Yellow", ILI9488_YELLOW);
	drawColor(240, 80, "Orange", ILI9488_ORANGE);
	drawColor(240, 160, "Cyan", ILI9488_CYAN);
	drawColor(240, 240, "Pink", ILI9488_PINK);
	delay(110);
	if ( !(ii % 10) ) {
		if (use_frame_buffer) {
			tft.updateScreen();
			use_frame_buffer = false;
		} else {
			use_frame_buffer = true;
		}
		tft.useFrameBuffer(use_frame_buffer);
		delay(2500);
	}
	ii++;
}
 
Last edited:
Is this a complete and good replacement to allow adjustment in ::

<edit> Opps - mixed TFT_metaphor
Compiled the 9341 DemoSauce for ili9341 and saw a break :( - fixed?


FOR 9341: ...\libraries\ILI9341_t3\ILI9341_t3.h
Code:
#if defined(__MK64FX512__) || defined(__MK66FX1M0__)
#if F_BUS >= 64000000
#define ILI9341_SPICLOCK 64000000
#define ILI9341_SPICLOCK_READ 4000000
#else
#define ILI9341_SPICLOCK 30000000
#define ILI9341_SPICLOCK_READ 2000000
#endif
#elif defined(__IMXRT1052__) || defined(__IMXRT1062__)  // Teensy 4.x
#define ILI9341_SPICLOCK 36000000
#define ILI9341_SPICLOCK_READ 4000000
#else
#define ILI9341_SPICLOCK 30000000
#define ILI9341_SPICLOCK_READ 2000000
#endif

for 9488: ...\libraries\ILI9488_t3\ILI9488_t3.h
Code:
#if defined(__MK64FX512__) || defined(__MK66FX1M0__)
#if F_BUS >= 64000000
#define ILI9488_SPICLOCK 64000000
#define ILI9488_SPICLOCK_READ 4000000
#else
#define ILI9488_SPICLOCK 30000000
#define ILI9488_SPICLOCK_READ 2000000
#endif
#elif defined(__IMXRT1052__) || defined(__IMXRT1062__)  // Teensy 4.x
#define ILI9488_SPICLOCK 36000000
#define ILI9488_SPICLOCK_READ 4000000
#else
#define ILI9488_SPICLOCK 30000000
#define ILI9488_SPICLOCK_READ 2000000
#endif
 
Last edited:
@mjs513 - did you edit this into my post #37?
"EDIT: @KurtE - Did a little debugging by recreating the sketch piecemeal. The problem looks like it is in writeRectNBPP when using 2 and 4bits. 8 and 1bit rect's work, I think. I can't think of what the problem could be with the function."
 
@mjs513 - did you edit this into my post #37?
"EDIT: @KurtE - Did a little debugging by recreating the sketch piecemeal. The problem looks like it is in writeRectNBPP when using 2 and 4bits. 8 and 1bit rect's work, I think. I can't think of what the problem could be with the function."

No - I had edited that into the previous post #36? I was curious how it got there.

@defragster - just fixed it...
 
Last edited:
@KurtE and @defragster

Just pushed one more change to the master branch - hardcoded SPI0 for Teensy LC in readReact(….).

Ok, what's next on the list for the 9488?
 
@mjs513 and @defragster - Actually FB does not work on T4 B1 :( :eek:

When you tried putting DMAMEM on and it said did not fit in RAM... Should have been a clue to all of us...

Tried that again here and it failed, so removed, did simple test program:

Code:
//=============================================================================
//=============================================================================

#include <ILI9488_t3.h>
#include <ILI9488_t3_font_Arial.h>
#include <ILI9488_t3_font_ArialBold.h>
#define TFT_RST 8
#define TFT_DC 9
#define TFT_CS 10
//DMAMEM uint16_t frame_buffer[ILI9488_TFTWIDTH*ILI9488_TFTHEIGHT];

ILI9488_t3 tft = ILI9488_t3(TFT_CS, TFT_DC, TFT_RST);
//=============================================================================
// Setup
//=============================================================================
void setup()
{
  tft.begin();
//  tft.setFrameBuffer(frame_buffer);
  tft.setRotation(3); // 180
  delay(100);

  tft.fillScreen(ILI9488_BLACK);
  delay(250);
  }
//=============================================================================
// Loop
//=============================================================================
void loop()
{
  tft.useFrameBuffer(false);
  uint32_t start_time = millis();
  tft.fillScreen(ILI9488_BLACK);
  tft.fillScreen(ILI9488_RED);
  tft.fillScreen(ILI9488_GREEN);
  tft.fillScreen(ILI9488_BLUE);
  tft.fillScreen(ILI9488_WHITE);
  tft.fillScreen(ILI9488_YELLOW);
  tft.fillScreen(ILI9488_ORANGE);
  tft.fillScreen(ILI9488_CYAN);
  tft.fillScreen(ILI9488_PINK);
  uint32_t non_frame_buffer_time = millis() - start_time;
  delay(250);
  tft.useFrameBuffer(true);
  start_time = millis();
  tft.fillScreen(ILI9488_BLACK);
  tft.fillScreen(ILI9488_RED);
  tft.fillScreen(ILI9488_GREEN);
  tft.fillScreen(ILI9488_BLUE);
  tft.fillScreen(ILI9488_WHITE);
  tft.fillScreen(ILI9488_YELLOW);
  tft.fillScreen(ILI9488_ORANGE);
  tft.fillScreen(ILI9488_CYAN);
  tft.fillScreen(ILI9488_PINK);
  tft.updateScreen();
  uint32_t frame_buffer_time = millis() - start_time;
  delay(250);
  tft.fillScreen(ILI9488_BLACK);
  tft.setTextSize(3);
  tft.setCursor(0, 130);
  tft.printf("Reg: %d\nFB: %d", non_frame_buffer_time, frame_buffer_time);
  tft.updateScreen();    
  delay(2500);
}
Which shows frame buffer not working:
Then used calculator: 320*480*2 = 307200 which does not fit in 256K...
 
@mjs513 and @defragster - Actually FB does not work on T4 B1 :( :eek:

When you tried putting DMAMEM on and it said did not fit in RAM... Should have been a clue to all of us...

Tried that again here and it failed, so removed, did simple test program:

……..
Which shows frame buffer not working:
Then used calculator: 320*480*2 = 307200 which does not fit in 256K...
Too bad - have to wait until B2 to test I guess? You know I forgot with that big of a screen would it even work on a T3.x?
 
There might be some other options, which may or may not be worthwhile...

With the ILI9341, I at one point tried it on an ESP32 chip and found that you could not allocate the frame buffer in one memory allocation. It required two (if memory is correct). So code working with frame buffer had to know where the break was and adjust...

Why I mention this is: program in last post if I add:
Code:
DMAMEM uint16_t frame_buffer[480*270];
uint16_t fb2[480*50];
It still compiles and runs. So Between the two it gets us the 480*320...
If the Beta 1 boards were going to ship I would say maybe worth it.

Also Still maybe points out we still need some way to access and use memory in both regions...

---

And/Or - Could do a version of the Frame buffer which the backing buffer is only a byte, and we store a color index into a color pallet.
We could either always assume that the low byte of color is the index... (Or could do this in some color state, tft.usePallet()...

And/or could have the code convert color to index, which for sure would be slower, but very little user code would change... We might have some issues with some primitives like Gradient fills...

I think Frank tried something like this...

Plus is, should be able to also work on T3.5/6. But not sure of any way to make Asynch work... Wish there was some DMA chain you could setup that would read from one memory, use it as index into some other memory to then transfer to SPI...
 
Back
Top