The wait in mci_WaitForEvent will delay all card transactions.

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