]> sigrok.org Git - libsigrokdecode.git/blame - decoders/uart.py
srd: Add initial UART decoder.
[libsigrokdecode.git] / decoders / uart.py
CommitLineData
f44d2db2
UH
1##
2## This file is part of the sigrok project.
3##
4## Copyright (C) 2011 Uwe Hermann <uwe@hermann-uwe.de>
5##
6## This program is free software; you can redistribute it and/or modify
7## it under the terms of the GNU General Public License as published by
8## the Free Software Foundation; either version 2 of the License, or
9## (at your option) any later version.
10##
11## This program is distributed in the hope that it will be useful,
12## but WITHOUT ANY WARRANTY; without even the implied warranty of
13## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14## GNU General Public License for more details.
15##
16## You should have received a copy of the GNU General Public License
17## along with this program; if not, write to the Free Software
18## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19##
20
21#
22# UART protocol decoder
23#
24
25import sigrok
26
27# States
28WAIT_FOR_START_BIT = 0
29GET_START_BIT = 1
30GET_DATA_BITS = 2
31GET_PARITY_BIT = 3
32GET_STOP_BITS = 4
33
34# Parity options
35PARITY_NONE = 0
36PARITY_ODD = 1
37PARITY_EVEN = 2
38PARITY_ZERO = 3
39PARITY_ONE = 4
40
41# Stop bit options
42STOP_BITS_0_5 = 0
43STOP_BITS_1 = 1
44STOP_BITS_1_5 = 2
45STOP_BITS_2 = 3
46
47# Bit order options
48LSB_FIRST = 0
49MSB_FIRST = 1
50
51# Output data formats
52DATA_FORMAT_ASCII = 0
53DATA_FORMAT_HEX = 1
54
55# TODO: Remove me later.
56quick_hack = 1
57
58class Sample():
59 def __init__(self, data):
60 self.data = data
61 def probe(self, probe):
62 s = ord(self.data[probe / 8]) & (1 << (probe % 8))
63 return True if s else False
64
65def sampleiter(data, unitsize):
66 for i in range(0, len(data), unitsize):
67 yield(Sample(data[i:i+unitsize]))
68
69# Given a parity type to check (odd, even, zero, one), the value of the
70# parity bit, the value of the data, and the length of the data (5-9 bits,
71# usually 8 bits) return True if the parity is correct, False otherwise.
72# PARITY_NONE is _not_ allowed as value for 'parity_type'.
73def parity_ok(parity_type, parity_bit, data, num_data_bits):
74
75 # Handle easy cases first (parity bit is always 1 or 0).
76 if parity_type == PARITY_ZERO:
77 return parity_bit == 0
78 elif parity_type == PARITY_ONE:
79 return parity_bit == 1
80
81 # Count number of 1 (high) bits in the data (and the parity bit itself!).
82 parity = bin(data).count('1') + parity_bit
83
84 # Check for odd/even parity.
85 if parity_type == PARITY_ODD:
86 return (parity % 2) == 1
87 elif parity_type == PARITY_EVEN:
88 return (parity % 2) == 0
89 else:
90 raise Exception('Invalid parity type: %d' % parity_type)
91
92class Decoder(sigrok.Decoder):
93 id = 'uart'
94 name = 'UART'
95 longname = 'Universal Asynchronous Receiver/Transmitter (UART)'
96 desc = 'Universal Asynchronous Receiver/Transmitter (UART)'
97 longdesc = 'TODO.'
98 author = 'Uwe Hermann'
99 email = 'uwe@hermann-uwe.de'
100 license = 'gplv2+'
101 inputs = ['logic']
102 outputs = ['uart']
103 probes = {
104 # Allow specifying only one of the signals, e.g. if only one data
105 # direction exists (or is relevant).
106 ## 'rx': {'ch': 0, 'name': 'RX', 'desc': 'UART receive line'},
107 ## 'tx': {'ch': 1, 'name': 'TX', 'desc': 'UART transmit line'},
108 'rx': 0,
109 'tx': 1,
110 }
111 options = {
112 'baudrate': ['UART baud rate', 115200],
113 'num_data_bits': ['Data bits', 8], # Valid: 5-9.
114 'parity': ['Parity', PARITY_NONE],
115 'parity_check': ['Check parity', True],
116 'num_stop_bits': ['Stop bit(s)', STOP_BITS_1],
117 'bit_order': ['Bit order', LSB_FIRST],
118 'data_format': ['Output data format', DATA_FORMAT_ASCII],
119 # TODO: Options to invert the signal(s).
120 # ...
121 }
122
123 def __init__(self, **kwargs):
124 self.probes = Decoder.probes.copy()
125
126 # Set defaults, can be overridden in 'start'.
127 self.baudrate = 115200
128 self.num_data_bits = 8
129 self.parity = PARITY_NONE
130 self.check_parity = True
131 self.num_stop_bits = 1
132 self.bit_order = LSB_FIRST
133 self.data_format = DATA_FORMAT_ASCII
134
135 self.samplenum = 0
136 self.frame_start = -1
137 self.startbit = -1
138 self.cur_data_bit = 0
139 self.databyte = 0
140 self.stopbit1 = -1
141 self.startsample = -1
142
143 # Initial state.
144 self.staterx = WAIT_FOR_START_BIT
145
146 # Get the channel/probe number of the RX/TX signals.
147 ## self.rx_bit = self.probes['rx']['ch']
148 ## self.tx_bit = self.probes['tx']['ch']
149 self.rx_bit = self.probes['rx']
150 self.tx_bit = self.probes['tx']
151
152 self.oldrx = None
153 self.oldtx = None
154
155 def start(self, metadata):
156 self.unitsize = metadata['unitsize']
157 self.samplerate = metadata['samplerate']
158
159 # TODO
160 ### self.baudrate = metadata['baudrate']
161 ### self.num_data_bits = metadata['num_data_bits']
162 ### self.parity = metadata['parity']
163 ### self.parity_check = metadata['parity_check']
164 ### self.num_stop_bits = metadata['num_stop_bits']
165 ### self.bit_order = metadata['bit_order']
166 ### self.data_format = metadata['data_format']
167
168 # The width of one UART bit in number of samples.
169 self.bit_width = float(self.samplerate) / float(self.baudrate)
170
171 def report(self):
172 pass
173
174 # Return true if we reached the middle of the desired bit, false otherwise.
175 def reached_bit(self, bitnum):
176 # bitpos is the samplenumber which is in the middle of the
177 # specified UART bit (0 = start bit, 1..x = data, x+1 = parity bit
178 # (if used) or the first stop bit, and so on).
179 bitpos = self.frame_start + (self.bit_width / 2.0)
180 bitpos += bitnum * self.bit_width
181 if self.samplenum >= bitpos:
182 return True
183 return False
184
185 def reached_bit_last(self, bitnum):
186 bitpos = self.frame_start + ((bitnum + 1) * self.bit_width)
187 if self.samplenum >= bitpos:
188 return True
189 return False
190
191 def wait_for_start_bit(self, old_signal, signal):
192 # The start bit is always 0 (low). As the idle UART (and the stop bit)
193 # level is 1 (high), the beginning of a start bit is a falling edge.
194 if not (old_signal == 1 and signal == 0):
195 return
196
197 # Save the sample number where the start bit begins.
198 self.frame_start = self.samplenum
199
200 self.staterx = GET_START_BIT
201
202 def get_start_bit(self, signal):
203 # Skip samples until we're in the middle of the start bit.
204 if not self.reached_bit(0):
205 return []
206
207 self.startbit = signal
208
209 if self.startbit != 0:
210 # TODO: Startbit must be 0. If not, we report an error.
211 pass
212
213 self.cur_data_bit = 0
214 self.databyte = 0
215 self.startsample = -1
216
217 self.staterx = GET_DATA_BITS
218
219 if quick_hack: # TODO
220 return []
221
222 o = [{'type': 'S', 'range': (self.frame_start, self.samplenum),
223 'data': None, 'ann': 'Start bit'}]
224 return o
225
226 def get_data_bits(self, signal):
227 # Skip samples until we're in the middle of the desired data bit.
228 if not self.reached_bit(self.cur_data_bit + 1):
229 return []
230
231 # Save the sample number where the data byte starts.
232 if self.startsample == -1:
233 self.startsample = self.samplenum
234
235 # Get the next data bit in LSB-first or MSB-first fashion.
236 if self.bit_order == LSB_FIRST:
237 self.databyte >>= 1
238 self.databyte |= (signal << (self.num_data_bits - 1))
239 elif self.bit_order == MSB_FIRST:
240 self.databyte <<= 1
241 self.databyte |= (signal << 0)
242 else:
243 raise Exception('Invalid bit order value: %d', self.bit_order)
244
245 # Return here, unless we already received all data bits.
246 if self.cur_data_bit < self.num_data_bits - 1: # TODO? Off-by-one?
247 self.cur_data_bit += 1
248 return []
249
250 # Convert the data byte into the configured format.
251 if self.data_format == DATA_FORMAT_ASCII:
252 d = chr(self.databyte)
253 elif self.data_format == DATA_FORMAT_HEX:
254 d = '0x%02x' % self.databyte
255 else:
256 raise Exception('Invalid data format value: %d', self.data_format)
257
258 self.staterx = GET_PARITY_BIT
259
260 if quick_hack: # TODO
261 return [d]
262
263 o = [{'type': 'D', 'range': (self.startsample, self.samplenum - 1),
264 'data': d, 'ann': None}]
265
266 return o
267
268 def get_parity_bit(self, signal):
269 # If no parity is used/configured, skip to the next state immediately.
270 if self.parity == PARITY_NONE:
271 self.staterx = GET_STOP_BITS
272 return []
273
274 # Skip samples until we're in the middle of the parity bit.
275 if not self.reached_bit(self.num_data_bits + 1):
276 return []
277
278 self.paritybit = signal
279
280 self.staterx = GET_STOP_BITS
281
282 if parity_ok(self.parity, self.paritybit, self.databyte,
283 self.num_data_bits):
284 if quick_hack: # TODO
285 # return ['P']
286 return []
287 # TODO: Fix range.
288 o = [{'type': 'P', 'range': (self.samplenum, self.samplenum),
289 'data': self.paritybit, 'ann': 'Parity bit'}]
290 else:
291 if quick_hack: # TODO
292 return ['PE']
293 o = [{'type': 'PE', 'range': (self.samplenum, self.samplenum),
294 'data': self.paritybit, 'ann': 'Parity error'}]
295
296 return o
297
298 # TODO: Currently only supports 1 stop bit.
299 def get_stop_bits(self, signal):
300 # Skip samples until we're in the middle of the stop bit(s).
301 skip_parity = 0
302 if self.parity != PARITY_NONE:
303 skip_parity = 1
304 if not self.reached_bit(self.num_data_bits + 1 + skip_parity):
305 return []
306
307 self.stopbit1 = signal
308
309 if self.stopbit1 != 1:
310 # TODO: Stop bits must be 1. If not, we report an error.
311 pass
312
313 self.staterx = WAIT_FOR_START_BIT
314
315 if quick_hack: # TODO
316 return []
317
318 # TODO: Fix range.
319 o = [{'type': 'P', 'range': (self.samplenum, self.samplenum),
320 'data': None, 'ann': 'Stop bit'}]
321 return o
322
323 def decode(self, data):
324 """UART protocol decoder"""
325
326 out = []
327
328 for sample in sampleiter(data["data"], self.unitsize):
329
330 # TODO: Eliminate the need for ord().
331 s = ord(sample.data)
332
333 # TODO: Start counting at 0 or 1? Increase before or after?
334 self.samplenum += 1
335
336 # First sample: Save RX/TX value.
337 if self.oldrx == None:
338 # Get RX/TX bit values (0/1 for low/high) of the first sample.
339 self.oldrx = (s & (1 << self.rx_bit)) >> self.rx_bit
340 # self.oldtx = (s & (1 << self.tx_bit)) >> self.tx_bit
341 continue
342
343 # Get RX/TX bit values (0/1 for low/high).
344 rx = (s & (1 << self.rx_bit)) >> self.rx_bit
345 # tx = (s & (1 << self.tx_bit)) >> self.tx_bit
346
347 # State machine.
348 if self.staterx == WAIT_FOR_START_BIT:
349 self.wait_for_start_bit(self.oldrx, rx)
350 elif self.staterx == GET_START_BIT:
351 out += self.get_start_bit(rx)
352 elif self.staterx == GET_DATA_BITS:
353 out += self.get_data_bits(rx)
354 elif self.staterx == GET_PARITY_BIT:
355 out += self.get_parity_bit(rx)
356 elif self.staterx == GET_STOP_BITS:
357 out += self.get_stop_bits(rx)
358 else:
359 raise Exception('Invalid state: %s' % self.staterx)
360
361 # Save current RX/TX values for the next round.
362 self.oldrx = rx
363 # self.oldtx = tx
364
365 if out != []:
366 self.put(out)
367