Skip to content

Commit eb476d0

Browse files
committed
Add support for Makerfabs MaTouch boards
1 parent a22ce8c commit eb476d0

5 files changed

Lines changed: 427 additions & 88 deletions

File tree

README.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,11 @@
77

88
Currently this requires:
99
- CircuitPython 9.x (pre-alpha)
10-
- an 800x480 "dot clock"/"666" display
10+
- a "dot clock"/"666" display
1111
- FocalTech capacitive touch chips (Currently supports FT6206 & FT6236)
12+
- GOODIX GT911 touch interface
1213

13-
This has only been tested using the [HackTablet](https://hackaday.io/project/185831-hacktablet-crestron-tss-752-teardown-rebuild)
14+
This has only been tested using the [HackTablet](https://hackaday.io/project/185831-hacktablet-crestron-tss-752-teardown-rebuild) and the [MaTouch ESP32-S3 7"](https://www.makerfabs.com/index.php?route=product/product&product_id=774)
1415

1516
The **lib/pydos_ui_virt.py** file performs the keyboard abstraction for PyDOS.
1617

lib/gt911_touch.py

Lines changed: 222 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,222 @@
1+
# SPDX-FileCopyrightText: 2017 ladyada for Adafruit Industries
2+
#
3+
# SPDX-License-Identifier: MIT
4+
5+
"""
6+
`gt911_touch`
7+
====================================================
8+
9+
CircuitPython driver for GOODix GT911 touch chip.
10+
11+
* Author(s): ladyada, retiredwizard
12+
13+
Implementation Notes
14+
--------------------
15+
16+
**Hardware:**
17+
18+
* MaTouch ESP32-S3 Parallel TFT with Touch 7"
19+
20+
**Software and Dependencies:**
21+
22+
* Adafruit CircuitPython firmware for the ESP32-S3 boards:
23+
https://github.com/adafruit/circuitpython/releases
24+
* Adafruit's Bus Device library (when using I2C/SPI):
25+
https://github.com/adafruit/Adafruit_CircuitPython_BusDevice
26+
"""
27+
28+
# imports
29+
30+
__version__ = "0.0.0+auto.0"
31+
#__repo__ = "https://github.com/retiredwizard/PyDOS_virtkeyboard.git"
32+
33+
import struct
34+
import digitalio
35+
import time
36+
37+
from adafruit_bus_device.i2c_device import I2CDevice
38+
39+
from micropython import const
40+
41+
try:
42+
from typing import List
43+
except ImportError:
44+
pass
45+
46+
47+
_GT_DEFAULT_I2C_ADDR = 0x5D
48+
49+
_GT_COMMAND = const(0x8040)
50+
51+
52+
_GT_REG_STATUS = const(0x814E)
53+
_GT_POINT1_COORD = const(0x814F)
54+
_GT_REG_PRODID_1 = const(0x8140)
55+
_GT_REG_PRODID_2 = const(0x8141)
56+
_GT_REG_PRODID_3 = const(0x8142)
57+
_GT_REG_PRODID_4 = const(0x8143)
58+
_GT_REG_FIRMVERSH = const(0x8145)
59+
_GT_REG_FIRMVERSL = const(0x8144)
60+
_GT_REG_VENDID = const(0x814A)
61+
62+
_GT_PANNEL_BITFREQH = const(0x8068)
63+
_GT_PANNEL_BITFREQL = const(0x8067)
64+
_GT_SCREEN_TOUCH_LVL = const(0x8053)
65+
66+
_GT_TOUCH_NO = const(0x804C)
67+
_GT_X_THRESHOLD = const(0x8057)
68+
_GT_Y_THRESHOLD = const(0x8058)
69+
70+
71+
class GT911_Touch:
72+
"""
73+
A driver for the GT911 capacitive touch sensor.
74+
"""
75+
76+
def __init__(self, i2c, res_pin, address=_GT_DEFAULT_I2C_ADDR, debug=False, irq_pin=None):
77+
78+
self._debug = debug
79+
self._irq_pin = irq_pin
80+
81+
if type(res_pin) != digitalio.DigitalInOut:
82+
raise RuntimeError("res_pin must be of type digitalio.DigitalInOut")
83+
84+
self._reset(address,res_pin,irq_pin)
85+
try:
86+
self._i2c = I2CDevice(i2c, address)
87+
except:
88+
if debug:
89+
print("Second reset attempt")
90+
self._reset(address,res_pin,irq_pin)
91+
self._i2c = I2CDevice(i2c, address)
92+
93+
self._last_touch = self._read_last_touch()
94+
95+
chip_id = chr(self._read(_GT_REG_PRODID_1,1)[0])
96+
chip_id += chr(self._read(_GT_REG_PRODID_2,1)[0])
97+
chip_id += chr(self._read(_GT_REG_PRODID_3,1)[0])
98+
chip_id += chr(self._read(_GT_REG_PRODID_4,1)[0])
99+
firm_id = self._read(_GT_REG_FIRMVERSH,1)[0]
100+
firm_id = (firm_id << 8) | self._read(_GT_REG_FIRMVERSL,1)[0]
101+
vend_id = self._read(_GT_REG_VENDID,1)[0]
102+
num_touch = self._read(_GT_TOUCH_NO,1)[0] * 0x0F
103+
x_thresh = self._read(_GT_X_THRESHOLD,1)[0]
104+
y_thresh = self._read(_GT_Y_THRESHOLD,1)[0]
105+
106+
if debug:
107+
print("Number of touchpoints: ",num_touch," X,Y Thresholds: ",x_thresh,",",y_thresh)
108+
print(
109+
"chip_id: {:4}, firm_id: {:02X}, vend_id: {:02X}".format(
110+
chip_id, firm_id, vend_id
111+
)
112+
)
113+
print("Firmware ID %02X" % firm_id)
114+
print("Point rate %d Hz" % ((self._read(_GT_PANNEL_BITFREQH, 1)[0] << 8) | self._read(_GT_PANNEL_BITFREQL, 1)[0]))
115+
print("Thresh %d" % self._read(_GT_SCREEN_TOUCH_LVL, 1)[0])
116+
117+
self._write(_GT_COMMAND,[0]) # Read coordinates status
118+
119+
@property
120+
def touched(self) -> int:
121+
curr_touch = self._read_last_touch()
122+
if self._last_touch != curr_touch:
123+
self._last_touch = curr_touch
124+
""" If this extra call to _read_last_touch()
125+
isn't made then the next touch is missed ?????
126+
I have no idea why """
127+
self._read_last_touch()
128+
return 1
129+
else:
130+
return 0
131+
132+
def _read_last_touch(self):
133+
self._write(_GT_REG_STATUS,[0])
134+
test = self._read(_GT_REG_STATUS,1)[0]
135+
timeout = 1000
136+
while not (test & 0x80) and (timeout := timeout-1) > 0:
137+
if test == 0:
138+
break
139+
time.sleep(.001)
140+
self._write(_GT_REG_STATUS,[0])
141+
test = self._read(_GT_REG_STATUS,1)[0]
142+
self._write(_GT_REG_STATUS,[0])
143+
return [v for v in self._read(_GT_POINT1_COORD,7)]
144+
145+
# pylint: disable=unused-variable
146+
@property
147+
def touches(self) -> List[dict]:
148+
"""
149+
Returns a list of touchpoint dicts, with 'x' and 'y' containing the
150+
touch coordinates, and 'id' as the touch # for multitouch tracking
151+
"""
152+
touchpoints = []
153+
data = self._last_touch
154+
155+
touchcount = 1
156+
if self._debug:
157+
print("touchcount: {}".format(touchcount))
158+
159+
for i in range(touchcount):
160+
touch_id = data[0]
161+
162+
x = data[2] * 256 + data[1]
163+
y = data[4] * 256 + data[3]
164+
165+
point = {"x": x, "y": y, "id": touch_id}
166+
if self._debug:
167+
print("id: {}, x: {}, y: {}".format(touch_id, x, y))
168+
touchpoints.append(point)
169+
return touchpoints
170+
171+
def _reset(self, address, res_pin, irq_pin=None) -> None:
172+
""" Initialize board """
173+
time.sleep(.0001)
174+
res_pin.direction = digitalio.Direction.OUTPUT
175+
res_pin.value = True
176+
if irq_pin is not None:
177+
irq_pin.direction = digitalio.Direction.OUTPUT
178+
irq_pin.value = False
179+
time.sleep(.005)
180+
res_pin.value = False
181+
time.sleep(.001)
182+
if irq_pin is not None:
183+
irq_pin.value = (address != _GT_DEFAULT_I2C_ADDR)
184+
time.sleep(.001)
185+
res_pin.value = True
186+
time.sleep(.01)
187+
if irq_pin is not None:
188+
irq_pin.value = False
189+
time.sleep(.055)
190+
if irq_pin is not None:
191+
irq_pin.direction = digitalio.Direction.INPUT
192+
time.sleep(0.055)
193+
194+
return
195+
196+
def _read(self, register, length, irq_pin=None) -> bytearray:
197+
"""Returns an array of 'length' bytes from the 'register'"""
198+
with self._i2c as i2c:
199+
if irq_pin is not None:
200+
while irq_pin.value:
201+
pass
202+
203+
i2c.write(bytes([((register & 0xFF00) >> 8),(register & 0xFF)]))
204+
result = bytearray(length)
205+
time.sleep(.1)
206+
207+
i2c.readinto(result)
208+
if self._debug:
209+
print("\t$%02X => %s" % (register, [hex(i) for i in result]))
210+
return result
211+
212+
def _write(self, register, values) -> None:
213+
"""Writes an array of 'length' bytes to the 'register'"""
214+
with self._i2c as i2c:
215+
values = [((register & 0xFF00) >> 8), (register & 0xFF)] + [(v & 0xFF) for v in values]
216+
#print("register: %02X, value: %02X" % (values[0], values[1]))
217+
i2c.write(bytes(values))
218+
219+
if self._debug:
220+
print("\t$%02X <= %s" % (values[0], [hex(i) for i in values[1:]]))
221+
222+

0 commit comments

Comments
 (0)