LCDGFX LCD display driver  1.2.0
Lightweight graphics library for SSD1306, SSD1325, SSD1327, SSD1331, SSD1351, SH1106, SH1107, IL9163, ST7735, ST7789, ILI9341, PCD8544 displays over I2C/SPI
xpt2046.h
Go to the documentation of this file.
1 /*
2  MIT License
3 
4  Copyright (c) 2025, Alexey Dynda
5 
6  Permission is hereby granted, free of charge, to any person obtaining a copy
7  of this software and associated documentation files (the "Software"), to deal
8  in the Software without restriction, including without limitation the rights
9  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10  copies of the Software, and to permit persons to whom the Software is
11  furnished to do so, subject to the following conditions:
12 
13  The above copyright notice and this permission notice shall be included in all
14  copies or substantial portions of the Software.
15 
16  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22  SOFTWARE.
23 */
28 #ifndef _LCDGFX_TOUCH_XPT2046_H_
29 #define _LCDGFX_TOUCH_XPT2046_H_
30 
31 #include "touch.h"
32 
48 namespace lcdgfx_xpt2046
49 {
50 constexpr uint8_t CMD_X = 0xD3;
51 constexpr uint8_t CMD_Y = 0x93;
52 constexpr uint8_t CMD_Z1 = 0xB3;
53 constexpr uint8_t CMD_Z2 = 0xC3;
54 } // namespace lcdgfx_xpt2046
55 
71 template <typename SpiT> class LcdGfxXpt2046
72 {
73 public:
77  explicit LcdGfxXpt2046(SpiT &spi)
78  : m_spi(spi)
79  {
80  }
81 
86  void begin()
87  {
88  m_spi.begin();
89  }
90 
94  void end()
95  {
96  m_spi.end();
97  }
98 
104  {
105  m_calibration = cal;
106  }
107 
112  {
113  return m_calibration;
114  }
115 
120  void setPressureThreshold(uint16_t threshold)
121  {
122  m_pressureThreshold = threshold;
123  }
124 
132  bool readRaw(int16_t &rawX, int16_t &rawY, int16_t &rawZ)
133  {
134  m_spi.start();
135  uint16_t z1 = sampleChannel(lcdgfx_xpt2046::CMD_Z1);
136  uint16_t z2 = sampleChannel(lcdgfx_xpt2046::CMD_Z2);
137  rawZ = (int16_t)(z1 + (4095 - z2));
138 
139  uint16_t xs[3];
140  uint16_t ys[3];
141  for ( int i = 0; i < 3; i++ )
142  {
143  xs[i] = sampleChannel(lcdgfx_xpt2046::CMD_X);
144  ys[i] = sampleChannel(lcdgfx_xpt2046::CMD_Y);
145  }
146  m_spi.stop();
147 
148  rawX = (int16_t)median3(xs[0], xs[1], xs[2]);
149  rawY = (int16_t)median3(ys[0], ys[1], ys[2]);
150  return z1 > m_pressureThreshold;
151  }
152 
157  bool read(int16_t &x, int16_t &y)
158  {
159  int16_t rawX, rawY, rawZ;
160  bool pressed = readRaw(rawX, rawY, rawZ);
161  if ( !pressed )
162  {
163  return false;
164  }
165  m_calibration.apply(rawX, rawY, x, y);
166  return true;
167  }
168 
173  bool read(int16_t &x, int16_t &y, int16_t &pressure)
174  {
175  int16_t rawX, rawY;
176  bool pressed = readRaw(rawX, rawY, pressure);
177  if ( !pressed )
178  {
179  return false;
180  }
181  m_calibration.apply(rawX, rawY, x, y);
182  return true;
183  }
184 
185 private:
186  SpiT &m_spi;
187  TouchCalibration m_calibration{};
188  uint16_t m_pressureThreshold = 200;
189 
190  uint16_t sampleChannel(uint8_t cmd)
191  {
192  m_spi.transfer(cmd);
193  uint8_t hi = m_spi.transfer(0x00);
194  uint8_t lo = m_spi.transfer(0x00);
195  // 16 bits clocked out: result is 12-bit, MSB first, with 3 leading
196  // status/zero bits and 1 trailing zero bit. Compose the 12-bit value:
197  return (uint16_t)(((uint16_t)hi << 5) | (lo >> 3)) & 0x0FFF;
198  }
199 
200  static uint16_t median3(uint16_t a, uint16_t b, uint16_t c)
201  {
202  if ( a > b )
203  {
204  uint16_t t = a;
205  a = b;
206  b = t;
207  }
208  if ( b > c )
209  {
210  uint16_t t = b;
211  b = c;
212  c = t;
213  }
214  if ( a > b )
215  {
216  uint16_t t = a;
217  a = b;
218  b = t;
219  }
220  return b;
221  }
222 };
223 
228 #endif
LcdGfxXpt2046(SpiT &spi)
Constructs the driver around an SPI transport instance owned by the caller.
Definition: xpt2046.h:77
bool read(int16_t &x, int16_t &y)
Reads calibrated screen-pixel coordinates.
Definition: xpt2046.h:157
XPT2046 control byte definitions.
Definition: xpt2046.h:48
Driver for the XPT2046 resistive touch controller (also compatible with ADS7843 / TSC2046 silicon)...
Definition: xpt2046.h:71
constexpr uint8_t CMD_X
1 101 0 0 11 - read X (differential, 12-bit)
Definition: xpt2046.h:50
Generic touch driver interfaces and calibration helpers.
constexpr uint8_t CMD_Z1
1 011 0 0 11 - read Z1
Definition: xpt2046.h:52
void setPressureThreshold(uint16_t threshold)
Sets the minimum pressure (Z1 reading) considered an active touch.
Definition: xpt2046.h:120
void setCalibration(const TouchCalibration &cal)
Sets the calibration used by read().
Definition: xpt2046.h:103
void end()
Releases the SPI transport.
Definition: xpt2046.h:94
Linear calibration mapping raw ADC counts from a resistive touch panel into screen pixel coordinates...
Definition: touch.h:50
bool read(int16_t &x, int16_t &y, int16_t &pressure)
Reads calibrated coordinates plus raw pressure.
Definition: xpt2046.h:173
constexpr uint8_t CMD_Z2
1 100 0 0 11 - read Z2
Definition: xpt2046.h:53
bool readRaw(int16_t &rawX, int16_t &rawY, int16_t &rawZ)
Reads raw 12-bit ADC samples from the controller without applying any calibration.
Definition: xpt2046.h:132
TouchCalibration & calibration()
Returns the current calibration (mutable reference).
Definition: xpt2046.h:111
void begin()
Initialises the SPI transport.
Definition: xpt2046.h:86
constexpr uint8_t CMD_Y
1 001 0 0 11 - read Y
Definition: xpt2046.h:51