16
16
* Author(s): Scott Shawcroft
17
17
"""
18
18
19
- import adafruit_pioasm
20
19
import array
20
+ import time
21
+
22
+ import adafruit_pioasm
21
23
import busio
22
24
import rp2pio
23
- import time
24
25
25
26
__version__ = "0.0.0+auto.0"
26
27
__repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_PIO_UART.git"
27
28
28
29
29
30
class UART :
31
+ """PIO implementation of CircuitPython UART API."""
32
+
30
33
Parity = busio .UART .Parity
31
34
32
- def __init__ (self , tx = None , rx = None , baudrate = 9600 , bits = 8 , parity = None , stop = 1 , timeout = 1 ):
35
+ def __init__ (
36
+ self , tx = None , rx = None , baudrate = 9600 , bits = 8 , parity = None , stop = 1 , timeout = 1
37
+ ): # pylint: disable=invalid-name, too-many-arguments
33
38
self .bitcount = bits + (1 if parity else 0 )
34
39
self .bits = bits
35
40
self .parity = parity
36
- self .mask = (( 1 << bits ) - 1 )
41
+ self .mask = (1 << bits ) - 1
37
42
self .shift = 8 - (self .bitcount % 8 )
38
43
self ._timeout = timeout
39
44
self .rx_pio = None
@@ -50,27 +55,26 @@ def __init__(self, tx=None, rx=None, baudrate=9600, bits=8, parity=None, stop=1,
50
55
# * Sample data
51
56
# * Each iteration is 8 cycles
52
57
rx_code = adafruit_pioasm .assemble (
53
- ".program uart_rx_mini\n " +
54
- "start:\n "
55
- " wait 0 pin 0\n " +
56
- f" set x, { self .bitcount - 1 } [10]\n " +
57
- "bitloop:\n " +
58
- " in pins, 1\n " +
59
- " jmp x-- bitloop [6]\n " +
60
- " jmp pin good_stop\n " +
61
- # Skip IRQ
62
- " wait 1 pin 0\n " +
63
- " jmp start\n " +
64
- "good_stop:\n " +
65
- " push\n "
58
+ ".program uart_rx_mini\n "
59
+ + "start:\n "
60
+ + " wait 0 pin 0\n "
61
+ + f" set x, { self .bitcount - 1 } [10]\n "
62
+ + "bitloop:\n "
63
+ + " in pins, 1\n "
64
+ + " jmp x-- bitloop [6]\n "
65
+ + " jmp pin good_stop\n "
66
+ + " wait 1 pin 0\n " # Skip IRQ
67
+ + " jmp start\n "
68
+ + "good_stop:\n "
69
+ + " push\n "
66
70
)
67
71
self .rx_pio = rp2pio .StateMachine (
68
72
rx_code ,
69
73
first_in_pin = rx ,
70
74
jmp_pin = rx ,
71
75
frequency = 8 * baudrate ,
72
76
auto_push = False ,
73
- push_threshold = self .bitcount
77
+ push_threshold = self .bitcount ,
74
78
)
75
79
76
80
self .tx_pio = None
@@ -86,13 +90,13 @@ def __init__(self, tx=None, rx=None, baudrate=9600, bits=8, parity=None, stop=1,
86
90
# * Shift 1 bit from OSR to the first OUT pin
87
91
# * Each loop iteration is 8 cycles.
88
92
tx_code = adafruit_pioasm .Program (
89
- ".program uart_tx\n " +
90
- ".side_set 1 opt\n " +
91
- f" pull side 1 [{ stop_delay } ]\n " +
92
- f" set x, { self .bitcount - 1 } side 0 [7]\n " +
93
- "bitloop:\n " +
94
- " out pins, 1\n " +
95
- " jmp x-- bitloop [6]\n "
93
+ ".program uart_tx\n "
94
+ + ".side_set 1 opt\n "
95
+ + f" pull side 1 [{ stop_delay } ]\n "
96
+ + f" set x, { self .bitcount - 1 } side 0 [7]\n "
97
+ + "bitloop:\n "
98
+ + " out pins, 1\n "
99
+ + " jmp x-- bitloop [6]\n "
96
100
)
97
101
self .tx_pio = rp2pio .StateMachine (
98
102
tx_code .assembled ,
@@ -107,63 +111,74 @@ def __init__(self, tx=None, rx=None, baudrate=9600, bits=8, parity=None, stop=1,
107
111
)
108
112
109
113
def deinit (self ):
114
+ """De-initialize the UART object."""
110
115
if self .rx_pio :
111
116
self .rx_pio .deinit ()
112
117
if self .tx_pio :
113
118
self .tx_pio .deinit ()
114
119
115
120
@property
116
121
def timeout (self ):
122
+ """Return the UART timeout."""
117
123
return self ._timeout
118
124
119
125
@timeout .setter
120
126
def timeout (self , value ):
127
+ """Set the UART timeout."""
121
128
self ._timeout = value
122
129
123
130
@property
124
131
def baudrate (self ):
132
+ """Return the UART baudrate."""
125
133
if self .tx_pio :
126
134
return self .tx_pio .frequency // 8
127
135
return self .rx_pio .frequency // 8
128
136
129
137
@baudrate .setter
130
138
def baudrate (self , frequency ):
139
+ """Set the UART baudrate."""
131
140
if self .rx_pio :
132
141
self .rx_pio .frequency = frequency * 8
133
142
if self .tx_pio :
134
143
self .tx_pio .frequency = frequency * 8
135
144
136
145
@property
137
146
def in_waiting (self ):
147
+ """Return whether the UART is waiting."""
138
148
return self .rx_pio .in_waiting
139
149
140
150
def reset_input_buffer (self ):
151
+ """Clear the UART input buffer."""
141
152
self .rx_pio .clear_rxfifo ()
142
153
143
154
def readinto (self , buf ):
155
+ """Read UART data into buf and return the number of bytes read."""
144
156
if self .bitcount > 8 :
145
157
raw_in = array .array ("H" )
146
158
for _ in range (len (buf )):
147
159
raw_in .append (0 )
148
160
else :
149
161
raw_in = buf
150
- mv = memoryview (raw_in )
162
+ mem_view = memoryview (raw_in )
151
163
count = 0
152
164
start_time = time .monotonic ()
153
- while count < len (buf ) and (self .timeout == 0 or (time .monotonic () - start_time ) < self .timeout ):
165
+ while count < len (buf ) and (
166
+ self .timeout == 0 or (time .monotonic () - start_time ) < self .timeout
167
+ ):
154
168
waiting = min (len (buf ) - count , self .rx_pio .in_waiting )
155
- self .rx_pio .readinto (mv [count : count + waiting ])
169
+ self .rx_pio .readinto (mem_view [count : count + waiting ])
156
170
if self .timeout == 0 and waiting == 0 :
157
171
return None if count == 0 else count
158
172
count += waiting
159
173
160
- if self .parity != None :
174
+ if self .parity is not None :
161
175
for i in range (count ):
162
176
# TODO: Check parity bits instead of just masking them.
163
177
buf [i ] = (raw_in [i ] >> self .shift ) & self .mask
164
178
return count
165
179
166
180
def read (self , n ):
181
+ """Read and return an array of up to n values from the UART."""
167
182
if self .bits > 8 :
168
183
buf = array .array (n )
169
184
else :
@@ -174,11 +189,12 @@ def read(self, n):
174
189
return buf
175
190
176
191
def write (self , buf ):
192
+ """Write the contents of buf to the UART."""
177
193
# Compute parity if we need to
178
194
if self .parity :
179
195
if self .bitcount > 8 :
180
- a = array .array ("H" )
181
- for i , v in enumerate (buf ):
196
+ a = array .array ("H" ) # pylint: disable=invalid-name
197
+ for i , v in enumerate (buf ): # pylint: disable=invalid-name
182
198
a .append (v )
183
199
ones = 0
184
200
for pos in range (self .bitcount - 1 ):
@@ -188,7 +204,8 @@ def write(self, buf):
188
204
if self .parity == self .Parity .ODD :
189
205
if (ones % 2 ) == 0 :
190
206
parity = 1
191
- elif (ones % 2 ) == 1 : # even parity needs another one if the data is odd
207
+ elif (ones % 2 ) == 1 :
208
+ # even parity needs another one if the data is odd
192
209
parity = 1
193
210
a [i ] |= parity << (self .bitcount - 1 )
194
211
buf = a
0 commit comments