Recommendations for 10" TFT Display with touchscreen for Teensy 4.1

All,

I had the same problem with lag when using the touch screen. Basically the interrupt pin is not being picked up by the teensy. Also when the screen is touched the I2C starts "chattering" continuously at 100 ms (see picture below) also look at the lower right for the full screen showing the continuous chatter.
I am a little fuzzy on how I fixed it but the best I remember I had to "redirect" the interrupt so it was on the main program and not call straight to the library. Here is a chunk of the code. I added the "void InterruptRoutine()" so I can attach and detach the interrupt as needed. I also went into the GT9271.cpp and commented out "armIRQ()" and "disArmIRQ()".


Code:
// Callback from irq function.
void handleTouch(int8_t contacts, GTPoint *points) {
  detachInterrupt(digitalPinToInterrupt(INT_PIN));
  Serial.printf("Number Of Contact Points: %d\n", contacts);
  for (uint8_t i = 0; i < contacts; i++) {
    // X and Y coords are inverted side to side and up and down.
    // Subtract from screen width and height to get x/y origins at
    // 0,0 instead of 1023,599. Also generate 16bit coords from two
    // 8bit coords (big endian).
    XAxis = (uint16_t)LCD_WIDTH - ((points[i].x_msb << 8) | points[i].x_lsb);
    YAxis = (uint16_t)LCD_HEIGHT - ((points[i].y_msb << 8) | points[i].y_lsb);
    uint16_t area = (uint16_t)((points[i].area_msb << 8) | points[i].area_lsb);
    Serial.printf("Contact #%d: Track ID %d, X position %d, Y position %d, area %d\n", i, points[i].trackId, XAxis, YAxis, area);
  }

  if (TimeForButtonDebounceMillis < millis()) {
    ScreenButtonCheck();
    TimeForButtonDebounceMillis = millis() + TimeADDEDForButtonDebounceMillis;
  }  // End if(TimeForButtonDebounceMillis < millis())
  attachInterrupt(INT_PIN, InterruptRoutine, FALLING);
}  // End void handleTouch(int8_t contacts, GTPoint *points)

void InterruptRoutine() {
  touch.onIRQ();
}  // End void InterruptRoutine()

Screenshot 2024-12-02 104245.png


It took me a week to figure out what to do. Here is after the code change. the response time is 25 ms

Screenshot 2024-12-02 104617.png
 
I've always kept the ISR handler to an absolute minimum, ie set flag / store data and the main loop checks for said flag and process the stored data. I never call Serial.printf within an ISR, even other "library" functions if at all possible.
 
Turby,

You are correct... I was using that to follow the flow during my debugging. you should comment that out or delete it.
 
Another comment... after you get the Interrupt working faster you may need to add a debounce. for every finger press and release the touchscreen sends ~5-10 actual presses to the teensy (as shown in the second picture in the above post).

I had two screens with a pushbutton in the same location on each screen. When I pressed the button on the first screen it was supposed to switch to the second screen and when I pressed the button on the second screen it was supposed to navigate back to the first screen. However when I pressed the button nothing happened... or at least appeared like nothing happened. because of the multiple interrupts and the speed of the teensy 4.1 the screens changed so fast that it appeared like it had never changed. So I added the debounce timer in the code above.
 
@DJETH,
Hi,i tried to reproduce your works to speed up the touch,but i missed the initialization of:
Code:
unsigned long TimeForButtonDebounceMillis = ?;
unsigned long TimeADDEDForButtonDebounceMillis = ?;
And also i can't figure how to build this function: ScreenButtonCheck(); :unsure:

By default,in my GT9271.cpp "armIRQ()" & "disArmIRQ()" were already commented out.
 
AntiLoop,

I have only been doing this for less than a year and have had no formal instruction in the art of writing code. I write for myself and not necessarily for others so it is in my own style. The code I attached below is mostly from Warren Watson and only some is mine. I did however rename the "#include" and you will need to rename them with the original names to match your libraries that WWatson has produced.

I have left the Serial.print() active so you can see the "touches" on the serial monitor.
If you put the time of the debounce to 0 you will understand the need of it.
This very basic sketch is what I used to help me understand how the touch screen works with the display (Did this a couple of months ago). all it does is changes from screen 1 to screen 2 using a button.
Note: my backlight pin is on 33.

Code:
// GT9271_Teensy_Touch.ino
/*
 * License: Refer to LICENSE file in main directory.
 * Modified: For use with Teensy 4.x and MicroMod
 *       By: Warren Watson 2024.
*/

#include <Wire.h>
#include "Display_CPT_Touchscreen_GT9271.h"
#include "DJETH_RA8876_Config_8080.h"
#include <DJETH_RA8876_t41_p.h>
#include "_font_ComicSansMS.h"
#include "DJETH_RA8876_common.h"    //added this one and may not be needed
#include "DJETH_RA8876Registers.h"  //added this one and may not be needed

RA8876_t41_p tft = RA8876_t41_p(RA8876_8080_DC, RA8876_8080_CS, RA8876_8080_RESET);

#define INT_PIN 8    // was 22
#define RST_PIN 255  // 255 means do not use reset pin else reset using pin number.
#define USE_WRITERECT





int TFT_Backlight_Pin = 33;
DisplayCPTGT9271 touch = DisplayCPTGT9271(INT_PIN, RST_PIN, 0x5D);  // was 0x5d
int ScreenActive = 0;
int ButtonPressGoToScreen = 0;
int XAxis = 0;
int YAxis = 0;
int TimeADDEDForButtonDebounceMillis = 300;
long unsigned int TimeForButtonDebounceMillis = 0;


void setup() {


  digitalWrite(TFT_Backlight_Pin, HIGH);

  Serial.begin(115200);
  while (!Serial && millis() < 1000) {}  //wait for Serial Monitor

  // Set 8/16bit bus mode. Default is 8bit bus mode.
  tft.setBusWidth(16);  // RA8876_8080_BUS_WIDTH is defined in
                        // src/RA8876_Config_8080.h.
  tft.begin(40);        // RA8876_8080_BUS_WIDTH is defined in
                        // src/RA8876_Config_8080.h. Default is 20MHz.  // 60 and 120
  tft.fillScreen(BLUE);

  // Setup callback.
  touch.setHandler(handleTouch);
  // We are using Wire2 on T41. Set this to your wire usage.
  touch.setWireObject(&Wire2);  // Default set to Wire on reset or power up.  // was &Wire
  // Start touchscreen.
  if (touch.begin() != true) {
    Serial.println("! Module Initialize: Failed");
  } else {
    Serial.println("Module Initialize: Succeded");
  }
  Serial.printf("\nUp to 10 contact points can be used with this driver.\n");
  Serial.printf("The screen is ready to be touched...\n");
  Wire2.setClock(400000);
  HomeScreenDraw();
  attachInterrupt(INT_PIN, InterruptRoutine, FALLING);

  TimeForButtonDebounceMillis = millis();

}  // End Void Setup  //////////////////////////////////////////////////////////////////////

void loop() {
  //touch.armIRQ();
  //touch.onIRQ();
  //touch.loop();
  // delay(100);
}  // End Void Loop/ ////////////////////////////////////////////////////////////


// Callback from irq function.
void handleTouch(int8_t contacts, GTPoint *points) {
  detachInterrupt(digitalPinToInterrupt(INT_PIN));
  Serial.printf("Number Of Contact Points: %d\n", contacts);
  for (uint8_t i = 0; i < contacts; i++) {
    // X and Y coords are inverted side to side and up and down.
    // Subtract from screen width and height to get x/y origins at
    // 0,0 instead of 1023,599. Also generate 16bit coords from two
    // 8bit coords (big endian).
    XAxis = (uint16_t)LCD_WIDTH - ((points[i].x_msb << 8) | points[i].x_lsb);
    YAxis = (uint16_t)LCD_HEIGHT - ((points[i].y_msb << 8) | points[i].y_lsb);
    uint16_t area = (uint16_t)((points[i].area_msb << 8) | points[i].area_lsb);
    Serial.printf("Contact #%d: Track ID %d, X position %d, Y position %d, area %d\n", i, points[i].trackId, XAxis, YAxis, area);

  }  // End for loop
  if (TimeForButtonDebounceMillis < millis()) {
      ScreenButtonCheck();
    TimeForButtonDebounceMillis = millis() + TimeADDEDForButtonDebounceMillis;
    
  }  // End if(TimeForButtonDebounceMillis < millis())
 attachInterrupt(INT_PIN, InterruptRoutine, FALLING);
}  // End void handleTouch(int8_t contacts, GTPoint *points)

void InterruptRoutine() {
 // tft.setCursor(20, 20);
 // tft.print("Hello");
  touch.onIRQ();
}


void ScreenButtonCheck() {
  if (XAxis > 400 && XAxis < 650 && YAxis > 50 && YAxis < 100) {
    if (ButtonPressGoToScreen == 1) {
      HomeScreenDraw();
    }
    else if (ButtonPressGoToScreen == 2) {
      SecondScreen();
    }
  }  // End if(XAxis > 400 && XAxis < 650 && YAxis > 50 && YAxis < 100)

}  // End void ScreenButtonCheck()

void HomeScreenDraw() {
  ScreenActive = 1;
  ButtonPressGoToScreen = 2;
  tft.fillScreen(RED);
  //tft.drawCircleSquareFill(ru16 x0, ru16 y0, ru16 x1, ru16 y1, ru16 xr, ru16 yr, ru16 color)
  tft.drawCircleSquareFill(400, 50, 650, 100, 10, 10, BLACK);
  tft.drawCircleSquare(400, 50, 650, 100, 10, 10, BLUE);
  tft.setTextColor(WHITE);
  tft.setFont(ComicSansMS_18);
  tft.setCursor(415, 64);
  tft.print("GOTO Screen 2");

}  // End void HomeScreen()



void SecondScreen() {
  ScreenActive = 2;
  ButtonPressGoToScreen = 1;
  tft.fillScreen(YELLOW);
  //tft.drawCircleSquareFill(ru16 x0, ru16 y0, ru16 x1, ru16 y1, ru16 xr, ru16 yr, ru16 color)
  tft.drawCircleSquareFill(400, 50, 650, 100, 10, 10, BLUE);
  tft.drawCircleSquare(400, 50, 650, 100, 10, 10, BLACK);
  tft.setTextColor(WHITE);
  tft.setFont(ComicSansMS_18);
  tft.setCursor(415, 64);
  tft.print("GOTO Screen 1");
}  // End void SecondScreen()
 
@DJETH,
Thank you so much,it's a very nice job you did!
It's a difference like day and night,fast as ILI9341_t3 and XPT2046,surely faster that RA8875 and FT5206 touch !
i'm sure,the IRQ handling will also solve my overriding touch problems when i use buttons at the same coordonnates
but in differents menu scenes,i will test that later.
What a happyness to play my RA8876 stuffs now ,i appreciate your help :)
 
Back
Top