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

Just downloaded and gave it a go with and without @defragster's added test case.

I tested at 30/72Mhz without any problems. I don't see any of the issues of "tearing and flashing of the screen except when the Tim's psychedelic effect hits :) Then I get dizzy.

Cool. Yes, it is a bit much - color changes and fast update attempts on full screen are asking for the flash/tear, all else was smooth and good - but thought of it and somehow it works - though not sure it is properly done … it does as expected.

Have tried some alterations and they are a big fail … on my part abusing the system … not doing right stuff in right order at right time?
 
Will look to test on T_3.6 shortly.

My idea to test was draw a screen with existing >> our_pallet[]

Then shift the pallet and repeat the update by indexing through this Double pallet:
Code:
		uint16_t our_palletDbl[] = {
		ILI9488_BLACK,  ILI9488_RED, ILI9488_GREEN,  ILI9488_BLUE,   ILI9488_WHITE,
		ILI9488_YELLOW, ILI9488_ORANGE, ILI9488_CYAN, ILI9488_PINK,
		ILI9488_BLACK,  ILI9488_RED, ILI9488_GREEN,  ILI9488_BLUE,   ILI9488_WHITE,
		ILI9488_YELLOW, ILI9488_ORANGE, ILI9488_CYAN, ILI9488_PINK
	};

	tft.updateScreenAsync(false);
	for (int ii = 0; ii < 8; ii++) {
		tft.setPallet(&our_palletDbl[ii], sizeof(our_pallet) / sizeof(our_pallet[0]));
		tft.updateScreen();
	}

The idea was it would recreate the PSYCHO scrolling above - by just changing the pallet association? And show that alternate pallets could be used …
 
@... Quick update... Yes looks like image being shifted off... In test app, I disabled the dizzy stuff :lol:

Added a section at end:
Code:
 tft.fillScreen(0);  // Turn all read;
  tft.drawRect(0, 0, tft.width()-1, tft.height()-1, 1);
  tft.drawLine(0, 0, tft.width(), tft.height(), 2);
  tft.drawLine(0, tft.height()-1, tft.width()-1, 0, 2);
  tft.updateScreen();
  delay(500);
  tft.updateScreenAsync();
  tft.waitUpdateAsyncComplete();
  delay(1000);
and if you watch the display you will see it first display the quick image and then shift over a pixel... Now to figure out fix!
Will probably be similar to ILI9341 (where first DMA output is shortened by one pixel (3 bytes)...

Should be fun...

Update: before actual clicking post button.

Hopefully fixed the offset issue... Hopefully did not hurt T4 code...
 
@KurtE
Just tested on the Teensy64 and without issue - didn't notice the pixel shifting but then again my eyes ain't that good :) Tested with the dizzy stuff still in - a lot more crazy on the T$ than the T3.6 :)

Update: Just loaded it up on the T3.6, new update and working no issues. I am also glad to report that it works just fine on the T$ as well - nothing broke in the translation :)

Looks like its ready for a merge?
 
@Glad it is working - Could merge now or...

Somethings that would maybe be nice?
a) I have not done it yet on T3.5... There were some issues with some SPI stuff on 3.5 that was differently for the ILI9341 - Not sure if it was mainly SPI1/SPI2 issues as these only have one SPI source/dest on those...

b) Wonder if tft.colorsArePalletIndex(true); and tft.useFrameBuffer(false); - If I should do the inverse and convert the Index into the actual color from Pallet and send it out...

c) Need to check some more of the primitives. Did I properly handle all of the different text types: built in font, transparent, opaque and Actual font transparent and Opaque. Can we optimize the conversion of colors to indexes better...

d) Wonder if we may want multiple Frame buffer types when we go to T4 B2?

And at some point would be fun to have it supported on different SPI objects... Will probably try to avoid SPIN, All of the data is in SPI object, just need to get it out...

But again merging now probably would not stop us from begin able to do the other stuff...

So should I issue PR?
 
@Glad it is working - Could merge now or...

Somethings that would maybe be nice?
a) I have not done it yet on T3.5... There were some issues with some SPI stuff on 3.5 that was differently for the ILI9341 - Not sure if it was mainly SPI1/SPI2 issues as these only have one SPI source/dest on those...

b) Wonder if tft.colorsArePalletIndex(true); and tft.useFrameBuffer(false); - If I should do the inverse and convert the Index into the actual color from Pallet and send it out...

c) Need to check some more of the primitives. Did I properly handle all of the different text types: built in font, transparent, opaque and Actual font transparent and Opaque. Can we optimize the conversion of colors to indexes better...

d) Wonder if we may want multiple Frame buffer types when we go to T4 B2?

And at some point would be fun to have it supported on different SPI objects... Will probably try to avoid SPIN, All of the data is in SPI object, just need to get it out...

But again merging now probably would not stop us from begin able to do the other stuff...

So should I issue PR?

Sounds like you are having fun. But you are probably right.

As for supporting on different SPI objects. Just did that. Pushed that change to my master the other day so the constructor is now has to be
ILI9488_t3(&SPI, …..). For T$ only supports SPI0, for T3.5/3.6 should support all available SPI ports. Think the only thing I didn't do was a test to make sure you didn't specify as SPI object not supported by the Teensy. Know at lest for T$ and Teensy64 works when you specify SPI. Was lazy didn't test all the buses.

I would say go ahead and do the PR so we have a baseline and then we can go with corrections/improvements going forward. To be honest either way is good for me.

EDIT: See post #66 for spi change
 
Nice Work KurtE :) Works on Teensy64_3.6!

Thought RoundRect would be cool - not what I thought - though it does expose the CORNERS during the PSYCHO phase and shows they are respected, symmetric and maintained - i.e. nothing image shifts

Here is the updated source for that with T64 inclusion. Hopefully the SPI SPEED will go in the Merge - it helps T_3.6 too.

Changed on loop counter so it ends on corners not matching the outer Rect - CYAN behind Purple.
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

uint16_t our_pallet[] = {
	ILI9488_BLACK,  ILI9488_RED, ILI9488_GREEN,  ILI9488_BLUE,   ILI9488_WHITE,
	ILI9488_YELLOW, ILI9488_ORANGE, ILI9488_CYAN, ILI9488_PINK
};

//=============================================================================
// Setup
//=============================================================================
void setup()
{
	tft.begin();
	tft.setRotation(3); // 180
	delay(100);

	tft.fillScreen(ILI9488_BLACK);
	tft.useFrameBuffer(true);
	tft.setPallet(our_pallet, sizeof(our_pallet) / sizeof(our_pallet[0]));
	tft.colorsArePalletIndex(true);
	delay(250);
	Serial.println("\n" __FILE__ " " __DATE__ " " __TIME__);
}
//=============================================================================
// Loop
//=============================================================================
int zz = 0;
uint32_t non_frame_buffer_time[2] = {0, 0};
uint32_t frame_buffer_time[2] = {0, 0};
void loop()
{
	// First simple pallet output sync output
	tft.fillScreen(0);
	uint16_t x = 5;
	uint16_t y = 5;

	for (uint8_t i = 1; i < (sizeof(our_pallet) / sizeof(our_pallet[0])); i++) {
		tft.drawRect(x, y, tft.width() - x * 2, tft.height() - y * 2, i);
		x += tft.width() / 16;
		y += tft.height() / 16;
	}
	tft.updateScreen();
	delay(2500);

	x = 5;
	y = 5;

	// next simple pallet Async output;
	for (uint8_t i = 1; i < (sizeof(our_pallet) / sizeof(our_pallet[0])); i++) {
		tft.fillRect(x, y, tft.width() - x * 2, tft.height() - y * 2, i);
		x += tft.width() / 16;
		y += tft.height() / 16;
	}
	tft.updateScreenAsync();  // Try an async update...
	tft.waitUpdateAsyncComplete();
	if (1) {
		delay(2500);

		// Next lets try some continuous outputs...
		// Lets update the screen in 16 chunks, every 2 frames.
		uint32_t next_update_frame_count = 2;
		tft.setTextColor(0);
		tft.setTextSize(2);
		tft.setCursor(5, 5);
		tft.print("Cont...");
		tft.updateScreen();
		tft.updateScreenAsync(true);  // Try an async update...
		for (uint16_t i = 1; i <= 16; i++) {
			// wait for the next frame...
			while (tft.frameCount() < next_update_frame_count) ;
			x = 5;
			y = 5;
			tft.setClipRect(0, 0, tft.width(), i * (tft.height() / 16));
			for (uint8_t i = 1; i < (sizeof(our_pallet) / sizeof(our_pallet[0])); i++) {
				tft.fillRect(x, y, tft.width() - x * 2, tft.height() - y * 2, 8 - i);
				x += tft.width() / 16;
				y += tft.height() / 16;
			}
			next_update_frame_count += 2;
		}
		tft.setClipRect();
		tft.endUpdateAsync();  // Tell system to cancel async updates
		tft.waitUpdateAsyncComplete();
	}
	delay(1000);

	for (uint16_t kk = 0; kk < 8; kk++) {
		for (uint16_t jj = 1; jj < sizeof(our_pallet) / sizeof(our_pallet[0]); jj++) {
			for (uint16_t i = 1; i <= 16; i++) {
				x = 5;
				y = 5;
				tft.setClipRect(0, 0, tft.width(), i * (tft.height() / 16));
				for (uint8_t i = 0; i < (sizeof(our_pallet) / sizeof(our_pallet[0])); i++) {
					if ( kk < 4 )
						tft.fillRoundRect(x, y, tft.width() - x * 2, tft.height() - y * 2, 12, ((jj + i) % 9));
					else
						tft.fillRoundRect(x, y, tft.width() - x * 2, tft.height() - y * 2, 12, ((18 + (jj - i)) % 9));
					x += tft.width() / 16;
					y += tft.height() / 16;
				}
			}
			tft.updateScreen();
			tft.waitUpdateAsyncComplete();
			//delay(5);
		}
	}
	delay(1500);
}
 
@mjs513 - Started to do PR, but says it can not automerge... Not sure how many conflicts?

Can still do and then you or (I think I can maybe) do fix of it... Or I could try sync your main branch to mine, probably create a new branch merge in my current stuff and then do PR...

As for a question earlier about being able to do SPIN stuff without SPIN... Here is a hacked up program to get the data from SPI... Currently only setup for KINETISK...

Code:
#include <SPI.h>

void printSPIInfo(uint8_t spi_index, SPIClass *pspi) {
  pspi->begin(); // do begin to not have us die when look at registers
  Serial.printf("SPI%d Info (%x)\n", spi_index, (uint32_t)pspi);
  uint32_t *pa = (uint32_t*)((void*)pspi);
#ifdef KINETISK
  KINETISK_SPI_t *_ps = (KINETISK_SPI_t*)(void*)pa[0];
  SPIClass::SPI_Hardware_t *_ph = (SPIClass::SPI_Hardware_t*)(void*)pa[1];
  Serial.printf("_pkinetisk_spi=%x SPIClass::SPI_Hardware_t=%x\n", (uint32_t)_ps, 
      (uint32_t)_ph);
  Serial.flush();
  Serial.printf("Queue size:%d tx dma:%d rx dma:%d\n", _ph->queue_size, _ph->tx_dma_channel, 
    _ph->rx_dma_channel);
  Serial.printf("SPI MCR:%x SR:%x\n", _ps->MCR, _ps->SR); 

#elif defined(__IMXRT1052__) || defined(__IMXRT1062__)  // Teensy 4.x

  IMXRT_LPSPI_t *_ps = (IMXRT_LPSPI_t*)(void*)pa[0];
  SPIClass::SPI_Hardware_t *_ph = (SPIClass::SPI_Hardware_t*)(void*)pa[1];
  Serial.printf("IMXRT_LPSPI_t=%x SPIClass::SPI_Hardware_t=%x\n", (uint32_t)_ps, 
      (uint32_t)_ph);
  Serial.flush();
  Serial.printf("TX dma:%d RX dma:%d\n", _ph->tx_dma_channel, _ph->rx_dma_channel);
  Serial.printf("SPI CR:%x TCR:%x\n", _ps->CR, _ps->TCR); 

#endif
  Serial.println();
}

void setup() {
  while (!Serial && (millis() < 2000)) ;
  Serial.begin(115200);
  delay(1000);
  printSPIInfo(0, &SPI);
#if defined(__MK64FX512__) || defined(__MK66FX1M0__)
  printSPIInfo(1, &SPI1);
  printSPIInfo(2, &SPI2);
#endif
}

void loop() {
}

Output on T3.6
Code:
SPI0 Info (1fff0730)
_pkinetisk_spi=4002c000 SPIClass::SPI_Hardware_t=7718
Queue size:4 tx dma:15 rx dma:14
SPI MCR:801f0000 SR:42000000

SPI1 Info (1fff0770)
_pkinetisk_spi=4002d000 SPIClass::SPI_Hardware_t=7684
Queue size:1 tx dma:17 rx dma:16
SPI MCR:801f0000 SR:42000000

SPI2 Info (1fff07b0) SPI0 Info (20000a68)
IMXRT_LPSPI_t=403a0000 SPIClass::SPI_Hardware_t=20000070
TX dma:80 RX dma:79
SPI CR:2 TCR:1f

Do you think it smells a little ;)

Edit: Updated to show T4 data as well
T4 output:
Code:
_pkinetisk_spi=400ac000 SPIClass::SPI_Hardware_t=75f0
Queue size:1 tx dma:39 rx dma:38
SPI MCR:801f0000 SR:42000000
[/CODE]
 
Last edited:
@KurtE
I rewrote the SPI stuff so in the constructor call it looks like:
Code:
ILI9488_t3::ILI9488_t3(SPIClass *SPIWire, uint8_t cs, uint8_t dc, uint8_t rst, uint8_t mosi, uint8_t sclk, uint8_t miso)
{
	spi_port = SPIWire;
#if defined(__IMXRT1052__) || defined(__IMXRT1062__)
	_spi_port_memorymap = 0x403A0000;
#elif defined(__MK20DX256__) || defined(__MK64FX512__) || defined(__MK66FX1M0__)
	if ( SPIWire == (SPIClass*)&SPI ) _spi_port_memorymap = 0x4002C000;
	if ( SPIWire == (SPIClass*)&SPI1 ) _spi_port_memorymap = 0x4002D000;
	if ( SPIWire == (SPIClass*)&SPI2 ) _spi_port_memorymap = 0x400AC000;
#elif defined(KINETISL)
	if ( SPIWire == (SPIClass*)&SPI ) _spi_port_memorymap = 0x40076000;
	if ( SPIWire == (SPIClass*)&SPI1 ) _spi_port_memorymap = 0x40077000;
#endif
	_cs   = cs;
....

Then in the functions for example:
Code:
uint8_t ILI9488_t3::readcommand8(uint8_t c, uint8_t index)
{
    // Bail if not valid miso
    if (_miso == 0xff) return 0;

 #ifdef KINETISK
    uint16_t wTimeout = 0xffff;
    uint8_t r=0;

    beginSPITransaction();
    while ((((*(KINETISK_SPI_t *)_spi_port_memorymap).SR) & (15 << 12)) && (--wTimeout)) ; // wait until empty

    // Make sure the last frame has been sent...
    (*(KINETISK_SPI_t *)_spi_port_memorymap).SR = SPI_SR_TCF;   // dlear it out;
    wTimeout = 0xffff;
    while (!(((*(KINETISK_SPI_t *)_spi_port_memorymap).SR) & SPI_SR_TCF) && (--wTimeout)) ; // wait until it says the last frame completed
...

Maybe this is why it doesn't want to merge.

I have no clue about GitHub to be honest - I usually do the last way you mentioned.
 
Good luck with merging ... CodeCompare is really good for manually merging and @mjs513 has done some good work there.

... wanted to go back to the test with exec times displayed ... where I added SPI SPEED … had to copy the code from forum … The TSET works so well in GitHub I can create new Sketches at will … which is why I put that 'file info' line in setup() ...

Anyhow returned to :: ILI9488_t3-Support-for-the-ILI9488-on-T3-x-and-beyond on prior page.

T$:
T:\tCode\T4\keFBP8test\keFBP8test.ino Apr 15 2019 18:18:28
ILI9488_SPICLOCK @ 72000000
Reg: 979,634
FB: 10,9047
AS:536
Reg: 981,288
FBvoid: 1,043,794
ASwt:116,072

And Teensy64_3.6:
ILI9488_SPICLOCK @ 64000000
Reg: 1,369,879
FB: 166,995
AS:3060
Reg: 1,369,879
FBvoid: 1,398,228
ASwt:136,789

Speaking of TSet's 'NEW' ... Have not mentioned lately how cool Sublime is with TSet and FrankB's Compile.cmd. Not just not having to OPEN the IDE ever, but so cool how it plops the big red error text right by the line the compiler barfs on. And since TyComm adds the MCU name to the HEX - once you point it to a Teensy it goes there - even with two Teensy's running the same sketch.

<edit> added the commas above for readability - but didn't read the values until posting ... the T$ does good work here versus the T_3.6 at 256 MHz. Then thanks to SPI speed I see I had the labels backwards?

<edit2> Not sure there is a good answer [dump buffer on Odd rotation count?] but screen rotation with active buffer is great on 180's - but +/- 90° is garbage. Something happens though even rotating/displaying through 1>2>3 leaves artifacts. Not that that is needed - just odd.

That was just 'at hand' for something to test common functions.

Running for hours at posted higher speeds both of the prior samples are dong well - no mystery white screens or oddity.
 
Last edited:
@KurtE and @defragster and others

Incorporated the Pallet changes into the master as well as @defrages SPIClock changes into the .h file. Just be forewarned your constructor needs to change if you pull the master:
Code:
#if defined(__MK66FX1M0__) && !defined(TEENSY64)
#define TFT_RST 255
#define TFT_DC 20
#define TFT_CS 21
ILI9488_t3n tft = ILI9488_t3n([COLOR="#FF0000"]&SPI,[/COLOR] TFT_CS, TFT_DC, TFT_RST);
#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 9
#define TFT_CS 10
ILI9488_t3 tft = ILI9488_t3([COLOR="#FF0000"]&SPI, [/COLOR]TFT_CS, TFT_DC, TFT_RST);
#elif defined(TEENSY64)
#define TFT_RST 255
#define TFT_DC 20
#define TFT_CS 21
#define TFT_SCK 14
#define TFT_MISO 39
#define TFT_MOSI 28
ILI9488_t3 tft = ILI9488_t3([COLOR="#FF0000"]&SPI,[/COLOR] TFT_CS, TFT_DC, TFT_RST, TFT_MOSI, TFT_SCK, TFT_MISO);
#else
#error "This example App will only work with Teensy 3.6 or Teensy 4."
#endif
You should now be able to use any SPI on the T3.6 or T3.5 once that is sorted out.
 
@defragster and @KurtE

I updated the buddhabrot sketch to use framebuffer but no color palette since I am using a color ramp and it seems to drawing no problem. Here is the sketch changes - hope I did framebuffer stuff correctly.

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 <ili9488_t3_font_Arial.h>

#define ILI9488_RST 23 //23 for t4
#define ILI9488_DC 9
#define ILI9488_CS 10
ILI9488_t3 tft = ILI9488_t3(&SPI, ILI9488_CS, ILI9488_DC, ILI9488_RST);


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)

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

  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.");
  tft.useFrameBuffer(true);
  tft.colorsArePalletIndex(false);

}

uint32_t CCdiff;
void loop() {
  plotPlots();
  static int Dexposures = 0;
  time++;
  if (time % 30 == 0) {
    // show progress every 2 seconds or so...
    CCdiff = ARM_DWT_CYCCNT;
    findMaxExposure();
    CCdiff = ARM_DWT_CYCCNT - CCdiff;
    renderBrot();
    //saveBMP();
    // 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);
    tft.updateScreen();

    Dexposures = exposures;
  }

  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);
    }
  }
    tft.updateScreen();
}

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
}
 
@mjs513 and @defragster and ...

Thanks for doing the merge. I started it yesterday, but then found you had moved many of the internal macros (inline functions) from the header file into the c++ file and the merge programs were getting a little confused on what parts went where...

The last quick and dirty test for DMA is still working on T3.6... After adding in the &SPI...

Looks like the new stuff needs some more editing for different SPI ports... Example:
Code:
#elif defined(__MK66FX1M0__) 
	_dmasettings[0].sourceBuffer(&_dma_pixel_buffer0[3], sizeof(_dma_pixel_buffer0)-3);
	_dmasettings[0].destination(KINETISK_SPI0.PUSHR);
	_dmasettings[0].TCD->ATTR_DST = 0;
	_dmasettings[0].replaceSettingsOnCompletion(_dmasettings[1]);
	_dmasettings[0].interruptAtCompletion();
Which should be easy, just need to edit the new areas to repalce things like IMXRT_LPSPI4_S. or KINETISK_SPI0. with your new equivalent The more interesting part is in the function updateScreenAsync or initDMASettings on lines like:
(T4) _dmatx.triggerAtHardwareEvent(DMAMUX_SOURCE_LPSPI4_TX );
(T3.6) _dmatx.triggerAtHardwareEvent(DMAMUX_SOURCE_SPI0_TX);

The values of things like: DMAMUX_SOURCE_LPSPI4_TX are specific to each SPI port... Which is why I was playing around with that Hack program in #108...
As you can see from the output for T3.6:
Code:
SPI0 Info (1fff0730)
_pkinetisk_spi=4002c000 SPIClass::SPI_Hardware_t=7718
Queue size:4 tx dma:15 rx dma:14
SPI MCR:801f0000 SR:42000000

SPI1 Info (1fff0770)
_pkinetisk_spi=4002d000 SPIClass::SPI_Hardware_t=7684
Queue size:1 tx dma:17 rx dma:16
SPI MCR:801f0000 SR:42000000

SPI2 Info (1fff07b0) SPI0 Info (20000a68)
IMXRT_LPSPI_t=403a0000 SPIClass::SPI_Hardware_t=20000070
TX dma:80 RX dma:79
SPI CR:2 TCR:1f
That the TX DMA sources are different for SPI it is 15, for SPI1 17 SPI2 80...

Will start playing :D Maybe some of the quick updates there...

Question for us... Should this run on a T3.2? Obviously the Frame buffer code would not work with it, but the rest could...
 
Hi @mjs513...

I was doing some hacking to update the rest of the conversion to multiple SPI busses... Which I will push up soon.

Note: I updated some of your constructor code and wanted your thoughts... So far only KinetisK...

I hate magic numbers:
Code:
#if defined(__IMXRT1052__) || defined(__IMXRT1062__)
	_spi_port_memorymap = 0x403A0000;
#elif defined(__MK20DX256__) || defined(__MK64FX512__) || defined(__MK66FX1M0__)
	if ( SPIWire == (SPIClass*)&SPI ) _spi_port_memorymap = (uint32_t)&KINETISK_SPI0;  // 0x4002C000;
    #if defined(__MK64FX512__) || defined(__MK66FX1M0__)
	if ( SPIWire == (SPIClass*)&SPI1 ) _spi_port_memorymap = (uint32_t)&KINETISK_SPI1; //0x4002D000;
	if ( SPIWire == (SPIClass*)&SPI2 ) _spi_port_memorymap = (uint32_t)&KINETISK_SPI2; //0x400AC000;
	#endif
#elif defined(KINETISL)
	if ( SPIWire == (SPIClass*)&SPI ) _spi_port_memorymap = 0x40076000;
	if ( SPIWire == (SPIClass*)&SPI1 ) _spi_port_memorymap = 0x40077000;
#endif
Also updated that part as T3.2 does not have SPI1 nor SPI2, so it would not compile checking for them...

But also then wondering which way is better to go: currently you are holding it as uint32_t so for example you have:
(*(KINETISK_SPI_t *)_spi_port_memorymap).SR = SPI_SR_TCF;

Versus holding the kinetisk value as a pointer (KINETISK_SPI_T *) example in member name, like: _spi_port

Then all of the same references would be like: _spi_port->SR = SPI_SR_TCF;

Either should work and my guess is generate the same code...
 
@KurtE

Missed those changes for DMA on different ports - like you said should be easier to do especially with your changes. Oh, probably have to fix queque size as well I kind of hard coded that in for now. Just remembered.

As for the T3.2 think we should get the SPI changes fixed first on the T3.6, then verify on the T3.5 then move onto the T3.2, might as well. I know for the LC @tonton81 had all kinds of problems with the way it did SPI. So guess stick with the T3.x :)

EDIT: I thought we were all magicians with getting this working :)

EDIT:
But also then wondering which way is better to go: currently you are holding it as uint32_t so for example you have:
(*(KINETISK_SPI_t *)_spi_port_memorymap).SR = SPI_SR_TCF;

Versus holding the kinetisk value as a pointer (KINETISK_SPI_T *) example in member name, like: _spi_port
Probably later way - just got it working that way, not very good with pointers. Besides figured you all would improve on it going forward. I tend to take the long way around when I figure out how things work. :(
 
@KurtE
Just tried to compile for the T3.5. Think you need some more fences for when frame buffer is not specified.

EDIT: Then I guess we need to add the dma settings for the T3.5.
 
@mjs513 - I did a quick PR that did some of the stuff I mentioned in previous post about using something like _pkinetisk_spi->SR

Note sure yet if you want to Pull in yet, or after I update (Hack) for knowing which DMA Channel is needed...
And maybe knowing the queue size (did not check to see if you have that already or not?

I am also not a very good expert at lots of this pointer mumble jumble... But have hit many of these same issues earlier with SPIN and ILI9341_t3n...

Then to try T3.5...

EDIT: Question is for this additional information, should I use the hack I mentioned in grabbing this data from SPI object, or again have to know for each processor type...
 
@mjs513 - I did a quick PR that did some of the stuff I mentioned in previous post about using something like _pkinetisk_spi->SR

Note sure yet if you want to Pull in yet, or after I update (Hack) for knowing which DMA Channel is needed...
And maybe knowing the queue size (did not check to see if you have that already or not?

I am also not a very good expert at lots of this pointer mumble jumble... But have hit many of these same issues earlier with SPIN and ILI9341_t3n...

Then to try T3.5...

EDIT: Question is for this additional information, should I use the hack I mentioned in grabbing this data from SPI object, or again have to know for each processor type...

As much as I hate to say this I would use the hack to get the additional information. Otherwise its looking like magic numbers again. I'll hold off the incorporating the PR until after..... I was trying to figure it out but kept running into problems so now I can see what you did for future reference. :)

EDIT: Ok see what you did now and how it works. Thanks for the lesson, again...
 
Hi @mjs513... I put up phase two of the hack (in PR) that hopefully gets the size of the FIFO as well as the DMA channel. So far appears to work with SPI on T3.6 and 4...

Next up try SPI1... Probably still issue with reading pixels, but...
 
@KurtE
Cool. Just got done with errands and Doctors and just catching up to see what I missed. You got pretty far - to me its one step at a time. As Michelangelo said to pope (at least Charlton Hesston said it) - "It will be finished when its finished!" :)

I'll go ahead and pull in the PR just to so it wont starting getting conflicts :)

EDIT: CHANGES MERGED :)
 
@mjs513 and ...

Thanks,

FYI - Just got back as well... Was at town for awhile and then at lunch...

Just tried the simple test app with T3.6 on SPI1...
Code:
//=============================================================================
//=============================================================================
#include <ILI9488_t3.h>
#include <ILI9488_t3_font_Arial.h>
#include <ILI9488_t3_font_ArialBold.h>

#define TRY_SPI1
#if defined(TRY_SPI1) &&  defined(KINETISK)
// MOSI 0, MISO 1, SCK 32
#define TFT_RST 8
#define TFT_DC 31
#define TFT_CS 30 // not physical CS pin
ILI9488_t3 tft = ILI9488_t3(&SPI1, TFT_CS, TFT_DC, TFT_RST);

#else
// MOSI 11, MISO 12, SCK 13
#define TFT_RST 8
#define TFT_DC 9
#define TFT_CS 10
ILI9488_t3 tft = ILI9488_t3(&SPI, TFT_CS, TFT_DC, TFT_RST);
#endif

uint16_t our_pallet[] = {
  ILI9488_BLACK,  ILI9488_RED, ILI9488_GREEN,  ILI9488_BLUE,   ILI9488_WHITE,
  ILI9488_YELLOW, ILI9488_ORANGE, ILI9488_CYAN, ILI9488_PINK
};

//=============================================================================
// Setup
//=============================================================================
void setup()
{
  tft.begin();
  tft.setRotation(3); // 180
  delay(100);

  tft.fillScreen(ILI9488_BLACK);
  tft.useFrameBuffer(true);
  tft.setPallet(our_pallet, sizeof(our_pallet) / sizeof(our_pallet[0]));
  tft.colorsArePalletIndex(true);
  delay(250);
}
//=============================================================================
// Loop
//=============================================================================
int zz = 0;
uint32_t non_frame_buffer_time[2] = {0, 0};
uint32_t frame_buffer_time[2] = {0, 0};
void loop()
{
  // First simple pallet output sync output
  tft.fillScreen(0);
  uint16_t x = 5;
  uint16_t y = 5;

  for (uint8_t i = 1; i < (sizeof(our_pallet) / sizeof(our_pallet[0])); i++) {
    tft.drawRect(x, y, tft.width() - x * 2, tft.height() - y * 2, i);
    x += tft.width() / 16;
    y += tft.height() / 16;
  }
  tft.updateScreen();
  delay(2500);

  x = 5;
  y = 5;

  // next simple pallet Async output;
  for (uint8_t i = 1; i < (sizeof(our_pallet) / sizeof(our_pallet[0])); i++) {
    tft.fillRect(x, y, tft.width() - x * 2, tft.height() - y * 2, i);
    x += tft.width() / 16;
    y += tft.height() / 16;
  }
  tft.updateScreenAsync();  // Try an async update...
  tft.waitUpdateAsyncComplete();

  delay(2500);

  // Next lets try some continuous outputs...
  // Lets update the screen in 16 chunks, every 2 frames.
  uint32_t next_update_frame_count = 2;
  tft.setTextColor(0);
  tft.setTextSize(2);
  tft.setCursor(5, 5);
  tft.print("Cont...");
  tft.updateScreen();
  tft.updateScreenAsync(true);  // Try an async update...
  for (uint16_t i = 1; i <= 16; i++) {
    // wait for the next frame...
    while (tft.frameCount() < next_update_frame_count) ;
    x = 5;
    y = 5;
    tft.setClipRect(1, 1, tft.width()-2, i * (tft.height() / 16) -2);
    for (uint8_t i = 1; i < (sizeof(our_pallet) / sizeof(our_pallet[0])); i++) {
      tft.fillRect(x, y, tft.width() - x * 2, tft.height() - y * 2, 8 - i);
      x += tft.width() / 16;
      y += tft.height() / 16;
    }
    next_update_frame_count += 2;
  }
  tft.setClipRect();
  tft.endUpdateAsync();  // Tell system to cancel async updates
  tft.waitUpdateAsyncComplete();
/*
  delay(1000);
  for (uint16_t kk = 0; kk < 8; kk++) {
    for (uint16_t jj = 1; jj < sizeof(our_pallet) / sizeof(our_pallet[0]); jj++) {
      for (uint16_t i = 1; i <= 16; i++) {
        x = 5;
        y = 5;
        tft.setClipRect(0, 0, tft.width(), i * (tft.height() / 16));
        for (uint8_t i = 1; i < (sizeof(our_pallet) / sizeof(our_pallet[0])); i++) {
          if ( kk < 4 )
            tft.fillRect(x, y, tft.width() - x * 2, tft.height() - y * 2, ((jj + i) % 9));
          else
            tft.fillRect(x, y, tft.width() - x * 2, tft.height() - y * 2, ((18 + (jj - i)) % 9));
          x += tft.width() / 16;
          y += tft.height() / 16;
        }
      }
      tft.updateScreen();
      tft.waitUpdateAsyncComplete();
    }
  }
*/  
  delay(1000);
  tft.fillScreen(0);  // Turn all read;
  tft.drawRect(0, 0, tft.width()-1, tft.height()-1, 1);
  tft.drawLine(0, 0, tft.width(), tft.height(), 2);
  tft.drawLine(0, tft.height()-1, tft.width()-1, 0, 2);
  tft.updateScreen();
  delay(500);
  tft.updateScreenAsync();
  tft.waitUpdateAsyncComplete();
  delay(1000); 
}

And it appears to be running... Note: I have not checked the readPixel/readRect code yet... figures T3.5 would be next...
 
@KurtE and @defragster

Cool that it works on the other SPI objects. You know eventually maybe we can update the your 9341 library then you don't have to worry about SPIN library :) But that's a project for another day.

Any back to the project at hand. I just ran my scrolltest.ino sketch which uses readRect. No framebuffer/DMA/Palete. It works kind of. When it goes to scroll the last line in the scroll box the lines above are washed out - what do I mean - the text is there but the rect is comprised of alternating green and black lines. Here is my test sketch:
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>
#include <ILI9488_t3_font_ComicSansMS.h>

#define TEENSY64

// For the Adafruit shield, these are the default.
#if defined(__MK66FX1M0__) && !defined(TEENSY64)
#define TFT_RST 8
#define TFT_DC 9
#define TFT_CS 10
ILI9488_t3 tft = ILI9488_t3(&SPI,TFT_CS, TFT_DC, TFT_RST);
#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 9
#define TFT_CS 10
ILI9488_t3 tft = ILI9488_t3(&SPI,TFT_CS, TFT_DC, TFT_RST);
#elif defined(TEENSY64)
#define TFT_RST 255
#define TFT_DC 20
#define TFT_CS 21
#define TFT_SCK 14
#define TFT_MISO 39
#define TFT_MOSI 28
ILI9488_t3 tft = ILI9488_t3(&SPI,TFT_CS, TFT_DC, TFT_RST, TFT_MOSI, TFT_SCK, TFT_MISO);
#else
#error "This example App will only work with Teensy 3.6 or Teensy 4."
#endif
// If using the breakout, change pins as desired
//Adafruit_ILI9488 tft = Adafruit_ILI9488(TFT_CS, TFT_DC, TFT_MOSI, TFT_CLK, TFT_RST, TFT_MISO);

void setup() {

  Serial.begin(9600);
 
  tft.begin();

  tft.setRotation(3);

  tft.fillScreen(ILI9488_BLACK);
  while (!Serial) ; 
  tft.setTextColor(ILI9488_WHITE);  tft.setTextSize(4);
  tft.enableScroll();
  tft.setScrollTextArea(0,0,120,240);
  tft.setScrollBackgroundColor(ILI9488_GREEN);

  tft.setCursor(180, 100);

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

  tft.setCursor(0, 0);

  tft.setTextColor(ILI9488_BLACK); 

  for(int i=0;i<20;i++){
    tft.print("  this is line ");
    tft.println(i);
    delay(500);
  }

  tft.fillScreen(ILI9488_BLACK);
  tft.setScrollTextArea(40,50,120,120);
  tft.setScrollBackgroundColor(ILI9488_GREEN);
  tft.setFont(ComicSansMS_10);

  tft.setTextSize(1);
  tft.setCursor(40, 50);

  for(int i=0;i<20;i++){
    tft.print("  this is line ");
    tft.println(i);
    delay(500);
  }


}



void loop(void) {


}
If I use framebuffer(true) I don't see that effect. So don't know if that is the way it works now or something is off with readRect.
Code:
#include <SPI.h>
#include <ILI9488_t3.h>
#include <ILI9488_t3_font_ComicSansMS.h>

#define TEENSY64

// For the Adafruit shield, these are the default.
#if defined(__MK66FX1M0__) && !defined(TEENSY64)
#define TFT_RST 8
#define TFT_DC 9
#define TFT_CS 10
ILI9488_t3 tft = ILI9488_t3(&SPI,TFT_CS, TFT_DC, TFT_RST);
#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 9
#define TFT_CS 10
ILI9488_t3 tft = ILI9488_t3(&SPI,TFT_CS, TFT_DC, TFT_RST);
#elif defined(TEENSY64)
#define TFT_RST 255
#define TFT_DC 20
#define TFT_CS 21
#define TFT_SCK 14
#define TFT_MISO 39
#define TFT_MOSI 28
ILI9488_t3 tft = ILI9488_t3(&SPI,TFT_CS, TFT_DC, TFT_RST, TFT_MOSI, TFT_SCK, TFT_MISO);
#else
#error "This example App will only work with Teensy 3.6 or Teensy 4."
#endif
// If using the breakout, change pins as desired
//Adafruit_ILI9488 tft = Adafruit_ILI9488(TFT_CS, TFT_DC, TFT_MOSI, TFT_CLK, TFT_RST, TFT_MISO);

uint16_t our_pallet[] = {
  ILI9488_BLACK,  ILI9488_RED, ILI9488_GREEN,  ILI9488_BLUE,   ILI9488_WHITE,
  ILI9488_YELLOW, ILI9488_ORANGE, ILI9488_CYAN, ILI9488_PINK
};

void setup() {

  Serial.begin(9600);
 
  tft.begin();
  tft.useFrameBuffer(true);
  //tft.setPallet(our_pallet, sizeof(our_pallet) / sizeof(our_pallet[0]));
  tft.colorsArePalletIndex(false);
  tft.setRotation(3);

  tft.fillScreen(ILI9488_BLACK);
  while (!Serial) ; 

  tft.setTextColor(ILI9488_WHITE);  tft.setTextSize(4);
  tft.enableScroll();
  tft.setScrollTextArea(0,0,120,240);
  tft.setScrollBackgroundColor(ILI9488_GREEN);

  tft.setCursor(180, 100);

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

  tft.setCursor(0, 0);
  tft.setTextColor(ILI9488_BLACK); 

  for(int i=0;i<20;i++){
    tft.print("  this is line ");
    tft.println(i);
    tft.updateScreen();
    delay(500);
  }

  tft.fillScreen(ILI9488_BLACK);
  tft.setScrollTextArea(40,50,120,120);
  tft.setScrollBackgroundColor(ILI9488_GREEN);
  tft.setFont(ComicSansMS_10);

  tft.setTextSize(1);
  tft.setCursor(40, 50);
  tft.updateScreen();

  for(int i=0;i<20;i++){
    tft.print("  this is line ");
    tft.println(i);
      tft.updateScreen();

    delay(500);
  }
  tft.updateScreen();
}

void loop(void) {
}
 
@KurtE and @defragster

Same tests as in post 122 on the T$ and ran without issue with or without framebuffer.
 
@mjs513 and @defragster - Now trying to get T3.5 to work...
My earlier test without using Async Update does draw correctly. But first pass DMA is crashing...

I thought I would try doing it like T3.6 knowing that it probably would not work (as did not do it that way in ILI9341_t3n...). I know that SPI1/SPI2 have to be different, but was not sure about SPI0... Looks like I need to do it without using the chaining like I did in T.6... Also may need to do dummy RX DMA as well... so next up try again that way...

Probably tomorrow!
 
@KurtE Too much progress to test :) And @mjs513 - multiple SPI to wire ...

@mjs513 - did you make a board to Tri-State the TFT_MISO?
 
Back
Top