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:
Thu Aug 08 11:29:48 2019 +0000
Revision:
183:808f272e481e
Parent:
182:8832d03a2a29
Child:
193:74f80834d59d
Minor code-cleanup

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