/ adafruit_focaltouch.py
adafruit_focaltouch.py
  1  # The MIT License (MIT)
  2  #
  3  # Copyright (c) 2017 ladyada for adafruit industries
  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_focaltouch`
 24  ====================================================
 25  
 26  CircuitPython driver for common low-cost FocalTech capacitive touch chips.
 27  Currently supports FT6206 & FT6236.
 28  
 29  * Author(s): ladyada
 30  
 31  Implementation Notes
 32  --------------------
 33  
 34  **Hardware:**
 35  
 36  * Adafruit `2.8" TFT LCD with Cap Touch Breakout Board w/MicroSD Socket
 37    <http://www.adafruit.com/product/2090>`_ (Product ID: 2090)
 38  
 39  * Adafruit `2.8" TFT Touch Shield for Arduino w/Capacitive Touch
 40    <http://www.adafruit.com/product/1947>`_ (Product ID: 1947)
 41  
 42  **Software and Dependencies:**
 43  
 44  * Adafruit CircuitPython firmware for the ESP8622 and M0-based boards:
 45    https://github.com/adafruit/circuitpython/releases
 46  * Adafruit's Bus Device library (when using I2C/SPI):
 47    https://github.com/adafruit/Adafruit_CircuitPython_BusDevice
 48  """
 49  
 50  # imports
 51  
 52  __version__ = "0.0.0-auto.0"
 53  __repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_FocalTouch.git"
 54  
 55  try:
 56      import struct
 57  except ImportError:
 58      import ustruct as struct
 59  
 60  from adafruit_bus_device.i2c_device import I2CDevice
 61  
 62  from micropython import const
 63  
 64  
 65  _FT6206_DEFAULT_I2C_ADDR = 0x38
 66  
 67  _FT6XXX_REG_DATA = const(0x00)
 68  _FT6XXX_REG_NUMTOUCHES = const(0x02)
 69  _FT6XXX_REG_THRESHHOLD = const(0x80)
 70  _FT6XXX_REG_POINTRATE = const(0x88)
 71  _FT6XXX_REG_LIBH = const(0xA1)
 72  _FT6XXX_REG_LIBL = const(0xA2)
 73  _FT6XXX_REG_CHIPID = const(0xA3)
 74  _FT6XXX_REG_FIRMVERS = const(0xA6)
 75  _FT6XXX_REG_VENDID = const(0xA8)
 76  _FT6XXX_REG_RELEASE = const(0xAF)
 77  
 78  
 79  class Adafruit_FocalTouch:
 80      """
 81      A driver for the FocalTech capacitive touch sensor.
 82      """
 83  
 84      _debug = False
 85      chip = None
 86  
 87      def __init__(self, i2c, address=_FT6206_DEFAULT_I2C_ADDR, debug=False):
 88          self._i2c = I2CDevice(i2c, address)
 89          self._debug = debug
 90  
 91          chip_data = self._read(_FT6XXX_REG_LIBH, 8)
 92          lib_ver, chip_id, _, _, firm_id, _, vend_id = struct.unpack(
 93              ">HBBBBBB", chip_data
 94          )
 95  
 96          if vend_id != 0x11:
 97              raise RuntimeError("Did not find FT chip")
 98  
 99          if chip_id == 0x06:
100              self.chip = "FT6206"
101          elif chip_id == 0x64:
102              self.chip = "FT6236"
103  
104          if debug:
105              print("Library vers %04X" % lib_ver)
106              print("Firmware ID %02X" % firm_id)
107              print("Point rate %d Hz" % self._read(_FT6XXX_REG_POINTRATE, 1)[0])
108              print("Thresh %d" % self._read(_FT6XXX_REG_THRESHHOLD, 1)[0])
109  
110      @property
111      def touched(self):
112          """ Returns the number of touches currently detected """
113          return self._read(_FT6XXX_REG_NUMTOUCHES, 1)[0]
114  
115      # pylint: disable=unused-variable
116      @property
117      def touches(self):
118          """
119          Returns a list of touchpoint dicts, with 'x' and 'y' containing the
120          touch coordinates, and 'id' as the touch # for multitouch tracking
121          """
122          touchpoints = []
123          data = self._read(_FT6XXX_REG_DATA, 32)
124  
125          for i in range(2):
126              point_data = data[i * 6 + 3 : i * 6 + 9]
127              if all([i == 0xFF for i in point_data]):
128                  continue
129              # print([hex(i) for i in point_data])
130              x, y, weight, misc = struct.unpack(">HHBB", point_data)
131              # print(x, y, weight, misc)
132              touch_id = y >> 12
133              x &= 0xFFF
134              y &= 0xFFF
135              point = {"x": x, "y": y, "id": touch_id}
136              touchpoints.append(point)
137          return touchpoints
138  
139      # pylint: enable=unused-variable
140  
141      def _read(self, register, length):
142          """Returns an array of 'length' bytes from the 'register'"""
143          with self._i2c as i2c:
144              i2c.write(bytes([register & 0xFF]))
145              result = bytearray(length)
146              i2c.readinto(result)
147              if self._debug:
148                  print("\t$%02X => %s" % (register, [hex(i) for i in result]))
149              return result
150  
151      def _write(self, register, values):
152          """Writes an array of 'length' bytes to the 'register'"""
153          with self._i2c as i2c:
154              values = [(v & 0xFF) for v in [register] + values]
155              i2c.write(bytes(values))
156              if self._debug:
157                  print("\t$%02X <= %s" % (values[0], [hex(i) for i in values[1:]]))