roo_display
API Documentation for roo_display
Loading...
Searching...
No Matches
touch_xpt2046.h
Go to the documentation of this file.
1#pragma once
2
8
9namespace roo_display {
10
11static const int kSpiTouchFrequency = 2500000;
12
15
16// If two subsequent reads are further apart than this parameter, in either
17// X or Y direction, their conversion is rejected as UNSETTLED.
18// This parameter helps to filter out random noise. If the value is too small,
19// though, the panel may have a hard time registering touch.
20static const int kMaxRawSettlingDistance = 200;
21
22// How many conversions we attempt in order to get to kMinSettledConversions.
23// If we reach this limit, we return the result based on however many settled
24// conversions we have seen, even if it is below the minimum.
25static const int kMaxConversionAttempts = 100;
26
27// How many settled conversions is enough to consider the reading reliable.
28static const int kMinSettledConversions = 8;
29
30// How hard the press needs to be to count as touch.
31static const int kInitialTouchZThreshold = 400;
32
33// // How hard the press needs to be to count as continued touch (i.e., once
34// // the display has been touched). See kTouchSensitivityLagMs.
35// static const int kSustainedTouchZThreshold = 300;
36
37// // To avoid spurious drops in drag touch, the driver is more sensitive to
38// touch
39// // (and thus more prone to picking up noise) for this many ms since last
40// // definitive touch.
41// static const int kTouchSensitivityLagMs = 250;
42
43template <int pinCS, typename Spi = DefaultSpi, typename Gpio = DefaultGpio>
44class TouchXpt2046 : public BasicTouchDevice<1> {
45 public:
46 explicit TouchXpt2046(Spi spi = Spi());
47
48 virtual void initTouch() override { device_.init(); }
49
50 protected:
51 int readTouch(TouchPoint* points) override;
52
53 private:
54 typename Spi::Device<TouchXpt2046SpiSettings> device_;
55
56 bool pressed_;
57 unsigned long latest_confirmed_pressed_timestamp_;
58};
59
60// Implementation follows.
61
62template <int pinCS, typename Spi, typename Gpio>
64 : BasicTouchDevice(Config{.min_sampling_interval_ms = 5,
65 .touch_intertia_ms = 30,
66 .smoothing_factor = 0.8}),
67 device_(spi),
68 pressed_(false),
69 latest_confirmed_pressed_timestamp_(0) {
70 Gpio::setOutput(pinCS);
71 Gpio::template setHigh<pinCS>();
72}
73
74template <typename Spi>
76 spi.transfer(roo::byte{0xd3});
77 *x = spi.transfer16(0xd3) >> 3;
78 *x = spi.transfer16(0xd3) >> 3;
79 *x = spi.transfer16(0x93) >> 3;
80
81 // Start bit + XP sample request for y position
82 // spi.transfer(0x93);
83 *y = spi.transfer16(0x93) >> 3;
84 *y = spi.transfer16(0x93) >> 3;
85 *y = spi.transfer16(0x00) >> 3;
86}
87
88template <typename Spi>
90 int16_t tz = 0xFFF;
91 spi.transfer(roo::byte{0xb1});
92 tz += spi.transfer16(0xc1) >> 3;
93 tz -= spi.transfer16(0) >> 3;
94 return (uint16_t)tz;
95}
96
98
99template <typename Spi>
101 uint16_t* y, uint16_t* z) {
102 // Wait until pressure stops increasing
103 uint16_t z1 = 1;
104 uint16_t z2 = 0;
105 while (z1 > z2) {
106 z2 = z1;
107 z1 = get_raw_touch_z(spi);
108 }
109
110 if (z1 <= z_threshold) {
111 return UNTOUCHED;
112 }
113
114 uint16_t x1, y1, x2, y2;
115 get_raw_touch_xy(spi, &x1, &y1);
116 get_raw_touch_xy(spi, &x2, &y2);
117 if (abs(x1 - x2) > kMaxRawSettlingDistance) return UNSETTLED;
118 if (abs(y1 - y2) > kMaxRawSettlingDistance) return UNSETTLED;
120 if (z3 <= z_threshold) {
121 return UNSETTLED;
122 }
123
124 // We have a valid touch sample pair. Return an arithmetic average as the
125 // result.
126 *x = (x1 + x2) / 2;
127 *y = (y1 + y2) / 2;
128 *z = z3;
129 return TOUCHED;
130}
131
132template <int pinCS, typename Spi, typename Gpio>
134 // long now = micros();
136 // if (pressed_ &&
137 // (now - latest_confirmed_pressed_timestamp_ < kTouchSensitivityLagMs) &&
138 // z_threshold > kSustainedTouchZThreshold) {
139 // z_threshold = kSustainedTouchZThreshold;
140 // }
141
142 SpiReadWriteTransaction<pinCS, decltype(device_), Gpio> transaction(device_);
143
144 int settled_conversions = 0;
146 int32_t x_sum = 0;
147 int32_t y_sum = 0;
148 int32_t z_max = 0;
149 int count = 0;
150
151 // Discard a few initial conversions so that the sensor settles.
152 for (int i = 0; i < 5; ++i) {
155 if (result == UNSETTLED) continue;
156 }
157
158 bool touched = false;
159 for (int i = 0; i < kMaxConversionAttempts; ++i) {
162 if (result == UNSETTLED) continue;
164 if (result == TOUCHED) {
165 touched = true;
166 x_sum += x_tmp;
167 y_sum += y_tmp;
168 if (z_max < z_tmp) z_max = z_tmp;
169 count++;
170 }
172 // We got enough settled conversions to return a result.
173 if (touched) {
174 touch_point->id = 0;
175 touch_point->x = 4095 - (x_sum / count);
176 touch_point->y = 4095 - (y_sum / count);
177 touch_point->z = z_max;
178 // if (z >= kInitialTouchZThreshold) {
179 // // We got a definite press.
180 // latest_confirmed_pressed_timestamp_ = now;
181 // }
182 }
183 pressed_ = touched;
184 return pressed_ ? 1 : 0;
185 }
186 }
187 // No reliable readout despite numerous attempts - aborting.
188 pressed_ = false;
189 return 0;
190};
191
192} // namespace roo_display
int readTouch(TouchPoint *points) override
TouchXpt2046(Spi spi=Spi())
virtual void initTouch() override
Initialize the touch controller.
Defines 140 opaque HTML named colors.
uint16_t get_raw_touch_z(Spi &spi)
static const int kMaxConversionAttempts
SpiSettings< kSpiTouchFrequency, kSpiMsbFirst, kSpiMode0 > TouchXpt2046SpiSettings
static const int kMinSettledConversions
static const int kMaxRawSettlingDistance
static const int kSpiTouchFrequency
void get_raw_touch_xy(Spi &spi, uint16_t *x, uint16_t *y)
ConversionResult single_conversion(Spi &spi, uint16_t z_threshold, uint16_t *x, uint16_t *y, uint16_t *z)
static const int kInitialTouchZThreshold
A single touch point returned by a touch controller.
Definition device.h:390