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)

Committer:
WiredHome
Date:
Mon Nov 25 19:55:17 2019 +0000
Revision:
193:74f80834d59d
Parent:
182:8832d03a2a29
Child:
197:853d08e2fb53
Improve debouncing of resistive touch.; Minor format changes for easier maintenance.

Who changed what in which revision?

UserRevisionLine numberNew 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 182:8832d03a2a29 9 /// @attention 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 182:8832d03a2a29 12 /// @attention 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 182:8832d03a2a29 16 /// @attention It is probably clear that this represents a work in process, and is
WiredHome 170:7e26d51bc48b 17 /// 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 171:f92c0f1f6db4 72 //#define DEBUG "RAGL"
WiredHome 168:37a0c4d8791c 73 // ...
WiredHome 168:37a0c4d8791c 74 // INFO("Stuff to show %d", var); // new-line is automatically appended
WiredHome 168:37a0c4d8791c 75 //
WiredHome 168:37a0c4d8791c 76 #if (defined(DEBUG) && !defined(TARGET_LPC11U24))
WiredHome 168:37a0c4d8791c 77 #define INFO(x, ...) std::printf("[INF %s %4d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__);
WiredHome 168:37a0c4d8791c 78 #define WARN(x, ...) std::printf("[WRN %s %4d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__);
WiredHome 168:37a0c4d8791c 79 #define ERR(x, ...) std::printf("[ERR %s %4d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__);
WiredHome 193:74f80834d59d 80 static void HexDump(const char * title, const uint8_t * p, int count) {
WiredHome 168:37a0c4d8791c 81 int i;
WiredHome 168:37a0c4d8791c 82 char buf[100] = "0000: ";
WiredHome 168:37a0c4d8791c 83
WiredHome 168:37a0c4d8791c 84 if (*title)
WiredHome 168:37a0c4d8791c 85 INFO("%s", title);
WiredHome 168:37a0c4d8791c 86 for (i=0; i<count; ) {
WiredHome 168:37a0c4d8791c 87 sprintf(buf + strlen(buf), "%02X ", *(p+i));
WiredHome 168:37a0c4d8791c 88 if ((++i & 0x0F) == 0x00) {
WiredHome 168:37a0c4d8791c 89 INFO("%s", buf);
WiredHome 168:37a0c4d8791c 90 if (i < count)
WiredHome 168:37a0c4d8791c 91 sprintf(buf, "%04X: ", i);
WiredHome 168:37a0c4d8791c 92 else
WiredHome 168:37a0c4d8791c 93 buf[0] = '\0';
WiredHome 168:37a0c4d8791c 94 }
WiredHome 168:37a0c4d8791c 95 }
WiredHome 168:37a0c4d8791c 96 if (strlen(buf))
WiredHome 168:37a0c4d8791c 97 INFO("%s", buf);
WiredHome 168:37a0c4d8791c 98 }
WiredHome 168:37a0c4d8791c 99 #else
WiredHome 168:37a0c4d8791c 100 #define INFO(x, ...)
WiredHome 168:37a0c4d8791c 101 #define WARN(x, ...)
WiredHome 168:37a0c4d8791c 102 #define ERR(x, ...)
WiredHome 168:37a0c4d8791c 103 #define HexDump(a, b, c)
WiredHome 168:37a0c4d8791c 104 #endif
WiredHome 168:37a0c4d8791c 105
WiredHome 168:37a0c4d8791c 106
WiredHome 166:53fd4a876dac 107 #if 0
WiredHome 165:695c24cc5197 108 // Translate from GSL1680 Event Flag to Touch Code to API-match the
WiredHome 165:695c24cc5197 109 // alternate resistive touch screen driver common in the RA8875
WiredHome 165:695c24cc5197 110 // displays.
WiredHome 165:695c24cc5197 111 static const TouchCode_t GSL1680_EventFlagToTouchCode[4] = {
WiredHome 165:695c24cc5197 112 touch, // 00b Put Down
WiredHome 165:695c24cc5197 113 release, // 01b Put Up
WiredHome 165:695c24cc5197 114 held, // 10b Contact
WiredHome 165:695c24cc5197 115 no_touch // 11b Reserved
WiredHome 165:695c24cc5197 116 };
WiredHome 166:53fd4a876dac 117 #endif
WiredHome 165:695c24cc5197 118
WiredHome 165:695c24cc5197 119 RetCode_t RA8875::GSL1680_Init() {
WiredHome 165:695c24cc5197 120 RetCode_t r = noerror;
WiredHome 165:695c24cc5197 121 uint8_t buf[5] = {0}; // addr + up to 4 Bytes data
WiredHome 165:695c24cc5197 122 unsigned int source_line = 0;
WiredHome 165:695c24cc5197 123 unsigned int source_len;
WiredHome 165:695c24cc5197 124 const struct fw_data *ptr_fw;
WiredHome 165:695c24cc5197 125
WiredHome 168:37a0c4d8791c 126 INFO("GSL1680_Init()");
WiredHome 165:695c24cc5197 127 // Wake it
WiredHome 165:695c24cc5197 128 m_wake->write(false);
WiredHome 165:695c24cc5197 129 wait_ms(20);
WiredHome 165:695c24cc5197 130 m_wake->write(true);
WiredHome 165:695c24cc5197 131 wait_ms(20);
WiredHome 165:695c24cc5197 132
WiredHome 165:695c24cc5197 133 // Clear reg
WiredHome 165:695c24cc5197 134 buf[0] = 0xe0;
WiredHome 165:695c24cc5197 135 buf[1] = 0x88;
WiredHome 165:695c24cc5197 136 m_i2c->write(m_addr, (char *)buf, 2);
WiredHome 165:695c24cc5197 137 wait_ms(1);
WiredHome 165:695c24cc5197 138 buf[0] = 0x80;
WiredHome 165:695c24cc5197 139 buf[1] = 0x03;
WiredHome 165:695c24cc5197 140 m_i2c->write(m_addr, (char *)buf, 2);
WiredHome 165:695c24cc5197 141 wait_ms(1);
WiredHome 165:695c24cc5197 142 buf[0] = 0xe4;
WiredHome 165:695c24cc5197 143 buf[1] = 0x04;
WiredHome 165:695c24cc5197 144 m_i2c->write(m_addr, (char *)buf, 2);
WiredHome 165:695c24cc5197 145 wait_ms(1);
WiredHome 165:695c24cc5197 146 buf[0] = 0xe0;
WiredHome 165:695c24cc5197 147 buf[1] = 0x00;
WiredHome 165:695c24cc5197 148 m_i2c->write(m_addr, (char *)buf, 2);
WiredHome 165:695c24cc5197 149 wait_ms(1);
WiredHome 165:695c24cc5197 150
WiredHome 165:695c24cc5197 151 // Reset
WiredHome 165:695c24cc5197 152 buf[0] = 0xe0;
WiredHome 165:695c24cc5197 153 buf[1] = 0x88;
WiredHome 165:695c24cc5197 154 m_i2c->write(m_addr, (char *)buf, 2);
WiredHome 165:695c24cc5197 155 wait_ms(1);
WiredHome 165:695c24cc5197 156 buf[0] = 0xe4;
WiredHome 165:695c24cc5197 157 buf[1] = 0x04;
WiredHome 165:695c24cc5197 158 m_i2c->write(m_addr, (char *)buf, 2);
WiredHome 165:695c24cc5197 159 wait_ms(1);
WiredHome 165:695c24cc5197 160 buf[0] = 0xbc;
WiredHome 165:695c24cc5197 161 buf[1] = 0x00;
WiredHome 165:695c24cc5197 162 buf[2] = 0x00;
WiredHome 165:695c24cc5197 163 buf[3] = 0x00;
WiredHome 165:695c24cc5197 164 buf[4] = 0x00;
WiredHome 165:695c24cc5197 165 m_i2c->write(m_addr, (char *)buf, 5);
WiredHome 165:695c24cc5197 166 wait_ms(1);
WiredHome 165:695c24cc5197 167
WiredHome 165:695c24cc5197 168 // Load Firmware
WiredHome 165:695c24cc5197 169 ptr_fw = GSLX680_FW;
WiredHome 165:695c24cc5197 170 source_len = ARRAY_SIZE(GSLX680_FW);
WiredHome 165:695c24cc5197 171 for (source_line = 0; source_line < source_len; source_line++)
WiredHome 193:74f80834d59d 172
WiredHome 165:695c24cc5197 173 {
WiredHome 165:695c24cc5197 174 /* init page trans, set the page val */
WiredHome 193:74f80834d59d 175 if (0xf0 == ptr_fw[source_line].offset) {
WiredHome 165:695c24cc5197 176 buf[0] = 0xf0;
WiredHome 165:695c24cc5197 177 buf[1] = (uint8_t)(ptr_fw[source_line].val & 0x000000ff);
WiredHome 168:37a0c4d8791c 178 INFO("GSL1680 Firmware set page: %02X", buf[1]);
WiredHome 165:695c24cc5197 179 m_i2c->write(m_addr, (char *)buf, 2);
WiredHome 193:74f80834d59d 180 } else {
WiredHome 165:695c24cc5197 181 buf[0] = ptr_fw[source_line].offset;
WiredHome 165:695c24cc5197 182 buf[1] = (uint8_t)(ptr_fw[source_line].val & 0x000000ff);
WiredHome 165:695c24cc5197 183 buf[2] = (uint8_t)((ptr_fw[source_line].val & 0x0000ff00) >> 8);
WiredHome 165:695c24cc5197 184 buf[3] = (uint8_t)((ptr_fw[source_line].val & 0x00ff0000) >> 16);
WiredHome 165:695c24cc5197 185 buf[4] = (uint8_t)((ptr_fw[source_line].val & 0xff000000) >> 24);
WiredHome 168:37a0c4d8791c 186 //INFO("GSL1680 Firmware write[%02X] = %08X", ptr_fw[source_line].offset, ptr_fw[source_line].val);
WiredHome 165:695c24cc5197 187 m_i2c->write(m_addr, (char *)buf, 5);
WiredHome 165:695c24cc5197 188 }
WiredHome 165:695c24cc5197 189 }
WiredHome 165:695c24cc5197 190
WiredHome 165:695c24cc5197 191 // Startup chip
WiredHome 165:695c24cc5197 192 buf[0] = 0xe0;
WiredHome 165:695c24cc5197 193 buf[1] = 0x00;
WiredHome 165:695c24cc5197 194 m_i2c->write(m_addr, (char *)buf, 2);
WiredHome 165:695c24cc5197 195 wait_ms(100);
WiredHome 165:695c24cc5197 196
WiredHome 165:695c24cc5197 197 return r;
WiredHome 165:695c24cc5197 198 }
WiredHome 165:695c24cc5197 199
WiredHome 165:695c24cc5197 200 uint8_t RA8875::GSL1680_ReadRegU8(uint8_t reg, uint8_t * buf, int count) {
WiredHome 165:695c24cc5197 201 uint8_t lbuf[1];
WiredHome 165:695c24cc5197 202
WiredHome 165:695c24cc5197 203 if (buf == NULL) {
WiredHome 165:695c24cc5197 204 buf = lbuf;
WiredHome 165:695c24cc5197 205 count = 1;
WiredHome 165:695c24cc5197 206 }
WiredHome 165:695c24cc5197 207 m_i2c->write(m_addr, (char *)&reg, 1);
WiredHome 165:695c24cc5197 208 m_i2c->read(m_addr, (char *)buf, count);
WiredHome 165:695c24cc5197 209 return buf[0];
WiredHome 165:695c24cc5197 210 }
WiredHome 165:695c24cc5197 211
WiredHome 165:695c24cc5197 212
WiredHome 165:695c24cc5197 213 uint8_t RA8875::GSL1680_TouchPositions(void) {
WiredHome 166:53fd4a876dac 214 // [80] = # touch points
WiredHome 166:53fd4a876dac 215 // [81] not used
WiredHome 166:53fd4a876dac 216 // [82] not used
WiredHome 166:53fd4a876dac 217 // [83] not used
WiredHome 166:53fd4a876dac 218 // [84] --+ Touch # 1 info
WiredHome 166:53fd4a876dac 219 // [85] |
WiredHome 166:53fd4a876dac 220 // [86] |
WiredHome 166:53fd4a876dac 221 // [87] --+
WiredHome 166:53fd4a876dac 222 // [88] --+ Touch # 2 info
WiredHome 166:53fd4a876dac 223 // [89] |
WiredHome 166:53fd4a876dac 224 // [8A] |
WiredHome 166:53fd4a876dac 225 // [8B] --+
WiredHome 166:53fd4a876dac 226 // ...
WiredHome 193:74f80834d59d 227
WiredHome 166:53fd4a876dac 228 #define TD_SPACE (4 + 4 * GSL1680_TOUCH_POINTS)
WiredHome 170:7e26d51bc48b 229 if (m_irq->read() == 0) {
WiredHome 166:53fd4a876dac 230 uint8_t touch_data[TD_SPACE];
WiredHome 165:695c24cc5197 231
WiredHome 166:53fd4a876dac 232 GSL1680_ReadRegU8(0x80, touch_data, TD_SPACE);
WiredHome 165:695c24cc5197 233 numberOfTouchPoints = touch_data[0];
WiredHome 165:695c24cc5197 234 gesture = FT5206_GEST_ID_NO_GESTURE; // no gesture support
WiredHome 165:695c24cc5197 235
WiredHome 168:37a0c4d8791c 236 INFO("GSL1680 Touch %d points", numberOfTouchPoints);
WiredHome 166:53fd4a876dac 237 int tNdx = GSL1680_TOUCH_POINTS - 1;
WiredHome 166:53fd4a876dac 238 int dNdx = TD_SPACE - 1;
WiredHome 166:53fd4a876dac 239 for ( ; tNdx >= 0; tNdx--, dNdx -= 4) {
WiredHome 182:8832d03a2a29 240 uint16_t fingerAndY, AndX;
WiredHome 166:53fd4a876dac 241 fingerAndY = (uint16_t)(touch_data[dNdx-0])<<8 | (uint16_t)touch_data[dNdx-1];
WiredHome 166:53fd4a876dac 242 AndX = (uint16_t)(touch_data[dNdx-2])<<8 | (uint16_t)touch_data[dNdx-3];
WiredHome 166:53fd4a876dac 243 touchInfo[tNdx].coordinates.y = fingerAndY & 0x0FFF;
WiredHome 166:53fd4a876dac 244 touchInfo[tNdx].coordinates.x = AndX & 0x0FFFF;
WiredHome 166:53fd4a876dac 245 touchInfo[tNdx].touchID = (fingerAndY >> 12);
WiredHome 168:37a0c4d8791c 246 touchInfo[tNdx].touchCode = (numberOfTouchPoints > tNdx) ? touch : no_touch;
WiredHome 168:37a0c4d8791c 247 //INFO(" Code %d, Finger %d, xy (%4d,%4d)",
WiredHome 168:37a0c4d8791c 248 // touchInfo[tNdx].touchCode, touchInfo[tNdx].touchID,
WiredHome 168:37a0c4d8791c 249 // touchInfo[tNdx].coordinates.x, touchInfo[tNdx].coordinates.y);
WiredHome 166:53fd4a876dac 250 }
WiredHome 165:695c24cc5197 251 } else {
WiredHome 165:695c24cc5197 252 numberOfTouchPoints = 0;
WiredHome 170:7e26d51bc48b 253 ERR("GSL1680 Touch - else path, unexpected.");
WiredHome 165:695c24cc5197 254 }
WiredHome 165:695c24cc5197 255 return numberOfTouchPoints;
WiredHome 165:695c24cc5197 256 }