]> sigrok.org Git - libsigrokdecode.git/blame - decoders/usb_signalling/pd.py
avr_isp: Add more parts
[libsigrokdecode.git] / decoders / usb_signalling / pd.py
CommitLineData
2dc6d41c 1##
50bd5d25 2## This file is part of the libsigrokdecode project.
2dc6d41c
UH
3##
4## Copyright (C) 2011 Gareth McMullin <gareth@blacksphere.co.nz>
a6f703fd 5## Copyright (C) 2012-2020 Uwe Hermann <uwe@hermann-uwe.de>
2dc6d41c
UH
6##
7## This program is free software; you can redistribute it and/or modify
8## it under the terms of the GNU General Public License as published by
9## the Free Software Foundation; either version 2 of the License, or
10## (at your option) any later version.
11##
12## This program is distributed in the hope that it will be useful,
13## but WITHOUT ANY WARRANTY; without even the implied warranty of
14## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15## GNU General Public License for more details.
16##
17## You should have received a copy of the GNU General Public License
4539e9ca 18## along with this program; if not, see <http://www.gnu.org/licenses/>.
2dc6d41c
UH
19##
20
2dc6d41c 21import sigrokdecode as srd
a6f703fd 22from common.srdhelper import SrdIntEnum
2dc6d41c 23
a56b8fe1 24'''
c515eed7 25OUTPUT_PYTHON format:
a56b8fe1
UH
26
27Packet:
28[<ptype>, <pdata>]
29
30<ptype>, <pdata>:
31 - 'SOP', None
32 - 'SYM', <sym>
33 - 'BIT', <bit>
34 - 'STUFF BIT', None
35 - 'EOP', None
033d6221 36 - 'ERR', None
13e81308
SB
37 - 'KEEP ALIVE', None
38 - 'RESET', None
a56b8fe1
UH
39
40<sym>:
41 - 'J', 'K', 'SE0', or 'SE1'
42
43<bit>:
033d6221 44 - '0' or '1'
a56b8fe1 45 - Note: Symbols like SE0, SE1, and the J that's part of EOP don't yield 'BIT'.
a56b8fe1
UH
46'''
47
d1970f14 48# Low-/full-speed symbols.
2dc6d41c 49# Note: Low-speed J and K are inverted compared to the full-speed J and K!
7dc75721
UH
50symbols = {
51 'low-speed': {
2dc6d41c
UH
52 # (<dp>, <dm>): <symbol/state>
53 (0, 0): 'SE0',
54 (1, 0): 'K',
55 (0, 1): 'J',
56 (1, 1): 'SE1',
7dc75721
UH
57 },
58 'full-speed': {
2dc6d41c
UH
59 # (<dp>, <dm>): <symbol/state>
60 (0, 0): 'SE0',
61 (1, 0): 'J',
62 (0, 1): 'K',
63 (1, 1): 'SE1',
7dc75721 64 },
519092e3
SB
65 'automatic': {
66 # (<dp>, <dm>): <symbol/state>
67 (0, 0): 'SE0',
68 (1, 0): 'FS_J',
69 (0, 1): 'LS_J',
70 (1, 1): 'SE1',
71 },
502acfc2
UH
72 # After a PREamble PID, the bus segment between Host and Hub uses LS
73 # signalling rate and FS signalling polarity (USB 2.0 spec, 11.8.4: "For
74 # both upstream and downstream low-speed data, the hub is responsible for
75 # inverting the polarity of the data before transmitting to/from a
76 # low-speed port.").
9821622a
SB
77 'low-speed-rp': {
78 # (<dp>, <dm>): <symbol/state>
79 (0, 0): 'SE0',
80 (1, 0): 'J',
81 (0, 1): 'K',
82 (1, 1): 'SE1',
83 },
2dc6d41c
UH
84}
85
5bb55598 86bitrates = {
502acfc2
UH
87 'low-speed': 1500000, # 1.5Mb/s (+/- 1.5%)
88 'low-speed-rp': 1500000, # 1.5Mb/s (+/- 1.5%)
5bb55598 89 'full-speed': 12000000, # 12Mb/s (+/- 0.25%)
519092e3 90 'automatic': None
5bb55598
UH
91}
92
56cc44ff
SB
93sym_annotation = {
94 'J': [0, ['J']],
95 'K': [1, ['K']],
96 'SE0': [2, ['SE0', '0']],
97 'SE1': [3, ['SE1', '1']],
85c03d60
UH
98}
99
a6f703fd
UH
100St = SrdIntEnum.from_str('St', 'IDLE GET_BIT GET_EOP WAIT_IDLE')
101
21cda951
UH
102class SamplerateError(Exception):
103 pass
104
2dc6d41c 105class Decoder(srd.Decoder):
12c56703 106 api_version = 3
2dc6d41c
UH
107 id = 'usb_signalling'
108 name = 'USB signalling'
109 longname = 'Universal Serial Bus (LS/FS) signalling'
2787cf2a 110 desc = 'USB (low-speed/full-speed) signalling protocol.'
2dc6d41c
UH
111 license = 'gplv2+'
112 inputs = ['logic']
113 outputs = ['usb_signalling']
d6d8a8a4 114 tags = ['PC']
6a15597a 115 channels = (
2dc6d41c
UH
116 {'id': 'dp', 'name': 'D+', 'desc': 'USB D+ signal'},
117 {'id': 'dm', 'name': 'D-', 'desc': 'USB D- signal'},
da9bcbd9 118 )
84c1c0b5
BV
119 options = (
120 {'id': 'signalling', 'desc': 'Signalling',
519092e3 121 'default': 'automatic', 'values': ('automatic', 'full-speed', 'low-speed')},
84c1c0b5 122 )
da9bcbd9 123 annotations = (
85c03d60
UH
124 ('sym-j', 'J symbol'),
125 ('sym-k', 'K symbol'),
126 ('sym-se0', 'SE0 symbol'),
127 ('sym-se1', 'SE1 symbol'),
da9bcbd9
BV
128 ('sop', 'Start of packet (SOP)'),
129 ('eop', 'End of packet (EOP)'),
130 ('bit', 'Bit'),
131 ('stuffbit', 'Stuff bit'),
033d6221 132 ('error', 'Error'),
13e81308
SB
133 ('keep-alive', 'Low-speed keep-alive'),
134 ('reset', 'Reset'),
da9bcbd9 135 )
066d6594 136 annotation_rows = (
13e81308 137 ('bits', 'Bits', (4, 5, 6, 7, 8, 9, 10)),
85c03d60 138 ('symbols', 'Symbols', (0, 1, 2, 3)),
066d6594 139 )
2dc6d41c
UH
140
141 def __init__(self):
10aeb8ea
GS
142 self.reset()
143
144 def reset(self):
f372d597 145 self.samplerate = None
d1970f14 146 self.oldsym = 'J' # The "idle" state is J.
fdd5ee5e 147 self.ss_block = None
5bb55598
UH
148 self.bitrate = None
149 self.bitwidth = None
a241cfb6 150 self.samplepos = None
d1970f14 151 self.samplenum_target = None
a241cfb6 152 self.samplenum_edge = None
6fbab493 153 self.samplenum_lastedge = 0
a241cfb6 154 self.edgepins = None
d1970f14 155 self.consecutive_ones = 0
1647db06 156 self.bits = None
a6f703fd 157 self.state = St.IDLE
2dc6d41c 158
f372d597 159 def start(self):
c515eed7 160 self.out_python = self.register(srd.OUTPUT_PYTHON)
be465111 161 self.out_ann = self.register(srd.OUTPUT_ANN)
f372d597
BV
162
163 def metadata(self, key, value):
164 if key == srd.SRD_CONF_SAMPLERATE:
165 self.samplerate = value
519092e3
SB
166 self.signalling = self.options['signalling']
167 if self.signalling != 'automatic':
168 self.update_bitrate()
169
170 def update_bitrate(self):
171 self.bitrate = bitrates[self.signalling]
172 self.bitwidth = float(self.samplerate) / float(self.bitrate)
2dc6d41c 173
d1970f14 174 def putpx(self, data):
6fbab493
SB
175 s = self.samplenum_edge
176 self.put(s, s, self.out_python, data)
7d4b5fac
UH
177
178 def putx(self, data):
6fbab493
SB
179 s = self.samplenum_edge
180 self.put(s, s, self.out_ann, data)
7d4b5fac 181
fdd5ee5e 182 def putpm(self, data):
6fbab493
SB
183 e = self.samplenum_edge
184 self.put(self.ss_block, e, self.out_python, data)
fdd5ee5e
UH
185
186 def putm(self, data):
6fbab493
SB
187 e = self.samplenum_edge
188 self.put(self.ss_block, e, self.out_ann, data)
fdd5ee5e 189
d1970f14 190 def putpb(self, data):
6fbab493
SB
191 s, e = self.samplenum_lastedge, self.samplenum_edge
192 self.put(s, e, self.out_python, data)
d1970f14
UH
193
194 def putb(self, data):
6fbab493
SB
195 s, e = self.samplenum_lastedge, self.samplenum_edge
196 self.put(s, e, self.out_ann, data)
d1970f14
UH
197
198 def set_new_target_samplenum(self):
f78b814d 199 self.samplepos += self.bitwidth
a241cfb6 200 self.samplenum_target = int(self.samplepos)
6fbab493 201 self.samplenum_lastedge = self.samplenum_edge
a241cfb6 202 self.samplenum_edge = int(self.samplepos - (self.bitwidth / 2))
d1970f14
UH
203
204 def wait_for_sop(self, sym):
205 # Wait for a Start of Packet (SOP), i.e. a J->K symbol change.
13e81308 206 if sym != 'K' or self.oldsym != 'J':
d1970f14 207 return
033d6221 208 self.consecutive_ones = 0
502acfc2 209 self.bits = ''
519092e3 210 self.update_bitrate()
ce780be2 211 self.samplepos = self.samplenum - (self.bitwidth / 2) + 0.5
d1970f14
UH
212 self.set_new_target_samplenum()
213 self.putpx(['SOP', None])
85c03d60 214 self.putx([4, ['SOP', 'S']])
a6f703fd 215 self.state = St.GET_BIT
d1970f14 216
bef4949d 217 def handle_bit(self, b):
033d6221
SB
218 if self.consecutive_ones == 6:
219 if b == '0':
220 # Stuff bit.
221 self.putpb(['STUFF BIT', None])
222 self.putb([7, ['Stuff bit: 0', 'SB: 0', '0']])
223 self.consecutive_ones = 0
224 else:
225 self.putpb(['ERR', None])
226 self.putb([8, ['Bit stuff error', 'BS ERR', 'B']])
a6f703fd 227 self.state = St.IDLE
d1970f14 228 else:
9059125f 229 # Normal bit (not a stuff bit).
a56b8fe1 230 self.putpb(['BIT', b])
85c03d60 231 self.putb([6, ['%s' % b]])
d1970f14
UH
232 if b == '1':
233 self.consecutive_ones += 1
234 else:
235 self.consecutive_ones = 0
236
237 def get_eop(self, sym):
238 # EOP: SE0 for >= 1 bittime (usually 2 bittimes), then J.
6fbab493 239 self.set_new_target_samplenum()
d1970f14 240 self.putpb(['SYM', sym])
56cc44ff 241 self.putb(sym_annotation[sym])
d1970f14 242 self.oldsym = sym
bef4949d
SB
243 if sym == 'SE0':
244 pass
245 elif sym == 'J':
9059125f 246 # Got an EOP.
fdd5ee5e 247 self.putpm(['EOP', None])
85c03d60 248 self.putm([5, ['EOP', 'E']])
a6f703fd 249 self.state = St.WAIT_IDLE
0f274b53
SB
250 else:
251 self.putpm(['ERR', None])
252 self.putm([8, ['EOP Error', 'EErr', 'E']])
a6f703fd 253 self.state = St.IDLE
d1970f14
UH
254
255 def get_bit(self, sym):
6fbab493 256 self.set_new_target_samplenum()
1647db06
SB
257 b = '0' if self.oldsym != sym else '1'
258 self.oldsym = sym
d1970f14 259 if sym == 'SE0':
bef4949d 260 # Start of an EOP. Change state, save edge
a6f703fd 261 self.state = St.GET_EOP
6fbab493 262 self.ss_block = self.samplenum_lastedge
bef4949d 263 else:
bef4949d 264 self.handle_bit(b)
d1970f14 265 self.putpb(['SYM', sym])
56cc44ff 266 self.putb(sym_annotation[sym])
1647db06
SB
267 if len(self.bits) <= 16:
268 self.bits += b
269 if len(self.bits) == 16 and self.bits == '0000000100111100':
270 # Sync and low-speed PREamble seen
271 self.putpx(['EOP', None])
a6f703fd 272 self.state = St.IDLE
1647db06
SB
273 self.signalling = 'low-speed-rp'
274 self.update_bitrate()
275 self.oldsym = 'J'
276 if b == '0':
519092e3 277 edgesym = symbols[self.signalling][tuple(self.edgepins)]
64b45b20
UH
278 if edgesym not in ('SE0', 'SE1'):
279 if edgesym == sym:
a241cfb6
SB
280 self.bitwidth = self.bitwidth - (0.001 * self.bitwidth)
281 self.samplepos = self.samplepos - (0.01 * self.bitwidth)
282 else:
283 self.bitwidth = self.bitwidth + (0.001 * self.bitwidth)
284 self.samplepos = self.samplepos + (0.01 * self.bitwidth)
d1970f14 285
13e81308
SB
286 def handle_idle(self, sym):
287 self.samplenum_edge = self.samplenum
288 se0_length = float(self.samplenum - self.samplenum_lastedge) / self.samplerate
289 if se0_length > 2.5e-6: # 2.5us
290 self.putpb(['RESET', None])
291 self.putb([10, ['Reset', 'Res', 'R']])
519092e3
SB
292 self.signalling = self.options['signalling']
293 elif se0_length > 1.2e-6 and self.signalling == 'low-speed':
13e81308
SB
294 self.putpb(['KEEP ALIVE', None])
295 self.putb([9, ['Keep-alive', 'KA', 'A']])
519092e3
SB
296
297 if sym == 'FS_J':
298 self.signalling = 'full-speed'
299 self.update_bitrate()
300 elif sym == 'LS_J':
301 self.signalling = 'low-speed'
302 self.update_bitrate()
831d893d 303 self.oldsym = 'J'
a6f703fd 304 self.state = St.IDLE
13e81308 305
12c56703 306 def decode(self):
21cda951
UH
307 if not self.samplerate:
308 raise SamplerateError('Cannot decode without samplerate.')
12c56703
UH
309
310 # Seed internal state from the very first sample.
1b9ef18b 311 pins = self.wait()
12c56703
UH
312 sym = symbols[self.options['signalling']][pins]
313 self.handle_idle(sym)
314
315 while True:
d1970f14 316 # State machine.
a6f703fd 317 if self.state == St.IDLE:
12c56703
UH
318 # Wait for any edge on either DP and/or DM.
319 pins = self.wait([{0: 'e'}, {1: 'e'}])
320 sym = symbols[self.signalling][pins]
13e81308
SB
321 if sym == 'SE0':
322 self.samplenum_lastedge = self.samplenum
a6f703fd 323 self.state = St.WAIT_IDLE
13e81308
SB
324 else:
325 self.wait_for_sop(sym)
a241cfb6 326 self.edgepins = pins
a6f703fd 327 elif self.state in (St.GET_BIT, St.GET_EOP):
d1970f14 328 # Wait until we're in the middle of the desired bit.
12c56703
UH
329 self.edgepins = self.wait([{'skip': self.samplenum_edge - self.samplenum}])
330 pins = self.wait([{'skip': self.samplenum_target - self.samplenum}])
331
332 sym = symbols[self.signalling][pins]
a6f703fd 333 if self.state == St.GET_BIT:
d1970f14 334 self.get_bit(sym)
a6f703fd 335 elif self.state == St.GET_EOP:
d1970f14 336 self.get_eop(sym)
a6f703fd 337 elif self.state == St.WAIT_IDLE:
c240da48 338 # Skip "all-low" input. Wait for high level on either DP or DM.
1b9ef18b 339 pins = self.wait()
c240da48
GS
340 while not pins[0] and not pins[1]:
341 pins = self.wait([{0: 'h'}, {1: 'h'}])
13e81308 342 if self.samplenum - self.samplenum_lastedge > 1:
12c56703 343 sym = symbols[self.options['signalling']][pins]
13e81308
SB
344 self.handle_idle(sym)
345 else:
12c56703 346 sym = symbols[self.signalling][pins]
13e81308 347 self.wait_for_sop(sym)
13e81308 348 self.edgepins = pins