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