-
Notifications
You must be signed in to change notification settings - Fork 11
/
Copy pathgt911.hpp
288 lines (259 loc) · 9.02 KB
/
gt911.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
#pragma once
#include <functional>
#include "logger.hpp"
namespace espp {
/// @brief Driver for the GT911 touch controller
///
/// \section Example
/// \snippet gt911_example.cpp gt911 example
class Gt911 {
public:
/// Default address for the GT911 chip
static constexpr uint8_t DEFAULT_ADDRESS_1 = 0x5D;
/// Alternate address for the GT911 chip
static constexpr uint8_t DEFAULT_ADDRESS_2 = 0x14;
/// @brief Function for writing to the GT911 chip
/// @param address The address of the GT911 chip
/// @param data The data to write to the chip
/// @param len The length of the data to write
typedef std::function<bool(uint8_t, uint8_t *, size_t)> write_fn;
/// @brief Function for writing to and reading from the GT911 chip
/// @param address The address of the GT911 chip
/// @param write_data The data to write to the chip
/// @param write_len The length of the data to write
/// @param read_data The data to read from the chip
/// @param read_len The length of the data to read
typedef std::function<bool(uint8_t, uint8_t *, size_t, uint8_t *, size_t)> write_read_fn;
/// @brief Configuration for the GT911 driver
struct Config {
write_fn write; ///< Function for writing to the GT911 chip
write_read_fn write_read; ///< Function for writing to and reading from the GT911 chip
uint8_t address = DEFAULT_ADDRESS_1; ///< Which address to use for this chip?
espp::Logger::Verbosity log_level{
espp::Logger::Verbosity::WARN}; ///< Log verbosity for the input driver.
};
/// @brief Constructor for the GT911 driver
/// @param config The configuration for the driver
explicit Gt911(const Config &config)
: write_read_(config.write_read), write_(config.write), address_(config.address),
logger_({.tag = "Gt911", .level = config.log_level}) {}
/// @brief Update the state of the GT911 driver
/// @param ec Error code to set if an error occurs
/// @return True if the GT911 has new data, false otherwise
bool update(std::error_code &ec) {
static constexpr size_t DATA_LEN = CONTACT_SIZE * MAX_CONTACTS;
static uint8_t data[DATA_LEN];
read(Registers::POINT_INFO, data, 1, ec);
if (ec) {
return false;
}
num_touch_points_ = data[0] & 0x0f;
if (num_touch_points_ > 0) {
logger_.debug("Got {} touch points", num_touch_points_);
read(Registers::POINTS, data, CONTACT_SIZE * num_touch_points_, ec);
if (ec) {
return false;
}
// convert the data pointer to a GTPoint*
const GTPoint *point = (GTPoint *)&data[0];
x_ = point->x;
y_ = point->y;
logger_.debug("Touch at ({}, {})", x_, y_);
}
write(Registers::POINT_INFO, 0x00, ec); // sync signal
if (ec) {
return false;
}
return num_touch_points_ > 0;
}
/// @brief Get the number of touch points
/// @return The number of touch points as of the last update
/// @note This is a cached value from the last update() call
uint8_t get_num_touch_points() const { return num_touch_points_; }
/// @brief Get the touch point data
/// @param num_touch_points The number of touch points as of the last update
/// @param x The x coordinate of the touch point
/// @param y The y coordinate of the touch point
/// @note This is a cached value from the last update() call
void get_touch_point(uint8_t *num_touch_points, uint16_t *x, uint16_t *y) const {
*num_touch_points = get_num_touch_points();
if (*num_touch_points != 0) {
*x = x_;
*y = y_;
}
}
/// @brief Get the home button state
/// @return True if the home button is pressed, false otherwise
/// @note This is a cached value from the last update() call
uint8_t get_home_button_state() const { return home_button_pressed_; }
protected:
static constexpr int CONTACT_SIZE = 8;
static constexpr int MAX_CONTACTS = 5;
static constexpr int CONFIG_MAX_LEN = 240;
static constexpr int CONFIG_911_LEN = 186;
static constexpr int CONFIG_967_LEN = 228;
enum class Registers : uint16_t {
COMMAND = 0x8040,
CONFIG = 0x8047,
SWITCH_1 = 0x804D,
SWITCH_2 = 0x804E,
REFRESH_RATE = 0x8056,
DATA = 0x8140,
POINT_INFO = 0x814E,
POINTS = 0x814F,
POINT_1 = 0x814F,
POINT_2 = 0x8157,
POINT_3 = 0x815F,
POINT_4 = 0x8167,
POINT_5 = 0x816F,
};
// From Goodix library
struct GTInfo {
// 0x8140-0x814A
char productId[4];
uint16_t fwId;
uint16_t xResolution;
uint16_t yResolution;
uint8_t vendorId;
} __attribute__((packed));
struct GTPoint {
// 0x814F-0x8156, ... 0x8176 (5 points)
uint8_t trackId;
uint16_t x;
uint16_t y;
uint16_t area;
uint8_t reserved;
} __attribute__((packed));
struct GTLevelConfig {
uint8_t touch; // Threshold of touch grow out of nothing
uint8_t leave; // Threshold of touch decrease to nothing
} __attribute__((packed));
struct GTStylusConfig {
uint8_t txGain;
uint8_t rxGain;
uint8_t dumpShift;
GTLevelConfig level;
uint8_t control; // Pen mode escape time out period (Unit: Sec)
} __attribute__((packed));
struct GTFreqHoppingConfig {
uint16_t hoppingBitFreq;
uint8_t hoppingFactor;
} __attribute__((packed));
struct GTKeyConfig {
// Key position: 0-255 valid
// 0 means no touch, it means independent touch key when 4 of the keys are 8 multiples
uint8_t pos1;
uint8_t pos2;
uint8_t pos3;
uint8_t pos4;
uint8_t area;
GTLevelConfig level;
uint8_t sens12;
uint8_t sens34;
uint8_t restrain;
} __attribute__((packed));
struct GTConfig {
// start at 0x8047
uint8_t configVersion;
uint16_t xResolution;
uint16_t yResolution;
// 0x804C
uint8_t touchNumber; // 3:0 Touch No.: 1~10
// 7:6 Reserved, 5:4 Stretch rank, 3 X2Y, 2 Sito
// 1:0 INT trig method: 00-rising, 01-falling, 02-low level, 03-high level enquiry
uint8_t moduleSwitch1;
uint8_t moduleSwitch2; // bit0 TouchKey
uint8_t shakeCount; // 3:0 Finger shake count
// 0x8050
// 7:6 First filter, 5:0 Normal filter (filtering value of original coordinate window,
// coefficiency is 1)
uint8_t filter;
uint8_t largeTouch;
uint8_t noiseReduction;
GTLevelConfig screenLevel;
uint8_t lowPowerControl; // Time to low power consumption (0~15s)
uint8_t refreshRate; // Coordinate report rate (Cycle: 5+N ms)
uint8_t xThreshold; // res
uint8_t yThreshold; // res
uint8_t xSpeedLimit; // res
uint8_t ySpeedLimit; // res
uint8_t vSpace; // 4bit top/bottom (coefficient 32)
uint8_t hSpace; // 4bit left/right
// 0x805D-0x8061
uint8_t stretchRate; // Level of weak stretch (Strtch X/16 Pitch)
uint8_t stretchR0; // Interval 1 coefficient
uint8_t stretchR1; // Interval 2 coefficient
uint8_t stretchR2; // Interval 3 coefficient
uint8_t stretchRM; // All intervals base number
uint8_t drvGroupANum;
uint8_t drvGroupBNum;
uint8_t sensorNum;
uint8_t freqAFactor;
uint8_t freqBFactor;
// 0x8067
uint16_t pannelBitFreq; // Baseband of Driver group A\B (1526HZ<baseband<14600Hz)
uint16_t pannelSensorTime; // res
uint8_t pannelTxGain;
uint8_t pannelRxGain;
uint8_t pannelDumpShift;
uint8_t drvFrameControl;
// 0x806F - 0x8071
uint8_t NC_2[3];
GTStylusConfig stylusConfig;
// 0x8078-0x8079
uint8_t NC_3[2];
uint8_t freqHoppingStart; // Frequency hopping start frequency (Unit: 2KHz, 50 means 100KHz )
uint8_t freqHoppingEnd; // Frequency hopping stop frequency (Unit: 2KHz, 150 means 300KHz )
uint8_t noiseDetectTims;
uint8_t hoppingFlag;
uint8_t hoppingThreshold;
uint8_t noiseThreshold;
uint8_t NC_4[2];
// 0x8082
GTFreqHoppingConfig hoppingSegments[5];
// 0x8091
uint8_t NC_5[2];
GTKeyConfig keys;
} __attribute__((packed));
void write(Registers reg, uint8_t val, std::error_code &ec) { write(reg, &val, 1, ec); }
void write(Registers reg, const uint8_t *data, size_t len, std::error_code &ec) {
uint16_t reg_addr = (uint16_t)reg;
size_t d_len = 2 + len;
uint8_t d[d_len];
d[0] = reg_addr >> 8;
d[1] = reg_addr & 0xFF;
memcpy(&d[2], data, len);
bool success = write_(address_, d, d_len);
if (!success) {
ec = std::make_error_code(std::errc::io_error);
}
}
uint8_t read(Registers reg, std::error_code &ec) {
uint8_t val = 0;
read(reg, &val, 1, ec);
if (ec) {
return 0;
}
return val;
}
void read(Registers reg, uint8_t *data, size_t len, std::error_code &ec) {
uint16_t reg_addr = (uint16_t)reg;
uint8_t reg_data[2] = {
(uint8_t)(reg_addr >> 8),
(uint8_t)(reg_addr & 0xFF),
};
bool success = write_read_(address_, reg_data, 2, data, len);
if (!success) {
ec = std::make_error_code(std::errc::io_error);
}
}
write_read_fn write_read_;
write_fn write_;
uint8_t address_;
std::atomic<bool> home_button_pressed_{false};
std::atomic<uint8_t> num_touch_points_;
std::atomic<uint16_t> x_;
std::atomic<uint16_t> y_;
espp::Logger logger_;
};
} // namespace espp