@@ -55,14 +55,8 @@ def __init__(
55
55
txMode , txAlt = self .savePinModeAlt (self .tx )
56
56
clkMode , clkAlt = self .savePinModeAlt (self .clk )
57
57
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 )
66
60
67
61
# The tx and clk pins just got their mode and alt set for PIO0 or PIO1,
68
62
# so we need to save them again to restore later when _write() is called
@@ -73,11 +67,34 @@ def __init__(
73
67
self .tx .init (mode = txMode , alt = txAlt )
74
68
self .clk .init (mode = clkMode , alt = clkAlt )
75
69
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
78
95
req_num = ((self .sm_id // 4 ) << 3 ) + (self .sm_id % 4 )
79
96
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
81
98
inc_write = False ,
82
99
treq_sel = req_num
83
100
)
@@ -86,9 +103,6 @@ def __init__(
86
103
ctrl = dma_ctrl
87
104
)
88
105
89
- # Call the parent class constructor
90
- super ().__init__ (width , height , rotation , color_order , reverse_bytes_in_word )
91
-
92
106
def _write (self , command = None , data = None ):
93
107
"""SPI write to the device: commands and data."""
94
108
# 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):
121
135
122
136
def _pio_write (self , data ):
123
137
"""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
129
139
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 )
133
145
self .dma .active (True )
134
146
while self .dma .active ():
135
147
pass
@@ -141,8 +153,7 @@ def _pio_write(self, data):
141
153
out_init = rp2 .PIO .OUT_LOW ,
142
154
sideset_init = rp2 .PIO .OUT_LOW ,
143
155
out_shiftdir = rp2 .PIO .SHIFT_LEFT ,
144
- autopull = True ,
145
- pull_thresh = 8 ,
156
+ autopull = True
146
157
)
147
158
def _pio_write_spi ():
148
159
out (pins , 1 ).side (0 )
0 commit comments