CUER / RA8875

Fork of RA8875 by David Smart

Files at this revision

API Documentation at this revision

Comitter:
WiredHome
Date:
Sun Jul 31 20:59:01 2016 +0000
Parent:
123:2f45e80fec5f
Child:
125:7a0b70f56550
Commit message:
Incorporated the Capacitive touch panel APIs in to the base RA8875 driver in a manner that integrated smoothly with the Resistive touch driver.

Changed in this revision

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/RA8875.cpp	Mon Jul 25 10:55:58 2016 +0000
+++ b/RA8875.cpp	Sun Jul 31 20:59:01 2016 +0000
@@ -91,18 +91,50 @@
     "not enough ram",         ///< could not allocate ram for scanline
 };
 
-RA8875::RA8875(PinName mosi, PinName miso, PinName sclk, PinName csel, PinName reset, const char *name)
+RA8875::RA8875(PinName mosi, PinName miso, PinName sclk, PinName csel, PinName reset, 
+    const char *name)
     : GraphicsDisplay(name)
     , spi(mosi, miso, sclk)
     , cs(csel)
     , res(reset)
 {
+    useTouchPanel = TP_NONE;
+    m_irq = NULL;
+    m_i2c = NULL;
     c_callback = NULL;
     obj_callback = NULL;
     method_callback = NULL;
     idle_callback = NULL;
 }
 
+
+RA8875::RA8875(PinName mosi, PinName miso, PinName sclk, PinName csel, PinName reset, 
+    PinName sda, PinName scl, PinName irq, const char * name) 
+    : GraphicsDisplay(name)
+    , spi(mosi, miso, sclk)
+    , cs(csel)
+    , res(reset)
+{
+    useTouchPanel = TP_CAP;
+    m_irq = new InterruptIn(irq);
+    m_i2c = new I2C(sda, scl);
+    c_callback = NULL;
+    obj_callback = NULL;
+    method_callback = NULL;
+    idle_callback = NULL;
+
+    // Cap touch panel config
+    m_addr = (FT5206_I2C_ADDRESS << 1);
+    m_i2c->frequency(FT5206_I2C_FREQUENCY);
+
+    // Interrupt
+    m_irq->mode(PullUp);
+    m_irq->enable_irq();
+    m_irq->fall(this, &RA8875::TouchPanelISR);
+    TouchPanelInit();
+}
+
+
 //RA8875::~RA8875()
 //{
 //}
@@ -168,8 +200,11 @@
         Backlight_u8(255);
     if (keypadon)
         KeypadInit();
-    if (touchscreenon)
+    if (touchscreenon) {
+        if (useTouchPanel == TP_NONE)
+            useTouchPanel = TP_RES;
         TouchPanelInit();
+    }
 #ifdef PERF_METRICS
     performance.start();
     ClearPerformance();
--- a/RA8875.h	Mon Jul 25 10:55:58 2016 +0000
+++ b/RA8875.h	Sun Jul 31 20:59:01 2016 +0000
@@ -113,6 +113,98 @@
 #define max(a,b) ((a>b)?a:b)
 
 
+/// FT5206 definitions follow
+#define FT5206_I2C_FREQUENCY                400000
+
+#define FT5206_I2C_ADDRESS                  0x38
+#define FT5206_NUMBER_OF_REGISTERS          31   // there are more registers, but this
+                                                 // is enough to get all 5 touch coordinates.
+
+#define FT5206_NUMBER_OF_TOTAL_REGISTERS    0xFE
+
+#define FT5206_DEVICE_MODE                  0x00 // Normal, test, etc.
+#define FT5206_GEST_ID                      0x01 // Gesture detected
+#define FT5206_TD_STATUS                    0x02 // How many points detected (3:0). 1-5 is valid.
+
+#define FT5206_TOUCH1_XH                    0x03 // Event Flag, Touch X Position
+#define FT5206_TOUCH1_XL                    0x04
+#define FT5206_TOUCH1_YH                    0x05 // Touch ID, Touch Y Position
+#define FT5206_TOUCH1_YL                    0x06
+
+#define FT5206_TOUCH2_XH                    0x09 // Event Flag, Touch X Position
+#define FT5206_TOUCH2_XL                    0x0a
+#define FT5206_TOUCH2_YH                    0x0b // Touch ID, Touch Y Position
+#define FT5206_TOUCH2_YL                    0x0c
+
+#define FT5206_TOUCH3_XH                    0x0f // Event Flag, Touch X Position
+#define FT5206_TOUCH3_XL                    0x10
+#define FT5206_TOUCH3_YH                    0x11 // Touch ID, Touch Y Position
+#define FT5206_TOUCH3_YL                    0x12
+
+#define FT5206_TOUCH4_XH                    0x15 // Event Flag, Touch X Position
+#define FT5206_TOUCH4_XL                    0x16
+#define FT5206_TOUCH4_YH                    0x17 // Touch ID, Touch Y Position
+#define FT5206_TOUCH4_YL                    0x18
+
+#define FT5206_TOUCH5_XH                    0x1b // Event Flag, Touch X Position
+#define FT5206_TOUCH5_XL                    0x1c
+#define FT5206_TOUCH5_YH                    0x1d // Touch ID, Touch Y Position
+#define FT5206_TOUCH5_YL                    0x1e
+
+// For typical usage, the registers listed below are not used.
+#define FT5206_ID_G_THGROUP                 0x80 // Valid touching detect threshold
+#define FT5206_ID_G_THPEAK                  0x81 // Valid touching peak detect threshold
+#define FT5206_ID_G_THCAL                   0x82 // The threshold when calculating the focus of touching
+#define FT5206_ID_G_THWATER                 0x83 // The threshold when there is surface water
+#define FT5206_ID_G_THTEMP                  0x84 // The threshold of temperature compensation
+#define FT5206_ID_G_CTRL                    0x86 // Power control mode
+#define FT5206_ID_G_TIME_ENTER_MONITOR      0x87 // The timer of entering monitor status
+#define FT5206_ID_G_PERIODACTIVE            0x88 // Period Active
+#define FT5206_ID_G_PERIODMONITOR           0x89 // The timer of entering idle while in monitor status
+#define FT5206_ID_G_AUTO_CLB_MODE           0xA0 // Auto calibration mode
+
+#define FT5206_TOUCH_LIB_VERSION_H          0xA1 // Firmware Library Version H byte
+#define FT5206_TOUCH_LIB_VERSION_L          0xA2 // Firmware Library Version L byte
+#define FT5206_ID_G_CIPHER                  0xA3 // Chip vendor ID
+#define FT5206_G_MODE                       0xA4 // The interrupt status to host
+#define FT5206_ID_G_PMODE                   0xA5 // Power Consume Mode
+#define FT5206_FIRMID                       0xA6 // Firmware ID
+#define FT5206_ID_G_STATE                   0xA7 // Running State
+#define FT5206_ID_G_FT5201ID                0xA8 // CTPM Vendor ID
+#define FT5206_ID_G_ERR                     0xA9 // Error Code
+#define FT5206_ID_G_CLB                     0xAA // Configure TP module during calibration in Test Mode
+#define FT5206_ID_G_B_AREA_TH               0xAE // The threshold of big area
+#define FT5206_LOG_MSG_CNT                  0xFE // The log MSG count
+#define FT5206_LOG_CUR_CHA                  0xFF // Current character of log message, will point to the next
+                                                 // character when one character is read.
+#define FT5206_GEST_ID_MOVE_UP              0x10
+#define FT5206_GEST_ID_MOVE_LEFT            0x14
+#define FT5206_GEST_ID_MOVE_DOWN            0x18
+#define FT5206_GEST_ID_MOVE_RIGHT           0x1c
+#define FT5206_GEST_ID_ZOOM_IN              0x48
+#define FT5206_GEST_ID_ZOOM_OUT             0x49
+#define FT5206_GEST_ID_NO_GESTURE           0x00
+
+#define FT5206_EVENT_FLAG_PUT_DOWN          0x00
+#define FT5206_EVENT_FLAG_PUT_UP            0x01
+#define FT5206_EVENT_FLAG_CONTACT           0x02
+#define FT5206_EVENT_FLAG_RESERVED          0x03
+
+#define FT5206_ID_G_POLLING_MODE            0x00
+#define FT5206_ID_G_TRIGGER_MODE            0x01
+
+#define FT5206_ID_G_PMODE_ACTIVE            0x00
+#define FT5206_ID_G_PMODE_MONITOR           0x01
+#define FT5206_ID_G_PMODE_HIBERNATE         0x03
+
+#define FT5206_ID_G_STATE_CONFIGURE         0x00
+#define FT5206_ID_G_STATE_WORK              0x01
+#define FT5206_ID_G_STATE_CALIBRATION       0x02
+#define FT5206_ID_G_STATE_FACTORY           0x03
+#define FT5206_ID_G_STATE_AUTO_CALIBRATION  0x04
+/// end of FT5206 definitions
+
+
 //namespace SW_graphics
 //{
 
@@ -301,7 +393,11 @@
     typedef RetCode_t (* IdleCallback_T)(IdleReason_T info);
 
     /// Constructor for a display based on the RAiO RA8875 
-    /// display controller.
+    /// display controller (use for TouchScreen: Resistive or none)
+    ///
+    /// This constructor differs from the alternate by supportting
+    /// either No Touch Screen, or the RA8875 built-in resistive
+    /// touch screen.
     ///
     /// This configures the registers and calls the @ref init method.
     ///
@@ -328,7 +424,33 @@
     /// @param[in] name is a text name for this object, which will permit
     ///         capturing stdout to puts() and printf() directly to it.
     ///
-    RA8875(PinName mosi, PinName miso, PinName sclk, PinName csel, PinName reset, const char * name = "lcd");
+    RA8875(PinName mosi, PinName miso, PinName sclk, PinName csel, PinName reset, 
+        const char * name = "lcd");
+    
+    
+    /// Constructor for a display based on the RAiO RA8875 
+    /// display controller (use for TouchScreen: Capacitive only)
+    ///
+    /// This constructor differs from the alternate by including support
+    /// for the Capactive Touch screen.
+    ///
+    /// @param[in] mosi is the SPI master out slave in pin on the mbed.
+    /// @param[in] miso is the SPI master in slave out pin on the mbed.
+    /// @param[in] sclk is the SPI shift clock pin on the mbed.
+    /// @param[in] csel is the DigitalOut pin on the mbed to use as the
+    ///         active low chip select for the display controller.
+    /// @param[in] reset is the DigitalOut pin on the mbed to use as the 
+    ///         active low reset input on the display controller - 
+    ///         but this is not currently used.
+    /// @param[in] sda is the I2C Serial Data pin you are wiring to the FT5206.
+    /// @param[in] scl is the I2C Serial Clock pin you are wiring to the FT5206.
+    /// @param[in] irq is the Interrupt Request pin you are wiring to the FT5206.
+    /// @param[in] name is a text name for this object, which will permit
+    ///         capturing stdout to puts() and printf() directly to it.
+    ///
+    RA8875(PinName mosi, PinName miso, PinName sclk, PinName csel, PinName reset, 
+        PinName sda, PinName scl, PinName irq, const char * name = "lcd");
+    
     
     // Destructor doesn't have much to do as this would typically be created
     // at startup, and not at runtime.
@@ -353,13 +475,17 @@
     ///             and the default is true (on). See @ref Power.
     /// @param[in] keypadon defines if the keypad support should be enabled. This parameter is optional
     ///             and the default is true (enabled). See @ref KeypadInit.
-    /// @param[in] touchscreeenon defines if the keypad support should be enabled. This parameter is optional
-    ///             and the default is true (enabled). See @ref TouchPanelInit.
+    /// @param[in] touchscreeenon defines if the touchscreen support should be enabled. 
+    ///             This parameter is optional and the default is true (enabled). See @ref TouchPanelInit.\\
+    ///             - If the constructor was called with support for the capacitive driver, this 
+    ///             parameter causes the driver to initialize.
+    ///             - If the constructor was called without support for the capacitive driver, this
+    ///             parameter is used to enable and initialize the resistive touchscreen driver.
     /// @returns success/failure code. See @ref RetCode_t.
     ///
     RetCode_t init(int width = 480, int height = 272, int color_bpp = 16, 
         bool poweron = true, bool keypadon = true, bool touchscreeenon = true);
-    
+
     /// Get a pointer to the error code.
     ///
     /// This method returns a pointer to a text string that matches the
@@ -495,7 +621,7 @@
     ///
     /// This activates the simplified touch panel init, which may work for
     /// most uses. The alternate API is available if fine-grained control
-    /// is needed for the numerous settings.
+    /// of the numerous settings of the resistive panel is needed.
     ///
     /// @returns success/failure code. See @ref RetCode_t.
     ///
@@ -504,7 +630,10 @@
     /// Initialize the Touch Panel controller with detailed settings.
     ///
     /// This is the detailed touch panel init, which provides the ability
-    /// to set nearly every possible option.
+    /// to set nearly every option.
+    ///
+    /// @note If the capacitive touch panel was constructed, this behaves
+    ///     the same as the simplified version.
     ///
     /// @param[in]  bTpEnable           Touch Panel enable/disable control:
     ///                                 - TP_ENABLE: enable the touch panel
@@ -574,7 +703,84 @@
     ///
     TouchCode_t TouchPanelReadable(point_t * TouchPoint = NULL);
 
+    /// Get the reported touch gesture, if any.
+    /// 
+    /// If it could detect a gesture, it will return a value based on
+    /// the interpreted gesture.\\
+    ///
+    /// Valid gesture values are:
+    /// @li 0x00 No gesture
+    /// @li 0x10 Move up
+    /// @li 0x14 Move left
+    /// @li 0x18 Move down
+    /// @li 0x1C Move right
+    /// @li 0x48 Zoom in
+    /// @li 0x49 Zoom out
+    ///
+    /// @returns gesture information.
+    ///
+    uint8_t TouchGesture(void) { return gesture; }
+    
 
+    /// Get the count of registered touches.
+    ///
+    /// @returns count of touch points to communicate; 0 to 5.
+    ///
+    int TouchCount(void) { return numberOfTouchPoints; }
+    
+    /// Get the count of possible touch channels.
+    ///
+    /// @returns count of touch channels supported by the hardware.
+    ///
+    int TouchChannels(void);
+    
+    /// Get the Touch ID value for a specified touch channel.
+    ///
+    /// Touch ID is a tracking number based on the order of the touch
+    /// detections. The first touch is ID 0, the next is ID 1, and 
+    /// so on. If the first touch is lifted (no touch), the touch count
+    /// decrements, and the remaining touch is communicated on
+    /// touch channel zero, even as the Touch ID remains as originally
+    /// reported (1 in this example). In this way, it is easy to track 
+    /// a specific touch.\\
+    ///
+    /// It is possible to query the data for a channel that is not
+    /// presently reported as touched.
+    ///
+    /// @param[in] channel is the touch channel, from 0 to 4, or 0 to getTouchCount()-1
+    ///     It defaults to 0, in case the user is not interested in multi-touch.
+    /// @returns the touch ID, or 15 if you get the ID for an untouched channel.
+    /// @returns 0 if an invalid channel is queried.
+    ///
+    uint8_t TouchID(uint8_t channel = 0) { return (channel < 5) ? touchInfo[channel].touchID : touchInfo[0].touchID; }
+    
+    /// Get the Touch Code for a touch channel.
+    ///
+    /// It is possible to query the data for a channel that is not
+    /// presently reported as touched.
+    ///
+    /// @param[in] channel is the touch channel, from 0 to 4, or 0 to getTouchCount()-1
+    ///     It defaults to 0, in case the user is not interested in multi-touch.
+    /// @returns the touch code (@ref TouchCode_t).
+    /// @returns channel 0 information if an invalid channel is queried.
+    ///
+    TouchCode_t TouchCode(uint8_t channel = 0) { return (channel < 5) ? touchInfo[channel].touchCode : touchInfo[0].touchCode; }
+
+    /// Get the coordinates for a touch channel.
+    ///
+    /// This returns the (X,Y) coordinates for a touch channel.
+    ///\\
+    ///
+    /// It is possible to query the data for a channel that is not
+    /// presently reported as touched.
+    ///
+    /// @param[in] channel is an optional touch channel, from 0 to 4, or 0 to getTouchCount()-1.
+    ///     It defaults to 0, in case the user is not interested in multi-touch.
+    /// @returns the coordinates as a point_t structure.
+    /// @returns channel 0 information if an invalid channel is queried.
+    ///
+    point_t TouchCoordinates(uint8_t channel = 0)  { return (channel < 5) ? touchInfo[channel].coordinates : touchInfo[0].coordinates; }
+    
     /// Poll the TouchPanel and on a touch event return the a to d filtered x, y coordinates.
     ///
     /// This method reads the touch controller, which has a 10-bit range for each the
@@ -2123,7 +2329,51 @@
 
 
 private:
-    /// Touch Panel register name definitions
+    /// Touch panel parameters - common to both resistive and capacitive
+    
+    /// Data type to indicate which TP, if any, is in use.
+    typedef enum {
+        TP_NONE,            ///< no touch panel in use
+        TP_RES,             ///< resistive touch panel using RA8875
+        TP_CAP,             ///< capacitive touch panel using FT5206
+    } WhichTP_T;
+    
+    /// boolean flag set true when using Capacitive touch panel, and false
+    /// for resistive.
+    WhichTP_T useTouchPanel;    ///< Indicates which TP is selected for use.
+        
+    /// Touch State used by TouchPanelReadable. See @ref TouchCode_t.
+    TouchCode_t touchState;
+
+    ////////////////// Start of Capacitive Touch Panel parameters
+    
+    uint8_t getTouchPositions(void);
+    void TouchPanelISR(void);
+    uint16_t numberOfTouchPoints;
+    uint8_t gesture;            ///< Holds the reported gesture information.
+    
+    /// Touch Information data structure
+    typedef struct {
+        uint8_t touchID;        ///< Contains the touch ID, which is the "order" of touch, from 0 to n-1
+        TouchCode_t touchCode;  ///< Contains the touch code; no_touch, touch, held, release
+        point_t coordinates;    ///< Contains the X,Y coordinate of the touch
+    } touchInfo_T;
+
+    touchInfo_T touchInfo[5];   /// Contains the actual touch information in an array from 0 to n-1
+
+    InterruptIn * m_irq;
+    I2C * m_i2c;
+    int m_addr;
+    uint8_t data[2];
+
+    bool panelTouched;
+    void writeRegister8(uint8_t reg, uint8_t val);
+    uint8_t readRegister8(uint8_t reg);
+
+    
+    ////////////////// Start of Resistive Touch Panel parameters
+    
+    /// Resistive Touch Panel register name definitions
     #define TPCR0   0x70
     #define TPCR1   0x71
     #define TPXH    0x72
@@ -2148,9 +2398,6 @@
     // 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 @ref TouchCode_t.
-    TouchCode_t touchState;
-
     /// Touch Panel ticker
     Ticker touchTicker;
     
@@ -2166,6 +2413,9 @@
     /// Touch Panel calibration matrix.
     tpMatrix_t tpMatrix;
 
+    ////////////////// End of Touch Panel parameters
+
+
     /// Internal function to put a character using the built-in (internal) font engine
     ///
     /// @param[in] c is the character to put to the screen.
@@ -2320,7 +2570,6 @@
     RetCode_t (* c_callback)(filecmd_t cmd, uint8_t * buffer, uint16_t size);
     FPointerDummy  *obj_callback;
     RetCode_t (FPointerDummy::*method_callback)(filecmd_t cmd, uint8_t * buffer, uint16_t size);
-    
     RetCode_t (* idle_callback)(IdleReason_T reason);
 };
 
--- a/RA8875_Touch.cpp	Mon Jul 25 10:55:58 2016 +0000
+++ b/RA8875_Touch.cpp	Sun Jul 31 20:59:01 2016 +0000
@@ -1,69 +1,107 @@
 /// This file contains the RA8875 Touch panel methods.
 ///
-
+/// It combines both resistive and capacitive touch methods, and tries
+/// to make them nearly transparent alternates for each other.
+///
 #include "RA8875.h"
 
 #define NOTOUCH_TIMEOUT_uS 100000
 #define TOUCH_TICKER_uS      1000
 
+
+// Translate from FT5206 Event Flag to Touch Code to API-match the
+// alternate resistive touch screen driver common in the RA8875
+// displays.
+static const TouchCode_t EventFlagToTouchCode[4] = {
+    touch,      // 00b Put Down
+    release,    // 01b Put Up
+    held,       // 10b Contact
+    no_touch    // 11b Reserved
+};
+
+
 RetCode_t RA8875::TouchPanelInit(void)
 {
-    //TPCR0: Set enable bit, default sample time, wakeup, and ADC clock
-    WriteCommand(TPCR0, TP_ENABLE | TP_ADC_SAMPLE_DEFAULT_CLKS | TP_ADC_CLKDIV_DEFAULT);
-    // TPCR1: Set auto/manual, Ref voltage, debounce, manual mode params
-    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;
-}
-
-RetCode_t RA8875::TouchPanelInit(uint8_t bTpEnable, uint8_t bTpAutoManual, uint8_t bTpDebounce, uint8_t bTpManualMode, uint8_t bTpAdcClkDiv, uint8_t bTpAdcSampleTime)
-{
-    // Parameter bounds check
-    if( \
-            !(bTpEnable == TP_ENABLE || bTpEnable == TP_ENABLE) || \
-            !(bTpAutoManual == TP_MODE_AUTO || bTpAutoManual == TP_MODE_MANUAL) || \
-            !(bTpDebounce == TP_DEBOUNCE_OFF || bTpDebounce == TP_DEBOUNCE_ON) || \
-            !(bTpManualMode <= TP_MANUAL_LATCH_Y) || \
-            !(bTpAdcClkDiv <= TP_ADC_CLKDIV_128) || \
-            !(bTpAdcSampleTime <= TP_ADC_SAMPLE_65536_CLKS) \
-      ) return bad_parameter;
-    // Construct the config byte for TPCR0 and write them
-    WriteCommand(TPCR0, bTpEnable | bTpAdcClkDiv | bTpAdcSampleTime);    // Note: Wakeup is never enabled
-    // Construct the config byte for TPCR1 and write them
-    WriteCommand(TPCR1, bTpManualMode | bTpDebounce | bTpManualMode);    // Note: Always uses internal Vref.
-    // 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) {
+    panelTouched = false;
+    if (useTouchPanel == TP_CAP) {
+        // Set to normal mode
+        writeRegister8(FT5206_DEVICE_MODE, 0);
+    } else {
+        //TPCR0: Set enable bit, default sample time, wakeup, and ADC clock
+        WriteCommand(TPCR0, TP_ENABLE | TP_ADC_SAMPLE_DEFAULT_CLKS | TP_ADC_CLKDIV_DEFAULT);
+        // TPCR1: Set auto/manual, Ref voltage, debounce, manual mode params
+        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();
-    } else {
-        touchTicker.detach();
-        touchTimer.stop();
     }
     return noerror;
 }
 
-    // +----------------------------------------------------+
-    // |                                                    |
-    // |  1                                                 |
-    // |                                                    |
-    // |                                                    |
-    // |                                               2    |
-    // |                                                    |
-    // |                                                    |
-    // |                         3                          |
-    // |                                                    |
-    // +----------------------------------------------------+
+
+RetCode_t RA8875::TouchPanelInit(uint8_t bTpEnable, uint8_t bTpAutoManual, uint8_t bTpDebounce, uint8_t bTpManualMode, uint8_t bTpAdcClkDiv, uint8_t bTpAdcSampleTime)
+{
+    if (useTouchPanel == TP_CAP) {
+        TouchPanelInit();
+    } else {
+        // Parameter bounds check
+        if( \
+                !(bTpEnable == TP_ENABLE || bTpEnable == TP_ENABLE) || \
+                !(bTpAutoManual == TP_MODE_AUTO || bTpAutoManual == TP_MODE_MANUAL) || \
+                !(bTpDebounce == TP_DEBOUNCE_OFF || bTpDebounce == TP_DEBOUNCE_ON) || \
+                !(bTpManualMode <= TP_MANUAL_LATCH_Y) || \
+                !(bTpAdcClkDiv <= TP_ADC_CLKDIV_128) || \
+                !(bTpAdcSampleTime <= TP_ADC_SAMPLE_65536_CLKS) \
+          ) return bad_parameter;
+        // Construct the config byte for TPCR0 and write them
+        WriteCommand(TPCR0, bTpEnable | bTpAdcClkDiv | bTpAdcSampleTime);    // Note: Wakeup is never enabled
+        // Construct the config byte for TPCR1 and write them
+        WriteCommand(TPCR1, bTpManualMode | bTpDebounce | bTpManualMode);    // Note: Always uses internal Vref.
+        // 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;
+}
+
+
+int RA8875::TouchChannels(void)
+{
+    if (useTouchPanel == TP_CAP) {
+        return 5;   // based on the FT5206 hardware
+    } else if (useTouchPanel == TP_RES) {
+        return 1;   // based on the RA8875 resistive touch driver
+    } else {
+        return 0;   // it isn't enabled, so there are none.
+    }
+}
+
+
+// +----------------------------------------------------+
+// |                                                    |
+// |  1                                                 |
+// |                                                    |
+// |                                                    |
+// |                                               2    |
+// |                                                    |
+// |                                                    |
+// |                         3                          |
+// |                                                    |
+// +----------------------------------------------------+
 
 RetCode_t RA8875::TouchPanelCalibrate(tpMatrix_t * matrix)
 {
@@ -76,7 +114,7 @@
     point_t pSample[3];
     int x,y;
     Timer timeout;  // timeout guards for not-installed, stuck, user not present...
-    
+
     timeout.start();
     while (TouchPanelA2DFiltered(&x, &y) && timeout.read() < maxwait_s) {
         wait_ms(20);
@@ -90,9 +128,12 @@
     if (msg)
         puts(msg);
     SetTextCursor(0,height()/2);
-    pTest[0].x = 50;            pTest[0].y = 50;
-    pTest[1].x = width() - 50;  pTest[1].y = height()/2;
-    pTest[2].x = width()/2;     pTest[2].y = height() - 50;
+    pTest[0].x = 50;
+    pTest[0].y = 50;
+    pTest[1].x = width() - 50;
+    pTest[1].y = height()/2;
+    pTest[2].x = width()/2;
+    pTest[2].y = height() - 50;
 
     for (int i=0; i<3; i++) {
         foreground(Blue);
@@ -144,24 +185,24 @@
  *  Description: Given a valid set of calibration factors and a point
  *                value reported by the touch screen, this function
  *                calculates and returns the true (or closest to true)
- *                display point below the spot where the touch screen 
+ *                display point below the spot where the touch screen
  *                was touched.
- * 
+ *
  *
- * 
+ *
  *  Argument(s): displayPtr (output) - Pointer to the calculated
  *                                      (true) display point.
  *               screenPtr (input) - Pointer to the reported touch
  *                                    screen point.
  *               matrixPtr (input) - Pointer to calibration factors
  *                                    matrix previously calculated
- *                                    from a call to 
+ *                                    from a call to
  *                                    setCalibrationMatrix()
- * 
+ *
  *
- *  The function simply solves for Xd and Yd by implementing the 
- *   computations required by the translation matrix.  
- * 
+ *  The function simply solves for Xd and Yd by implementing the
+ *   computations required by the translation matrix.
+ *
  *                                              /-     -\
  *              /-    -\     /-            -\   |       |
  *              |      |     |              |   |   Xs  |
@@ -171,10 +212,10 @@
  *              |      |     |              |   |   1   |
  *              \-    -/     \-            -/   |       |
  *                                              \-     -/
- * 
+ *
  *  It must be kept brief to avoid consuming CPU cycles.
  *
- *       Return: OK - the display point was correctly calculated 
+ *       Return: OK - the display point was correctly calculated
  *                     and its value is in the output argument.
  *               NOT_OK - an error was detected and the function
  *                         failed to return a valid point.
@@ -182,42 +223,60 @@
  *                 NOTE!    NOTE!    NOTE!
  *
  *  setCalibrationMatrix() and getDisplayPoint() will do fine
- *  for you as they are, provided that your digitizer         
+ *  for you as they are, provided that your digitizer
  *  resolution does not exceed 10 bits (1024 values).  Higher
  *  resolutions may cause the integer operations to overflow
- *  and return incorrect values.  If you wish to use these   
- *  functions with digitizer resolutions of 12 bits (4096    
- *  values) you will either have to a) use 64-bit signed     
- *  integer variables and math, or b) judiciously modify the 
- *  operations to scale results by a factor of 2 or even 4.  
+ *  and return incorrect values.  If you wish to use these
+ *  functions with digitizer resolutions of 12 bits (4096
+ *  values) you will either have to a) use 64-bit signed
+ *  integer variables and math, or b) judiciously modify the
+ *  operations to scale results by a factor of 2 or even 4.
  *
  */
 TouchCode_t RA8875::TouchPanelReadable(point_t * TouchPoint)
 {
-    int a2dX = 0;
-    int a2dY = 0;
-    
-    TouchCode_t ts = TouchPanelA2DFiltered(&a2dX, &a2dY);
-    if (ts != no_touch) {
-        if (tpMatrix.Divider != 0) {
-            if (TouchPoint) {
+    TouchCode_t ts = no_touch;
+
+    if (useTouchPanel == TP_RES) {
+        int a2dX = 0;
+        int a2dY = 0;
+        
+        touchInfo[0].touchID = 0;
+        ts = TouchPanelA2DFiltered(&a2dX, &a2dY);
+        if (ts != no_touch) {
+            panelTouched = true;
+            numberOfTouchPoints = 1;
+
+            if (tpMatrix.Divider != 0) {
+
                 /* 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 * a2dX) +
+                touchInfo[0].coordinates.x = ( (tpMatrix.An * a2dX) +
                                   (tpMatrix.Bn * a2dY) +
                                   tpMatrix.Cn
                                 ) / tpMatrix.Divider ;
 
-                TouchPoint->y = ( (tpMatrix.Dn * a2dX) +
+                touchInfo[0].coordinates.y = ( (tpMatrix.Dn * a2dX) +
                                   (tpMatrix.En * a2dY) +
                                   tpMatrix.Fn
                                 ) / tpMatrix.Divider ;
+            } else {
+                ts = no_cal;
             }
         } else {
-            ts = no_cal;
+            numberOfTouchPoints = 0;
         }
+        touchInfo[0].touchCode = ts;
+    }
+    if (panelTouched == true) {
+        panelTouched = false;
+        if (TouchPoint) {
+            *TouchPoint = touchInfo[0].coordinates;
+            ts = touchInfo[0].touchCode;
+        }
+        ts = touch;
     }
     return ts;
 }
@@ -226,7 +285,7 @@
 TouchCode_t RA8875::TouchPanelGet(point_t * TouchPoint)
 {
     TouchCode_t t = no_touch;
-    
+
     while (true) {
         t = TouchPanelReadable(TouchPoint);
         if (t != no_touch)
@@ -256,7 +315,7 @@
 {
     int i, j;
     int temp;
-    
+
     for(i = 1; i < bufsize; i++) {
         temp = buf[i];
         j = i;
@@ -386,28 +445,28 @@
  *
  *   Copyright (c) 2001, Carlos E. Vidales. All rights reserved.
  *
- *   This sample program was written and put in the public domain 
- *    by Carlos E. Vidales.  The program is provided "as is" 
+ *   This sample program was written and put in the public domain
+ *    by Carlos E. Vidales.  The program is provided "as is"
  *    without warranty of any kind, either expressed or implied.
  *   If you choose to use the program within your own products
  *    you do so at your own risk, and assume the responsibility
  *    for servicing, repairing or correcting the program should
  *    it prove defective in any manner.
- *   You may copy and distribute the program's source code in any 
+ *   You may copy and distribute the program's source code in any
  *    medium, provided that you also include in each copy an
  *    appropriate copyright notice and disclaimer of warranty.
  *   You may also modify this program and distribute copies of
- *    it provided that you include prominent notices stating 
+ *    it provided that you include prominent notices stating
  *    that you changed the file(s) and the date of any change,
- *    and that you do not charge any royalties or licenses for 
+ *    and that you do not charge any royalties or licenses for
  *    its use.
- * 
- *   This file contains functions that implement calculations 
+ *
+ *   This file contains functions that implement calculations
  *    necessary to obtain calibration factors for a touch screen
- *    that suffers from multiple distortion effects: namely, 
+ *    that suffers from multiple distortion effects: namely,
  *    translation, scaling and rotation.
  *
- *   The following set of equations represent a valid display 
+ *   The following set of equations represent a valid display
  *    point given a corresponding set of touch screen points:
  *
  *                                              /-     -\
@@ -420,7 +479,7 @@
  *              \-    -/     \-            -/   |       |
  *                                              \-     -/
  *    where:
- *           (Xd,Yd) represents the desired display point 
+ *           (Xd,Yd) represents the desired display point
  *                    coordinates,
  *           (Xs,Ys) represents the available touch screen
  *                    coordinates, and the matrix
@@ -428,18 +487,18 @@
  *           |A,B,C|
  *           |D,E,F| represents the factors used to translate
  *           \-   -/  the available touch screen point values
- *                    into the corresponding display 
+ *                    into the corresponding display
  *                    coordinates.
- *    Note that for practical considerations, the utilities 
+ *    Note that for practical considerations, the utilities
  *     within this file do not use the matrix coefficients as
- *     defined above, but instead use the following 
+ *     defined above, but instead use the following
  *     equivalents, since floating point math is not used:
- *            A = An/Divider 
- *            B = Bn/Divider 
- *            C = Cn/Divider 
- *            D = Dn/Divider 
- *            E = En/Divider 
- *            F = Fn/Divider 
+ *            A = An/Divider
+ *            B = Bn/Divider
+ *            C = Cn/Divider
+ *            D = Dn/Divider
+ *            E = En/Divider
+ *            F = Fn/Divider
  *    The functions provided within this file are:
  *          setCalibrationMatrix() - calculates the set of factors
  *                                    in the above equation, given
@@ -458,23 +517,23 @@
  *     Function: setCalibrationMatrix()
  *
  *  Description: Calling this function with valid input data
- *                in the display and screen input arguments 
+ *                in the display and screen input arguments
  *                causes the calibration factors between the
  *                screen and display points to be calculated,
- *                and the output argument - matrixPtr - to be 
+ *                and the output argument - matrixPtr - to be
  *                populated.
  *
  *               This function needs to be called only when new
  *                calibration factors are desired.
- *               
- *  
- *  Argument(s): displayPtr (input) - Pointer to an array of three 
+ *
+ *
+ *  Argument(s): displayPtr (input) - Pointer to an array of three
  *                                     sample, reference points.
- *               screenPtr (input) - Pointer to the array of touch 
- *                                    screen points corresponding 
+ *               screenPtr (input) - Pointer to the array of touch
+ *                                    screen points corresponding
  *                                    to the reference display points.
- *               matrixPtr (output) - Pointer to the calibration 
- *                                     matrix computed for the set 
+ *               matrixPtr (output) - Pointer to the calibration
+ *                                     matrix computed for the set
  *                                     of points being provided.
  *
  *
@@ -496,8 +555,8 @@
  *                                   Divider
  *
  *
- *                 Ys0*(Xs2*Xd1 - Xs1*Xd2) + 
- *                             Ys1*(Xs0*Xd2 - Xs2*Xd0) + 
+ *                 Ys0*(Xs2*Xd1 - Xs1*Xd2) +
+ *                             Ys1*(Xs0*Xd2 - Xs2*Xd0) +
  *                                           Ys2*(Xs1*Xd0 - Xs0*Xd1)
  *            C = ---------------------------------------------------
  *                                   Divider
@@ -513,17 +572,17 @@
  *                                   Divider
  *
  *
- *                 Ys0*(Xs2*Yd1 - Xs1*Yd2) + 
- *                             Ys1*(Xs0*Yd2 - Xs2*Yd0) + 
+ *                 Ys0*(Xs2*Yd1 - Xs1*Yd2) +
+ *                             Ys1*(Xs0*Yd2 - Xs2*Yd0) +
  *                                           Ys2*(Xs1*Yd0 - Xs0*Yd1)
  *            F = ---------------------------------------------------
  *                                   Divider
  *
  *
- *       Return: OK - the calibration matrix was correctly 
- *                     calculated and its value is in the 
+ *       Return: OK - the calibration matrix was correctly
+ *                     calculated and its value is in the
  *                     output argument.
- *               NOT_OK - an error was detected and the 
+ *               NOT_OK - an error was detected and the
  *                         function failed to return a valid
  *                         set of matrix values.
  *                        The only time this sample code returns
@@ -534,14 +593,14 @@
  *                 NOTE!    NOTE!    NOTE!
  *
  *  setCalibrationMatrix() and getDisplayPoint() will do fine
- *  for you as they are, provided that your digitizer         
+ *  for you as they are, provided that your digitizer
  *  resolution does not exceed 10 bits (1024 values).  Higher
  *  resolutions may cause the integer operations to overflow
- *  and return incorrect values.  If you wish to use these   
- *  functions with digitizer resolutions of 12 bits (4096    
- *  values) you will either have to a) use 64-bit signed     
- *  integer variables and math, or b) judiciously modify the 
- *  operations to scale results by a factor of 2 or even 4.  
+ *  and return incorrect values.  If you wish to use these
+ *  functions with digitizer resolutions of 12 bits (4096
+ *  values) you will either have to a) use 64-bit signed
+ *  integer variables and math, or b) judiciously modify the
+ *  operations to scale results by a factor of 2 or even 4.
  *
  */
 RetCode_t RA8875::TouchPanelComputeCalibration(point_t * displayPtr, point_t * screenPtr, tpMatrix_t * matrixPtr)
@@ -580,4 +639,83 @@
     return( retValue ) ;
 }
 
+////////////////// Capacitive Touch Panel
+
+uint8_t RA8875::readRegister8(uint8_t reg) {
+    char val;
+    
+    m_i2c->write(m_addr, (const char *)&reg, 1);
+    m_i2c->read(m_addr, &val, 1);
+    return (uint8_t)val;
+}
+
+void RA8875::writeRegister8(uint8_t reg, uint8_t val) {
+    char data[2];
+    
+    data[0] = (char)reg;
+    data[1] = (char)val;
+    m_i2c->write((int)FT5206_I2C_ADDRESS, data, 2);
+}
+
+
+// Interrupt for touch detection
+void RA8875::TouchPanelISR(void)
+{
+    getTouchPositions();
+    panelTouched = true;
+}
+
+uint8_t RA8875::getTouchPositions(void) {
+    uint8_t valXH;
+    uint8_t valYH;
+
+    numberOfTouchPoints = readRegister8(FT5206_TD_STATUS) & 0xF;
+    gesture = readRegister8(FT5206_GEST_ID);
+    
+    // If the switch statement was based only on numberOfTouchPoints, it would not
+    // be able to generate notification for 'release' events (as it is no longer touched).
+    // Therefore, forcing a 5, and it intentially falls through each lower case.
+    switch (5) {    // numberOfTouchPoints
+        case 5:
+            valXH  = readRegister8(FT5206_TOUCH5_XH);
+            valYH  = readRegister8(FT5206_TOUCH5_YH);
+            touchInfo[4].touchCode = EventFlagToTouchCode[valXH >> 6];
+            touchInfo[4].touchID   = (valYH >> 4);
+            touchInfo[4].coordinates.x = (valXH & 0x0f)*256 + readRegister8(FT5206_TOUCH5_XL);
+            touchInfo[4].coordinates.y = (valYH & 0x0f)*256 + readRegister8(FT5206_TOUCH5_YL);
+        case 4:
+            valXH  = readRegister8(FT5206_TOUCH4_XH);
+            valYH  = readRegister8(FT5206_TOUCH4_YH);
+            touchInfo[3].touchCode = EventFlagToTouchCode[valXH >> 6];
+            touchInfo[3].touchID   = (valYH >> 4);
+            touchInfo[3].coordinates.x = (readRegister8(FT5206_TOUCH4_XH) & 0x0f)*256 + readRegister8(FT5206_TOUCH4_XL);
+            touchInfo[3].coordinates.y = (valYH & 0x0f)*256 + readRegister8(FT5206_TOUCH4_YL);
+        case 3:
+            valXH  = readRegister8(FT5206_TOUCH3_XH);
+            valYH  = readRegister8(FT5206_TOUCH3_YH);
+            touchInfo[2].touchCode = EventFlagToTouchCode[valXH >> 6];
+            touchInfo[2].touchID   = (valYH >> 4);
+            touchInfo[2].coordinates.x = (readRegister8(FT5206_TOUCH3_XH) & 0x0f)*256 + readRegister8(FT5206_TOUCH3_XL);
+            touchInfo[2].coordinates.y = (valYH & 0x0f)*256 + readRegister8(FT5206_TOUCH3_YL);
+        case 2:
+            valXH  = readRegister8(FT5206_TOUCH2_XH);
+            valYH  = readRegister8(FT5206_TOUCH2_YH);
+            touchInfo[1].touchCode = EventFlagToTouchCode[valXH >> 6];
+            touchInfo[1].touchID   = (valYH >> 4);
+            touchInfo[1].coordinates.x  = (readRegister8(FT5206_TOUCH2_XH) & 0x0f)*256 + readRegister8(FT5206_TOUCH2_XL);
+            touchInfo[1].coordinates.y  = (valYH & 0x0f)*256 + readRegister8(FT5206_TOUCH2_YL);
+        case 1:
+            valXH  = readRegister8(FT5206_TOUCH1_XH);
+            valYH  = readRegister8(FT5206_TOUCH1_YH);
+            touchInfo[0].touchCode = EventFlagToTouchCode[valXH >> 6];
+            touchInfo[0].touchID   = (valYH >> 4);
+            touchInfo[0].coordinates.x = (readRegister8(FT5206_TOUCH1_XH) & 0x0f)*256 + readRegister8(FT5206_TOUCH1_XL);
+            touchInfo[0].coordinates.y = (valYH & 0x0f)*256 + readRegister8(FT5206_TOUCH1_YL);
+            break;
+        default:
+            break;
+    }
+    return numberOfTouchPoints;
+}
+
 // #### end of touch panel code additions