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

See Components - RA8875 Based Display

Enhanced touch-screen support - where it previous supported both the Resistive Touch and Capacitive Touch based on the FT5206 Touch Controller, now it also has support for the GSL1680 Touch Controller.

Offline Help Manual (Windows chm)

/media/uploads/WiredHome/ra8875.zip.bin (download, rename to .zip and unzip)

Revision:
83:7bad0068cca0
Parent:
81:01da2e34283d
Child:
85:022bba13c5c4
--- a/RA8875_Touch.cpp	Tue Dec 30 23:45:37 2014 +0000
+++ b/RA8875_Touch.cpp	Thu Jan 01 20:35:37 2015 +0000
@@ -3,6 +3,9 @@
 
 #include "RA8875.h"
 
+#define NOTOUCH_TIMEOUT_uS 100000
+#define TOUCH_TICKER_uS      1000
+
 // ### Touch Panel support code additions begin here
 
 RetCode_t RA8875::TouchPanelInit(void)
@@ -13,6 +16,11 @@
     WriteCommand(TPCR1, TP_MODE_DEFAULT | TP_DEBOUNCE_DEFAULT);
     WriteCommand(INTC1, ReadCommand(INTC1) | RA8875_INT_TP);        // reg INTC1: Enable Touch Panel Interrupts (D2 = 1)
     WriteCommand(INTC2, RA8875_INT_TP);                            // reg INTC2: Clear any TP interrupt flag
+    touchSample = 0;
+    touchState = no_cal;
+    touchTicker.attach_us(this, &RA8875::_TouchTicker, TOUCH_TICKER_uS);
+    touchTimer.start();
+    touchTimer.reset();
     return noerror;
 }
 
@@ -34,6 +42,16 @@
     // Set up the interrupt flag and enable bits
     WriteCommand(INTC1, ReadCommand(INTC1) | RA8875_INT_TP);        // reg INTC1: Enable Touch Panel Interrupts (D2 = 1)
     WriteCommand(INTC2, RA8875_INT_TP);                            // reg INTC2: Clear any TP interrupt flag
+    touchSample = 0;
+    touchState = no_cal;
+    if (bTpEnable == TP_ENABLE) {
+        touchTicker.attach_us(this, &RA8875::_TouchTicker, TOUCH_TICKER_uS);
+        touchTimer.start();
+        touchTimer.reset();
+    } else {
+        touchTicker.detach();
+        touchTimer.stop();
+    }
     return noerror;
 }
 
@@ -60,8 +78,10 @@
 {
     point_t pTest[3];
     point_t pSample[3];
-    loc_t x,y;
+    int x,y;
     
+    while (TouchPanelA2DFiltered(&x, &y))
+        wait_ms(20);
     cls();
     if (msg)
         puts(msg);
@@ -145,32 +165,32 @@
  *  operations to scale results by a factor of 2 or even 4.  
  *
  */
-bool RA8875::TouchPanelReadable(point_t * TouchPoint)
+TouchCode_t RA8875::TouchPanelReadable(point_t * TouchPoint)
 {
-    bool touched = false;
-    point_t screenpoint = {0, 0};
+    int a2dX = 0;
+    int a2dY = 0;
     
-    if (TouchPanelA2DFiltered(&screenpoint.x, &screenpoint.y)) {
-        touched = true;
+    TouchCode_t ts = TouchPanelA2DFiltered(&a2dX, &a2dY);
+    if (ts != no_touch) {
         if (tpMatrix.Divider != 0 && TouchPoint) {
             /* Operation order is important since we are doing integer */
             /*  math. Make sure you add all terms together before      */
             /*  dividing, so that the remainder is not rounded off     */
             /*  prematurely.                                           */
-            TouchPoint->x = ( (tpMatrix.An * screenpoint.x) +
-                              (tpMatrix.Bn * screenpoint.y) +
+            TouchPoint->x = ( (tpMatrix.An * a2dX) +
+                              (tpMatrix.Bn * a2dY) +
                               tpMatrix.Cn
                             ) / tpMatrix.Divider ;
 
-            TouchPoint->y = ( (tpMatrix.Dn * screenpoint.x) +
-                              (tpMatrix.En * screenpoint.y) +
+            TouchPoint->y = ( (tpMatrix.Dn * a2dX) +
+                              (tpMatrix.En * a2dY) +
                               tpMatrix.Fn
                             ) / tpMatrix.Divider ;
         } else {
-            touched = false;
+            ts = no_cal;
         }
     }
-    return touched;
+    return ts;
 }
 
 
@@ -179,27 +199,76 @@
     if (matrixPtr == NULL || matrixPtr->Divider == 0)
         return bad_parameter;
     memcpy(&tpMatrix, matrixPtr, sizeof(tpMatrix_t));
+    touchState = no_touch;
     return noerror;
 }
 
 
-bool RA8875::TouchPanelA2DFiltered(loc_t *x, loc_t *y)
+static void InsertionSort(int * buf, int bufsize)
+{
+    int i, j;
+    int temp;
+    
+    for(i = 1; i <= bufsize; i++) {
+        temp = buf[i];
+        j = i;
+        while( j && (buf[j-1] > temp) ) {
+            buf[j] = buf[j-1];
+            j = j-1;
+        }
+        buf[j] = temp;
+    } // End of sort
+}
+
+
+void RA8875::_TouchTicker(void)
 {
-    unsigned char touchready;
-    static int xbuf[TPBUFSIZE], ybuf[TPBUFSIZE], sample = 0;
-    int i, j, temp;
+    if (touchTimer.read_us() > NOTOUCH_TIMEOUT_uS) {
+        touchSample = 0;
+        if (touchState == held)
+            touchState = release;
+        else
+            touchState = no_touch;
+        touchTimer.reset();
+    }
+}
+
+TouchCode_t RA8875::TouchPanelA2DRaw(int *x, int *y)
+{
+    if( (ReadCommand(INTC2) & RA8875_INT_TP) ) {        // Test for TP Interrupt pending in register INTC2
+        touchTimer.reset();
+        *y = ReadCommand(TPYH) << 2 | ( (ReadCommand(TPXYL) & 0xC) >> 2 );   // D[9:2] from reg TPYH, D[1:0] from reg TPXYL[3:2]
+        *x = ReadCommand(TPXH) << 2 | ( (ReadCommand(TPXYL) & 0x3)      );   // D[9:2] from reg TPXH, D[1:0] from reg TPXYL[1:0]
+        WriteCommand(INTC2, RA8875_INT_TP);            // reg INTC2: Clear that TP interrupt flag
+        touchState = touch;
+    } else {
+        touchState = no_touch;
+    }
+    return touchState;
+}
+
+TouchCode_t RA8875::TouchPanelA2DFiltered(int *x, int *y)
+{
+    static int xbuf[TPBUFSIZE], ybuf[TPBUFSIZE];
+    static int lastX, lastY;
+    int i, j;
+    TouchCode_t ret = touchState;
 
     if( (ReadCommand(INTC2) & RA8875_INT_TP) ) {        // Test for TP Interrupt pending in register INTC2
+        touchTimer.reset();
         // Get the next data samples
-        ybuf[sample] =  ReadCommand(TPYH) << 2 | ( (ReadCommand(TPXYL) & 0xC) >> 2 );   // D[9:2] from reg TPYH, D[1:0] from reg TPXYL[3:2]
-        xbuf[sample] =  ReadCommand(TPXH) << 2 | ( (ReadCommand(TPXYL) & 0x3)      );   // D[9:2] from reg TPXH, D[1:0] from reg TPXYL[1:0]
+        ybuf[touchSample] =  ReadCommand(TPYH) << 2 | ( (ReadCommand(TPXYL) & 0xC) >> 2 );   // D[9:2] from reg TPYH, D[1:0] from reg TPXYL[3:2]
+        xbuf[touchSample] =  ReadCommand(TPXH) << 2 | ( (ReadCommand(TPXYL) & 0x3)      );   // D[9:2] from reg TPXH, D[1:0] from reg TPXYL[1:0]
         // Check for a complete set
-        if(++sample == TPBUFSIZE) {
+        if(++touchSample == TPBUFSIZE) {
             // Buffers are full, so process them using Finn's method described in Analog Dialogue No. 44, Feb 2010
             // This requires sorting the samples in order of size, then discarding the top 25% and
             //   bottom 25% as noise spikes. Finally, the middle 50% of the values are averaged to
             //   reduce Gaussian noise.
-
+#if 1
+            InsertionSort(ybuf, TPBUFSIZE);
+            InsertionSort(xbuf, TPBUFSIZE);
+#else
             // Sort the Y buffer using an Insertion Sort
             for(i = 1; i <= TPBUFSIZE; i++) {
                 temp = ybuf[i];
@@ -220,44 +289,49 @@
                 }
                 xbuf[j] = temp;
             } // End of X sort
+#endif
             // Average the middle half of the  Y values and report them
             j = 0;
             for(i = (TPBUFSIZE/4) - 1; i < TPBUFSIZE - TPBUFSIZE/4; i++ ) {
                 j += ybuf[i];
             }
-            *y = j * (float)2/TPBUFSIZE;    // This is the average
+            *y = lastY = j * (float)2/TPBUFSIZE;    // This is the average
             // Average the middle half of the  X values and report them
             j = 0;
             for(i = (TPBUFSIZE/4) - 1; i < TPBUFSIZE - TPBUFSIZE/4; i++ ) {
                 j += xbuf[i];
             }
-            *x = j * (float)2/TPBUFSIZE;    // This is the average
+            *x = lastX = j * (float)2/TPBUFSIZE;    // This is the average
             // Tidy up and return
-            touchready = 1;
-            sample = 0;             // Ready to start on the next set of data samples
+            if (touchState == touch || touchState == held)
+                touchState = held;
+            else
+                touchState = touch;
+            ret = touchState;
+            touchSample = 0;             // Ready to start on the next set of data samples
         } else {
             // Buffer not yet full, so do not return any results yet
-            touchready = 0;
+            if (touchState == touch || touchState == held) {
+                *x = lastX;
+                *y = lastY;
+                ret = touchState = held;
+            }
         }
         WriteCommand(INTC2, RA8875_INT_TP);            // reg INTC2: Clear that TP interrupt flag
     } // End of initial if -- data has been read and processed
-    else
-        touchready = 0;         // Touch Panel "Int" was not set
-    return touchready;
-}
-
-bool RA8875::TouchPanelA2DRaw(loc_t *x, loc_t *y)
-{
-    unsigned char touchready;
-
-    if( (ReadCommand(INTC2) & RA8875_INT_TP) ) {        // Test for TP Interrupt pending in register INTC2
-        *y =  ReadCommand(TPYH) << 2 | ( (ReadCommand(TPXYL) & 0xC) >> 2 );   // D[9:2] from reg TPYH, D[1:0] from reg TPXYL[3:2]
-        *x =  ReadCommand(TPXH) << 2 | ( (ReadCommand(TPXYL) & 0x3)      );   // D[9:2] from reg TPXH, D[1:0] from reg TPXYL[1:0]
-        WriteCommand(INTC2, RA8875_INT_TP);            // reg INTC2: Clear that TP interrupt flag
-        touchready = 1;
-    } else
-        touchready = 0;
-    return touchready;
+    else {
+        if (touchState == touch || touchState == held) {
+            *x = lastX;
+            *y = lastY;
+            ret = touchState = held;
+        } else if (touchState == release) {
+            *x = lastX;
+            *y = lastY;
+            ret = release;
+            touchState = no_touch;
+        }
+    }
+    return ret;
 }
 
 /*   The following section is derived from Carlos E. Vidales.
@@ -451,6 +525,7 @@
         tpMatrix.Fn = (screenPtr[2].x * displayPtr[1].y - screenPtr[1].x * displayPtr[2].y) * screenPtr[0].y +
                       (screenPtr[0].x * displayPtr[2].y - screenPtr[2].x * displayPtr[0].y) * screenPtr[1].y +
                       (screenPtr[1].x * displayPtr[0].y - screenPtr[0].x * displayPtr[1].y) * screenPtr[2].y ;
+        touchState = no_touch;
         if (matrixPtr)
             memcpy(matrixPtr, &tpMatrix, sizeof(tpMatrix_t));
     }