Screen refresh is too slow, Colors are Inverted(And other TFT woes)

Hey there folks,

Recently bought a cheap Chinese 2.4" TFT screen off of ebay(not SPI, lots of cabling). For my latest project I’m building a telemetry screen for my computer. I’m using a Nano V3 for controller. C# program I’ve coded will send some data to MC via serial, which in turn will write it to TFT.

I wanted to understand how TFTs work before I started with the rest of the project. After some struggles I’ve managed to make the LCD work. But having some problems. Wondered if anyone could help.

Here are the problems.

**1)**Colors are reversed. If I use tft.setTextColor(CYAN,WHITE); I get red text with black background. Colors are defined thusly

#define  BLACK   0x0000
#define BLUE    0x001F
#define RED     0xF800
#define GREEN   0x07E0
#define CYAN    0x07FF
#define MAGENTA 0xF81F
#define YELLOW  0xFFE0
#define WHITE   0xFFFF

I checked the wiring. It appears to be correct. So it must be driver related. For reference, lcd controller is SPFD5408. I’m using the library from here

**2)**Is there a way to bypass arduino and do the drawing directly with PC hardware? Some sort of pass-thru? In my case, arduino will always be connected to computer, and the data which TFT will display will come always from the computer. I feel like there should be a way to pass data straight to LCD, bypassing Nano. If I’m not mistaken, the display on Logitech G15(my inspiration for this project) works on such a principle.

3)This last one is kinda generic, but I still can’t find the solution to it. Screens refreshes too slowly. Considering this same screen is capable of playing video when connected to the Raspberry Pi, I know it’s Arduino related. I’ve found some libraries which claim to be 10-20 times faster than the adafruit one. But none of them has built in support for my display. It’s probably possible to port my LCD chip’s driver to them, but I’m not remotely as good a programmer to even attempt it.

Here is the sample code I use to test the screen. It literally takes 3 seconds to go through all the screen. In the real project I won’t really need to change all that many pixels at once but considering I need at least about 24hz refresh rate. It just won’t do.

void loop(void){
  tft.fillRect(2,2,randNumber,2,BLUE); //Kinda simulates a graph
  //delay(100);
  
  for (int begy = 10; begy < 200; begy = begy+ 20){ //Begining pixels for X and Y
    for(int begx =0; begx <300; begx = begx+50){     //
      tft.setCursor(begx,begy);
      tft.setTextSize  (2);
      tft.setTextColor(CYAN,WHITE);
      tft.println(randNumber+ begy);
      }   
    }
    tft.fillRect(2,2,randNumber,2,RED);

  
  randNumber = random (0,318);
  //delay(100);
  
  }

Bonus Question) What other MCs out there that has good LCD support and high clock speeds? I don’t wanna use rPi for this project. What I’m trying to accomplish shouldn’t require 4 cores running at 700mhz. I briefly considered Teensy 3.1 but, I’ve never used it before and also down the line I’m planning to do some small scale production of this project. And I don’t want the added complexity(and cost) of a 32 bit processor if I can help it.

you could start with optimize the loop by moving non changing parts out of it.
and add a “real” time measurement.

uint32_t start = 0;
uint32_t stop = 0;

void loop(void)
{
  randNumber = random(0, 318);

  tft.fillRect(2, 2, randNumber, 2, BLUE); // Kinda simulates a graph

  tft.setTextSize(2);
  tft.setTextColor(CYAN, WHITE);  

  start = millis();
  for (uint8_t  begy = 10; begy < 200; begy += 20) 
  {
    for(int begx = 0; begx < 300; begx += 50)
    {
       tft.setCursor(begx, begy);
       tft.print(randNumber + begy);
    }   
  }
  stop = millis();
  Serial.print("duration: ");
  Serial.println(stop - start);
  tft.fillRect(2, 2, randNumber, 2, RED);
}

give it a try

robtillaart:
you could start with optimize the loop by moving non changing parts out of it.
and add a “real” time measurement.

uint32_t start = 0;

uint32_t stop = 0;

void loop(void)
{
 randNumber = random(0, 318);

tft.fillRect(2, 2, randNumber, 2, BLUE); // Kinda simulates a graph

tft.setTextSize(2);
 tft.setTextColor(CYAN, WHITE);

start = millis();
 for (uint8_t  begy = 10; begy < 200; begy += 20)
 {
   for(int begx = 0; begx < 300; begx += 50)
   {
      tft.setCursor(begx, begy);
      tft.print(randNumber + begy);
   }  
 }
 stop = millis();
 Serial.print("duration: ");
 Serial.println(stop - start);
 tft.fillRect(2, 2, randNumber, 2, RED);
}




give it a try

Thanks for the reply. Added timing to my code. 1819ms. Yours is 1820ms. Doesn’t seem to help.

Thought maybe the loop itself was taking up the cycles. Removed the TFT code althogether and left only the loop and timing. Shows 0ms. Interesting, I didn’t think 328P go thru that loop under a milisecond. Got curious and started to expand the loop. Never really realized how much power was in those little 8 bit processors.

So the setTestsize and color do not take serious time

you can use micros() if you want finer timing granularity

The library is the next to investigate

void Adafruit_GFX::setCursor(int16_t x, int16_t y) {
 cursor_x = x;
 cursor_y = y;
}

that is no killer, so the one that takes all the time is

tft.print(randNumber + begy);

and as GFX is derived from Print class we must check the write() implementation.

#if ARDUINO >= 100
size_t Adafruit_GFX::write(uint8_t c) {
#else
void Adafruit_GFX::write(uint8_t c) {
#endif
  if (c == '\n') {
    cursor_y += textsize*8;
    cursor_x  = 0;
  } else if (c == '\r') {
    // skip em
  } else {
    drawChar(cursor_x, cursor_y, c, textcolor, textbgcolor, textsize);
    cursor_x += textsize*6;
    if (wrap && (cursor_x > (_width - textsize*6))) {
      cursor_y += textsize*8;
      cursor_x = 0;
    }
  }
#if ARDUINO >= 100
  return 1;
#endif
}

some math and compares that take few micros (math can be tweaked a bit, no big win)
but drawChar() is the workhorse here

// Draw a character
void Adafruit_GFX::drawChar(int16_t x, int16_t y, unsigned char c,
			    uint16_t color, uint16_t bg, uint8_t size) {

  if((x >= _width)            || // Clip right
     (y >= _height)           || // Clip bottom
     ((x + 6 * size - 1) < 0) || // Clip left
     ((y + 8 * size - 1) < 0))   // Clip top
    return;

  if(!_cp437 && (c >= 176)) c++; // Handle 'classic' charset behavior

  for (int8_t i=0; i<6; i++ ) {
    uint8_t line;
    if (i == 5) 
      line = 0x0;
    else 
      line = pgm_read_byte(font+(c*5)+i);
    for (int8_t j = 0; j<8; j++) {
      if (line & 0x1) {
        if (size == 1) // default size
          drawPixel(x+i, y+j, color);
        else {  // big size
          fillRect(x+(i*size), y+(j*size), size, size, color);
        } 
      } else if (bg != color) {
        if (size == 1) // default size
          drawPixel(x+i, y+j, bg);
        else {  // big size
          fillRect(x+i*size, y+j*size, size, size, bg);
        }
      }
      line >>= 1;
    }
  }
}

(math that can be tweaked a bit)

The call to fillRect() seems the bigger load here

// note all tests in the top, they are done every time,
// a leaner drawChar can be made IF the programmer takes care of the coordinates

lets look at fillRect()

void Adafruit_GFX::fillRect(int16_t x, int16_t y, int16_t w, int16_t h,
			    uint16_t color) {
  // Update in subclasses if desired!
  for (int16_t i=x; i<x+w; i++) {
    drawFastVLine(i, y, h, color);
  }
}

and drawFastVLine()

void Adafruit_GFX::drawFastVLine(int16_t x, int16_t y,
				 int16_t h, uint16_t color) {
  // Update in subclasses if desired!
  drawLine(x, y, x, y+h-1, color);
}

note we are already some levels deep ! and this is just calling a wrapper waste of cycles

dive into drawLine()

void Adafruit_GFX::drawLine(int16_t x0, int16_t y0,
			    int16_t x1, int16_t y1,
			    uint16_t color) {
  int16_t steep = abs(y1 - y0) > abs(x1 - x0);
  if (steep) {
    swap(x0, y0);
    swap(x1, y1);
  }

  if (x0 > x1) {
    swap(x0, x1);
    swap(y0, y1);
  }

  int16_t dx, dy;
  dx = x1 - x0;
  dy = abs(y1 - y0);

  int16_t err = dx / 2;
  int16_t ystep;

  if (y0 < y1) {
    ystep = 1;
  } else {
    ystep = -1;
  }

  for (; x0<=x1; x0++) {
    if (steep) {
      drawPixel(y0, x0, color);
    } else {
      drawPixel(x0, y0, color);
    }
    err -= dy;
    if (err < 0) {
      y0 += ystep;
      err += dx;
    }
  }
}

more math for every line… possible double swaps… expensive abs function calls
Bresenham line algorithm is good but remember we are drawing a vertical line so Bresenham is overkill,
B. is only good for non vertical or horizontal lines.

OK and what does drawPixel do? (note we now are in /SPFD5408_Adafruit_TFTLCD.cpp )

void Adafruit_TFTLCD::drawPixel(int16_t x, int16_t y, uint16_t color) {

  // Clip
  if((x < 0) || (y < 0) || (x >= _width) || (y >= _height)) return;

  CS_ACTIVE;
  if(driver == ID_932X) {
    int16_t t;
    switch(rotation) {
     case 1:
      t = x;
      x = TFTWIDTH  - 1 - y;
      y = t;
      break;
     case 2:
      x = TFTWIDTH  - 1 - x;
      y = TFTHEIGHT - 1 - y;
      break;
     case 3:
      t = x;
      x = y;
      y = TFTHEIGHT - 1 - t;
      break;
    }
    writeRegister16(0x0020, x);
    writeRegister16(0x0021, y);
    writeRegister16(0x0022, color);

  } else if(driver == ID_7575) {

    uint8_t hi, lo;
    switch(rotation) {
     default: lo = 0   ; break;
     case 1 : lo = 0x60; break;
     case 2 : lo = 0xc0; break;
     case 3 : lo = 0xa0; break;
    }
    writeRegister8(   HX8347G_MEMACCESS      , lo);
    // Only upper-left is set -- bottom-right is full screen default
    writeRegisterPair(HX8347G_COLADDRSTART_HI, HX8347G_COLADDRSTART_LO, x);
    writeRegisterPair(HX8347G_ROWADDRSTART_HI, HX8347G_ROWADDRSTART_LO, y);
    hi = color >> 8; lo = color;
    CD_COMMAND; write8(0x22); CD_DATA; write8(hi); write8(lo);

  } else if ((driver == ID_9341) || (driver == ID_HX8357D)) {
    setAddrWindow(x, y, _width-1, _height-1);
    CS_ACTIVE;
    CD_COMMAND; 
    write8(0x2C);
    CD_DATA; 
    write8(color >> 8); write8(color);
  }

  CS_IDLE;
}

The clipping test is not needed as we already did check that on higher level functions (drawChar)

did not dive deeper …


epilogue

to speed up I would reimplement the drawFastVLine() to this first.

void Adafruit_GFX::drawFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color) 
{
  int16_t y1 = y + h -1;
  for (int16_t y0 = y; y0 <=y1; y0++) drawPixel(x, y0, color);
}

in a similar way you can reimplement a drawFastHLine()

better rewrite fillRect() too

void Adafruit_GFX::fillRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color) 
{
  // insert clipping before the double loop?
  // if (x+w > _width) w = _width - x; 
  // if (y+h > _height) h = _height - y;
  for (int x0=x; x0 < x+w; x0++)
  {
    for (int y0=y; y0 < y+h; y0++)
    {
      drawPixel(x, y0, color);
    }
  }
}

please give it a try

FYI I raised an issue for these optimizations in the library - https://github.com/JoaoLopesF/SPFD5408/issues/2 -

The colour inversion has too wait :)

Thank you for your suggestions. Removing clipping check makes sense. Done them all, results are not what I expected…

Timing I got from the serial hasn’t changed at all for the 3 digit numbers. 1918ms
Timing for 2 digit numbers have changed to 1213. ms

I thought maybe the modified library wasn’t getting used, so restarted the IDE. No change.

One would think removing the clipping check for every pixel drawn would make a difference… Here is the code I used:

// IMPORTANT: Adafruit_TFTLCD LIBRARY MUST BE SPECIFICALLY
// CONFIGURED FOR EITHER THE TFT SHIELD OR THE BREAKOUT BOARD.
// SEE RELEVANT COMMENTS IN Adafruit_TFTLCD.h FOR SETUP.

// *** SPFD5408 change -- Begin
#include <SPFD5408_Adafruit_GFX.h>    // Core graphics library
#include <SPFD5408_Adafruit_TFTLCD.h> // Hardware-specific library
#include <SPFD5408_TouchScreen.h>
// *** SPFD5408 change -- End

// The control pins for the LCD can be assigned to any digital or
// analog pins...but we'll use the analog pins as this allows us to
// double up the pins with the touch screen (see the TFT paint example).
#define LCD_CS A3 // Chip Select goes to Analog 3
#define LCD_CD A2 // Command/Data goes to Analog 2
#define LCD_WR A1 // LCD Write goes to Analog 1
#define LCD_RD A0 // LCD Read goes to Analog 0

#define LCD_RESET A4 // Can alternately just connect to Arduino's reset pin

// Assign human-readable names to some common 16-bit color values:
#define  BLACK   0x0000
#define BLUE    0x001F
#define RED     0xF800
#define GREEN   0x07E0
#define CYAN    0x07FF
#define MAGENTA 0xF81F
#define YELLOW  0xFFE0
#define WHITE   0xFFFF

Adafruit_TFTLCD tft(LCD_CS, LCD_CD, LCD_WR, LCD_RD, LCD_RESET);
// If using the shield, all control and data lines are fixed, and
// a simpler declaration can optionally be used:
// Adafruit_TFTLCD tft;

long randNumber;

void setup(void) {
  Serial.begin(9600);
  Serial.print("TFT size is "); Serial.print(tft.width()); Serial.print("x"); Serial.println(tft.height());
  tft.reset();
  tft.begin(0x9341);
  tft.setRotation(1);
  tft.fillScreen(WHITE);
  tft.fillRect(0,0,320,10,RED);
  randomSeed(analogRead(0));

  
}

uint32_t start = 0;
uint32_t stop = 0;

void loop(void){
  tft.fillRect(2,2,randNumber,2,BLUE); //Kinda simulates a graph
  //delay(100);
  start = millis();
  for (int begy = 10; begy < 200; begy = begy+ 20){ //Begining pixels for X and Y
    for(int begx =0; begx <300; begx = begx+50){     //
      tft.setCursor(begx,begy);
      tft.setTextSize  (2);
      tft.setTextColor(CYAN,WHITE);
      tft.println(randNumber);
      }   
    }
    stop = millis();
    Serial.print("duration: ");
    Serial.println(stop - start);
    Serial.print("random: ");
    Serial.println(randNumber);
    tft.fillRect(2,2,randNumber,2,RED);

  
  randNumber = random (0,318);
  //delay(100);
  
  }

And here are the modified libraries

Strange, I really expect it would make a difference. As I do not have such display I cannot check.

your tests with 2 and 3 digit numbers seem to be constent ~600+ millis per digit.

Can you make a small test sketch to measure the time of drawPixel() ? (use micros)

update: my fillRect proposed code above should use drawPixel(x0, ... iso drawPixel(x, ...

Done. Here is the sketch I’ve made. It looks kinda cool when you run it. Matrixlike :smiley:

void loop(void){
  start = millis();  
  for (int begy = 10; begy < 235; begy = begy+ 5){ //Begining pixels for X and Y
    for(int begx =0; begx <300; begx = begx+50){
      tft.fillRect(begx,begy,40,2,WHITE);
      tft.fillRect(begx,begy,random(0,40),2,BLUE);    

      }   
    }
    stop = millis();
    Serial.print("duration: ");
    Serial.println(stop - start);
    
  }

Time is 230ms. That’s actually not that bad. It appears that drawing text is far more costly than rectangles.

I also loaded it up with the unmodified libraries. Still no differnce. ~230ms.

Quick note: Arduino Mega has arrived. Plugged the tft screen to it. Figured Mega's beefier CPU would help. Instead it's twice as slow :confused:

Nano v3 used to run the same code in 1918ms. Mega is running it in 3244ms. How come Nano run the same code that fast?

EDIT: After that, I tried it with Uno R3. Same performance as Nano 1918ms. It's really strange that the mega'd perform worse.

You are using a Shield that is designed for a UNO. If you look on the back, it even tells you which Arduino pins are connected.

It is extremely convenient to plug one standard shield into a standard Arduino. All the wiring is known to the rest of the world.

If you look at the data pins ( LCD_D0 .. LCD_D7 ), you can see that you have them spread over several ports. With a UNO it is easy to map. e.g. PORTB, PORTD With a MEGA it is very complex. With a DUE it is horrific With a Zero it is fairly complex

With a PRO MINI, you can put all the data pins on PORTD. This is the fastest way. But of course you have a massive hand-wiring job.

Incidentally, the SPFD5408A is a real TFT controller made by Orise Technology. It has no similarity to the ILI9341 (as claimed in your library) I have never seen a real-life SPFD5408 chip in current shields. I suspect that it might have been used in some historic shields. The Adafruit programs would report an ID of 0x5408 from a genuine SPFD5408A. Please post the ID that is reported for your display.

If anyone has a real SPFD5408, please could they PM me. It would be nice to add specific support to "MCUFRIEND_kbv.h"

If you want a TFT to be really fast, use an ARM chip with 16-bit parallel interface. A MEGA or DUE can do a 16-bit interface. You need to buy a standard TFT and a specific Adapter Shield. This is a lot more expensive than your $5 UNO shield.

David.

david_prentice: You are using a Shield that is designed for a UNO. If you look on the back, it even tells you which Arduino pins are connected.

It is extremely convenient to plug one standard shield into a standard Arduino. All the wiring is known to the rest of the world.

If you look at the data pins ( LCD_D0 .. LCD_D7 ), you can see that you have them spread over several ports. With a UNO it is easy to map. e.g. PORTB, PORTD With a MEGA it is very complex. With a DUE it is horrific With a Zero it is fairly complex

With a PRO MINI, you can put all the data pins on PORTD. This is the fastest way. But of course you have a massive hand-wiring job.

Incidentally, the SPFD5408A is a real TFT controller made by Orise Technology. It has no similarity to the ILI9341 (as claimed in your library) I have never seen a real-life SPFD5408 chip in current shields. I suspect that it might have been used in some historic shields. The Adafruit programs would report an ID of 0x5408 from a genuine SPFD5408A. Please post the ID that is reported for your display.

If anyone has a real SPFD5408, please could they PM me. It would be nice to add specific support to "MCUFRIEND_kbv.h"

If you want a TFT to be really fast, use an ARM chip with 16-bit parallel interface. A MEGA or DUE can do a 16-bit interface. You need to buy a standard TFT and a specific Adapter Shield. This is a lot more expensive than your $5 UNO shield.

David.

Thanks for informative reply. I've already done the identification. It returns 0x0000. I guess that signifies a counterfeit chip. Last time I've seen such an ID, it was on a fake FTDI chip.

The most frustrating thing about these shields for me, is that you can't really be sure what your chip is. There are two HC245 s on the back of the shield. Google says they are "octal buss trasceiver"(whatever that is). I don't think those are LCD drivers, but I can't see any other IC anywhere on the PCB...

I'm using the SPFD5408 library. But I'm fairly certain that's not what's actually in my shield.

I was planning on buying capacitive touch TFT's from adafruit after I've figured if what I want was possible. Now I'm not sure if I should spend 40$ on it. From what I gather, it won't work faster than the chinese knockoff I'm currently using.

Maybe I should just give up on 8 bit CPUs and utilize rPi...

Just plug the shield into a UNO. Run the diagnosis program from misc.ws website.

You can try my library that is attached to message #14 in http://forum.arduino.cc/index.php?topic=337473.msg2373456#msg2373456

It will tell you what chip that you have. That particular ZIP does not support the ILI9341 but I will shortly update it.

Life is a lot more reliable with shields. Hand-wiring is subject to all sorts of problems.

David.

david_prentice: Just plug the shield into a UNO. Run the diagnosis program from misc.ws website.

You can try my library that is attached to message #14 in http://forum.arduino.cc/index.php?topic=337473.msg2373456#msg2373456

It will tell you what chip that you have. That particular ZIP does not support the ILI9341 but I will shortly update it.

Life is a lot more reliable with shields. Hand-wiring is subject to all sorts of problems.

David.

Tried your library. "Unknown LCD driver chip: 0"

Readpixel example outputs:

g_ID = 0x0 ID = 0x9320 Unknown ID

In which case, please can you post a link to the shop / Ebay item where you bought your display.

The shield should work in a UNO or MEGA2560. I would expect a value of some description from a mcufriend.com shield.

Some 'other' shields do not have a RD pin or hardwire their buffer chips. The red shields do it properly.

David.

I bought it from a local shop, they didn't have any identifying information on the page except for "2.4" TFT display for arduino"

Here are some photos. Couldn't attach it to the post. Too big.

https://dl.dropboxusercontent.com/u/24552419/20151003_160042.jpg

https://dl.dropboxusercontent.com/u/24552419/20151003_160059.jpg

Ah-ha. I have 5 different red 2.4" LCD shields with “mcufriend.com” printed on the pcb.

The HC245 buffers, 2.3V regulator, microSD socket, pin connections are all in the same place.

However, the copper traces are all slightly different. Likewise, your photo shows the same layout of the major components. Your traces are different to all of my shields.

The beauty of the mcufriend shields is that you can read the ID. Which means that there is no guesswork.

Does your SD and Touchscreen work properly?
The diagnostic program from misc.ws displays the values from other registers. Are they all 0x0000 ?

You can run this:

#include <SPI.h>          // f.k. for Arduino-1.5.2
#include <Adafruit_GFX.h> // Hardware-specific library
#include <MCUFRIEND_kbv.h>
MCUFRIEND_kbv tft;   

void setup() 
{
    uint16_t i, val;
    Serial.begin(9600);
    tft.reset();
    for (i = 0; i < 0x14; i++) {
        Serial.print("Register 0x");
        if (i < 0x10) Serial.print("0");
        Serial.print(i, HEX);
        Serial.print(" = 0x");
        val = tft.readReg(i);    
        if (val < 0x10) Serial.print("0");
        Serial.print(val, HEX);
        Serial.println();
    }
}

void loop() {
  // put your main code here, to run repeatedly:

}

I suppose it is possible that they have wired LCD_RD wrongly. You can always work the display “write-only” but it involves guesswork as to which controller.

David.

david_prentice:
Ah-ha. I have 5 different red 2.4" LCD shields with “mcufriend.com” printed on the pcb.

The HC245 buffers, 2.3V regulator, microSD socket, pin connections are all in the same place.

However, the copper traces are all slightly different. Likewise, your photo shows the same layout of the major components. Your traces are different to all of my shields.

The beauty of the mcufriend shields is that you can read the ID. Which means that there is no guesswork.

Does your SD and Touchscreen work properly?
The diagnostic program from misc.ws displays the values from other registers. Are they all 0x0000 ?

You can run this:

#include <SPI.h>          // f.k. for Arduino-1.5.2

#include <Adafruit_GFX.h> // Hardware-specific library
#include <MCUFRIEND_kbv.h>
MCUFRIEND_kbv tft;

void setup()
{
    uint16_t i, val;
    Serial.begin(9600);
    tft.reset();
    for (i = 0; i < 0x14; i++) {
        Serial.print(“Register 0x”);
        if (i < 0x10) Serial.print(“0”);
        Serial.print(i, HEX);
        Serial.print(" = 0x");
        val = tft.readReg(i);   
        if (val < 0x10) Serial.print(“0”);
        Serial.print(val, HEX);
        Serial.println();
    }
}

void loop() {
  // put your main code here, to run repeatedly:

}




I suppose it is possible that they have wired LCD_RD wrongly. You can always work the display "write-only" but it involves guesswork as to which controller.

David.

So I got the counterfeit of a counterfeit :slight_smile: figures. The code you’ve posted outputs this.

Register 0x00 = 0x00
Register 0x01 = 0x00
Register 0x02 = 0x00
Register 0x03 = 0x00
Register 0x04 = 0x00
Register 0x05 = 0x00
Register 0x06 = 0x00
Register 0x07 = 0x00
Register 0x08 = 0x00
Register 0x09 = 0x00
Register 0x0A = 0x808
Register 0x0B = 0x00
Register 0x0C = 0x6666
Register 0x0D = 0x00
Register 0x0E = 0x00
Register 0x0F = 0x00
Register 0x10 = 0x00
Register 0x11 = 0x00
Register 0x12 = 0x00
Register 0x13 = 0x00

Touchscreen works properly. Although I had to fiddle around with the code a bit. Haven’t tried SD Card. Heard sometimes these shields output 5V and burn the card. Also, don’t really need an SD card for my project.

I am confused. You only read non-zero from registers 0x0A and 0x0C. I was expecting other values to give some clues. You can run the loop from 0x00 to 0xFF. Especially see the results from 0xD3 and 0xEF registers. Somehow, I suspect that you will get all zeros.

Regarding your SPFD5408 library. What identity value do you give for tft.begin() ?
Since you seem to get some response, your controller must be “similar”.
Ah-ha. You seem to assume 0x9341. I would expect some sort of return values from the low registers from an ILI9341 chip. However, there are other makes that have a “similar” register set.

It is easy enough to correct the Red and Blue swapping. And to swap Black / White.
I would feel a lot happier with knowing which controller chip is actually present.

I ought to tidy up my current library and post it. (the current library supports ILI9341)

David.

david_prentice: I am confused. You only read non-zero from registers 0x0A and 0x0C. I was expecting other values to give some clues. You can run the loop from 0x00 to 0xFF. Especially see the results from 0xD3 and 0xEF registers. Somehow, I suspect that you will get all zeros.

Regarding your SPFD5408 library. What identity value do you give for tft.begin() ? Since you seem to get some response, your controller must be "similar". Ah-ha. You seem to assume 0x9341. I would expect some sort of return values from the low registers from an ILI9341 chip. However, there are other makes that have a "similar" register set.

It is easy enough to correct the Red and Blue swapping. And to swap Black / White. I would feel a lot happier with knowing which controller chip is actually present.

I ought to tidy up my current library and post it. (the current library supports ILI9341)

David.

That's what I though too. Whatever chip that is, it's close enough to ILI9341 to somewhat work, but different parts causes glitches. I believe the inverse colors is a symptom of that.

This is what's in the begin line. tft.begin(0x9341); // SDFP5408

Seriously tho, where is that chip located at? I even unstuck the LCD panel from the PCB to look under it. Except for the two HC245s I can't find any ICs on the board. Is that thing inside the metal LCD panel?