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

Dependents:   FRDM_RA8875_mPaint RA8875_Demo RA8875_KeyPadDemo SignalGenerator ... more

Fork of SPI_TFT by Peter Drescher

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers RA8875_Touch_GSL1680.cpp Source File

RA8875_Touch_GSL1680.cpp

00001 ///
00002 /// Support for Touch Controller GSL1680
00003 ///
00004 /// Information is quite scarce for the SiLead GSL1680 Capacitive Touch controller.
00005 /// Further, this controller hosts a 32-bit micro, but is without flash memory, so
00006 /// after power-up, the program must be installed into the chip. This is done through
00007 /// the I2C interface.
00008 ///
00009 /// @attention To make it a bit more complicated, I cannot find any source
00010 ///     for this micro, only "bytestream", which one has to hope is defect free.
00011 ///
00012 /// @attention To make it even more complicated, I do not have a display with this
00013 ///     controller in it, so this body of work is the collective merge of what I've
00014 ///     found and interpreted and interface converted to align with this library.
00015 ///
00016 /// @attention It is probably clear that this represents a work in process, and is
00017 ///     an attempt to make a working driver.
00018 ///
00019 /// http://linux-sunxi.org/GSL1680 has some useful information, a bit of which
00020 /// is replicated here in case that site changes/disappears.
00021 ///
00022 /// To read from the chip, just write a single byte with the register number to
00023 /// start to read, and then do as many reads as registers to read.
00024 ///
00025 /// The known registers are:
00026 /// * 0x00-0x7F: these registers are used to load portions of the firmware.
00027 /// * 0x80: contains the number of touches in the screen.
00028 /// ** If zero, the user isn't touching the screen;
00029 /// ** if one, only one finger is on the screen;
00030 /// ** if two, there are two fingers; and so on.
00031 /// * 0x84-0x87: contains the coordinates for the first touch.
00032 /// * 0x88-0x8B: contains the coordinates for the second touch.
00033 /// * 0x8C-0xAB: contains the coordinates for the third, fourth, and so on
00034 /// ** (up to five in some devices, up to ten in other), touches,
00035 ///     in the same format than the previous ones (four bytes for each touch).
00036 /// * 0xE0: STATUS register
00037 /// * 0xE4, 0xBC-0xBF: some kind of control registers. Needed for uploading
00038 ///     the firmware and soft resetting the chip
00039 ///     (there's not more data available about them).
00040 /// * 0xF0: PAGE register. Contains the memory page number currently mapped
00041 ///     in the 0x00-0x7F registers.
00042 ///
00043 /// Touch coordinates format
00044 /// The four bytes of each group of coordinates contains the X and Y values,
00045 ///     and also the finger.
00046 ///
00047 /// * The first two bytes contains, in little endian format,
00048 /// ** the X coordinate in the 12 lower bits.
00049 /// * The other two bytes contains, in little endian format,
00050 /// ** the Y coordinate in the 12 lower bits.
00051 /// ** The 4 upper bits in the Y coordinate contains the finger identifier.
00052 ///
00053 /// Example:
00054 /// Let's say that the user touches the screen with one finger. The register 0x80
00055 /// will contain 1, and registers 0x84 to 0x87 will contain the X and Y coordinates,
00056 /// and the finger identifier will be 1.
00057 ///
00058 /// Now the user, without removing the first finger, touches the screen with a second finger.
00059 /// The register 0x80 will contain 2. Registers 0x84 to 0x87 will contain the
00060 /// X and Y coordinates of the first touch and the finger identifier in them will be 1.
00061 /// Registers 0x88 to 0x8B will contain the X and Y coordinates of the second touch
00062 /// and the finger identifier in them will be 2.
00063 ///
00064 /// Now the user removes the first finger, keeping the second one. The register 0x80
00065 /// will contain 1. Registers 0x84 to 0x87 will contain the X and Y coordinates,
00066 /// but the finger identifier will be 2, because that's the finger that remains
00067 /// in the screen.
00068 
00069 
00070 #include "RA8875.h"
00071 #include "RA8875_Touch_GSL1680_Firmware.h"
00072 
00073 //#define DEBUG "RAGL"
00074 // ...
00075 // INFO("Stuff to show %d", var); // new-line is automatically appended
00076 //
00077 #if (defined(DEBUG) && !defined(TARGET_LPC11U24))
00078 #define INFO(x, ...) std::printf("[INF %s %4d] " x "\r\n", DEBUG, __LINE__, ##__VA_ARGS__);
00079 #define WARN(x, ...) std::printf("[WRN %s %4d] " x "\r\n", DEBUG, __LINE__, ##__VA_ARGS__);
00080 #define ERR(x, ...)  std::printf("[ERR %s %4d] " x "\r\n", DEBUG, __LINE__, ##__VA_ARGS__);
00081 static void HexDump(const char * title, const uint8_t * p, int count)
00082 {
00083     int i;
00084     char buf[100] = "0000: ";
00085 
00086     if (*title)
00087         INFO("%s", title);
00088     for (i=0; i<count; ) {
00089         sprintf(buf + strlen(buf), "%02X ", *(p+i));
00090         if ((++i & 0x0F) == 0x00) {
00091             INFO("%s", buf);
00092             if (i < count)
00093                 sprintf(buf, "%04X: ", i);
00094             else
00095                 buf[0] = '\0';
00096         }
00097     }
00098     if (strlen(buf))
00099         INFO("%s", buf);
00100 }
00101 #else
00102 #define INFO(x, ...)
00103 #define WARN(x, ...)
00104 #define ERR(x, ...)
00105 #define HexDump(a, b, c)
00106 #endif
00107 
00108 RetCode_t RA8875::GSL1680_Init() {
00109     RetCode_t r = noerror;
00110     uint8_t buf[5] = { 0 };   // addr + up to 4 Bytes data
00111     unsigned int source_line = 0;
00112     unsigned int source_len;
00113     const struct fw_data * ptr_fw;
00114 
00115     INFO("GSL1680_Init()");
00116     // Wake it
00117     m_wake->write(false);
00118     wait_us(20000);
00119     m_wake->write(true);
00120     wait_us(20000);
00121 
00122     // Clear reg
00123     buf[0] = 0xe0;
00124     buf[1] = 0x88;
00125     m_i2c->write(m_addr, (char *)buf, 2);
00126     wait_us(1000);
00127     buf[0] = 0x80;
00128     buf[1] = 0x03;
00129     m_i2c->write(m_addr, (char *)buf, 2);
00130     wait_us(1000);
00131     buf[0] = 0xe4;
00132     buf[1] = 0x04;
00133     m_i2c->write(m_addr, (char *)buf, 2);
00134     wait_us(1000);
00135     buf[0] = 0xe0;
00136     buf[1] = 0x00;
00137     m_i2c->write(m_addr, (char *)buf, 2);
00138     wait_us(1000);
00139 
00140     // Reset
00141     buf[0] = 0xe0;
00142     buf[1] = 0x88;
00143     m_i2c->write(m_addr, (char *)buf, 2);
00144     wait_us(1000);
00145     buf[0] = 0xe4;
00146     buf[1] = 0x04;
00147     m_i2c->write(m_addr, (char *)buf, 2);
00148     wait_us(1000);
00149     buf[0] = 0xbc;
00150     buf[1] = 0x00;
00151     buf[2] = 0x00;
00152     buf[3] = 0x00;
00153     buf[4] = 0x00;
00154     m_i2c->write(m_addr, (char *)buf, 5);
00155     wait_us(1000);
00156 
00157     // Load Firmware
00158     ptr_fw = GSLX680_FW;
00159     source_len = ARRAY_SIZE(GSLX680_FW);
00160     for (source_line = 0; source_line < source_len; source_line++)
00161 
00162     {
00163         /* init page trans, set the page val */
00164         if (0xf0 == ptr_fw[source_line].offset) {
00165             buf[0] = 0xf0;
00166             buf[1] = (uint8_t)(ptr_fw[source_line].val & 0x000000ff);
00167             INFO("GSL1680 Firmware set page: %02X", buf[1]);
00168             m_i2c->write(m_addr, (char *)buf, 2);
00169         } else {
00170             buf[0] = ptr_fw[source_line].offset;
00171             buf[1] = (uint8_t)(ptr_fw[source_line].val & 0x000000ff);
00172             buf[2] = (uint8_t)((ptr_fw[source_line].val & 0x0000ff00) >> 8);
00173             buf[3] = (uint8_t)((ptr_fw[source_line].val & 0x00ff0000) >> 16);
00174             buf[4] = (uint8_t)((ptr_fw[source_line].val & 0xff000000) >> 24);
00175             //INFO("GSL1680 Firmware write[%02X] = %08X", ptr_fw[source_line].offset, ptr_fw[source_line].val);
00176             m_i2c->write(m_addr, (char *)buf, 5);
00177         }
00178     }
00179 
00180     // Startup chip
00181     buf[0] = 0xe0;
00182     buf[1] = 0x00;
00183     m_i2c->write(m_addr, (char *)buf, 2);
00184     wait_us(100000);
00185 
00186     return r;
00187 }
00188 
00189 uint8_t RA8875::GSL1680_ReadRegU8(uint8_t reg, uint8_t * buf, int count) {
00190     uint8_t lbuf[1];
00191 
00192     if (buf == NULL) {
00193         buf = lbuf;
00194         count = 1;
00195     }
00196     m_i2c->write(m_addr, (char *)&reg, 1);
00197     m_i2c->read(m_addr, (char *)buf, count);
00198     return buf[0];
00199 }
00200 
00201 
00202 uint8_t RA8875::GSL1680_TouchPositions(void) {
00203     // [80] = # touch points
00204     // [81]       not used
00205     // [82]       not used
00206     // [83]       not used
00207     // [84] --+ Touch # 1 info
00208     // [85]   |
00209     // [86]   |
00210     // [87] --+
00211     // [88] --+ Touch # 2 info
00212     // [89]   |
00213     // [8A]   |
00214     // [8B] --+
00215     // ...
00216 
00217 #define TD_SPACE (4 + 4 * GSL1680_TOUCH_POINTS)
00218     if (m_irq->read() == 0) {
00219         uint8_t touch_data[TD_SPACE];
00220 
00221         GSL1680_ReadRegU8(0x80, touch_data, TD_SPACE);
00222         numberOfTouchPoints = touch_data[0];
00223         gesture = FT5206_GEST_ID_NO_GESTURE;    // no gesture support
00224 
00225         INFO("GSL1680 Touch %d points", numberOfTouchPoints);
00226         int tNdx = GSL1680_TOUCH_POINTS - 1;
00227         int dNdx = TD_SPACE - 1;
00228         for (; tNdx >= 0; tNdx--, dNdx -= 4) {
00229             uint16_t fingerAndY, AndX;
00230             fingerAndY = (uint16_t)(touch_data[dNdx - 0]) << 8 | (uint16_t)touch_data[dNdx - 1];
00231             AndX = (uint16_t)(touch_data[dNdx - 2]) << 8 | (uint16_t)touch_data[dNdx - 3];
00232             touchInfo[tNdx].coordinates = TranslateOrientation( AndX & 0x0FFFF, fingerAndY & 0x0FFF );
00233             touchInfo[tNdx].touchID = (fingerAndY >> 12);
00234             touchInfo[tNdx].touchCode = (numberOfTouchPoints > tNdx) ? touch : no_touch;
00235             //INFO("  Code %d, Finger %d, xy (%4d,%4d)",
00236             //    touchInfo[tNdx].touchCode, touchInfo[tNdx].touchID,
00237             //    touchInfo[tNdx].coordinates.x, touchInfo[tNdx].coordinates.y);
00238         }
00239     } else {
00240         numberOfTouchPoints = 0;
00241         ERR("GSL1680 Touch - else path, unexpected.");
00242     }
00243     return numberOfTouchPoints;
00244 }