A library with drivers for different peripherals on the LPC4088 QuickStart Board or related add-on boards.
Fork of EALib by
TSC2046.cpp
00001 /* 00002 * Copyright 2013 Embedded Artists AB 00003 * 00004 * Licensed under the Apache License, Version 2.0 (the "License"); 00005 * you may not use this file except in compliance with the License. 00006 * You may obtain a copy of the License at 00007 * 00008 * http://www.apache.org/licenses/LICENSE-2.0 00009 * 00010 * Unless required by applicable law or agreed to in writing, software 00011 * distributed under the License is distributed on an "AS IS" BASIS, 00012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00013 * See the License for the specific language governing permissions and 00014 * limitations under the License. 00015 */ 00016 00017 #include "mbed.h" 00018 #include "mbed_debug.h" 00019 #include "TSC2046.h" 00020 00021 #ifndef ABS 00022 #define ABS(x) ( ((int32_t)(x)) < 0 ? (-(x)) : (x)) 00023 #endif 00024 00025 #define ADS_START (1 << 7) 00026 #define ADS_A2A1A0_d_y (1 << 4) /* differential */ 00027 #define ADS_A2A1A0_d_z1 (3 << 4) /* differential */ 00028 #define ADS_A2A1A0_d_z2 (4 << 4) /* differential */ 00029 #define ADS_A2A1A0_d_x (5 << 4) /* differential */ 00030 #define ADS_A2A1A0_temp0 (0 << 4) /* non-differential */ 00031 #define ADS_A2A1A0_vbatt (2 << 4) /* non-differential */ 00032 #define ADS_A2A1A0_vaux (6 << 4) /* non-differential */ 00033 #define ADS_A2A1A0_temp1 (7 << 4) /* non-differential */ 00034 #define ADS_8_BIT (1 << 3) 00035 #define ADS_12_BIT (0 << 3) 00036 #define ADS_SER (1 << 2) /* non-differential */ 00037 #define ADS_DFR (0 << 2) /* differential */ 00038 #define ADS_PD10_PDOWN (0 << 0) /* lowpower mode + penirq */ 00039 #define ADS_PD10_ADC_ON (1 << 0) /* ADC on */ 00040 #define ADS_PD10_REF_ON (2 << 0) /* vREF on + penirq */ 00041 #define ADS_PD10_ALL_ON (3 << 0) /* ADC + vREF on */ 00042 00043 00044 #define READ_12BIT_DFR(d, adc, vref) (ADS_START | d \ 00045 | ADS_12_BIT | ADS_DFR | \ 00046 (adc ? ADS_PD10_ADC_ON : 0) | (vref ? ADS_PD10_REF_ON : 0)) 00047 00048 #define READ_Y(vref) (READ_12BIT_DFR(ADS_A2A1A0_d_y, 1, vref)) 00049 #define READ_Z1(vref) (READ_12BIT_DFR(ADS_A2A1A0_d_z1, 1, vref)) 00050 #define READ_Z2(vref) (READ_12BIT_DFR(ADS_A2A1A0_d_z2, 1, vref)) 00051 #define READ_X(vref) (READ_12BIT_DFR(ADS_A2A1A0_d_x, 1, vref)) 00052 #define PWRDOWN (READ_12BIT_DFR(ADS_A2A1A0_d_y, 0, 0)) /* LAST */ 00053 00054 /* single-ended samples need to first power up reference voltage; 00055 * we leave both ADC and VREF powered 00056 */ 00057 #define READ_12BIT_SER(x) (ADS_START | x \ 00058 | ADS_12_BIT | ADS_SER) 00059 00060 #define REF_ON (READ_12BIT_DFR(ADS_A2A1A0_d_x, 1, 1)) 00061 #define REF_OFF (READ_12BIT_DFR(ADS_A2A1A0_d_y, 0, 0)) 00062 00063 #define DEBOUNCE_MAX 10 00064 #define DEBOUNCE_TOL 3 00065 00066 00067 TSC2046::TSC2046(PinName mosi, PinName miso, PinName sck, PinName cs) : 00068 _spi(mosi, miso, sck), _cs(cs) 00069 { 00070 _cs = 1; // active low 00071 00072 _spi.format(8, 3); 00073 00074 // We are limiting the clock rate to 500000 since 00075 // we have experienced a lot of noise when running with 00076 // higher rate. It has not been examined why there is a 00077 // lot of noise with higher rate. 00078 _spi.frequency(500000); 00079 _calibrated = false; 00080 _initialized = false; 00081 00082 _calibPoint = TSC2046_NUM_CALIB_POINTS+1; 00083 00084 _insetPx = 15; 00085 } 00086 00087 bool TSC2046::init(uint16_t width, uint16_t height) { 00088 _width = width; 00089 _height = height; 00090 00091 _cs = 0; 00092 00093 _spi.write(REF_ON); 00094 _spi.write((READ_12BIT_SER(ADS_A2A1A0_vaux) | ADS_PD10_ALL_ON)); 00095 _spi.write(PWRDOWN); 00096 00097 _cs = 1; 00098 00099 00100 _initialized = true; 00101 00102 return true; 00103 } 00104 00105 00106 bool TSC2046::read(touchCoordinate_t &coord) { 00107 00108 touchCoordinate_t tmpCoord; 00109 calibPoint_t displayPoint; 00110 calibPoint_t screenSample; 00111 00112 if (!_initialized) return false; 00113 00114 00115 readAndFilter(tmpCoord); 00116 00117 _cs = 0; 00118 _spi.write(PWRDOWN); 00119 _cs = 1; 00120 00121 coord.z = tmpCoord.z; 00122 00123 if (_calibrated) { 00124 screenSample.x = tmpCoord.x; 00125 screenSample.y = tmpCoord.y; 00126 00127 getDisplayPoint(&displayPoint, &screenSample, &_calibMatrix); 00128 00129 coord.x = displayPoint.x; 00130 coord.y = displayPoint.y; 00131 } 00132 else { 00133 coord.x = tmpCoord.x; 00134 coord.y = tmpCoord.y; 00135 } 00136 00137 return true; 00138 00139 } 00140 00141 bool TSC2046::calibrateStart() { 00142 if (!_initialized) return false; 00143 00144 _calibPoint = 0; 00145 00146 return true; 00147 } 00148 00149 bool TSC2046::getNextCalibratePoint(uint16_t* x, uint16_t* y) { 00150 touchCoordinate_t coord; 00151 00152 if (!_initialized) return false; 00153 00154 if (x == NULL || y == NULL) return false; 00155 00156 if (_calibPoint >= TSC2046_NUM_CALIB_POINTS) return false; 00157 00158 getCalibratePoint(_calibPoint, &coord.x, &coord.y); 00159 00160 *x = (uint16_t)coord.x; 00161 *y = (uint16_t)coord.y; 00162 _calibrateValues[_calibPoint][0] = coord; 00163 00164 return true; 00165 } 00166 00167 bool TSC2046::waitForCalibratePoint(bool* morePoints, uint32_t timeout) { 00168 int result = 0; 00169 bool ret = false; 00170 int32_t x = 0; 00171 int32_t y = 0; 00172 touchCoordinate_t coord; 00173 00174 if (!_initialized) return false; 00175 00176 do { 00177 if (morePoints == NULL || _calibPoint >= TSC2046_NUM_CALIB_POINTS) { 00178 break; 00179 } 00180 00181 result = waitForTouch(&x, &y, timeout); 00182 if (result != 0) { 00183 debug("wait for touch response failed (%d)\n", result); 00184 break; 00185 } 00186 00187 coord.x = x; 00188 coord.y = y; 00189 _calibrateValues[_calibPoint][1] = coord; 00190 00191 _calibPoint++; 00192 *morePoints = (_calibPoint < TSC2046_NUM_CALIB_POINTS); 00193 00194 if (!(*morePoints)) { 00195 00196 calibrate( 00197 _calibrateValues[0][0], 00198 _calibrateValues[1][0], 00199 _calibrateValues[2][0], 00200 _calibrateValues[0][1], 00201 _calibrateValues[1][1], 00202 _calibrateValues[2][1]); 00203 } 00204 00205 00206 ret = true; 00207 00208 } while (0); 00209 00210 00211 00212 if (!ret) { 00213 // calibration must restart if an error occurred 00214 _calibPoint = TSC2046_NUM_CALIB_POINTS+1; 00215 } 00216 00217 00218 00219 return ret; 00220 00221 } 00222 00223 00224 bool TSC2046::calibrate(touchCoordinate_t* values, int numValues) { 00225 if (values == NULL || numValues < TSC2046_NUM_CALIB_POINTS) return false; 00226 00227 touchCoordinate_t ref[TSC2046_NUM_CALIB_POINTS]; 00228 touchCoordinate_t scr[TSC2046_NUM_CALIB_POINTS]; 00229 00230 for (int i = 0; i < TSC2046_NUM_CALIB_POINTS; i++) { 00231 getCalibratePoint(i, &(ref[i].x), &(ref[i].y)); 00232 scr[i] = values[i]; 00233 } 00234 00235 calibrate(ref[0], ref[1], ref[2], scr[0], scr[1], scr[2]); 00236 00237 return true; 00238 } 00239 00240 00241 bool TSC2046::getCalibrationValues(touchCoordinate_t* values, int numValues) { 00242 if (values == NULL || numValues < TSC2046_NUM_CALIB_POINTS) return false; 00243 if (!_calibrated) return false; 00244 00245 for (int i = 0; i < TSC2046_NUM_CALIB_POINTS; i++) { 00246 values[i] = _calibrateValues[i][1]; 00247 } 00248 00249 return true; 00250 } 00251 00252 00253 void TSC2046::readAndFilter(touchCoordinate_t &coord) 00254 { 00255 int32_t ix, iy, iz1, iz2 = 0; 00256 int32_t lastx, lasty, lastz1, lastz2 = 0; 00257 int i = 0; 00258 00259 coord.x = 0; 00260 coord.y = 0; 00261 coord.z = 0; 00262 00263 lasty = getFilteredValue(READ_Y(0)); 00264 lasty >>= 3; 00265 if (lasty >= 4095) { 00266 lasty = 0; 00267 } 00268 00269 lastx = getFilteredValue(READ_X(0)); 00270 lastx >>= 3; 00271 if (lastx >= 4095) { 00272 lastx = 0; 00273 } 00274 00275 lastz1 = getFilteredValue(READ_Z1(0)); 00276 lastz1 >>= 3; 00277 00278 lastz2 = getFilteredValue(READ_Z2(0)); 00279 lastz2 >>= 3; 00280 00281 00282 if (lastx && lastz1) { 00283 coord.z = (lastx * ABS(lastz2 - lastz1)) / lastz1; 00284 } 00285 else { 00286 coord.z = 0; 00287 } 00288 00289 if (coord.z > 20000) { 00290 coord.z = 0; 00291 } 00292 00293 if (coord.z == 0) { 00294 return; 00295 } 00296 00297 for (i = 0; i < DEBOUNCE_MAX; i++) { 00298 iy = getFilteredValue(READ_Y(0)); 00299 iy >>= 3; 00300 00301 if (ABS (lasty - iy) <= DEBOUNCE_TOL) { 00302 break; 00303 } 00304 00305 lasty = iy; 00306 } 00307 00308 for (i = 0; i < DEBOUNCE_MAX; i++) { 00309 ix = getFilteredValue(READ_X(0)); 00310 ix >>= 3; 00311 if (ix > 4095) { 00312 ix = 0; 00313 } 00314 00315 if (ABS (lastx - ix) <= DEBOUNCE_TOL) { 00316 break; 00317 } 00318 00319 lastx = ix; 00320 } 00321 00322 for (i = 0; i < DEBOUNCE_MAX; i++) { 00323 iz1 = getFilteredValue(READ_Z1(0)); 00324 iz1 >>= 3; 00325 00326 if (ABS (lastz1 - iz1) <= DEBOUNCE_TOL) { 00327 break; 00328 } 00329 00330 lastz1 = iz1; 00331 } 00332 00333 for (i = 0; i < DEBOUNCE_MAX; i++) { 00334 iz2 = getFilteredValue(READ_Z2(0)); 00335 iz2 >>= 3; 00336 00337 if (ABS (lastz2 - iz2) <= DEBOUNCE_TOL) { 00338 break; 00339 } 00340 00341 lastz2 = iz2; 00342 } 00343 00344 coord.x = ix; 00345 coord.y = iy; 00346 00347 if (ix && iz1) { 00348 coord.z = (ix * ABS(iz2 - iz1)) / iz1; 00349 } 00350 else { 00351 coord.z = 0; 00352 } 00353 00354 if (coord.z > 20000) { 00355 coord.z = 0; 00356 } 00357 00358 } 00359 00360 int32_t TSC2046::getFilteredValue(int cmd) 00361 { 00362 int32_t a[7]; 00363 int32_t tmp = 0; 00364 int i = 0, j = 0; 00365 00366 /* 00367 * Median and averaging filter 00368 * 00369 * 1. Get 7 values 00370 * 2. Sort these values 00371 * 3. Take average of the 3 values in the middle 00372 */ 00373 00374 for (i = 0; i < 7; i++) { 00375 a[i] = spiTransfer(cmd); 00376 } 00377 00378 // bubble sort 00379 for (i = 0; i < 7; i++) { 00380 for (j = 0; j < (7-(i+1)); j++) { 00381 if (a[j] > a[j+1]) { 00382 // swap 00383 tmp = a[j]; 00384 a[j] = a[j+1]; 00385 a[j+1] = tmp; 00386 } 00387 } 00388 } 00389 00390 // average of 3 values in the middle 00391 return ((a[2]+a[3]+a[4])/3); 00392 } 00393 00394 uint16_t TSC2046::spiTransfer(uint8_t cmd) 00395 { 00396 uint8_t data[3]; 00397 00398 _cs = 0; 00399 00400 /*data[0] = */_spi.write(cmd); 00401 data[0] = _spi.write(0xff); 00402 data[1] = _spi.write(0xff); 00403 00404 _cs = 1; 00405 00406 return ((data[0] << 8) | data[1]); 00407 } 00408 00409 void TSC2046::calibrate(touchCoordinate_t &ref1, 00410 touchCoordinate_t &ref2, 00411 touchCoordinate_t &ref3, 00412 touchCoordinate_t &scr1, 00413 touchCoordinate_t &scr2, 00414 touchCoordinate_t &scr3) { 00415 00416 calibPoint_t disp[3]; 00417 calibPoint_t scr[3]; 00418 00419 disp[0].x = ref1.x; 00420 disp[0].y = ref1.y; 00421 disp[1].x = ref2.x; 00422 disp[1].y = ref2.y; 00423 disp[2].x = ref3.x; 00424 disp[2].y = ref3.y; 00425 00426 scr[0].x = scr1.x; 00427 scr[0].y = scr1.y; 00428 scr[1].x = scr2.x; 00429 scr[1].y = scr2.y; 00430 scr[2].x = scr3.x; 00431 scr[2].y = scr3.y; 00432 00433 setCalibrationMatrix(disp, scr, &_calibMatrix); 00434 00435 _calibrated = true; 00436 00437 } 00438 00439 void TSC2046::getCalibratePoint(int pointNum, int32_t* x, int32_t *y) { 00440 switch(pointNum) { 00441 case 0: 00442 *x = _insetPx; 00443 *y = _height - _insetPx; 00444 break; 00445 case 1: 00446 *x = _width/2; 00447 *y = _insetPx; 00448 break; 00449 case 2: 00450 *x = _width - _insetPx; 00451 *y = _height - _insetPx; 00452 break; 00453 } 00454 } 00455 00456 int TSC2046::waitForTouch(int32_t* x, int32_t* y, uint32_t timeout) { 00457 Timer t; 00458 touchCoordinate_t coord; 00459 bool waitForRelease = false; 00460 int32_t tx = 0; 00461 int32_t ty = 0; 00462 00463 00464 t.start(); 00465 while (timeout == 0 || ((uint32_t)t.read_ms() < timeout)) { 00466 00467 read(coord); 00468 00469 if (coord.z == 0 && waitForRelease) { 00470 *x = tx; 00471 *y = ty; 00472 break; 00473 } 00474 00475 if (coord.z > 0) { 00476 tx = coord.x; 00477 ty = coord.y; 00478 waitForRelease = true; 00479 } 00480 00481 wait_ms(10); 00482 } 00483 00484 if (timeout > 0 && (uint32_t)t.read_ms() > timeout) { 00485 return -1; 00486 } 00487 00488 return 0; 00489 00490 } 00491 00492 00493 00494 // ############################################################################ 00495 // >>>>>>>> Calibrate code >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 00496 // ############################################################################ 00497 00498 00499 /* 00500 * 00501 * Copyright (c) 2001, Carlos E. Vidales. All rights reserved. 00502 * 00503 * This sample program was written and put in the public domain 00504 * by Carlos E. Vidales. The program is provided "as is" 00505 * without warranty of any kind, either expressed or implied. 00506 * If you choose to use the program within your own products 00507 * you do so at your own risk, and assume the responsibility 00508 * for servicing, repairing or correcting the program should 00509 * it prove defective in any manner. 00510 * You may copy and distribute the program's source code in any 00511 * medium, provided that you also include in each copy an 00512 * appropriate copyright notice and disclaimer of warranty. 00513 * You may also modify this program and distribute copies of 00514 * it provided that you include prominent notices stating 00515 * that you changed the file(s) and the date of any change, 00516 * and that you do not charge any royalties or licenses for 00517 * its use. 00518 * 00519 * 00520 * 00521 * File Name: calibrate.c 00522 * 00523 * 00524 * This file contains functions that implement calculations 00525 * necessary to obtain calibration factors for a touch screen 00526 * that suffers from multiple distortion effects: namely, 00527 * translation, scaling and rotation. 00528 * 00529 * The following set of equations represent a valid display 00530 * point given a corresponding set of touch screen points: 00531 * 00532 * 00533 * /- -\ 00534 * /- -\ /- -\ | | 00535 * | | | | | Xs | 00536 * | Xd | | A B C | | | 00537 * | | = | | * | Ys | 00538 * | Yd | | D E F | | | 00539 * | | | | | 1 | 00540 * \- -/ \- -/ | | 00541 * \- -/ 00542 * 00543 * 00544 * where: 00545 * 00546 * (Xd,Yd) represents the desired display point 00547 * coordinates, 00548 * 00549 * (Xs,Ys) represents the available touch screen 00550 * coordinates, and the matrix 00551 * 00552 * /- -\ 00553 * |A,B,C| 00554 * |D,E,F| represents the factors used to translate 00555 * \- -/ the available touch screen point values 00556 * into the corresponding display 00557 * coordinates. 00558 * 00559 * 00560 * Note that for practical considerations, the utilitities 00561 * within this file do not use the matrix coefficients as 00562 * defined above, but instead use the following 00563 * equivalents, since floating point math is not used: 00564 * 00565 * A = An/Divider 00566 * B = Bn/Divider 00567 * C = Cn/Divider 00568 * D = Dn/Divider 00569 * E = En/Divider 00570 * F = Fn/Divider 00571 * 00572 * 00573 * 00574 * The functions provided within this file are: 00575 * 00576 * setCalibrationMatrix() - calculates the set of factors 00577 * in the above equation, given 00578 * three sets of test points. 00579 * getDisplayPoint() - returns the actual display 00580 * coordinates, given a set of 00581 * touch screen coordinates. 00582 * translateRawScreenCoordinates() - helper function to transform 00583 * raw screen points into values 00584 * scaled to the desired display 00585 * resolution. 00586 * 00587 * 00588 */ 00589 00590 00591 /********************************************************************** 00592 * 00593 * Function: setCalibrationMatrix() 00594 * 00595 * Description: Calling this function with valid input data 00596 * in the display and screen input arguments 00597 * causes the calibration factors between the 00598 * screen and display points to be calculated, 00599 * and the output argument - matrixPtr - to be 00600 * populated. 00601 * 00602 * This function needs to be called only when new 00603 * calibration factors are desired. 00604 * 00605 * 00606 * Argument(s): displayPtr (input) - Pointer to an array of three 00607 * sample, reference points. 00608 * screenPtr (input) - Pointer to the array of touch 00609 * screen points corresponding 00610 * to the reference display points. 00611 * matrixPtr (output) - Pointer to the calibration 00612 * matrix computed for the set 00613 * of points being provided. 00614 * 00615 * 00616 * From the article text, recall that the matrix coefficients are 00617 * resolved to be the following: 00618 * 00619 * 00620 * Divider = (Xs0 - Xs2)*(Ys1 - Ys2) - (Xs1 - Xs2)*(Ys0 - Ys2) 00621 * 00622 * 00623 * 00624 * (Xd0 - Xd2)*(Ys1 - Ys2) - (Xd1 - Xd2)*(Ys0 - Ys2) 00625 * A = --------------------------------------------------- 00626 * Divider 00627 * 00628 * 00629 * (Xs0 - Xs2)*(Xd1 - Xd2) - (Xd0 - Xd2)*(Xs1 - Xs2) 00630 * B = --------------------------------------------------- 00631 * Divider 00632 * 00633 * 00634 * Ys0*(Xs2*Xd1 - Xs1*Xd2) + 00635 * Ys1*(Xs0*Xd2 - Xs2*Xd0) + 00636 * Ys2*(Xs1*Xd0 - Xs0*Xd1) 00637 * C = --------------------------------------------------- 00638 * Divider 00639 * 00640 * 00641 * (Yd0 - Yd2)*(Ys1 - Ys2) - (Yd1 - Yd2)*(Ys0 - Ys2) 00642 * D = --------------------------------------------------- 00643 * Divider 00644 * 00645 * 00646 * (Xs0 - Xs2)*(Yd1 - Yd2) - (Yd0 - Yd2)*(Xs1 - Xs2) 00647 * E = --------------------------------------------------- 00648 * Divider 00649 * 00650 * 00651 * Ys0*(Xs2*Yd1 - Xs1*Yd2) + 00652 * Ys1*(Xs0*Yd2 - Xs2*Yd0) + 00653 * Ys2*(Xs1*Yd0 - Xs0*Yd1) 00654 * F = --------------------------------------------------- 00655 * Divider 00656 * 00657 * 00658 * Return: OK - the calibration matrix was correctly 00659 * calculated and its value is in the 00660 * output argument. 00661 * NOT_OK - an error was detected and the 00662 * function failed to return a valid 00663 * set of matrix values. 00664 * The only time this sample code returns 00665 * NOT_OK is when Divider == 0 00666 * 00667 * 00668 * 00669 * NOTE! NOTE! NOTE! 00670 * 00671 * setCalibrationMatrix() and getDisplayPoint() will do fine 00672 * for you as they are, provided that your digitizer 00673 * resolution does not exceed 10 bits (1024 values). Higher 00674 * resolutions may cause the integer operations to overflow 00675 * and return incorrect values. If you wish to use these 00676 * functions with digitizer resolutions of 12 bits (4096 00677 * values) you will either have to a) use 64-bit signed 00678 * integer variables and math, or b) judiciously modify the 00679 * operations to scale results by a factor of 2 or even 4. 00680 * 00681 * 00682 */ 00683 int TSC2046::setCalibrationMatrix( calibPoint_t * displayPtr, 00684 calibPoint_t * screenPtr, 00685 calibMatrix_t * matrixPtr) 00686 { 00687 int retValue = 0 ; 00688 00689 00690 matrixPtr->Divider = ((screenPtr[0].x - screenPtr[2].x) * (screenPtr[1].y - screenPtr[2].y)) - 00691 ((screenPtr[1].x - screenPtr[2].x) * (screenPtr[0].y - screenPtr[2].y)) ; 00692 if( matrixPtr->Divider == 0 ) 00693 { 00694 retValue = 1 ; 00695 } 00696 else 00697 { 00698 matrixPtr->An = ((displayPtr[0].x - displayPtr[2].x) * (screenPtr[1].y - screenPtr[2].y)) - 00699 ((displayPtr[1].x - displayPtr[2].x) * (screenPtr[0].y - screenPtr[2].y)) ; 00700 matrixPtr->Bn = ((screenPtr[0].x - screenPtr[2].x) * (displayPtr[1].x - displayPtr[2].x)) - 00701 ((displayPtr[0].x - displayPtr[2].x) * (screenPtr[1].x - screenPtr[2].x)) ; 00702 matrixPtr->Cn = (screenPtr[2].x * displayPtr[1].x - screenPtr[1].x * displayPtr[2].x) * screenPtr[0].y + 00703 (screenPtr[0].x * displayPtr[2].x - screenPtr[2].x * displayPtr[0].x) * screenPtr[1].y + 00704 (screenPtr[1].x * displayPtr[0].x - screenPtr[0].x * displayPtr[1].x) * screenPtr[2].y ; 00705 matrixPtr->Dn = ((displayPtr[0].y - displayPtr[2].y) * (screenPtr[1].y - screenPtr[2].y)) - 00706 ((displayPtr[1].y - displayPtr[2].y) * (screenPtr[0].y - screenPtr[2].y)) ; 00707 00708 matrixPtr->En = ((screenPtr[0].x - screenPtr[2].x) * (displayPtr[1].y - displayPtr[2].y)) - 00709 ((displayPtr[0].y - displayPtr[2].y) * (screenPtr[1].x - screenPtr[2].x)) ; 00710 matrixPtr->Fn = (screenPtr[2].x * displayPtr[1].y - screenPtr[1].x * displayPtr[2].y) * screenPtr[0].y + 00711 (screenPtr[0].x * displayPtr[2].y - screenPtr[2].x * displayPtr[0].y) * screenPtr[1].y + 00712 (screenPtr[1].x * displayPtr[0].y - screenPtr[0].x * displayPtr[1].y) * screenPtr[2].y ; 00713 } 00714 00715 return( retValue ) ; 00716 } 00717 00718 /********************************************************************** 00719 * 00720 * Function: getDisplayPoint() 00721 * 00722 * Description: Given a valid set of calibration factors and a point 00723 * value reported by the touch screen, this function 00724 * calculates and returns the true (or closest to true) 00725 * display point below the spot where the touch screen 00726 * was touched. 00727 * 00728 * 00729 * 00730 * Argument(s): displayPtr (output) - Pointer to the calculated 00731 * (true) display point. 00732 * screenPtr (input) - Pointer to the reported touch 00733 * screen point. 00734 * matrixPtr (input) - Pointer to calibration factors 00735 * matrix previously calculated 00736 * from a call to 00737 * setCalibrationMatrix() 00738 * 00739 * 00740 * The function simply solves for Xd and Yd by implementing the 00741 * computations required by the translation matrix. 00742 * 00743 * /- -\ 00744 * /- -\ /- -\ | | 00745 * | | | | | Xs | 00746 * | Xd | | A B C | | | 00747 * | | = | | * | Ys | 00748 * | Yd | | D E F | | | 00749 * | | | | | 1 | 00750 * \- -/ \- -/ | | 00751 * \- -/ 00752 * 00753 * It must be kept brief to avoid consuming CPU cycles. 00754 * 00755 * 00756 * Return: OK - the display point was correctly calculated 00757 * and its value is in the output argument. 00758 * NOT_OK - an error was detected and the function 00759 * failed to return a valid point. 00760 * 00761 * 00762 * 00763 * NOTE! NOTE! NOTE! 00764 * 00765 * setCalibrationMatrix() and getDisplayPoint() will do fine 00766 * for you as they are, provided that your digitizer 00767 * resolution does not exceed 10 bits (1024 values). Higher 00768 * resolutions may cause the integer operations to overflow 00769 * and return incorrect values. If you wish to use these 00770 * functions with digitizer resolutions of 12 bits (4096 00771 * values) you will either have to a) use 64-bit signed 00772 * integer variables and math, or b) judiciously modify the 00773 * operations to scale results by a factor of 2 or even 4. 00774 * 00775 * 00776 */ 00777 int TSC2046::getDisplayPoint( calibPoint_t * displayPtr, 00778 calibPoint_t * screenPtr, 00779 calibMatrix_t * matrixPtr ) 00780 { 00781 int retValue = 0 ; 00782 00783 if( matrixPtr->Divider != 0 ) 00784 { 00785 /* Operation order is important since we are doing integer */ 00786 /* math. Make sure you add all terms together before */ 00787 /* dividing, so that the remainder is not rounded off */ 00788 /* prematurely. */ 00789 displayPtr->x = ( (matrixPtr->An * screenPtr->x) + 00790 (matrixPtr->Bn * screenPtr->y) + 00791 matrixPtr->Cn 00792 ) / matrixPtr->Divider ; 00793 displayPtr->y = ( (matrixPtr->Dn * screenPtr->x) + 00794 (matrixPtr->En * screenPtr->y) + 00795 matrixPtr->Fn 00796 ) / matrixPtr->Divider ; 00797 } 00798 else 00799 { 00800 retValue = 1 ; 00801 } 00802 return( retValue ) ; 00803 } 00804 00805 00806 00807 // ############################################################################ 00808 // <<<<<<<< Calibrate code <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 00809 // ############################################################################ 00810 00811 00812
Generated on Wed Jul 13 2022 02:29:31 by 1.7.2