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)

Files at this revision

API Documentation at this revision

Comitter:
WiredHome
Date:
Thu Apr 30 13:51:32 2020 +0000
Parent:
201:0b25d24d9bda
Child:
203:704df2dbd3e6
Commit message:
Private max,min macros; avoid collision with other libs.; Correct jpg rendering defect; window() to SetWindow().; Coordinate translation for touch with orientation.; Added method; get rendered rect_t for string.; Fix for the reset pin option.;

Changed in this revision

GraphicsDisplay.cpp Show annotated file Show diff for this revision Revisions of this file
GraphicsDisplayJPEG.cpp 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
RA8875_Touch_FT5206.cpp Show annotated file Show diff for this revision Revisions of this file
RA8875_Touch_GSL1680.cpp Show annotated file Show diff for this revision Revisions of this file
--- a/GraphicsDisplay.cpp	Sun Mar 29 18:12:24 2020 +0000
+++ b/GraphicsDisplay.cpp	Thu Apr 30 13:51:32 2020 +0000
@@ -142,8 +142,8 @@
         windowrect.p1.y = y1;
         windowrect.p2.x = x2;
         windowrect.p2.y = y2;
-        tempWidth = max(virt_screenwidth, virt_screenheight);
-        tempHeight = min(virt_screenwidth, virt_screenheight);
+        tempWidth = RAmax(virt_screenwidth, virt_screenheight);
+        tempHeight = RAmin(virt_screenwidth, virt_screenheight);
         virt_screenwidth = tempWidth;
         virt_screenheight = tempHeight;
         //GraphicsDisplay::SetWindow(x1, y1, x2, y2);
@@ -158,8 +158,8 @@
         windowrect.p1.y = x1;
         windowrect.p2.x = y2;
         windowrect.p2.y = x2;
-        tempWidth = min(virt_screenwidth, virt_screenheight);
-        tempHeight = max(virt_screenwidth, virt_screenheight);
+        tempWidth = RAmin(virt_screenwidth, virt_screenheight);
+        tempHeight = RAmax(virt_screenwidth, virt_screenheight);
         virt_screenwidth = tempWidth;
         virt_screenheight = tempHeight;
         //GraphicsDisplay::SetWindow(x1, y1, x2, y2);
--- a/GraphicsDisplayJPEG.cpp	Sun Mar 29 18:12:24 2020 +0000
+++ b/GraphicsDisplayJPEG.cpp	Thu Apr 30 13:51:32 2020 +0000
@@ -854,7 +854,7 @@
     } while (--pCount);
     #endif
     //
-    rect_t oldWin = SetWindow(x0+img_x, y0+img_y, x0 + img_x + w - 1, y0 + img_y + y1 - y0 );
+    rect_t oldWin = SetWindow(x0 + img_x, y0 + img_y, x0 + img_x + w - 1, y0 + img_y + y1 - y0 - 0);
     uint16_t *src = (uint16_t *)bitmap;     // pointer to RGB565 format
     pixelStream(src, pixelCount, x0+img_x, y0+img_y);
     SetWindow(oldWin);
--- a/RA8875.cpp	Sun Mar 29 18:12:24 2020 +0000
+++ b/RA8875.cpp	Thu Apr 30 13:51:32 2020 +0000
@@ -736,8 +736,8 @@
 
 bool RA8875::Intersect(rect_t rect, point_t p)
 {
-    if (p.x >= min(rect.p1.x, rect.p2.x) && p.x <= max(rect.p1.x, rect.p2.x)
-    && p.y >= min(rect.p1.y, rect.p2.y) && p.y <= max(rect.p1.y, rect.p2.y))
+    if (p.x >= RAmin(rect.p1.x, rect.p2.x) && p.x <= RAmax(rect.p1.x, rect.p2.x)
+    && p.y >= RAmin(rect.p1.y, rect.p2.y) && p.y <= RAmax(rect.p1.y, rect.p2.y))
         return true;
     else
         return false;
@@ -748,12 +748,12 @@
 {
 #if 1
     // If one rectangle is on left side of other
-    if (max(rect1.p1.x,rect1.p2.x) < min(rect2.p1.x,rect2.p2.x)
-        || min(rect1.p1.x, rect1.p2.x) > max(rect2.p1.x, rect2.p2.x))
+    if (RAmax(rect1.p1.x,rect1.p2.x) < RAmin(rect2.p1.x,rect2.p2.x)
+        || RAmin(rect1.p1.x, rect1.p2.x) > RAmax(rect2.p1.x, rect2.p2.x))
         return false;
     // If one rectangle is above other
-    if (max(rect1.p1.y, rect1.p2.y) < min(rect2.p1.y, rect2.p2.y)
-        || min(rect1.p1.y, rect1.p2.y) > max(rect2.p1.y, rect2.p2.y))
+    if (RAmax(rect1.p1.y, rect1.p2.y) < RAmin(rect2.p1.y, rect2.p2.y)
+        || RAmin(rect1.p1.y, rect1.p2.y) > RAmax(rect2.p1.y, rect2.p2.y))
         return false;
     return true;            // all that's left is they overlap
 #else
@@ -776,10 +776,10 @@
     if (Intersect(*pRect1, *pRect2)) {
         rect_t iSect;
 
-        iSect.p1.x = max(min(pRect1->p1.x,pRect1->p2.x),min(pRect2->p1.x,pRect2->p2.x));
-        iSect.p1.y = max(min(pRect1->p1.y,pRect1->p2.y),min(pRect2->p1.y,pRect2->p2.y));
-        iSect.p2.x = min(max(pRect1->p1.x,pRect1->p2.x),max(pRect2->p1.x,pRect2->p2.x));
-        iSect.p2.y = min(max(pRect1->p1.y,pRect1->p2.y),max(pRect2->p1.y,pRect2->p2.y));
+        iSect.p1.x = RAmax(RAmin(pRect1->p1.x,pRect1->p2.x),RAmin(pRect2->p1.x,pRect2->p2.x));
+        iSect.p1.y = RAmax(RAmin(pRect1->p1.y,pRect1->p2.y),RAmin(pRect2->p1.y,pRect2->p2.y));
+        iSect.p2.x = RAmin(RAmax(pRect1->p1.x,pRect1->p2.x),RAmax(pRect2->p1.x,pRect2->p2.x));
+        iSect.p2.y = RAmin(RAmax(pRect1->p1.y,pRect1->p2.y),RAmax(pRect2->p1.y,pRect2->p2.y));
         *pRect1 = iSect;
         return true;
     } else {
@@ -1073,20 +1073,23 @@
 point_t RA8875::SetTextCursor(loc_t x, loc_t y)
 {
     point_t oldCursor = GetTextCursor();
-    cursor_x = x;     // set these values for non-internal fonts
-    cursor_y = y;
-    switch (screen_orientation) {
-    default:
-    case rotate_0:
-    case rotate_180:
-        WriteCommandW(RA8875_FCURXL, x);
-        WriteCommandW(RA8875_FCURYL, y);
-        break;
-    case rotate_90:
-    case rotate_270:
-        WriteCommandW(RA8875_FCURXL, y);
-        WriteCommandW(RA8875_FCURYL, x);
-        break;
+    if (x >= 0 && x <= virt_screenwidth
+        && y >= 0 && y <= virt_screenheight) {
+        cursor_x = x;     // set these values for non-internal fonts
+        cursor_y = y;
+        switch (screen_orientation) {
+            default:
+            case rotate_0:
+            case rotate_180:
+                WriteCommandW(RA8875_FCURXL, x);
+                WriteCommandW(RA8875_FCURYL, y);
+                break;
+            case rotate_90:
+            case rotate_270:
+                WriteCommandW(RA8875_FCURXL, y);
+                WriteCommandW(RA8875_FCURYL, x);
+                break;
+        }
     }
     return oldCursor;
 }
@@ -1186,6 +1189,32 @@
     }
 }
 
+point_t RA8875::TranslateOrientation(loc_t x, loc_t y) {
+    point_t pt;
+
+    switch (screen_orientation) {
+        default:
+        case rotate_0:
+            pt.x = x;
+            pt.y = y;
+            break;
+        case rotate_90:
+            pt.x = y;
+            pt.y = x;
+            break;
+        case rotate_180:
+            pt.x = virt_screenwidth - 1 - x;
+            pt.y = virt_screenheight - 1 - y;
+            break;
+        case rotate_270:
+            pt.x = virt_screenheight - 1 - y;
+            pt.y = virt_screenwidth - 1 - x;
+            break;
+    }
+    return pt;
+}
+
+
 orientation_t RA8875::GetGraphicsOrientation()
 {
     return screen_orientation;
@@ -1205,29 +1234,29 @@
     switch (angle) {
         case normal:
             //dpcrVal |= 0x00;
-            tempWidth = max(virt_screenwidth, virt_screenheight);
-            tempHeight = min(virt_screenwidth, virt_screenheight);
+            tempWidth = RAmax(virt_screenwidth, virt_screenheight);
+            tempHeight = RAmin(virt_screenwidth, virt_screenheight);
             break;
         case rotate_90:
             dpcrVal |= 0x08;
             mwcr0 |= 0x08;
             mrcd |= 0x02;
-            tempWidth = min(virt_screenwidth, virt_screenheight);
-            tempHeight = max(virt_screenwidth, virt_screenheight);
+            tempWidth = RAmin(virt_screenwidth, virt_screenheight);
+            tempHeight = RAmax(virt_screenwidth, virt_screenheight);
             break;
         case rotate_180:
             dpcrVal |= 0x0C;
             //mwcr0 |= 0x00;
             //mrcd |= 0x00;
-            tempWidth = max(virt_screenwidth, virt_screenheight);
-            tempHeight = min(virt_screenwidth, virt_screenheight);
+            tempWidth = RAmax(virt_screenwidth, virt_screenheight);
+            tempHeight = RAmin(virt_screenwidth, virt_screenheight);
             break;
         case rotate_270:
             dpcrVal |= 0x04;
             mwcr0 |= 0x08;
             mrcd |= 0x02;
-            tempWidth = min(virt_screenwidth, virt_screenheight);
-            tempHeight = max(virt_screenwidth, virt_screenheight);
+            tempWidth = RAmin(virt_screenwidth, virt_screenheight);
+            tempHeight = RAmax(virt_screenwidth, virt_screenheight);
             break;
         default:
             return invalid;
@@ -1264,6 +1293,7 @@
         return invalid;
     }
     WriteCommand(RA8875_FNCR1, fncr1Val);
+    text_orientation = angle;
     return oldAngle;
 }
 
@@ -1355,6 +1385,58 @@
     }
 }
 
+rect_t RA8875::GetTextRect(const char* text, bool charOnly) {
+    rect_t rect = { 0, 0, 0, 0 };
+
+    if (charOnly) {
+        if (font == NULL) {
+            rect.p2.x = fontwidth();
+            rect.p2.y = fontheight();
+        } else {
+            dim_t cWidth, cHeight;
+            if (getCharMetrics(*text, &cWidth, &cHeight)) {
+                rect.p2.x = cWidth;
+                rect.p2.y = cHeight;
+            }
+        }
+    } else {
+        rect.p2.y = fontheight();
+        const char* p = text;
+        dim_t curX = 0;
+        while (*p) {
+            rect_t cRect = GetTextRect(p, true);
+            switch (*p) {
+                case '\r':
+                    curX = 0;
+                    break;
+                case '\n':
+                    rect.p2.y += cRect.p2.y;
+                    break;
+                default:
+                    if ((curX + cRect.p2.x) >= virt_screenwidth) {
+                        rect.p2.x = virt_screenwidth - 1;
+                        curX = cRect.p2.x;
+                        if ((rect.p2.y + cRect.p2.y) > virt_screenheight) {
+                            rect.p2.y = virt_screenheight - 1;
+                        } else {
+                            rect.p2.y += cRect.p2.y;
+                        }
+                    } else {
+                        curX += cRect.p2.x;
+                        if (curX > rect.p2.x)
+                            rect.p2.x = curX;
+                    }
+                    break;
+            }
+            if (rect.p2.y >= virt_screenheight - 1)
+                break;
+            p++;
+        }
+    }
+    return rect;
+}
+
+
 int RA8875::_putc(int c)
 {
     if (font == NULL) {
@@ -1649,8 +1731,8 @@
     switch (screen_orientation) {
     case rotate_0:
     case rotate_180:
-        tempWidth = max(virt_screenwidth, virt_screenheight);
-        tempHeight = min(virt_screenwidth, virt_screenheight);
+        tempWidth = RAmax(virt_screenwidth, virt_screenheight);
+        tempHeight = RAmin(virt_screenwidth, virt_screenheight);
         virt_screenwidth = tempWidth;
         virt_screenheight = tempHeight;
         //GraphicsDisplay::SetWindow(x1, y1, x2, y2);
@@ -1661,8 +1743,8 @@
         break;
     case rotate_90:
     case rotate_270:
-        tempWidth = min(virt_screenwidth, virt_screenheight);
-        tempHeight = max(virt_screenwidth, virt_screenheight);
+        tempWidth = RAmin(virt_screenwidth, virt_screenheight);
+        tempHeight = RAmax(virt_screenwidth, virt_screenheight);
         virt_screenwidth = tempWidth;
         virt_screenheight = tempHeight;
         //GraphicsDisplay::SetWindow(x1, y1, x2, y2);
@@ -3569,7 +3651,7 @@
     for (i=0; i<16; i++) {
         x1 = 300 + rand() % 100;
         y1 = 70 + rand() % 200;
-        r1 = rand() % min(y1 - 20, 100);
+        r1 = rand() % RAmin(y1 - 20, 100);
         display.circle(x1,y1,r1, display.DOSColor(i));
         if (!SuppressSlowStuff)
             wait_us(20000);
@@ -3703,13 +3785,13 @@
     for (i=0; i<16; i++) {
         x = 100 + rand() % 100;
         y = 70 + rand() % 200;
-        r1 = rand() % min(y - 20, 100);
+        r1 = rand() % RAmin(y - 20, 100);
         //pc.printf("  (%d,%d) - %d\r\n", x,y,r1);
         display.circle(x,y,r1, display.DOSColor(i));
 
         x = 300 + rand() % 100;
         y = 70 + rand() % 200;
-        r1 = rand() % min(y - 20, 100);
+        r1 = rand() % RAmin(y - 20, 100);
         //pc.printf("  (%d,%d) - %d FILL\r\n", x,y,r1);
         display.circle(x,y,r1, display.DOSColor(i), FILL);
     }
@@ -3729,14 +3811,14 @@
     for (i=0; i<16; i++) {
         x = 100 + rand() % 100;
         y = 70 + rand() % 200;
-        r1 = rand() % min(y - 20, 100);
-        r2 = rand() % min(y - 20, 100);
+        r1 = rand() % RAmin(y - 20, 100);
+        r2 = rand() % RAmin(y - 20, 100);
         display.ellipse(x,y,r1,r2, display.DOSColor(i));
 
         x = 300 + rand() % 100;
         y = 70 + rand() % 200;
-        r1 = rand() % min(y - 20, 100);
-        r2 = rand() % min(y - 20, 100);
+        r1 = rand() % RAmin(y - 20, 100);
+        r2 = rand() % RAmin(y - 20, 100);
         display.ellipse(x,y,r1,r2, FILL);
     }
 }
--- a/RA8875.h	Sun Mar 29 18:12:24 2020 +0000
+++ b/RA8875.h	Thu Apr 30 13:51:32 2020 +0000
@@ -496,8 +496,8 @@
 #define DarkBrown       (color_t)(RGB(63,63,0))
 #define DarkGray        (color_t)(RGB(63,63,63))
 
-#define min(a,b) ((a<b)?a:b)
-#define max(a,b) ((a>b)?a:b)
+#define RAmin(a,b) ((a<b)?a:b)
+#define RAmax(a,b) ((a>b)?a:b)
 
 
 //namespace SW_graphics
@@ -1083,7 +1083,8 @@
     /// @endcode
     ///
     /// @param[out] TouchPoint is a pointer to a point_t, which is set as the touch point,
-    ///             if a touch is registered.
+    ///             if a touch is registered. The coordinate system is based on the
+    ///             graphics orientation (@ref SetGraphicsOrientation(), @ref GetGraphicsOrientation())
     /// @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.
@@ -1741,6 +1742,9 @@
     /// Prepare the controller to write text to the screen by positioning
     /// the cursor.
     ///
+    /// @note If the cursor location is not valid (not on-screen), the
+    ///     cursor is not set and no error is generated.
+    ///
     /// @code
     ///     lcd.SetTextCursor(100, 25);
     ///     lcd.puts("Hello");
@@ -1756,6 +1760,9 @@
     /// Prepare the controller to write text to the screen by positioning
     /// the cursor.
     ///
+    /// @note If the cursor location is not valid (not on-screen), the
+    ///     cursor is not set.
+    ///
     /// @code
     ///     point_t point = {100, 25};
     ///     lcd.SetTextCursor(point);
@@ -1825,6 +1832,16 @@
     RetCode_t SetTextFont(font_t font = ISO8859_1);
 
 
+    /// Translate an (x,y) orientation in the display hardware coordinates
+    /// into (x,y) coordinates given the current orientation.
+    ///
+    /// @param[in] x is the hardware x coordinate
+    /// @param[in] y is the hardware y coordinate
+    /// @returns the translated coordinates as a point
+    ///
+    point_t TranslateOrientation(loc_t x, loc_t y);
+
+
     /// Gets the display orientation
     ///
 
@@ -2027,14 +2044,26 @@
     ///
     RetCode_t GetTextFontSize(HorizontalScale * hScale, VerticalScale * vScale);
 
-    /// put a character on the screen.
+    /// Get the width of a string (or character) based on the current font.
     ///
     /// @param[in] text is a pointer to a text string to evaluate.
     /// @param[in] charOnly defaults to false, which computes over the whole string.
     /// @returns width in pixels, given the selected font and scale.
     ///
-    dim_t GetTextWidth(const char * text, bool charOnly = false);
-
+    dim_t GetTextWidth(const char* text, bool charOnly = false);
+
+    /// Get the rectange of a string (or character) based on the current font.
+    ///
+    /// @note This computes the rect without considering wordwrap. It will
+    ///     treat <cr> as a return to left margin and <lf> as a vertical
+    ///     advance. It will also use the currently selected font metrics,
+    ///     which includes proportional fonts.
+    ///
+    /// @param[in] text is a pointer to a text string to evaluate.
+    /// @param[in] charOnly defaults to false, which computes over the whole string.
+    /// @returns rectangle that holds this text, as a rect_t
+    ///
+    rect_t GetTextRect(const char* text, bool charOnly = false);
 
     /// put a character on the screen.
     ///
@@ -3604,7 +3633,9 @@
     RetCode_t (FPointerDummy::*method_callback)(filecmd_t cmd, uint8_t * buffer, uint16_t size);
     RetCode_t (* idle_callback)(IdleReason_T reason, uint16_t param);
 
+#if 0
     point_t TranslateOrientation(point_t rawPoint);
+#endif
 };
 
 
--- a/RA8875_Touch.cpp	Sun Mar 29 18:12:24 2020 +0000
+++ b/RA8875_Touch.cpp	Thu Apr 30 13:51:32 2020 +0000
@@ -257,7 +257,7 @@
     if (panelTouched == true) {
         panelTouched = false;
         if (TouchPoint) {
-            *TouchPoint = TranslateOrientation(touchInfo[0].coordinates);
+            *TouchPoint = touchInfo[0].coordinates;
             ts = touchInfo[0].touchCode;
             #ifdef DEBUG
             static TouchCode_t lastTS = no_touch;
@@ -292,7 +292,7 @@
 {
     if (channel >= TouchChannels())
         channel = 0;
-    return TranslateOrientation(touchInfo[channel].coordinates);
+    return touchInfo[channel].coordinates; // TranslateOrientation(touchInfo[channel].coordinates);
 }
 
 TouchCode_t RA8875::TouchPanelGet(point_t * TouchPoint)
@@ -312,6 +312,7 @@
     return t;
 }
 
+#if 0
 point_t RA8875::TranslateOrientation(point_t rawPoint)
 {
     point_t newPoint = rawPoint;
@@ -334,7 +335,7 @@
     //INFO("Translate(%3d x %3d) => (%3d x %3d)", rawPoint.x, rawPoint.y, newPoint.x, newPoint.y);
     return newPoint;
 }
-
+#endif
 
 // Below here are primarily "helper" functions. While many are accessible
 // to the user code, they usually don't need to be called.
@@ -451,12 +452,9 @@
             /*  math. Make sure you add all terms together before      */
             /*  dividing, so that the remainder is not rounded off     */
             /*  prematurely.                                           */
-            touchInfo[0].coordinates.x = ((tpMatrix.An * a2dX) +
-                (tpMatrix.Bn * a2dY) + tpMatrix.Cn
-                ) / tpMatrix.Divider;
-            touchInfo[0].coordinates.y = ((tpMatrix.Dn * a2dX) +
-                (tpMatrix.En * a2dY) + tpMatrix.Fn
-                ) / tpMatrix.Divider;
+            touchInfo[0].coordinates = TranslateOrientation( 
+                ((tpMatrix.An * a2dX) + (tpMatrix.Bn * a2dY) + tpMatrix.Cn) / tpMatrix.Divider,
+                ((tpMatrix.Dn * a2dX) + (tpMatrix.En * a2dY) + tpMatrix.Fn) / tpMatrix.Divider );
         } else {
             ts = no_cal;
         }
--- a/RA8875_Touch_FT5206.cpp	Sun Mar 29 18:12:24 2020 +0000
+++ b/RA8875_Touch_FT5206.cpp	Thu Apr 30 13:51:32 2020 +0000
@@ -38,7 +38,6 @@
 #endif
 
 
-
 // Translate from FT5206 Event Flag to Touch Code to API-match the
 // alternate resistive touch screen driver common in the RA8875
 // displays.
@@ -91,8 +90,9 @@
     touchInfo[4].touchCode = FT5206_EventFlagToTouchCode[valXH >> 6];
     INFO("  touchID %d", touchInfo[4].touchCode);
     touchInfo[4].touchID   = (valYH >> 4);
-    touchInfo[4].coordinates.x = (valXH & 0x0f)*256 + FT5206_ReadRegU8(FT5206_TOUCH5_XL);
-    touchInfo[4].coordinates.y = (valYH & 0x0f)*256 + FT5206_ReadRegU8(FT5206_TOUCH5_YL);
+    touchInfo[4].coordinates = TranslateOrientation(
+        (valXH & 0x0f)*256 + FT5206_ReadRegU8(FT5206_TOUCH5_XL),
+        (valYH & 0x0f)*256 + FT5206_ReadRegU8(FT5206_TOUCH5_YL) );
    
 
     valXH  = FT5206_ReadRegU8(FT5206_TOUCH4_XH);
@@ -100,17 +100,19 @@
     touchInfo[3].touchCode = FT5206_EventFlagToTouchCode[valXH >> 6];
     INFO("  touchID %d", touchInfo[3].touchCode);
     touchInfo[3].touchID   = (valYH >> 4);
-    touchInfo[3].coordinates.x = (valXH & 0x0f)*256 + FT5206_ReadRegU8(FT5206_TOUCH4_XL);
-    touchInfo[3].coordinates.y = (valYH & 0x0f)*256 + FT5206_ReadRegU8(FT5206_TOUCH4_YL);
-   
+    touchInfo[3].coordinates = TranslateOrientation(
+        (valXH & 0x0f)*256 + FT5206_ReadRegU8(FT5206_TOUCH4_XL),
+        (valYH & 0x0f)*256 + FT5206_ReadRegU8(FT5206_TOUCH4_YL) );
+
 
     valXH  = FT5206_ReadRegU8(FT5206_TOUCH3_XH);
     valYH  = FT5206_ReadRegU8(FT5206_TOUCH3_YH);
     touchInfo[2].touchCode = FT5206_EventFlagToTouchCode[valXH >> 6];
     INFO("  touchID %d", touchInfo[2].touchCode);
     touchInfo[2].touchID   = (valYH >> 4);
-    touchInfo[2].coordinates.x = (valXH & 0x0f)*256 + FT5206_ReadRegU8(FT5206_TOUCH3_XL);
-    touchInfo[2].coordinates.y = (valYH & 0x0f)*256 + FT5206_ReadRegU8(FT5206_TOUCH3_YL);
+    touchInfo[2].coordinates = TranslateOrientation(
+        (valXH & 0x0f)*256 + FT5206_ReadRegU8(FT5206_TOUCH3_XL),
+        (valYH & 0x0f)*256 + FT5206_ReadRegU8(FT5206_TOUCH3_YL) );
    
 
     valXH  = FT5206_ReadRegU8(FT5206_TOUCH2_XH);
@@ -118,8 +120,9 @@
     touchInfo[1].touchCode = FT5206_EventFlagToTouchCode[valXH >> 6];
     INFO("  touchID %d", touchInfo[1].touchCode);
     touchInfo[1].touchID   = (valYH >> 4);
-    touchInfo[1].coordinates.x = (valXH & 0x0f)*256 + FT5206_ReadRegU8(FT5206_TOUCH2_XL);
-    touchInfo[1].coordinates.y = (valYH & 0x0f)*256 + FT5206_ReadRegU8(FT5206_TOUCH2_YL);
+    touchInfo[1].coordinates = TranslateOrientation(
+        (valXH & 0x0f)*256 + FT5206_ReadRegU8(FT5206_TOUCH2_XL),
+        (valYH & 0x0f)*256 + FT5206_ReadRegU8(FT5206_TOUCH2_YL) );
    
 
     valXH  = FT5206_ReadRegU8(FT5206_TOUCH1_XH);
@@ -127,8 +130,9 @@
     touchInfo[0].touchCode = FT5206_EventFlagToTouchCode[valXH >> 6];
     INFO("  touchID %d", touchInfo[0].touchCode);
     touchInfo[0].touchID   = (valYH >> 4);
-    touchInfo[0].coordinates.x = (valXH & 0x0f)*256 + FT5206_ReadRegU8(FT5206_TOUCH1_XL);
-    touchInfo[0].coordinates.y = (valYH & 0x0f)*256 + FT5206_ReadRegU8(FT5206_TOUCH1_YL);
+    touchInfo[0].coordinates = TranslateOrientation(
+        (valXH & 0x0f)*256 + FT5206_ReadRegU8(FT5206_TOUCH1_XL),
+        (valYH & 0x0f)*256 + FT5206_ReadRegU8(FT5206_TOUCH1_YL) );
 
     return numberOfTouchPoints;
 }
--- a/RA8875_Touch_GSL1680.cpp	Sun Mar 29 18:12:24 2020 +0000
+++ b/RA8875_Touch_GSL1680.cpp	Thu Apr 30 13:51:32 2020 +0000
@@ -105,19 +105,6 @@
 #define HexDump(a, b, c)
 #endif
 
-
-#if 0
-// Translate from GSL1680 Event Flag to Touch Code to API-match the
-// alternate resistive touch screen driver common in the RA8875
-// displays.
-static const TouchCode_t GSL1680_EventFlagToTouchCode[4] = {
-    touch,      // 00b Put Down
-    release,    // 01b Put Up
-    held,       // 10b Contact
-    no_touch    // 11b Reserved
-};
-#endif
-
 RetCode_t RA8875::GSL1680_Init() {
     RetCode_t r = noerror;
     uint8_t buf[5] = { 0 };   // addr + up to 4 Bytes data
@@ -242,8 +229,7 @@
             uint16_t fingerAndY, AndX;
             fingerAndY = (uint16_t)(touch_data[dNdx - 0]) << 8 | (uint16_t)touch_data[dNdx - 1];
             AndX = (uint16_t)(touch_data[dNdx - 2]) << 8 | (uint16_t)touch_data[dNdx - 3];
-            touchInfo[tNdx].coordinates.y = fingerAndY & 0x0FFF;
-            touchInfo[tNdx].coordinates.x = AndX & 0x0FFFF;
+            touchInfo[tNdx].coordinates = TranslateOrientation( AndX & 0x0FFFF, fingerAndY & 0x0FFF );
             touchInfo[tNdx].touchID = (fingerAndY >> 12);
             touchInfo[tNdx].touchCode = (numberOfTouchPoints > tNdx) ? touch : no_touch;
             //INFO("  Code %d, Finger %d, xy (%4d,%4d)",