Skip to content

Commit e8de453

Browse files
matouch_esp32_s3_2_8_spi work
- Natural orientation: camera on top, USB ports on bottom - OV3660 camera works (but colors are off and it breaks the touch input) - Improve board detection
1 parent 4e16096 commit e8de453

7 files changed

Lines changed: 363 additions & 42 deletions

File tree

internal_filesystem/lib/mpos/board/matouch_esp32_s3_2_8.py

Lines changed: 13 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11

22
print("matouch_esp32_s3_2_8.py initialization")
33
# Hardware initialization for Makerfabs MaTouch ESP32-S3 SPI 2.8" with Camera
4-
# Manufacturer's website: https://www.makerfabs.com/matouch-esp32-s3.html
4+
# Manufacturer's website: https://www.makerfabs.com/matouch-esp32-s3-spi-ips-2-8-with-camera-ov3660.html
55
# Hardware Specifications:
66
# - MCU: ESP32-S3 with 16MB Flash, 8MB Octal PSRAM
77
# - Display: 2.8" IPS LCD, 320x240 resolution, ST7789 driver, SPI interface
@@ -77,45 +77,25 @@
7777
mpos.ui.main_display.set_backlight(100)
7878

7979
# Touch handling
80-
# Often times, a "ghost" device seems to show up on the I2C bus at 0x14.
81-
# Initializing it, although it fails, seems to bring up the "proper" GT911 at address 0x5D (gt911.I2C_ADDR).
8280
try:
8381
import i2c
84-
import gt911
85-
i2c_bus = i2c.I2C.Bus(host=0, scl=38, sda=39, freq=400000, use_locks=False)
86-
touch_dev = i2c.I2C.Device(bus=i2c_bus, dev_id=0x14, reg_bits=gt911.BITS)
87-
indev = gt911.GT911(touch_dev, reset_pin=1, interrupt_pin=40, debug=True)
88-
except Exception as e:
89-
print(f"Touch init phase 1 got exception: {e}")
90-
try:
91-
import pointer_framework
82+
i2c_bus = i2c.I2C.Bus(host=0, scl=38, sda=39)
83+
import mpos.indev.gt911 as gt911
9284
touch_dev = i2c.I2C.Device(bus=i2c_bus, dev_id=gt911.I2C_ADDR, reg_bits=gt911.BITS)
93-
indev = gt911.GT911(touch_dev, reset_pin=1, interrupt_pin=40, startup_rotation=pointer_framework.lv.DISPLAY_ROTATION._180, debug=True)
85+
indev = gt911.GT911(touch_dev, reset_pin=1, interrupt_pin=40, debug=True) # remove debug because it's slower
9486
except Exception as e:
95-
print(f"Touch init phase 2 got exception: {e}")
87+
print(f"Touch init got exception: {e}")
9688

9789
# Initialize LVGL
9890
lv.init()
99-
mpos.ui.main_display.set_rotation(lv.DISPLAY_ROTATION._90) # must be done after initializing display and creating the touch drivers, to ensure proper handling
100-
101-
# === BATTERY VOLTAGE MONITORING ===
102-
# Note: MaTouch ESP32-S3 battery monitoring configuration may vary
103-
# This is a placeholder - adjust ADC pin and conversion formula based on actual hardware
104-
from mpos import BatteryManager
105-
106-
def adc_to_voltage(adc_value):
107-
"""
108-
Convert raw ADC value to battery voltage.
109-
Currently uses simple linear scaling: voltage = adc * 0.00262
110-
111-
This should be calibrated with actual battery voltages and ADC readings.
112-
To calibrate: measure actual battery voltages and corresponding ADC readings,
113-
then fit a linear or polynomial function.
114-
"""
115-
return adc_value * 0.00262
116-
117-
# Note: Adjust ADC pin number based on actual hardware schematic
118-
# BatteryManager.init_adc(5, adc_to_voltage)
91+
92+
# TODO: initialize SDIO (instead of SPI) SD card with:
93+
# CMD = 2
94+
# SCLK = 42
95+
# D0 = 41
96+
#import mpos.sdcard
97+
#mpos.sdcard.init(spi_bus, cs_pin=14)
98+
11999

120100
# === AUDIO HARDWARE ===
121101
# Note: MaTouch ESP32-S3 has no buzzer or I2S audio hardware
Lines changed: 178 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,178 @@
1+
# Copyright (c) 2024 - 2025 Kevin G. Schlosser
2+
3+
# this driver uses a special i2c bus implimentation I have written.
4+
# This implimentation takes into consideration the ESP32 and it having
5+
# threading available. It also has some convience methods built into it
6+
# that figure out what is wanting to be done automatically.
7+
# read more about it's use in the stub files.
8+
9+
from micropython import const # NOQA
10+
import pointer_framework
11+
import machine # NOQA
12+
import time
13+
14+
15+
_CMD_REG = const(0x8040)
16+
_CMD_CHECK_REG = const(0x8046)
17+
_CMD_READ_DATA = const(0x01)
18+
19+
_ESD_CHECK_REG = const(0x8041)
20+
21+
_STATUS_REG = const(0x814E)
22+
_POINT_1_REG = const(0x8150)
23+
24+
_PRODUCT_ID_REG = const(0x8140)
25+
_FIRMWARE_VERSION_REG = const(0x8144)
26+
_VENDOR_ID_REG = const(0x814A)
27+
28+
_X_CORD_RES_REG = const(0x8146)
29+
_Y_CORD_RES_REG = const(0x8148)
30+
31+
I2C_ADDR = 0x5D
32+
BITS = 16
33+
34+
_ADDR2 = const(0x14)
35+
36+
37+
class GT911(pointer_framework.PointerDriver):
38+
39+
def _read_reg(self, reg, num_bytes=None, buf=None):
40+
self._tx_buf[0] = reg >> 8
41+
self._tx_buf[1] = reg & 0xFF
42+
try:
43+
if num_bytes is not None:
44+
self._device.write_readinto(self._tx_mv[:2], self._rx_mv[:num_bytes])
45+
else:
46+
self._device.write_readinto(self._tx_mv[:2], buf)
47+
except Exception as e:
48+
print(f"GT911 _read_reg got exception: {e}")
49+
50+
def _write_reg(self, reg, value=None, buf=None):
51+
try:
52+
if value is not None:
53+
self._tx_buf[0] = value
54+
self._device.write_mem(reg, self._tx_mv[:1])
55+
elif buf is not None:
56+
self._device.write_mem(reg, buf)
57+
except Exception as e:
58+
print(f"GT911 _write_reg got exception: {e}")
59+
60+
def __init__(
61+
self,
62+
device,
63+
reset_pin=None,
64+
interrupt_pin=None,
65+
touch_cal=None,
66+
startup_rotation=pointer_framework.lv.DISPLAY_ROTATION._0, # NOQA
67+
debug=False
68+
):
69+
self._tx_buf = bytearray(3)
70+
self._tx_mv = memoryview(self._tx_buf)
71+
self._rx_buf = bytearray(6)
72+
self._rx_mv = memoryview(self._rx_buf)
73+
74+
self._device = device
75+
76+
self.__x = 0
77+
self.__y = 0
78+
self.__last_state = self.RELEASED
79+
80+
if isinstance(reset_pin, int):
81+
reset_pin = machine.Pin(reset_pin, machine.Pin.OUT)
82+
83+
if isinstance(interrupt_pin, int):
84+
interrupt_pin = machine.Pin(interrupt_pin, machine.Pin.OUT)
85+
86+
self._reset_pin = reset_pin
87+
self._interrupt_pin = interrupt_pin
88+
89+
self.hw_reset()
90+
super().__init__(
91+
touch_cal=touch_cal, startup_rotation=startup_rotation, debug=debug
92+
)
93+
94+
def hw_reset(self):
95+
if self._interrupt_pin and self._reset_pin:
96+
self._interrupt_pin.init(self._interrupt_pin.OUT)
97+
self._interrupt_pin(0)
98+
self._reset_pin(0)
99+
time.sleep_ms(10) # NOQA
100+
self._interrupt_pin(0)
101+
time.sleep_ms(1) # NOQA
102+
self._reset_pin(1)
103+
time.sleep_ms(5) # NOQA
104+
self._interrupt_pin(0)
105+
time.sleep_ms(50) # NOQA
106+
self._interrupt_pin.init(self._interrupt_pin.IN)
107+
time.sleep_ms(50) # NOQA
108+
109+
self._write_reg(_ESD_CHECK_REG, 0x00)
110+
self._write_reg(_CMD_CHECK_REG, _CMD_READ_DATA)
111+
self._write_reg(_CMD_REG, _CMD_READ_DATA)
112+
113+
self._read_reg(_PRODUCT_ID_REG, 4)
114+
115+
product_id = ''
116+
for item in self._rx_buf[:4]:
117+
try:
118+
product_id += chr(item)
119+
except: # NOQA
120+
break
121+
122+
print('Touch Product id:', product_id)
123+
124+
self._read_reg(_FIRMWARE_VERSION_REG, 2)
125+
print(
126+
'Touch Firmware version:',
127+
hex(self._rx_buf[0] + (self._rx_buf[1] << 8))
128+
)
129+
130+
self._read_reg(_VENDOR_ID_REG, 1)
131+
print(f'Touch Vendor id: 0x{hex(self._rx_buf[0])[2:].upper()}')
132+
x, y = self.hw_size
133+
print(f'Touch resolution: width={x}, height={y}')
134+
135+
@property
136+
def hw_size(self):
137+
self._read_reg(_X_CORD_RES_REG, 2)
138+
x = self._rx_buf[0] + (self._rx_buf[1] << 8)
139+
140+
self._read_reg(_Y_CORD_RES_REG, 2)
141+
y = self._rx_buf[0] + (self._rx_buf[1] << 8)
142+
143+
return x, y
144+
145+
@property
146+
def firmware_config(self):
147+
try:
148+
import gt911_extension
149+
except ImportError:
150+
raise ImportError(
151+
'you need to upload the gt911_extension.py file to the MCU'
152+
)
153+
return gt911_extension.GT911Extension(self, self._device)
154+
155+
def _get_coords(self):
156+
self._read_reg(_STATUS_REG, 1)
157+
touch_cnt = self._rx_buf[0] & 0x0F
158+
status = self._rx_buf[0] & 0x80
159+
160+
if status:
161+
if touch_cnt == 1:
162+
self._read_reg(_POINT_1_REG, 6)
163+
164+
x = self._rx_buf[0] + (self._rx_buf[1] << 8)
165+
y = self._rx_buf[2] + (self._rx_buf[3] << 8)
166+
167+
self._write_reg(_STATUS_REG, 0x00)
168+
169+
self.__x = x
170+
self.__y = y
171+
self.__last_state = self.PRESSED
172+
173+
elif touch_cnt == 0:
174+
self.__last_state = self.RELEASED
175+
176+
self._write_reg(_STATUS_REG, 0x00)
177+
178+
return self.__last_state, self.__x, self.__y

0 commit comments

Comments
 (0)