Skip to content
Merged
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
26 changes: 26 additions & 0 deletions internal_filesystem/lib/drivers/display/hx8357d/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import sys
from . import hx8357d
from . import _hx8357d_init

# Register _hx8357d_init in sys.modules so __import__('_hx8357d_init') can find it
# This is needed because display_driver_framework.py uses __import__('_hx8357d_init')
# expecting a top-level module, but _hx8357d_init is in the hx8357d package subdirectory
sys.modules['_hx8357d_init'] = _hx8357d_init

# Explicitly define __all__ and re-export public symbols from hx8357d module
__all__ = [
'HX8357D',
'STATE_HIGH',
'STATE_LOW',
'STATE_PWM',
'BYTE_ORDER_RGB',
'BYTE_ORDER_BGR',
]

# Re-export the public symbols
HX8357D = hx8357d.HX8357D
STATE_HIGH = hx8357d.STATE_HIGH
STATE_LOW = hx8357d.STATE_LOW
STATE_PWM = hx8357d.STATE_PWM
BYTE_ORDER_RGB = hx8357d.BYTE_ORDER_RGB
BYTE_ORDER_BGR = hx8357d.BYTE_ORDER_BGR
93 changes: 93 additions & 0 deletions internal_filesystem/lib/drivers/display/hx8357d/_hx8357d_init.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
# Copyright (c) 2024 - 2025 Kevin G. Schlosser

import time
from micropython import const # NOQA

import lvgl as lv # NOQA
import lcd_bus # NOQA


_SWRESET = const(0x01)
_SLPOUT = const(0x11)
_DISPON = const(0x29)
_COLMOD = const(0x3A)
_MADCTL = const(0x36)
_TEON = const(0x35)
_TEARLINE = const(0x44)
_SETOSC = const(0xB0)
_SETPWR1 = const(0xB1)
_SETRGB = const(0xB3)
_SETCOM = const(0xB6)
_SETCYC = const(0xB4)
_SETC = const(0xB9)
_SETSTBA = const(0xC0)
_SETPANEL = const(0xCC)
_SETGAMMA = const(0xE0)


def init(self):
param_buf = bytearray(34)
param_mv = memoryview(param_buf)

time.sleep_ms(300) # NOQA
param_buf[:3] = bytearray([0xFF, 0x83, 0x57])
self.set_params(_SETC, param_mv[:3])

param_buf[0] = 0x80
self.set_params(_SETRGB, param_mv[:1])

param_buf[:4] = bytearray([0x00, 0x06, 0x06, 0x25])
self.set_params(_SETCOM, param_mv[:4])

param_buf[0] = 0x68
self.set_params(_SETOSC, param_mv[:1])

param_buf[0] = 0x05
self.set_params(_SETPANEL, param_mv[:1])

param_buf[:6] = bytearray([0x00, 0x15, 0x1C, 0x1C, 0x83, 0xAA])
self.set_params(_SETPWR1, param_mv[:6])

param_buf[:6] = bytearray([0x50, 0x50, 0x01, 0x3C, 0x1E, 0x08])
self.set_params(_SETSTBA, param_mv[:6])

param_buf[:7] = bytearray([0x02, 0x40, 0x00, 0x2A, 0x2A, 0x0D, 0x78])
self.set_params(_SETCYC, param_mv[:7])

param_buf[:34] = bytearray([
0x02, 0x0A, 0x11, 0x1d, 0x23, 0x35, 0x41, 0x4b, 0x4b, 0x42, 0x3A,
0x27, 0x1B, 0x08, 0x09, 0x03, 0x02, 0x0A, 0x11, 0x1d, 0x23, 0x35,
0x41, 0x4b, 0x4b, 0x42, 0x3A, 0x27, 0x1B, 0x08, 0x09, 0x03, 0x00, 0x01])
self.set_params(_SETGAMMA, param_mv[:34])

param_buf[0] = (
self._madctl(
self._color_byte_order,
self._ORIENTATION_TABLE # NOQA
)
)
self.set_params(_MADCTL, param_mv[:1])

color_size = lv.color_format_get_size(self._color_space)
if color_size == 2: # NOQA
pixel_format = 0x55
else:
raise RuntimeError(
f'{self.__class__.__name__} IC only supports '
'lv.COLOR_FORMAT.RGB565'
)

param_buf[0] = pixel_format
self.set_params(_COLMOD, param_mv[:1])

param_buf[0] = 0x00
self.set_params(_TEON, param_mv[:1])

param_buf[:2] = bytearray([0x00, 0x02])
self.set_params(_TEARLINE, param_mv[:2])

time.sleep_ms(150) # NOQA
self.set_params(_SLPOUT)

time.sleep_ms(50) # NOQA
self.set_params(_DISPON)
15 changes: 15 additions & 0 deletions internal_filesystem/lib/drivers/display/hx8357d/hx8357d.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Copyright (c) 2024 - 2025 Kevin G. Schlosser

import display_driver_framework


STATE_HIGH = display_driver_framework.STATE_HIGH
STATE_LOW = display_driver_framework.STATE_LOW
STATE_PWM = display_driver_framework.STATE_PWM

BYTE_ORDER_RGB = display_driver_framework.BYTE_ORDER_RGB
BYTE_ORDER_BGR = display_driver_framework.BYTE_ORDER_BGR


class HX8357D(display_driver_framework.DisplayDriver):
pass
127 changes: 127 additions & 0 deletions internal_filesystem/lib/drivers/indev/xpt2046.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
# Copyright (c) 2024 - 2025 Kevin G. Schlosser

import lvgl as lv # NOQA
from micropython import const # NOQA
import micropython # NOQA
import machine # NOQA
import pointer_framework
import time


_CMD_X_READ = const(0xD0) # 12 bit resolution
_CMD_Y_READ = const(0x90) # 12 bit resolution
_CMD_Z1_READ = const(0xB0)
_CMD_Z2_READ = const(0xC0)
_MIN_RAW_COORD = const(10)
_MAX_RAW_COORD = const(4090)


class XPT2046(pointer_framework.PointerDriver):
touch_threshold = 400
confidence = 5
margin = 50

def __init__(
self,
device: machine.SPI.Bus,
display_width: int,
display_height: int,
lcd_cs: int,
touch_cs: int,
touch_cal=None,
startup_rotation=lv.DISPLAY_ROTATION._0,
debug=False,
):
self._device = device # machine.SPI.Bus() instance, shared with display
self._debug = debug

self.lcd_cs = machine.Pin(lcd_cs, machine.Pin.OUT, value=0)
self.touch_cs = machine.Pin(touch_cs, machine.Pin.OUT, value=1)

self._width = display_width
self._height = display_height

self._tx_buf = bytearray(3)
self._tx_mv = memoryview(self._tx_buf)

self._rx_buf = bytearray(3)
self._rx_mv = memoryview(self._rx_buf)

self.__confidence = max(min(self.confidence, 25), 3)
self.__points = [[0, 0] for _ in range(self.__confidence)]

margin = max(min(self.margin, 100), 1)
self.__margin = margin * margin

super().__init__(
touch_cal=touch_cal, startup_rotation=startup_rotation, debug=debug
)

def _read_reg(self, reg, num_bytes):
self._tx_buf[0] = reg
self._device.write_readinto(self._tx_mv[:num_bytes], self._rx_mv[:num_bytes])
return ((self._rx_buf[1] << 8) | self._rx_buf[2]) >> 3

def _get_coords(self):
try:
self.lcd_cs.value(1) # deselect LCD to avoid conflicts
self.touch_cs.value(0) # select touch chip

z1 = self._read_reg(_CMD_Z1_READ, 3)
z2 = self._read_reg(_CMD_Z2_READ, 3)
z = z1 + ((_MAX_RAW_COORD + 6) - z2)
if z < self.touch_threshold:
return None # Not touched

points = self.__points
count = 0
end_time = time.ticks_us() + 5000
while time.ticks_us() < end_time:
if count == self.__confidence:
break

raw_x = self._read_reg(_CMD_X_READ, 3)
if raw_x < _MIN_RAW_COORD:
continue

raw_y = self._read_reg(_CMD_Y_READ, 3)
if raw_y > _MAX_RAW_COORD:
continue

# put in buff
points[count][0] = raw_x
points[count][1] = raw_y
count += 1

finally:
self.touch_cs.value(1) # deselect touch chip
self.lcd_cs.value(0) # select LCD

if not count:
return None # Not touched

meanx = sum([points[i][0] for i in range(count)]) // count
meany = sum([points[i][1] for i in range(count)]) // count
dev = (
sum(
[
(points[i][0] - meanx) ** 2 + (points[i][1] - meany) ** 2
for i in range(count)
]
)
/ count
)
if dev >= self.__margin:
return None # Not touched

x = pointer_framework.remap(
meanx, _MIN_RAW_COORD, _MAX_RAW_COORD, 0, self._orig_width
)
y = pointer_framework.remap(
meany, _MIN_RAW_COORD, _MAX_RAW_COORD, 0, self._orig_height
)
if self._debug:
print(
f"{self.__class__.__name__}_TP_DATA({count=} {meanx=} {meany=} {z1=} {z2=} {z=})"
) # NOQA
return self.PRESSED, x, y
Loading
Loading