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

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

# Explicitly define __all__ and re-export public symbols from st7701s module
__all__ = [
'ST7701S',
]

# Re-export the public symbols
ST7701S = st7701s.ST7701S
89 changes: 89 additions & 0 deletions internal_filesystem/lib/drivers/display/st7701s/_st7701s_init.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
# ST7701S initialization

import time
from micropython import const

_SWRESET = const(0x01)
_SLPOUT = const(0x11)
_DISPON = const(0x29)
_MADCTL = const(0x36)
_COLMOD = const(0x3A)
_LCD_DELAY = const(0xFF)
_CASET = const(0x2A)
_RASET = const(0x2B)
_INVOFF = const(0x20)
_INVON = const(0x21)


def init(self):
print("_st7701s_init.py Send initialization commands to ST7701S...")

# ST7701S init sequence
seq = [
# (cmd, data) or (None, ms) for delay
(_SWRESET, None),
(None, 150),
(_SLPOUT, None),
(None, 100),
(0xFF, [0x77, 0x01, 0x00, 0x00, 0x10]),
(0xC0, [0x3B, 0x00]),
(0xC1, [0x0D, 0x02]),
(0xC2, [0x21, 0x08]),
(0xCD, [0x08]),
(0xB0, [0x00, 0x11, 0x18, 0x0E, 0x11, 0x06, 0x07, 0x08, 0x07, 0x22, 0x04, 0x12, 0x0F, 0xAA, 0x31, 0x18]),
(0xB1, [0x00, 0x11, 0x19, 0x0E, 0x12, 0x07, 0x08, 0x08, 0x08, 0x22, 0x04, 0x11, 0x11, 0xA9, 0x32, 0x18]),
(0xFF, [0x77, 0x01, 0x00, 0x00, 0x11]),
(0xB0, [0x60]),
(0xB1, [0x30]),
(0xB2, [0x87]),
(0xB3, [0x80]),
(0xB5, [0x49]),
(0xB7, [0x85]),
(0xB8, [0x21]),
(0xC1, [0x78]),
(0xC2, [0x78]),
(None, 20),
(0xE0, [0x00, 0x1B, 0x02]),
(0xE1, [0x08, 0xA0, 0x00, 0x00, 0x07, 0xA0, 0x00, 0x00, 0x00, 0x44, 0x44]),
(0xE2, [0x11, 0x11, 0x44, 0x44, 0xA0, 0x00, 0x00, 0xEC, 0xA0, 0x00, 0x00]),
(0xE3, [0x00, 0x00, 0x11, 0x11]),
(0xE4, [0x44, 0x44]),
(0xE5, [0x0A, 0xE9, 0xD8, 0xA0, 0x0C, 0xEB, 0xD8, 0xA0, 0x0E, 0xED, 0xD8, 0xA0, 0x10, 0xEF, 0xD8, 0xA0]),
(0xE6, [0x00, 0x00, 0x11, 0x11]),
(0xE7, [0x44, 0x44]),
(0xE8, [0x09, 0xE8, 0xD8, 0xA0, 0x0B, 0xEA, 0xD8, 0xA0, 0x0D, 0xEC, 0xD8, 0xA0, 0x0F, 0xEE, 0xD8, 0xA0]),
(0xEB, [0x02, 0x00, 0xE4, 0xE4, 0x88, 0x00, 0x40]),
(0xEC, [0x3C, 0x00]),
(0xED, [0xAB, 0x89, 0x76, 0x54, 0x02, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x20, 0x45, 0x67, 0x98, 0xBA]),
(0xFF, [0x77, 0x01, 0x00, 0x00, 0x00]),
(_MADCTL, [0x00]),
(_COLMOD, [0x66]),
(0x21, None),
(None, 120),
(None, 120),
# Column address set (CASET):
(_CASET, [0x00, 0x00, (self.display_width >> 8) & 0xFF, self.display_width & 0xFF]),
# Page address set (RASET):
(_RASET, [0x00, 0x00, (self.display_height >> 8) & 0xFF, self.display_height & 0xFF]),
(_DISPON, None),
(None, 120),
(_INVOFF, None),
]

if self.set_params_func:
print("Using custom set_params_func for initialization")
set_params = self.set_params_func
else:
print("Using default set_params method for initialization")
set_params = self.set_params

for cmd, data in seq:
if cmd is None:
time.sleep_ms(data)
else:
if data is None:
set_params(cmd)
else:
set_params(cmd, bytearray(data))

print("_st7701s_init.py initialization complete")
53 changes: 53 additions & 0 deletions internal_filesystem/lib/drivers/display/st7701s/st7701s.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import lvgl as lv
import rgb_display_framework


class ST7701S(rgb_display_framework.RGBDisplayDriver):
def __init__(
self,
data_bus,
display_width,
display_height,
frame_buffer1=None,
frame_buffer2=None,
reset_pin=None,
reset_state=rgb_display_framework.STATE_HIGH,
power_pin=None,
power_on_state=rgb_display_framework.STATE_HIGH,
backlight_pin=None,
backlight_on_state=rgb_display_framework.STATE_HIGH,
offset_x=0,
offset_y=0,
color_byte_order=rgb_display_framework.BYTE_ORDER_RGB,
color_space=lv.COLOR_FORMAT.RGB888,
set_params_func=None,
):
super().__init__(
data_bus=data_bus,
display_width=display_width,
display_height=display_height,
frame_buffer1=frame_buffer1,
frame_buffer2=frame_buffer2,
reset_pin=reset_pin,
reset_state=reset_state,
power_pin=power_pin,
power_on_state=power_on_state,
backlight_pin=backlight_pin,
backlight_on_state=backlight_on_state,
offset_x=offset_x,
offset_y=offset_y,
color_byte_order=color_byte_order,
color_space=color_space,
rgb565_byte_swap=False,
)
self.set_params_func = set_params_func

mod_name = f'_st7701s_init'
mod = __import__(mod_name)
mod.init(self)

def set_params(self, cmd, params=None):
if self.set_params_func:
self.set_params_func(cmd, params)
else:
super().set_params(cmd, params)
Empty file.
81 changes: 81 additions & 0 deletions internal_filesystem/lib/drivers/io_expander/tca9555.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import struct

import i2c
import machine
from micropython import const


class TCA9555:
"""
LCA9555 / TCA9555 IO expansion chip
(LCA9555 is register-compatible with TCA9555)
"""

# Register addresses
REG_INPUT = const(0x00)
REG_OUTPUT = const(0x02)
REG_CONFIG = const(0x06)

def __init__(self, i2c_bus: i2c.I2C.Bus, dev_id: int):
self.tca_dev = i2c.I2C.Device(bus=i2c_bus, dev_id=dev_id)
self.directions = 0xFFFF # All inputs by default
self.output_states = 0x0000 # All low by default

# Set IO expander initially as all inputs
self._write_word(0x06, self.directions)

# Read current directions and states
self.directions = self._read_word(0x06)
self.output_states = self._read_word(0x02)

def _write_word(self, reg, value):
print(f"Writing to TCA9555: reg={reg:#02x}, value={value:#04x}")
self.tca_dev.write(bytes([reg, value & 0xFF, (value >> 8) & 0xFF]))

def _read_word(self, reg):
self.tca_dev.write(bytes([reg]))
data = self.tca_dev.read(2)
return struct.unpack("<H", data)[0]

def pin_mode(self, pin, mode):
if pin & 0x40: # Pins with 0x40 bit set are controlled by TCA9555
pin &= 0xBF # Mask out high bit
if mode == machine.Pin.OUT:
self.directions &= ~(1 << pin)
else:
self.directions |= 1 << pin
self._write_word(self.REG_OUTPUT, self.directions)
else:
# Handle standard ESP32 pin
machine.Pin(pin, mode)

def digital_write(self, pin, value):
if pin & 0x40: # Pins with 0x40 bit set are controlled by TCA9555
pin &= 0xBF
if value:
self.output_states |= 1 << pin
else:
self.output_states &= ~(1 << pin)
self._write_word(self.REG_OUTPUT, self.output_states)

# Ensure pin is set to output
self.directions &= ~(1 << pin)
self._write_word(self.REG_CONFIG, self.directions)
else:
# Handle standard ESP32 pin
p = machine.Pin(pin, machine.Pin.OUT)
p.value(value)

def digital_read(self, pin):
if pin & 0x40: # Pins with 0x40 bit set are controlled by TCA9555
pin &= 0xBF
# Ensure pin is set to input
self.directions |= 1 << pin
self._write_word(self.REG_CONFIG, self.directions)

inputs = self._read_word(self.REG_INPUT)
return 1 if (inputs & (1 << pin)) else 0
else:
# Handle standard ESP32 pin
p = machine.Pin(pin, machine.Pin.IN)
return p.value()
Loading
Loading