Teensy 4.0 First Beta Test

Status
Not open for further replies.
@KurtE, @defragster and others,

Got scrolling and the drawnumber, strings, etc incorporated. However, scrolling has become problematic - same issue as before until we did framebuffer. So guess framebuffer is next or is it a problem with readrect?

EDIT: Decided to play around with framebuffer but couldn't seem to get it working - first problem I ran into is if you use a frame_buffer of 480x320 you get a ram overflow, second problem I got it to run but not sure how much I needed to incorporate of the DMA stuff so put it away for now.
 
Last edited:
ili9488 working on T4 and T_3.6 (FB_teensy36 / C64) !!

ODD on T_3.6: Compiled at 180 MHz the graphicstest.ino completes faster than when set to 256 MHz? [sum us shows below]

Running :: ...\libraries\ILI9488_t3\examples\graphicstest\graphicstest.ino
As @mjs513 noted the first Groop test is flipped.

@mjs513:: Did you post 9488 BhudaBrot? … <edit> FOUND IT post 2186
@mjs513:: On the C64 I left the ili9341 in place on first upload and it worked as before - the 9488 code colors are wrong but the out of range drawing is ignored and it shows the connections are right.
Then I swapped on the 9488 having Made these adds to get C64. And for T4 had RST on #23 so that had to be included as below.
Code:
#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
// For the Adafruit shield, these are the default.
#define TFT_DC  9
#define TFT_CS 10

// Use hardware SPI (on Uno, #13, #12, #11) and the above for CS/DC
ILI9488_t3 tft = ILI9488_t3(TFT_CS, TFT_DC, 23);
#endif

Also something I always wanted was a single number SUM of the cumulative times:
T4b @600 :: TEST SUM us = 5855022
T_3.6 @180 :: TEST SUM us = 5553157
T_3.6 @256 :: TEST SUM us = 7104130

Here is the T4 I see:
Benchmark Time (microseconds)
Screen fill 735175
Text 16530
Lines 193125
Horiz/Vert Lines 62173
Rectangles (outline) 23995
Rectangles (filled) 1778031
Circles (filled) 231796
Circles (outline) 178960
Triangles (outline) 41924
Triangles (filled) 564861
Rounded rects (outline) 74359
Rounded rects (filled) 1954093

TEST SUM us = 5855022
 
Last edited:
ILI9488 Buddhabrot works T_3.6 and T4 with prior posted KurtE library.

Also note: Hoping T4 USB update not much more work before release? Prior post overnight run of T4_DemoSauce above HALTED when I closed SerMon ( updated TyCommander ) - usually it restarts when SerMon returns - but not this time?

Cycle Counts for one Buddhabrot exposure 'period' at 320x320 pixels (exclude screen update/Serial.prints:
T4 :: 423,713,072
T_3.6 :: 405,619,651
>> oppps:: Updated CycleCount to track exposures not some subsegment : T_3.6 uses FEWER cycles overall! - will have to watch on T4_1062 - this may be a memory placement or cache issue?

@mjs513 [others with Teensy64 or ili9488]
@mjs513 - no faults on T4 in breadboarded use of 9488.
Here is Buddhabrot ili9488 with USB show of cycle count with #ifdef edits for FrankB Teensy64 when compiled T_3.6:
Code:
// Buddhabrot
// j.tarbell   January, 2004
// Albuquerque, New Mexico
// complexification.net
//  http://www.complexification.net/gallery/machines/buddhabrot/appletl/index.html
// based on code by Paul Bourke
// astronomy.swin.edu.au/~pbourke/
// j.tarbell   April, 2005
//
/*
WRITE BMP TO SD CARD
Jeff Thompson
Summer 2012
Writes pixel data to an SD card, saved as a BMP file.  Lots of code
via the following...
BMP header and pixel format:
   http://stackoverflow.com/a/2654860
SD save:
   http://arduino.cc/forum/index.php?topic=112733 (lots of thanks!)
... and the SdFat example files too
www.jeffreythompson.org
*/
// Modified to run on Teensy
// MJS     March, 2019

#include <ILI9488_t3.h> // Hardware-specific library
#include <SD.h>
#include <SPI.h>
#include <font_Arial.h>

#ifdef __MK66FX1M0__
#define __C64__ 1
#else
#endif

// Connection konfiguration of ILI9341 LCD TFT
#if defined(__C64__)
//const int cardPin = BUILTIN_SDCARD; //18;          // pin that the SD is connected to (d8 for SparkFun MicroSD shield)
#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 ILI9488_RST 23 //23 for t4
#define ILI9488_DC 9
#define ILI9488_CS 10
ILI9488_t3 tft = ILI9488_t3(ILI9488_CS, ILI9488_DC, ILI9488_RST);
#endif

const int dim = 320;             // screen dimensions (square window)
int bailout = 200;         // number of iterations before bail
int plots = 10000;        // number of plots to execute per frame (x30 = plots per second)

// 2D array to hold exposure values
byte exposure[dim * dim];
int maxexposure;           // maximum exposure value
int time = 0;
int exposures = 0;

boolean drawing;

//bmp save
char name[] = "9px_0000.bmp";       // filename convention (will auto-increment)
const int w = dim;                   // image width in pixels
const int h = dim;                    // " height
const boolean debugPrint = true;    // print details of process over serial?

const int imgSize = w * h;
// set fileSize (used in bmp header)
int rowSize = 4 * ((3 * w + 3) / 4);  // how many bytes in the row (used to create padding)
int fileSize = 54 + h * rowSize;      // headers (54 bytes) + pixel data

unsigned char *img = NULL;

File file;
const int cardPin = 18;          // pin that the SD is connected to (d8 for SparkFun MicroSD shield)

uint32_t CCdiff;
void setup() {
	Serial.begin(115200);
	tft.begin();
	tft.setRotation(3);
	//tft.setFont(Arial_9);
	tft.fillScreen(ILI9488_BLACK);
	//tft.setTextColor(ILI9488_WHITE, ILI9488_BLACK);
	//tft.setTextDatum(TL_DATUM);
	while (!Serial && millis() < 4000 );
	Serial.println("\n" __FILE__ " " __DATE__ " " __TIME__);

	if ( ARM_DWT_CYCCNT == ARM_DWT_CYCCNT ) {
		ARM_DEMCR |= ARM_DEMCR_TRCENA; // T_3.x only needs this
		ARM_DWT_CTRL |= ARM_DWT_CTRL_CYCCNTENA;
		Serial.println("CycleCnt Started.");
	}

	// SD setup
	Serial.begin(9600);
	Serial.print("Initializing SD card...");
	if (!SD.begin(cardPin)) {
		Serial.println("initialization failed!");
		return;
	}
	Serial.println("initialization done.");
	CCdiff = ARM_DWT_CYCCNT;
}

void loop() {
	plotPlots();
	static int Dexposures = 0;
	time++;
	if (time % 30 == 0) {
		// show progress every 2 seconds or so...
		CCdiff = ARM_DWT_CYCCNT - CCdiff;
		findMaxExposure();
		renderBrot();
		//saveBMP();
		// show exposure value
		// show exposure value
		//tft.drawString("bailout:  ", 0, 0);
		//tft.drawNumber(bailout, 0, 25);
		//tft.drawString("exposures: ", 0, 40);
		//tft.drawNumber(exposures, 0, 60);
		//tft.drawNumber(exposures - Dexposures, 0, 80);
		//tft.drawString("Cycles: ", 0, 100);
		//tft.drawNumber(CCdiff, 0, 120);
		Serial.print("exposures: ");
		Serial.print(exposures);
		Serial.print("   delta exp: ");
		Serial.print(exposures - Dexposures);
		Serial.print("   Cycles: ");
		Serial.println(CCdiff);
		Dexposures = exposures;
	    CCdiff = ARM_DWT_CYCCNT;
	}

	if ( exposures > 10000000 ) {
		exposures = 0;
		memset(exposure, 0, sizeof( exposure ));
	}
}

void plotPlots() {
	float x, y;
	// iterate through some plots
	for (int n = 0; n < plots; n++) {
		// Choose a random point in same range
		x = randomFloat(-2.0, 1.0);
		y = randomFloat(-1.5, 1.5);
		if (iterate(x, y, false)) {
			iterate(x, y, true);
			exposures++;
		}
	}
}


//   Iterate the Mandelbrot and return TRUE if the point exits
//   Also handle the drawing of the exit points
boolean iterate(float x0, float y0, boolean drawIt) {
	float x = 0;
	float y = 0;
	float xnew, ynew;
	int ix, iy;

	for (int i = 0; i < bailout; i++) {
		xnew = x * x - y * y + x0;
		ynew = 2 * x * y + y0;
		if (drawIt && (i > 3)) {
			ix = int(dim * (xnew + 2.0) / 3.0);
			iy = int(dim * (ynew + 1.5) / 3.0);
			if (ix >= 0 && iy >= 0 && ix < dim && iy < dim) {
				// rotate and expose point
				exposure[ix * dim + iy]++;
			}
		}
		if ((xnew * xnew + ynew * ynew) > 4) {
			// escapes
			return true;
		}
		x = xnew;
		y = ynew;
	}
	// does not escape
	return false;
}

void findMaxExposure() {
	// assume no exposure
	maxexposure = 0;
	// find the largest density value
	for (int i = 0; i < dim; i++) {
		for (int j = 0; j < dim; j++) {
			maxexposure = max(maxexposure, exposure[i * dim + j]);
		}
	}
}


void renderBrot() {
	// draw to screen
	for (int i = 0; i < dim; i++) {
		for (int j = 0; j < dim; j++) {
			float ramp = exposure[i * dim + j] / (maxexposure / 2.5);

			// blow out ultra bright regions
			if (ramp > 3)  {
				ramp = 1;
			}
			uint16_t color = tft.color565(int(ramp * 128), int(ramp * 128), int(ramp * 255));
			tft.drawPixel(j + 80, i, color);

			//color c = color(int(ramp*255), int(ramp*255), int(ramp*255));
			//set(j,i,c);
		}
	}
}

double randomFloat(float minf, float maxf)
{
	return minf + random(1UL << 31) * (maxf - minf) / (1UL << 31);  // use 1ULL<<63 for max double values)
}

void saveBMP() {
	// if name exists, create new filename
	for (int i = 0; i < 10000; i++) {
		name[4] = (i / 1000) % 10 + '0'; // thousands place
		name[5] = (i / 100) % 10 + '0'; // hundreds
		name[6] = (i / 10) % 10 + '0';  // tens
		name[7] = i % 10 + '0';         // ones
		file = SD.open(name, O_CREAT | O_EXCL | O_WRITE);
		if (file) {
			break;
		}
	}

	// set fileSize (used in bmp header)
	int rowSize = 4 * ((3 * w + 3) / 4);  // how many bytes in the row (used to create padding)
	int fileSize = 54 + h * rowSize;      // headers (54 bytes) + pixel data

	img = (unsigned char *)malloc(3 * w * h);

	for (int i = 0; i < dim; i++) {
		for (int j = 0; j < dim; j++) {
			float ramp = exposure[i * dim + j] / (maxexposure / 2.5);

			// blow out ultra bright regions
			if (ramp > 3)  {
				ramp = 1;
			}
			//uint16_t color = tft.color565(int(ramp*128), int(ramp*128), int(ramp*255));
			//tft.drawPixel(j+80, i, color);
			img[(j * w + i) * 3 + 0] = (unsigned char)(int(ramp * 255)); // B
			img[(j * w + i) * 3 + 1] = (unsigned char)(int(ramp * 128)); // G
			img[(j * w + i) * 3 + 2] = (unsigned char)(int(ramp * 128)); // R

			// padding (the 4th byte) will be added later as needed...
			//color c = color(int(ramp*255), int(ramp*255), int(ramp*255));
			//set(j,i,c);
		}
	}

	// create padding (based on the number of pixels in a row
	unsigned char bmpPad[rowSize - 3 * w];
	for (int i = 0; i < sizeof(bmpPad); i++) {     // fill with 0s
		bmpPad[i] = 0;
	}

	// create file headers (also taken from StackOverflow example)
	unsigned char bmpFileHeader[14] = {            // file header (always starts with BM!)
		'B', 'M', 0, 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, 0
	};
	unsigned char bmpInfoHeader[40] = {            // info about the file (size, etc)
		40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 24, 0
	};

	bmpFileHeader[ 2] = (unsigned char)(fileSize      );
	bmpFileHeader[ 3] = (unsigned char)(fileSize >>  8);
	bmpFileHeader[ 4] = (unsigned char)(fileSize >> 16);
	bmpFileHeader[ 5] = (unsigned char)(fileSize >> 24);

	bmpInfoHeader[ 4] = (unsigned char)(       dim      );
	bmpInfoHeader[ 5] = (unsigned char)(       dim >>  8);
	bmpInfoHeader[ 6] = (unsigned char)(       dim >> 16);
	bmpInfoHeader[ 7] = (unsigned char)(       w >> 24);
	bmpInfoHeader[ 8] = (unsigned char)(       h      );
	bmpInfoHeader[ 9] = (unsigned char)(       h >>  8);
	bmpInfoHeader[10] = (unsigned char)(       h >> 16);
	bmpInfoHeader[11] = (unsigned char)(       h >> 24);

	// write the file (thanks forum!)
	file.write(bmpFileHeader, sizeof(bmpFileHeader));    // write file header
	file.write(bmpInfoHeader, sizeof(bmpInfoHeader));    // " info header

	for (int i = 0; i < h; i++) {                        // iterate image array
		file.write(img + (w * (h - i - 1) * 3), 3 * w);    // write px data
		file.write(bmpPad, (4 - (w * 3) % 4) % 4);         // and padding as needed
	}
	free(img);
	file.close();                                        // close file when done writing
}
 
@defragster - just a warning - I haven't been able to get ILI9488_t3 running on the FB_Teensy64. Same behavior with the original version of the ili9488 lib that we started with.

The faults have been happening with something plugged into the USBhost or the tft connected. The last fault was with just the ILI9488. Once I did a hard reset it cleared itself and was able run sketches again.

As posted above - Teensy64 works with 9341 and 9488. I have a V0.1 and the current V0.3 PCB - and both work with both displays. Posted Bhudda code as I have it working and the same #ifdef worked on the other sketch.

T4 on breadboard (No BreakOut pogo connections?) also noted working with 9341 and 9488 - and no faults or recent 15s_Reset needed. I do not have Serial1 or debug #4 pins wired yet either - odd but will connect and see if it shows anything.
 
@defragster
Man you have been busy now that you are up and running.

the 9488 code colors are wrong
Noticed that too. Just ran the graphicstest with the @KurtEs latest color changes and I agree the colors seem off compared to the previous version.

Odd that the T3.6@180 is faster than at 256?
 
@Frank B, @defragster, @KurtE and others

I just ran the graphics test on a T3.6 with the ILI9488 with a bit different results:
Code:
T3.6@180 -- 5553132
T3.6@240 -- 5553095
 
Yes I think above a certain level the speed of SPI is the only limiting factor - not F_CPU, because the CPU is waiting all the time.
Default F_BUS for 256MHz is 64MHz z
- can be set to 128MHz. Maybe set the SPI speed in the driver to 64MHZ (needs128MHZ F_BUS)? It should work with the Teensy64 Board.
 
Yes I think above a certain level the speed of SPI is the only limiting factor - not F_CPU, because the CPU is waiting all the time.
Default F_BUS for 256MHz is 64MHz z
- can be set to 128MHz. Maybe set the SPI speed in the driver to 64MHZ (needs128MHZ F_BUS)? It should work with the Teensy64 Board.

I think this is how you do that: https://forum.pjrc.com/threads/5554...s-PS2-keyboard?p=201545&viewfull=1#post201545

@Frank B,
UPDATE: Did that and changed SPI in the driver:
Code:
#define ILI9488_SPICLOCK 64000000
#define ILI9488_SPICLOCK_READ 4000000
With overclock to 256K
Code:
T3.6@256 -- 2830364
Just about a 50% speed improvement
 
Last edited:
@defragster
Man you have been busy now that you are up and running.

Noticed that too. Just ran the graphicstest with the @KurtEs latest color changes and I agree the colors seem off compared to the previous version.
Which changes on which processor? I don't think I changed anything for T3.x except allowing more of the fifo to be used (writedata8_cont vs writedata8_last) If there is some place I missed using a last then maybe?

T4 I packed the 3 bytes back into an uint32_t to then pass off to SPI with size of 24... But if I screwed that up (first attempt I did), the colors should be really screwed up.
 
Which changes on which processor? I don't think I changed anything for T3.x except allowing more of the fifo to be used (writedata8_cont vs writedata8_last) If there is some place I missed using a last then maybe?

T4 I packed the 3 bytes back into an uint32_t to then pass off to SPI with size of 24... But if I screwed that up (first attempt I did), the colors should be really screwed up.

Going to do a bit more testing on that one later but right now I am trying to fix scroll so I am copied your functions for readpixel, readrect, writerect, clip stuff into _t3 :) Think I am stuck on this:
Code:
#if defined(KINETISK)
 	KINETISK_SPI_t *_pkinetisk_spi;
#elif defined(__IMXRT1052__) || defined(__IMXRT1062__)  // Teensy 4.x
 	IMXRT_LPSPI_t *_pimxrt_spi;

#elif defined(KINETISL)
 	KINETISL_SPI_t *_pkinetisl_spi;
#endif
Is this just specifying which spi bus? if it is can I just substitute SPI.xxxxx in the rect functions. Also, what is the sizeFIFO function (can't seem to find where that is speficied?

Apologize if this sounds curt but I still need more coffee :)

EDIT: Working too many configs at the same time, so going to concentrate on T4 for now.
 
@KurtE
Ok found some of my answers in SPIN class but just don't know the right constructs:
Code:
	inline IMXRT_LPSPI_t & port() { return *(IMXRT_LPSPI_t *)_port_addr; }
	IMXRT_LPSPI_t *_pimxrt_spi
?????

help :)
 
Good Morning again...

First on colors, looks like there may be some issues with non horizontal/vertical lines... To debug...
Here is a quick and dirty test program to show colors...
Code:
//=============================================================================
//=============================================================================

#include <ILI9488_t3.h>
#define TFT_RST 8
#define TFT_DC 10
#define TFT_CS 9
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);
  

  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);
}

void drawColor(uint16_t x, uint16_t y, const char *psz, uint16_t color)
{
  tft.setTextColor(color);
  tft.setTextSize(2);
  tft.setCursor(x,y);
  tft.print(psz);
  tft.fillRect(x+100, y, 50, 50, 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, 30, color);
  tft.fillCircle(x+50, y+50, 20, color);  
}


//=============================================================================
// Loop
//=============================================================================
void loop()
{
}
More graphic functions can be added... to see what loos like it might fail to do right colors... Like gradient stuff...

Now to question of port() stuff and the like.
This was the ability to get the actual SPI registers for the SPI port you are using... This was a construct that Paul used when he helped migrate the SPIN stuff into SPI... Or more specific stuff I needed to do to emulate what he did with some other places like wire library.

In particular the ability to get constepxr on the constructor of the class, we were not able to directly pass in a pointer to the SPI registers, that would work when global constructors are called,
so instead is passed in is a uintptr_t to the start of the SPI registers.

The port() function is c++ mumble jumble stuff, that then casts that pointer to be a reference to the SPI registers.
So for example if on Teensy 3.x you were trying to access the PUSHR register on SPI0 which is something like SPI0_PUSHR, you would instead internally do: port().PUSHR

And nice thing here is that assuming you actually have different SPI objects, the code is setup to handle the right registers for that SPI object.

And yes sizeFIFO is member of SPIN class which reads that value out of the data passed in to the constructor...

As I mentioned this same init table (SPI_Hardware_t) is used in the SPI code as well. There is a queue_size member. The only issue is we did not provide a method for calling code to get this information.
 
@KurtE
Tried a bunch of constructs but just couldn't get the port() stuff working so I just followed your lead for the 1052/1062 and hard coded IMXRT_LPSPI4_S. instead of using the pointer. Like you said have no clue with port() stuff :( what did you call it , mumble jumble :)

So scroll looks like it improved not sure if clipping is working or not have to figure that one out. Anyway this is what I have so far for the T4 - still have to try and get T3.x working. Scroll is still not perfect but maybe need to incorporate your opaque - just have to find it :)
 

Attachments

  • ILI9488_t3.zip
    1 MB · Views: 69
Hi @mjs513

Will take a look, busy with chasing Annie...

Also maybe need to debug some of the earlier drawing stuff..
I updated the program in previous one to:
Code:
void drawColor(uint16_t x, uint16_t y, const char *psz, uint16_t color)
{
  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, 30, color);
  tft.fillCircle(x+50, y+50, 20, color);  
}
That is I shrank the fill rect and added drawRect and the drawRect looks screwed up.
ili9488_test.jpg
 
Update: Fixed some of the color issues, HLine, VLine, Pixel were not converted to use the Write16BitColor...
Those functions now in my header look like:
Code:
	void HLine(int16_t x, int16_t y, int16_t w, uint16_t color)
	  __attribute__((always_inline)) {
	  	if((x >= _width) || (y >= _height) || (y < 0)) return;
		if(x < 0) {	w += x; x = 0; 	}
		if((x+w-1) >= _width)  w = _width-x;

		setAddr(x, y, x+w-1, y);
		writecommand_cont(ILI9488_RAMWR);
		while (w > 1) {
			write16BitColor(color);
		 	w--;
		}
		write16BitColor(color, true);

	}
	void VLine(int16_t x, int16_t y, int16_t h, uint16_t color)
	  __attribute__((always_inline)) {
		if((x >= _width) || (x < 0) || (y >= _height)) return;
		if(y < 0) {	h += y; y = 0; 	}
		if((y+h-1) >= _height) h = _height-y;
		setAddr(x, y, x, y+h-1);
		writecommand_cont(ILI9488_RAMWR);
		while (h > 1) {
			write16BitColor(color);
		 	h--;
		}
		write16BitColor(color, true);
	}
	void Pixel(int16_t x, int16_t y, uint16_t color)
	  __attribute__((always_inline)) {
		if((x >= _width) || (x < 0) || (y >= _height) || (y < 0)) return;
		setAddr(x, y, x, y);
		writecommand_cont(ILI9488_RAMWR);
		write16BitColor(color);
	}
Picture looks correct now...

GraphicTest appears to show more of the right colors now...

But I also saw some stuff, that was interesting. In that I ran my display app, then downloaded graphic test and it started off, by doing a bunch of the tests only using a portion of the display. Almost like the init code was setup maybe for ili9341 so only output 320x240...
 
@KurtE
Here is an updated one with opaque - looking better for scroll.
Anyway just gave your test program a try and not sure if its better or worse:
20190411_114750.jpg

Ran graphics test but think I have something off.

EDIT: Colors don't seem so bad though
 
@mjs513 did you incorporate the HLine, VLine and pixel fixes? I Don't see the draw rectangle or the diagonal line so not sure from picture.
 
@mjs513 did you incorporate the HLine, VLine and pixel fixes? I Don't see the draw rectangle or the diagonal line so not sure from picture.

Yep - not sure I did it right though - reason, in graphics test I am not seeing lines properly. Have to go do a compare and see what happened. Maybe forgot to change something in the conversion

@KurtE
EDIT: Went back in and for some reason (think I know why, hline, vline and pixel functions where not there?) Updated and now not getting any lines whatsoever?? I have clipping incorporated etc.

@KurtE:
Edit 2: Got it now. Forgot this in the contructor in .cpp
Code:
	setClipRect();
	setOrigin();
or I should say - have some of it (the lines on the left of the screen)
 
Last edited:
Thanks @mjs513 - but just a bit of time compiling code - not a lot of work. I should have posted my GraphicsTest Sum time calc - See Below - perhaps some times missed?

I put this in ili9488_t3.h <edit> : I did not bump 256MHz F_BUS to 128 - this is working with default F_BUS 64 MHz (?)
Code:
#if defined(__MK66FX1M0__)
#if F_BUS >= 64000000
[B][U]#define ILI9488_SPICLOCK 64000000
[/U][/B]#define ILI9488_SPICLOCK_READ 4000000
#else
#define ILI9488_SPICLOCK 30000000
#define ILI9488_SPICLOCK_READ 2000000
#endif
#else
[B][U]#define ILI9488_SPICLOCK 64000000[/U][/B]
#define ILI9488_SPICLOCK_READ 4000000
#endif

Instead of TEST SUM us = 7104160 on T_3.6 at 256MHz I get TEST SUM us = 5193962

This leaves the T_3.6 at 180 MHz unchanged as :: TEST SUM us = 5553136

That also boosts T4 from TEST SUM us = 5855033 to TEST SUM us = 4011218

Here is updated :: \libraries\ILI9488_t3\examples\graphicstest\graphicstest.ino
Total time in 12 places routed through >> gtSum += ...
Code:
/***************************************************
  This is our GFX example for the Adafruit ILI9488 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 "ILI9488_t3.h"

#ifdef __MK66FX1M0__
#define __C64__ 1
#else
#endif

// Connection konfiguration of ILI9341 LCD TFT
#if defined(__C64__)
//const int cardPin = BUILTIN_SDCARD; //18;          // pin that the SD is connected to (d8 for SparkFun MicroSD shield)
#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
// For the Adafruit shield, these are the default.
#define TFT_DC  9
#define TFT_CS 10

// Use hardware SPI (on Uno, #13, #12, #11) and the above for CS/DC
ILI9488_t3 tft = ILI9488_t3(TFT_CS, TFT_DC, 23);
#endif

uint32_t gtSum = 0;
void setup() {
  tft.begin();
  tft.fillScreen(ILI9488_BLACK);
  tft.setTextColor(ILI9488_YELLOW);
  tft.setTextSize(2);
  tft.println("Waiting for Arduino Serial Monitor...");

  Serial.begin(9600);
  while (!Serial) ; // wait for Arduino Serial Monitor
  Serial.println("ILI9488 Test!");

  // read diagnostics (optional but can help debug problems)
  uint8_t x = tft.readcommand8(ILI9488_RDMODE);
  Serial.print("Display Power Mode: 0x"); Serial.println(x, HEX);
  x = tft.readcommand8(ILI9488_RDMADCTL);
  Serial.print("MADCTL Mode: 0x"); Serial.println(x, HEX);
  x = tft.readcommand8(ILI9488_RDPIXFMT);
  Serial.print("Pixel Format: 0x"); Serial.println(x, HEX);
  x = tft.readcommand8(ILI9488_RDIMGFMT);
  Serial.print("Image Format: 0x"); Serial.println(x, HEX);
  x = tft.readcommand8(ILI9488_RDSELFDIAG);
  Serial.print("Self Diagnostic: 0x"); Serial.println(x, HEX);

  Serial.println(F("Benchmark                Time (microseconds)"));

  Serial.print(F("Screen fill              "));
  Serial.println(testFillScreen());
  delay(200);

  Serial.print(F("Text                     "));
  Serial.println(testText());
  delay(600);

  Serial.print(F("Lines                    "));
  Serial.println(testLines(ILI9488_CYAN));
  delay(200);

  Serial.print(F("Horiz/Vert Lines         "));
  Serial.println(testFastLines(ILI9488_RED, ILI9488_BLUE));
  delay(200);

  Serial.print(F("Rectangles (outline)     "));
  Serial.println(testRects(ILI9488_GREEN));
  delay(200);

  Serial.print(F("Rectangles (filled)      "));
  Serial.println(testFilledRects(ILI9488_YELLOW, ILI9488_MAGENTA));
  delay(200);

  Serial.print(F("Circles (filled)         "));
  Serial.println(testFilledCircles(10, ILI9488_MAGENTA));

  Serial.print(F("Circles (outline)        "));
  Serial.println(testCircles(10, ILI9488_WHITE));
  delay(200);

  Serial.print(F("Triangles (outline)      "));
  Serial.println(testTriangles());
  delay(200);

  Serial.print(F("Triangles (filled)       "));
  Serial.println(testFilledTriangles());
  delay(200);

  Serial.print(F("Rounded rects (outline)  "));
  Serial.println(testRoundRects());
  delay(200);

  Serial.print(F("Rounded rects (filled)   "));
  Serial.println(testFilledRoundRects());
  Serial.print(F("\n TEST SUM us = "));
  Serial.println(gtSum);
  delay(200);

  Serial.println(F("Done!"));

}


void loop(void) {
  for (uint8_t rotation = 0; rotation < 4; rotation++) {
    tft.setRotation(rotation);
    testText();
    delay(1000);
  }
}

unsigned long testFillScreen() {
  unsigned long start = micros();
  tft.fillScreen(ILI9488_BLACK);
  tft.fillScreen(ILI9488_RED);
  tft.fillScreen(ILI9488_GREEN);
  tft.fillScreen(ILI9488_BLUE);
  tft.fillScreen(ILI9488_BLACK);
  gtSum += micros() - start;
  return micros() - start;
}

unsigned long testText() {
  tft.fillScreen(ILI9488_BLACK);
  unsigned long start = micros();
  tft.setCursor(0, 0);
  tft.setTextColor(ILI9488_WHITE);  tft.setTextSize(1);
  tft.println("Hello World!");
  tft.setTextColor(ILI9488_YELLOW); tft.setTextSize(2);
  tft.println(1234.56);
  tft.setTextColor(ILI9488_RED);    tft.setTextSize(3);
  tft.println(0xDEADBEEF, HEX);
  tft.println();
  tft.setTextColor(ILI9488_GREEN);
  tft.setTextSize(5);
  tft.println("Groop");
  tft.setTextSize(2);
  tft.println("I implore thee,");
  tft.setTextSize(1);
  tft.println("my foonting turlingdromes.");
  tft.println("And hooptiously drangle me");
  tft.println("with crinkly bindlewurdles,");
  tft.println("Or I will rend thee");
  tft.println("in the gobberwarts");
  tft.println("with my blurglecruncheon,");
  tft.println("see if I don't!");
  gtSum += micros() - start;
  return micros() - start;
}

unsigned long testLines(uint16_t color) {
  unsigned long start, t;
  int           x1, y1, x2, y2,
                w = tft.width(),
                h = tft.height();

  tft.fillScreen(ILI9488_BLACK);

  x1 = y1 = 0;
  y2    = h - 1;
  start = micros();
  for (x2 = 0; x2 < w; x2 += 6) tft.drawLine(x1, y1, x2, y2, color);
  x2    = w - 1;
  for (y2 = 0; y2 < h; y2 += 6) tft.drawLine(x1, y1, x2, y2, color);
  t     = micros() - start; // fillScreen doesn't count against timing

  tft.fillScreen(ILI9488_BLACK);

  x1    = w - 1;
  y1    = 0;
  y2    = h - 1;
  start = micros();
  for (x2 = 0; x2 < w; x2 += 6) tft.drawLine(x1, y1, x2, y2, color);
  x2    = 0;
  for (y2 = 0; y2 < h; y2 += 6) tft.drawLine(x1, y1, x2, y2, color);
  t    += micros() - start;

  tft.fillScreen(ILI9488_BLACK);

  x1    = 0;
  y1    = h - 1;
  y2    = 0;
  start = micros();
  for (x2 = 0; x2 < w; x2 += 6) tft.drawLine(x1, y1, x2, y2, color);
  x2    = w - 1;
  for (y2 = 0; y2 < h; y2 += 6) tft.drawLine(x1, y1, x2, y2, color);
  t    += micros() - start;

  tft.fillScreen(ILI9488_BLACK);

  x1    = w - 1;
  y1    = h - 1;
  y2    = 0;
  start = micros();
  for (x2 = 0; x2 < w; x2 += 6) tft.drawLine(x1, y1, x2, y2, color);
  x2    = 0;
  for (y2 = 0; y2 < h; y2 += 6) tft.drawLine(x1, y1, x2, y2, color);

  gtSum += micros() - start;
  return micros() - start;
}

unsigned long testFastLines(uint16_t color1, uint16_t color2) {
  unsigned long start;
  int           x, y, w = tft.width(), h = tft.height();

  tft.fillScreen(ILI9488_BLACK);
  start = micros();
  for (y = 0; y < h; y += 5) tft.drawFastHLine(0, y, w, color1);
  for (x = 0; x < w; x += 5) tft.drawFastVLine(x, 0, h, color2);

  gtSum += micros() - start;
  return micros() - start;
}

unsigned long testRects(uint16_t color) {
  unsigned long start;
  int           n, i, i2,
                cx = tft.width()  / 2,
                cy = tft.height() / 2;

  tft.fillScreen(ILI9488_BLACK);
  n     = min(tft.width(), tft.height());
  start = micros();
  for (i = 2; i < n; i += 6) {
    i2 = i / 2;
    tft.drawRect(cx - i2, cy - i2, i, i, color);
  }

  gtSum += micros() - start;
  return micros() - start;
}

unsigned long testFilledRects(uint16_t color1, uint16_t color2) {
  unsigned long start, t = 0;
  int           n, i, i2,
                cx = tft.width()  / 2 - 1,
                cy = tft.height() / 2 - 1;

  tft.fillScreen(ILI9488_BLACK);
  n = min(tft.width(), tft.height()) - 1;
  for (i = n; i > 0; i -= 6) {
    i2    = i / 2;
    start = micros();
    tft.fillRect(cx - i2, cy - i2, i, i, color1);
    t    += micros() - start;
    // Outlines are not included in timing results
    tft.drawRect(cx - i2, cy - i2, i, i, color2);
  }

  gtSum += t;
  return t;
}

unsigned long testFilledCircles(uint8_t radius, uint16_t color) {
  unsigned long start;
  int x, y, w = tft.width(), h = tft.height(), r2 = radius * 2;

  tft.fillScreen(ILI9488_BLACK);
  start = micros();
  for (x = radius; x < w; x += r2) {
    for (y = radius; y < h; y += r2) {
      tft.fillCircle(x, y, radius, color);
    }
  }

  gtSum += micros() - start;
  return micros() - start;
}

unsigned long testCircles(uint8_t radius, uint16_t color) {
  unsigned long start;
  int           x, y, r2 = radius * 2,
                      w = tft.width()  + radius,
                      h = tft.height() + radius;

  // Screen is not cleared for this one -- this is
  // intentional and does not affect the reported time.
  start = micros();
  for (x = 0; x < w; x += r2) {
    for (y = 0; y < h; y += r2) {
      tft.drawCircle(x, y, radius, color);
    }
  }

  gtSum += micros() - start;
  return micros() - start;
}

unsigned long testTriangles() {
  unsigned long start;
  int           n, i, cx = tft.width()  / 2 - 1,
                      cy = tft.height() / 2 - 1;

  tft.fillScreen(ILI9488_BLACK);
  n     = min(cx, cy);
  start = micros();
  for (i = 0; i < n; i += 5) {
    tft.drawTriangle(
      cx    , cy - i, // peak
      cx - i, cy + i, // bottom left
      cx + i, cy + i, // bottom right
      tft.color565(0, 0, i));
  }

  gtSum += micros() - start;
  return micros() - start;
}

unsigned long testFilledTriangles() {
  unsigned long start, t = 0;
  int           i, cx = tft.width()  / 2 - 1,
                   cy = tft.height() / 2 - 1;

  tft.fillScreen(ILI9488_BLACK);
  start = micros();
  for (i = min(cx, cy); i > 10; i -= 5) {
    start = micros();
    tft.fillTriangle(cx, cy - i, cx - i, cy + i, cx + i, cy + i,
                     tft.color565(0, i, i));
    t += micros() - start;
    tft.drawTriangle(cx, cy - i, cx - i, cy + i, cx + i, cy + i,
                     tft.color565(i, i, 0));
  }

  gtSum += t;
  return t;
}

unsigned long testRoundRects() {
  unsigned long start;
  int           w, i, i2,
                cx = tft.width()  / 2 - 1,
                cy = tft.height() / 2 - 1;

  tft.fillScreen(ILI9488_BLACK);
  w     = min(tft.width(), tft.height()) - 1;
  start = micros();
  for (i = 0; i < w; i += 6) {
    i2 = i / 2;
    tft.drawRoundRect(cx - i2, cy - i2, i, i, i / 8, tft.color565(i, 0, 0));
  }

  gtSum += micros() - start;
  return micros() - start;
}

unsigned long testFilledRoundRects() {
  unsigned long start;
  int           i, i2,
                cx = tft.width()  / 2 - 1,
                cy = tft.height() / 2 - 1;

  tft.fillScreen(ILI9488_BLACK);
  start = micros();
  for (i = min(tft.width(), tft.height()) - 1; i > 20; i -= 6) {
    i2 = i / 2;
    tft.fillRoundRect(cx - i2, cy - i2, i, i, i / 8, tft.color565(0, i, 0));
  }

  gtSum += micros() - start;
  return micros() - start;
}
 
@defragster - thanks will have to give it a go in a bit. Trying to get everything incorporated into the new lib.

@KurtE
Played a bit more and this is what I have not. Can't tell where the problem is though.
20190411_135929.jpg
 
@mjs513 @defragster,

I downloaded the github library :D So far I just cloned it down and have not forked it yet. Not sure if should just update changes or would you like fork with PR?

I updated the HLine/VLine functions to closer match my later changes where hopefully the last pixel is output with _last...

I ran my updated test program:
Code:
//=============================================================================
//=============================================================================

#include <ILI9488_t3.h>
#define TFT_RST 8
#define TFT_DC 10
#define TFT_CS 9
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);
  

  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);
}

void drawColor(uint16_t x, uint16_t y, const char *psz, uint16_t color)
{
  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, 30, color);
  tft.fillCircle(x+50, y+50, 20, color);  
}


//=============================================================================
// Loop
//=============================================================================
void loop()
{
}
And get right colors... BUT! not everything is showing up?

That is:
ili9488_test2.jpg

That is if you look the colors on right side of display, the drawRect is now showing up, the circle is being clipped and the other lines are not showing up...

suspicion is added clip rectangle and maybe setup by default to ILI9341 display size...
 
@KurtE

the problem was in the setRotation function, it needed these two lines:
Code:
	setClipRect();
	setOrigin();
so the whole function looks like this:
Code:
void ILI9488_t3::setRotation(uint8_t m)
{
	rotation = m % 4; // can't be higher than 3
	beginSPITransaction();
	writecommand_cont(ILI9488_MADCTL);
	switch (rotation) {
	case 0:
		writedata8_last(MADCTL_MX | MADCTL_BGR);
		_width  = ILI9488_TFTWIDTH;
		_height = ILI9488_TFTHEIGHT;
		break;
	case 1:
		writedata8_last(MADCTL_MV | MADCTL_BGR);
		_width  = ILI9488_TFTHEIGHT;
		_height = ILI9488_TFTWIDTH;
		break;
	case 2:
		writedata8_last(MADCTL_MY | MADCTL_BGR);
		_width  = ILI9488_TFTWIDTH;
		_height = ILI9488_TFTHEIGHT;
		break;
	case 3:
		writedata8_last(MADCTL_MX | MADCTL_MY | MADCTL_MV | MADCTL_BGR);
		_width  = ILI9488_TFTHEIGHT;
		_height = ILI9488_TFTWIDTH;
		break;
	}
	endSPITransaction();
	setClipRect();
	setOrigin();
	
	cursor_x = 0;
	cursor_y = 0;
}
Then it draws the whole thing :) Shoot I forgot to push the change. I'll do it now. ,,, ok change pushed.

If you want to go ahead and update hline and vline not a problem - don't need a pr.

By the way you need to change your one horizontal line to:
Code:
tft.drawLine(x+100, y+70,x+220, y+70, color);
then the triangle connects :)
 
Last edited:
Status
Not open for further replies.
Back
Top