@@ -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