1
- /* ----------------------------------------------------------------------
2
- * Touch screen calibration for XPT2046_Touchscreen
1
+ /* ----------------------------------------------------------------------------
2
+ * A wrapper class for the touchscreen libraries that supports
3
+ * calibration of the touch panel and rotation of the screen
3
4
*
4
5
* This program is based on the following article:
5
6
* https://bytesnbits.co.uk/arduino-touchscreen-calibration-coding/
6
- *----------------------------------------------------------------------*/
7
+ *---------------------------------------------------------------------------- */
7
8
#ifndef _XPT2046_SCREENPOINT_H_
8
9
#define _XPT2046_SCREENPOINT_H_
9
10
28
29
#error use LovyanGFX, TFT_eSPI, Adafruit_GFX or GFX_Library_for_Arduino
29
30
#endif
30
31
32
+ #if defined (_XPT2046_Touchscreen_h_)
33
+ /* ************************************************/
34
+ /* *** Inherits from XPT2046_Touchscreen class ****/
35
+ /* ************************************************/
36
+ #define PARENT_CLASS XPT2046_Touchscreen
37
+ #define SCREEN_POINT TS_Point
38
+ #define SP_RAW_X (p ) p.x
39
+ #define SP_RAW_Y (p ) p.y
40
+ #define SP_RAW_Z (p ) p.z
41
+
42
+ #define Z_THRESHOLD 600
43
+ #endif // _XPT2046_Touchscreen_h_
44
+
45
+ #if defined (XPT2046_Bitbang_h)
46
+ /* ************************************************/
47
+ /* ***** Inherits from XPT2046_Bitbang class ******/
48
+ /* ************************************************/
49
+ #define PARENT_CLASS XPT2046_Bitbang
50
+ #define SCREEN_POINT TouchPoint
51
+ #define SP_RAW_X (p ) p.xRaw
52
+ #define SP_RAW_Y (p ) p.yRaw
53
+ #define SP_RAW_Z (p ) p.zRaw
54
+
55
+ #define N_SAMPLES 4
56
+ #define N_THRESHOLD 3
57
+ #define Z_THRESHOLD 600
58
+ #endif // XPT2046_Bitbang_h
59
+
31
60
/* ----------------------------------------------------------------------
32
- * Defining the class that inherits from XPT2046_Touchscreen class
61
+ * Defining the class that inherits from XPT2046 libraries
33
62
*----------------------------------------------------------------------*/
34
- class XPT2046_ScreenPoint : public XPT2046_Touchscreen {
63
+ class XPT2046_ScreenPoint : public PARENT_CLASS {
35
64
// Inheriting constructor from the parent class
36
- using XPT2046_Touchscreen::XPT2046_Touchscreen ;
65
+ using PARENT_CLASS::PARENT_CLASS ;
37
66
38
67
private:
39
68
bool calibrated = false ;
@@ -42,13 +71,17 @@ class XPT2046_ScreenPoint : public XPT2046_Touchscreen {
42
71
float xCalM = 0.0 , yCalM = 0.0 ; // gradients
43
72
float xCalC = 0.0 , yCalC = 0.0 ; // y axis crossing points
44
73
74
+ #if defined (_XPT2046_Touchscreen_h_)
75
+ /* ************************************************/
76
+ /* *** Inherits from XPT2046_Touchscreen class ****/
77
+ /* ************************************************/
45
78
public:
46
79
void setRotation (uint8_t r) {
47
- XPT2046_Touchscreen ::setRotation (rotation = r % 4 );
80
+ PARENT_CLASS ::setRotation (rotation = r % 4 );
48
81
}
49
82
50
83
void begin (SPIClass &spi, uint16_t w, uint16_t h, uint8_t r = 0 ) {
51
- XPT2046_Touchscreen ::begin (spi);
84
+ PARENT_CLASS ::begin (spi);
52
85
setRotation (r);
53
86
width = w;
54
87
height = h;
@@ -57,6 +90,102 @@ class XPT2046_ScreenPoint : public XPT2046_Touchscreen {
57
90
void begin (uint16_t w, uint16_t h, uint8_t r = 0 ) {
58
91
begin (SPI, w, h, r);
59
92
}
93
+ #endif // _XPT2046_Touchscreen_h_
94
+
95
+ #if defined (XPT2046_Bitbang_h)
96
+ /* ************************************************/
97
+ /* ***** Inherits from XPT2046_Bitbang class ******/
98
+ /* ************************************************/
99
+
100
+ // Smirnov-Grubbs criterion
101
+ static SCREEN_POINT filter (SCREEN_POINT *p) {
102
+ uint16_t xRaw, yRaw, zRaw;
103
+
104
+ xRaw = yRaw = zRaw = 0 ;
105
+ for (int i = 0 ; i < N_SAMPLES; ++i) {
106
+ xRaw += SP_RAW_X (p[i]);
107
+ yRaw += SP_RAW_Y (p[i]);
108
+ zRaw += SP_RAW_Z (p[i]);
109
+ }
110
+
111
+ xRaw /= N_SAMPLES;
112
+ yRaw /= N_SAMPLES;
113
+ zRaw /= N_SAMPLES;
114
+
115
+ uint16_t n, x, y, z;
116
+ n = x = y = z = 0 ;
117
+ for (int i = 0 ; i < N_SAMPLES; i++) {
118
+ if (abs (xRaw - SP_RAW_X (p[i])) <= N_THRESHOLD && abs (yRaw - SP_RAW_Y (p[i])) <= N_THRESHOLD) {
119
+ x += SP_RAW_X (p[i]);
120
+ y += SP_RAW_Y (p[i]);
121
+ z += SP_RAW_Z (p[i]);
122
+ n++;
123
+ }
124
+ }
125
+
126
+ if (n > 0 ) {
127
+ x /= n;
128
+ y /= n;
129
+ z /= n;
130
+ }
131
+
132
+ return SCREEN_POINT {0 , 0 , x, y, z};
133
+ }
134
+
135
+ public:
136
+ void setRotation (uint8_t r) {
137
+ rotation = r % 4 ;
138
+ }
139
+
140
+ void begin (uint16_t w, uint16_t h, uint8_t r = 0 ) {
141
+ PARENT_CLASS::begin ();
142
+ setRotation (r);
143
+ width = w;
144
+ height = h;
145
+ }
146
+
147
+ void begin (void ) {
148
+ begin ();
149
+ }
150
+
151
+ bool touched (void ) {
152
+ SCREEN_POINT p = PARENT_CLASS::getTouch ();
153
+ return (SP_RAW_Z (p) >= Z_THRESHOLD);
154
+ }
155
+
156
+ SCREEN_POINT getPoint (void ) {
157
+ SCREEN_POINT p[N_SAMPLES], q, r;
158
+
159
+ for (int i = 0 ; i < N_SAMPLES; i++) {
160
+ p[i] = PARENT_CLASS::getTouch ();
161
+ }
162
+
163
+ // Filter outliers
164
+ q = filter (p);
165
+
166
+ switch (rotation) {
167
+ case 0 :
168
+ SP_RAW_X (r) = 4095 - SP_RAW_Y (q);
169
+ SP_RAW_Y (r) = SP_RAW_X (q);
170
+ break ;
171
+ case 1 :
172
+ SP_RAW_X (r) = SP_RAW_X (q);
173
+ SP_RAW_Y (r) = SP_RAW_Y (q);
174
+ break ;
175
+ case 2 :
176
+ SP_RAW_X (r) = SP_RAW_Y (q);
177
+ SP_RAW_Y (r) = 4095 - SP_RAW_X (q);
178
+ break ;
179
+ default : // 3
180
+ SP_RAW_X (r) = 4095 - SP_RAW_X (q);
181
+ SP_RAW_Y (r) = 4095 - SP_RAW_Y (q);
182
+ break ;
183
+ }
184
+ SP_RAW_Z (r) = SP_RAW_Z (q);
185
+ r.x = r.y = 0 ;
186
+ return r;
187
+ }
188
+ #endif // XPT2046_Bitbang_h
60
189
61
190
bool setTouch (const uint16_t *cal) {
62
191
if (cal[4 ] == rotation) {
@@ -82,37 +211,34 @@ class XPT2046_ScreenPoint : public XPT2046_Touchscreen {
82
211
return calibrated;
83
212
}
84
213
85
- bool getTouch (uint16_t *x, uint16_t *y, uint16_t threshold = 600 ) {
86
- if (touched ()) {
87
- TS_Point p = getPoint ();
88
-
89
- if (p.z >= threshold) {
90
- if (calibrated) {
91
- int16_t xCoord = round ((p.x * xCalM) + xCalC);
92
- int16_t yCoord = round ((p.y * yCalM) + yCalC);
93
-
94
- if (xCoord < 0 ) xCoord = 0 ; else
95
- if (xCoord >= width ) xCoord = width - 1 ;
96
- if (yCoord < 0 ) yCoord = 0 ; else
97
- if (yCoord >= height) yCoord = height - 1 ;
98
-
99
- *x = xCoord;
100
- *y = yCoord;
101
- } else {
102
- // https://randomnerdtutorials.com/lvgl-cheap-yellow-display-esp32-2432s028r/
103
- static const struct {
104
- uint16_t xmin, xmax, ymin, ymax;
105
- } cal[4 ] = {
106
- {240 , 3800 , 200 , 3700 },
107
- {200 , 3700 , 240 , 3800 },
108
- {260 , 3850 , 300 , 3950 },
109
- {300 , 3950 , 260 , 3850 }
110
- };
111
- *x = map (p.x , cal[rotation].xmin , cal[rotation].xmax , 0 , width );
112
- *y = map (p.y , cal[rotation].ymin , cal[rotation].ymax , 0 , height);
113
- }
114
- return true ;
214
+ bool getTouch (uint16_t *x, uint16_t *y, uint16_t threshold = Z_THRESHOLD) {
215
+ SCREEN_POINT gp = getPoint ();
216
+ if (SP_RAW_Z (gp) >= threshold) {
217
+ if (calibrated) {
218
+ int16_t xCoord = round ((SP_RAW_X (gp) * xCalM) + xCalC);
219
+ int16_t yCoord = round ((SP_RAW_Y (gp) * yCalM) + yCalC);
220
+
221
+ if (xCoord < 0 ) xCoord = 0 ; else
222
+ if (xCoord >= width ) xCoord = width - 1 ;
223
+ if (yCoord < 0 ) yCoord = 0 ; else
224
+ if (yCoord >= height) yCoord = height - 1 ;
225
+
226
+ *x = xCoord;
227
+ *y = yCoord;
228
+ } else {
229
+ // https://randomnerdtutorials.com/lvgl-cheap-yellow-display-esp32-2432s028r/
230
+ static const struct {
231
+ uint16_t xmin, xmax, ymin, ymax;
232
+ } cal[4 ] = {
233
+ {240 , 3800 , 200 , 3700 },
234
+ {200 , 3700 , 240 , 3800 },
235
+ {260 , 3850 , 300 , 3950 },
236
+ {300 , 3950 , 260 , 3850 }
237
+ };
238
+ *x = map (SP_RAW_X (gp), cal[rotation].xmin , cal[rotation].xmax , 0 , width );
239
+ *y = map (SP_RAW_Y (gp), cal[rotation].ymin , cal[rotation].ymax , 0 , height);
115
240
}
241
+ return true ;
116
242
}
117
243
return false ;
118
244
}
@@ -138,9 +264,13 @@ class XPT2046_ScreenPoint : public XPT2046_Touchscreen {
138
264
while (!touched ());
139
265
delay (50 ); // wait for touch being stable
140
266
141
- TS_Point p = getPoint ();
142
- cal[0 ] = p.x ;
143
- cal[1 ] = p.y ;
267
+ SCREEN_POINT p;
268
+ do {
269
+ p = getPoint ();
270
+ } while (SP_RAW_Z (p) < Z_THRESHOLD);
271
+
272
+ cal[0 ] = SP_RAW_X (p);
273
+ cal[1 ] = SP_RAW_Y (p);
144
274
tft->drawFastHLine (10 , 20 , 20 , color_bg);
145
275
tft->drawFastVLine (20 , 10 , 20 , color_bg);
146
276
@@ -153,9 +283,12 @@ class XPT2046_ScreenPoint : public XPT2046_Touchscreen {
153
283
while (!touched ());
154
284
delay (50 ); // wait for touch being stable
155
285
156
- p = getPoint ();
157
- cal[2 ] = p.x ;
158
- cal[3 ] = p.y ;
286
+ do {
287
+ p = getPoint ();
288
+ } while (SP_RAW_Z (p) < Z_THRESHOLD);
289
+
290
+ cal[2 ] = SP_RAW_X (p);
291
+ cal[3 ] = SP_RAW_Y (p);
159
292
tft->drawFastHLine (width - 30 , height - 20 , 20 , color_bg);
160
293
tft->drawFastVLine (width - 20 , height - 30 , 20 , color_bg);
161
294
0 commit comments