Skip to content

Commit 14ebe55

Browse files
authored
Add support for LilyGo T-HMI board and initialize display and battery… (#90)
* Add support for LilyGo T-HMI board and initialize display and battery management * Implement detection for LilyGO T-HMI touch screen * Refactor LilyGO T-HMI initialization and update touch device configuration * Remove t-hmi target configuration from build script and streamline OTA support handling
1 parent 2cc0565 commit 14ebe55

3 files changed

Lines changed: 206 additions & 4 deletions

File tree

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
print("lilygo_t_hmi.py initialization")
2+
# Manufacturer: https://lilygo.cc/en-us/products/t-hmi
3+
# Hardware reference: https://www.tinytronics.nl/en/development-boards/microcontroller-boards/with-wi-fi/lilygo-t-hmi-esp32-s3-2.8-inch-ips-tft-display-met-touchscreen
4+
# Vendor repository: https://github.com/Xinyuan-LilyGO/T-HMI
5+
6+
7+
# --- POWER HOLD ---
8+
from machine import Pin
9+
10+
Pin(10, Pin.OUT, value=1)
11+
Pin(14, Pin.OUT, value=1)
12+
13+
import lcd_bus
14+
import machine
15+
from drivers.indev.xpt2046 import XPT2046
16+
17+
import mpos.ui
18+
19+
import lvgl as lv
20+
21+
from machine import Pin
22+
from micropython import const
23+
from mpos import BatteryManager
24+
25+
# display settings
26+
_WIDTH = const(240)
27+
_HEIGHT = const(320)
28+
_BL = const(38)
29+
_RST = -1
30+
_CS = const(6)
31+
_DC = const(7)
32+
_WR = const(8)
33+
_FREQ = const(20000000)
34+
_DATA0 = const(48)
35+
_DATA1 = const(47)
36+
_DATA2 = const(39)
37+
_DATA3 = const(40)
38+
_DATA4 = const(41)
39+
_DATA5 = const(42)
40+
_DATA6 = const(45)
41+
_DATA7 = const(46)
42+
_BATTERY_PIN = const(5)
43+
44+
_TOUCH_CS = const(2)
45+
46+
_BUFFER_SIZE = const(28800)
47+
48+
display_bus = lcd_bus.I80Bus(
49+
dc=_DC,
50+
wr=_WR,
51+
cs=_CS,
52+
data0=_DATA0,
53+
data1=_DATA1,
54+
data2=_DATA2,
55+
data3=_DATA3,
56+
data4=_DATA4,
57+
data5=_DATA5,
58+
data6=_DATA6,
59+
data7=_DATA7
60+
)
61+
62+
fb1 = display_bus.allocate_framebuffer(_BUFFER_SIZE, lcd_bus.MEMORY_SPIRAM)
63+
fb2 = display_bus.allocate_framebuffer(_BUFFER_SIZE, lcd_bus.MEMORY_SPIRAM)
64+
65+
import drivers.display.st7789 as st7789
66+
67+
mpos.ui.main_display = st7789.ST7789(
68+
data_bus=display_bus,
69+
frame_buffer1=fb1,
70+
frame_buffer2=fb2,
71+
display_width=_WIDTH,
72+
display_height=_HEIGHT,
73+
backlight_pin=_BL,
74+
color_byte_order=st7789.BYTE_ORDER_RGB,
75+
rgb565_byte_swap=False,
76+
)
77+
78+
spi_bus = machine.SPI.Bus(
79+
host=2,
80+
mosi=3,
81+
miso=4,
82+
sck=1
83+
)
84+
85+
touch_dev = machine.SPI.Device(
86+
spi_bus=spi_bus,
87+
freq=const(1000000),
88+
cs=_TOUCH_CS
89+
)
90+
91+
indev = XPT2046(
92+
touch_dev,
93+
lcd_cs=_CS,
94+
touch_cs=_TOUCH_CS,
95+
display_width=_WIDTH,
96+
display_height=_HEIGHT,
97+
startup_rotation=lv.DISPLAY_ROTATION._0
98+
)
99+
100+
mpos.ui.main_display.init()
101+
mpos.ui.main_display.set_color_inversion(False)
102+
mpos.ui.main_display.set_backlight(100)
103+
mpos.ui.main_display.set_rotation(lv.DISPLAY_ROTATION._0) # must be done after initializing display and creating the touch drivers, to ensure proper handling
104+
105+
lv.init()
106+
107+
print("lilygo_t_hmi.py SDCard initialization...")
108+
109+
# Initialize SD card in SDIO mode
110+
from mpos import sdcard
111+
sdcard.init(cmd_pin=11,clk_pin=12,d0_pin=13)
112+
113+
print("lilygo_t_hmi.py Battery initialization...")
114+
115+
116+
def adc_to_voltage(raw_adc_value):
117+
"""
118+
The percentage calculation uses MIN_VOLTAGE = 3.15 and MAX_VOLTAGE = 4.15
119+
0% at 3.15V -> raw_adc_value = 210
120+
100% at 4.15V -> raw_adc_value = 310
121+
122+
4.15 - 3.15 = 1V
123+
310 - 210 = 100 raw ADC steps
124+
125+
So each raw ADC step is 1V / 100 = 0.01V
126+
Offset calculation:
127+
"""
128+
return raw_adc_value * 0.001651 + 0.08709
129+
130+
BatteryManager.init_adc(_BATTERY_PIN, adc_to_voltage)
131+
132+
print("lilygo_t_hmi.py finished")

internal_filesystem/lib/mpos/main.py

Lines changed: 73 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,75 @@ def single_address_i2c_scan(i2c_bus, address):
5353
print(f"scan error: {e}")
5454
return False
5555

56+
def detect_lilygo_t_hmi():
57+
from machine import Pin, SoftSPI
58+
import time
59+
60+
try:
61+
sck = Pin(1)
62+
mosi = Pin(3)
63+
miso = Pin(4)
64+
cs = Pin(2, Pin.OUT, value=1)
65+
irq = Pin(9, Pin.IN, Pin.PULL_UP)
66+
67+
spi = SoftSPI(
68+
baudrate=500000,
69+
polarity=0,
70+
phase=0,
71+
sck=sck,
72+
mosi=mosi,
73+
miso=miso,
74+
)
75+
76+
def read_cmd(cmd):
77+
tx = bytearray([cmd, 0x00, 0x00])
78+
rx = bytearray(3)
79+
80+
cs(0)
81+
spi.write_readinto(tx, rx)
82+
cs(1)
83+
84+
return ((rx[1] << 8) | rx[2]) >> 3
85+
86+
samples = []
87+
for _ in range(5):
88+
vals = (
89+
read_cmd(0xD0), # X
90+
read_cmd(0x90), # Y
91+
read_cmd(0xB0), # Z1
92+
irq.value(),
93+
)
94+
samples.append(vals)
95+
print("T-HMI touch sample:", vals)
96+
time.sleep_ms(20)
97+
98+
# Observed stable idle signature on LilyGO T-HMI:
99+
# X=0, Y=4095, Z1=0/1, IRQ=1
100+
signature_hits = sum(
101+
x == 0 and y == 4095 and z in (0, 1) and irqv == 1
102+
for x, y, z, irqv in samples
103+
)
104+
105+
print(f"T-HMI signature hits: {signature_hits}/5")
106+
107+
if signature_hits >= 4:
108+
print("LilyGO T-HMI touch signature matched")
109+
return True
110+
111+
except Exception as e:
112+
print(f"LilyGO T-HMI detection failed: {e}")
113+
114+
finally:
115+
try:
116+
Pin(1, Pin.IN, pull=None)
117+
Pin(2, Pin.IN, pull=None)
118+
Pin(3, Pin.IN, pull=None)
119+
Pin(4, Pin.IN, pull=None)
120+
Pin(9, Pin.IN, pull=None)
121+
except Exception:
122+
pass
123+
124+
return False
56125

57126
def fail_save_i2c(sda, scl):
58127
from machine import I2C, Pin
@@ -103,8 +172,11 @@ def detect_board():
103172
if unique_id_prefixes == b'\x30\xae\xa4':
104173
return "odroid_go"
105174

106-
# Do I2C-based board detection
175+
print("lilygo_t_hmi ?")
176+
if detect_lilygo_t_hmi():
177+
return "lilygo_t_hmi"
107178

179+
# Do I2C-based board detection
108180
print("lilygo_t_watch_s3_plus ?")
109181
if i2c0 := fail_save_i2c(sda=10, scl=11):
110182
if single_address_i2c_scan(i2c0, 0x19): # IMU on 0x19, vibrator on 0x5A and scan also shows: [52, 81]

scripts/build_mpos.sh

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,4 @@ PY
219219
rm "$stream_wav_file".backup
220220
else
221221
echo "invalid target $target"
222-
fi
223-
224-
222+
fi

0 commit comments

Comments
 (0)