Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
132 changes: 132 additions & 0 deletions internal_filesystem/lib/mpos/board/lilygo_t_hmi.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
print("lilygo_t_hmi.py initialization")
# Manufacturer: https://lilygo.cc/en-us/products/t-hmi
# 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
# Vendor repository: https://github.com/Xinyuan-LilyGO/T-HMI


# --- POWER HOLD ---
from machine import Pin

Pin(10, Pin.OUT, value=1)
Pin(14, Pin.OUT, value=1)

import lcd_bus
import machine
from drivers.indev.xpt2046 import XPT2046

import mpos.ui

import lvgl as lv

from machine import Pin
from micropython import const
from mpos import BatteryManager

# display settings
_WIDTH = const(240)
_HEIGHT = const(320)
_BL = const(38)
_RST = -1
_CS = const(6)
_DC = const(7)
_WR = const(8)
_FREQ = const(20000000)
_DATA0 = const(48)
_DATA1 = const(47)
_DATA2 = const(39)
_DATA3 = const(40)
_DATA4 = const(41)
_DATA5 = const(42)
_DATA6 = const(45)
_DATA7 = const(46)
_BATTERY_PIN = const(5)

_TOUCH_CS = const(2)

_BUFFER_SIZE = const(28800)

display_bus = lcd_bus.I80Bus(
dc=_DC,
wr=_WR,
cs=_CS,
data0=_DATA0,
data1=_DATA1,
data2=_DATA2,
data3=_DATA3,
data4=_DATA4,
data5=_DATA5,
data6=_DATA6,
data7=_DATA7
)

fb1 = display_bus.allocate_framebuffer(_BUFFER_SIZE, lcd_bus.MEMORY_SPIRAM)
fb2 = display_bus.allocate_framebuffer(_BUFFER_SIZE, lcd_bus.MEMORY_SPIRAM)

import drivers.display.st7789 as st7789

mpos.ui.main_display = st7789.ST7789(
data_bus=display_bus,
frame_buffer1=fb1,
frame_buffer2=fb2,
display_width=_WIDTH,
display_height=_HEIGHT,
backlight_pin=_BL,
color_byte_order=st7789.BYTE_ORDER_RGB,
rgb565_byte_swap=False,
)

spi_bus = machine.SPI.Bus(
host=2,
mosi=3,
miso=4,
sck=1
)

touch_dev = machine.SPI.Device(
spi_bus=spi_bus,
freq=const(1000000),
cs=_TOUCH_CS
)

indev = XPT2046(
touch_dev,
lcd_cs=_CS,
touch_cs=_TOUCH_CS,
display_width=_WIDTH,
display_height=_HEIGHT,
startup_rotation=lv.DISPLAY_ROTATION._0
)

mpos.ui.main_display.init()
mpos.ui.main_display.set_color_inversion(False)
mpos.ui.main_display.set_backlight(100)
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

lv.init()

print("lilygo_t_hmi.py SDCard initialization...")

# Initialize SD card in SDIO mode
from mpos import sdcard
sdcard.init(cmd_pin=11,clk_pin=12,d0_pin=13)

print("lilygo_t_hmi.py Battery initialization...")


def adc_to_voltage(raw_adc_value):
"""
The percentage calculation uses MIN_VOLTAGE = 3.15 and MAX_VOLTAGE = 4.15
0% at 3.15V -> raw_adc_value = 210
100% at 4.15V -> raw_adc_value = 310

4.15 - 3.15 = 1V
310 - 210 = 100 raw ADC steps

So each raw ADC step is 1V / 100 = 0.01V
Offset calculation:
"""
return raw_adc_value * 0.001651 + 0.08709

BatteryManager.init_adc(_BATTERY_PIN, adc_to_voltage)

print("lilygo_t_hmi.py finished")
74 changes: 73 additions & 1 deletion internal_filesystem/lib/mpos/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,75 @@ def single_address_i2c_scan(i2c_bus, address):
print(f"scan error: {e}")
return False

def detect_lilygo_t_hmi():
from machine import Pin, SoftSPI
import time

try:
sck = Pin(1)
mosi = Pin(3)
miso = Pin(4)
cs = Pin(2, Pin.OUT, value=1)
irq = Pin(9, Pin.IN, Pin.PULL_UP)

spi = SoftSPI(
baudrate=500000,
polarity=0,
phase=0,
sck=sck,
mosi=mosi,
miso=miso,
)

def read_cmd(cmd):
tx = bytearray([cmd, 0x00, 0x00])
rx = bytearray(3)

cs(0)
spi.write_readinto(tx, rx)
cs(1)

return ((rx[1] << 8) | rx[2]) >> 3

samples = []
for _ in range(5):
vals = (
read_cmd(0xD0), # X
read_cmd(0x90), # Y
read_cmd(0xB0), # Z1
irq.value(),
)
samples.append(vals)
print("T-HMI touch sample:", vals)
time.sleep_ms(20)

# Observed stable idle signature on LilyGO T-HMI:
# X=0, Y=4095, Z1=0/1, IRQ=1
signature_hits = sum(
x == 0 and y == 4095 and z in (0, 1) and irqv == 1
for x, y, z, irqv in samples
)

print(f"T-HMI signature hits: {signature_hits}/5")

if signature_hits >= 4:
print("LilyGO T-HMI touch signature matched")
return True

except Exception as e:
print(f"LilyGO T-HMI detection failed: {e}")

finally:
try:
Pin(1, Pin.IN, pull=None)
Pin(2, Pin.IN, pull=None)
Pin(3, Pin.IN, pull=None)
Pin(4, Pin.IN, pull=None)
Pin(9, Pin.IN, pull=None)
except Exception:
pass

return False

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

# Do I2C-based board detection
print("lilygo_t_hmi ?")
if detect_lilygo_t_hmi():
return "lilygo_t_hmi"

# Do I2C-based board detection
print("lilygo_t_watch_s3_plus ?")
if i2c0 := fail_save_i2c(sda=10, scl=11):
if single_address_i2c_scan(i2c0, 0x19): # IMU on 0x19, vibrator on 0x5A and scan also shows: [52, 81]
Expand Down
9 changes: 4 additions & 5 deletions scripts/build_mpos.sh
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ echo "Refreshing freezefs..."
if [ "$target" == "esp32" -o "$target" == "esp32s3" -o "$target" == "unphone" ]; then
partition_size="4194304"
flash_size="16"
otasupport="--ota"
extra_configs=""
if [ "$target" == "esp32" ]; then
BOARD=ESP32_GENERIC
Expand All @@ -117,6 +118,7 @@ if [ "$target" == "esp32" -o "$target" == "esp32s3" -o "$target" == "unphone" ];
if [ "$target" == "unphone" ]; then
partition_size="3900000"
flash_size="8"
otasupport="" # too small for 2 OTA partitions + internal storage
fi
BOARD=ESP32_GENERIC_S3
BOARD_VARIANT=SPIRAM_OCT
Expand Down Expand Up @@ -146,8 +148,7 @@ if [ "$target" == "esp32" -o "$target" == "esp32s3" -o "$target" == "unphone" ];
# CONFIG_FREERTOS_GENERATE_RUN_TIME_STATS=y
# CONFIG_ADC_MIC_TASK_CORE=1 because with the default (-1) it hangs the CPU
# CONFIG_SPIRAM_XIP_FROM_PSRAM: load entire firmware into RAM to reduce SD vs PSRAM contention (recommended at https://github.com/MicroPythonOS/MicroPythonOS/issues/17)
# python3 make.py --ota --partition-size=$partition_size --flash-size=$flash_size esp32 BOARD=$BOARD BOARD_VARIANT=$BOARD_VARIANT \
python3 make.py --optimize-size --partition-size=$partition_size --flash-size=$flash_size esp32 BOARD=$BOARD BOARD_VARIANT=$BOARD_VARIANT \
python3 make.py "$otasupport" --optimize-size --partition-size=$partition_size --flash-size=$flash_size esp32 BOARD=$BOARD BOARD_VARIANT=$BOARD_VARIANT \
USER_C_MODULE="$codebasedir"/micropython-camera-API/src/micropython.cmake \
USER_C_MODULE="$codebasedir"/secp256k1-embedded-ecdh/micropython.cmake \
USER_C_MODULE="$codebasedir"/c_mpos/micropython.cmake \
Expand Down Expand Up @@ -218,6 +219,4 @@ PY
rm "$stream_wav_file".backup
else
echo "invalid target $target"
fi


fi
Loading