acidportal- 😈 Worlds smallest Evil Portal on a LilyGo T-QT |
git clone git://git.acid.vegas/acidportal.git |
Log | Files | Refs | Archive | README | LICENSE |
Touch.cpp (13298B)
1 // The following touch screen support code by maxpautsch was merged 1/10/17 2 // https://github.com/maxpautsch 3 4 // Define TOUCH_CS is the user setup file to enable this code 5 6 // A demo is provided in examples Generic folder 7 8 // Additions by Bodmer to double sample, use Z value to improve detection reliability 9 // and to correct rotation handling 10 11 // See license in root directory. 12 13 // Define a default pressure threshold 14 #ifndef Z_THRESHOLD 15 #define Z_THRESHOLD 350 // Touch pressure threshold for validating touches 16 #endif 17 18 /*************************************************************************************** 19 ** Function name: begin_touch_read_write - was spi_begin_touch 20 ** Description: Start transaction and select touch controller 21 ***************************************************************************************/ 22 // The touch controller has a low SPI clock rate 23 inline void TFT_eSPI::begin_touch_read_write(void){ 24 DMA_BUSY_CHECK; 25 CS_H; // Just in case it has been left low 26 #if defined (SPI_HAS_TRANSACTION) && defined (SUPPORT_TRANSACTIONS) 27 if (locked) {locked = false; spi.beginTransaction(SPISettings(SPI_TOUCH_FREQUENCY, MSBFIRST, SPI_MODE0));} 28 #else 29 spi.setFrequency(SPI_TOUCH_FREQUENCY); 30 #endif 31 SET_BUS_READ_MODE; 32 T_CS_L; 33 } 34 35 /*************************************************************************************** 36 ** Function name: end_touch_read_write - was spi_end_touch 37 ** Description: End transaction and deselect touch controller 38 ***************************************************************************************/ 39 inline void TFT_eSPI::end_touch_read_write(void){ 40 T_CS_H; 41 #if defined (SPI_HAS_TRANSACTION) && defined (SUPPORT_TRANSACTIONS) 42 if(!inTransaction) {if (!locked) {locked = true; spi.endTransaction();}} 43 #else 44 spi.setFrequency(SPI_FREQUENCY); 45 #endif 46 //SET_BUS_WRITE_MODE; 47 } 48 49 /*************************************************************************************** 50 ** Function name: Legacy - deprecated 51 ** Description: Start/end transaction 52 ***************************************************************************************/ 53 void TFT_eSPI::spi_begin_touch() {begin_touch_read_write();} 54 void TFT_eSPI::spi_end_touch() { end_touch_read_write();} 55 56 /*************************************************************************************** 57 ** Function name: getTouchRaw 58 ** Description: read raw touch position. Always returns true. 59 ***************************************************************************************/ 60 uint8_t TFT_eSPI::getTouchRaw(uint16_t *x, uint16_t *y){ 61 uint16_t tmp; 62 63 begin_touch_read_write(); 64 65 // Start YP sample request for x position, read 4 times and keep last sample 66 spi.transfer(0xd0); // Start new YP conversion 67 spi.transfer(0); // Read first 8 bits 68 spi.transfer(0xd0); // Read last 8 bits and start new YP conversion 69 spi.transfer(0); // Read first 8 bits 70 spi.transfer(0xd0); // Read last 8 bits and start new YP conversion 71 spi.transfer(0); // Read first 8 bits 72 spi.transfer(0xd0); // Read last 8 bits and start new YP conversion 73 74 tmp = spi.transfer(0); // Read first 8 bits 75 tmp = tmp <<5; 76 tmp |= 0x1f & (spi.transfer(0x90)>>3); // Read last 8 bits and start new XP conversion 77 78 *x = tmp; 79 80 // Start XP sample request for y position, read 4 times and keep last sample 81 spi.transfer(0); // Read first 8 bits 82 spi.transfer(0x90); // Read last 8 bits and start new XP conversion 83 spi.transfer(0); // Read first 8 bits 84 spi.transfer(0x90); // Read last 8 bits and start new XP conversion 85 spi.transfer(0); // Read first 8 bits 86 spi.transfer(0x90); // Read last 8 bits and start new XP conversion 87 88 tmp = spi.transfer(0); // Read first 8 bits 89 tmp = tmp <<5; 90 tmp |= 0x1f & (spi.transfer(0)>>3); // Read last 8 bits 91 92 *y = tmp; 93 94 end_touch_read_write(); 95 96 return true; 97 } 98 99 /*************************************************************************************** 100 ** Function name: getTouchRawZ 101 ** Description: read raw pressure on touchpad and return Z value. 102 ***************************************************************************************/ 103 uint16_t TFT_eSPI::getTouchRawZ(void){ 104 105 begin_touch_read_write(); 106 107 // Z sample request 108 int16_t tz = 0xFFF; 109 spi.transfer(0xb0); // Start new Z1 conversion 110 tz += spi.transfer16(0xc0) >> 3; // Read Z1 and start Z2 conversion 111 tz -= spi.transfer16(0x00) >> 3; // Read Z2 112 113 end_touch_read_write(); 114 115 if (tz == 4095) tz = 0; 116 117 return (uint16_t)tz; 118 } 119 120 /*************************************************************************************** 121 ** Function name: validTouch 122 ** Description: read validated position. Return false if not pressed. 123 ***************************************************************************************/ 124 #define _RAWERR 20 // Deadband error allowed in successive position samples 125 uint8_t TFT_eSPI::validTouch(uint16_t *x, uint16_t *y, uint16_t threshold){ 126 uint16_t x_tmp, y_tmp, x_tmp2, y_tmp2; 127 128 // Wait until pressure stops increasing to debounce pressure 129 uint16_t z1 = 1; 130 uint16_t z2 = 0; 131 while (z1 > z2) 132 { 133 z2 = z1; 134 z1 = getTouchRawZ(); 135 delay(1); 136 } 137 138 // Serial.print("Z = ");Serial.println(z1); 139 140 if (z1 <= threshold) return false; 141 142 getTouchRaw(&x_tmp,&y_tmp); 143 144 // Serial.print("Sample 1 x,y = "); Serial.print(x_tmp);Serial.print(",");Serial.print(y_tmp); 145 // Serial.print(", Z = ");Serial.println(z1); 146 147 delay(1); // Small delay to the next sample 148 if (getTouchRawZ() <= threshold) return false; 149 150 delay(2); // Small delay to the next sample 151 getTouchRaw(&x_tmp2,&y_tmp2); 152 153 // Serial.print("Sample 2 x,y = "); Serial.print(x_tmp2);Serial.print(",");Serial.println(y_tmp2); 154 // Serial.print("Sample difference = ");Serial.print(abs(x_tmp - x_tmp2));Serial.print(",");Serial.println(abs(y_tmp - y_tmp2)); 155 156 if (abs(x_tmp - x_tmp2) > _RAWERR) return false; 157 if (abs(y_tmp - y_tmp2) > _RAWERR) return false; 158 159 *x = x_tmp; 160 *y = y_tmp; 161 162 return true; 163 } 164 165 /*************************************************************************************** 166 ** Function name: getTouch 167 ** Description: read callibrated position. Return false if not pressed. 168 ***************************************************************************************/ 169 uint8_t TFT_eSPI::getTouch(uint16_t *x, uint16_t *y, uint16_t threshold){ 170 uint16_t x_tmp, y_tmp; 171 172 if (threshold<20) threshold = 20; 173 if (_pressTime > millis()) threshold=20; 174 175 uint8_t n = 5; 176 uint8_t valid = 0; 177 while (n--) 178 { 179 if (validTouch(&x_tmp, &y_tmp, threshold)) valid++;; 180 } 181 182 if (valid<1) { _pressTime = 0; return false; } 183 184 _pressTime = millis() + 50; 185 186 convertRawXY(&x_tmp, &y_tmp); 187 188 if (x_tmp >= _width || y_tmp >= _height) return false; 189 190 _pressX = x_tmp; 191 _pressY = y_tmp; 192 *x = _pressX; 193 *y = _pressY; 194 return valid; 195 } 196 197 /*************************************************************************************** 198 ** Function name: convertRawXY 199 ** Description: convert raw touch x,y values to screen coordinates 200 ***************************************************************************************/ 201 void TFT_eSPI::convertRawXY(uint16_t *x, uint16_t *y) 202 { 203 uint16_t x_tmp = *x, y_tmp = *y, xx, yy; 204 205 if(!touchCalibration_rotate){ 206 xx=(x_tmp-touchCalibration_x0)*_width/touchCalibration_x1; 207 yy=(y_tmp-touchCalibration_y0)*_height/touchCalibration_y1; 208 if(touchCalibration_invert_x) 209 xx = _width - xx; 210 if(touchCalibration_invert_y) 211 yy = _height - yy; 212 } else { 213 xx=(y_tmp-touchCalibration_x0)*_width/touchCalibration_x1; 214 yy=(x_tmp-touchCalibration_y0)*_height/touchCalibration_y1; 215 if(touchCalibration_invert_x) 216 xx = _width - xx; 217 if(touchCalibration_invert_y) 218 yy = _height - yy; 219 } 220 *x = xx; 221 *y = yy; 222 } 223 224 /*************************************************************************************** 225 ** Function name: calibrateTouch 226 ** Description: generates calibration parameters for touchscreen. 227 ***************************************************************************************/ 228 void TFT_eSPI::calibrateTouch(uint16_t *parameters, uint32_t color_fg, uint32_t color_bg, uint8_t size){ 229 int16_t values[] = {0,0,0,0,0,0,0,0}; 230 uint16_t x_tmp, y_tmp; 231 232 233 234 for(uint8_t i = 0; i<4; i++){ 235 fillRect(0, 0, size+1, size+1, color_bg); 236 fillRect(0, _height-size-1, size+1, size+1, color_bg); 237 fillRect(_width-size-1, 0, size+1, size+1, color_bg); 238 fillRect(_width-size-1, _height-size-1, size+1, size+1, color_bg); 239 240 if (i == 5) break; // used to clear the arrows 241 242 switch (i) { 243 case 0: // up left 244 drawLine(0, 0, 0, size, color_fg); 245 drawLine(0, 0, size, 0, color_fg); 246 drawLine(0, 0, size , size, color_fg); 247 break; 248 case 1: // bot left 249 drawLine(0, _height-size-1, 0, _height-1, color_fg); 250 drawLine(0, _height-1, size, _height-1, color_fg); 251 drawLine(size, _height-size-1, 0, _height-1 , color_fg); 252 break; 253 case 2: // up right 254 drawLine(_width-size-1, 0, _width-1, 0, color_fg); 255 drawLine(_width-size-1, size, _width-1, 0, color_fg); 256 drawLine(_width-1, size, _width-1, 0, color_fg); 257 break; 258 case 3: // bot right 259 drawLine(_width-size-1, _height-size-1, _width-1, _height-1, color_fg); 260 drawLine(_width-1, _height-1-size, _width-1, _height-1, color_fg); 261 drawLine(_width-1-size, _height-1, _width-1, _height-1, color_fg); 262 break; 263 } 264 265 // user has to get the chance to release 266 if(i>0) delay(1000); 267 268 for(uint8_t j= 0; j<8; j++){ 269 // Use a lower detect threshold as corners tend to be less sensitive 270 while(!validTouch(&x_tmp, &y_tmp, Z_THRESHOLD/2)); 271 values[i*2 ] += x_tmp; 272 values[i*2+1] += y_tmp; 273 } 274 values[i*2 ] /= 8; 275 values[i*2+1] /= 8; 276 } 277 278 279 // from case 0 to case 1, the y value changed. 280 // If the measured delta of the touch x axis is bigger than the delta of the y axis, the touch and TFT axes are switched. 281 touchCalibration_rotate = false; 282 if(abs(values[0]-values[2]) > abs(values[1]-values[3])){ 283 touchCalibration_rotate = true; 284 touchCalibration_x0 = (values[1] + values[3])/2; // calc min x 285 touchCalibration_x1 = (values[5] + values[7])/2; // calc max x 286 touchCalibration_y0 = (values[0] + values[4])/2; // calc min y 287 touchCalibration_y1 = (values[2] + values[6])/2; // calc max y 288 } else { 289 touchCalibration_x0 = (values[0] + values[2])/2; // calc min x 290 touchCalibration_x1 = (values[4] + values[6])/2; // calc max x 291 touchCalibration_y0 = (values[1] + values[5])/2; // calc min y 292 touchCalibration_y1 = (values[3] + values[7])/2; // calc max y 293 } 294 295 // in addition, the touch screen axis could be in the opposite direction of the TFT axis 296 touchCalibration_invert_x = false; 297 if(touchCalibration_x0 > touchCalibration_x1){ 298 values[0]=touchCalibration_x0; 299 touchCalibration_x0 = touchCalibration_x1; 300 touchCalibration_x1 = values[0]; 301 touchCalibration_invert_x = true; 302 } 303 touchCalibration_invert_y = false; 304 if(touchCalibration_y0 > touchCalibration_y1){ 305 values[0]=touchCalibration_y0; 306 touchCalibration_y0 = touchCalibration_y1; 307 touchCalibration_y1 = values[0]; 308 touchCalibration_invert_y = true; 309 } 310 311 // pre calculate 312 touchCalibration_x1 -= touchCalibration_x0; 313 touchCalibration_y1 -= touchCalibration_y0; 314 315 if(touchCalibration_x0 == 0) touchCalibration_x0 = 1; 316 if(touchCalibration_x1 == 0) touchCalibration_x1 = 1; 317 if(touchCalibration_y0 == 0) touchCalibration_y0 = 1; 318 if(touchCalibration_y1 == 0) touchCalibration_y1 = 1; 319 320 // export parameters, if pointer valid 321 if(parameters != NULL){ 322 parameters[0] = touchCalibration_x0; 323 parameters[1] = touchCalibration_x1; 324 parameters[2] = touchCalibration_y0; 325 parameters[3] = touchCalibration_y1; 326 parameters[4] = touchCalibration_rotate | (touchCalibration_invert_x <<1) | (touchCalibration_invert_y <<2); 327 } 328 } 329 330 331 /*************************************************************************************** 332 ** Function name: setTouch 333 ** Description: imports calibration parameters for touchscreen. 334 ***************************************************************************************/ 335 void TFT_eSPI::setTouch(uint16_t *parameters){ 336 touchCalibration_x0 = parameters[0]; 337 touchCalibration_x1 = parameters[1]; 338 touchCalibration_y0 = parameters[2]; 339 touchCalibration_y1 = parameters[3]; 340 341 if(touchCalibration_x0 == 0) touchCalibration_x0 = 1; 342 if(touchCalibration_x1 == 0) touchCalibration_x1 = 1; 343 if(touchCalibration_y0 == 0) touchCalibration_y0 = 1; 344 if(touchCalibration_y1 == 0) touchCalibration_y1 = 1; 345 346 touchCalibration_rotate = parameters[4] & 0x01; 347 touchCalibration_invert_x = parameters[4] & 0x02; 348 touchCalibration_invert_y = parameters[4] & 0x04; 349 }