Guillermo Stedile / RA8875

Dependencies:   GPS

Dependents:   SNOCC_V1 SNOCC_V2

Fork of RA8875 by SNOCC

Files at this revision

API Documentation at this revision

Comitter:
WiredHome
Date:
Thu Jan 01 20:35:37 2015 +0000
Parent:
82:f7d300f26540
Child:
84:e102021864b5
Commit message:
Improve touch interface to automatically provide no_touch, touch, held, release, no_cal value.; Touch API return codes were modified to accommodate this.; Enhance some APIs with (point_t p) parameters.; Minor internal documentation improvement.

Changed in this revision

DisplayDefs.h Show annotated file Show diff for this revision Revisions of this file
RA8875.cpp Show annotated file Show diff for this revision Revisions of this file
RA8875.h Show annotated file Show diff for this revision Revisions of this file
RA8875_Touch.cpp Show annotated file Show diff for this revision Revisions of this file
--- a/DisplayDefs.h	Tue Dec 30 23:45:37 2014 +0000
+++ b/DisplayDefs.h	Thu Jan 01 20:35:37 2015 +0000
@@ -21,6 +21,17 @@
     LastErrCode,            // Private marker.
 } RetCode_t;
 
+/// return values from TouchPanelReadable, TouchPanelA2DRaw, TouchPanelA2DFiltered.
+/// @see TouchPanelReadable.
+typedef enum
+{
+    no_touch,               ///< no touch is detected
+    touch,                  ///< touch is detected
+    held,                   ///< held after touch
+    release,                ///< release is detected
+    no_cal,                 ///< no calibration matrix is available
+} TouchCode_t;
+
 /// type that manages locations, which is typically an x or y pixel location,
 /// which can range from -N to +N (even if the screen is 0 to +n). @see textloc_t.
 typedef int16_t loc_t;
--- a/RA8875.cpp	Tue Dec 30 23:45:37 2014 +0000
+++ b/RA8875.cpp	Thu Jan 01 20:35:37 2015 +0000
@@ -418,20 +418,8 @@
 
 RetCode_t RA8875::WriteCommandW(uint8_t command, uint16_t data)
 {
-#if 1
     WriteCommand(command, data & 0xFF);
     WriteCommand(command+1, data >> 8);
-#else
-    // This should be a little faster, but doesn't work...
-    INFO("WriteCommandW(%02X, %04X)", command, data);
-    _select(true);
-    _spiwrite(0x80);
-    _spiwrite(command);
-    //_spiwrite(0x00);     // dummy
-    _spiwrite(data & 0xFF);
-    _spiwrite(data >> 8);
-    _select(false);
-#endif
     return noerror;
 }
 
@@ -439,7 +427,7 @@
 RetCode_t RA8875::WriteCommand(unsigned char command, unsigned int data)
 {
     _select(true);
-    _spiwrite(0x80);         // cmd: write command
+    _spiwrite(0x80);            // RS:1 (Cmd/Status), RW:0 (Write)
     _spiwrite(command);
     if (data <= 0xFF) {   // only if in the valid range
         _spiwrite(0x00);
@@ -453,7 +441,7 @@
 RetCode_t RA8875::WriteDataW(uint16_t data)
 {
     _select(true);
-    _spiwrite(0x00);         // cmd: write data
+    _spiwrite(0x00);            // RS:0 (Data), RW:0 (Write)
     _spiwrite(data & 0xFF);
     _spiwrite(data >> 8);
     _select(false);
@@ -464,7 +452,7 @@
 RetCode_t RA8875::WriteData(unsigned char data)
 {
     _select(true);
-    _spiwrite(0x00);
+    _spiwrite(0x00);            // RS:0 (Data), RW:0 (Write)
     _spiwrite(data);
     _select(false);
     return noerror;
@@ -483,7 +471,7 @@
     unsigned char data;
 
     _select(true);
-    _spiwrite(0x40);
+    _spiwrite(0x40);            // RS:0 (Data), RW:1 (Read)
     data = _spiread();
     _select(false);
     return data;
@@ -495,7 +483,7 @@
     uint16_t data;
 
     _select(true);
-    _spiwrite(0x40);
+    _spiwrite(0x40);            // RS:0 (Data), RW:1 (Read)
     data  = _spiread();
     data |= (_spiread() << 8);
     _select(false);
@@ -508,7 +496,7 @@
     unsigned char data;
 
     _select(true);
-    _spiwrite(0xC0);         // These two bits are for the special "Status Read" [STSR]
+    _spiwrite(0xC0);            // RS:1 (Cmd/Status), RW:1 (Read) (Read STSR)
     data = _spiread();
     _select(false);
     return data;
@@ -1019,6 +1007,18 @@
 }
 
 
+RetCode_t RA8875::line(point_t p1, point_t p2)
+{
+    return line(p1.x, p1.y, p2.x, p2.y);
+}
+
+
+RetCode_t RA8875::line(point_t p1, point_t p2, color_t color)
+{
+    return line(p1.x, p1.y, p2.x, p2.y, color);
+}
+
+
 RetCode_t RA8875::line(loc_t x1, loc_t y1, loc_t x2, loc_t y2, color_t color)
 {
     foreground(color);
@@ -1196,6 +1196,29 @@
     return ret;
 }
 
+
+RetCode_t RA8875::circle(point_t p, dim_t radius,
+                         color_t color, fill_t fillit)
+{
+    foreground(color);
+    return circle(p.x,p.y,radius,fillit);
+}
+
+
+RetCode_t RA8875::fillcircle(point_t p, dim_t radius,
+                             color_t color, fill_t fillit)
+{
+    foreground(color);
+    return circle(p.x,p.y,radius,fillit);
+}
+
+
+RetCode_t RA8875::circle(point_t p, dim_t radius, fill_t fillit)
+{
+    return circle(p.x,p.y,radius,fillit);
+}
+
+
 RetCode_t RA8875::circle(loc_t x, loc_t y, dim_t radius,
                          color_t color, fill_t fillit)
 {
--- a/RA8875.h	Tue Dec 30 23:45:37 2014 +0000
+++ b/RA8875.h	Thu Jan 01 20:35:37 2015 +0000
@@ -468,9 +468,14 @@
     /// 
     /// @param[out] x is the x scale a/d value.
     /// @param[out] y is the y scale a/d value.
-    /// @returns true if touch was detected, in which case the x and y values were set.
+    /// @returns a value indicating the state of the touch,
+    ///         - no_cal:   no calibration matrix is available, touch coordinates are not returned.
+    ///         - no_touch: no touch is detected, touch coordinates are not returned.
+    ///         - touch:    touch is detected, touch coordinates are returned.
+    ///         - held:     held after touch, touch coordinates are returned.
+    ///         - release:  indicates a release, touch coordinates are returned.
     ///
-    bool TouchPanelA2DFiltered(loc_t *x, loc_t *y);
+    TouchCode_t TouchPanelA2DFiltered(int *x, int *y);
 
     /// Poll the TouchPanel and on a touch event return the a to d raw x, y coordinates.
     ///
@@ -486,10 +491,45 @@
     /// 
     /// @param[out] x is the x scale a/d value.
     /// @param[out] y is the y scale a/d value.
-    /// @returns true if touch was detected, in which case the x and y values were set.
+    /// @returns a value indicating the state of the touch,
+    ///         - no_cal:   no calibration matrix is available, touch coordinates are not returned.
+    ///         - no_touch: no touch is detected, touch coordinates are not returned.
+    ///         - touch:    touch is detected, touch coordinates are returned.
+    ///         - held:     held after touch, touch coordinates are returned.
+    ///         - release:  indicates a release, touch coordinates are returned.
+    ///
+    TouchCode_t TouchPanelA2DRaw(int *x, int *y);
+    
+    /// Get the screen calibrated point of touch.
+    ///
+    /// This method determines if there is a touch and if so it will provide
+    /// the screen-relative touch coordinates. This method can be used in
+    /// a manner similar to Serial.readable(), to determine if there was a 
+    /// touch and indicate that - but not care about the coordinates. Alternately,
+    /// if a valid pointer to a point_t is provided, then if a touch is detected
+    /// the point_t will be populated with data. 
     ///
-    bool TouchPanelA2DRaw(loc_t *x, loc_t *y);
-    
+    /// @code
+    ///     Timer t;
+    ///     t.start();
+    ///     do {
+    ///        point_t point = {0, 0};
+    ///        if (display.TouchPanelReadable(&point)) {
+    ///            display.pixel(point.x, point.y, Red);
+    ///        }
+    ///    } while (t.read_ms() < 30000);
+    /// @endcode
+    ///
+    /// @param[out] touch is the touch point, if a touch is registered.
+    /// @returns a value indicating the state of the touch,
+    ///         - no_cal:   no calibration matrix is available, touch coordinates are not returned.
+    ///         - no_touch: no touch is detected, touch coordinates are not returned.
+    ///         - touch:    touch is detected, touch coordinates are returned.
+    ///         - held:     held after touch, touch coordinates are returned.
+    ///         - release:  indicates a release, touch coordinates are returned.
+    ///
+    TouchCode_t TouchPanelReadable(point_t * touch = NULL);
+
     /// Calibrate the touch panel.
     ///
     /// This method accepts two lists - one list is target points in ,
@@ -569,32 +609,6 @@
     ///
     RetCode_t TouchPanelCalibrate(const char * msg, tpMatrix_t * matrix = NULL);
 
-    /// Get the screen calibrated point of touch.
-    ///
-    /// This method determines if there is a touch and if so it will provide
-    /// the screen-relative touch coordinates. This method can be used in
-    /// a manner similar to Serial.readable(), to determine if there was a 
-    /// touch and indicate that - but not care about the coordinates. Alternately,
-    /// if a valid pointer to a point_t is provided, then if a touch is detected
-    /// the point_t will be populated with data. 
-    ///
-    /// @code
-    ///     Timer t;
-    ///     t.start();
-    ///     do {
-    ///        point_t point = {0, 0};
-    ///        if (display.TouchPanelReadable(&point)) {
-    ///            display.pixel(point.x, point.y, Red);
-    ///        }
-    ///    } while (t.read_ms() < 30000);
-    /// @endcode
-    ///
-    /// @param[out] touch is the touch point, if a touch is registered.
-    /// @returns true if a touch was registered, and touch is updated.
-    /// @returns false if no touch was detected, or if the calibration matrix is not defined.
-    ///
-    bool TouchPanelReadable(point_t * touch = NULL);
-
     /// Wait for a touch panel touch and return it.
     /// 
     /// This method is similar to Serial.getc() in that it will wait for a touch
@@ -1204,6 +1218,28 @@
     /// @note As a side effect, this changes the current
     ///     foreground color for subsequent operations.
     ///
+    /// @param[in] p1 is the point to start the line.
+    /// @param[in] p2 is the point to end the line.
+    /// @param[in] color defines the foreground color.
+    /// @returns success/failure code. @see RetCode_t.
+    ///
+    RetCode_t line(point_t p1, point_t p2, color_t color);
+
+    /// Draw a line
+    ///
+    /// Draws a line using the foreground color setting.
+    ///
+    /// @param[in] p1 is the point to start the line.
+    /// @param[in] p2 is the point to end the line.
+    /// @returns success/failure code. @see RetCode_t.
+    ///
+    RetCode_t line(point_t p1, point_t p2);
+    
+    /// Draw a line in the specified color
+    ///
+    /// @note As a side effect, this changes the current
+    ///     foreground color for subsequent operations.
+    ///
     /// @param[in] x1 is the horizontal start of the line.
     /// @param[in] y1 is the vertical start of the line.
     /// @param[in] x2 is the horizontal end of the line.
@@ -1424,6 +1460,41 @@
     RetCode_t triangle(loc_t x1, loc_t y1, loc_t x2, loc_t y2, 
         loc_t x3, loc_t y3, fill_t fillit = NOFILL);
     
+
+    /// Draw a circle using the specified color.
+    ///
+    /// @note As a side effect, this changes the current
+    ///     foreground color for subsequent operations.
+    ///
+    /// @param[in] p defines the center of the circle.
+    /// @param[in] radius defines the size of the circle.
+    /// @param[in] color defines the foreground color.
+    /// @returns success/failure code. @see RetCode_t.
+    ///
+    RetCode_t circle(point_t p, dim_t radius, color_t color, fill_t fillit = NOFILL);
+
+    /// Draw a filled circle using the specified color.
+    ///
+    /// @note As a side effect, this changes the current
+    ///     foreground color for subsequent operations.
+    ///
+    /// @param[in] p defines the center of the circle.
+    /// @param[in] radius defines the size of the circle.
+    /// @param[in] color defines the foreground color.
+    /// @returns success/failure code. @see RetCode_t.
+    ///
+    RetCode_t fillcircle(point_t p, dim_t radius, color_t color, fill_t fillit = FILL);
+
+    /// Draw a circle.
+    ///
+    /// Draws a circle using the foreground color setting.
+    ///
+    /// @param[in] p defines the center of the circle.
+    /// @param[in] radius defines the size of the circle.
+    /// @returns success/failure code. @see RetCode_t.
+    ///
+    RetCode_t circle(point_t p, dim_t radius, fill_t fillit = NOFILL);
+
     /// Draw a circle using the specified color.
     ///
     /// @note As a side effect, this changes the current
@@ -1720,6 +1791,27 @@
     /// Other Touch Panel params
     #define TPBUFSIZE   16       // Depth of the averaging buffers for x and y data
 
+    // Needs both a ticker and a timer. (could have created a timer from the ticker, but this is easier).
+    // on a touch, the timer is reset.
+    // the ticker monitors the timer to see if it has been a long time since
+    // a touch, and if so, it then clears the sample counter so it doesn't get partial old
+    // and partial new.
+    
+    /// Touch State used by TouchPanelReadable. @see TouchCode_t.
+    TouchCode_t touchState;
+
+    /// Touch Panel ticker
+    Ticker touchTicker;
+    
+    /// Touch Panel timer
+    Timer touchTimer;
+    
+    /// keeps track of which sample we're collecting to filter out the noise.
+    int touchSample;
+    
+    /// Private function for touch ticker callback.
+    void _TouchTicker(void);
+    
     /// Touch Panel calibration matrix.
     tpMatrix_t tpMatrix;
 
@@ -1842,7 +1934,6 @@
 //     /__/      /_____________/ /_____________/       /__/
 
 #include "WebColors.h"
-#include "Arial12x12.h"
 #include <algorithm>
 
 extern "C" void mbed_reset();
--- 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));
     }