Add XPT2046 touch controller support

supports esp8266 + RPi displays
This commit is contained in:
Max
2017-10-01 00:32:30 +02:00
parent ca54325fbc
commit 944e505f36
4 changed files with 195 additions and 32 deletions

View File

@@ -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).

View File

@@ -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

View File

@@ -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;

View File

@@ -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.