SensorLib 0.5.0
Multi-platform sensor driver library for Arduino, PlatformIO, and ESP-IDF
Loading...
Searching...
No Matches
gt9895_gesture_lilygo_p4.ino
Go to the documentation of this file.
1
30#include <Wire.h> // Adafruit NRF52 CI failure was avoided.
31#include <TouchDrvGoodix.hpp>
32#include <IoExpanderDrv.hpp>
33
34// Pin definitions for the LilyGo-P4
35#define P4_TOUCH_SDA 7
36#define P4_TOUCH_SCL 8
37#define IO_EXPANDER_TOUCH_RST (3 | 0x80)
38#define IO_EXPANDER_TOUCH_IRQ (4 | 0x80)
39
40#ifdef ARDUINO_ESP32P4_DEV
41
44
45enum GestureType {
46 GESTURE_NONE,
47 GESTURE_TAP,
48 GESTURE_LEFT,
49 GESTURE_RIGHT,
50 GESTURE_UP,
51 GESTURE_DOWN
52};
53
54struct GestureState {
55 bool active = false;
56 uint8_t id = 0xFF;
57 int16_t startX = 0;
58 int16_t startY = 0;
59 int16_t lastX = 0;
60 int16_t lastY = 0;
61 uint32_t startTime = 0;
62 uint32_t lastTime = 0;
63 uint16_t samples = 0;
64};
65
66GestureState gesture;
67
68static const int SWIPE_THRESHOLD = 70; // Minimum movement for swipe gesture
69static const int TAP_MOVE_THRESHOLD = 18; // Maximum movement for tap gesture
70static const uint32_t TAP_TIME_THRESHOLD = 250; // Maximum time for tap gesture
71static const uint32_t MAX_GESTURE_TIME = 1200; // Maximum gesture duration
72static const float DOMINANCE_RATIO = 1.2f; // Dominance ratio for swipe gestures
73static const bool enableTap = false; // Disable print tap event
74
75// only swipe gesture is limited by cooldown
76static const uint32_t SWIPE_COOLDOWN_MS = 600;
77
78uint32_t lastSwipeEventTime = 0;
79bool swipeEventLocked = false;
80
81
82void TouchDrvDigitalWrite(uint8_t gpio, uint8_t level)
83{
84 if (gpio & 0x80) {
85 expander.digitalWrite(gpio & 0x7F, level);
86 } else {
87 digitalWrite(gpio, level);
88 }
89}
90
91uint8_t TouchDrvDigitalRead(uint8_t gpio)
92{
93 if (gpio & 0x80) {
94 return expander.digitalRead(gpio & 0x7F);
95 } else {
96 return digitalRead(gpio);
97 }
98}
99
100void TouchDrvPinMode(uint8_t gpio, uint8_t mode)
101{
102 if (gpio & 0x80) {
103 expander.pinMode(gpio & 0x7F, mode);
104 } else {
105 pinMode(gpio, mode);
106 }
107}
108
109const char *gestureToString(GestureType g)
110{
111 switch (g) {
112 case GESTURE_TAP: return "TAP";
113 case GESTURE_LEFT: return "LEFT";
114 case GESTURE_RIGHT: return "RIGHT";
115 case GESTURE_UP: return "UP";
116 case GESTURE_DOWN: return "DOWN";
117 default: return "NONE";
118 }
119}
120
121bool isSwipeGesture(GestureType g)
122{
123 return g == GESTURE_LEFT ||
124 g == GESTURE_RIGHT ||
125 g == GESTURE_UP ||
126 g == GESTURE_DOWN;
127}
128
129void resetGesture()
130{
131 gesture.active = false;
132 gesture.id = 0xFF;
133 gesture.startX = 0;
134 gesture.startY = 0;
135 gesture.lastX = 0;
136 gesture.lastY = 0;
137 gesture.startTime = 0;
138 gesture.lastTime = 0;
139 gesture.samples = 0;
140}
141
142GestureType classifyGesture(int dx, int dy, uint32_t dt)
143{
144 int adx = abs(dx);
145 int ady = abs(dy);
146
147 if (dt <= TAP_TIME_THRESHOLD && adx <= TAP_MOVE_THRESHOLD && ady <= TAP_MOVE_THRESHOLD) {
148 return GESTURE_TAP;
149 }
150
151 if (dt > MAX_GESTURE_TIME) {
152 return GESTURE_NONE;
153 }
154
155 if (adx >= SWIPE_THRESHOLD && (float)adx > (float)ady * DOMINANCE_RATIO) {
156 return dx > 0 ? GESTURE_RIGHT : GESTURE_LEFT;
157 }
158
159 if (ady >= SWIPE_THRESHOLD && (float)ady > (float)adx * DOMINANCE_RATIO) {
160 return dy > 0 ? GESTURE_DOWN : GESTURE_UP;
161 }
162
163 return GESTURE_NONE;
164}
165
166void unlockSwipeIfNeeded(uint32_t now)
167{
168 if (swipeEventLocked && (now - lastSwipeEventTime) >= SWIPE_COOLDOWN_MS) {
169 swipeEventLocked = false;
170 }
171}
172
173bool canEmitSwipe(uint32_t now)
174{
175 if (!swipeEventLocked) {
176 return true;
177 }
178 return (now - lastSwipeEventTime) >= SWIPE_COOLDOWN_MS;
179}
180
181void lockSwipeEvent(uint32_t now)
182{
183 lastSwipeEventTime = now;
184 swipeEventLocked = true;
185}
186
187void printGestureResult(GestureType type, int dx, int dy, uint32_t dt)
188{
189 Serial.println("===== Gesture Result =====");
190 Serial.printf("id : %u\n", gesture.id);
191 Serial.printf("start : (%d, %d)\n", gesture.startX, gesture.startY);
192 Serial.printf("end : (%d, %d)\n", gesture.lastX, gesture.lastY);
193 Serial.printf("delta : dx=%d dy=%d\n", dx, dy);
194 Serial.printf("time : %lu ms\n", (unsigned long)dt);
195 Serial.printf("samples : %u\n", gesture.samples);
196 Serial.printf("gesture : %s\n", gestureToString(type));
197 if (isSwipeGesture(type)) {
198 Serial.printf("swipe cooldown: %lu ms\n", (unsigned long)SWIPE_COOLDOWN_MS);
199 }
200 Serial.println();
201}
202
203void setup()
204{
205 Serial.begin(115200);
206 while (!Serial);
207
208 Serial.println("GT9895 Gesture Test - swipe cooldown only, tap excluded");
209
210 Wire.begin(P4_TOUCH_SDA, P4_TOUCH_SCL);
211
212 if (!expander.begin(Wire, XL9555_SLAVE_ADDRESS0)) {
213 while (1) {
214 Serial.println("Failed to find io expander - check your wiring!");
215 delay(1000);
216 }
217 }
218
221
222 if (!touch.begin(Wire, GT9895_SLAVE_ADDRESS_L)) {
223 while (1) {
224 Serial.println("Failed to find touch device - check your wiring!");
225 delay(1000);
226 }
227 }
228
229 Serial.println("GT9895 Touch Initialized");
230 Serial.print("Chip ID : 0x");
231 Serial.println(touch.getChipID(), HEX);
232
233 touch.setResolution(1060, 2400);
234 touch.setTargetResolution(568, 1232);
235
236 // If direction is wrong, try:
237 // touch.setSwapXY(true);
238 // touch.setMirrorXY(true, false);
239 // touch.setMirrorXY(false, true);
240 // touch.setMirrorXY(true, true);
241
242 Serial.printf("Ready. Swipe cooldown = %lu ms, TAP is not limited.\n",
243 (unsigned long)SWIPE_COOLDOWN_MS);
244 Serial.println();
245}
246
247void loop()
248{
249 uint32_t now = millis();
250 unlockSwipeIfNeeded(now);
251
252 TouchPoints touch_points = touch.getTouchPoints();
253
254 if (touch_points.hasPoints()) {
255 const TouchPoint &point = touch_points.getPoint(0);
256
257 if (!gesture.active) {
258 gesture.active = true;
259 gesture.id = point.id;
260 gesture.startX = point.x;
261 gesture.startY = point.y;
262 gesture.lastX = point.x;
263 gesture.lastY = point.y;
264 gesture.startTime = now;
265 gesture.lastTime = now;
266 gesture.samples = 1;
267 } else {
268 gesture.lastX = point.x;
269 gesture.lastY = point.y;
270 gesture.lastTime = now;
271 gesture.samples++;
272 }
273 } else {
274 if (gesture.active) {
275 int dx = gesture.lastX - gesture.startX;
276 int dy = gesture.lastY - gesture.startY;
277 uint32_t dt = gesture.lastTime - gesture.startTime;
278
279 GestureType type = classifyGesture(dx, dy, dt);
280
281 if (type == GESTURE_TAP) {
282 if (enableTap) {
283 printGestureResult(type, dx, dy, dt);
284 }
285 } else if (isSwipeGesture(type)) {
286 if (canEmitSwipe(now)) {
287 printGestureResult(type, dx, dy, dt);
288 lockSwipeEvent(now);
289 }
290 }
291 resetGesture();
292 }
293 }
294
295 delay(10);
296}
297
298#else
299void setup()
300{
301 Serial.begin(115200);
302}
303void loop()
304{
305 Serial.println("Sketch only works with LilyGo-T-Display-P4 AMOLED(GT9895) Version");
306 delay(1000);
307}
308#endif
@license MIT License
@license MIT License
uint8_t level
bool begin(SensorCommCustom::CustomCallback callback, uint8_t addr)
Initialize the sensor using custom callback interface.
bool digitalRead(uint8_t pin)
Read the digital value from an input pin.
void pinMode(uint8_t pin, uint8_t mode)
Set the direction of a GPIO pin.
void digitalWrite(uint8_t pin, bool value)
Write a digital value to an output pin.
Concrete driver for the XL9555 16‑bit I2C GPIO expander.
bool begin(SensorCommCustom::CustomCallback callback, SensorCommCustomHal::CustomHalCallback hal_callback, uint8_t addr) override
Initialize the touch driver for custom communication.
const TouchPoints & getTouchPoints() override
Get the touch points.
uint32_t getChipID() override
Get the chip ID.
virtual void setGpioCallback(SensorHalCustom::CustomMode mode_cb, SensorHalCustom::CustomWrite write_cb, SensorHalCustom::CustomRead read_cb)
Set custom GPIO callbacks for pin control (e.g., reset, interrupt).
virtual void setResolution(uint16_t width, uint16_t height)
Set the raw resolution of the touch panel (physical maximum coordinates).
virtual void setPins(int rst, int irq)
Set the hardware reset and interrupt pin numbers.
virtual void setTargetResolution(uint16_t width, uint16_t height)
Set the target display resolution to map touch coordinates to screen pixels.
Container for touch point data and optional gesture information.
TouchPoint & getPoint(uint8_t index)
Gets a reference to a touch point at the specified index.
bool hasPoints() const
Checks whether any touch points are stored.
#define P4_TOUCH_SCL
#define IO_EXPANDER_TOUCH_IRQ
#define P4_TOUCH_SDA
#define IO_EXPANDER_TOUCH_RST
IoExpanderPCA9570 expander
Represents a single touch point with its properties.
uint8_t id
Touch point ID for multi‑touch tracking.
uint16_t x
X coordinate of the touch point.
uint16_t y
Y coordinate of the touch point.
TouchDrvCSTXXX touch
Definition touch_drv.cpp:42
void TouchDrvPinMode(uint8_t gpio, uint8_t mode)
void TouchDrvDigitalWrite(uint8_t gpio, uint8_t level)
uint8_t TouchDrvDigitalRead(uint8_t gpio)