Skip to content

Commit ba50266

Browse files
committed
WIP: Support SQUiXL device by "Unexpected Maker"
1 parent 0011a39 commit ba50266

7 files changed

Lines changed: 901 additions & 79 deletions

File tree

internal_filesystem/lib/drivers/__init__.py

Whitespace-only changes.
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
from micropython import const # NOQA
2+
import display_driver_framework
3+
import lvgl as lv
4+
5+
# Annahme: Es gibt ein lca9555-Modul für den IO-Expander
6+
try:
7+
import lca9555
8+
except ImportError:
9+
lca9555 = None # Platzhalter für Tests
10+
11+
12+
from drivers.display.st7789.st7789 import ST7789
13+
from drivers.io_expander.tca9555 import TCA9555
14+
15+
16+
class ST7701S(ST7789):
17+
def __init__(
18+
self,
19+
data_bus,
20+
display_width,
21+
display_height,
22+
ioex: TCA9555,
23+
frame_buffer1=None,
24+
frame_buffer2=None,
25+
reset_pin=None,
26+
reset_state=display_driver_framework.STATE_HIGH,
27+
power_pin=None,
28+
power_on_state=display_driver_framework.STATE_HIGH,
29+
backlight_pin=None,
30+
backlight_on_state=display_driver_framework.STATE_HIGH,
31+
offset_x=0,
32+
offset_y=0,
33+
color_byte_order=display_driver_framework.BYTE_ORDER_RGB,
34+
color_space=lv.COLOR_FORMAT.RGB888, # NOQA
35+
):
36+
self.ioex = ioex
37+
38+
super().__init__(
39+
data_bus=data_bus,
40+
display_width=display_width,
41+
display_height=display_height,
42+
frame_buffer1=frame_buffer1,
43+
frame_buffer2=frame_buffer2,
44+
reset_pin=reset_pin,
45+
reset_state=reset_state,
46+
power_pin=power_pin,
47+
power_on_state=power_on_state,
48+
backlight_pin=backlight_pin,
49+
backlight_on_state=backlight_on_state,
50+
offset_x=offset_x,
51+
offset_y=offset_y,
52+
color_byte_order=color_byte_order,
53+
color_space=color_space,
54+
rgb565_byte_swap=False,
55+
)
56+
57+
def _set_tca9555_pin(self, name, value):
58+
if self.ioex and name in self.tca9555_pins:
59+
self.ioex.digital_write(self.tca9555_pins[name], value)
60+
61+
def hardware_reset(self):
62+
# Reset-Sequenz über TCA9555
63+
self._set_tca9555_pin("reset", 0)
64+
display_driver_framework.sleep_ms(20)
65+
self._set_tca9555_pin("reset", 1)
66+
display_driver_framework.sleep_ms(120)
67+
68+
def send_init_sequence(self, sequence):
69+
# Sende Initialisierungssequenz über SPI-Emulation via TCA9555
70+
for cmd, data in sequence:
71+
self._set_tca9555_pin("cs", 0)
72+
self._spi_write(cmd, is_cmd=True)
73+
if data:
74+
for d in data:
75+
self._spi_write(d, is_cmd=False)
76+
self._set_tca9555_pin("cs", 1)
77+
78+
def _spi_write(self, value, is_cmd):
79+
# Schreibe ein Byte über TCA9555 (Bit-Banging)
80+
self._set_tca9555_pin("clk", 0)
81+
self._set_tca9555_pin("mosi", 0 if is_cmd else 1) # Annahme: DC über MOSI
82+
for i in range(8):
83+
bit = (value >> (7 - i)) & 1
84+
self._set_tca9555_pin("mosi", bit)
85+
self._set_tca9555_pin("clk", 1)
86+
self._set_tca9555_pin("clk", 0)
87+
88+
def init_display(self):
89+
self.hardware_reset()
90+
# Beispiel-Init-Sequenz, muss ggf. angepasst werden
91+
init_seq = [
92+
(0x11, None), # Sleep Out
93+
(0x29, None), # Display On
94+
]
95+
self.send_init_sequence(init_seq)
96+
# Danach übernimmt der RGB-Bus die Pixelübertragung

internal_filesystem/lib/drivers/io_expander/__init__.py

Whitespace-only changes.
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
import struct
2+
import sys
3+
import time
4+
5+
import esp32
6+
import i2c
7+
import lcd_bus
8+
import lvgl as lv
9+
import machine
10+
import mpos.ui
11+
from drivers.display.hx8357d import hx8357d
12+
from drivers.indev.xpt2046 import XPT2046
13+
from machine import Pin
14+
from micropython import const
15+
from mpos import InputManager
16+
17+
18+
class TCA9555:
19+
"""
20+
TCA9555 IO expansion chip
21+
The LCA9555 is register-compatible with the TCA9555
22+
"""
23+
24+
I2C_DEV_ID = const(38) # 0x26 - TI TCA9555's I²C addr
25+
26+
# Register addresses
27+
REG_INPUT = const(0x00)
28+
REG_OUTPUT = const(0x02)
29+
REG_CONFIG = const(0x06)
30+
31+
def __init__(self, i2c_bus: i2c.I2C.Bus, dev_id:int):
32+
self.tca_dev = i2c.I2C.Device(bus=i2c_bus, dev_id=dev_id)
33+
self.directions = 0xFFFF # All inputs by default
34+
self.output_states = 0x0000 # All low by default
35+
36+
# Set IO expander initially as all inputs
37+
self._write_word(0x06, self.directions)
38+
39+
# Read current directions and states
40+
self.directions = self._read_word(0x06)
41+
self.output_states = self._read_word(0x02)
42+
43+
def _write_word(self, reg, value):
44+
print(f"Writing to TCA9555: reg={reg:#02x}, value={value:#04x}")
45+
self.tca_dev.write(bytes([reg, value & 0xFF, (value >> 8) & 0xFF]))
46+
47+
def _read_word(self, reg):
48+
self.tca_dev.write(bytes([reg]))
49+
data = self.tca_dev.read(2)
50+
return struct.unpack("<H", data)[0]
51+
52+
def pin_mode(self, pin, mode):
53+
if pin & 0x40: # Pins with 0x40 bit set are controlled by TCA9555
54+
pin &= 0xBF # Mask out high bit
55+
if mode == machine.Pin.OUT:
56+
self.directions &= ~(1 << pin)
57+
else:
58+
self.directions |= 1 << pin
59+
self._write_word(self.REG_OUTPUT, self.directions)
60+
else:
61+
# Handle standard ESP32 pin
62+
machine.Pin(pin, mode)
63+
64+
def digital_write(self, pin, value):
65+
if pin & 0x40: # Pins with 0x40 bit set are controlled by TCA9555
66+
pin &= 0xBF
67+
if value:
68+
self.output_states |= 1 << pin
69+
else:
70+
self.output_states &= ~(1 << pin)
71+
self._write_word(self.REG_OUTPUT, self.output_states)
72+
73+
# Ensure pin is set to output
74+
self.directions &= ~(1 << pin)
75+
self._write_word(self.REG_CONFIG, self.directions)
76+
else:
77+
# Handle standard ESP32 pin
78+
p = machine.Pin(pin, machine.Pin.OUT)
79+
p.value(value)
80+
81+
def digital_read(self, pin):
82+
if pin & 0x40: # Pins with 0x40 bit set are controlled by TCA9555
83+
pin &= 0xBF
84+
# Ensure pin is set to input
85+
self.directions |= 1 << pin
86+
self._write_word(self.REG_CONFIG, self.directions)
87+
88+
inputs = self._read_word(self.REG_INPUT)
89+
return 1 if (inputs & (1 << pin)) else 0
90+
else:
91+
# Handle standard ESP32 pin
92+
p = machine.Pin(pin, machine.Pin.IN)
93+
return p.value()

0 commit comments

Comments
 (0)