SensorLib 0.5.0
Multi-platform sensor driver library for Arduino, PlatformIO, and ESP-IDF
Loading...
Searching...
No Matches
TouchDrvGT911.cpp
Go to the documentation of this file.
1
30#include "../SensorBuildOpt.h"
31#if !SENSORLIB_EXCLUDE_TOUCH_GT911
32
33#include "TouchDrvGT911.hpp"
34
36{
37 if (_pinsCfg.irqPin != -1) {
38 hal->pinMode(_pinsCfg.irqPin, OUTPUT);
39 hal->digitalWrite(_pinsCfg.irqPin, LOW);
40 }
41 writeCommand(0x05);
42
43 /*
44 * Depending on the chip and platform, setting it to input after removing sleep will affect power consumption.
45 * The chip platform determines whether
46 *
47 * * */
48 // if (_pinsCfg.irqPin != -1) {
49 // hal->digitalWrite(_pinsCfg.irqPin, INPUT);
50 // }
51}
52
54{
55 if (_pinsCfg.irqPin != -1) {
56 hal->pinMode(_pinsCfg.irqPin, OUTPUT);
57 hal->digitalWrite(_pinsCfg.irqPin, HIGH);
58 hal->delay(8);
59 hal->pinMode(_pinsCfg.irqPin, INPUT);
60 } else {
61 reset();
62 }
63}
64
66{
67 static constexpr uint8_t POINT_BUFFER_SIZE = (MAX_FINGER_NUM * BYTES_PER_POINT);
68 uint8_t buffer[POINT_BUFFER_SIZE] = {0};
69 int numPoints = 0;
70
71 // Clear cached touch points
73
74 numPoints = readGT911(GT911_POINT_INFO);
75 // If there is a home button callback and the home button is pressed
76 if (_HButtonCallback && (numPoints & 0x10)) {
78 clearBuffer();
79 return _touchPoints;
80 }
81
82 // Clear the buffer
83 clearBuffer();
84
85 // Mask the number of points
86 numPoints &= 0x0F;
87 if (numPoints <= 0 || numPoints > MAX_FINGER_NUM) {
88 return _touchPoints;
89 }
90
91 uint8_t expectedBytes = numPoints * BYTES_PER_POINT; // 8 bytes per touch point
92
93 // GT911_POINT_1 0X814F
95
96 if (writeThenRead(buffer, COMMAND_SIZE, buffer, expectedBytes) == 0) {
97 for (int i = 0; i < numPoints; i++) {
98 const uint8_t id = buffer[i * BYTES_PER_POINT];
99 const uint16_t x = buffer[1 + i * BYTES_PER_POINT] | (buffer[2 + i * BYTES_PER_POINT] << 8);
100 const uint16_t y = buffer[3 + i * BYTES_PER_POINT] | (buffer[4 + i * BYTES_PER_POINT] << 8);
101 const uint16_t pressure = buffer[5 + i * BYTES_PER_POINT] | (buffer[6 + i * BYTES_PER_POINT] << 8);
103 }
104
105 // Swap XY or mirroring coordinates,if set
107 }
108
109 return _touchPoints;
110}
111
113{
114 return "GT911";
115}
116
118{
119 // GT911_MODULE_SWITCH_1 0x804D
120 uint8_t oldTriggerLevel = _pinsCfg.irqTriggerLevel;
121 uint8_t irqMode = readGT911(GT911_MODULE_SWITCH_1);
122 irqMode &= (~IRQ_TRIGGER_MASK);
123 switch (mode) {
124 case FALLING_EDGE:
125 irqMode |= 0x01;
127 break;
128 case RISING_EDGE:
129 irqMode |= 0x00;
131 break;
132 case LOW_LEVEL_QUERY:
133 irqMode |= 0x02;
135 break;
136 case HIGH_LEVEL_QUERY:
137 irqMode |= 0x03;
139 break;
140 }
141 writeGT911(GT911_MODULE_SWITCH_1, irqMode);
142 if (!reloadConfig()) {
143 _pinsCfg.irqTriggerLevel = oldTriggerLevel;
144 return false;
145 }
146 return true;
147}
148
150{
151 uint8_t irqMode = readGT911(GT911_MODULE_SWITCH_1);
152 irqMode &= IRQ_TRIGGER_MASK;
153 switch (irqMode) {
154 case 0:
156 break;
157 case 1:
159 break;
160 case 2:
162 break;
163 case 3:
165 break;
166 default:
167 break;
168 }
169 return static_cast<InterruptMode>(irqMode);
170}
171
173{
174 char product_id[4] = {0};
175 // GT911_PRODUCT_ID 0x8140
176 for (int i = 0; i < 4; ++i) {
177 product_id[i] = readGT911(GT911_PRODUCT_ID + i);
178 }
179 return atoi(product_id);
180}
181
183{
184 uint8_t fw_ver[2] = {0};
185 // GT911_FIRMWARE_VERSION 0x8144
186 for (int i = 0; i < 2; ++i) {
187 fw_ver[i] = readGT911(GT911_FIRMWARE_VERSION + i);
188 }
189 return fw_ver[0] | (fw_ver[1] << 8);
190}
191
193{
194 return readGT911(GT911_CONFIG_VERSION);
195}
196
198{
199 if (rate_ms < 5) {
200 rate_ms = 5;
201 }
202 if (rate_ms > 15) {
203 rate_ms = 15;
204 }
205 rate_ms -= 5;
206 writeGT911(GT911_REFRESH_RATE, rate_ms);
207 reloadConfig();
208}
209
211{
212 uint8_t rate_ms = readGT911(GT911_REFRESH_RATE);
213 return rate_ms + GT911_BASE_REF_RATE ;
214}
215
217{
218 return readGT911(GT911_VENDOR_ID);
219}
220
221#ifdef ENABLE_GT911_CONFIG
222bool TouchDrvGT911::writeConfig(const uint8_t *config_buffer, size_t buffer_size)
223{
224 uint8_t check_sum = 0;
225 for (int i = 0; i < (GT911_REG_LENGTH - 2 ); i++) {
226 check_sum += config_buffer[i];
227 }
228 check_sum = (~check_sum) + 1;
229 if (check_sum != config_buffer[GT911_REG_LENGTH - 2]) {
230 SENSORLIB_LOG_E("Config checksum error !");
231 return false;
232 }
233 SENSORLIB_LOG_D("Update touch config , write %zu Bytes check sum:0x%X", buffer_size, check_sum);
235 int err = writeBuff(GT911_CONFIG_VERSION, (uint8_t *)config_buffer, buffer_size);
236 return err == 0;
237}
238#endif
239
240// Load touch configuration ,need manual release memory
241uint8_t *TouchDrvGT911::loadConfig(size_t *output_size, bool print_out)
242{
243 *output_size = 0;
244 uint8_t *buffer = (uint8_t *)malloc(GT911_REG_LENGTH);
245 if (!buffer)return NULL;
247 if (writeThenRead(buffer, COMMAND_SIZE, buffer, GT911_REG_LENGTH) == -1) {
248 return NULL;
249 }
250 if (print_out) {
251 printf("const unsigned char config[186] = {");
252 for (int i = 0; i < GT911_REG_LENGTH; ++i) {
253 if ( (i % 8) == 0) {
254 printf("\n");
255 }
256 printf(" 0x%02X", buffer[i]);
257 if ((i + 1) < GT911_REG_LENGTH) {
258 printf(",");
259 }
260 }
261 printf("};\n");
262 }
263 *output_size = GT911_REG_LENGTH;
264 return buffer;
265}
266
268{
269 uint8_t buffer[GT911_REG_LENGTH] = {};
272 if (writeThenRead(buffer, 2, buffer, GT911_REG_LENGTH - 2) == -1) {
273 return false;
274 }
275
276 uint8_t check_sum = 0;
277 for (int i = 0; i < (GT911_REG_LENGTH - 2 ); i++) {
278 check_sum += buffer[i];
279 }
280 check_sum = (~check_sum) + 1;
281 SENSORLIB_LOG_D("reloadConfig check_sum : 0x%X\n", check_sum);
282 writeGT911(GT911_CONFIG_CHKSUM, check_sum);
283 writeGT911(GT911_CONFIG_FRESH, 0x01);
284 return true;
285}
286
288{
289 if (num < 1)num = 1;
290 if (num > 5) num = 5;
291 writeGT911(GT911_TOUCH_NUMBER, num);
292 reloadConfig();
293}
294
295uint8_t TouchDrvGT911::readGT911(uint16_t cmd)
296{
297 uint8_t value = 0x00;
298 uint8_t write_buffer[2] = {sensorlib::_highByte(cmd), sensorlib::_lowByte(cmd)};
299 writeThenRead(write_buffer, arraySize(write_buffer),
300 &value, 1);
301 return value;
302}
303
304int TouchDrvGT911::writeGT911(uint16_t cmd, uint8_t value)
305{
306 uint8_t write_buffer[3] = {sensorlib::_highByte(cmd), sensorlib::_lowByte(cmd), value};
307 return writeBuff(write_buffer, arraySize(write_buffer));
308}
309
310void TouchDrvGT911::writeCommand(uint8_t command)
311{
312 // GT911_COMMAND 0x8040
313 uint8_t write_buffer[3] = {0x80, 0x40, command};
314 writeBuff(write_buffer, arraySize(write_buffer));
315}
316
317void TouchDrvGT911::clearBuffer()
318{
319 writeGT911(GT911_POINT_INFO, 0x00);
320}
321
322bool TouchDrvGT911::probeAddress()
323{
324 const uint8_t device_address[2] = {GT911_SLAVE_ADDRESS_L, GT911_SLAVE_ADDRESS_H};
325 for (size_t i = 0; i < arraySize(device_address); ++i) {
326 setAddress(device_address[i]);
327 for (int retry = 0; retry < 3; ++retry) {
328 _chipID = getChipID();
329 if (_chipID == GT911_DEV_ID) {
330 SENSORLIB_LOG_I("Touch device address found is : 0x%X", device_address[i]);
331 return true;
332 }
333 }
334 }
335 SENSORLIB_LOG_E("GT911 not found, touch device 7-bit address should be 0x5D or 0x14");
336 return false;
337}
338
339bool TouchDrvGT911::initImpl(uint8_t)
340{
341 if (_addr == GT911_SLAVE_ADDRESS_H && _pinsCfg.rstPin != -1 && _pinsCfg.irqPin != -1) {
342
343 SENSORLIB_LOG_I("Try using 0x14 as the device address");
344
345 hal->pinMode(_pinsCfg.rstPin, OUTPUT);
346 hal->pinMode(_pinsCfg.irqPin, OUTPUT);
347
348 hal->digitalWrite(_pinsCfg.rstPin, LOW);
349 hal->digitalWrite(_pinsCfg.irqPin, HIGH);
350 hal->delayMicroseconds(120);
351 hal->digitalWrite(_pinsCfg.rstPin, HIGH);
352 // The stable value after testing was 18ms.
353 hal->delay(18);
354
355 hal->pinMode(_pinsCfg.irqPin, INPUT);
356
357 } else if (_addr == GT911_SLAVE_ADDRESS_L && _pinsCfg.rstPin != -1 && _pinsCfg.irqPin != -1) {
358
359 SENSORLIB_LOG_I("Try using 0x5D as the device address");
360
361 hal->pinMode(_pinsCfg.rstPin, OUTPUT);
362 hal->pinMode(_pinsCfg.irqPin, OUTPUT);
363
364 hal->digitalWrite(_pinsCfg.rstPin, LOW);
365 hal->digitalWrite(_pinsCfg.irqPin, LOW);
366 hal->delayMicroseconds(120);
367 hal->digitalWrite(_pinsCfg.rstPin, HIGH);
368 // The stable value after testing was 18ms.
369 hal->delay(18);
370 hal->pinMode(_pinsCfg.irqPin, INPUT);
371
372 } else {
373 if (!autoProbe()) {
374 return false;
375 }
376 }
377
378 // For variants where the GPIO is controlled by I2C, a hal->delay is required here
379 hal->delay(20);
380
381
382 /*
383 * For the ESP32 platform, the default buffer is 128.
384 * Need to re-apply for a larger buffer to fully read the configuration table.
385 *
386 * TODO: NEED FIX
387 if (!this->reallocBuffer(GT911_REG_LENGTH + 2)) {
388 SENSORLIB_LOG_E("realloc i2c buffer failed !");
389 return false;
390 }
391 */
392
393 _chipID = getChipID();
394
395 if (_chipID != GT911_DEV_ID) {
396 SENSORLIB_LOG_I("Not found device GT911,Try to found the GT911");
397 if (!autoProbe()) {
398 return false;
399 }
400 }
401
402 uint8_t x_resolution[2] = {0}, y_resolution[2] = {0};
403 for (int i = 0; i < 2; ++i) {
404 x_resolution[i] = readGT911(GT911_X_RESOLUTION + i);
405 }
406 for (int i = 0; i < 2; ++i) {
407 y_resolution[i] = readGT911(GT911_Y_RESOLUTION + i);
408 }
409
410 _touchConfig.resolutionX = x_resolution[0] | (x_resolution[1] << 8);
411 _touchConfig.resolutionY = y_resolution[0] | (y_resolution[1] << 8);
412 SENSORLIB_LOG_D("Model:GT911");
413 SENSORLIB_LOG_D("RST Pin:%d", _pinsCfg.rstPin);
414 SENSORLIB_LOG_D("IRQ Pin:%d", _pinsCfg.irqPin);
415 SENSORLIB_LOG_I("Product id:%" PRId32, _chipID);
416 SENSORLIB_LOG_D("Firmware version: 0x%x", getFwVersion());
417 SENSORLIB_LOG_D("Resolution : X = %d Y = %d", _touchConfig.resolutionX, _touchConfig.resolutionY);
418 SENSORLIB_LOG_D("Vendor id:%d", getVendorID());
419 SENSORLIB_LOG_D("Refresh Rate:%d ms", getRefreshRate());
420 _maxTouchPoints = readGT911(GT911_TOUCH_NUMBER) & 0x0F;
421 SENSORLIB_LOG_D("MaxTouchPoint:%d", _maxTouchPoints);
422
423 // Get the default interrupt trigger mode of the current screen
424 uint8_t irqMode = getInterruptMode();
425 switch (irqMode) {
426 case 0:
427 SENSORLIB_LOG_D("Interrupt Mode: RISING");
428 break;
429 case 1:
430 SENSORLIB_LOG_D("Interrupt Mode: FALLING");
431 break;
432 case 2:
433 SENSORLIB_LOG_D("Interrupt Mode: LOW_LEVEL_QUERY");
434 break;
435 case 3:
436 SENSORLIB_LOG_D("Interrupt Mode: HIGH_LEVEL_QUERY");
437 break;
438 default:
439 SENSORLIB_LOG_E("Interrupt Mode: UNKNOWN");
440 break;
441 }
442
443 return true;
444}
445
446bool TouchDrvGT911::autoProbe()
447{
448 if (_pinsCfg.rstPin != -1) {
449 hal->pinMode(_pinsCfg.rstPin, OUTPUT);
450 hal->digitalWrite(_pinsCfg.rstPin, HIGH);
451 hal->delay(10);
452 }
453
454 // Automatically determine the current device
455 // address when using the reset pin without connection
456 if (!probeAddress()) {
457 return false;
458 }
459
460 // Reset Config
461 reset();
462
463 if (_pinsCfg.irqPin != -1) {
464 hal->pinMode(_pinsCfg.irqPin, INPUT);
465 }
466
467 return true;
468}
469
470#endif
constexpr size_t arraySize(const T(&arr)[N])
Returns the number of elements in a C‑style array at compile time.
#define SENSORLIB_LOG_I(...)
#define SENSORLIB_LOG_E(...)
#define SENSORLIB_LOG_D(...)
void addrToBeBuf(uint32_t addr, uint8_t buf[4])
SensorPressure pressure(bhy)
std::unique_ptr< SensorHal > hal
int writeBuff(uint8_t *buf, size_t len)
int writeThenRead(const uint8_t *write_buffer, size_t write_len, uint8_t *read_buffer, size_t read_len)
void setAddress(uint8_t address)
static constexpr uint16_t GT911_Y_RESOLUTION
bool setInterruptMode(InterruptMode mode)
Set the interrupt mode.
static constexpr uint16_t GT911_CONFIG_FRESH
static constexpr uint16_t GT911_FIRMWARE_VERSION
void wakeup() override
Wake up the touch driver.
uint32_t getChipID() override
Get the chip ID.
bool reloadConfig()
Reload the configuration data.
void setMaxTouchPoint(uint8_t num)
Set the maximum touch points.
static constexpr uint16_t GT911_X_RESOLUTION
static constexpr uint16_t GT911_PRODUCT_ID
static constexpr uint16_t GT911_POINT_INFO
uint8_t * loadConfig(size_t *output_size, bool print_out=false)
Load the configuration data.
static constexpr uint16_t COMMAND_SIZE
static constexpr uint8_t IRQ_TRIGGER_MASK
static constexpr uint8_t GT911_BASE_REF_RATE
void sleep() override
Puts the touch driver to sleep.
InterruptMode getInterruptMode()
Get the interrupt mode.
static constexpr uint16_t GT911_VENDOR_ID
uint8_t getConfigVersion()
Get the configuration version.
uint8_t getRefreshRate()
Get the refresh rate.
static constexpr uint16_t GT911_REFRESH_RATE
static constexpr uint16_t GT911_MODULE_SWITCH_1
uint16_t getFwVersion()
Get the firmware version.
static constexpr uint16_t GT911_CONFIG_VERSION
static constexpr uint16_t GT911_POINT_1
static constexpr uint8_t GT911_REG_LENGTH
static constexpr uint16_t GT911_CONFIG_CHKSUM
const char * getModelName() override
Get the model name.
static constexpr uint16_t GT911_DEV_ID
static constexpr uint16_t GT911_TOUCH_NUMBER
int getVendorID()
Get the vendor ID.
const TouchPoints & getTouchPoints() override
Get the touch points.
void updateRefreshRate(uint8_t rate_ms)
Get the refresh rate.
uint32_t _chipID
Chip identification value.
TouchConfig _touchConfig
Configuration for coordinate transformations.
virtual void reset()
Reset the touch controller.
void * _userData
User data for home button callback.
virtual void updateXY(TouchPoints &points) const
Apply coordinate transformations (swap, scale, mirror) to all touch points.
TouchPinsCfg _pinsCfg
Configuration for reset and interrupt pins.
TouchPoints _touchPoints
Touch points data.
uint8_t _maxTouchPoints
Maximum supported touch points.
HomeButtonCallback _HButtonCallback
Home button callback function.
Container for touch point data and optional gesture information.
bool addPoint(uint16_t x, uint16_t y, uint16_t pressure=0, uint8_t id=0, uint8_t event=0)
Adds a touch point to the container.
void clear()
Clears all stored touch points and gesture.
constexpr uint8_t _lowByte(uint16_t w)
Definition SensorLib.h:69
constexpr uint8_t _highByte(uint16_t w)
Definition SensorLib.h:73
uint8_t i
const uint16_t buffer_size
int16_t x[5]
int16_t y[5]