mirror of
https://github.com/openmv/openmv.git
synced 2025-09-26 23:09:13 +08:00
139 lines
4.3 KiB
Python
139 lines
4.3 KiB
Python
"""
|
|
This file is part of the OpenMV project.
|
|
|
|
Copyright (c) 2023 Ibrahim Abdelkader <iabdalkader@openmv.io>
|
|
Copyright (c) 2023 Kwabena W. Agyeman <kwagyeman@openmv.io>
|
|
|
|
This work is licensed under the MIT license, see the file LICENSE for details.
|
|
|
|
GT911 5-Point Capacitive Touch Controller driver for MicroPython.
|
|
|
|
Basic polling mode example usage:
|
|
|
|
import time
|
|
from gt911 import GT911
|
|
from machine import I2C
|
|
|
|
# Note use pin numbers or names not Pin objects because the
|
|
# driver needs to change pin directions to reset the controller.
|
|
touch = GT911(I2C(1, freq=400_000), reset_pin="P1", irq_pin="P2", touch_points=5)
|
|
|
|
while True:
|
|
n, points = touch.read_points()
|
|
for i in range(0, n):
|
|
print(f"id {points[i][3]} x {points[i][0]} y {points[i][1]} size {points[i][2]}")
|
|
time.sleep_ms(100)
|
|
"""
|
|
|
|
from time import sleep_ms
|
|
from array import array
|
|
from machine import Pin
|
|
|
|
_DEFAULT_ADDR = const(0x5D)
|
|
|
|
_COMMAND = const(0x8040)
|
|
_REFRESH_RATE = const(0x8056)
|
|
_RESOLUTION_X = const(0x8048)
|
|
_RESOLUTION_Y = const(0x804A)
|
|
_TOUCH_POINTS = const(0x804C)
|
|
_MODULE_SWITCH1 = const(0x804D)
|
|
_CONFIG_CHKSUM = const(0x80FF)
|
|
_CONFIG_FRESH = const(0x8100)
|
|
_POINT_DATA_START = const(0x8150)
|
|
_DATA_BUFFER = const(0x814E)
|
|
|
|
|
|
class GT911:
|
|
def __init__(
|
|
self,
|
|
bus,
|
|
reset_pin,
|
|
irq_pin,
|
|
address=_DEFAULT_ADDR,
|
|
width=800,
|
|
height=480,
|
|
touch_points=1,
|
|
reverse_x=False,
|
|
reverse_y=False,
|
|
reverse_axis=True,
|
|
sito=True,
|
|
refresh_rate=240,
|
|
touch_callback=None,
|
|
):
|
|
self.bus = bus
|
|
self.address = address
|
|
self.touch_callback = touch_callback
|
|
self.rst_pin = Pin(reset_pin, Pin.OUT_PP, value=0)
|
|
self.irq_pin = None
|
|
self.irq_pin_label = irq_pin
|
|
|
|
# Reset the touch panel controller.
|
|
self.reset()
|
|
|
|
# Write and update the config.
|
|
self._write_reg(_RESOLUTION_X, width, 2)
|
|
self._write_reg(_RESOLUTION_Y, height, 2)
|
|
self._write_reg(_TOUCH_POINTS, touch_points)
|
|
self._write_reg(
|
|
_MODULE_SWITCH1,
|
|
(int(reverse_y) << 7)
|
|
| (int(reverse_x) << 6)
|
|
| (int(reverse_axis) << 3)
|
|
| (int(sito) << 2)
|
|
| 0x01,
|
|
)
|
|
self._write_reg(_REFRESH_RATE, (1000 * 1000) // (refresh_rate * 250))
|
|
self._write_reg(_COMMAND, 0x00)
|
|
self._update_config()
|
|
|
|
# Allocate scratch buffer.
|
|
self.points_data = [array("H", [0, 0, 0, 0]) for x in range(5)]
|
|
|
|
def _read_reg(self, reg, size=1, buf=None):
|
|
if buf is not None:
|
|
self.bus.readfrom_mem_into(self.address, reg, buf, addrsize=16)
|
|
else:
|
|
return self.bus.readfrom_mem(self.address, reg, size, addrsize=16)
|
|
|
|
def _write_reg(self, reg, val, size=1):
|
|
buf = bytes([val & 0xFF]) if size == 1 else bytes([val & 0xFF, val >> 8])
|
|
self.bus.writeto_mem(self.address, reg, buf, addrsize=16)
|
|
|
|
def _update_config(self):
|
|
# Read current config
|
|
chksum = ~sum(self._read_reg(0x8047, 184)) + 1
|
|
# Calculate checksum
|
|
self._write_reg(_CONFIG_CHKSUM, chksum)
|
|
# Update the config
|
|
self._write_reg(_CONFIG_FRESH, 0x01)
|
|
|
|
def read_id(self):
|
|
return self._read_reg(0x8140, 4)
|
|
|
|
def read_points(self):
|
|
status = self._read_reg(_DATA_BUFFER)[0]
|
|
n_points = status & 0x0F
|
|
if status & 0x80:
|
|
for i in range(0, n_points):
|
|
self._read_reg(_POINT_DATA_START + i * 8, buf=self.points_data[i])
|
|
# We read an extra reserved byte, shift track ID to fix it.
|
|
self.points_data[i][-1] = self.points_data[i][-1] >> 8
|
|
self._write_reg(_DATA_BUFFER, 0)
|
|
return n_points, self.points_data
|
|
|
|
def reset(self):
|
|
if self.irq_pin is not None:
|
|
self.irq_pin.irq(handler=None)
|
|
self.rst_pin(0)
|
|
sleep_ms(10)
|
|
self.irq_pin = Pin(self.irq_pin_label, Pin.OUT_PP, value=0)
|
|
sleep_ms(50)
|
|
self.rst_pin(1)
|
|
# Note must wait for at least 50ms before switching the IRQ pin to input.
|
|
sleep_ms(100)
|
|
self.irq_pin = Pin(self.irq_pin_label, Pin.IN, Pin.PULL_UP)
|
|
if self.touch_callback is not None:
|
|
self.irq_pin.irq(
|
|
handler=self.touch_callback, trigger=Pin.IRQ_FALLING, hard=False
|
|
)
|