├── keywords.txt ├── library.properties ├── Calibration.h ├── README.md ├── TFT_Touch.h ├── Examples ├── TFT_Touch_Draw_2-4 │ └── TFT_Touch_Draw_2-4.ino ├── TFT_Touch_Raw │ └── TFT_Touch_Raw.ino └── TFT_Touch_Calibrate_v2 │ └── TFT_Touch_Calibrate_v2.ino └── TFT_Touch.cpp /keywords.txt: -------------------------------------------------------------------------------- 1 | TFT_Touch KEYWORD1 2 | Pressed KEYWORD2 3 | ReadRawX KEYWORD2 4 | ReadRawY KEYWORD2 5 | RawX KEYWORD2 6 | RawY KEYWORD2 7 | X KEYWORD2 8 | Y KEYWORD2 9 | Zone KEYWORD2 10 | setResolution KEYWORD2 11 | setCal KEYWORD2 12 | setRotation KEYWORD2 13 | ReadCal KEYWORD2 14 | -------------------------------------------------------------------------------- /library.properties: -------------------------------------------------------------------------------- 1 | name=TFT_Touch 2 | version=0.3 3 | author=Bodmer 4 | maintainer=Bodmer 5 | 6 | sentence=A TFT touch screen library for Arduino AVR processors (UNO, Mega, Leonardo, Pro Mini etc) 7 | paragraph=Supports TFT displays using the XPT2046 driver. 8 | category=Display 9 | url=https://github.com/Bodmer/TFT_Touch 10 | architectures=avr 11 | -------------------------------------------------------------------------------- /Calibration.h: -------------------------------------------------------------------------------- 1 | #ifndef _Calibration_H 2 | #define _Calibration_H 3 | 4 | // When a touch is detected the library samples x and y twice 5 | // The two x and two y values must be within RAWERR of each other 6 | // otherwise the touch is rejected as noisy. 7 | // Define +/- raw coord error limit for a press 8 | // A value of about 10 seems good 9 | 10 | #define _RAWERR 10 11 | 12 | #endif -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # TFT_Touch 2 | Arduino touch screen library for XPT2046 3 | 4 | This library has been tested on a 2.4" TFT screen that uses 5 | the ILI9341 display driver and XPT2046 touch controller. 6 | 7 | These displays are available at low cost on eBay and AliExpress. 8 | 9 | The library includes three sketches: 10 | 11 | * TFT_Touch_Calibrate_v2: to calibrate and test the screen 12 | * TFT_Touch_Draw_2-4 : a simple paint program 13 | * TFT_Touch_Raw : a touch screen test sketch (Serial Monitor output only) 14 | 15 | To make things really easy the calibration sketch reports the setup() 16 | calibration code to use in your sketch via a serial port message. 17 | 18 | The library could be used with any graphics library but the examples 19 | use this one: 20 | 21 | https://github.com/Bodmer/TFT_ILI9341 22 | 23 | 24 | -------------------------------------------------------------------------------- /TFT_Touch.h: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Library for 2046 controller based TFT touch screen. 4 | 5 | Significantly modified by Rowboteer 22/11/15 6 | Renamed TFT_Touch 7 | 8 | See original header text at end of file 9 | 10 | */ 11 | 12 | #ifndef _TFT_Touch_H 13 | #define _TFT_Touch_H 14 | 15 | #include "Arduino.h" 16 | #include "Calibration.h" 17 | 18 | class TFT_Touch 19 | { 20 | public: 21 | TFT_Touch(byte CS_Pin, byte Clk_Pin, byte Din_DIO, byte Dout_DIO); 22 | boolean Pressed(void); 23 | uint16_t ReadRawX(void); 24 | uint16_t ReadRawY(void); 25 | uint16_t RawX(void); 26 | uint16_t RawY(void); 27 | uint16_t X(void); 28 | uint16_t Y(void); 29 | uint32_t Zone(void); 30 | 31 | void setResolution(uint16_t xres, uint16_t yres); 32 | void setCal(uint16_t xmin, uint16_t xmax, uint16_t ymin, uint16_t ymax, uint16_t xres, uint16_t yres, boolean axis);//, boolean xflip, boolean yflip); 33 | void setRotation(byte rotation); 34 | 35 | int16_t ReadCal(byte param); 36 | 37 | uint16_t _hmin, _hmax, _vmin, _vmax, _hres, _vres; 38 | boolean _axis, _xyswap, _xflip, _yflip; 39 | 40 | private: 41 | 42 | int16_t _ReadAxis(boolean Axis); 43 | 44 | byte _CS; 45 | byte _Clk; 46 | byte _Din; 47 | byte _Dout; 48 | 49 | int16_t _xraw, _yraw, _xcoord, _ycoord; 50 | //boolean _XYswap, _Xflip, _Yflip; 51 | 52 | void _PulseClock(void); 53 | uint16_t _ReadData(void); 54 | void _OutputData(byte Data); 55 | }; 56 | 57 | #endif 58 | 59 | // Original header 60 | 61 | /* FILE: HCTFT_Touch.h 62 | DATE: 10/06/14 63 | VERSION: 0.1 64 | AUTHOR: Andrew Davies 65 | 66 | Library header for 2046 controller based TFT touch screen. 67 | 68 | You may copy, alter and reuse this code in any way you like, but please leave 69 | reference to HobbyComponents.com in your comments if you redistribute this code. 70 | This software may not be used directly for the purpose of selling products that 71 | directly compete with Hobby Components Ltd's own range of products. 72 | 73 | THIS SOFTWARE IS PROVIDED "AS IS". HOBBY COMPONENTS MAKES NO WARRANTIES, WHETHER 74 | EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF 75 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ACCURACY OR LACK OF NEGLIGENCE. 76 | HOBBY COMPONENTS SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR ANY DAMAGES, 77 | INCLUDING, BUT NOT LIMITED TO, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES FOR ANY 78 | REASON WHATSOEVER. 79 | */ -------------------------------------------------------------------------------- /Examples/TFT_Touch_Draw_2-4/TFT_Touch_Draw_2-4.ino: -------------------------------------------------------------------------------- 1 | /* 2 | This is a simple paint sketch! 3 | 4 | Tested with a 2.4" ILI9341 based display of 320 x 240 pixles 5 | 6 | Uses font 2 only 7 | 8 | The example will read the current state of the touch screen and output it to the serial 9 | port as raw X and Y coordinates, as the current position in pixels and a zone number. 10 | 11 | >>>> YOU MUST CALIBRATE THE TOUCH SCREEN AND COPY THE SETTINGS TO LINE 48 OF THIS SKETCH <<<< 12 | 13 | >>>> YOU MUST CHANGE THE PIN DEFINITION AT LINES 29-32 TO SUIT YOUR SETUP <<<< 14 | 15 | Created by Rowboteer: 22/11/15 16 | */ 17 | 18 | // Call up the TFT driver library 19 | #include // Hardware-specific TFT library 20 | #include 21 | 22 | // Call up touch screen library 23 | #include 24 | 25 | // Invoke custom TFT driver library 26 | TFT_ILI9341 tft = TFT_ILI9341(); // Invoke custom library 27 | 28 | // These are the pins used to interface between the 2046 touch controller and Arduino Pro 29 | #define DOUT A0 /* Data out pin (T_DO) of touch screen */ 30 | #define DIN A2 /* Data in pin (T_DIN) of touch screen */ 31 | #define DCS 9 /* Chip select pin (T_CS) of touch screen */ 32 | #define DCLK 8 /* Clock pin (T_CLK) of touch screen */ 33 | 34 | /* Create an instance of the touch screen library */ 35 | TFT_Touch touch = TFT_Touch(DCS, DCLK, DIN, DOUT); 36 | 37 | int ColorPaletteHigh = 30; // Height of palette boxes 38 | int color = TFT_WHITE; //Starting paint brush color 39 | 40 | // Pallete button colour sequence 41 | unsigned int colors[10] = {TFT_RED, TFT_GREEN, TFT_BLUE, TFT_BLACK, TFT_CYAN, TFT_YELLOW, TFT_WHITE, TFT_MAGENTA, TFT_BLACK, TFT_BLACK}; 42 | 43 | void setup() 44 | { 45 | Serial.begin(38400); 46 | 47 | tft.init(); 48 | 49 | //This is the calibration line produced by the TFT_Touch_Calibrate_v2 sketch 50 | touch.setCal(481, 3395, 755, 3487, 320, 240, 1); 51 | 52 | // Set the TFT and touch screen to landscape orientation 53 | tft.setRotation(1); 54 | touch.setRotation(1); 55 | 56 | tft.setTextSize(1); 57 | tft.fillScreen(TFT_BLACK); 58 | tft.setTextColor(TFT_GREEN); 59 | 60 | //Draw the pallet 61 | for (int i = 0; i < 10; i++) 62 | { 63 | tft.fillRect(i * 32, 0, 32, ColorPaletteHigh, colors[i]); 64 | } 65 | 66 | //Draw the clear screen button 67 | tft.setCursor(264, 7, 2); // x,y,font 68 | tft.setTextColor(TFT_WHITE); 69 | tft.print("Clear"); 70 | tft.drawRect(0, 0, 319, 30, TFT_WHITE); 71 | 72 | // Plot the current colour in the screen clear box 73 | tft.fillRect(300, 9, 12, 12, color); 74 | } 75 | 76 | /* Main program */ 77 | void loop() 78 | { 79 | int X_RawData; 80 | int Y_RawData; 81 | int X_Coord; 82 | int Y_Coord; 83 | 84 | // Check if the touch screen is currently pressed 85 | // Raw and coordinate values are stored within library at this instant 86 | // for later retrieval by GetRaw and GetCoord functions. 87 | 88 | if (touch.Pressed()) // Note this function updates coordinates stored within library variables 89 | { 90 | // Read the current X and Y axis as co-ordinates at the last touch time 91 | // The values were captured when Pressed() was called! 92 | X_Coord = touch.X(); 93 | Y_Coord = touch.Y(); 94 | 95 | Serial.print(X_Coord); Serial.print(","); Serial.println(Y_Coord); 96 | 97 | // Detect paint brush color change 98 | if (Y_Coord < ColorPaletteHigh + 2) 99 | { 100 | if (X_Coord / 32 > 7) 101 | { 102 | // Clear the screen to current colour 103 | tft.fillRect(0, 30, 399, 239, color); 104 | } 105 | else 106 | { 107 | color = colors[X_Coord / 32]; 108 | // Update the cuurent colour in the clear box 109 | tft.fillRect(300, 9, 12, 12, color); 110 | } 111 | } 112 | else 113 | { 114 | tft.fillCircle(X_Coord, Y_Coord, 2, color); 115 | } 116 | } 117 | } 118 | 119 | -------------------------------------------------------------------------------- /Examples/TFT_Touch_Raw/TFT_Touch_Raw.ino: -------------------------------------------------------------------------------- 1 | /* FILE: TFT_Touch_Example1 2 | DATE: 10/06/14 3 | VERSION: 0.1 4 | ORIGINAL AUTHOR: Andrew Davies 5 | 6 | This is an example of how to use the TFT_Touch library. It does not display 7 | anything on the screen! 8 | 9 | Open up the Serial Monitor Window from the IDE and set to 38400 baud to see the 10 | information from screen contacts 11 | 12 | By using a stylus at the screen extremes or touch zone limits this sketch can be 13 | used to check tha calibration values. 14 | 15 | IMPORTANT: The 2.4" screen orientation used for calibration is with the SD Card slot on the left! 16 | 17 | The library provides the ability to read the current status of the touch screen. 18 | It does not provide any graphics drawing functions for controlling the TFT screen itself 19 | it is intended for providing touch screen support to any graphics sketches and libraries. 20 | However the library will work standalone as this example sketch will demonstrate. 21 | 22 | The example will read the current state of the touch screen and output it to the serial 23 | port as raw X and Y coordinates. 24 | 25 | No information will be displayed on the TFT screen itself whilst this example is running. 26 | 27 | You may copy, alter and reuse this code in any way you like, but please leave 28 | reference to HobbyComponents.com in your comments if you redistribute this code. 29 | This software may not be used directly for the purpose of selling products that 30 | directly compete with Hobby Components Ltd's own range of products. 31 | 32 | THIS SOFTWARE IS PROVIDED "AS IS". HOBBY COMPONENTS MAKES NO WARRANTIES, WHETHER 33 | EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF 34 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ACCURACY OR LACK OF NEGLIGENCE. 35 | HOBBY COMPONENTS SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR ANY DAMAGES, 36 | INCLUDING, BUT NOT LIMITED TO, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES FOR ANY 37 | REASON WHATSOEVER. 38 | 39 | Adapted by Rowboteer 13/5/15 40 | */ 41 | 42 | // These are the pins used to interface between the 2046 touch controller and Arduino Mega 43 | #define DOUT A0 /* Data out pin (T_DO) of touch screen */ 44 | #define DIN A2 /* Data in pin (T_DIN) of touch screen */ 45 | #define DCS 9 /* Chip select pin (T_CS) of touch screen */ 46 | #define DCLK 8 /* Clock pin (T_CLK) of touch screen */ 47 | 48 | // These are the default min and maximum values, set to 0 and 4095 to test the screen 49 | #define HMIN 0 50 | #define HMAX 4095 51 | #define VMIN 0 52 | #define VMAX 4095 53 | #define XYSWAP 0 // 0 or 1 54 | 55 | // This is the screen size for the raw to coordinate transformation 56 | // width and height specified for landscape orientation 57 | #define HRES 320 /* Default screen resulution for X axis */ 58 | #define VRES 320 /* Default screen resulution for Y axis */ 59 | 60 | #include 61 | 62 | /* Create an instance of the touch screen library */ 63 | TFT_Touch touch = TFT_Touch(DCS, DCLK, DIN, DOUT); 64 | 65 | void setup() 66 | { 67 | Serial.begin(38400); 68 | touch.setCal(HMIN, HMAX, VMIN, VMAX, HRES, VRES, XYSWAP); // Raw xmin, xmax, ymin, ymax, width, height 69 | touch.setRotation(1); 70 | } 71 | 72 | /* Main program */ 73 | void loop() 74 | { 75 | unsigned int X_Raw; 76 | unsigned int Y_Raw; 77 | 78 | /* Check if the touch screen is currently pressed*/ 79 | // Raw and coordinate values are stored within library at this instant 80 | // for later retrieval by GetRaw and GetCoord functions. 81 | // This avoids getting duff values returned 82 | if (touch.Pressed()) // Note this function updates coordinates stored within library variables 83 | { 84 | /* Read the current X and Y axis as raw co-ordinates at the last touch time*/ 85 | // The values returned were captured when Pressed() was called! 86 | 87 | X_Raw = touch.RawX(); 88 | Y_Raw = touch.RawY(); 89 | 90 | /* Output the results to the serial port */ 91 | Serial.print("Raw x,y = "); 92 | Serial.print(X_Raw); 93 | Serial.print(","); 94 | Serial.println(Y_Raw); 95 | delay(10); 96 | } 97 | delay(10); 98 | } 99 | 100 | -------------------------------------------------------------------------------- /TFT_Touch.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Library for 2046 controller based TFT touch screen. 4 | 5 | Significantly modified by Rowboteer 22/11/15 6 | Renamed TFT_Touch 7 | 8 | See original header text at end of file 9 | */ 10 | 11 | 12 | #include "Arduino.h" 13 | #include "TFT_Touch.h" 14 | 15 | /* Constructor to initialise the GPIO */ 16 | TFT_Touch::TFT_Touch(byte CS_Pin, byte Clk_Pin, byte Din_Pin, byte Dout_Pin) 17 | { 18 | _CS = CS_Pin; 19 | _Clk = Clk_Pin; 20 | _Din = Din_Pin; 21 | _Dout = Dout_Pin; 22 | 23 | pinMode(_CS, OUTPUT); 24 | pinMode(_Clk, OUTPUT); 25 | pinMode(_Din, OUTPUT); 26 | pinMode(_Dout, INPUT); 27 | 28 | digitalWrite(_CS, HIGH); 29 | digitalWrite(_Clk, LOW); 30 | digitalWrite(_Din, LOW); 31 | 32 | _hmin = 0; 33 | _hmax = 4095; 34 | _vmin = 0; 35 | _vmax = 4095; 36 | _hres = 320; 37 | _vres = 240; 38 | 39 | _xyswap = 0; 40 | _xflip = 0; 41 | _yflip = 0; 42 | 43 | _axis = 0; 44 | 45 | //_XYswap = 0; 46 | //_Xflip = 0; 47 | //_Yflip = 0; 48 | } 49 | 50 | /* Detects if the touch screen is currently pressed. Returns TRUE if pressed */ 51 | boolean TFT_Touch::Pressed(void) 52 | { 53 | 54 | // Get the raw contact coordinates 55 | _xraw = _ReadAxis(_axis); 56 | _yraw = _ReadAxis(!_axis); 57 | 58 | // Now double check the touch is still near the initial contact point 59 | // This helps to debounce the touch contact 60 | // We are working with signed integers intentionally 61 | delay(1); 62 | if (abs(_xraw - _ReadAxis(_axis)) > _RAWERR) return false; 63 | if (abs(_yraw - _ReadAxis(!_axis)) > _RAWERR) return false; 64 | delay(1); 65 | if (abs(_xraw - _ReadAxis(_axis)) > _RAWERR) return false; 66 | if (abs(_yraw - _ReadAxis(!_axis)) > _RAWERR) return false; 67 | 68 | /* 69 | // Get the raw contact coordinates, temporary test to emulate a flip and rotation 70 | _xraw = _ReadAxis(!_axis); 71 | _yraw = 4095 - _ReadAxis(_axis); 72 | 73 | // Now double check the touch is still near the initial contact point 74 | // This helps to debounce the touch contact 75 | // We are working with signed integers intentionally 76 | delay(1); 77 | if (abs(_xraw - _ReadAxis(!_axis)) > _RAWERR) return false; 78 | if (abs(_yraw - (4095 - _ReadAxis(_axis))) > _RAWERR) return false; 79 | delay(1); 80 | if (abs(_xraw - _ReadAxis(!_axis)) > _RAWERR) return false; 81 | if (abs(_yraw - (4095 - _ReadAxis(_axis))) > _RAWERR) return false; 82 | */ 83 | 84 | // Check values are in calibration range 85 | //if((_yraw > _vmin && _yraw < _vmax) && (_xraw > _hmin && _xraw < _hmax)) 86 | if((_yraw > 0 && _yraw < 4095) && (_xraw > 0 && _xraw < 4095)) 87 | { 88 | if (_xyswap){ 89 | _xcoord = constrain(map(_yraw, _vmin, _vmax, 30, _vres-30), 0, _vres); 90 | _ycoord = constrain(map(_xraw, _hmin, _hmax, 30, _hres-30), 0, _hres); 91 | if(_xflip) _xcoord = _vres - _xcoord; 92 | if(_yflip) _ycoord = _hres - _ycoord; 93 | } 94 | else 95 | { 96 | _xcoord = constrain(map(_xraw, _hmin, _hmax, 30, _hres-30), 0, _hres); 97 | _ycoord = constrain(map(_yraw, _vmin, _vmax, 30, _vres-30), 0, _vres); 98 | if(_xflip) _xcoord = _hres - _xcoord; 99 | if(_yflip) _ycoord = _vres - _ycoord; 100 | } 101 | 102 | return true; 103 | }else 104 | { 105 | return false; 106 | } 107 | } 108 | 109 | /* Reads one of the axis (XAXIS or YAXIS) raw coordinates. */ 110 | int16_t TFT_Touch::_ReadAxis(boolean Axis) 111 | { 112 | int Data; 113 | 114 | digitalWrite(_CS, LOW); 115 | if (Axis) 116 | { 117 | _OutputData(0x90); 118 | }else 119 | { 120 | _OutputData(0xD0); 121 | } 122 | 123 | digitalWrite(_Clk, HIGH); digitalWrite(_Clk, LOW); //_PulseClock(); 124 | Data = _ReadData(); 125 | digitalWrite(_Clk, HIGH); digitalWrite(_Clk, LOW); //_PulseClock(); 126 | digitalWrite(_Clk, HIGH); digitalWrite(_Clk, LOW); //_PulseClock(); 127 | digitalWrite(_Clk, HIGH); digitalWrite(_Clk, LOW); //_PulseClock(); 128 | digitalWrite(_CS, HIGH); 129 | digitalWrite(_Din, LOW); 130 | 131 | return Data; 132 | } 133 | 134 | /* Reads the raw data from the touch screen */ 135 | uint16_t TFT_Touch::_ReadData(void) 136 | { 137 | byte index; 138 | int Data; 139 | Data = 0; 140 | for (index = 12; index > 0; index--) 141 | { 142 | Data += digitalRead(_Dout) << (index-1); 143 | digitalWrite(_Clk, HIGH); digitalWrite(_Clk, LOW); //_PulseClock(); 144 | } 145 | return Data; 146 | } 147 | 148 | /* Writes to the touch screen's configuration register */ 149 | void TFT_Touch::_OutputData(byte Data) 150 | { 151 | byte index; 152 | 153 | for (index = 8; index > 0; index--) 154 | { 155 | digitalWrite(_Din, (Data >> (index -1)) & 1); 156 | digitalWrite(_Clk, HIGH); digitalWrite(_Clk, LOW); //_PulseClock(); 157 | } 158 | } 159 | 160 | /* Read the current position from the touch screen and return it as a pixel position. */ 161 | uint16_t TFT_Touch::ReadRawX(void) 162 | { 163 | return _ReadAxis(_axis);; 164 | } 165 | 166 | /* Read the current position from the touch screen and return it as a pixel position. */ 167 | uint16_t TFT_Touch::ReadRawY(void) 168 | { 169 | return _ReadAxis(!_axis);; 170 | } 171 | 172 | /* Read the last position from the touch screen and return it as a pixel position. */ 173 | uint16_t TFT_Touch::RawX(void) 174 | { 175 | return _xraw; 176 | } 177 | 178 | /* Read the last position from the touch screen and return it as a pixel position. */ 179 | uint16_t TFT_Touch::RawY(void) 180 | { 181 | return _yraw; 182 | } 183 | 184 | /* Read the last position from the touch screen and return it as a pixel position. */ 185 | uint16_t TFT_Touch::X(void) 186 | { 187 | return _xcoord; 188 | } 189 | 190 | /* Read the last position from the touch screen and return it as a pixel position. */ 191 | uint16_t TFT_Touch::Y(void) 192 | { 193 | return _ycoord; 194 | } 195 | 196 | /* Read the last zone from the touch screen and return it as a pixel position. */ 197 | uint32_t TFT_Touch::Zone(void) 198 | { 199 | return _xcoord + (uint32_t)_ycoord *_hres; 200 | } 201 | 202 | /* Set the screen resolution in pixels. */ 203 | void TFT_Touch::setResolution(uint16_t hres, uint16_t vres) 204 | { 205 | _hres = hres; 206 | _vres = vres; 207 | } 208 | 209 | /* Set the screen calibration values */ 210 | void TFT_Touch::setCal(uint16_t hmin, uint16_t hmax, 211 | uint16_t vmin, uint16_t vmax, 212 | uint16_t hres, uint16_t vres, 213 | bool axis)//, bool xflip, bool yflip) 214 | { 215 | _hmin = hmin; 216 | _hmax = hmax; 217 | _vmin = vmin; 218 | _vmax = vmax; 219 | _hres = hres; 220 | _vres = vres; 221 | 222 | _axis = axis; 223 | //_Xflip = xflip; 224 | //_Yflip = yflip; 225 | } 226 | 227 | int16_t TFT_Touch::ReadCal(byte param) 228 | { 229 | switch(param) { 230 | case 1: 231 | return _hmin; 232 | break; 233 | case 2: 234 | return _hmax; 235 | break; 236 | case 3: 237 | return _vmin; 238 | break; 239 | case 4: 240 | return _vmax; 241 | break; 242 | case 5: 243 | return _hres; 244 | break; 245 | case 6: 246 | return _vres; 247 | break; 248 | case 7: 249 | return _axis; 250 | break; 251 | //case 8: 252 | // return _xflip; 253 | // break; 254 | //case 9: 255 | // return _yflip; 256 | // break; 257 | } 258 | return 0; 259 | } 260 | void TFT_Touch::setRotation(byte rotation) 261 | { 262 | switch(rotation) { 263 | case 1: 264 | _xyswap = 0; 265 | _xflip = 0;//_Xflip; 266 | _yflip = 0;//_Yflip; 267 | break; 268 | case 2: 269 | _xyswap = 1; 270 | _xflip = 0;//_Xflip; 271 | _yflip = 1;//!_Yflip; 272 | break; 273 | case 3: 274 | _xyswap = 0; 275 | _xflip = 1;//!_Xflip; 276 | _yflip = 1;//!_Yflip; 277 | break; 278 | case 0: 279 | _xyswap = 1; 280 | _xflip = 1;//!_Xflip; 281 | _yflip = 0;//_Yflip; 282 | break; 283 | } 284 | } 285 | 286 | 287 | // Original header 288 | 289 | /* FILE: HCTFT_Touch.h 290 | DATE: 10/06/14 291 | VERSION: 0.1 292 | AUTHOR: Andrew Davies 293 | 294 | Library for 2046 controller based TFT touch screen. 295 | 296 | You may copy, alter and reuse this code in any way you like, but please leave 297 | reference to HobbyComponents.com in your comments if you redistribute this code. 298 | This software may not be used directly for the purpose of selling products that 299 | directly compete with Hobby Components Ltd's own range of products. 300 | 301 | THIS SOFTWARE IS PROVIDED "AS IS". HOBBY COMPONENTS MAKES NO WARRANTIES, WHETHER 302 | EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF 303 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ACCURACY OR LACK OF NEGLIGENCE. 304 | HOBBY COMPONENTS SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR ANY DAMAGES, 305 | INCLUDING, BUT NOT LIMITED TO, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES FOR ANY 306 | REASON WHATSOEVER. 307 | */ 308 | -------------------------------------------------------------------------------- /Examples/TFT_Touch_Calibrate_v2/TFT_Touch_Calibrate_v2.ino: -------------------------------------------------------------------------------- 1 | /* 2 | This is a sketch to calibrate the screem and list the values to use in the 3 | setCal() function. 4 | 5 | The calibration report is sent to the Serial port at 38400 baud. 6 | 7 | Designed for use with the TFT_ILI9341 library 8 | https://github.com/Bodmer/TFT_ILI9341 9 | 10 | Uses font 2 only. 11 | 12 | Created by Rowboteer for the ILI9341 3.4" 320 x 240 TFT touch display: 22/11/15 13 | */ 14 | 15 | // TFT Screen pixel resolution in landscape orientation, change these to suit your display 16 | // Defined in landscape orientation ! 17 | #define HRES 320 18 | #define VRES 240 19 | 20 | // Call up the TFT driver library 21 | #include // Hardware-specific TFT library 22 | #include 23 | 24 | // Call up touch screen library 25 | #include 26 | 27 | // Invoke custom TFT driver library 28 | TFT_ILI9341 tft = TFT_ILI9341(); // Invoke custom library 29 | 30 | // These are the pins I used to interface between the 2046 touch controller and Arduino Mega 31 | // they can be changed to other digital pins 32 | 33 | #define DOUT A0 /* Data out pin (T_DO) of touch screen */ 34 | #define DIN A2 /* Data in pin (T_DIN) of touch screen */ 35 | #define DCS 9 /* Chip select pin (T_CS) of touch screen */ 36 | #define DCLK 8 /* Clock pin (T_CLK) of touch screen */ 37 | // The touch screen interrupt request pin (T_IRQ) is not used 38 | 39 | /* Create an instance of the touch screen library */ 40 | TFT_Touch touch = TFT_Touch(DCS, DCLK, DIN, DOUT); 41 | 42 | int X_Raw = 0, Y_Raw = 0; 43 | 44 | void setup() 45 | { 46 | // Messages are sent to the serial port 47 | Serial.begin(38400); 48 | 49 | // Initialise the TFT 50 | tft.init(); 51 | 52 | // Set the TFT screen to landscape orientation 53 | tft.setRotation(1); 54 | 55 | tft.setTextDatum(TC_DATUM); // Set text plotting reference datum to Top Centre (TC) 56 | tft.setTextColor(TFT_WHITE, TFT_BLACK); // Set text to white on black 57 | } 58 | 59 | /* Main program */ 60 | void loop() 61 | { 62 | int x1, y1; 63 | int x2, y2; 64 | int x3, y3; 65 | bool xyswap = 0, xflip = 0, yflip = 0; 66 | 67 | Serial.println("TFT_Touch Calibration, follow TFT screen prompts.."); 68 | 69 | // Reset the calibration values 70 | touch.setCal(0, 4095, 0, 4095, 320, 240, 0);//, 0, 0); 71 | 72 | // Set TFT the screen to landscape orientation 73 | tft.setRotation(1); 74 | 75 | // Set Touch the screen to the same landscape orientation 76 | touch.setRotation(1); 77 | 78 | // Clear the screen 79 | tft.fillScreen(TFT_BLACK); 80 | 81 | // Show the screen prompt 82 | drawPrompt(); 83 | 84 | drawCross(30, 30, TFT_RED); 85 | while (!touch.Pressed()); 86 | delay(100); 87 | 88 | getCoord(); // This function assigns values to X_Raw and Y_Raw 89 | 90 | drawCross(30, 30, TFT_BLACK); 91 | Serial.print("First point : Raw x,y = "); 92 | Serial.print(X_Raw); 93 | Serial.print(","); 94 | Serial.println(Y_Raw); 95 | 96 | x1 = X_Raw; 97 | y1 = Y_Raw; 98 | 99 | drawCross(HRES/2, VRES/2, TFT_RED); 100 | delay(10); 101 | 102 | while (getCoord()); // This waits for the centre area to be touched 103 | 104 | drawCross(HRES/2, VRES/2, TFT_BLACK); 105 | Serial.print("Second point : Raw x,y = "); 106 | Serial.print(X_Raw); 107 | Serial.print(","); 108 | Serial.println(Y_Raw); 109 | 110 | drawCross(HRES-30, VRES-30, TFT_RED); 111 | 112 | while (!getCoord()); // This waits until the centre area is no longer pressed 113 | delay(10); // Wait a little for touch bounces to stop after release 114 | 115 | getCoord(); 116 | drawCross(HRES-30, VRES-30, TFT_BLACK); 117 | Serial.print("Third point : Raw x,y = "); 118 | Serial.print(X_Raw); 119 | Serial.print(","); 120 | Serial.println(Y_Raw); 121 | 122 | x2 = X_Raw; 123 | y2 = Y_Raw; 124 | 125 | drawCross(HRES/2, VRES/2, TFT_RED); 126 | delay(10); 127 | 128 | while (getCoord()); // This waits for the centre area to be touched 129 | 130 | drawCross(HRES/2, VRES/2, TFT_BLACK); 131 | Serial.print("Fourth point : Raw x,y = "); 132 | Serial.print(X_Raw); 133 | Serial.print(","); 134 | Serial.println(Y_Raw); 135 | 136 | drawCross(30, VRES-30, TFT_RED); 137 | 138 | while (!getCoord()); // This waits until the centre area is no longer pressed 139 | delay(10); // Wait a little for touch bounces to stop after release 140 | 141 | getCoord(); 142 | drawCross(30, VRES-30, TFT_BLACK); 143 | Serial.print("Fifth point : Raw x,y = "); 144 | Serial.print(X_Raw); 145 | Serial.print(","); 146 | Serial.println(Y_Raw); 147 | 148 | x3 = X_Raw; 149 | y3 = Y_Raw; 150 | 151 | int temp; 152 | if (abs(x1 - x3) > 1000) { 153 | xyswap = 1; 154 | temp = x1; x1 = y1; y1 = temp; 155 | temp = x2; x2 = y2; y2 = temp; 156 | temp = x3; x3 = y3; y3 = temp; 157 | } 158 | else xyswap = 0; 159 | 160 | 161 | //if (x2 < x1) { 162 | // temp = x2; x2 = x1; x1 = temp; 163 | // xflip = 1; 164 | //} 165 | 166 | //if (y2 < y1) { 167 | // temp = y2; y2 = y1; y1 = temp; 168 | // yflip = 1; 169 | //} 170 | 171 | int hmin = x1;// - (x2 - x1) * 3 / (HRES/10 - 6); 172 | int hmax = x2;// + (x2 - x1) * 3 / (HRES/10 - 6); 173 | 174 | int vmin = y1;// - (y2 - y1) * 3 / (VRES/10 - 6); 175 | int vmax = y2;// + (y2 - y1) * 3 / (VRES/10 - 6); 176 | 177 | // Serial.println(); 178 | // Serial.println("These are the values you can use in Calibration.h"); 179 | // Serial.print("#define _XMIN "); 180 | // Serial.println(xmin); 181 | // Serial.print("#define _YMIN "); 182 | // Serial.println(ymin); 183 | 184 | // Serial.print("#define _XMAX "); 185 | // Serial.println(xmax); 186 | // Serial.print("#define _YMAX "); 187 | // Serial.println(ymax); 188 | 189 | Serial.println(); 190 | Serial.println(" //This is the calibration line to use in your sketch"); 191 | Serial.println(" //you can copy and paste into your sketch setup()"); 192 | Serial.print(" touch.setCal("); 193 | Serial.print(hmin); Serial.print(", "); 194 | Serial.print(hmax); Serial.print(", "); 195 | Serial.print(vmin); Serial.print(", "); 196 | Serial.print(vmax); Serial.print(", "); 197 | Serial.print(HRES); Serial.print(", "); 198 | Serial.print(VRES); Serial.print(", "); 199 | Serial.print(xyswap); //Serial.print(", "); 200 | //Serial.print(xflip); Serial.print(", "); 201 | //Serial.print(yflip); 202 | Serial.println(");"); 203 | 204 | Serial.println(); 205 | Serial.println("Test the touch screen, green crosses appear at the touch coordinates!"); 206 | Serial.println("Send any character from the serial monitor window to restart calibration"); 207 | 208 | // These are the calibration settings the sketch has calculated to try out! 209 | touch.setCal(hmin, hmax, vmin, vmax, HRES, VRES, xyswap);//, xflip, yflip); // Raw xmin, xmax, ymin, ymax, 320, 240, XYswap, xflip, yflip 210 | 211 | // Keep TFT and Touch rotations the same, try values 0 to 3 212 | // Start with the current orientation 213 | // Receiving any serial character moves on to next orientation test 214 | tft.setRotation(1); 215 | touch.setRotation(1); 216 | test(); 217 | 218 | tft.setRotation(2); 219 | touch.setRotation(2); 220 | test(); 221 | 222 | tft.setRotation(3); 223 | touch.setRotation(3); 224 | test(); 225 | 226 | tft.setRotation(0); 227 | touch.setRotation(0); 228 | test(); 229 | 230 | Serial.println(); 231 | } 232 | 233 | void test(void) 234 | { 235 | tft.fillScreen(TFT_BLACK); 236 | 237 | drawCross(30, 30, TFT_WHITE); 238 | 239 | drawCross(tft.width() - 30, tft.height() - 30, TFT_WHITE); 240 | 241 | int centre = tft.width()/2; // Get and work out x coord of screen centre 242 | 243 | String text; 244 | text+= "Screen rotation = "; 245 | text+= tft.getRotation(); 246 | char buffer[30]; 247 | text.toCharArray(buffer,30); 248 | 249 | tft.drawString(buffer, centre, 50, 2); 250 | 251 | tft.drawString("Touch anywhere on screen", centre, 70, 2); 252 | tft.drawString("to test settings", centre, 90, 2); 253 | 254 | tft.drawString("Send a character from the", centre, 120, 2); 255 | tft.drawString("IDE Serial Monitor to", centre, 140, 2); 256 | tft.drawString("continue!", centre, 160, 2); 257 | 258 | while (Serial.available()) Serial.read(); // Empty the serial buffer before we start 259 | 260 | while (!Serial.available()) { 261 | if (touch.Pressed()) // Note this function updates coordinates stored within library variables 262 | { 263 | /* Read the current X and Y axis as co-ordinates at the last touch time*/ 264 | // The values returned were captured when Pressed() was called! 265 | int X_Coord = touch.X(); 266 | int Y_Coord = touch.Y(); 267 | 268 | drawCross(X_Coord, Y_Coord, TFT_GREEN); 269 | 270 | //delay(20); 271 | tft.setCursor(centre, 0, 2); 272 | tft.print("X = ");tft.print(X_Coord);tft.print(" "); 273 | tft.setCursor(centre, 20, 2); 274 | tft.print("Y = ");tft.print(Y_Coord);tft.print(" "); 275 | 276 | } 277 | } 278 | } 279 | 280 | void drawPrompt(void) 281 | { 282 | tft.setTextColor(TFT_WHITE, TFT_BLACK); 283 | 284 | int centre = tft.width()/2; // Get and work out x coord of screen centre 285 | 286 | tft.drawString("CALIBRATION", centre, 20, 2); 287 | 288 | tft.drawString("Touch the red cross accurately", centre, 61, 2); 289 | tft.drawString("( using a cocktail stick works well! )", centre, 81, 2); 290 | } 291 | 292 | void drawCross(int x, int y, unsigned int color) 293 | { 294 | tft.drawLine(x - 5, y, x + 5, y, color); 295 | tft.drawLine(x, y - 5, x, y + 5, color); 296 | } 297 | 298 | bool getCoord() 299 | { 300 | bool Xwait = 1, Ywait = 1; 301 | int X_Temp1 = 9999, Y_Temp1 = 9999; 302 | int X_Temp2 = -1, Y_Temp2 = -1; 303 | X_Raw = -1; 304 | Y_Raw = -1; 305 | 306 | while (Xwait || Ywait) { 307 | if (touch.Pressed()) // Note this function updates coordinates stored within library variables 308 | { 309 | /* Read the current X and Y axis as co-ordinates at the last touch time*/ 310 | // The values returned were captured when Pressed() was called! 311 | X_Temp1 = touch.RawX(); 312 | Y_Temp1 = touch.RawY(); 313 | } 314 | delay(5); 315 | if (touch.Pressed()) // Note this function updates coordinates stored within library variables 316 | { 317 | /* Read the current X and Y axis as co-ordinates at the last touch time*/ 318 | // The values returned were captured when Pressed() was called! 319 | X_Temp2 = touch.RawX(); 320 | Y_Temp2 = touch.RawY(); 321 | } 322 | 323 | #define RAW_ERROR 10 324 | 325 | if ( (abs(X_Temp1 - X_Temp2) < RAW_ERROR) && Xwait ) { 326 | X_Raw = (X_Temp1 + X_Temp2) / 2; 327 | Xwait = 0; 328 | } 329 | if ( (abs(Y_Temp1 - Y_Temp2) < RAW_ERROR) && Ywait ) { 330 | Y_Raw = (Y_Temp1 + Y_Temp2) / 2; 331 | Ywait = 0; 332 | } 333 | } 334 | 335 | // Check if press is near middle third of screen 336 | if ((X_Raw > 1365) && (X_Raw < 2731) && (Y_Raw > 1365) && (Y_Raw < 2371)) return 0; 337 | 338 | // otherwise it is near edge for calibration points 339 | else return 1; 340 | } 341 | 342 | --------------------------------------------------------------------------------