A library with drivers for different peripherals on the LPC4088 QuickStart Board or related add-on boards.

Dependencies:   FATFileSystem

Fork of EALib by EmbeddedArtists AB

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers TSC2046.cpp Source File

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