@@ -4,6 +4,7 @@ package piolib
44
55import (
66 "machine"
7+ "time"
78
89 pio "github.com/tinygo-org/pio/rp2-pio"
910)
@@ -17,6 +18,7 @@ type SPI3w struct {
1718
1819 enableStatus bool
1920 lastStatus uint32
21+ pinMask uint32
2022}
2123
2224func NewSPI3w (sm pio.StateMachine , dio , clk machine.Pin , baud uint32 ) (* SPI3w , error ) {
@@ -53,14 +55,15 @@ func NewSPI3w(sm pio.StateMachine, dio, clk machine.Pin, baud uint32) (*SPI3w, e
5355 // Initialize state machine.
5456 sm .Init (offset , cfg )
5557 pinMask := uint32 (1 << dio | 1 << clk )
56- sm .SetPindirsMasked (0 , pinMask )
58+ sm .SetPindirsMasked (pinMask , pinMask )
5759 sm .SetPinsMasked (0 , pinMask )
5860
5961 sm .SetEnabled (true )
6062
6163 spiw := & SPI3w {
62- sm : sm ,
63- offset : offset ,
64+ sm : sm ,
65+ offset : offset ,
66+ pinMask : pinMask ,
6467 }
6568 return spiw , nil
6669}
@@ -103,40 +106,46 @@ func (spi *SPI3w) read(r []uint32) error {
103106 return spi .readDMA (r )
104107 }
105108 i := 0
106- retries := timeoutRetries
107- for i < len (r ) && retries > 0 {
109+ deadline := spi . newDeadline ()
110+ for i < len (r ) {
108111 if spi .sm .IsRxFIFOEmpty () {
112+ if deadline .expired () {
113+ return errTimeout
114+ }
109115 gosched ()
110- retries --
111116 continue
112117 }
113118 r [i ] = spi .sm .RxGet ()
114119 spi .sm .TxPut (r [i ])
115120 i ++
116121 }
117- if retries <= 0 {
118- return errTimeout
119- }
122+
120123 return nil
121124}
122125
123126func (spi * SPI3w ) write (w []uint32 ) error {
124127 if spi .IsDMAEnabled () {
125128 return spi .writeDMA (w )
126129 }
130+
127131 i := 0
128- retries := timeoutRetries
129- for i < len (w ) && retries > 0 {
132+ deadline := spi . newDeadline ()
133+ for i < len (w ) {
130134 if spi .sm .IsTxFIFOFull () {
135+ if deadline .expired () {
136+ return errTimeout
137+ }
131138 gosched ()
132- retries --
133139 continue
134140 }
135141 spi .sm .TxPut (w [i ])
136142 i ++
137143 }
138- if retries <= 0 {
139- return errTimeout
144+ for ! spi .sm .IsTxFIFOEmpty () {
145+ if deadline .expired () {
146+ return errTimeout
147+ }
148+ gosched ()
140149 }
141150 return nil
142151}
@@ -151,6 +160,15 @@ func (spi *SPI3w) EnableStatus(enabled bool) {
151160 spi .enableStatus = enabled
152161}
153162
163+ // SetTimeout sets the read/write timeout. Use 0 as argument to disable timeouts.
164+ func (spi * SPI3w ) SetTimeout (timeout time.Duration ) {
165+ spi .dma .dl .setTimeout (timeout )
166+ }
167+
168+ func (spi * SPI3w ) newDeadline () deadline {
169+ return spi .dma .dl .newDeadline ()
170+ }
171+
154172func (spi * SPI3w ) getStatus () error {
155173 var buf [1 ]uint32
156174 err := spi .read (buf [:1 ])
@@ -161,12 +179,14 @@ func (spi *SPI3w) getStatus() error {
161179 return nil
162180}
163181
182+ func (spi * SPI3w ) forcePinsLow () { spi .sm .SetPinsMasked (0 , spi .pinMask ) }
183+
164184func (spi * SPI3w ) prepTx (readbits , writebits uint32 ) {
165185 spi .sm .SetEnabled (false )
166186
167- spi .sm .ClearFIFOs ()
168- spi .sm .SetX (readbits )
169- spi .sm .SetY (writebits )
187+ // spi.sm.ClearFIFOs()
188+ spi .sm .SetX (writebits )
189+ spi .sm .SetY (readbits )
170190 spi .sm .Exec (pio .EncodeSet (pio .SrcDestPinDirs , 1 )) // Set Pindir out.
171191 spi .sm .Jmp (spi .offset + spi3wWrapTarget , pio .JmpAlways )
172192
@@ -188,6 +208,7 @@ func (spi *SPI3w) EnableDMA(enabled bool) error {
188208 if ! ok {
189209 return errDMAUnavail
190210 }
211+ channel .dl = spi .dma .dl // Copy deadline.
191212 spi .dma = channel
192213 return nil
193214}
0 commit comments