Skip to content

Commit e1dd199

Browse files
committed
Change HM01B0 PIO driver to use 32-bit transfers after initialization
This now operates at the theoretical best rate of 16.4ms
1 parent 6150a9e commit e1dd199

File tree

1 file changed

+35
-24
lines changed

1 file changed

+35
-24
lines changed

cv2_drivers/displays/st7789_pio.py

Lines changed: 35 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -55,14 +55,8 @@ def __init__(
5555
txMode, txAlt = self.savePinModeAlt(self.tx)
5656
clkMode, clkAlt = self.savePinModeAlt(self.clk)
5757

58-
# Initialize the PIO state machine
59-
self.sm = rp2.StateMachine(
60-
self.sm_id,
61-
self._pio_write_spi,
62-
freq = self.freq,
63-
out_base = self.tx,
64-
sideset_base = self.clk,
65-
)
58+
# Start the PIO state machine and DMA with 1 bytes per transfer
59+
self._setup_sm_and_dma(1)
6660

6761
# The tx and clk pins just got their mode and alt set for PIO0 or PIO1,
6862
# so we need to save them again to restore later when _write() is called
@@ -73,11 +67,34 @@ def __init__(
7367
self.tx.init(mode=txMode, alt=txAlt)
7468
self.clk.init(mode=clkMode, alt=clkAlt)
7569

76-
# Set up DMA to transfer to the PIO state machine
77-
self.dma = rp2.DMA()
70+
# Call the parent class constructor
71+
super().__init__(width, height, rotation, color_order, reverse_bytes_in_word)
72+
73+
# Change the transfer size to 4 bytes for faster throughput
74+
self._setup_sm_and_dma(4)
75+
76+
def _setup_sm_and_dma(self, bytes_per_transfer):
77+
# Store the bytes per transfer for later use
78+
self.bytes_per_transfer = bytes_per_transfer
79+
80+
# Initialize the PIO state machine
81+
self.sm = rp2.StateMachine(
82+
self.sm_id,
83+
self._pio_write_spi,
84+
freq = self.freq,
85+
out_base = self.tx,
86+
sideset_base = self.clk,
87+
pull_thresh = bytes_per_transfer * 8
88+
)
89+
90+
# Instantiate a DMA controller if not already done
91+
if not hasattr(self, 'dma'):
92+
self.dma = rp2.DMA()
93+
94+
# Configure up DMA to write to the PIO state machine
7895
req_num = ((self.sm_id // 4) << 3) + (self.sm_id % 4)
7996
dma_ctrl = self.dma.pack_ctrl(
80-
size = 0, # 0 = 8-bit, 1 = 16-bit, 2 = 32-bit
97+
size = {1:0, 2:1, 4:2}[bytes_per_transfer], # 0 = 8-bit, 1 = 16-bit, 2 = 32-bit
8198
inc_write = False,
8299
treq_sel = req_num
83100
)
@@ -86,9 +103,6 @@ def __init__(
86103
ctrl = dma_ctrl
87104
)
88105

89-
# Call the parent class constructor
90-
super().__init__(width, height, rotation, color_order, reverse_bytes_in_word)
91-
92106
def _write(self, command=None, data=None):
93107
"""SPI write to the device: commands and data."""
94108
# Save the current mode and alt of the spi pins in case they're used by
@@ -121,15 +135,13 @@ def _write(self, command=None, data=None):
121135

122136
def _pio_write(self, data):
123137
"""Write data to the display using PIO."""
124-
# Start the state machine
125-
self.sm.active(1)
126-
127-
# Configure DMA to read from the buffer and write to the state machine
128-
self.dma.read = data
138+
# Configure the DMA transfer count and read address
129139
count = len(data) if isinstance(data, (bytes, bytearray)) else data.size
130-
self.dma.count = count
131-
132-
# Start the DMA transfer and wait for it to finish
140+
self.dma.count = count // self.bytes_per_transfer
141+
self.dma.read = data
142+
143+
# Start the state machine and DMA transfer, and wait for it to finish
144+
self.sm.active(1)
133145
self.dma.active(True)
134146
while self.dma.active():
135147
pass
@@ -141,8 +153,7 @@ def _pio_write(self, data):
141153
out_init = rp2.PIO.OUT_LOW,
142154
sideset_init = rp2.PIO.OUT_LOW,
143155
out_shiftdir = rp2.PIO.SHIFT_LEFT,
144-
autopull = True,
145-
pull_thresh = 8,
156+
autopull = True
146157
)
147158
def _pio_write_spi():
148159
out(pins, 1).side(0)

0 commit comments

Comments
 (0)