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:
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?

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 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 *)&reg, 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 }