KSM edits to RA8875

Dependents:   Liz_Test_Code

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 /// @caution 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 /// @caution 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 /// @caution 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 #include "RA8875.h"
00070 #include "RA8875_Touch_GSL1680_Firmware.h"
00071 
00072 //#define DEBUG "RAGL"
00073 // ...
00074 // INFO("Stuff to show %d", var); // new-line is automatically appended
00075 //
00076 #if (defined(DEBUG) && !defined(TARGET_LPC11U24))
00077 #define INFO(x, ...) std::printf("[INF %s %4d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__);
00078 #define WARN(x, ...) std::printf("[WRN %s %4d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__);
00079 #define ERR(x, ...)  std::printf("[ERR %s %4d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__);
00080 static void HexDump(const char * title, const uint8_t * p, int count)
00081 {
00082     int i;
00083     char buf[100] = "0000: ";
00084 
00085     if (*title)
00086         INFO("%s", title);
00087     for (i=0; i<count; ) {
00088         sprintf(buf + strlen(buf), "%02X ", *(p+i));
00089         if ((++i & 0x0F) == 0x00) {
00090             INFO("%s", buf);
00091             if (i < count)
00092                 sprintf(buf, "%04X: ", i);
00093             else
00094                 buf[0] = '\0';
00095         }
00096     }
00097     if (strlen(buf))
00098         INFO("%s", buf);
00099 }
00100 #else
00101 #define INFO(x, ...)
00102 #define WARN(x, ...)
00103 #define ERR(x, ...)
00104 #define HexDump(a, b, c)
00105 #endif
00106 
00107 
00108 #if 0
00109 // Translate from GSL1680 Event Flag to Touch Code to API-match the
00110 // alternate resistive touch screen driver common in the RA8875
00111 // displays.
00112 static const TouchCode_t GSL1680_EventFlagToTouchCode[4] = {
00113     touch,      // 00b Put Down
00114     release,    // 01b Put Up
00115     held,       // 10b Contact
00116     no_touch    // 11b Reserved
00117 };
00118 #endif
00119 
00120 RetCode_t RA8875::GSL1680_Init() {
00121     RetCode_t r = noerror;
00122     uint8_t buf[5] = {0};   // addr + up to 4 Bytes data
00123     unsigned int source_line = 0;
00124     unsigned int source_len;
00125     const struct fw_data *ptr_fw;
00126 
00127     INFO("GSL1680_Init()");
00128     // Wake it
00129     m_wake->write(false);
00130     wait_ms(20);
00131     m_wake->write(true);
00132     wait_ms(20);
00133     
00134     // Clear reg
00135     buf[0] = 0xe0;
00136     buf[1] = 0x88;
00137     m_i2c->write(m_addr, (char *)buf, 2);
00138     wait_ms(1);
00139     buf[0] = 0x80;
00140     buf[1] = 0x03;
00141     m_i2c->write(m_addr, (char *)buf, 2);
00142     wait_ms(1);
00143     buf[0] = 0xe4;
00144     buf[1] = 0x04;
00145     m_i2c->write(m_addr, (char *)buf, 2);
00146     wait_ms(1);
00147     buf[0] = 0xe0;
00148     buf[1] = 0x00;
00149     m_i2c->write(m_addr, (char *)buf, 2);
00150     wait_ms(1);
00151     
00152     // Reset
00153     buf[0] = 0xe0;
00154     buf[1] = 0x88;
00155     m_i2c->write(m_addr, (char *)buf, 2);
00156     wait_ms(1);
00157     buf[0] = 0xe4;
00158     buf[1] = 0x04;
00159     m_i2c->write(m_addr, (char *)buf, 2);
00160     wait_ms(1);
00161     buf[0] = 0xbc;
00162     buf[1] = 0x00;
00163     buf[2] = 0x00;
00164     buf[3] = 0x00;
00165     buf[4] = 0x00;
00166     m_i2c->write(m_addr, (char *)buf, 5);
00167     wait_ms(1);
00168     
00169     // Load Firmware
00170     ptr_fw = GSLX680_FW;
00171     source_len = ARRAY_SIZE(GSLX680_FW);
00172     for (source_line = 0; source_line < source_len; source_line++) 
00173     {
00174         /* init page trans, set the page val */
00175         if (0xf0 == ptr_fw[source_line].offset)
00176         {
00177             buf[0] = 0xf0;
00178             buf[1] = (uint8_t)(ptr_fw[source_line].val & 0x000000ff);
00179             INFO("GSL1680 Firmware set page: %02X", buf[1]);
00180             m_i2c->write(m_addr, (char *)buf, 2);
00181         }
00182         else 
00183         {
00184             buf[0] = ptr_fw[source_line].offset;
00185             buf[1] = (uint8_t)(ptr_fw[source_line].val & 0x000000ff);
00186             buf[2] = (uint8_t)((ptr_fw[source_line].val & 0x0000ff00) >> 8);
00187             buf[3] = (uint8_t)((ptr_fw[source_line].val & 0x00ff0000) >> 16);
00188             buf[4] = (uint8_t)((ptr_fw[source_line].val & 0xff000000) >> 24);
00189             //INFO("GSL1680 Firmware write[%02X] = %08X", ptr_fw[source_line].offset, ptr_fw[source_line].val);
00190             m_i2c->write(m_addr, (char *)buf, 5);
00191         }
00192     }
00193     
00194     // Startup chip
00195     buf[0] = 0xe0;
00196     buf[1] = 0x00;
00197     m_i2c->write(m_addr, (char *)buf, 2);
00198     wait_ms(100);
00199     
00200     return r;
00201 }
00202 
00203 uint8_t RA8875::GSL1680_ReadRegU8(uint8_t reg, uint8_t * buf, int count) {
00204     uint8_t lbuf[1];
00205     
00206     if (buf == NULL) {
00207         buf = lbuf;
00208         count = 1;
00209     }
00210     m_i2c->write(m_addr, (char *)&reg, 1);
00211     m_i2c->read(m_addr, (char *)buf, count);
00212     return buf[0];
00213 }
00214 
00215 
00216 uint8_t RA8875::GSL1680_TouchPositions(void) {
00217     uint16_t fingerAndY, AndX;
00218 
00219     // [80] = # touch points
00220     // [81]       not used
00221     // [82]       not used
00222     // [83]       not used
00223     // [84] --+ Touch # 1 info
00224     // [85]   |
00225     // [86]   |
00226     // [87] --+
00227     // [88] --+ Touch # 2 info
00228     // [89]   |
00229     // [8A]   |
00230     // [8B] --+
00231     // ...    
00232     #define TD_SPACE (4 + 4 * GSL1680_TOUCH_POINTS)
00233     if (m_irq->read() == 0) {
00234         uint8_t touch_data[TD_SPACE];
00235 
00236         GSL1680_ReadRegU8(0x80, touch_data, TD_SPACE);
00237         numberOfTouchPoints = touch_data[0];
00238         gesture = FT5206_GEST_ID_NO_GESTURE;    // no gesture support
00239 
00240         INFO("GSL1680 Touch %d points", numberOfTouchPoints);
00241         int tNdx = GSL1680_TOUCH_POINTS - 1;
00242         int dNdx = TD_SPACE - 1;
00243         for ( ; tNdx >= 0; tNdx--, dNdx -= 4) {
00244             fingerAndY = (uint16_t)(touch_data[dNdx-0])<<8 | (uint16_t)touch_data[dNdx-1];
00245             AndX = (uint16_t)(touch_data[dNdx-2])<<8 | (uint16_t)touch_data[dNdx-3];
00246             touchInfo[tNdx].coordinates.y = fingerAndY & 0x0FFF;
00247             touchInfo[tNdx].coordinates.x = AndX & 0x0FFFF;
00248             touchInfo[tNdx].touchID = (fingerAndY >> 12);
00249             touchInfo[tNdx].touchCode = (numberOfTouchPoints > tNdx) ? touch : no_touch;
00250             //INFO("  Code %d, Finger %d, xy (%4d,%4d)",
00251             //    touchInfo[tNdx].touchCode, touchInfo[tNdx].touchID,
00252             //    touchInfo[tNdx].coordinates.x, touchInfo[tNdx].coordinates.y);
00253         }
00254     } else {
00255         numberOfTouchPoints = 0;
00256         ERR("GSL1680 Touch - else path, unexpected.");
00257     }
00258     return numberOfTouchPoints;
00259 }