Another 2.8" off brand tft

Hi all, trying to get a keyestudio 2.8tft (The shield in question) to work in 8bit parallel. on an atmel 2560.

The screen works with adafruit graphics tests how ever that would be in SPI mode as far as I can tell (connected in breakout rather than shield)

Pins as below
LCD_RST-A4
LCD_CS(Y+)-A3
LCD_RS(X-)-A2
LCD_WR-A1
LCD_RD-A0

D0(Y-)-P22
D1(X+)-P23
D2-P24
D3-P25
D4-P26
D5-P27
D6-P28
D7-P29

Adafruit graphics test give the below in serial monitor:

17:17:18.538 -> TFT LCD test
17:17:18.538 -> Using Adafruit 2.8" TFT Breakout Board Pinout
17:17:18.585 -> TFT size is 240x320
17:17:18.633 -> Found ILI9325 LCD driver
17:17:19.196 -> Benchmark Time (microseconds)

MCUFRIEND gives the below when running diagnose_TFT_support:

17:19:24.474 -> tft.readID() finds: ID = 0xD3D3
17:19:24.522 ->
17:19:24.522 -> MCUFRIEND_kbv version: 3.0.0
17:19:24.522 ->
17:19:24.522 -> Probably a write-only Mega2560 Shield

MCUFRIEND gives the below when running LCD_ID_readreg:

17:21:40.185 -> reg(0x0000) 93 25 ID: ILI9320, ILI9325, ILI9335, ...
17:21:40.233 -> reg(0x0004) 00 00 00 00 Manufacturer ID
17:21:40.281 -> reg(0x0009) 00 00 00 00 00 Status Register
17:21:40.329 -> reg(0x000A) 00 00 Get Power Mode
17:21:40.376 -> reg(0x000C) 00 00 Get Pixel Format
17:21:40.422 -> reg(0x0061) 00 00 RDID1 HX8347-G
17:21:40.422 -> reg(0x0062) 00 00 RDID2 HX8347-G
17:21:40.470 -> reg(0x0063) 00 00 RDID3 HX8347-G
17:21:40.517 -> reg(0x0064) 00 00 RDID1 HX8347-A
17:21:40.563 -> reg(0x0065) 00 00 RDID2 HX8347-A
17:21:40.563 -> reg(0x0066) 00 00 RDID3 HX8347-A
17:21:40.610 -> reg(0x0067) 00 00 RDID Himax HX8347-A
17:21:40.657 -> reg(0x0070) 00 00 Panel Himax HX8347-A
17:21:40.704 -> reg(0x00A1) 00 00 00 00 00 RD_DDB SSD1963
17:21:40.751 -> reg(0x00B0) 00 00 RGB Interface Signal Control
17:21:40.798 -> reg(0x00B4) 00 00 Inversion Control
17:21:40.849 -> reg(0x00B6) 00 00 00 00 00 Display Control
17:21:40.894 -> reg(0x00B7) 00 00 Entry Mode Set
17:21:40.894 -> reg(0x00BF) 00 00 00 00 00 00 ILI9481, HX8357-B
17:21:40.986 -> reg(0x00C0) 00 00 00 00 00 00 00 00 00 Panel Control
17:21:40.986 -> reg(0x00C8) 00 00 00 00 00 00 00 00 00 00 00 00 00 GAMMA
17:21:41.079 -> reg(0x00CC) 00 00 Panel Control
17:21:41.125 -> reg(0x00D0) 00 00 00 Power Control
17:21:41.125 -> reg(0x00D2) 00 00 00 00 00 NVM Read
17:21:41.219 -> reg(0x00D3) 00 00 00 00 ILI9341, ILI9488
17:21:41.219 -> reg(0x00D4) 00 00 00 00 Novatek ID
17:21:41.266 -> reg(0x00DA) 00 00 RDID1
17:21:41.312 -> reg(0x00DB) 00 00 RDID2
17:21:41.359 -> reg(0x00DC) 00 00 RDID3
17:21:41.359 -> reg(0x00E0) 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 GAMMA-P
17:21:41.406 -> reg(0x00E1) 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 GAMMA-N
17:21:41.501 -> reg(0x00EF) 12 31 12 31 12 31 ILI9327
17:21:41.548 -> reg(0x00F2) 00 00 00 00 00 00 00 00 00 00 00 00 Adjust Control 2
17:21:41.595 -> reg(0x00F6) 00 00 00 00 Interface Control

If I understand correctly the first register identifies the display? If so then what causes the TFT_support to not detect the correct display?

Great, got the above figured out with some small edits in the utility libraries, mcufriend_special and mcufriend_shield.

Now working on getting the touch screen calibrated. As mentioned in first post the XYpins share pins with D0-1 and RS/CS. Again, I can get it to work with Adafruit paint (so I guess this screen is a copy of an Adafruit 2.8TFT except that they left the SD card level shifter off, was able to sort that out fortunately)

The code that I am trying to use
At line 30 I have changed the Pins to the correct pins for my setup
Uncommented lines 48~50 as it does share pins (tried it with the lines still commented as well.)

// TouchScreen_Calibr_native for MCUFRIEND UNO Display Shields
// adapted by David Prentice
// for Adafruit's <TouchScreen.h> Resistive Touch Screen Library
// from Henning Karlsen's original UTouch_Calibration program.
// Many Thanks.

#define PORTRAIT  0
#define LANDSCAPE 1
#define USE_XPT2046   0
#define USE_LOCAL_KBV 1

#define TOUCH_ORIENTATION  PORTRAIT

#if defined(USB_PID) && USB_PID == 0x804E // Arduino M0 Native
#define Serial SerialUSB
#endif

#define SWAP(x, y) { int t = x; x = y; y = t; }

#define TITLE "TouchScreen.h GFX Calibration"
#include <Adafruit_GFX.h>
#include <MCUFRIEND_kbv.h>
MCUFRIEND_kbv tft;

// MCUFRIEND UNO shield shares pins with the TFT.
#if defined(ESP32)
int XP = 27, YP = 4, XM = 15, YM = 14;  //most common configuration
#else
//int XP = 6, YP = A1, XM = A2, YM = 7;  //most common configuration
int XP = 22, YP = A3, XM = A2, YM = 23;  //next common configuration
//int XP=PB7,XM=PA6,YP=PA7,YM=PB6; //BLUEPILL must have Analog for YP, XM
#endif
#if USE_LOCAL_KBV
#include "TouchScreen_kbv.h"         //my hacked version
#define TouchScreen TouchScreen_kbv
#define TSPoint     TSPoint_kbv
#else
#include <TouchScreen.h>         //Adafruit Library
#endif
TouchScreen ts(XP, YP, XM, YM, 300);   //re-initialised after diagnose
TSPoint tp;                            //global point

void readResistiveTouch(void)
{
    tp = ts.getPoint();
    pinMode(YP, OUTPUT);      //restore shared pins
    pinMode(XM, OUTPUT);
    //digitalWrite(YP, HIGH);  //because TFT control pins
    //digitalWrite(XM, HIGH);
    //    Serial.println("tp.x=" + String(tp.x) + ", tp.y=" + String(tp.y) + ", tp.z =" + String(tp.z));
}

uint16_t readID(void) {
    uint16_t ID = tft.readID();
    if (ID == 0xD3D3) ID = 0x9486;
    return ID;
}
#define TFT_BEGIN()  tft.begin(ID)

#define WHITE 0xFFFF
#define RED   0xF800
#define BLUE  0x001F
#define GREEN 0x07E0
#define BLACK 0x0000

//#define GRAY  0x2408        //un-highlighted cross-hair
#define GRAY      BLUE     //idle cross-hair colour
#define GRAY_DONE RED      //finished cross-hair

bool ISPRESSED(void)
{
    // .kbv this was too sensitive !!
    // now touch has to be stable for 50ms
    int count = 0;
    bool state, oldstate;
    while (count < 10) {
        readResistiveTouch();
        state = tp.z > 200;     //ADJUST THIS VALUE TO SUIT YOUR SCREEN e.g. 20 ... 250
        if (state == oldstate) count++;
        else count = 0;
        oldstate = state;
        delay(5);
    }
    return oldstate;
}

uint32_t cx, cy, cz;
uint32_t rx[8], ry[8];
int32_t clx, crx, cty, cby;
float px, py;
int dispx, dispy, text_y_center, swapxy;
uint32_t calx, caly, cals;

char *Aval(int pin)
{
    static char buf[2][10], cnt;
    cnt = !cnt;
#if defined(ESP32)
    sprintf(buf[cnt], "%d", pin);
#else
    sprintf(buf[cnt], "A%d", pin - A0);
#endif
    return buf[cnt];
}

void showpins(int A, int D, int value, const char *msg)
{
    char buf[40];
    sprintf(buf, "%s (%s, D%d) = %d", msg, Aval(A), D, value);
    Serial.println(buf);
}

void bofe(char *buf)
{
    tft.println(buf);
    Serial.println(buf);
}

#if USE_XPT2046 == 0
bool diagnose_pins()
{
    uint8_t i, j, Apins[2], Dpins[2], found = 0;
    uint16_t value, Values[2];

    Serial.println(F("Making all control and bus pins INPUT_PULLUP"));
    Serial.println(F("Typical 30k Analog pullup with corresponding pin"));
    Serial.println(F("would read low when digital is written LOW"));
    Serial.println(F("e.g. reads ~25 for 300R X direction"));
    Serial.println(F("e.g. reads ~30 for 500R Y direction"));
    Serial.println(F(""));

    for (i = A0; i < A5; i++) pinMode(i, INPUT_PULLUP);
    for (i = 2; i < 10; i++) pinMode(i, INPUT_PULLUP);
    for (i = A0; i < A4; i++) {
        pinMode(i, INPUT_PULLUP);
        for (j = 5; j < 10; j++) {
            pinMode(j, OUTPUT);
            digitalWrite(j, LOW);
            value = analogRead(i);               // ignore first reading
            value = analogRead(i);
            if (value < 100 && value > 0) {
                showpins(i, j, value, "Testing :");
                if (found < 2) {
                    Apins[found] = i;
                    Dpins[found] = j;
                    Values[found] = value;
                }
                found++;
            }
            pinMode(j, INPUT_PULLUP);
        }
        pinMode(i, INPUT_PULLUP);
    }
    if (found == 2) {
        int idx = Values[0] < Values[1];
        /*
                Serial.println(F("Diagnosing as:-"));
                for (i = 0; i < 2; i++) {
                    showpins(Apins[i], Dpins[i], Values[i],
                             (Values[i] < Values[!i]) ? "XM,XP: " : "YP,YM: ");
                }
        */
        XM = Apins[!idx]; XP = Dpins[!idx]; YP = Apins[idx]; YM = Dpins[idx];
        ts = TouchScreen(XP, YP, XM, YM, 300);    //re-initialise with pins
        return true;                              //success
    }
    if (found == 0) Serial.println(F("MISSING TOUCHSCREEN"));
    //else Serial.println(F("BROKEN TOUCHSCREEN"));
    return false;
}
#endif

void setup()
{
    char buf[40];
    uint16_t ID = readID();
    TFT_BEGIN();
    tft.fillScreen(TFT_NAVY);
    tft.println("Waiting for Serial");
    delay(1000);
    Serial.begin(9600);
    while (!Serial);
    tft.fillScreen(TFT_BLUE);
    Serial.println(TITLE);
    bool ret = true;
#if USE_XPT2046 || defined(__arm__) || defined(ESP32)
    Serial.println(F("Not possible to diagnose Touch pins on ARM or ESP32"));
#else
    ret = diagnose_pins();  //destroys TFT pin modes
    TFT_BEGIN();            //start again
#endif
    tft.setRotation(TOUCH_ORIENTATION);
    dispx = tft.width();
    dispy = tft.height();
    text_y_center = (dispy / 2) - 6;
    sprintf(buf, "ID = 0x%04x", ID);
    Serial.println(buf);
    if (ret == false) {
        centerprint("BROKEN TOUCHSCREEN", text_y_center);
        fail();
    }
}

void loop()
{
    startup();

    int x, y, cnt, idx = 0;
    tft.fillScreen(BLACK);
    for (x = 10, cnt = 0; x < dispx; x += (dispx - 20) / 2) {
        for (y = 10; y < dispy; y += (dispy - 20) / 2) {
            if (++cnt != 5) drawCrossHair(x, y, GRAY);
        }
    }
    centerprint("***********", text_y_center - 12);
    centerprint("***********", text_y_center + 12);
    for (x = 10, cnt = 0; x < dispx; x += (dispx - 20) / 2) {
        for (y = 10; y < dispy; y += (dispy - 20) / 2) {
            if (++cnt != 5) calibrate(x, y, idx++, F(" X, Y, Pressure"));
        }
    }

    cals = (long(dispx - 1) << 12) + (dispy - 1);
    swapxy = rx[2] - rx[0];
    //else swapxy = ry[2] - ry[0];
    swapxy = (swapxy < -400 || swapxy > 400);
    if (swapxy != 0) {
        clx = (ry[0] + ry[1] + ry[2]); //rotate 90
        crx = (ry[5] + ry[6] + ry[7]);
        cty = (rx[0] + rx[3] + rx[5]);
        cby = (rx[2] + rx[4] + rx[7]);
    } else {
        clx = (rx[0] + rx[1] + rx[2]); //regular
        crx = (rx[5] + rx[6] + rx[7]);
        cty = (ry[0] + ry[3] + ry[5]);
        cby = (ry[2] + ry[4] + ry[7]);
    }
    clx /= 3;
    crx /= 3;
    cty /= 3;
    cby /= 3;
    px = float(crx - clx) / (dispx - 20);
    py = float(cby - cty) / (dispy - 20);
    //  px = 0;
    clx -= px * 10;
    crx += px * 10;
    cty -= py * 10;
    cby += py * 10;

    calx = (long(clx) << 14) + long(crx);
    caly = (long(cty) << 14) + long(cby);
    if (swapxy)
        cals |= (1L << 31);

    report();          // report results
    while (true) {}    // tread water
}

void readCoordinates()
{
    int iter = 5000;
    int failcount = 0;
    int cnt = 0;
    uint32_t tx = 0;
    uint32_t ty = 0;
    uint32_t tz = 0;
    bool OK = false;

    while (OK == false)
    {
        centerprint("*  PRESS  *", text_y_center);
        while (ISPRESSED() == false) {}
        centerprint("*  HOLD!  *", text_y_center);
        cnt = 0;
        iter = 400;
        do
        {
            readResistiveTouch();
            if (tp.z > 200)  //.kbv
            {
                tx += tp.x;
                ty += tp.y;
                tz += tp.z;
                cnt++;
            }
            else
                failcount++;
        } while ((cnt < iter) && (failcount < 10000));
        if (cnt >= iter)
        {
            OK = true;
        }
        else
        {
            tx = 0;
            ty = 0;
            tz = 0;
            cnt = 0;
        }
        if (failcount >= 10000)
            fail();
    }

    cx = tx / iter;
    cy = ty / iter;
    cz = tz / iter;
}

void calibrate(int x, int y, int i, String msg)
{
    drawCrossHair(x, y, WHITE);
    readCoordinates();
    centerprint("* RELEASE *", text_y_center);
    drawCrossHair(x, y, GRAY_DONE);
    rx[i] = cx;
    ry[i] = cy;
    char buf[40];
    sprintf(buf, "\r\ncx=%ld cy=%ld cz=%ld %s", cx, cy, cz, msg.c_str());
    Serial.print(buf);
    while (ISPRESSED() == true) {}
}

void report()
{
    uint16_t TS_LEFT, TS_RT, TS_TOP, TS_BOT, TS_WID, TS_HT, TS_SWAP;
    int16_t tmp;
    char buf[60];
    centertitle(TITLE);

    tft.println(F("To use the new calibration"));
    tft.println(F("settings you must map the values"));
    tft.println(F("from Point p = ts.getPoint() e.g. "));
    tft.println(F("x = map(p.x, LEFT, RT, 0, tft.width());"));
    tft.println(F("y = map(p.y, TOP, BOT, 0, tft.height());"));
    tft.println(F("swap p.x and p.y if diff ORIENTATION"));

    //.kbv show human values
    TS_LEFT = (calx >> 14) & 0x3FFF;
    TS_RT   = (calx >>  0) & 0x3FFF;
    TS_TOP  = (caly >> 14) & 0x3FFF;
    TS_BOT  = (caly >>  0) & 0x3FFF;
    TS_WID  = ((cals >> 12) & 0x0FFF) + 1;
    TS_HT   = ((cals >>  0) & 0x0FFF) + 1;
    TS_SWAP = (cals >> 31);
    if (TOUCH_ORIENTATION == LANDSCAPE) { //always show PORTRAIT first
        tmp = TS_LEFT, TS_LEFT = TS_BOT, TS_BOT = TS_RT, TS_RT = TS_TOP, TS_TOP = tmp;
        tmp = TS_WID, TS_WID = TS_HT, TS_HT = tmp;
    }
    sprintf(buf, "\n\n*** COPY-PASTE from Serial Terminal:");
    bofe(buf);
    bool ts_landscape = (TOUCH_ORIENTATION == LANDSCAPE) ^ swapxy;
#if (USE_XPT2046)
    sprintf(buf, "const int TS_LANDSCAPE=%d; //%s", ts_landscape, TITLE);
    bofe(buf);
#else
    if (ts_landscape) {
        SWAP(XM, YP);
        SWAP(XP, YM);
        SWAP(TS_LEFT, TS_RT);
        SWAP(TS_TOP, TS_BOT);
    }
    sprintf(buf, "const int XP=%d,XM=%s,YP=%s,YM=%d; //%dx%d ID=0x%04X",
            XP, Aval(XM), Aval(YP), YM, TS_WID, TS_HT, readID());
    Serial.println(buf);
    sprintf(buf, "\nTouch Pin Wiring XP=%d XM=%s YP=%s YM=%d",
            XP, Aval(XM), Aval(YP), YM);
    tft.println(buf);
#endif
    sprintf(buf, "const int TS_LEFT=%d,TS_RT=%d,TS_TOP=%d,TS_BOT=%d;",
            TS_LEFT, TS_RT, TS_TOP, TS_BOT);
    Serial.println(buf);

#if !defined(ARDUINO_AVR_LEONARDO)
    for (int orient = 0; orient < 2; orient++) {
        sprintf(buf, "\n%s CALIBRATION     %d x %d",
                orient ? "LANDSCAPE" : "PORTRAIT ", TS_WID, TS_HT);
        bofe(buf);
        sprintf(buf, "x = map(p.%s, LEFT=%d, RT=%d, 0, %d)",
                orient ? "y" : "x", TS_LEFT, TS_RT, TS_WID);
        bofe(buf);
        sprintf(buf, "y = map(p.%s, TOP=%d, BOT=%d, 0, %d)",
                orient ? "x" : "y", TS_TOP, TS_BOT, TS_HT);
        bofe(buf);
        tmp = TS_LEFT, TS_LEFT = TS_TOP, TS_TOP = TS_RT, TS_RT = TS_BOT, TS_BOT = tmp;
        tmp = TS_WID, TS_WID = TS_HT, TS_HT = tmp;
    }

    int16_t x_range = TS_LEFT - TS_RT, y_range = TS_TOP - TS_BOT;
    if (abs(x_range) > 500 && abs(y_range) > 650) //LANDSCAPE
        return;
    sprintf(buf, "\n*** UNUSUAL CALIBRATION RANGES %d %d", x_range, y_range);
    bofe(buf);
#endif
}

void drawCrossHair(int x, int y, uint16_t color)
{
    tft.drawRect(x - 10, y - 10, 20, 20, color);
    tft.drawLine(x - 5, y, x + 5, y, color);
    tft.drawLine(x, y - 5, x, y + 5, color);
}

void centerprint(const char *s, int y)
{
    int len = strlen(s) * 6;
    tft.setTextColor(WHITE, RED);
    tft.setCursor((dispx - len) / 2, y);
    tft.print(s);
}

void centertitle(const char *s)
{
    tft.fillScreen(BLACK);
    tft.fillRect(0, 0, dispx, 14, RED);
    tft.fillRect(0, 14, dispx, 1, WHITE);
    centerprint(s, 1);
    tft.setCursor(0, 30);
    tft.setTextColor(WHITE, BLACK);
}

void startup()
{
    centertitle(TITLE);

    tft.println(F("#define NUMSAMPLES 3 in Library\n"));
    tft.println(F("Use a stylus or something"));
    tft.println(F("similar to touch as close"));
    tft.println(F("to the center of the WHITE"));
    tft.println(F("crosshair.  Keep holding"));
    tft.println(F("until crosshair turns RED."));
    tft.println(F("Repeat for all crosshairs.\n"));
    tft.println(F("Report can be pasted from Serial\n"));
    tft.println(F("Touch screen to continue"));

    while (ISPRESSED() == false) {}
    while (ISPRESSED() == true) {}
    //    waitForTouch();
}

void fail()
{
    centertitle("Touch Calibration FAILED");

    tft.println(F("Unable to read the position"));
    tft.println(F("of the press. This is a"));
    tft.println(F("hardware issue and can not"));
    tft.println(F("be corrected in software."));
    tft.println(F("check XP, XM pins with a multimeter"));
    tft.println(F("check YP, YM pins with a multimeter"));
    tft.println(F("should be about 300 ohms"));

    while (true) {};
}

Serial Monitor

11:52:25.844 -> TouchScreen.h GFX Calibration
11:52:25.844 -> Making all control and bus pins INPUT_PULLUP
11:52:25.937 -> Typical 30k Analog pullup with corresponding pin
11:52:25.937 -> would read low when digital is written LOW
11:52:26.031 -> e.g. reads ~25 for 300R X direction
11:52:26.031 -> e.g. reads ~30 for 500R Y direction
11:52:26.077 ->
11:52:26.077 -> MISSING TOUCHSCREEN
11:52:26.638 -> ID = 0x9325

Screen displays:

Touch Calibration FAILED
Unable to read the position
of the press. This is a
hardware issue and can not
be corrected in software.
check XP, XM pins with a multimeter
check YP, YM pins with a multimeter
should be about 300 ohms

Any pointers would be greatly appreciated.

EDIT: Tried setting #define USE_LOCAL_KBV 1 to 0 so the code will use the TouchScreen Library to no real effect.

I also gave the diagnose_Touchpins example sketch a try with a little massaging of the code with each attempted to see if I was missing something simple but also no luck.

EDIT2: MCUFRIEND example for simple buttons works, but the calibration is just a bit off. I thought I would just give it a try and see. So at least I know that the touch panel it self is deffinitely working and the pins are working as they should. Going to try work backwards through the button_simple example and try figure out why the calibration example is not working.

EDIT3: Got a step further, the diagnose_pins section now works, this was the hold up before. I see now that they were mapped for different digital pins vs what I am using which makes complete sense in the context of the shield plugged directly onto an UNO. The rest of the the calibration is still not working, the screen now requests a press to proceed with calibration but it is not detecting anything. I figure pin modes are are not being switched back somewhere.
Serial monitor now returns:

TouchScreen.h GFX Calibration
Making all control and bus pins INPUT_PULLUP
Typical 30k Analog pullup with corresponding pin
would read low when digital is written LOW
e.g. reads ~25 for 300R X direction
e.g. reads ~30 for 500R Y direction

Testing : (A2, D22) = 26
Testing : (A3, D23) = 29
ID = 0x9325
tp.x=0, tp.y=0, tp.z =0

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.