Skip to content

Commit 918cb58

Browse files
committed
Change ST7789 SPI driver to require SPI bus instead of initializing it
Improves behavior when using the same SPI bus with multiple devices, like an SD card Also modify DC pin behavior to restore previous mode/alt parameters after communicating with display, in case the pin is used by another device (eg. SPI by SD card)
1 parent 37756bb commit 918cb58

File tree

1 file changed

+57
-19
lines changed

1 file changed

+57
-19
lines changed

drivers/display/st7789_spi.py

Lines changed: 57 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -118,15 +118,11 @@ class ST7789_SPI():
118118
OpenCV SPI driver for ST7789 displays
119119
120120
Args:
121-
width (int): display width **Required**
121+
width (int): display width **Required**
122122
height (int): display height **Required**
123-
spi_id (int): SPI bus ID
124-
spi_baudrate (int): SPI baudrate, default 24MHz
125-
pin_sck (pin): SCK pin number
126-
pin_mosi (pin): MOSI pin number
127-
pin_miso (pin): MISO pin number
128-
pin_cs (pin): Chip Select pin number
129-
pin_dc (pin): Data/Command pin number
123+
spi (SPI): SPI bus **Required**
124+
pin_dc (Pin): Data/Command pin number **Required**
125+
pin_cs (Pin): Chip Select pin number
130126
rotation (int): Orientation of display
131127
- 0-Portrait, default
132128
- 1-Landscape
@@ -142,24 +138,17 @@ def __init__(
142138
self,
143139
width,
144140
height,
145-
spi_id,
146-
spi_baudrate=24000000,
147-
pin_sck=None,
148-
pin_mosi=None,
149-
pin_miso=None,
141+
spi,
142+
pin_dc,
150143
pin_cs=None,
151-
pin_dc=None,
152144
rotation=0,
153145
color_order=BGR,
154146
reverse_bytes_in_word=True,
155147
):
156148
# Store SPI arguments
157-
self.spi = SPI(spi_id, baudrate=spi_baudrate,
158-
sck=Pin(pin_sck, Pin.OUT) if pin_sck else None,
159-
mosi=Pin(pin_mosi, Pin.OUT) if pin_mosi else None,
160-
miso=Pin(pin_miso, Pin.IN) if pin_miso else None)
149+
self.spi = spi
150+
self.dc = Pin(pin_dc) # Don't change mode/alt
161151
self.cs = Pin(pin_cs, Pin.OUT, value=1) if pin_cs else None
162-
self.dc = Pin(pin_dc, Pin.OUT, value=1) if pin_dc else None
163152
# Initial dimensions and offsets; will be overridden when rotation applied
164153
self.width = width
165154
self.height = height
@@ -359,8 +348,54 @@ def clear(self):
359348
# Write the buffer to the display
360349
self._write(None, self.buffer)
361350

351+
def saveDcPin(self):
352+
"""
353+
Saves the current `mode` and `alt` of the DC pin so it can be restored
354+
later. Mostly used to restore the SPI mode (MISO) of the DC pin after
355+
communication with the display in case another device is using the same
356+
SPI bus.
357+
358+
Returns:
359+
tuple: (mode, alt)
360+
"""
361+
# There's no way to get the mode and alt of a pin directly, so we
362+
# convert the pin to a string and parse it. Example format:
363+
# "Pin(GPIO16, mode=ALT, alt=SPI)"
364+
dcStr = str(self.dc)
365+
366+
# Extract the "mode" parameter from the pin string
367+
if "mode=" in dcStr:
368+
# Split between "mode=" and the next comma or closing parenthesis
369+
modeStr = dcStr.split("mode=")[1].split(",")[0].split(")")[0]
370+
371+
# Look up the mode in Pin class dictionary
372+
mode = Pin.__dict__[modeStr]
373+
else:
374+
# No mode specified, just set to None
375+
mode = None
376+
377+
# Extrct the "alt" parameter from the pin string
378+
if "alt=" in dcStr:
379+
# Split between "alt=" and the next comma or closing parenthesis
380+
altStr = dcStr.split("alt=")[1].split(",")[0].split(")")[0]
381+
382+
# Look up the alt in Pin class dictionary (with "ALT_" prefix)
383+
alt = Pin.__dict__["ALT_" + altStr]
384+
else:
385+
# No alt specified, just set to None
386+
alt = None
387+
388+
# Return the mode and alt as a tuple
389+
return (mode, alt)
390+
362391
def _write(self, command=None, data=None):
363392
"""SPI write to the device: commands and data."""
393+
# Save the current mode and alt of the DC pin in case it's used by
394+
# another device on the same SPI bus
395+
mode, alt = self.saveDcPin()
396+
# Temporarily set the DC pin to output mode
397+
self.dc.init(mode=Pin.OUT)
398+
364399
if self.cs:
365400
self.cs.off()
366401
if command is not None:
@@ -371,3 +406,6 @@ def _write(self, command=None, data=None):
371406
self.spi.write(data)
372407
if self.cs:
373408
self.cs.on()
409+
410+
# Restore the DC pin to its original mode and alt
411+
self.dc.init(mode=mode, alt=alt)

0 commit comments

Comments
 (0)