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

@mjs513 - Hopefully your screen is not damaged so you can play :D I do see the Touch CS pin being manipulated after each write of 4 bytes... My guess is it is tied to the shift registers or the like and tells it to update the output bits... I am seeing in the earlier capture about 90 nano-seconds, so the Delay 1us is still maybe 10 times more than it needs.

Unfortunately it sort of neuters the usage of the FIFO otherwise it might make sense to try using 32 bit writes from FIFO, but that would only gain sligthly...

Wonder what would happen if you got rid of the delay all together if it would still work. Where did you get your display from :) Think mine is dead.
 
Hi @mjs513 - I changed it to:
Code:
  digitalWriteFast(TOUCH_CS, LOW);
  delayNanoseconds(1);
  digitalWriteFast(TOUCH_CS, HIGH);
Using digitalWrites with no delay worked, using digitalWriteFast with no delays did not...


I also played with loop() to get an idea of how fast it was crawling...
Code:
void loop() {

	//Update rotation
	lcd_setrotation(lcd_rot);

	//Fill entire screen with new color
  elapsedMillis em = 0;
	lcd_fillframe(0,0,lcd_w,lcd_h,colors[color]);
  Serial.println((uint32_t)em, DEC);
	//Make a color+1 box, 5 pixels from the top-left corner, 20 pixels high, 95 (100-5) pixels from right border.
	lcd_fillframe(5,5,lcd_w-100,20,colors[(color+1) & 0xF]);
The fillFrame is taking about 298Ms to complete or little over 3 frames per second... If I bump up SPICLOCK to 60000000 it cuts this to 250...

Real question is, Do we really want to do anything with these? If I had purchased 100 of these and had some product to sell, maybe worth the time, to make driver that works with them... Not sure anyone else has one? @defragster?

I do believe it can be sped up some.. Things like not needing to set CS for each of these transfers... But still have wait for transfers to complete in order to change touch cs state...
 

The fillFrame is taking about 298Ms to complete or little over 3 frames per second... If I bump up SPICLOCK to 60000000 it cuts this to 250...

Real question is, Do we really want to do anything with these? If I had purchased 100 of these and had some product to sell, maybe worth the time, to make driver that works with them... Not sure anyone else has one? @defragster?
...

Yikes - nice 60 MHz works but only dropping to 298 to 250 ms sounds like some ugly overhead involved. Not following close enough to know what display this is without reading prior page - but whatever it is sounds like it is good to be working.

I'd call it a day and move on. Could be usable when updated with care for simple 'textout' - but it won't ever be fast.
 
@KurtE - @defragster

Real question is, Do we really want to do anything with these? If I had purchased 100 of these and had some product to sell, maybe worth the time, to make driver that works with them... Not sure anyone else has one? @defragster?
Don't think its worth the time to do a proper driver for it. There are better displays to work with than that one. One of the complaints was about the update speed - it stunk! as you found out. Think the only thing that I would do is just update the sketch to display a one of the pics from the GitHub page just for completeness. Maybe 'textout' for curiosity but that's about it. There is a lot of better things to spend time on.

@defragster - its that crazy display that you have and I got -- 6 pin header plus a 4-pin header - for the RPI.

PS. I did order another one from EBAY - was relatively cheap ($16) - after all the time I spent researching what the heck it was want to see it work :)
 
Got the feeling it was that one missing proper control pins from recent posts - after posting I went one page back and didn't see a link. This thread for 9488 has seen other traffic so wasn't sure.

As KurtE noticed I ordered a 240x240 small one I assume is similar with missing control pins?

For that many pixels it will be nice to have a high res display someday for monitoring barometer change - or maybe tides … maybe the phase of the moon … or paint drying :)
 
HI Mr KurtE!
I have some problem with your lib.
I'm using this module: https://aliexpress.com/item/32985467436.html?spm=a2g0s.9042311.0.0.24fb4c4deqeB20
It used ILI9488+XPT2046.
I use this XPT2046 lib: https://github.com/PaulStoffregen/XPT2046_Touchscreen
Wiring as below:
For display
-TFT_DC 20
-TFT_CS 21
-TFT_RST 255
-TFT_MOSI 7
-TFT_SCLK 14
-TFT_MISO 39
For touch
-T_CLK 13
-T_CS 8
-T_DIN 11
-T_DO 12
-T_IRQ 2

When I using the example pictureEmbed to check the display: it worked.
When I using the example TouchTestIRQ to check the touch screen: it worked.
But when I combine 2 of them. the touch screen doesn't work.
this is my code:

Code:
#include <XPT2046_Touchscreen.h>
#include <SPI.h>
#include <ILI9488_t3.h>

#define CS_PIN  8
#define TIRQ_PIN  2
XPT2046_Touchscreen ts(CS_PIN, 2);  // Param 2 - Touch IRQ Pin - interrupt enabled polling

#define TFT_DC      20
#define TFT_CS      21
#define TFT_RST    255  // 255 = unused, connect to 3.3V
#define TFT_MOSI     7
#define TFT_SCLK    14
#define TFT_MISO    39

#define TS_MINX 150
#define TS_MINY 130
#define TS_MAXX 3800
#define TS_MAXY 4000
ILI9488_t3 tft = ILI9488_t3(&SPI, TFT_CS, TFT_DC, TFT_RST, TFT_MOSI, TFT_SCLK, TFT_MISO);
#define BOXSIZE 40
#define PENRADIUS 3
int oldcolor, currentcolor;
void setup() {
  Serial.begin(38400);
    tft.begin();

   if (!ts.begin()) {
    Serial.println("Couldn't start touchscreen controller");
    while (1);
  }
  Serial.println("Touchscreen started");
  ts.setRotation(1);
  while (!Serial && (millis() <= 1000));

}
boolean wastouched = true;
void loop() {

  // tirqTouched() is much faster than touched().  For projects where other SPI chips
  // or other time sensitive tasks are added to loop(), using tirqTouched() can greatly
  // reduce the delay added to loop() when the screen has not been touched.
  if (ts.tirqTouched()) {
    if (ts.touched()) {
      TS_Point p = ts.getPoint();
      Serial.print("Pressure = ");
      Serial.print(p.z);
      Serial.print(", x = ");
      Serial.print(p.x);
      Serial.print(", y = ");
      Serial.print(p.y);
      delay(30);
      Serial.println();
    }
  }

}
The result is:
Pressure = 4095, x = 0, y = 0
Pressure = 4095, x = 0, y = 0
Pressure = 4095, x = 0, y = 0
Pressure = 4095, x = 0, y = 0
Pressure = 4095, x = 0, y = 0
Pressure = 4095, x = 0, y = 0
Pressure = 4095, x = 0, y = 0
....

When I disable the line tft.begin() the touch screen work again. I don't know how to fix it. COuld you please to help me. Thank you
 
Last edited by a moderator:
This has been a collaborative project, the actual github master fork is https://github.com/mjs513/ILI9488_t3 (@mjs513)

This sounds like the classic issue with multiple SPI devices on the same buss. You might try setting all of the CS pins HIGH before trying to init either device.

Code:
#include <XPT2046_Touchscreen.h>
#include <SPI.h>
#include <ILI9488_t3.h>

#define CS_PIN  8
#define TIRQ_PIN  2
XPT2046_Touchscreen ts(CS_PIN, 2);  // Param 2 - Touch IRQ Pin - interrupt enabled polling

#define TFT_DC      20
#define TFT_CS      21
#define TFT_RST    255  // 255 = unused, connect to 3.3V
#define TFT_MOSI     7
#define TFT_SCLK    14
#define TFT_MISO    39

#define TS_MINX 150
#define TS_MINY 130
#define TS_MAXX 3800
#define TS_MAXY 4000
ILI9488_t3 tft = ILI9488_t3(&SPI, TFT_CS, TFT_DC, TFT_RST, TFT_MOSI, TFT_SCLK, TFT_MISO);
#define BOXSIZE 40
#define PENRADIUS 3
int oldcolor, currentcolor;
void setup() {
  [COLOR="#FF0000"]while (!Serial && millis() < 2000) ;   // Waits for up to 2 seconds for Serial 
  pinMode(TFT_CS, OUTPUT);
  digitalWrite(TFT_CS, HIGH);
  pinMode(CS_PIN, OUTPUT);
  digitalWrite(CS_PIN, HIGH);[/COLOR]

  Serial.begin(38400);
    tft.begin();

   if (!ts.begin()) {
    Serial.println("Couldn't start touchscreen controller");
    while (1);
  }
  Serial.println("Touchscreen started");
  ts.setRotation(1);
  while (!Serial && (millis() <= 1000));

}
boolean wastouched = true;
void loop() {

  // tirqTouched() is much faster than touched().  For projects where other SPI chips
  // or other time sensitive tasks are added to loop(), using tirqTouched() can greatly
  // reduce the delay added to loop() when the screen has not been touched.
  if (ts.tirqTouched()) {
    if (ts.touched()) {
      TS_Point p = ts.getPoint();
      Serial.print("Pressure = ");
      Serial.print(p.z);
      Serial.print(", x = ");
      Serial.print(p.x);
      Serial.print(", y = ");
      Serial.print(p.y);
      delay(30);
      Serial.println();
    }
  }

}
 
@KurtE - @defragster

Don't think its worth the time to do a proper driver for it. There are better displays to work with than that one. One of the complaints was about the update speed - it stunk! as you found out. Think the only thing that I would do is just update the sketch to display a one of the pics from the GitHub page just for completeness. Maybe 'textout' for curiosity but that's about it. There is a lot of better things to spend time on.

@defragster - its that crazy display that you have and I got -- 6 pin header plus a 4-pin header - for the RPI.

PS. I did order another one from EBAY - was relatively cheap ($16) - after all the time I spent researching what the heck it was want to see it work :)

Looks like you probably ordered from the same Ebay one I did (at least same price)... I hear you...

Might play a little more with it. Who knows maybe I will start hacking a version starting from ili9488_t3 code and migrate some of this stuff in...
There are lots of the support functions that may not be needed that is for the T4, that is: mostly we simply need to do something very much like:

SPI.transfer32(value);
digitalWrite(DC_PIN, LOW);
digitalWrite(DC_PIN, HIGH);

Obviously for T3.x you would maybe need simple code to: maybe PUSHR two values and wait for those two to fully send...
 
Hi again @mjs513 and @defragster and anyone else with this RPI display...

Mike,

I hacked up your hacked up sketch to only be one tab... Can still be a lot cleaner... But if you wish to take a look at current stuff with only one tab.

Still doing identical to the version you posted... But removing all of the queue stuff except some simple stuff. Got me to now about 180ms to draw screen.

The most interesting part of the code is:
Code:
void inline beginSPITransaction() {
  g_tcr_save = IMXRT_LPSPI4_S.TCR;
  SPI.beginTransaction(SPISettings(SPICLOCK, MSBFIRST, SPI_MODE0));
  IMXRT_LPSPI4_S.TCR = (g_tcr_save & 0xfffff000) | LPSPI_TCR_FRAMESZ(31);  // turn on 32 bit mode
//  digitalWriteFast(LCD_CS, LOW);
}

void inline endSPITransaction() {
//  digitalWriteFast(LCD_CS, HIGH);
  SPI.endTransaction();
}


void spi_transmit(uint8_t *data_in, int len)
{
  uint32_t data32;
  digitalWriteFast(LCD_CS, LOW);
  if (len == 4) {
    // currently only T4...
    if ((IMXRT_LPSPI4_S.TCR & 0xfff) != 31) {
      IMXRT_LPSPI4_S.TCR = (g_tcr_save & 0xfffff000) | LPSPI_TCR_FRAMESZ(31);  // turn on 32 bit mode
    }
    data32 = ((uint32_t)data_in[0] << 24) | ((uint32_t)data_in[1] << 16) |
             ((uint32_t)data_in[2] << 8) | (uint32_t)data_in[3];
  } else {
    if ((IMXRT_LPSPI4_S.TCR & 0xfff) != 23) {
      IMXRT_LPSPI4_S.TCR = (g_tcr_save & 0xfffff000) | LPSPI_TCR_FRAMESZ(23);  // turn on 32 bit mode
    }
    data32 = ((uint32_t)data_in[0] << 16) | ((uint32_t)data_in[1] << 8) |
             (uint32_t)data_in[2];
  }
  IMXRT_LPSPI4_S.TDR = data32;    // output 32 bit data.
  while ((IMXRT_LPSPI4_S.RSR & LPSPI_RSR_RXEMPTY)) ;  // wait while the RSR fifo is empty...
  data32 = IMXRT_LPSPI4_S.RDR;
  digitalWriteFast(LCD_CS, HIGH);
  digitalWriteFast(TOUCH_CS, LOW);
  delayNanoseconds(1);
  digitalWriteFast(TOUCH_CS, HIGH);
  return;
}
 

Attachments

  • Kedei_simple-190711a.zip
    3.8 KB · Views: 63
Last edited:
@KurtE

Cool change - so changing to 32bit transfers actually helped. That's quite a speed performance you got over what we started with the RPI display. I know, its now become a challenge. Really can't do much with my display out of action until I get a new one. Can't wait to give it a try.

SSD1351 UncannyEyes:
I actually bought 2 of them to test with. I can get one working but not both but I am not sure if its a power problem or not. If I have both connected the screens just remain black. If I remove one from the breadboard the other will work. Have to do some more testing. Was a bit distracted today - putting together my new breakout board with the tri-state buffer. It works like a charm on the ILI9488, even works with the ILI9341 which doesn't have a problem with being tri-stated. Had to stop for the day - was not doing well - think I need to start watching what I am eating.

Have to tell you that cheap LA I got - while not a Salae - has come in handy to do some troubleshooting. Think at some point going to have to pick up a Salae - yes I saw your note on the hobbyist discount.:)
 
Cool update to T4 speed, I'll have to see about hooking mine up to test. Will have to find right LIB and PIN list - just pulled above ZIP.

So Kurt/Mike - have bootloader/USB hangs stopped happening with displays - or was it just that one prior unit?

FrankB did a PT8211 edit I tested and it got pulled today. I went ahead with proposed Startup__Hook()'s, very cool that (digital) I/O usable under 2 ms after clock starts - all else but Serial under 46 ms.

Mike - let me know if you look at TempMon again - I did a quick look and quit before getting anywhere. Also not seeing anything but 1[SRC_SRSR_IPP_RESET_B] reading from the 'resetReasonHw = SRC_SRSR;' - am I using that right? Maybe the 1062 startup is always kicked off with reset by the bootloader MCU?
 
Cool update to T4 speed, I'll have to see about hooking mine up to test. Will have to find right LIB and PIN list - just pulled above ZIP.

So Kurt/Mike - have bootloader/USB hangs stopped happening with displays - or was it just that one prior unit?

FrankB did a PT8211 edit I tested and it got pulled today. I went ahead with proposed Startup__Hook()'s, very cool that (digital) I/O usable under 2 ms after clock starts - all else but Serial under 46 ms.

Mike - let me know if you look at TempMon again - I did a quick look and quit before getting anywhere. Also not seeing anything but 1[SRC_SRSR_IPP_RESET_B] reading from the 'resetReasonHw = SRC_SRSR;' - am I using that right? Maybe the 1062 startup is always kicked off with reset by the bootloader MCU?

@defragster

For the RPI display relatively easy hook - MOSI=11, L_CS=10, T_CS=6, CLK=13, Gnd=Ground, 5v=5v. No addition Libs necessary. Everything self contained.

As for the ST7735 using uncannyeyes - yep - still having the problem. For the 1351's not yet - but that is using a different lib.

Saw the post on the _Hook()'s - cool the digialIO is available - can come in handy down the road.

Promise I will get back to tempmon stuff soon - want to work on the 1351's a while.
 
@mjs513,

Telling SPI to use higher word sizes helps some as it removes the inter word delay...

I am still wondering about the schematics shown for this display. Some reason I think it is wrong.. Since the CS of touch is needed, I think that must be tied to the latch the data (one of the clock names)...

SSD1351 - Only have one... So not much help yet on debugging two. I did add in a sendCommand into the other library, which I did not test out, but hopefully gives us hooks. Hopefully the owner will pull the changes in.
 
@KurtE
Not 100% sure about the schematics either. One that was for an earlier revision of the board and two it was reversed engineered - never could find anything official on the display which is always a concern.

Probably will play more with the 1351's tomorrow. Will keep you posted :)
 
@KurtE

Well I lied - had to try something, turn debug back on:
Code:
C:\Users\Merli\OneDrive\Desktop\uncannyEyes\uncannyEyes.ino Jul 11 2019 20:06:43
>>> Reason for 'reset': 1 IPP_RESET_B :: done Reason
F_CPU==600000000   F_BUS==150000000 FreeMem(); 4293328820
Init
Create display #0
Create display #1

 >>>> Debug Fault   >>>> debug_fault   >>>> TYPE:isr
debug_tt Info:

 >>>> Debug Fault   >>>> TYPE:isr
--- Faulted >>>>  Execution Halted.

<EDIT>Well problem could be I was using pin 7 for CS that caused the fault but changed the pin number and same thing happened so..
 
Last edited:
@KurtE

Well I lied - had to try something, turn debug back on:
Code:
C:\Users\Merli\OneDrive\Desktop\uncannyEyes\uncannyEyes.ino Jul 11 2019 20:06:43
>>> Reason for 'reset': 1 IPP_RESET_B :: done Reason
F_CPU==600000000   F_BUS==150000000 FreeMem(); 4293328820
Init
Create display #0
Create display #1

 >>>> Debug Fault   >>>> debug_fault   >>>> TYPE:isr
debug_tt Info:

 >>>> Debug Fault   >>>> TYPE:isr
--- Faulted >>>>  Execution Halted.

<EDIT>Well problem could be I was using pin 7 for CS that caused the fault but changed the pin number and same thing happened so..

That is the debug_tt triggering from a pin CHANGE:: debug_fault >>>> TYPE:isr

In this statement :: debBegin_tt( (HardwareSerial*)&SERIAL_tt, LED_BUILTIN, BUTTON_ISR);

The param 'BUTTON_ISR' pin is being changed in the code/hardware.

Change that to NO_ISR (255) or a pin you might want to use to break into the code while it is running.
 
It looks to be working - very washed out - very bright backlight on this unit?
>> Placing a 1 sec delay in setup last fill screen on black (0,0,0) it shows as gray.

Edits to this:: #define SPICLOCK 48000000
Code:
24M:311
32M:245
48M:183
60M:183 << No faster
 
@KurtE

Progress on the SSD1351 UncannyEyes. Turns out the primary problem with running 2 LED displays is power. I added a external supply to supply power to the OLEDs and got the eyes to display. But still have some problems.

Using this for the eyes:
Code:
  //{ 10, 0, 0, 0 }, // LEFT EYE display-select and wink pins, no rotation
  { 5, 2, 0, 0 }, // LEFT EYE display-select and wink pins, no rotation
I got an eye to display on each display individually. When I try to display on both I wind up with both the eyes displaying on last eye configured - weird effect though :). In other words in the case above both eyes will display on the OLED on C/S pin 5.

@defragster - cool that you got that RPI display working. Fun isn't it.
 
@... :D

@mjs513 - Which library are you using? Adafruit? Or the one I have been modifying? I assume the later... Remember there are pieces of the uncannyEyes that I had #ifdefed out in the case of this library as did not find easy way to do so in the other library...

Like: There is no setRotation - Note: the way I had it setup the display was being used with single buffer mode (like useFrameBuffer in my stuff) so all of the drawPixel like calls are just setting value in memory... So probably would not be hard to update... Or maybe there already is a way...

Also there was some code that was used on 2nd eye to mirror stuff, by setting some values on the hardware. At the time there was no sendCommand like code. I added that code yesterday, to maybe allow that, but did not try it out... (Don't have 2nd display so not sure again if it would work). At a minimum I believe if you enable it, not all of the constants (Operation codes) will be defined as they came from Adafruit, but should not be hard to just add those local to sketch...)

@defragster - Yep RPI one is sort of an interesting animal...
As for setting SPI speeds - When you ask for 60mhz not sure which speed you are actually getting...
I think we default the SPI clock to 528mhz (PLL2) I think this translates to something like: 528/9= about 58.6mhz...

But could be wrong..
 
@KurtE

Wanted to let you know about the power issue using 2 OLEDs. Remember you told me about SendCommand yesterday :). There are so many ifdef's in there to cover the different displays I didn't even notice :). Was just happy about getting it working with the 2 displays attached. Will take a look - been doing errands today :)
 
@mjs513 - Yep lots of #ifdef stuff... Most of the stuff for this other library was under #else...
That is there was #if for the tft displays, then #elif for the adafruit OLED library and then #else for this one... As I did not see any good define to check directly for other library... it uses #pragma ONCE or the like...


It will be interesting to see well setting the remap register will work...
Code:
   // If OLED, loop through ALL eyes and set up remap register
    // from either mirrorOLED[] (first eye) or rotateOLED[] (others).
    // The OLED library doesn't normally use the remap reg (TFT does).
    for (e = 0; e < NUM_EYES; e++) {
      eye[e].display->sendCommand(SSD1351_CMD_SETREMAP, e ?
                                  &rotateOLED[eyeInfo[e].rotation & 3] :
                                  &mirrorOLED[eyeInfo[e].rotation & 3], 1);
    }
Hopefully it should just work... Although again I did not handle any of the rotation code earlier...

Alternative to both of these... Could simply try changing the call:
eye[e].display->drawPixel(screenX,screenY,p);
For this library to when necessary (for rotation and which eye) to swap X,Y and maybe change X to be something like (width-1)-x...
 
@KurtE - @defragster

Ok - got it displaying on both screens now - actually turned out easy fix but had to add one function to your lib :)

Here is my kludged up version just for the SSD1351 - didn't put the mirror/rotate sendcommand in the right spot:
View attachment uncannyEyes.zip

Added this function to your lib, just a combined sendcommand:
Code:
	void sendCommand(uint8_t commandByte, uint8_t *dataBytes, uint8_t numDataBytes) {

		beginSPITransaction();
		sendCommandAndContinue(commandByte);
		for (int i=0; i<(numDataBytes-1); i++) {
		  sendDataAndContinue(*dataBytes++); // Send the data bytes
		}
		sendLastData(*dataBytes++);
		endSPITransaction();
	}
 
Hi @mjs513 - I think the version up on github currently has the sendCommand (I put it in yesterday ;) )

But have not tested it:
Code:
    void sendCommand(uint8_t commandByte, const uint8_t *dataBytes, uint8_t numDataBytes) {
	    beginSPITransaction();
	    if (numDataBytes) {
	    	sendCommandAndContinue(commandByte);
    		for (uint8_t i=0; i<(numDataBytes-1); i++) {
	  			sendDataAndContinue(*dataBytes++); // Send the data bytes
    		}
    		sendLastData(*dataBytes);
	    } else {
	    	sendLastCommand(commandByte);
	    }
  
    	endSPITransaction();

    }

Mentioned in post #314
 
@KurtE

Oops - sorry I misunderstood thought you were referring to the other sendcommands - sorry my bad. Will have to download the latest copy. Only problem now I am running into is that that after a few frames the animation stops sometimes. Resetting it a couple of times seems to get it working fully. Will try with your latest version

<EDIT>
Download your lasted using
Code:
  { 10, 0, 0, 0 }, // LEFT EYE display-select and wink pins, no rotation
  { 5, 2, 0, 0 }, // LEFT EYE display-select and wink pins, no rotation
Still freezes after a few eye movements.

Code:
  { 10, 0, 0, 0 }, // LEFT EYE display-select and wink pins, no rotation
  //{ 5, 2, 0, 0 }, // LEFT EYE display-select and wink pins, no rotation
This works no problem showing left eye only

Code:
  { 10, 0, 0, 0 }, // LEFT EYE display-select and wink pins, no rotation
  //{ 5, 2, 0, 0 }, // LEFT EYE display-select and wink pins, no rotation
This on the other hand will display eyes on both displays - hehehe.
 
Last edited:
Back
Top