Library to control a Graphics TFT connected to 4-wire SPI - revised for the Raio RA8875 Display Controller.
Dependents: FRDM_RA8875_mPaint RA8875_Demo RA8875_KeyPadDemo SignalGenerator ... more
Fork of SPI_TFT by
RA8875_Touch.cpp
00001 /// This file contains the RA8875 Touch panel methods. 00002 /// 00003 /// It combines both resistive and capacitive touch methods, and tries 00004 /// to make them nearly transparent alternates for each other. 00005 /// 00006 #include "RA8875.h" 00007 #include "RA8875_Touch_FT5206.h" 00008 #include "RA8875_Touch_GSL1680.h" 00009 00010 #define NOTOUCH_TIMEOUT_uS 100000 00011 #define TOUCH_TICKER_uS 1000 00012 00013 //#define DEBUG "TUCH" 00014 // ... 00015 // INFO("Stuff to show %d", var); // new-line is automatically appended 00016 // 00017 #if (defined(DEBUG) && !defined(TARGET_LPC11U24)) 00018 #define INFO(x, ...) std::printf("[INF %s %4d] " x "\r\n", DEBUG, __LINE__, ##__VA_ARGS__); 00019 #define WARN(x, ...) std::printf("[WRN %s %4d] " x "\r\n", DEBUG, __LINE__, ##__VA_ARGS__); 00020 #define ERR(x, ...) std::printf("[ERR %s %4d] " x "\r\n", DEBUG, __LINE__, ##__VA_ARGS__); 00021 static void HexDump(const char * title, const uint8_t * p, int count) 00022 { 00023 int i; 00024 char buf[100] = "0000: "; 00025 00026 if (*title) 00027 INFO("%s", title); 00028 for (i=0; i<count; ) { 00029 sprintf(buf + strlen(buf), "%02X ", *(p+i)); 00030 if ((++i & 0x0F) == 0x00) { 00031 INFO("%s", buf); 00032 if (i < count) 00033 sprintf(buf, "%04X: ", i); 00034 else 00035 buf[0] = '\0'; 00036 } 00037 } 00038 if (strlen(buf)) 00039 INFO("%s", buf); 00040 } 00041 #else 00042 #define INFO(x, ...) 00043 #define WARN(x, ...) 00044 #define ERR(x, ...) 00045 #define HexDump(a, b, c) 00046 #endif 00047 00048 00049 RetCode_t RA8875::TouchPanelInit(void) 00050 { 00051 RetCode_t r = noerror; 00052 00053 m_irq->disable_irq(); // ensure disabled while configuring it 00054 panelTouched = false; 00055 if (useTouchPanel == TP_GSL1680) { 00056 INFO("TouchPanelInit: TP_GSL1680"); 00057 r = GSL1680_Init(); 00058 } else if (useTouchPanel == TP_FT5206) { 00059 // Set to normal mode 00060 INFO("TouchPanelInit: TP_FT5206"); 00061 r = FT5206_Init(); 00062 } else { 00063 INFO("TouchPanelInit: TP_RES"); 00064 //RA8875_TPCR0: Set enable bit, default sample time, wakeup, and ADC clock 00065 WriteCommand(RA8875_TPCR0, TP_ENABLE | TP_ADC_SAMPLE_DEFAULT_CLKS | TP_ADC_CLKDIV_DEFAULT); 00066 // RA8875_TPCR1: Set auto/manual, Ref voltage, debounce, manual mode params 00067 WriteCommand(RA8875_TPCR1, TP_MODE_DEFAULT | TP_DEBOUNCE_DEFAULT); 00068 WriteCommand(RA8875_INTC1, ReadCommand(RA8875_INTC1) | RA8875_INT_TP); // reg RA8875_INTC1: Enable Touch Panel Interrupts (D2 = 1) 00069 WriteCommand(RA8875_INTC2, RA8875_INT_TP); // reg RA8875_INTC2: Clear any TP interrupt flag 00070 touchSample = 0; 00071 touchState = no_cal; 00072 #if 0 00073 #if (MBED_MAJOR_VERSION >= 5) || (MBED_LIBRARY_VERSION > 127) 00074 touchTicker.attach_us(callback(this, &RA8875::_TouchTicker), TOUCH_TICKER_uS); 00075 #else 00076 touchTicker.attach_us(this, &RA8875::_TouchTicker, TOUCH_TICKER_uS); 00077 #endif 00078 #endif 00079 timeSinceTouch.start(); 00080 timeSinceTouch.reset(); 00081 r = _internal_ts_cal(); 00082 } 00083 m_irq->enable_irq(); 00084 return r; 00085 } 00086 00087 00088 RetCode_t RA8875::TouchPanelInit(uint8_t bTpEnable, uint8_t bTpAutoManual, uint8_t bTpDebounce, uint8_t bTpManualMode, uint8_t bTpAdcClkDiv, uint8_t bTpAdcSampleTime) 00089 { 00090 if (useTouchPanel == TP_GSL1680) { 00091 INFO("TouchPanelInit: TP_GSL1680"); 00092 } else if (useTouchPanel == TP_FT5206) { 00093 INFO("TouchPanelInit: TP_FT5206"); 00094 TouchPanelInit(); 00095 } else { 00096 INFO("TouchPanelInit: TP_RES"); 00097 m_irq->disable_irq(); // ensure disabled while configuring it 00098 // Parameter bounds check 00099 if( \ 00100 !(bTpEnable == TP_ENABLE || bTpEnable == TP_ENABLE) || \ 00101 !(bTpAutoManual == TP_MODE_AUTO || bTpAutoManual == TP_MODE_MANUAL) || \ 00102 !(bTpDebounce == TP_DEBOUNCE_OFF || bTpDebounce == TP_DEBOUNCE_ON) || \ 00103 !(bTpManualMode <= TP_MANUAL_LATCH_Y) || \ 00104 !(bTpAdcClkDiv <= TP_ADC_CLKDIV_128) || \ 00105 !(bTpAdcSampleTime <= TP_ADC_SAMPLE_65536_CLKS) \ 00106 ) return bad_parameter; 00107 // Construct the config byte for RA8875_TPCR0 and write them 00108 WriteCommand(RA8875_TPCR0, bTpEnable | bTpAdcClkDiv | bTpAdcSampleTime); // Note: Wakeup is never enabled 00109 // Construct the config byte for RA8875_TPCR1 and write them 00110 WriteCommand(RA8875_TPCR1, bTpDebounce | bTpManualMode); // Note: Always uses internal Vref. 00111 // Set up the interrupt flag and enable bits 00112 WriteCommand(RA8875_INTC1, ReadCommand(RA8875_INTC1) | RA8875_INT_TP); // reg RA8875_INTC1: Enable Touch Panel Interrupts (D2 = 1) 00113 WriteCommand(RA8875_INTC2, RA8875_INT_TP); // reg RA8875_INTC2: Clear any TP interrupt flag 00114 touchSample = 0; 00115 touchState = no_cal; 00116 if (bTpEnable == TP_ENABLE) { 00117 //touchTicker.attach_us(callback(this, &RA8875::_TouchTicker), TOUCH_TICKER_uS); 00118 #if (MBED_MAJOR_VERSION >= 5) || (MBED_LIBRARY_VERSION > 127) 00119 touchTicker.attach_us(callback(this, &RA8875::_TouchTicker), TOUCH_TICKER_uS); 00120 #else 00121 touchTicker.attach_us(this, &RA8875::_TouchTicker, TOUCH_TICKER_uS); 00122 #endif 00123 00124 timeSinceTouch.start(); 00125 timeSinceTouch.reset(); 00126 } else { 00127 touchTicker.detach(); 00128 timeSinceTouch.stop(); 00129 } 00130 _internal_ts_cal(); 00131 m_irq->enable_irq(); 00132 } 00133 return noerror; 00134 } 00135 00136 00137 int RA8875::TouchChannels(void) 00138 { 00139 if (useTouchPanel == TP_GSL1680) { 00140 return GSL1680_TOUCH_POINTS; // based on TP_GSL1680 firmware 00141 } else if (useTouchPanel == TP_FT5206) { 00142 return FT5206_TOUCH_POINTS; // based on the FT5206 hardware 00143 } else if (useTouchPanel == TP_RES) { 00144 return RESISTIVE_TOUCH_POINTS; // based on the RA8875 resistive touch driver 00145 } else { 00146 return 0; // it isn't enabled, so there are none. 00147 } 00148 } 00149 00150 00151 // +----------------------------------------------------+ 00152 // | | 00153 // | 1 | 00154 // | | 00155 // | | 00156 // | 2 | 00157 // | | 00158 // | | 00159 // | 3 | 00160 // | | 00161 // +----------------------------------------------------+ 00162 00163 RetCode_t RA8875::TouchPanelCalibrate(tpMatrix_t * matrix) 00164 { 00165 return TouchPanelCalibrate(NULL, matrix); 00166 } 00167 00168 RetCode_t RA8875::TouchPanelCalibrate(const char * msg, tpMatrix_t * matrix, int maxwait_s) 00169 { 00170 point_t pTest[3]; 00171 point_t pSample[3]; 00172 int x,y; 00173 Timer timeout; // timeout guards for not-installed, stuck, user not present... 00174 00175 timeout.start(); 00176 while (TouchPanelA2DFiltered(&x, &y) && timeout.read() < maxwait_s) { 00177 wait_us(20000); 00178 if (idle_callback) { 00179 if (external_abort == (*idle_callback)(touchcal_wait, 0)) { 00180 return external_abort; 00181 } 00182 } 00183 } 00184 cls(); 00185 if (msg) { // User defines the message 00186 if (*msg) puts(msg); // If any 00187 } else { // Default message 00188 puts("Touch '+' to calibrate the touch panel"); 00189 } 00190 SetTextCursor(0,height()/2); 00191 pTest[0].x = 50; 00192 pTest[0].y = 50; 00193 pTest[1].x = width() - 50; 00194 pTest[1].y = height()/2; 00195 pTest[2].x = width()/2; 00196 pTest[2].y = height() - 50; 00197 00198 for (int i=0; i<3; i++) { 00199 foreground(Blue); 00200 printf(" (%3d,%3d) => ", pTest[i].x, pTest[i].y); 00201 fillcircle(pTest[i].x,pTest[i].y, 20, White); 00202 line(pTest[i].x-10, pTest[i].y, pTest[i].x+10, pTest[i].y, Blue); 00203 line(pTest[i].x, pTest[i].y-10, pTest[i].x, pTest[i].y+10, Blue); 00204 while (!TouchPanelA2DFiltered(&x, &y) && timeout.read() < maxwait_s) { 00205 wait_us(20000); 00206 if (idle_callback) { 00207 if (external_abort == (*idle_callback)(touchcal_wait, 0)) { 00208 return external_abort; 00209 } 00210 } 00211 } 00212 pSample[i].x = x; 00213 pSample[i].y = y; 00214 fillcircle(pTest[i].x,pTest[i].y, 20, Black); // Erase the target 00215 //line(pTest[i].x-10, pTest[i].y, pTest[i].x+10, pTest[i].y, Black); 00216 //line(pTest[i].x, pTest[i].y-10, pTest[i].x, pTest[i].y+10, Black); 00217 foreground(Blue); 00218 printf(" (%4d,%4d)\r\n", x,y); 00219 while (TouchPanelA2DFiltered(&x, &y) && timeout.read() < maxwait_s) { 00220 wait_us(20000); 00221 if (idle_callback) { 00222 if (external_abort == (*idle_callback)(touchcal_wait, 0)) { 00223 return external_abort; 00224 } 00225 } 00226 } 00227 for (int t=0; t<100; t++) { 00228 wait_us(20000); 00229 if (idle_callback) { 00230 if (external_abort == (*idle_callback)(touchcal_wait, 0)) { 00231 return external_abort; 00232 } 00233 } 00234 } 00235 } 00236 if (timeout.read() >= maxwait_s) 00237 return touch_cal_timeout; 00238 else 00239 return TouchPanelComputeCalibration(pTest, pSample, matrix); 00240 } 00241 00242 00243 /********************************************************************** 00244 * 00245 * Function: TouchPanelReadable() 00246 * 00247 */ 00248 TouchCode_t RA8875::TouchPanelReadable(point_t * TouchPoint) 00249 { 00250 TouchCode_t ts = no_touch; 00251 00252 if (useTouchPanel == TP_FT5206) { 00253 //INFO("TP_FT5206"); 00254 } else if (useTouchPanel == TP_GSL1680) { 00255 //INFO("TP_GSL1680"); 00256 } else if (useTouchPanel == TP_RES) { 00257 ReadResistive(); 00258 } 00259 // For Resistive touch, panelTouched is computed above. 00260 // For Cap Sense, panelTouched is set in another process 00261 if (panelTouched == true) { 00262 panelTouched = false; 00263 if (TouchPoint) { 00264 *TouchPoint = touchInfo[0].coordinates; 00265 ts = touchInfo[0].touchCode; 00266 INFO("ts %d", ts); 00267 #ifdef DEBUG 00268 static TouchCode_t lastTS = no_touch; 00269 if (lastTS != ts) 00270 INFO("Touch[0] %2d (%4d,%4d)", touchInfo[0].touchCode, 00271 touchInfo[0].coordinates.x, touchInfo[0].coordinates.y); 00272 lastTS = ts; 00273 #endif 00274 } else { 00275 ts = touchInfo[0].touchCode; 00276 INFO("ts %d", ts); 00277 } 00278 } 00279 return ts; 00280 } 00281 00282 uint8_t RA8875::TouchID(uint8_t channel) 00283 { 00284 if (channel >= TouchChannels()) 00285 channel = 0; 00286 return touchInfo[channel].touchID; 00287 } 00288 00289 TouchCode_t RA8875::TouchCode(uint8_t channel) 00290 { 00291 if (channel >= TouchChannels()) 00292 channel = 0; 00293 INFO("TouchCode[%d] = %d", channel, touchInfo[channel].touchCode); 00294 return touchInfo[channel].touchCode; 00295 } 00296 00297 point_t RA8875::TouchCoordinates(uint8_t channel) 00298 { 00299 if (channel >= TouchChannels()) 00300 channel = 0; 00301 return touchInfo[channel].coordinates; 00302 } 00303 00304 TouchCode_t RA8875::TouchPanelGet(point_t * TouchPoint) 00305 { 00306 TouchCode_t t = no_touch; 00307 00308 while (true) { 00309 t = TouchPanelReadable(TouchPoint); 00310 if (t != no_touch) 00311 break; 00312 if (idle_callback) { 00313 if (external_abort == (*idle_callback)(touch_wait, 0)) { 00314 return no_touch; 00315 } 00316 } 00317 } 00318 return t; 00319 } 00320 00321 // Below here are primarily "helper" functions. While many are accessible 00322 // to the user code, they usually don't need to be called. 00323 00324 RetCode_t RA8875::TouchPanelSetMatrix(tpMatrix_t * matrixPtr) 00325 { 00326 if (matrixPtr == NULL || matrixPtr->Divider == 0) 00327 return bad_parameter; 00328 memcpy(&tpMatrix, matrixPtr, sizeof(tpMatrix_t)); 00329 touchState = no_touch; 00330 return noerror; 00331 } 00332 00333 const tpMatrix_t * RA8875::TouchPanelGetMatrix() 00334 { 00335 return &tpMatrix; 00336 } 00337 00338 00339 static void InsertionSort(int * buf, int bufsize) 00340 { 00341 int i, j; 00342 int temp; 00343 00344 for(i = 1; i < bufsize; i++) { 00345 temp = buf[i]; 00346 j = i; 00347 while( j && (buf[j-1] > temp) ) { 00348 buf[j] = buf[j-1]; 00349 j = j-1; 00350 } 00351 buf[j] = temp; 00352 } // End of sort 00353 } 00354 00355 00356 void RA8875::_TouchTicker(void) 00357 { 00358 //INFO("_TouchTicker()"); 00359 if (timeSinceTouch.read_us() > NOTOUCH_TIMEOUT_uS) { 00360 touchSample = 0; 00361 if (touchState == held) { 00362 touchState = release; 00363 INFO("release %d", touchState); 00364 } else { 00365 INFO("!= held %d", touchState); 00366 touchState = no_touch; 00367 } 00368 timeSinceTouch.reset(); 00369 } 00370 } 00371 00372 00373 // Description: Given a valid set of calibration factors and a point 00374 // value reported by the touch screen, this function 00375 // calculates and returns the true (or closest to true) 00376 // display point below the spot where the touch screen 00377 // was touched. 00378 // 00379 // Argument(s): displayPtr (output) - Pointer to the calculated 00380 // (true) display point. 00381 // screenPtr (input) - Pointer to the reported touch 00382 // screen point. 00383 // matrixPtr (input) - Pointer to calibration factors 00384 // matrix previously calculated 00385 // from a call to 00386 // setCalibrationMatrix() 00387 // 00388 // The function simply solves for Xd and Yd by implementing the 00389 // computations required by the translation matrix. 00390 // 00391 // /- -\ // 00392 // /- -\ /- -\ | | // 00393 // | | | | | Xs | // 00394 // | Xd | | A B C | | | // 00395 // | | = | | * | Ys | // 00396 // | Yd | | D E F | | | // 00397 // | | | | | 1 | // 00398 // \- -/ \- -/ | | // 00399 // \- -/ // 00400 // 00401 // It must be kept brief to avoid consuming CPU cycles. 00402 // 00403 // Return: OK - the display point was correctly calculated 00404 // and its value is in the output argument. 00405 // NOT_OK - an error was detected and the function 00406 // failed to return a valid point. 00407 // 00408 // NOTE! NOTE! NOTE! 00409 // 00410 // setCalibrationMatrix() and getDisplayPoint() will do fine 00411 // for you as they are, provided that your digitizer 00412 // resolution does not exceed 10 bits (1024 values). Higher 00413 // resolutions may cause the integer operations to overflow 00414 // and return incorrect values. If you wish to use these 00415 // functions with digitizer resolutions of 12 bits (4096 00416 // values) you will either have to a) use 64-bit signed 00417 // integer variables and math, or b) judiciously modify the 00418 // operations to scale results by a factor of 2 or even 4. 00419 // 00420 void RA8875::ReadResistive() { 00421 TouchCode_t ts = no_touch; 00422 int a2dX = 0; 00423 int a2dY = 0; 00424 00425 touchInfo[0].touchID = 0; 00426 ts = TouchPanelA2DFiltered(&a2dX, &a2dY); 00427 if (ts != no_touch) { 00428 panelTouched = true; 00429 numberOfTouchPoints = 1; 00430 00431 if (tpMatrix.Divider != 0) { 00432 /* Operation order is important since we are doing integer */ 00433 /* math. Make sure you add all terms together before */ 00434 /* dividing, so that the remainder is not rounded off */ 00435 /* prematurely. */ 00436 touchInfo[0].coordinates = TranslateOrientation( 00437 ((tpMatrix.An * a2dX) + (tpMatrix.Bn * a2dY) + tpMatrix.Cn) / tpMatrix.Divider, 00438 ((tpMatrix.Dn * a2dX) + (tpMatrix.En * a2dY) + tpMatrix.Fn) / tpMatrix.Divider ); 00439 } else { 00440 ts = no_cal; 00441 } 00442 } else { 00443 numberOfTouchPoints = 0; 00444 } 00445 touchInfo[0].touchCode = ts; 00446 } 00447 00448 00449 TouchCode_t RA8875::TouchPanelA2DRaw(int *x, int *y) 00450 { 00451 INFO("A2Raw"); 00452 if( (ReadCommand(RA8875_INTC2) & RA8875_INT_TP) ) { // Test for TP Interrupt pending in register RA8875_INTC2 00453 INFO("Int pending"); 00454 timeSinceTouch.reset(); 00455 *y = ReadCommand(RA8875_TPYH) << 2 | ( (ReadCommand(RA8875_TPXYL) & 0xC) >> 2 ); // D[9:2] from reg RA8875_TPYH, D[1:0] from reg RA8875_TPXYL[3:2] 00456 *x = ReadCommand(RA8875_TPXH) << 2 | ( (ReadCommand(RA8875_TPXYL) & 0x3) ); // D[9:2] from reg RA8875_TPXH, D[1:0] from reg RA8875_TPXYL[1:0] 00457 INFO("(x,y) = (%d,%d)", *x, *y); 00458 WriteCommand(RA8875_INTC2, RA8875_INT_TP); // reg RA8875_INTC2: Clear that TP interrupt flag 00459 touchState = touch; 00460 } else if (ReadCommand(RA8875_TPXYL) & RA8875_TPXYL_ADET) { 00461 INFO("held"); 00462 touchState = held; 00463 } else { 00464 INFO("no touch"); 00465 touchState = no_touch; 00466 } 00467 return touchState; 00468 } 00469 00470 TouchCode_t RA8875::TouchPanelA2DFiltered(int *x, int *y) 00471 { 00472 static int xbuf[TPBUFSIZE], ybuf[TPBUFSIZE]; 00473 static int lastX, lastY; 00474 int i, j; 00475 TouchCode_t ret = touchState; 00476 00477 if ( (ReadCommand(RA8875_INTC2) & RA8875_INT_TP) ) { // Test for TP Interrupt pending in register RA8875_INTC2 00478 timeSinceTouch.reset(); 00479 // Get the next data samples 00480 ybuf[touchSample] = ReadCommand(RA8875_TPYH) << 2 | ( (ReadCommand(RA8875_TPXYL) & 0xC) >> 2 ); // D[9:2] from reg RA8875_TPYH, D[1:0] from reg RA8875_TPXYL[3:2] 00481 xbuf[touchSample] = ReadCommand(RA8875_TPXH) << 2 | ( (ReadCommand(RA8875_TPXYL) & 0x3) ); // D[9:2] from reg RA8875_TPXH, D[1:0] from reg RA8875_TPXYL[1:0] 00482 // Check for a complete set 00483 if (++touchSample == TPBUFSIZE) { 00484 // Buffers are full, so process them using Finn's method described in Analog Dialogue No. 44, Feb 2010 00485 // This requires sorting the samples in order of size, then discarding the top 25% and 00486 // bottom 25% as noise spikes. Finally, the middle 50% of the values are averaged to 00487 // reduce Gaussian noise. 00488 InsertionSort(ybuf, TPBUFSIZE); 00489 InsertionSort(xbuf, TPBUFSIZE); 00490 // Average the middle half of the Y values and report them 00491 j = 0; 00492 for (i = (TPBUFSIZE/4) - 1; i < TPBUFSIZE - TPBUFSIZE/4; i++ ) { 00493 j += ybuf[i]; 00494 } 00495 *y = lastY = j * (float)2/TPBUFSIZE; // This is the average 00496 // Average the middle half of the X values and report them 00497 j = 0; 00498 for(i = (TPBUFSIZE/4) - 1; i < TPBUFSIZE - TPBUFSIZE/4; i++ ) { 00499 j += xbuf[i]; 00500 } 00501 *x = lastX = j * (float)2/TPBUFSIZE; // This is the average 00502 // Tidy up and return 00503 if (touchState == touch || touchState == held) { 00504 touchState = held; 00505 //INFO("held"); 00506 } else { 00507 touchState = touch; 00508 //INFO("touch"); 00509 } 00510 ret = touchState; 00511 touchSample = 0; // Ready to start on the next set of data samples 00512 } else { 00513 // Buffer not yet full, so do not return any results yet 00514 if (touchState == touch || touchState == held) { 00515 *x = lastX; 00516 *y = lastY; 00517 #ifdef DEBUG 00518 { 00519 static TouchCode_t lastTC = no_touch; 00520 if (lastTC != touchState) 00521 //INFO("held"); 00522 lastTC = touchState; 00523 } 00524 #endif 00525 ret = touchState = held; 00526 } else { 00527 INFO("else %d, %d", touchState, touchSample); 00528 } 00529 } 00530 WriteCommand(RA8875_INTC2, RA8875_INT_TP); // reg RA8875_INTC2: Clear that TP interrupt flag 00531 } else if (0 == (ReadCommand(RA8875_TPXYL) & RA8875_TPXYL_ADET)) { 00532 INFO("held"); 00533 *x = lastX; 00534 *y = lastY; 00535 ret = touchState = held; 00536 } else if (timeSinceTouch.read_ms() < 20) { 00537 *x = lastX; 00538 *y = lastY; 00539 //ret = touchState; 00540 } else { 00541 //INFO("touchState %d", touchState); 00542 //touchSample = 0; 00543 *x = lastX; 00544 *y = lastY; 00545 if (touchState == no_touch || touchState == release) { 00546 ret = touchState = no_touch; 00547 } else { 00548 INFO("release"); 00549 touchSample = 0; 00550 touchState = no_touch; 00551 ret = release; 00552 } 00553 #if 0 00554 if (touchState == touch || touchState == held) { 00555 *x = lastX; 00556 *y = lastY; 00557 ret = touchState = held; 00558 INFO("held"); 00559 } else if (touchState == release) { 00560 *x = lastX; 00561 *y = lastY; 00562 ret = release; 00563 touchState = no_touch; 00564 INFO("release"); 00565 } 00566 #endif 00567 } 00568 return ret; 00569 } 00570 00571 /// The following section is derived from Carlos E. Vidales. 00572 /// 00573 /// @copyright © 2001, Carlos E. Vidales. All rights reserved. 00574 /// 00575 /// This sample program was written and put in the public domain 00576 /// by Carlos E. Vidales. The program is provided "as is" 00577 /// without warranty of any kind, either expressed or implied. 00578 /// If you choose to use the program within your own products 00579 /// you do so at your own risk, and assume the responsibility 00580 /// for servicing, repairing or correcting the program should 00581 /// it prove defective in any manner. 00582 /// You may copy and distribute the program's source code in any 00583 /// medium, provided that you also include in each copy an 00584 /// appropriate copyright notice and disclaimer of warranty. 00585 /// You may also modify this program and distribute copies of 00586 /// it provided that you include prominent notices stating 00587 /// that you changed the file(s) and the date of any change, 00588 /// and that you do not charge any royalties or licenses for 00589 /// its use. 00590 /// 00591 /// This file contains functions that implement calculations 00592 /// necessary to obtain calibration factors for a touch screen 00593 /// that suffers from multiple distortion effects: namely, 00594 /// translation, scaling and rotation. 00595 /// 00596 /// The following set of equations represent a valid display 00597 /// point given a corresponding set of touch screen points: 00598 /// 00599 /// <pre> 00600 /// /- -\ // 00601 /// /- -\ /- -\ | | // 00602 /// | | | | | Xs | // 00603 /// | Xd | | A B C | | | // 00604 /// | | = | | * | Ys | // 00605 /// | Yd | | D E F | | | // 00606 /// | | | | | 1 | // 00607 /// \- -/ \- -/ | | // 00608 /// \- -/ // 00609 /// where: 00610 /// (Xd,Yd) represents the desired display point 00611 /// coordinates, 00612 /// (Xs,Ys) represents the available touch screen 00613 /// coordinates, and the matrix 00614 /// /- -\ represents the factors used to translate 00615 /// |A,B,C| the available touch screen point values 00616 /// |D,E,F| into the corresponding display 00617 /// \- -/ coordinates. 00618 /// 00619 /// Note that for practical considerations, the utilities 00620 /// within this file do not use the matrix coefficients as 00621 /// defined above, but instead use the following 00622 /// equivalents, since floating point math is not used: 00623 /// A = An/Divider 00624 /// B = Bn/Divider 00625 /// C = Cn/Divider 00626 /// D = Dn/Divider 00627 /// E = En/Divider 00628 /// F = Fn/Divider 00629 /// The functions provided within this file are: 00630 /// setCalibrationMatrix() - calculates the set of factors 00631 /// in the above equation, given 00632 /// three sets of test points. 00633 /// getDisplayPoint() - returns the actual display 00634 /// coordinates, given a set of 00635 /// touch screen coordinates. 00636 /// translateRawScreenCoordinates() - helper function to transform 00637 /// raw screen points into values 00638 /// scaled to the desired display 00639 /// resolution. 00640 /// 00641 /// 00642 /// Function: setCalibrationMatrix() 00643 /// 00644 /// Description: Calling this function with valid input data 00645 /// in the display and screen input arguments 00646 /// causes the calibration factors between the 00647 /// screen and display points to be calculated, 00648 /// and the output argument - matrixPtr - to be 00649 /// populated. 00650 /// 00651 /// This function needs to be called only when new 00652 /// calibration factors are desired. 00653 /// 00654 /// 00655 /// Argument(s): displayPtr (input) - Pointer to an array of three 00656 /// sample, reference points. 00657 /// screenPtr (input) - Pointer to the array of touch 00658 /// screen points corresponding 00659 /// to the reference display points. 00660 /// matrixPtr (output) - Pointer to the calibration 00661 /// matrix computed for the set 00662 /// of points being provided. 00663 /// 00664 /// 00665 /// From the article text, recall that the matrix coefficients are 00666 /// resolved to be the following: 00667 /// 00668 /// 00669 /// Divider = (Xs0 - Xs2)*(Ys1 - Ys2) - (Xs1 - Xs2)*(Ys0 - Ys2) 00670 /// 00671 /// 00672 /// 00673 /// (Xd0 - Xd2)*(Ys1 - Ys2) - (Xd1 - Xd2)*(Ys0 - Ys2) 00674 /// A = --------------------------------------------------- 00675 /// Divider 00676 /// 00677 /// 00678 /// (Xs0 - Xs2)*(Xd1 - Xd2) - (Xd0 - Xd2)*(Xs1 - Xs2) 00679 /// B = --------------------------------------------------- 00680 /// Divider 00681 /// 00682 /// 00683 /// Ys0*(Xs2*Xd1 - Xs1*Xd2) + 00684 /// Ys1*(Xs0*Xd2 - Xs2*Xd0) + 00685 /// Ys2*(Xs1*Xd0 - Xs0*Xd1) 00686 /// C = --------------------------------------------------- 00687 /// Divider 00688 /// 00689 /// 00690 /// (Yd0 - Yd2)*(Ys1 - Ys2) - (Yd1 - Yd2)*(Ys0 - Ys2) 00691 /// D = --------------------------------------------------- 00692 /// Divider 00693 /// 00694 /// 00695 /// (Xs0 - Xs2)*(Yd1 - Yd2) - (Yd0 - Yd2)*(Xs1 - Xs2) 00696 /// E = --------------------------------------------------- 00697 /// Divider 00698 /// 00699 /// 00700 /// Ys0*(Xs2*Yd1 - Xs1*Yd2) + 00701 /// Ys1*(Xs0*Yd2 - Xs2*Yd0) + 00702 /// Ys2*(Xs1*Yd0 - Xs0*Yd1) 00703 /// F = --------------------------------------------------- 00704 /// Divider 00705 /// 00706 /// 00707 /// Return: OK - the calibration matrix was correctly 00708 /// calculated and its value is in the 00709 /// output argument. 00710 /// NOT_OK - an error was detected and the 00711 /// function failed to return a valid 00712 /// set of matrix values. 00713 /// The only time this sample code returns 00714 /// NOT_OK is when Divider == 0 00715 /// 00716 /// 00717 /// 00718 /// NOTE! NOTE! NOTE! 00719 /// 00720 /// setCalibrationMatrix() and getDisplayPoint() will do fine 00721 /// for you as they are, provided that your digitizer 00722 /// resolution does not exceed 10 bits (1024 values). Higher 00723 /// resolutions may cause the integer operations to overflow 00724 /// and return incorrect values. If you wish to use these 00725 /// functions with digitizer resolutions of 12 bits (4096 00726 /// values) you will either have to a) use 64-bit signed 00727 /// integer variables and math, or b) judiciously modify the 00728 /// operations to scale results by a factor of 2 or even 4. 00729 /// 00730 /// </pre> 00731 /// 00732 RetCode_t RA8875::TouchPanelComputeCalibration(point_t * displayPtr, point_t * screenPtr, tpMatrix_t * matrixPtr) 00733 { 00734 RetCode_t retValue = noerror; 00735 00736 tpMatrix.Divider = ((screenPtr[0].x - screenPtr[2].x) * (screenPtr[1].y - screenPtr[2].y)) - 00737 ((screenPtr[1].x - screenPtr[2].x) * (screenPtr[0].y - screenPtr[2].y)) ; 00738 00739 if( tpMatrix.Divider == 0 ) { 00740 retValue = bad_parameter; 00741 } else { 00742 tpMatrix.An = ((displayPtr[0].x - displayPtr[2].x) * (screenPtr[1].y - screenPtr[2].y)) - 00743 ((displayPtr[1].x - displayPtr[2].x) * (screenPtr[0].y - screenPtr[2].y)) ; 00744 00745 tpMatrix.Bn = ((screenPtr[0].x - screenPtr[2].x) * (displayPtr[1].x - displayPtr[2].x)) - 00746 ((displayPtr[0].x - displayPtr[2].x) * (screenPtr[1].x - screenPtr[2].x)) ; 00747 00748 tpMatrix.Cn = (screenPtr[2].x * displayPtr[1].x - screenPtr[1].x * displayPtr[2].x) * screenPtr[0].y + 00749 (screenPtr[0].x * displayPtr[2].x - screenPtr[2].x * displayPtr[0].x) * screenPtr[1].y + 00750 (screenPtr[1].x * displayPtr[0].x - screenPtr[0].x * displayPtr[1].x) * screenPtr[2].y ; 00751 00752 tpMatrix.Dn = ((displayPtr[0].y - displayPtr[2].y) * (screenPtr[1].y - screenPtr[2].y)) - 00753 ((displayPtr[1].y - displayPtr[2].y) * (screenPtr[0].y - screenPtr[2].y)) ; 00754 00755 tpMatrix.En = ((screenPtr[0].x - screenPtr[2].x) * (displayPtr[1].y - displayPtr[2].y)) - 00756 ((displayPtr[0].y - displayPtr[2].y) * (screenPtr[1].x - screenPtr[2].x)) ; 00757 00758 tpMatrix.Fn = (screenPtr[2].x * displayPtr[1].y - screenPtr[1].x * displayPtr[2].y) * screenPtr[0].y + 00759 (screenPtr[0].x * displayPtr[2].y - screenPtr[2].x * displayPtr[0].y) * screenPtr[1].y + 00760 (screenPtr[1].x * displayPtr[0].y - screenPtr[0].x * displayPtr[1].y) * screenPtr[2].y ; 00761 touchState = no_touch; 00762 if (matrixPtr) 00763 memcpy(matrixPtr, &tpMatrix, sizeof(tpMatrix_t)); 00764 } 00765 return( retValue ) ; 00766 } 00767 00768 void RA8875::ResTouchPanelCfg(const char * _tpFQFN, const char * _tpCalMessage) 00769 { 00770 tpFQFN = _tpFQFN; 00771 tpCalMessage = _tpCalMessage; 00772 } 00773 00774 00775 RetCode_t RA8875::_internal_ts_cal() 00776 { 00777 FILE * fh; 00778 tpMatrix_t matrix; 00779 RetCode_t r = noerror; 00780 00781 if (tpFQFN) { 00782 fh = fopen(tpFQFN, "rb"); 00783 if (fh) { 00784 fread(&matrix, sizeof(tpMatrix_t), 1, fh); 00785 fclose(fh); 00786 TouchPanelSetMatrix(&matrix); 00787 } else { 00788 r = TouchPanelCalibrate(tpCalMessage, &matrix); 00789 if (r == noerror) { 00790 fh = fopen(tpFQFN, "wb"); 00791 if (fh) { 00792 fwrite(&matrix, sizeof(tpMatrix_t), 1, fh); 00793 fclose(fh); 00794 INFO(" tp cal written to '%s'.", tpFQFN); 00795 } else { 00796 ERR(" couldn't open tpcal file '%s'.", tpFQFN); 00797 r = file_not_found; 00798 } 00799 } else { 00800 ERR("error return: %d", r); 00801 } 00802 HexDump("TPCal", (const uint8_t *)&matrix, sizeof(tpMatrix_t)); 00803 cls(); 00804 } 00805 } 00806 return r; 00807 } 00808 00809 00810 00811 ////////////////// Capacitive Touch Panel 00812 00813 uint8_t RA8875::FT5206_ReadRegU8(uint8_t reg) { 00814 char val; 00815 00816 m_i2c->write(m_addr, (const char *)®, 1); 00817 m_i2c->read(m_addr, &val, 1); 00818 //INFO("ReadReg %02X, Val %02X", reg, val); 00819 return (uint8_t)val; 00820 } 00821 00822 // Interrupt for touch detection 00823 void RA8875::TouchPanelISR(void) 00824 { 00825 if (useTouchPanel == TP_FT5206) { 00826 FT5206_TouchPositions(); // Picks up the final release 00827 panelTouched = true; 00828 timeSinceTouch.reset(); 00829 } else if (useTouchPanel == TP_GSL1680) { 00830 GSL1680_TouchPositions(); 00831 panelTouched = true; 00832 timeSinceTouch.reset(); 00833 } 00834 } 00835 00836 // #### end of touch panel code additions
Generated on Tue Jul 12 2022 17:28:36 by 1.7.2