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

Got it - guess I am getting itchy again :)

This probably should go on the T4 thread but - I hooked up a 5v SR05 sonar sensor through a level shifter to the T4, which I have mounted on a HS-645MG servo. So using the graph function from Kris K's example I got it plotting real-time sonar data on a x-y plot using a ILI9341 display and your ILI9341_t3n library. It works perfectly. Too bad no pictures yet. Just playing with real world examples now.

EDIT: You know I am eventually going to play with some of that stuff - just looking at a few of their options, arcs and pushColor so you can get dotted lines :)
 
@KurtE

Since you have become the defacto expert on displays (yes I am being a buster). I am trying to get a 3d engine working with either the ILI9341 and/or the ILI9488 libraries that I found here: https://github.com/michaelerule/Uno9341TFT - see video: https://vimeo.com/150386845. But I am kind of stuck on a function and what he is really doing. Since its avr he has some port stuff involved but not 100% sure about the macros - it looks like this macro "IDENTITY(color>>8)" is just returning the high byte of the color, and this one "IDENTITY(color);" the low byte? Then in the function he is sending the pair of bytes - probably should just send the color. Any advice would be appreciated.
Code:
Macros

//////////////////////////////////////////////////////////////////////////
// Color reading and writing

#define QUICK_READ PIND

//////////////////////////////////////////////////////////////////////////
// Permutations between color bit order and port bit order.
// In the Leonardo these are complex, and are computed ahead of time
// to speed up IO.
// On the Uno, these permutations can be replaced by the identity map.

// Send color data from 565 format into the permuted representation
// for faster IO
#define BIT_TO_PORT_PERMUTATION(b) b
#define PORT_TO_BIT_PERMUTATION(b) b
#define WRITE_PERMUTED_BUS(d) WRITE_BUS(d)
#define IDENTITY(b) BIT_TO_PORT_PERMUTATION(PORT_TO_BIT_PERMUTATION(b))
#define PERMUTED_QUICK_READ QUICK_READ
======================================================
//Functions

void Arduino_TFTLCD::fastFlood(uint8_t c, uint16_t l) {
    flood( 0x0101*c, l);
}

// Very fast flood routine. 
void Arduino_TFTLCD::flood(uint16_t color, uint32_t len) {
    uint8_t  i;
    uint8_t hi = IDENTITY(color>>8);
    uint8_t lo = IDENTITY(color);
    START_PIXEL_DATA();

        if(hi == lo) {
            WRITE_BUS(color);
            while (len>=128) {
                CLOCK_128;
                len-=128;
            } 
            if (len &0b01000000) { CLOCK_64; }
            if (len &0b00100000) { CLOCK_32; }
            if (len &0b00010000) { CLOCK_16; }
            if (len &0b00001000) { CLOCK_8; }
            if (len &0b00000100) { CLOCK_4; }
            if (len &0b00000010) { CLOCK_2; }
            if (len &0b00000001) { CLOCK_1; }
        } else {
            uint16_t blocks = (uint16_t)(len/32); 
            while(blocks--) {
              i = 4;
              do {
                SEND_PAIR(hi,lo); SEND_PAIR(hi,lo); 
                SEND_PAIR(hi,lo); SEND_PAIR(hi,lo);
                SEND_PAIR(hi,lo); SEND_PAIR(hi,lo); 
                SEND_PAIR(hi,lo); SEND_PAIR(hi,lo);
              } while(--i);
            }
            for(i = (uint8_t)len&31; i--; ) SEND_PAIR(hi,lo);
        }
}
 
My impression of the function is it is outputting a 8 bit color? what it thinks is very fast...

My AVR register stuff is pretty rusty, but I think this is using a parallel interface to the display, It is using 2 or 3 IO ports to talk to the display.
So the WRITE_BUS(color);

Is doing:
#define WRITE_BUS(b) {\
PORTB=PORTD=(b);\
}
So it is setting portB and portD to the one color (8 bits).

Then the CLOCK_macros all end up: just inline toggle of the IO pins N times:
Code:
#define CLOCK_1   {CLOCK_DATA; CLOCK_DATA;};
#define CLOCK_2   {CLOCK_1   CLOCK_1};
#define CLOCK_4   {CLOCK_2   CLOCK_2};
#define CLOCK_8   {CLOCK_4   CLOCK_4};
#define CLOCK_16  {CLOCK_8   CLOCK_8};
#define CLOCK_32  {CLOCK_16  CLOCK_16};
#define CLOCK_64  {CLOCK_32  CLOCK_32};
#define CLOCK_128 {CLOCK_64  CLOCK_64};
#define CLOCK_256 {CLOCK_128 CLOCK_128};

Where Clock_data:
Code:
#define CLOCK_DATA {\
    READY_DATA;\
    SEND_DATA;\
}\
Where:
Code:
#define READY_COMMAND     CONTROLPORT=(DEFAULT|RD_FLAG)
#define SEND_COMMAND      CONTROLPORT=(DEFAULT|RD_FLAG|WR_FLAG)
So on UNO, they have the CONTROLPORT as #define CONTROLPORT PORTC
And in this port they have the other display signals:
Code:
#define RS_PIN 4
#define CS_PIN 3
#define CD_PIN 2
#define WR_PIN 1
#define RD_PIN 0
So the CLOCK_DATA: Turns off the Write bit and turns it back on... So it toggles the data out... Twice...
And when the data of high byte does not equal low byte, it calls off through:
Code:
#define _SEND_PAIR(hi,lo) {\
    WRITE_BUS(hi);\
    CLOCK_DATA;\
    WRITE_BUS(lo);\
    CLOCK_DATA;\
}
So it alternates setting B and D buss to the high and low byte and the then clock the data which clears and then sets the data bit in Port C ...
 
@KurtE

Thanks for the explanation - think that explains what is going. That is the only one that stumped me. From the way it looks can pretty much ditch everything in that function and just use our write16BitColor function to send the color: write16BitColor(uint16_t color, uint16_t count, bool last_pixel). Right now the goal is just to get it working then fix up what I messed up :)

Will keep you posted on how it goes. Almost ready to give it try but first a nap - was up all night, not feeling well.
 
With the Teensy 3.2-3.6, I mostly saw that it was the SSD1306 (OLED screens) that were problematical with higher SPI bus speeds. I don't recall having to slow down the SPI bus for the ST7735, but it maybe at the faster Teensy 4 speeds you do.

Just a note, though this is SSD1306 related, and possibly not ST7735, ILI9488, or ST7789 related. I recently switched setups for uncanny eyes:
  • I soldered up a protoboard for doing displays (as opposed to using breadboards);
  • I added 2.2K pull-up resistors between each of the two CS pins (23 and 22 currently) and 3.3v;
  • For flexibility, I use a switch to switch between using 23 and 10 for the first CS line and 22 and 9 for the second CS line (using pin 15/A1 for D/C);
  • I used a new pack of dupont wiring to connect between the displays and the protoboard instead of the older wiring (which at times could come loose and the pin getting pushed out).

I can now run the two Adafruit SSD1306 displays with a SPI clock speed of up to 19Mhz. I don't see any corruption on the screen. I did cut the SPI speed down slightly to 18Mhz, as the frame rate was the same between 19Mhz and 18Mhz.

Before moving to the protoboard, I tried the pull-up resistors on the breadboard (using the old wiring) and I still got some corruption about 11Mhz.

The pull-up resistors comes from Paul's paper about better SPI bus design:
 
@MichaelMeissner

Haven't tried the SSD1306's with uncanny eyes just the ST7735's and SSD1351's. Think this thread has turned into the display driver thread, which is alright. When the ST7735's work (I don't hang the usb port) there is no problem with running UncannyEyes - don't see any corruption in the data. This is at 24Mhz as well. Only time I loose USB and the T4 hangs is if I try to change any settings in the config file. Got around that by adding a single printf statement (no a delay doesn't work). Think I had a problem with the 1351's but don't remember what it was but I did run into another interesting scenario where the resistors on the CS lines might work out. Have to try it out.

The pull-up resistors comes from Paul's paper about better SPI bus design:
https://www.pjrc.com/better-spi-bus-design-in-3-steps/
Think that should be mandatory reading :) That's where I figured out what to do with the tri-state buffer
 
@KurtE

Something strange going on with fillTriangle and the 9488 display. I was testing some of the changes i made for the 3D functions and was testing one of the demos that uses fillTriangles. The image is comprised of 4 trianges with vertices in the corner and basically the others at 1/2 width and height. Wound up adding drawTriangles just for reference which seem to work. This is what i am getting and the code follows:

20190806_162946.jpg

Code:
 #include "ILI9488_t3.h"

ILI9488_t3 tft = ILI9488_t3(&SPI, 10, 9, 8);

void setup() {
  tft.begin();
  tft.setRotation(2);
  tft.fillScreen(ILI9488_BLACK);
}

#define DELAY 500

void loop() { 
    tft.drawTriangle( 0,0,   160,0,  0,240,  ILI9488_WHITE);
  tft.fillTriangle( 0,0,   160,0,  0,240,  ILI9488_BLUE);
    tft.drawTriangle( 310,0, 160,0,  310,240, ILI9488_WHITE);
  tft.fillTriangle( 310,0, 160,0,  310,240, ILI9488_ORANGE);
    tft.drawTriangle( 310,460, 160,460, 310,240, ILI9488_WHITE);
  tft.fillTriangle( 310,460, 160,460, 310,240, ILI9488_GREEN);
  tft.fillTriangle( 0,460,  160,460,   0,240, ILI9488_YELLOW);
    tft.drawTriangle( 0,460,  160,460,   0,240, ILI9488_WHITE);

  delay(DELAY);
}
Can't see the problem.
 
Actually if you look at ili9341_t3n log on April 8th, there was a fix for fillTriangles.

So in ILI9488.t3.cpp line 2147, try changing int16_t to int32_t...

And see if that helps
 
Actually if you look at ili9341_t3n log on April 8th, there was a fix for fillTriangles.

So in ILI9488.t3.cpp line 2147, try changing int16_t to int32_t...

And see if that helps

Yeah that got it working. I was looking but didn't see that difference - something was telling me just to recopy the function.
 
@KurtE

When I try to compile ILI9341_t3n for T4, I get the following error:

ILI9341_t3n.cpp:1946:6: error: '_pkinetisk_spi' was not declared in this scope

Preceding that is a "#ifdef SPIN2_OBJECT_CREATED"...

Do you get that error when trying to compile for T4? (edited for my incorrect line number reading)
 
Last edited:
@KurtE - @wcalvert

I can confirm with the latest. Looks like line1946 needs to be replaced with what you did for SPIN1, i.e., 1946 should be:
Code:
#ifdef KINETISK
				_pkinetisk_spi = &_pspin->port();
#elif defined(__IMXRT1052__) || defined(__IMXRT1062__)  // Teensy 4.x 
				_pimxrt_spi = &_pspin->port();
#else
				_pkinetisl_spi = &_pspin->port();
#endif
 
@wcalvert, @mjs513 - Try syncing again. I believe all of this was fixed in my other branch, that I had done the work to fix the DMA issue for T4, plus added support for multiple displays with frame buffers....
So I merged those changes in the master branch.
 
@KurtE

Thanks - will do. BTW: have you ever tried to use readPixel function. Every time I try it, it returns 0 even if I do a fillScreen of RED? Haven't tried it yet on a T3.6 though - only on a T4?
 
It has been awhile since I tried it... May have to pull out boards again...

I should ask, which display? ili9341 or ili9488 or ...
 
Last edited:
@mjs513 - May have to look at the readPixel. I do have tests that use readRect. Like my

View attachment Kurts_ILI9341_t3n_FB_and_clip_tests-190808a.zip

Which draws some stuff on the screen, then does a readRect and then does a writeRect that is offset on the display, as to see if they are working. When you hit CR it alternates between using frame buffer and not using frame buffer, and in both cases, it looks like it is reading the data...

But maybe I need to verify that it is reading all of the data correctly...
Currently for non KINETISK chips readPixel is doing:
Code:
uint16_t ILI9341_t3n::readPixel(int16_t x, int16_t y)
{
	uint16_t colors = 0;
	readRect(x, y, 1, 1, &colors);
	return colors;
}

EDIT: In the above sketch I added a quick and dirty test:
Code:
  tft.readRect(0, 0, 50, 50, pixel_data);
  // For heck of it lets make sure readPixel and ReadRect 
  // give us same data, maybe check along diagnal?
  for (uint i=0; i < 50; i++) {
    uint16_t pixel_color = tft.readPixel(i,i);
    if (pixel_color != pixel_data[i*50+i]) {
      DBGSerial.printf("Read rect/pixel mismatch: %d %x %x\n", i, pixel_color,pixel_data[i*50+i]);
    }    
  }
The readRect was already there.

I have run this and so far I am not seeing any of the messages.
 
@KurtE
Thanks for the test case. I just ran it on the ILI9488 with the T4 and got the following results with a couple of mismatches:
Code:
ILI9488_t3n: (T4) SPI automatically selected

Use FB: 0 Read rect/pixel mismatch: 1 f000 0
Read rect/pixel mismatch: 4 c000 0
Read rect/pixel mismatch: 8 8000 0
Read rect/pixel mismatch: 15 8000 0
Read rect/pixel mismatch: 43 fc00 0

Now on the T4 with the ILI9341 display I don't any messages. But, out of curiosity I changed the test to for mismatch to match, i.e., pixel_color != pixel_data[i*50+i and I get:
Code:
Read rect/pixel mismatch: 0 0 0
Read rect/pixel mismatch: 1 0 0
Read rect/pixel mismatch: 2 0 0
Read rect/pixel mismatch: 3 0 0
Read rect/pixel mismatch: 4 0 0
Read rect/pixel mismatch: 5 0 0
Read rect/pixel mismatch: 6 0 0
Read rect/pixel mismatch: 7 0 0
Read rect/pixel mismatch: 8 0 0......
 
Looks like I need to look again at ILI9488... Need to see where I put the display and what wires go where...

As for the test program on ILI9481...
IMG_0130-(002).jpg
You should see the word Test and Text near upper left corner of display, and then the readRect/writeRect should make a copy of part of it toward the upper Right as you can see in this image...
And if you don't see this, I would double check the MISO pin (12) to make sure you have good connection

Edit: I think you are going through some level shifter/buffer ship for your MISO? As it was in conflict with other MISO pins? I don't remember if @defragster for example may have cut the etch or the like for that pin on his?
 
Note: It appears like I am not receiving any data back on my MISO line as well with the one display (ILI9488...)
 
@KurtE

You ready for the confusion now that you showed me what the screen is suppose to look like.

On the T3.6 with the ILI9341 I see exactly the same image as in your previous post with the following output:

Code:
Display Power Mode: 0x2
MADCTL Mode: 0x0
Pixel Format: 0x2
Image Format: 0x0
Self Diagnostic: 0x0
Use FB: 0 Read rect/pixel mismatch: 2 ffff 9cf3
Read rect/pixel mismatch: 8 ffff 9cf3
Read rect/pixel mismatch: 9 ffff 9cf3
Read rect/pixel mismatch: 10 ffff 9cf3
Read rect/pixel mismatch: 11 ffff 9cf3
Read rect/pixel mismatch: 12 f618 8cf0
Read rect/pixel mismatch: 35 f800 0
Read rect/pixel mismatch: 36 f800 2000
Read rect/pixel mismatch: 37 f800 0
Read rect/pixel mismatch: 38 f800 2000
Read rect/pixel mismatch: 39 f800 0
Read rect/pixel mismatch: 42 7bef ffff
Read rect/pixel mismatch: 43 7bef ffff
Read rect/pixel mismatch: 44 7800 f800
Read rect/pixel mismatch: 45 7800 f800
Read rect/pixel mismatch: 46 7800 f800
Read rect/pixel mismatch: 47 7800 f800
Read rect/pixel mismatch: 48 7800 f800
Read rect/pixel mismatch: 49 7be0 ffff
128

On the T4 with the ILI9341 display I don't see anything in the upper right hand corner and some of the rectangles are not showing:
20190808_160124.jpg
and I get this:
Code:
Display Power Mode: 0x0
MADCTL Mode: 0x80
Pixel Format: 0x87
Image Format: 0x85
Self Diagnostic: 0x87
Use FB: 0 Read rect/pixel mismatch: 1 2000 0
Read rect/pixel mismatch: 8 8000 0
Read rect/pixel mismatch: 9 8000 0
Read rect/pixel mismatch: 12 8000 0
108

On the T4 both displays look like what I posted for the ILI9488?
 
Note: It appears like I am not receiving any data back on my MISO line as well with the one display (ILI9488...)

Oops missed this post. Tested with and without the tri-state buffer on the miso. Pretty much the same results
 
Back
Top