/ adafruit_stmpe610.py
adafruit_stmpe610.py
1 # The MIT License (MIT) 2 # 3 # Copyright (c) 2017 Jerry Needell 4 # 5 # Permission is hereby granted, free of charge, to any person obtaining a copy 6 # of this software and associated documentation files (the "Software"), to deal 7 # in the Software without restriction, including without limitation the rights 8 # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 # copies of the Software, and to permit persons to whom the Software is 10 # furnished to do so, subject to the following conditions: 11 # 12 # The above copyright notice and this permission notice shall be included in 13 # all copies or substantial portions of the Software. 14 # 15 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 # THE SOFTWARE. 22 """ 23 `adafruit_stmpe610` 24 ==================================================== 25 26 This is a CircuitPython Driver for the STMPE610 Resistive Touch sensor 27 28 * Author(s): Jerry Needell 29 """ 30 31 # imports 32 33 import time 34 from micropython import const 35 36 37 __version__ = "0.0.0-auto.0" 38 __repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_STMPE610.git" 39 40 41 _STMPE_ADDR = const(0x41) 42 _STMPE_VERSION = const(0x0811) 43 44 _STMPE_SYS_CTRL1 = const(0x03) 45 _STMPE_SYS_CTRL1_RESET = const(0x02) 46 _STMPE_SYS_CTRL2 = const(0x04) 47 48 _STMPE_TSC_CTRL = const(0x40) 49 _STMPE_TSC_CTRL_EN = const(0x01) 50 _STMPE_TSC_CTRL_XYZ = const(0x00) 51 _STMPE_TSC_CTRL_XY = const(0x02) 52 53 _STMPE_INT_CTRL = const(0x09) 54 _STMPE_INT_CTRL_POL_HIGH = const(0x04) 55 _STMPE_INT_CTRL_POL_LOW = const(0x00) 56 _STMPE_INT_CTRL_EDGE = const(0x02) 57 _STMPE_INT_CTRL_LEVEL = const(0x00) 58 _STMPE_INT_CTRL_ENABLE = const(0x01) 59 _STMPE_INT_CTRL_DISABLE = const(0x00) 60 61 62 _STMPE_INT_EN = const(0x0A) 63 _STMPE_INT_EN_TOUCHDET = const(0x01) 64 _STMPE_INT_EN_FIFOTH = const(0x02) 65 _STMPE_INT_EN_FIFOOF = const(0x04) 66 _STMPE_INT_EN_FIFOFULL = const(0x08) 67 _STMPE_INT_EN_FIFOEMPTY = const(0x10) 68 _STMPE_INT_EN_ADC = const(0x40) 69 _STMPE_INT_EN_GPIO = const(0x80) 70 71 _STMPE_INT_STA = const(0x0B) 72 _STMPE_INT_STA_TOUCHDET = const(0x01) 73 74 _STMPE_ADC_CTRL1 = const(0x20) 75 _STMPE_ADC_CTRL1_12BIT = const(0x08) 76 _STMPE_ADC_CTRL1_10BIT = const(0x00) 77 78 _STMPE_ADC_CTRL2 = const(0x21) 79 _STMPE_ADC_CTRL2_1_625MHZ = const(0x00) 80 _STMPE_ADC_CTRL2_3_25MHZ = const(0x01) 81 _STMPE_ADC_CTRL2_6_5MHZ = const(0x02) 82 83 _STMPE_TSC_CFG = const(0x41) 84 _STMPE_TSC_CFG_1SAMPLE = const(0x00) 85 _STMPE_TSC_CFG_2SAMPLE = const(0x40) 86 _STMPE_TSC_CFG_4SAMPLE = const(0x80) 87 _STMPE_TSC_CFG_8SAMPLE = const(0xC0) 88 _STMPE_TSC_CFG_DELAY_10US = const(0x00) 89 _STMPE_TSC_CFG_DELAY_50US = const(0x08) 90 _STMPE_TSC_CFG_DELAY_100US = const(0x10) 91 _STMPE_TSC_CFG_DELAY_500US = const(0x18) 92 _STMPE_TSC_CFG_DELAY_1MS = const(0x20) 93 _STMPE_TSC_CFG_DELAY_5MS = const(0x28) 94 _STMPE_TSC_CFG_DELAY_10MS = const(0x30) 95 _STMPE_TSC_CFG_DELAY_50MS = const(0x38) 96 _STMPE_TSC_CFG_SETTLE_10US = const(0x00) 97 _STMPE_TSC_CFG_SETTLE_100US = const(0x01) 98 _STMPE_TSC_CFG_SETTLE_500US = const(0x02) 99 _STMPE_TSC_CFG_SETTLE_1MS = const(0x03) 100 _STMPE_TSC_CFG_SETTLE_5MS = const(0x04) 101 _STMPE_TSC_CFG_SETTLE_10MS = const(0x05) 102 _STMPE_TSC_CFG_SETTLE_50MS = const(0x06) 103 _STMPE_TSC_CFG_SETTLE_100MS = const(0x07) 104 105 _STMPE_FIFO_TH = const(0x4A) 106 107 _STMPE_FIFO_SIZE = const(0x4C) 108 109 _STMPE_FIFO_STA = const(0x4B) 110 _STMPE_FIFO_STA_RESET = const(0x01) 111 _STMPE_FIFO_STA_OFLOW = const(0x80) 112 _STMPE_FIFO_STA_FULL = const(0x40) 113 _STMPE_FIFO_STA_EMPTY = const(0x20) 114 _STMPE_FIFO_STA_THTRIG = const(0x10) 115 116 _STMPE_TSC_I_DRIVE = const(0x58) 117 _STMPE_TSC_I_DRIVE_20MA = const(0x00) 118 _STMPE_TSC_I_DRIVE_50MA = const(0x01) 119 120 _STMPE_TSC_DATA_X = const(0x4D) 121 _STMPE_TSC_DATA_Y = const(0x4F) 122 _STMPE_TSC_FRACTION_Z = const(0x56) 123 124 _STMPE_GPIO_SET_PIN = const(0x10) 125 _STMPE_GPIO_CLR_PIN = const(0x11) 126 _STMPE_GPIO_DIR = const(0x13) 127 _STMPE_GPIO_ALT_FUNCT = const(0x17) 128 129 130 class Adafruit_STMPE610: 131 """ 132 A driver for the STMPE610 Resistive Touch sensor. 133 """ 134 135 def __init__(self): 136 """Reset the controller""" 137 self._write_register_byte(_STMPE_SYS_CTRL1, _STMPE_SYS_CTRL1_RESET) 138 time.sleep(0.001) 139 140 self._write_register_byte(_STMPE_SYS_CTRL2, 0x0) # turn on clocks! 141 self._write_register_byte( 142 _STMPE_TSC_CTRL, _STMPE_TSC_CTRL_XYZ | _STMPE_TSC_CTRL_EN 143 ) # XYZ and enable! 144 self._write_register_byte(_STMPE_INT_EN, _STMPE_INT_EN_TOUCHDET) 145 self._write_register_byte( 146 _STMPE_ADC_CTRL1, _STMPE_ADC_CTRL1_10BIT | (0x6 << 4) 147 ) # 96 clocks per conversion 148 self._write_register_byte(_STMPE_ADC_CTRL2, _STMPE_ADC_CTRL2_6_5MHZ) 149 self._write_register_byte( 150 _STMPE_TSC_CFG, 151 _STMPE_TSC_CFG_4SAMPLE 152 | _STMPE_TSC_CFG_DELAY_1MS 153 | _STMPE_TSC_CFG_SETTLE_5MS, 154 ) 155 self._write_register_byte(_STMPE_TSC_FRACTION_Z, 0x6) 156 self._write_register_byte(_STMPE_FIFO_TH, 1) 157 self._write_register_byte(_STMPE_FIFO_STA, _STMPE_FIFO_STA_RESET) 158 self._write_register_byte(_STMPE_FIFO_STA, 0) # unreset 159 self._write_register_byte(_STMPE_TSC_I_DRIVE, _STMPE_TSC_I_DRIVE_50MA) 160 self._write_register_byte(_STMPE_INT_STA, 0xFF) # reset all ints 161 self._write_register_byte( 162 _STMPE_INT_CTRL, _STMPE_INT_CTRL_POL_HIGH | _STMPE_INT_CTRL_ENABLE 163 ) 164 165 def read_data(self): 166 """Request next stored reading - return tuple containing (x,y,pressure) """ 167 d_1 = self._read_byte(0xD7) 168 d_2 = self._read_byte(0xD7) 169 d_3 = self._read_byte(0xD7) 170 d_4 = self._read_byte(0xD7) 171 x_loc = d_1 << 4 | d_2 >> 4 172 y_loc = (d_2 & 0xF) << 8 | d_3 173 pressure = d_4 174 # reset all ints (not sure what this does) 175 if self.buffer_empty: 176 self._write_register_byte(_STMPE_INT_STA, 0xFF) 177 return (x_loc, y_loc, pressure) 178 179 def _read_byte(self, register): 180 """Read a byte register value and return it""" 181 return self._read_register(register, 1)[0] 182 183 def _read_register(self, register, length): 184 # Read an arbitrarily long register (specified by length number of 185 # bytes) and return a bytearray of the retrieved data. 186 # Subclasses MUST implement this! 187 raise NotImplementedError 188 189 def _write_register_byte(self, register, value): 190 # Write a single byte register at the specified register address. 191 # Subclasses MUST implement this! 192 raise NotImplementedError 193 194 @property 195 def touches(self): 196 """ 197 Returns a list of touchpoint dicts, with 'x' and 'y' containing the 198 touch coordinates, and 'pressure' 199 """ 200 touchpoints = [] 201 while (len(touchpoints) < 4) and not self.buffer_empty: 202 (x_loc, y_loc, pressure) = self.read_data() 203 point = {"x": x_loc, "y": y_loc, "pressure": pressure} 204 touchpoints.append(point) 205 return touchpoints 206 207 @property 208 def get_version(self): 209 "Read the version number from the sensosr" 210 v_1 = self._read_byte(0) 211 v_2 = self._read_byte(1) 212 version = v_1 << 8 | v_2 213 # print("version ",hex(version)) 214 return version 215 216 @property 217 def touched(self): 218 "Report if any touches have been detectd" 219 touch = self._read_byte(_STMPE_TSC_CTRL) & 0x80 220 return touch == 0x80 221 222 @property 223 def buffer_size(self): 224 "The amount of touch data in the buffer" 225 return self._read_byte(_STMPE_FIFO_SIZE) 226 227 @property 228 def buffer_empty(self): 229 "Buffer empty status" 230 empty = self._read_byte(_STMPE_FIFO_STA) & _STMPE_FIFO_STA_EMPTY 231 return empty != 0 232 233 @property 234 def get_point(self): 235 "Read one touch from the buffer" 236 (x_loc, y_loc, pressure) = self.read_data() 237 point = {"x": x_loc, "y": y_loc, "pressure": pressure} 238 return point 239 240 241 class Adafruit_STMPE610_I2C(Adafruit_STMPE610): 242 """ 243 I2C driver for the STMPE610 Resistive Touch sensor. 244 """ 245 246 def __init__(self, i2c, address=_STMPE_ADDR): 247 """ 248 Check the STMPE610 was founnd 249 Default address is 0x41 but another address can be passed in as an argument 250 """ 251 import adafruit_bus_device.i2c_device as i2cdev # pylint: disable=import-outside-toplevel 252 253 self._i2c = i2cdev.I2CDevice(i2c, address) 254 # Check device version. 255 version = self.get_version 256 if _STMPE_VERSION != version: 257 raise RuntimeError("Failed to find STMPE610! Chip Version 0x%x" % version) 258 super().__init__() 259 260 def _read_register(self, register, length): 261 """Low level register reading over I2C, returns a list of values""" 262 with self._i2c as i2c: 263 i2c.write(bytearray([register & 0xFF])) 264 result = bytearray(length) 265 i2c.readinto(result) 266 # print("$%02X => %s" % (register, [hex(i) for i in result])) 267 return result 268 269 def _write_register_byte(self, register, value): 270 """Low level register writing over I2C, writes one 8-bit value""" 271 with self._i2c as i2c: 272 i2c.write(bytes([register & 0xFF, value & 0xFF])) 273 # print("$%02X <= 0x%02X" % (register, value)) 274 275 276 class Adafruit_STMPE610_SPI(Adafruit_STMPE610): 277 """ 278 SPI driver for the STMPE610 Resistive Touch sensor. 279 """ 280 281 def __init__(self, spi, cs, baudrate=1000000): 282 """ 283 Check the STMPE610 was found,Default clock rate 1000000 - can be changed with 'baudrate' 284 """ 285 import adafruit_bus_device.spi_device as spidev # pylint: disable=import-outside-toplevel 286 287 self._spi = spidev.SPIDevice(spi, cs, baudrate=baudrate) 288 # Check device version. 289 version = self.get_version 290 if _STMPE_VERSION != version: 291 # if it fails try SPI MODE 1 -- that is what Arduino does 292 self._spi = spidev.SPIDevice( 293 spi, cs, baudrate=baudrate, polarity=0, phase=1 294 ) 295 version = self.get_version 296 if _STMPE_VERSION != version: 297 raise RuntimeError( 298 "Failed to find STMPE610! Chip Version 0x%x" % version 299 ) 300 super().__init__() 301 302 # pylint: disable=no-member 303 # Disable should be reconsidered when refactor can be tested. 304 def _read_register(self, register, length): 305 """Low level register reading over SPI, returns a list of values""" 306 register = (register | 0x80) & 0xFF # Read single, bit 7 high. 307 with self._spi as spi: 308 spi.write(bytearray([register])) 309 result = bytearray(length) 310 spi.readinto(result) 311 # print("$%02X => %s" % (register, [hex(i) for i in result])) 312 return result 313 314 def _write_register_byte(self, register, value): 315 """Low level register writing over SPI, writes one 8-bit value""" 316 register &= 0x7F # Write, bit 7 low. 317 with self._spi as spi: 318 spi.write(bytes([register, value & 0xFF]))