KSM edits to RA8875
Embed:
(wiki syntax)
Show/hide line numbers
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 INFO("Raw Values: (%d, %d)", a2dX, a2dY); 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 INFO("Calced Values: (%d, %d)", touchInfo[0].coordinates.x, touchInfo[0].coordinates.y); 00325 } else { 00326 INFO("NO CAL!!"); 00327 ts = no_cal; 00328 } 00329 } else { 00330 numberOfTouchPoints = 0; 00331 } 00332 touchInfo[0].touchCode = ts; 00333 } 00334 // For Resistive touch, panelTouched is computed above. 00335 // For Cap Sense, panelTouched is set in another process 00336 if (panelTouched == true) { 00337 panelTouched = false; 00338 if (TouchPoint) { 00339 *TouchPoint = touchInfo[0].coordinates; 00340 ts = touchInfo[0].touchCode; 00341 INFO("Touch[0] %2d (%4d,%4d)", touchInfo[0].touchCode, 00342 touchInfo[0].coordinates.x, touchInfo[0].coordinates.y); 00343 } else { 00344 ts = touch; 00345 } 00346 } 00347 return ts; 00348 } 00349 00350 uint8_t RA8875::TouchID(uint8_t channel) 00351 { 00352 if (channel >= TouchChannels()) 00353 channel = 0; 00354 return touchInfo[channel].touchID; 00355 } 00356 00357 TouchCode_t RA8875::TouchCode(uint8_t channel) 00358 { 00359 if (channel >= TouchChannels()) 00360 channel = 0; 00361 return touchInfo[channel].touchCode; 00362 } 00363 00364 point_t RA8875::TouchCoordinates(uint8_t channel) 00365 { 00366 if (channel >= TouchChannels()) 00367 channel = 0; 00368 return touchInfo[channel].coordinates; 00369 } 00370 00371 TouchCode_t RA8875::TouchPanelGet(point_t * TouchPoint) 00372 { 00373 TouchCode_t t = no_touch; 00374 00375 while (true) { 00376 t = TouchPanelReadable(TouchPoint); 00377 if (t != no_touch) 00378 break; 00379 if (idle_callback) { 00380 if (external_abort == (*idle_callback)(touch_wait, 0)) { 00381 return no_touch; 00382 } 00383 } 00384 } 00385 return t; 00386 } 00387 00388 // Below here are primarily "helper" functions. While many are accessible 00389 // to the user code, they usually don't need to be called. 00390 00391 RetCode_t RA8875::TouchPanelSetMatrix(tpMatrix_t * matrixPtr) 00392 { 00393 if (matrixPtr == NULL || matrixPtr->Divider == 0) 00394 return bad_parameter; 00395 memcpy(&tpMatrix, matrixPtr, sizeof(tpMatrix_t)); 00396 touchState = no_touch; 00397 return noerror; 00398 } 00399 00400 const tpMatrix_t * RA8875::TouchPanelGetMatrix() 00401 { 00402 return &tpMatrix; 00403 } 00404 00405 00406 static void InsertionSort(int * buf, int bufsize) 00407 { 00408 int i, j; 00409 int temp; 00410 00411 for(i = 1; i < bufsize; i++) { 00412 temp = buf[i]; 00413 j = i; 00414 while( j && (buf[j-1] > temp) ) { 00415 buf[j] = buf[j-1]; 00416 j = j-1; 00417 } 00418 buf[j] = temp; 00419 } // End of sort 00420 } 00421 00422 00423 void RA8875::_TouchTicker(void) 00424 { 00425 //INFO("_TouchTicker()"); 00426 if (timeSinceTouch.read_us() > NOTOUCH_TIMEOUT_uS) { 00427 touchSample = 0; 00428 if (touchState == held) 00429 touchState = release; 00430 else 00431 touchState = no_touch; 00432 timeSinceTouch.reset(); 00433 } 00434 } 00435 00436 TouchCode_t RA8875::TouchPanelA2DRaw(int *x, int *y) 00437 { 00438 INFO("A2Raw"); 00439 if( (ReadCommand(INTC2) & RA8875_INT_TP) ) { // Test for TP Interrupt pending in register INTC2 00440 INFO("Int pending"); 00441 timeSinceTouch.reset(); 00442 *y = ReadCommand(TPYH) << 2 | ( (ReadCommand(TPXYL) & 0xC) >> 2 ); // D[9:2] from reg TPYH, D[1:0] from reg TPXYL[3:2] 00443 *x = ReadCommand(TPXH) << 2 | ( (ReadCommand(TPXYL) & 0x3) ); // D[9:2] from reg TPXH, D[1:0] from reg TPXYL[1:0] 00444 INFO("(x,y) = (%d,%d)", x, y); 00445 WriteCommand(INTC2, RA8875_INT_TP); // reg INTC2: Clear that TP interrupt flag 00446 touchState = touch; 00447 } else { 00448 INFO("no touch"); 00449 touchState = no_touch; 00450 } 00451 return touchState; 00452 } 00453 00454 TouchCode_t RA8875::TouchPanelA2DFiltered(int *x, int *y) 00455 { 00456 static int xbuf[TPBUFSIZE], ybuf[TPBUFSIZE]; 00457 static int lastX, lastY; 00458 int i, j; 00459 TouchCode_t ret = touchState; 00460 00461 if( (ReadCommand(INTC2) & RA8875_INT_TP) ) { // Test for TP Interrupt pending in register INTC2 00462 timeSinceTouch.reset(); 00463 // Get the next data samples 00464 ybuf[touchSample] = ReadCommand(TPYH) << 2 | ( (ReadCommand(TPXYL) & 0xC) >> 2 ); // D[9:2] from reg TPYH, D[1:0] from reg TPXYL[3:2] 00465 xbuf[touchSample] = ReadCommand(TPXH) << 2 | ( (ReadCommand(TPXYL) & 0x3) ); // D[9:2] from reg TPXH, D[1:0] from reg TPXYL[1:0] 00466 // Check for a complete set 00467 if(++touchSample == TPBUFSIZE) { 00468 // Buffers are full, so process them using Finn's method described in Analog Dialogue No. 44, Feb 2010 00469 // This requires sorting the samples in order of size, then discarding the top 25% and 00470 // bottom 25% as noise spikes. Finally, the middle 50% of the values are averaged to 00471 // reduce Gaussian noise. 00472 #if 1 00473 InsertionSort(ybuf, TPBUFSIZE); 00474 InsertionSort(xbuf, TPBUFSIZE); 00475 #else 00476 // Sort the Y buffer using an Insertion Sort 00477 for(i = 1; i <= TPBUFSIZE; i++) { 00478 temp = ybuf[i]; 00479 j = i; 00480 while( j && (ybuf[j-1] > temp) ) { 00481 ybuf[j] = ybuf[j-1]; 00482 j = j-1; 00483 } 00484 ybuf[j] = temp; 00485 } // End of Y sort 00486 // Sort the X buffer the same way 00487 for(i = 1; i <= TPBUFSIZE; i++) { 00488 temp = xbuf[i]; 00489 j = i; 00490 while( j && (xbuf[j-1] > temp) ) { 00491 xbuf[j] = xbuf[j-1]; 00492 j = j-1; 00493 } 00494 xbuf[j] = temp; 00495 } // End of X sort 00496 #endif 00497 // Average the middle half of the Y values and report them 00498 j = 0; 00499 for(i = (TPBUFSIZE/4) - 1; i < TPBUFSIZE - TPBUFSIZE/4; i++ ) { 00500 j += ybuf[i]; 00501 } 00502 *y = lastY = j * (float)2/TPBUFSIZE; // This is the average 00503 // Average the middle half of the X values and report them 00504 j = 0; 00505 for(i = (TPBUFSIZE/4) - 1; i < TPBUFSIZE - TPBUFSIZE/4; i++ ) { 00506 j += xbuf[i]; 00507 } 00508 *x = lastX = j * (float)2/TPBUFSIZE; // This is the average 00509 // Tidy up and return 00510 if (touchState == touch || touchState == held) 00511 touchState = held; 00512 else 00513 touchState = touch; 00514 ret = touchState; 00515 touchSample = 0; // Ready to start on the next set of data samples 00516 } else { 00517 // Buffer not yet full, so do not return any results yet 00518 if (touchState == touch || touchState == held) { 00519 *x = lastX; 00520 *y = lastY; 00521 ret = touchState = held; 00522 } 00523 } 00524 WriteCommand(INTC2, RA8875_INT_TP); // reg INTC2: Clear that TP interrupt flag 00525 } // End of initial if -- data has been read and processed 00526 else { 00527 if (touchState == touch || touchState == held) { 00528 *x = lastX; 00529 *y = lastY; 00530 ret = touchState = held; 00531 } else if (touchState == release) { 00532 *x = lastX; 00533 *y = lastY; 00534 ret = release; 00535 touchState = no_touch; 00536 } 00537 } 00538 return ret; 00539 } 00540 00541 /// The following section is derived from Carlos E. Vidales. 00542 /// 00543 /// @copyright © 2001, Carlos E. Vidales. All rights reserved. 00544 /// 00545 /// This sample program was written and put in the public domain 00546 /// by Carlos E. Vidales. The program is provided "as is" 00547 /// without warranty of any kind, either expressed or implied. 00548 /// If you choose to use the program within your own products 00549 /// you do so at your own risk, and assume the responsibility 00550 /// for servicing, repairing or correcting the program should 00551 /// it prove defective in any manner. 00552 /// You may copy and distribute the program's source code in any 00553 /// medium, provided that you also include in each copy an 00554 /// appropriate copyright notice and disclaimer of warranty. 00555 /// You may also modify this program and distribute copies of 00556 /// it provided that you include prominent notices stating 00557 /// that you changed the file(s) and the date of any change, 00558 /// and that you do not charge any royalties or licenses for 00559 /// its use. 00560 /// 00561 /// This file contains functions that implement calculations 00562 /// necessary to obtain calibration factors for a touch screen 00563 /// that suffers from multiple distortion effects: namely, 00564 /// translation, scaling and rotation. 00565 /// 00566 /// The following set of equations represent a valid display 00567 /// point given a corresponding set of touch screen points: 00568 /// 00569 /// <pre> 00570 /// /- -\ 00571 /// /- -\ /- -\ | | 00572 /// | | | | | Xs | 00573 /// | Xd | | A B C | | | 00574 /// | | = | | * | Ys | 00575 /// | Yd | | D E F | | | 00576 /// | | | | | 1 | 00577 /// \- -/ \- -/ | | 00578 /// \- -/ 00579 /// where: 00580 /// (Xd,Yd) represents the desired display point 00581 /// coordinates, 00582 /// (Xs,Ys) represents the available touch screen 00583 /// coordinates, and the matrix 00584 /// /- -\ 00585 /// |A,B,C| 00586 /// |D,E,F| represents the factors used to translate 00587 /// \- -/ the available touch screen point values 00588 /// into the corresponding display 00589 /// coordinates. 00590 /// Note that for practical considerations, the utilities 00591 /// within this file do not use the matrix coefficients as 00592 /// defined above, but instead use the following 00593 /// equivalents, since floating point math is not used: 00594 /// A = An/Divider 00595 /// B = Bn/Divider 00596 /// C = Cn/Divider 00597 /// D = Dn/Divider 00598 /// E = En/Divider 00599 /// F = Fn/Divider 00600 /// The functions provided within this file are: 00601 /// setCalibrationMatrix() - calculates the set of factors 00602 /// in the above equation, given 00603 /// three sets of test points. 00604 /// getDisplayPoint() - returns the actual display 00605 /// coordinates, given a set of 00606 /// touch screen coordinates. 00607 /// translateRawScreenCoordinates() - helper function to transform 00608 /// raw screen points into values 00609 /// scaled to the desired display 00610 /// resolution. 00611 /// 00612 /// 00613 /// Function: setCalibrationMatrix() 00614 /// 00615 /// Description: Calling this function with valid input data 00616 /// in the display and screen input arguments 00617 /// causes the calibration factors between the 00618 /// screen and display points to be calculated, 00619 /// and the output argument - matrixPtr - to be 00620 /// populated. 00621 /// 00622 /// This function needs to be called only when new 00623 /// calibration factors are desired. 00624 /// 00625 /// 00626 /// Argument(s): displayPtr (input) - Pointer to an array of three 00627 /// sample, reference points. 00628 /// screenPtr (input) - Pointer to the array of touch 00629 /// screen points corresponding 00630 /// to the reference display points. 00631 /// matrixPtr (output) - Pointer to the calibration 00632 /// matrix computed for the set 00633 /// of points being provided. 00634 /// 00635 /// 00636 /// From the article text, recall that the matrix coefficients are 00637 /// resolved to be the following: 00638 /// 00639 /// 00640 /// Divider = (Xs0 - Xs2)*(Ys1 - Ys2) - (Xs1 - Xs2)*(Ys0 - Ys2) 00641 /// 00642 /// 00643 /// 00644 /// (Xd0 - Xd2)*(Ys1 - Ys2) - (Xd1 - Xd2)*(Ys0 - Ys2) 00645 /// A = --------------------------------------------------- 00646 /// Divider 00647 /// 00648 /// 00649 /// (Xs0 - Xs2)*(Xd1 - Xd2) - (Xd0 - Xd2)*(Xs1 - Xs2) 00650 /// B = --------------------------------------------------- 00651 /// Divider 00652 /// 00653 /// 00654 /// Ys0*(Xs2*Xd1 - Xs1*Xd2) + 00655 /// Ys1*(Xs0*Xd2 - Xs2*Xd0) + 00656 /// Ys2*(Xs1*Xd0 - Xs0*Xd1) 00657 /// C = --------------------------------------------------- 00658 /// Divider 00659 /// 00660 /// 00661 /// (Yd0 - Yd2)*(Ys1 - Ys2) - (Yd1 - Yd2)*(Ys0 - Ys2) 00662 /// D = --------------------------------------------------- 00663 /// Divider 00664 /// 00665 /// 00666 /// (Xs0 - Xs2)*(Yd1 - Yd2) - (Yd0 - Yd2)*(Xs1 - Xs2) 00667 /// E = --------------------------------------------------- 00668 /// Divider 00669 /// 00670 /// 00671 /// Ys0*(Xs2*Yd1 - Xs1*Yd2) + 00672 /// Ys1*(Xs0*Yd2 - Xs2*Yd0) + 00673 /// Ys2*(Xs1*Yd0 - Xs0*Yd1) 00674 /// F = --------------------------------------------------- 00675 /// Divider 00676 /// 00677 /// 00678 /// Return: OK - the calibration matrix was correctly 00679 /// calculated and its value is in the 00680 /// output argument. 00681 /// NOT_OK - an error was detected and the 00682 /// function failed to return a valid 00683 /// set of matrix values. 00684 /// The only time this sample code returns 00685 /// NOT_OK is when Divider == 0 00686 /// 00687 /// 00688 /// 00689 /// NOTE! NOTE! NOTE! 00690 /// 00691 /// setCalibrationMatrix() and getDisplayPoint() will do fine 00692 /// for you as they are, provided that your digitizer 00693 /// resolution does not exceed 10 bits (1024 values). Higher 00694 /// resolutions may cause the integer operations to overflow 00695 /// and return incorrect values. If you wish to use these 00696 /// functions with digitizer resolutions of 12 bits (4096 00697 /// values) you will either have to a) use 64-bit signed 00698 /// integer variables and math, or b) judiciously modify the 00699 /// operations to scale results by a factor of 2 or even 4. 00700 /// 00701 /// </pre> 00702 /// 00703 RetCode_t RA8875::TouchPanelComputeCalibration(point_t * displayPtr, point_t * screenPtr, tpMatrix_t * matrixPtr) 00704 { 00705 RetCode_t retValue = noerror; 00706 00707 tpMatrix.Divider = ((screenPtr[0].x - screenPtr[2].x) * (screenPtr[1].y - screenPtr[2].y)) - 00708 ((screenPtr[1].x - screenPtr[2].x) * (screenPtr[0].y - screenPtr[2].y)) ; 00709 00710 if( tpMatrix.Divider == 0 ) { 00711 retValue = bad_parameter; 00712 } else { 00713 tpMatrix.An = ((displayPtr[0].x - displayPtr[2].x) * (screenPtr[1].y - screenPtr[2].y)) - 00714 ((displayPtr[1].x - displayPtr[2].x) * (screenPtr[0].y - screenPtr[2].y)) ; 00715 00716 tpMatrix.Bn = ((screenPtr[0].x - screenPtr[2].x) * (displayPtr[1].x - displayPtr[2].x)) - 00717 ((displayPtr[0].x - displayPtr[2].x) * (screenPtr[1].x - screenPtr[2].x)) ; 00718 00719 tpMatrix.Cn = (screenPtr[2].x * displayPtr[1].x - screenPtr[1].x * displayPtr[2].x) * screenPtr[0].y + 00720 (screenPtr[0].x * displayPtr[2].x - screenPtr[2].x * displayPtr[0].x) * screenPtr[1].y + 00721 (screenPtr[1].x * displayPtr[0].x - screenPtr[0].x * displayPtr[1].x) * screenPtr[2].y ; 00722 00723 tpMatrix.Dn = ((displayPtr[0].y - displayPtr[2].y) * (screenPtr[1].y - screenPtr[2].y)) - 00724 ((displayPtr[1].y - displayPtr[2].y) * (screenPtr[0].y - screenPtr[2].y)) ; 00725 00726 tpMatrix.En = ((screenPtr[0].x - screenPtr[2].x) * (displayPtr[1].y - displayPtr[2].y)) - 00727 ((displayPtr[0].y - displayPtr[2].y) * (screenPtr[1].x - screenPtr[2].x)) ; 00728 00729 tpMatrix.Fn = (screenPtr[2].x * displayPtr[1].y - screenPtr[1].x * displayPtr[2].y) * screenPtr[0].y + 00730 (screenPtr[0].x * displayPtr[2].y - screenPtr[2].x * displayPtr[0].y) * screenPtr[1].y + 00731 (screenPtr[1].x * displayPtr[0].y - screenPtr[0].x * displayPtr[1].y) * screenPtr[2].y ; 00732 touchState = no_touch; 00733 if (matrixPtr) 00734 memcpy(matrixPtr, &tpMatrix, sizeof(tpMatrix_t)); 00735 } 00736 return( retValue ) ; 00737 } 00738 00739 void RA8875::ResTouchPanelCfg(const char * _tpFQFN, const char * _tpCalMessage) 00740 { 00741 tpFQFN = _tpFQFN; 00742 tpCalMessage = _tpCalMessage; 00743 } 00744 00745 00746 RetCode_t RA8875::_internal_ts_cal() 00747 { 00748 FILE * fh; 00749 tpMatrix_t matrix; 00750 RetCode_t r = noerror; 00751 00752 if (tpFQFN) { 00753 fh = fopen(tpFQFN, "rb"); 00754 if (fh) { 00755 fread(&matrix, sizeof(tpMatrix_t), 1, fh); 00756 fclose(fh); 00757 TouchPanelSetMatrix(&matrix); 00758 } else { 00759 r = TouchPanelCalibrate(tpCalMessage, &matrix); 00760 if (r == noerror) { 00761 fh = fopen(tpFQFN, "wb"); 00762 if (fh) { 00763 fwrite(&matrix, sizeof(tpMatrix_t), 1, fh); 00764 fclose(fh); 00765 INFO(" tp cal written to '%s'.", tpFQFN); 00766 } else { 00767 ERR(" couldn't open tpcal file '%s'.", tpFQFN); 00768 r = file_not_found; 00769 } 00770 } else { 00771 ERR("error return: %d", r); 00772 } 00773 HexDump("TPCal", (const uint8_t *)&matrix, sizeof(tpMatrix_t)); 00774 cls(); 00775 } 00776 } 00777 return r; 00778 } 00779 00780 00781 00782 ////////////////// Capacitive Touch Panel 00783 00784 uint8_t RA8875::FT5206_ReadRegU8(uint8_t reg) { 00785 char val; 00786 00787 m_i2c->write(m_addr, (const char *)®, 1); 00788 m_i2c->read(m_addr, &val, 1); 00789 return (uint8_t)val; 00790 } 00791 00792 // Interrupt for touch detection 00793 void RA8875::TouchPanelISR(void) 00794 { 00795 if (useTouchPanel == TP_FT5206) { 00796 if (FT5206_TouchPositions()) 00797 panelTouched = true; 00798 } else if (useTouchPanel == TP_GSL1680) { 00799 if (GSL1680_TouchPositions()) 00800 panelTouched = true; 00801 } 00802 } 00803 00804 00805 // #### end of touch panel code additions
Generated on Tue Jul 26 2022 07:46:24 by 1.7.2