From ca54325fbc989263a39f538ee2791b2485c1b641 Mon Sep 17 00:00:00 2001 From: Max Date: Sun, 1 Oct 2017 00:26:33 +0200 Subject: [PATCH 1/5] Add XPT2046 touch controller supports esp8266 + RPi displays OO --- User_Setups/Setup10_RPi_touch_ILI9486.h | 163 ++++++++++++++++++ .../Touch_Controller_Demo.ino | 76 ++++++++ 2 files changed, 239 insertions(+) create mode 100644 User_Setups/Setup10_RPi_touch_ILI9486.h create mode 100644 examples/480 x 320/Touch_Controller_Demo/Touch_Controller_Demo.ino diff --git a/User_Setups/Setup10_RPi_touch_ILI9486.h b/User_Setups/Setup10_RPi_touch_ILI9486.h new file mode 100644 index 0000000..b572e0f --- /dev/null +++ b/User_Setups/Setup10_RPi_touch_ILI9486.h @@ -0,0 +1,163 @@ +// USER DEFINED SETTINGS +// Set driver type, fonts to be loaded, pins used and SPI control method etc +// +// See the User_Setup_Select.h file if you wish to be able to define multiple +// setups and then easily select which setup file is used by the compiler. +// +// If this file is editted correctly then all the library example sketches should +// run without the need to make any more changes for a particular hardware setup! + +// ################################################################################## +// +// Section 0. Call up the right driver file and any options for it +// +// ################################################################################## + +// Only define one driver, the other ones must be commented out +//#define ILI9341_DRIVER +//#define ST7735_DRIVER +//#define ILI9163_DRIVER +//#define S6D02A1_DRIVER +#define RPI_ILI9486_DRIVER // 20MHz maximum SPI +// to enable XPT2046 touch controller, define TOUCH_CS + +// For ST7735 ONLY, define the type of display, originally this was based on the +// colour of the tab on the screen protector film but this is not always true, so try +// out the different options below if the screen does not display graphics correctly, +// e.g. colours wrong, mirror images, or tray pixels at the edges. +// Comment out ALL BUT ONE of these options for a ST7735 display driver, save this +// this User_Setup file, then rebuild and upload the sketch to the board again: + +//#define ST7735_INITB +//#define ST7735_GREENTAB +//#define ST7735_GREENTAB2 +//#define ST7735_GREENTAB3 +//#define ST7735_REDTAB +//#define ST7735_BLACKTAB + +// For ST7735 ONLY, define the pixel width and height in portrait orientation +//#define TFT_WIDTH 128 +//#define TFT_HEIGHT 160 +//#define TFT_HEIGHT 128 + +// ################################################################################## +// +// Section 1. Define the pins that are used to interface with the display here +// +// ################################################################################## + +// We must use hardware SPI, a minimum of 3 GPIO pins is needed. +// Typical setup for NodeMCU ESP-12 is : +// +// Display SDO/MISO to NodeMCU pin D6 (or leave disconnected if not reading TFT) +// Display LED to NodeMCU pin VIN (or 5V, see below) +// Display SCK to NodeMCU pin D5 +// Display SDI/MOSI to NodeMCU pin D7 +// Display DC (or AO)to NodeMCU pin D3 +// Display RESET to NodeMCU pin D4 (or RST, see below) +// Display CS to NodeMCU pin D8 (or GND, see below) +// Display GND to NodeMCU pin GND (0V) +// Display VCC to NodeMCU 5V or 3.3V +// +// The TFT RESET pin can be connected to the NodeMCU RST pin or 3.3V to free up a control pin +// +// With some displays such as the ILI9341 the TFT CS pin can be connected to GND if no more +// SPI deivces (e.g. an SD Card) are connected, in this case comment out the #define TFT_CS +// line below so it is NOT defined. Other displays such at the ST7735 require the TFT CS pin +// to be toggled during setup, so in these cases the TFT_CS line must be defined and connected. +// +// The NodeMCU D0 pin can be used for RST +// +// See Section 2. below if DC or CS is connected to D0 +// +// Note: only some versions of the NodeMCU provide the USB 5V on the VIN pin +// If 5V is not available at a pin you can use 3.3V but backlight brightness +// will be lower. + +// ###### EDIT THE PIN NUMBERS IN THE LINES FOLLOWING TO SUIT YOUR SETUP ###### + +// ModeMCU +#define TFT_CS PIN_D8 // Chip select control pin D8 +#define TFT_DC PIN_D3 // Data Command control pin +//#define TFT_RST PIN_D4 // Reset pin (could connect to NodeMCU RST, see next line) +#define TFT_RST -1 // Set TFT_RST to -1 if the display RESET is connected to NodeMCU RST or 3.3V +#define TOUCH_CS D4 // Chip select pin (T_CS) of touch screen controller XPT2046 + +//#define TFT_WR PIN_D2 // Write strobe for modified Raspberry Pi TFT only + +// ESP32 Dev board (planned, not supported yet) +//#define TFT_CS 5 // Chip select control pin +//#define TFT_DC 2 // Data Command control pin +//#define TFT_RST 4 // Reset pin (could connect to Arduino RESET pin) +//#define TFT_RST -1 // Set TFT_RST to -1 if display RESET is connected to ESP32 board RST + +// ################################################################################## +// +// Section 2. Define the way the DC and/or CS lines are driven +// +// ################################################################################## + +// Normally the library uses direct register access for the DC and CS lines for speed +// If D0 (GPIO16) is used for CS or DC then a different slower method must be used +// Uncomment one line if D0 is used for DC or CS +// DC on D0 = 6% performance penalty at 40MHz SPI running graphics test +// CS on D0 = 2% performance penalty at 40MHz SPI running graphics test + +// #define D0_USED_FOR_DC +// #define D0_USED_FOR_CS + +// ################################################################################## +// +// Section 3. Define the fonts that are to be used here +// +// ################################################################################## + +// Comment out the #defines below with // to stop that font being loaded +// The ESP8366 had plenty of memory so commenting out fonts is not normally necessary +// If all fonts are loaded the extra FLASH space required is about 17Kbytes... +// To save FLASH space only enable the fonts you need! + +#define LOAD_GLCD // Font 1. Original Adafruit 8 pixel font needs ~1820 bytes in FLASH +#define LOAD_FONT2 // Font 2. Small 16 pixel high font, needs ~3534 bytes in FLASH, 96 characters +#define LOAD_FONT4 // Font 4. Medium 26 pixel high font, needs ~5848 bytes in FLASH, 96 characters +#define LOAD_FONT6 // Font 6. Large 48 pixel font, needs ~2666 bytes in FLASH, only characters 1234567890:-.apm +#define LOAD_FONT7 // Font 7. 7 segment 48 pixel font, needs ~2438 bytes in FLASH, only characters 1234567890:. +#define LOAD_FONT8 // Font 8. Large 75 pixel font needs ~3256 bytes in FLASH, only characters 1234567890:-. +#define LOAD_GFXFF // FreeFonts. Include access to the 48 Adafruit_GFX free fonts FF1 to FF48 and custom fonts + +// ################################################################################## +// +// Section 4. Not used +// +// ################################################################################## + + +// ################################################################################## +// +// Section 5. Other options +// +// ################################################################################## + +// Define the SPI clock frequency +// With an ILI9341 display 40MHz works OK, 80MHz sometimes fails +// With a ST7735 display more than 27MHz may not work (spurious pixels and lines) +// With an ILI9163 display TBD MHz works OK, + +// #define SPI_FREQUENCY 1000000 +// #define SPI_FREQUENCY 5000000 + #define SPI_FREQUENCY 10000000 +// #define SPI_FREQUENCY 20000000 +// #define SPI_FREQUENCY 27000000 // Actually sets it to 26.67MHz = 80/3 +// #define SPI_FREQUENCY 40000000 // Maximum to use SPIFFS +// #define SPI_FREQUENCY 80000000 + +#define SPI_TOUCH_FREQUENCY 2500000 + + +// Comment out the following #define if "SPI Transactions" do not need to be +// supported. Tranaction support is required if other SPI devices are connected. +// When commented out the code size will be smaller and sketches will +// run slightly faster, so leave it commented out unless you need it! +// Transaction support is needed to work with SD library but not needed with TFT_SdFat + +// #define SUPPORT_TRANSACTIONS diff --git a/examples/480 x 320/Touch_Controller_Demo/Touch_Controller_Demo.ino b/examples/480 x 320/Touch_Controller_Demo/Touch_Controller_Demo.ino new file mode 100644 index 0000000..6eda034 --- /dev/null +++ b/examples/480 x 320/Touch_Controller_Demo/Touch_Controller_Demo.ino @@ -0,0 +1,76 @@ +#include "FS.h" +#include +#include +TFT_eSPI tft = TFT_eSPI(); + +#define CALIBRATION_FILE "/calibrationData" + +void setup(void) { + uint16_t calibrationData[4]; + uint8_t calDataOK = 0; + + Serial.begin(115200); + Serial.println("starting"); + + tft.init(); + + tft.setRotation(2); + tft.fillScreen((0xFFFF)); + + tft.setCursor(20, 0, 2); + tft.setTextColor(TFT_BLACK, TFT_WHITE); tft.setTextSize(1); + tft.println("calibration run"); + + // check file system + if (!SPIFFS.begin()) { + Serial.println("formating file system"); + + SPIFFS.format(); + SPIFFS.begin(); + } + + // check if calibration file exists + if (SPIFFS.exists(CALIBRATION_FILE)) { + File f = SPIFFS.open(CALIBRATION_FILE, "r"); + if (f) { + if (f.readBytes((char *)calibrationData, 12) == 12) + calDataOK = 1; + f.close(); + } + } + if (calDataOK) { + // calibration data valid + tft.setTouch(calibrationData); + } else { + // data not valid. recalibrate + tft.calibrateTouch(calibrationData, TFT_WHITE, TFT_RED, 15); + // store data + File f = SPIFFS.open(CALIBRATION_FILE, "w"); + if (f) { + f.write((const unsigned char *)calibrationData, 12); + f.close(); + } + } + + tft.fillScreen((0xFFFF)); + +} + +void loop() { + uint16_t x, y; + static uint16_t color; + + if (tft.getTouch(&x, &y) { + + tft.setCursor(5, 5, 2); + tft.printf("x: %i ", x); + tft.setCursor(5, 20, 2); + tft.printf("y: %i ", y); + + tft.drawPixel(x, y, color); + color += 155; + } +} + + + From 944e505f3677cfb051d6c7aa0d873850fa261c78 Mon Sep 17 00:00:00 2001 From: Max Date: Sun, 1 Oct 2017 00:32:30 +0200 Subject: [PATCH 2/5] Add XPT2046 touch controller support supports esp8266 + RPi displays --- README.md | 3 ++ TFT_eSPI.cpp | 149 +++++++++++++++++++++++++++++++++++++++++++++++++++ TFT_eSPI.h | 21 ++++++++ User_Setup.h | 54 ++++++++----------- 4 files changed, 195 insertions(+), 32 deletions(-) diff --git a/README.md b/README.md index 606516d..d059391 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,8 @@ # TFT_eSPI +In addition to the original library, this library supports the XPT2046 touch screen controller, which is part of many RPi displays. The SPI is shared with the TFT and only an additional chip select line is needed. + + An Arduino IDE compatible graphics and fonts library for ESP8266 and ESP32 processors with a driver for ILI9341, ILI9163, ST7735 and S6D02A1 based TFT displays that support SPI. The library also supports TFT displays designed for the Raspberry Pi that are based on a ILI9486 driver chip with a 480 x 320 pixel screen. This display must be of the Waveshare design and use a 16 bit serial interface based on the 74HC04, 74HC4040 and 2 x 74HC4094 logic chips. A modification to these displays is possible (see mod image in Tools folder) to make many graphics functions much faster (e.g. 23ms to clear the screen, 1.2ms to draw a 72 pixel high numeral). diff --git a/TFT_eSPI.cpp b/TFT_eSPI.cpp index 0189854..5d22513 100644 --- a/TFT_eSPI.cpp +++ b/TFT_eSPI.cpp @@ -73,6 +73,12 @@ TFT_eSPI::TFT_eSPI(int16_t w, int16_t h) pinMode(TFT_CS, OUTPUT); #endif +// Configure chip select for touchscreen controller if present +#ifdef TOUCH_CS + digitalWrite(TOUCH_CS, HIGH); // Chip select high (inactive) + pinMode(TOUCH_CS, OUTPUT); +#endif + #ifdef TFT_WR digitalWrite(TFT_WR, HIGH); // Set write strobe high (inactive) pinMode(TFT_WR, OUTPUT); @@ -3641,6 +3647,149 @@ void spiWriteBlock(uint16_t color, uint32_t repeat) } #endif + +/*************************************************************************************** +** Function name: getTouchRaw +** Description: read raw position of touchpad if pressed. Return false if not pressed. +***************************************************************************************/ +#ifdef TOUCH_CS + +uint8_t TFT_eSPI::getTouchRaw(uint16_t *x, uint16_t *y){ + uint16_t tmp; + CS_H; + T_CS_L; + + SPI.setFrequency(SPI_TOUCH_FREQUENCY); + + // Start bit + YP sample request for x position + tmp = SPI.transfer(0xd0); + tmp = SPI.transfer(0); + tmp = tmp <<5; + tmp |= 0x1f & (SPI.transfer(0)>>3); + + if(tmp == 0 || tmp == 0x3ff){ + T_CS_H; + SPI.setFrequency(SPI_FREQUENCY); + return false; + } + + *x = tmp; + + // Start bit + XP sample request for y position + SPI.transfer(0x90); + tmp = SPI.transfer(0); + tmp = tmp <<5; + tmp |= 0x1f & (SPI.transfer(0)>>3); + + *y = tmp; + + T_CS_H; + SPI.setFrequency(SPI_FREQUENCY); + + if(tmp == 0 || tmp == 0x3ff){ + return false; + } + return true; +} + +/*************************************************************************************** +** Function name: getTouch +** Description: read callibrated position of touchpad if pressed. Return false if not pressed. +***************************************************************************************/ +uint8_t TFT_eSPI::getTouch(uint16_t *x, uint16_t *y){ + uint8_t retVal; + uint16_t x_tmp, y_tmp; + + retVal = getTouchRaw(&x_tmp,&y_tmp); + if(!retVal) + return retVal; + + *x=(x_tmp-touchCalibration_x0)*_width/(touchCalibration_x1-touchCalibration_x0); + *y=(y_tmp-touchCalibration_y0)*_height/(touchCalibration_y1-touchCalibration_y0); + + return retVal; +} + +/*************************************************************************************** +** Function name: calibrateTouch +** Description: generates calibration data for touchscreen. +***************************************************************************************/ +uint8_t TFT_eSPI::calibrateTouch(uint16_t *data, uint32_t color_bg, uint32_t color_fg, uint8_t size){ + uint16_t values[] = {0,0,0,0,0,0,0,0}; + uint16_t x_tmp, y_tmp; + + + for(uint8_t i = 0; i<4; i++){ + fillRect(0, 0, size+1, size+1, color_bg); + fillRect(0, _height-size-1, size+1, size+1, color_bg); + fillRect(_width-size-1, 0, size+1, size+1, color_bg); + fillRect(_width-size-1, _height-size-1, size+1, size+1, color_bg); + + if (i == 5) break; // used to clear the arrows + + switch (i) { + case 0: // up left + drawLine(0, 0, 0, size, color_fg); + drawLine(0, 0, size, 0, color_fg); + drawLine(0, 0, size , size, color_fg); + break; + case 1: // bot left + drawLine(0, _height-size-1, 0, _height-1, color_fg); + drawLine(0, _height-1, size, _height-1, color_fg); + drawLine(size, _height-size-1, 0, _height-1 , color_fg); + break; + case 2: // up right + drawLine(_width-size-1, 0, _width-1, 0, color_fg); + drawLine(_width-size-1, size, _width-1, 0, color_fg); + drawLine(_width-1, size, _width-1, 0, color_fg); + break; + case 3: // bot right + drawLine(_width-size-1, _height-size-1, _width-1, _height-1, color_fg); + drawLine(_width-1, _height-1-size, _width-1, _height-1, color_fg); + drawLine(_width-1-size, _height-1, _width-1, _height-1, color_fg); + break; + } + + // user has to get the chance to release + if(i>0) delay(1000); + + for(uint8_t j= 0; j<8; j++){ + while(!getTouchRaw(&x_tmp, &y_tmp)) delay(100); + values[i*2 ] += x_tmp; + values[i*2+1] += y_tmp; + } + values[i*2 ] /= 8; + values[i*2+1] /= 8; + } + + // TODO: build in orientation check! + touchCalibration_x0 = (values[0] + values[2])/2; // calc min x + touchCalibration_x1 = (values[4] + values[6])/2; // calc max x + touchCalibration_y0 = (values[1] + values[5])/2; // calc min y + touchCalibration_y1 = (values[3] + values[7])/2; // calc max y + + if(data != NULL){ + data[0] = touchCalibration_x0; + data[1] = touchCalibration_x1; + data[2] = touchCalibration_y0; + data[3] = touchCalibration_y1; + } +} + + +/*************************************************************************************** +** Function name: setTouch +** Description: imports calibration data for touchscreen. +***************************************************************************************/ +void TFT_eSPI::setTouch(uint16_t *data){ + touchCalibration_x0 = data[0]; + touchCalibration_x1 = data[1]; + touchCalibration_y0 = data[2]; + touchCalibration_y1 = data[3]; +} + +#endif + /*************************************************** The majority of code in this file is "FunWare", the only condition of use of those portions is that users have fun! Most of the effort has been spent on diff --git a/TFT_eSPI.h b/TFT_eSPI.h index 25c86b6..eff876f 100644 --- a/TFT_eSPI.h +++ b/TFT_eSPI.h @@ -108,6 +108,16 @@ #endif #endif +// chip select signal for touchscreen +#ifndef TOUCH_CS + #define T_CS_L // No macro allocated so it generates no code + #define T_CS_H // No macro allocated so it generates no code +#else + #define T_CS_L digitalWrite(TOUCH_CS, LOW) + #define T_CS_H digitalWrite(TOUCH_CS, HIGH) +#endif + + #ifdef TFT_WR #if defined (ESP32) #define WR_L GPIO.out_w1tc = (1 << TFT_WR) @@ -417,6 +427,13 @@ class TFT_eSPI : public Print { void setAddrWindow(int32_t xs, int32_t ys, int32_t xe, int32_t ye); +#ifdef TOUCH_CS + uint8_t getTouch(uint16_t *x, uint16_t *y); + uint8_t getTouchRaw(uint16_t *x, uint16_t *y); + uint8_t calibrateTouch(uint16_t *data, uint32_t color_bg, uint32_t color_fg, uint8_t size); + void setTouch(uint16_t *data); +#endif + virtual size_t write(uint8_t); private: @@ -435,6 +452,10 @@ inline void spi_end() __attribute__((always_inline)); uint32_t lastColor = 0xFFFF; +#ifdef TOUCH_CS + uint16_t touchCalibration_x0, touchCalibration_x1, touchCalibration_y0, touchCalibration_y1; +#endif + protected: int32_t cursor_x, cursor_y, win_xe, win_ye, padX; diff --git a/User_Setup.h b/User_Setup.h index a106fd9..70f798a 100644 --- a/User_Setup.h +++ b/User_Setup.h @@ -14,16 +14,11 @@ // ################################################################################## // Only define one driver, the other ones must be commented out -#define ILI9341_DRIVER +//#define ILI9341_DRIVER //#define ST7735_DRIVER //#define ILI9163_DRIVER //#define S6D02A1_DRIVER -//#define RPI_ILI9486_DRIVER // 20MHz maximum SPI - -// For ST7735 and ILI9163 ONLY, define the pixel width and height in portrait orientation -//#define TFT_WIDTH 128 -//#define TFT_HEIGHT 160 -//#define TFT_HEIGHT 128 +#define RPI_ILI9486_DRIVER // 20MHz maximum SPI // For ST7735 ONLY, define the type of display, originally this was based on the // colour of the tab on the screen protector film but this is not always true, so try @@ -36,10 +31,14 @@ //#define ST7735_GREENTAB //#define ST7735_GREENTAB2 //#define ST7735_GREENTAB3 -//#define ST7735_GREENTAB128 // For 128 x 128 display //#define ST7735_REDTAB //#define ST7735_BLACKTAB +// For ST7735 ONLY, define the pixel width and height in portrait orientation +//#define TFT_WIDTH 128 +//#define TFT_HEIGHT 160 +//#define TFT_HEIGHT 128 + // ################################################################################## // // Section 1. Define the pins that are used to interface with the display here @@ -53,7 +52,7 @@ // Display LED to NodeMCU pin VIN (or 5V, see below) // Display SCK to NodeMCU pin D5 // Display SDI/MOSI to NodeMCU pin D7 -// Display DC (RS/AO)to NodeMCU pin D3 +// Display DC (or AO)to NodeMCU pin D3 // Display RESET to NodeMCU pin D4 (or RST, see below) // Display CS to NodeMCU pin D8 (or GND, see below) // Display GND to NodeMCU pin GND (0V) @@ -61,8 +60,6 @@ // // The TFT RESET pin can be connected to the NodeMCU RST pin or 3.3V to free up a control pin // -// The DC (Data Command) pin may be labelled AO or RS (Register Select) -// // With some displays such as the ILI9341 the TFT CS pin can be connected to GND if no more // SPI deivces (e.g. an SD Card) are connected, in this case comment out the #define TFT_CS // line below so it is NOT defined. Other displays such at the ST7735 require the TFT CS pin @@ -76,35 +73,26 @@ // If 5V is not available at a pin you can use 3.3V but backlight brightness // will be lower. -// ###### EDIT THE PIN NUMBERS IN THE LINES FOLLOWING TO SUIT YOUR ESP8266 SETUP ###### - -// For ModeMCU - use pin numbers in the form PIN_Dx where Dx is the NodeMCU pin designation +// ###### EDIT THE PIN NUMBERS IN THE LINES FOLLOWING TO SUIT YOUR SETUP ###### +// ModeMCU #define TFT_CS PIN_D8 // Chip select control pin D8 #define TFT_DC PIN_D3 // Data Command control pin -#define TFT_RST PIN_D4 // Reset pin (could connect to NodeMCU RST, see next line) -//#define TFT_RST -1 // Set TFT_RST to -1 if the display RESET is connected to NodeMCU RST or 3.3V +//#define TFT_RST PIN_D4 // Reset pin (could connect to NodeMCU RST, see next line) +#define TFT_RST -1 // Set TFT_RST to -1 if the display RESET is connected to NodeMCU RST or 3.3V +#define TOUCH_CS D4 // Chip select pin (T_CS) of touch screen //#define TFT_WR PIN_D2 // Write strobe for modified Raspberry Pi TFT only -// ###### EDIT THE PIN NUMBERS IN THE LINES FOLLOWING TO SUIT YOUR ESP32 SETUP ###### - -// For ESP32 Dev board (only tested with ILI9341 display) -// The hardware SPI can be mapped to any pins - -//#define TFT_MISO 19 -//#define TFT_MOSI 23 -//#define TFT_SCLK 18 -//#define TFT_CS 15 // Chip select control pin -//#define TFT_DC 2 // Data Command control pin -//#define TFT_RST 4 // Reset pin (could connect to RST pin) +// ESP32 Dev board (planned, not supported yet) +//#define TFT_CS 5 // Chip select control pin +//#define TFT_DC 2 // Data Command control pin +//#define TFT_RST 4 // Reset pin (could connect to Arduino RESET pin) //#define TFT_RST -1 // Set TFT_RST to -1 if display RESET is connected to ESP32 board RST -//#define TFT_WR 22 // Write strobe for modified Raspberry Pi TFT only - // ################################################################################## // -// Section 2. Define the way the DC and/or CS lines are driven (ESP8266 only) +// Section 2. Define the way the DC and/or CS lines are driven // // ################################################################################## @@ -156,12 +144,14 @@ // #define SPI_FREQUENCY 1000000 // #define SPI_FREQUENCY 5000000 -// #define SPI_FREQUENCY 10000000 + #define SPI_FREQUENCY 10000000 // #define SPI_FREQUENCY 20000000 - #define SPI_FREQUENCY 27000000 // Actually sets it to 26.67MHz = 80/3 +// #define SPI_FREQUENCY 27000000 // Actually sets it to 26.67MHz = 80/3 // #define SPI_FREQUENCY 40000000 // Maximum to use SPIFFS // #define SPI_FREQUENCY 80000000 +#define SPI_TOUCH_FREQUENCY 2500000 + // Comment out the following #define if "SPI Transactions" do not need to be // supported. Tranaction support is required if other SPI devices are connected. From 8813ed35b150429012ea00966d7ab0989dc3c26d Mon Sep 17 00:00:00 2001 From: Max Date: Sun, 1 Oct 2017 00:56:05 +0200 Subject: [PATCH 3/5] should add esp32 support. have no hardware to test. --- TFT_eSPI.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/TFT_eSPI.cpp b/TFT_eSPI.cpp index 5d22513..732b83e 100644 --- a/TFT_eSPI.cpp +++ b/TFT_eSPI.cpp @@ -3659,6 +3659,12 @@ uint8_t TFT_eSPI::getTouchRaw(uint16_t *x, uint16_t *y){ CS_H; T_CS_L; +#ifdef SPI_HAS_TRANSACTION + #ifdef SUPPORT_TRANSACTIONS + if (locked) {locked = false; SPI.beginTransaction(SPISettings(SPI_TOUCH_FREQUENCY, MSBFIRST, SPI_MODE0));} + #endif +#endif + SPI.setFrequency(SPI_TOUCH_FREQUENCY); // Start bit + YP sample request for x position @@ -3670,6 +3676,7 @@ uint8_t TFT_eSPI::getTouchRaw(uint16_t *x, uint16_t *y){ if(tmp == 0 || tmp == 0x3ff){ T_CS_H; SPI.setFrequency(SPI_FREQUENCY); + spi_end(); return false; } @@ -3685,6 +3692,7 @@ uint8_t TFT_eSPI::getTouchRaw(uint16_t *x, uint16_t *y){ T_CS_H; SPI.setFrequency(SPI_FREQUENCY); + spi_end(); if(tmp == 0 || tmp == 0x3ff){ return false; From b6d234af709dc608116e69172b377043334ed3bd Mon Sep 17 00:00:00 2001 From: Max Date: Sun, 1 Oct 2017 00:58:33 +0200 Subject: [PATCH 4/5] should add ESP32 support. do not have hardware to test. --- .../480 x 320/Touch_Controller_Demo/Touch_Controller_Demo.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/480 x 320/Touch_Controller_Demo/Touch_Controller_Demo.ino b/examples/480 x 320/Touch_Controller_Demo/Touch_Controller_Demo.ino index 6eda034..4e03770 100644 --- a/examples/480 x 320/Touch_Controller_Demo/Touch_Controller_Demo.ino +++ b/examples/480 x 320/Touch_Controller_Demo/Touch_Controller_Demo.ino @@ -60,7 +60,7 @@ void loop() { uint16_t x, y; static uint16_t color; - if (tft.getTouch(&x, &y) { + if (tft.getTouch(&x, &y)) { tft.setCursor(5, 5, 2); tft.printf("x: %i ", x); From 548fcca258c55d780d0bfa6273ed479ab1268499 Mon Sep 17 00:00:00 2001 From: Max Date: Sun, 1 Oct 2017 21:34:11 +0200 Subject: [PATCH 5/5] now calibration works with all orientations. --- TFT_eSPI.cpp | 69 ++++++++++++++++--- TFT_eSPI.h | 1 + .../Touch_Controller_Demo.ino | 8 +-- 3 files changed, 66 insertions(+), 12 deletions(-) diff --git a/TFT_eSPI.cpp b/TFT_eSPI.cpp index 732b83e..a335193 100644 --- a/TFT_eSPI.cpp +++ b/TFT_eSPI.cpp @@ -3712,8 +3712,21 @@ uint8_t TFT_eSPI::getTouch(uint16_t *x, uint16_t *y){ if(!retVal) return retVal; - *x=(x_tmp-touchCalibration_x0)*_width/(touchCalibration_x1-touchCalibration_x0); - *y=(y_tmp-touchCalibration_y0)*_height/(touchCalibration_y1-touchCalibration_y0); + if(!touchCalibration_rotate){ + *x=(x_tmp-touchCalibration_x0)*_width/touchCalibration_x1; + *y=(y_tmp-touchCalibration_y0)*_height/touchCalibration_y1; + if(touchCalibration_invert_x) + *x = _width - *x; + if(touchCalibration_invert_y) + *y = _height - *y; + } else { + *y=(x_tmp-touchCalibration_x0)*_height/touchCalibration_x1; + *x=(y_tmp-touchCalibration_y0)*_width/touchCalibration_y1; + if(touchCalibration_invert_x) + *x = _width - *x; + if(touchCalibration_invert_y) + *y = _height - *y; + } return retVal; } @@ -3723,10 +3736,11 @@ uint8_t TFT_eSPI::getTouch(uint16_t *x, uint16_t *y){ ** Description: generates calibration data for touchscreen. ***************************************************************************************/ uint8_t TFT_eSPI::calibrateTouch(uint16_t *data, uint32_t color_bg, uint32_t color_fg, uint8_t size){ - uint16_t values[] = {0,0,0,0,0,0,0,0}; + int16_t values[] = {0,0,0,0,0,0,0,0}; uint16_t x_tmp, y_tmp; + for(uint8_t i = 0; i<4; i++){ fillRect(0, 0, size+1, size+1, color_bg); fillRect(0, _height-size-1, size+1, size+1, color_bg); @@ -3770,17 +3784,52 @@ uint8_t TFT_eSPI::calibrateTouch(uint16_t *data, uint32_t color_bg, uint32_t col values[i*2+1] /= 8; } - // TODO: build in orientation check! - touchCalibration_x0 = (values[0] + values[2])/2; // calc min x - touchCalibration_x1 = (values[4] + values[6])/2; // calc max x - touchCalibration_y0 = (values[1] + values[5])/2; // calc min y - touchCalibration_y1 = (values[3] + values[7])/2; // calc max y + + // check orientation + // from case 0 to case 1, the y value changed. + // If the meassured delta of the touch x axis is bigger than the delta of the y axis, the touch and TFT axes are switched. + touchCalibration_rotate = false; + if(abs(values[0]-values[2]) > abs(values[1]-values[3])){ + touchCalibration_rotate = true; + touchCalibration_x1 = (values[0] + values[4])/2; // calc min x + touchCalibration_x0 = (values[2] + values[6])/2; // calc max x + touchCalibration_y1 = (values[1] + values[3])/2; // calc min y + touchCalibration_y0 = (values[5] + values[7])/2; // calc max y + } else { + touchCalibration_x0 = (values[0] + values[2])/2; // calc min x + touchCalibration_x1 = (values[4] + values[6])/2; // calc max x + touchCalibration_y0 = (values[1] + values[5])/2; // calc min y + touchCalibration_y1 = (values[3] + values[7])/2; // calc max y + } + + // in addition, the touch screen axis could be in the opposit direction of the TFT axis + touchCalibration_invert_x = false; + if(touchCalibration_x0 > touchCalibration_x1){ + values[0]=touchCalibration_x0; + touchCalibration_x0 = touchCalibration_x1; + touchCalibration_x1 = values[0]; + touchCalibration_invert_x = true; + } + touchCalibration_invert_y = false; + if(touchCalibration_y0 > touchCalibration_y1){ + values[0]=touchCalibration_y0; + touchCalibration_y0 = touchCalibration_y1; + touchCalibration_y1 = values[0]; + touchCalibration_invert_y = true; + } + + // pre calculate + touchCalibration_x1 -= touchCalibration_x0; + touchCalibration_y1 -= touchCalibration_y0; + + // export data, if pointer valid if(data != NULL){ data[0] = touchCalibration_x0; data[1] = touchCalibration_x1; data[2] = touchCalibration_y0; data[3] = touchCalibration_y1; + data[4] = touchCalibration_rotate | (touchCalibration_invert_x <<1) | (touchCalibration_invert_y <<2); } } @@ -3794,6 +3843,10 @@ void TFT_eSPI::setTouch(uint16_t *data){ touchCalibration_x1 = data[1]; touchCalibration_y0 = data[2]; touchCalibration_y1 = data[3]; + + touchCalibration_rotate = data[4] & 0x01; + touchCalibration_invert_x = data[4] & 0x02; + touchCalibration_invert_y = data[4] & 0x04; } #endif diff --git a/TFT_eSPI.h b/TFT_eSPI.h index eff876f..d3a37da 100644 --- a/TFT_eSPI.h +++ b/TFT_eSPI.h @@ -454,6 +454,7 @@ inline void spi_end() __attribute__((always_inline)); #ifdef TOUCH_CS uint16_t touchCalibration_x0, touchCalibration_x1, touchCalibration_y0, touchCalibration_y1; + uint8_t touchCalibration_rotate, touchCalibration_invert_x, touchCalibration_invert_y; #endif protected: diff --git a/examples/480 x 320/Touch_Controller_Demo/Touch_Controller_Demo.ino b/examples/480 x 320/Touch_Controller_Demo/Touch_Controller_Demo.ino index 4e03770..f0b14d8 100644 --- a/examples/480 x 320/Touch_Controller_Demo/Touch_Controller_Demo.ino +++ b/examples/480 x 320/Touch_Controller_Demo/Touch_Controller_Demo.ino @@ -6,7 +6,7 @@ TFT_eSPI tft = TFT_eSPI(); #define CALIBRATION_FILE "/calibrationData" void setup(void) { - uint16_t calibrationData[4]; + uint16_t calibrationData[5]; uint8_t calDataOK = 0; Serial.begin(115200); @@ -14,7 +14,7 @@ void setup(void) { tft.init(); - tft.setRotation(2); + tft.setRotation(3); tft.fillScreen((0xFFFF)); tft.setCursor(20, 0, 2); @@ -33,7 +33,7 @@ void setup(void) { if (SPIFFS.exists(CALIBRATION_FILE)) { File f = SPIFFS.open(CALIBRATION_FILE, "r"); if (f) { - if (f.readBytes((char *)calibrationData, 12) == 12) + if (f.readBytes((char *)calibrationData, 14) == 14) calDataOK = 1; f.close(); } @@ -47,7 +47,7 @@ void setup(void) { // store data File f = SPIFFS.open(CALIBRATION_FILE, "w"); if (f) { - f.write((const unsigned char *)calibrationData, 12); + f.write((const unsigned char *)calibrationData, 14); f.close(); } }