This is the David Smart RA8875 Library with mods for working with FRDM-K64F
RA8875_Touch_GSL1680.cpp@166:53fd4a876dac, 2019-02-24 (annotated)
- Committer:
- WiredHome
- Date:
- Sun Feb 24 19:28:26 2019 +0000
- Revision:
- 166:53fd4a876dac
- Parent:
- 165:695c24cc5197
- Child:
- 168:37a0c4d8791c
Some refactoring, but mostly to improve support for GSL1680 controller to extract the touch id.
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
WiredHome | 166:53fd4a876dac | 1 | /// |
WiredHome | 166:53fd4a876dac | 2 | /// Support for Touch Controller GSL1680 |
WiredHome | 166:53fd4a876dac | 3 | /// |
WiredHome | 166:53fd4a876dac | 4 | /// Information is quite scarce for the SiLead GSL1680 Capacitive Touch controller. |
WiredHome | 166:53fd4a876dac | 5 | /// Further, this controller hosts a 32-bit micro, but is without flash memory, so |
WiredHome | 166:53fd4a876dac | 6 | /// after power-up, the program must be installed into the chip. This is done through |
WiredHome | 166:53fd4a876dac | 7 | /// the I2C interface. |
WiredHome | 166:53fd4a876dac | 8 | /// |
WiredHome | 166:53fd4a876dac | 9 | /// @caution To make it a bit more complicated, I cannot find any source |
WiredHome | 166:53fd4a876dac | 10 | /// for this micro, only "bytestream", which one has to hope is defect free. |
WiredHome | 166:53fd4a876dac | 11 | /// |
WiredHome | 166:53fd4a876dac | 12 | /// @caution To make it even more complicated, I do not have a display with this |
WiredHome | 166:53fd4a876dac | 13 | /// controller in it, so this body of work is the collective merge of what I've |
WiredHome | 166:53fd4a876dac | 14 | /// found and interpreted and interface converted to align with this library. |
WiredHome | 166:53fd4a876dac | 15 | /// |
WiredHome | 166:53fd4a876dac | 16 | /// @caution It is probably clear that this represents a work in process, and is |
WiredHome | 166:53fd4a876dac | 17 | /// in an attempt to make a working driver. |
WiredHome | 166:53fd4a876dac | 18 | /// |
WiredHome | 166:53fd4a876dac | 19 | /// http://linux-sunxi.org/GSL1680 has some useful information, a bit of which |
WiredHome | 166:53fd4a876dac | 20 | /// is replicated here in case that site changes/disappears. |
WiredHome | 166:53fd4a876dac | 21 | /// |
WiredHome | 166:53fd4a876dac | 22 | /// To read from the chip, just write a single byte with the register number to |
WiredHome | 166:53fd4a876dac | 23 | /// start to read, and then do as many reads as registers to read. |
WiredHome | 166:53fd4a876dac | 24 | /// |
WiredHome | 166:53fd4a876dac | 25 | /// The known registers are: |
WiredHome | 166:53fd4a876dac | 26 | /// * 0x00-0x7F: these registers are used to load portions of the firmware. |
WiredHome | 166:53fd4a876dac | 27 | /// * 0x80: contains the number of touches in the screen. |
WiredHome | 166:53fd4a876dac | 28 | /// ** If zero, the user isn't touching the screen; |
WiredHome | 166:53fd4a876dac | 29 | /// ** if one, only one finger is on the screen; |
WiredHome | 166:53fd4a876dac | 30 | /// ** if two, there are two fingers; and so on. |
WiredHome | 166:53fd4a876dac | 31 | /// * 0x84-0x87: contains the coordinates for the first touch. |
WiredHome | 166:53fd4a876dac | 32 | /// * 0x88-0x8B: contains the coordinates for the second touch. |
WiredHome | 166:53fd4a876dac | 33 | /// * 0x8C-0xAB: contains the coordinates for the third, fourth, and so on |
WiredHome | 166:53fd4a876dac | 34 | /// ** (up to five in some devices, up to ten in other), touches, |
WiredHome | 166:53fd4a876dac | 35 | /// in the same format than the previous ones (four bytes for each touch). |
WiredHome | 166:53fd4a876dac | 36 | /// * 0xE0: STATUS register |
WiredHome | 166:53fd4a876dac | 37 | /// * 0xE4, 0xBC-0xBF: some kind of control registers. Needed for uploading |
WiredHome | 166:53fd4a876dac | 38 | /// the firmware and soft resetting the chip |
WiredHome | 166:53fd4a876dac | 39 | /// (there's not more data available about them). |
WiredHome | 166:53fd4a876dac | 40 | /// * 0xF0: PAGE register. Contains the memory page number currently mapped |
WiredHome | 166:53fd4a876dac | 41 | /// in the 0x00-0x7F registers. |
WiredHome | 166:53fd4a876dac | 42 | /// |
WiredHome | 166:53fd4a876dac | 43 | /// Touch coordinates format |
WiredHome | 166:53fd4a876dac | 44 | /// The four bytes of each group of coordinates contains the X and Y values, |
WiredHome | 166:53fd4a876dac | 45 | /// and also the finger. |
WiredHome | 166:53fd4a876dac | 46 | /// |
WiredHome | 166:53fd4a876dac | 47 | /// * The first two bytes contains, in little endian format, |
WiredHome | 166:53fd4a876dac | 48 | /// ** the X coordinate in the 12 lower bits. |
WiredHome | 166:53fd4a876dac | 49 | /// * The other two bytes contains, in little endian format, |
WiredHome | 166:53fd4a876dac | 50 | /// ** the Y coordinate in the 12 lower bits. |
WiredHome | 166:53fd4a876dac | 51 | /// ** The 4 upper bits in the Y coordinate contains the finger identifier. |
WiredHome | 166:53fd4a876dac | 52 | /// |
WiredHome | 166:53fd4a876dac | 53 | /// Example: |
WiredHome | 166:53fd4a876dac | 54 | /// Let's say that the user touches the screen with one finger. The register 0x80 |
WiredHome | 166:53fd4a876dac | 55 | /// will contain 1, and registers 0x84 to 0x87 will contain the X and Y coordinates, |
WiredHome | 166:53fd4a876dac | 56 | /// and the finger identifier will be 1. |
WiredHome | 166:53fd4a876dac | 57 | /// |
WiredHome | 166:53fd4a876dac | 58 | /// Now the user, without removing the first finger, touches the screen with a second finger. |
WiredHome | 166:53fd4a876dac | 59 | /// The register 0x80 will contain 2. Registers 0x84 to 0x87 will contain the |
WiredHome | 166:53fd4a876dac | 60 | /// X and Y coordinates of the first touch and the finger identifier in them will be 1. |
WiredHome | 166:53fd4a876dac | 61 | /// Registers 0x88 to 0x8B will contain the X and Y coordinates of the second touch |
WiredHome | 166:53fd4a876dac | 62 | /// and the finger identifier in them will be 2. |
WiredHome | 166:53fd4a876dac | 63 | /// |
WiredHome | 166:53fd4a876dac | 64 | /// Now the user removes the first finger, keeping the second one. The register 0x80 |
WiredHome | 166:53fd4a876dac | 65 | /// will contain 1. Registers 0x84 to 0x87 will contain the X and Y coordinates, |
WiredHome | 166:53fd4a876dac | 66 | /// but the finger identifier will be 2, because that's the finger that remains |
WiredHome | 166:53fd4a876dac | 67 | /// in the screen. |
WiredHome | 165:695c24cc5197 | 68 | |
WiredHome | 165:695c24cc5197 | 69 | #include "RA8875.h" |
WiredHome | 166:53fd4a876dac | 70 | #include "RA8875_Touch_GSL1680_Firmware.h" |
WiredHome | 165:695c24cc5197 | 71 | |
WiredHome | 166:53fd4a876dac | 72 | #if 0 |
WiredHome | 165:695c24cc5197 | 73 | // Translate from GSL1680 Event Flag to Touch Code to API-match the |
WiredHome | 165:695c24cc5197 | 74 | // alternate resistive touch screen driver common in the RA8875 |
WiredHome | 165:695c24cc5197 | 75 | // displays. |
WiredHome | 165:695c24cc5197 | 76 | static const TouchCode_t GSL1680_EventFlagToTouchCode[4] = { |
WiredHome | 165:695c24cc5197 | 77 | touch, // 00b Put Down |
WiredHome | 165:695c24cc5197 | 78 | release, // 01b Put Up |
WiredHome | 165:695c24cc5197 | 79 | held, // 10b Contact |
WiredHome | 165:695c24cc5197 | 80 | no_touch // 11b Reserved |
WiredHome | 165:695c24cc5197 | 81 | }; |
WiredHome | 166:53fd4a876dac | 82 | #endif |
WiredHome | 165:695c24cc5197 | 83 | |
WiredHome | 165:695c24cc5197 | 84 | RetCode_t RA8875::GSL1680_Init() { |
WiredHome | 165:695c24cc5197 | 85 | RetCode_t r = noerror; |
WiredHome | 165:695c24cc5197 | 86 | uint8_t buf[5] = {0}; // addr + up to 4 Bytes data |
WiredHome | 165:695c24cc5197 | 87 | unsigned int source_line = 0; |
WiredHome | 165:695c24cc5197 | 88 | unsigned int source_len; |
WiredHome | 165:695c24cc5197 | 89 | const struct fw_data *ptr_fw; |
WiredHome | 165:695c24cc5197 | 90 | |
WiredHome | 165:695c24cc5197 | 91 | // Wake it |
WiredHome | 165:695c24cc5197 | 92 | m_wake->write(false); |
WiredHome | 165:695c24cc5197 | 93 | wait_ms(20); |
WiredHome | 165:695c24cc5197 | 94 | m_wake->write(true); |
WiredHome | 165:695c24cc5197 | 95 | wait_ms(20); |
WiredHome | 165:695c24cc5197 | 96 | |
WiredHome | 165:695c24cc5197 | 97 | // Clear reg |
WiredHome | 165:695c24cc5197 | 98 | buf[0] = 0xe0; |
WiredHome | 165:695c24cc5197 | 99 | buf[1] = 0x88; |
WiredHome | 165:695c24cc5197 | 100 | m_i2c->write(m_addr, (char *)buf, 2); |
WiredHome | 165:695c24cc5197 | 101 | wait_ms(1); |
WiredHome | 165:695c24cc5197 | 102 | buf[0] = 0x80; |
WiredHome | 165:695c24cc5197 | 103 | buf[1] = 0x03; |
WiredHome | 165:695c24cc5197 | 104 | m_i2c->write(m_addr, (char *)buf, 2); |
WiredHome | 165:695c24cc5197 | 105 | wait_ms(1); |
WiredHome | 165:695c24cc5197 | 106 | buf[0] = 0xe4; |
WiredHome | 165:695c24cc5197 | 107 | buf[1] = 0x04; |
WiredHome | 165:695c24cc5197 | 108 | m_i2c->write(m_addr, (char *)buf, 2); |
WiredHome | 165:695c24cc5197 | 109 | wait_ms(1); |
WiredHome | 165:695c24cc5197 | 110 | buf[0] = 0xe0; |
WiredHome | 165:695c24cc5197 | 111 | buf[1] = 0x00; |
WiredHome | 165:695c24cc5197 | 112 | m_i2c->write(m_addr, (char *)buf, 2); |
WiredHome | 165:695c24cc5197 | 113 | wait_ms(1); |
WiredHome | 165:695c24cc5197 | 114 | |
WiredHome | 165:695c24cc5197 | 115 | // Reset |
WiredHome | 165:695c24cc5197 | 116 | buf[0] = 0xe0; |
WiredHome | 165:695c24cc5197 | 117 | buf[1] = 0x88; |
WiredHome | 165:695c24cc5197 | 118 | m_i2c->write(m_addr, (char *)buf, 2); |
WiredHome | 165:695c24cc5197 | 119 | wait_ms(1); |
WiredHome | 165:695c24cc5197 | 120 | buf[0] = 0xe4; |
WiredHome | 165:695c24cc5197 | 121 | buf[1] = 0x04; |
WiredHome | 165:695c24cc5197 | 122 | m_i2c->write(m_addr, (char *)buf, 2); |
WiredHome | 165:695c24cc5197 | 123 | wait_ms(1); |
WiredHome | 165:695c24cc5197 | 124 | buf[0] = 0xbc; |
WiredHome | 165:695c24cc5197 | 125 | buf[1] = 0x00; |
WiredHome | 165:695c24cc5197 | 126 | buf[2] = 0x00; |
WiredHome | 165:695c24cc5197 | 127 | buf[3] = 0x00; |
WiredHome | 165:695c24cc5197 | 128 | buf[4] = 0x00; |
WiredHome | 165:695c24cc5197 | 129 | m_i2c->write(m_addr, (char *)buf, 5); |
WiredHome | 165:695c24cc5197 | 130 | wait_ms(1); |
WiredHome | 165:695c24cc5197 | 131 | |
WiredHome | 165:695c24cc5197 | 132 | // Load Firmware |
WiredHome | 165:695c24cc5197 | 133 | ptr_fw = GSLX680_FW; |
WiredHome | 165:695c24cc5197 | 134 | source_len = ARRAY_SIZE(GSLX680_FW); |
WiredHome | 165:695c24cc5197 | 135 | for (source_line = 0; source_line < source_len; source_line++) |
WiredHome | 165:695c24cc5197 | 136 | { |
WiredHome | 165:695c24cc5197 | 137 | /* init page trans, set the page val */ |
WiredHome | 165:695c24cc5197 | 138 | if (0xf0 == ptr_fw[source_line].offset) |
WiredHome | 165:695c24cc5197 | 139 | { |
WiredHome | 165:695c24cc5197 | 140 | buf[0] = 0xf0; |
WiredHome | 165:695c24cc5197 | 141 | buf[1] = (uint8_t)(ptr_fw[source_line].val & 0x000000ff); |
WiredHome | 165:695c24cc5197 | 142 | m_i2c->write(m_addr, (char *)buf, 2); |
WiredHome | 165:695c24cc5197 | 143 | } |
WiredHome | 165:695c24cc5197 | 144 | else |
WiredHome | 165:695c24cc5197 | 145 | { |
WiredHome | 165:695c24cc5197 | 146 | buf[0] = ptr_fw[source_line].offset; |
WiredHome | 165:695c24cc5197 | 147 | buf[1] = (uint8_t)(ptr_fw[source_line].val & 0x000000ff); |
WiredHome | 165:695c24cc5197 | 148 | buf[2] = (uint8_t)((ptr_fw[source_line].val & 0x0000ff00) >> 8); |
WiredHome | 165:695c24cc5197 | 149 | buf[3] = (uint8_t)((ptr_fw[source_line].val & 0x00ff0000) >> 16); |
WiredHome | 165:695c24cc5197 | 150 | buf[4] = (uint8_t)((ptr_fw[source_line].val & 0xff000000) >> 24); |
WiredHome | 165:695c24cc5197 | 151 | m_i2c->write(m_addr, (char *)buf, 5); |
WiredHome | 165:695c24cc5197 | 152 | } |
WiredHome | 165:695c24cc5197 | 153 | } |
WiredHome | 165:695c24cc5197 | 154 | |
WiredHome | 165:695c24cc5197 | 155 | // Startup chip |
WiredHome | 165:695c24cc5197 | 156 | buf[0] = 0xe0; |
WiredHome | 165:695c24cc5197 | 157 | buf[1] = 0x00; |
WiredHome | 165:695c24cc5197 | 158 | m_i2c->write(m_addr, (char *)buf, 2); |
WiredHome | 165:695c24cc5197 | 159 | wait_ms(100); |
WiredHome | 165:695c24cc5197 | 160 | |
WiredHome | 165:695c24cc5197 | 161 | return r; |
WiredHome | 165:695c24cc5197 | 162 | } |
WiredHome | 165:695c24cc5197 | 163 | |
WiredHome | 165:695c24cc5197 | 164 | uint8_t RA8875::GSL1680_ReadRegU8(uint8_t reg, uint8_t * buf, int count) { |
WiredHome | 165:695c24cc5197 | 165 | uint8_t lbuf[1]; |
WiredHome | 165:695c24cc5197 | 166 | |
WiredHome | 165:695c24cc5197 | 167 | if (buf == NULL) { |
WiredHome | 165:695c24cc5197 | 168 | buf = lbuf; |
WiredHome | 165:695c24cc5197 | 169 | count = 1; |
WiredHome | 165:695c24cc5197 | 170 | } |
WiredHome | 165:695c24cc5197 | 171 | m_i2c->write(m_addr, (char *)®, 1); |
WiredHome | 165:695c24cc5197 | 172 | m_i2c->read(m_addr, (char *)buf, count); |
WiredHome | 165:695c24cc5197 | 173 | return buf[0]; |
WiredHome | 165:695c24cc5197 | 174 | } |
WiredHome | 165:695c24cc5197 | 175 | |
WiredHome | 165:695c24cc5197 | 176 | |
WiredHome | 165:695c24cc5197 | 177 | uint8_t RA8875::GSL1680_TouchPositions(void) { |
WiredHome | 166:53fd4a876dac | 178 | uint16_t fingerAndY, AndX; |
WiredHome | 166:53fd4a876dac | 179 | |
WiredHome | 166:53fd4a876dac | 180 | // [80] = # touch points |
WiredHome | 166:53fd4a876dac | 181 | // [81] not used |
WiredHome | 166:53fd4a876dac | 182 | // [82] not used |
WiredHome | 166:53fd4a876dac | 183 | // [83] not used |
WiredHome | 166:53fd4a876dac | 184 | // [84] --+ Touch # 1 info |
WiredHome | 166:53fd4a876dac | 185 | // [85] | |
WiredHome | 166:53fd4a876dac | 186 | // [86] | |
WiredHome | 166:53fd4a876dac | 187 | // [87] --+ |
WiredHome | 166:53fd4a876dac | 188 | // [88] --+ Touch # 2 info |
WiredHome | 166:53fd4a876dac | 189 | // [89] | |
WiredHome | 166:53fd4a876dac | 190 | // [8A] | |
WiredHome | 166:53fd4a876dac | 191 | // [8B] --+ |
WiredHome | 166:53fd4a876dac | 192 | // ... |
WiredHome | 166:53fd4a876dac | 193 | #define TD_SPACE (4 + 4 * GSL1680_TOUCH_POINTS) |
WiredHome | 165:695c24cc5197 | 194 | if (m_irq->read() == 1) { |
WiredHome | 166:53fd4a876dac | 195 | uint8_t touch_data[TD_SPACE]; |
WiredHome | 165:695c24cc5197 | 196 | |
WiredHome | 166:53fd4a876dac | 197 | GSL1680_ReadRegU8(0x80, touch_data, TD_SPACE); |
WiredHome | 165:695c24cc5197 | 198 | numberOfTouchPoints = touch_data[0]; |
WiredHome | 165:695c24cc5197 | 199 | gesture = FT5206_GEST_ID_NO_GESTURE; // no gesture support |
WiredHome | 165:695c24cc5197 | 200 | |
WiredHome | 166:53fd4a876dac | 201 | int tNdx = GSL1680_TOUCH_POINTS - 1; |
WiredHome | 166:53fd4a876dac | 202 | int dNdx = TD_SPACE - 1; |
WiredHome | 166:53fd4a876dac | 203 | for ( ; tNdx >= 0; tNdx--, dNdx -= 4) { |
WiredHome | 166:53fd4a876dac | 204 | fingerAndY = (uint16_t)(touch_data[dNdx-0])<<8 | (uint16_t)touch_data[dNdx-1]; |
WiredHome | 166:53fd4a876dac | 205 | AndX = (uint16_t)(touch_data[dNdx-2])<<8 | (uint16_t)touch_data[dNdx-3]; |
WiredHome | 166:53fd4a876dac | 206 | touchInfo[tNdx].coordinates.y = fingerAndY & 0x0FFF; |
WiredHome | 166:53fd4a876dac | 207 | touchInfo[tNdx].coordinates.x = AndX & 0x0FFFF; |
WiredHome | 166:53fd4a876dac | 208 | touchInfo[tNdx].touchID = (fingerAndY >> 12); |
WiredHome | 166:53fd4a876dac | 209 | touchInfo[tNdx].touchCode = (numberOfTouchPoints > tNdx) ? touch : no_touch; |
WiredHome | 166:53fd4a876dac | 210 | } |
WiredHome | 165:695c24cc5197 | 211 | } else { |
WiredHome | 165:695c24cc5197 | 212 | numberOfTouchPoints = 0; |
WiredHome | 165:695c24cc5197 | 213 | } |
WiredHome | 165:695c24cc5197 | 214 | return numberOfTouchPoints; |
WiredHome | 165:695c24cc5197 | 215 | } |