Library to control a Graphics TFT connected to 4-wire SPI - revised for the Raio RA8875 Display Controller.

Dependents:   FRDM_RA8875_mPaint RA8875_Demo RA8875_KeyPadDemo SignalGenerator ... more

Fork of SPI_TFT by Peter Drescher

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers RA8875_Touch.cpp Source File

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