2 ## This file is part of the libsigrokdecode project.
4 ## Copyright (C) 2011 Gareth McMullin <gareth@blacksphere.co.nz>
5 ## Copyright (C) 2012-2013 Uwe Hermann <uwe@hermann-uwe.de>
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.
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.
17 ## You should have received a copy of the GNU General Public License
18 ## along with this program; if not, write to the Free Software
19 ## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22 import sigrokdecode as srd
39 - 'J', 'K', 'SE0', or 'SE1'
43 - Note: Symbols like SE0, SE1, and the J that's part of EOP don't yield 'BIT'.
46 # Low-/full-speed symbols.
47 # Note: Low-speed J and K are inverted compared to the full-speed J and K!
50 # (<dp>, <dm>): <symbol/state>
57 # (<dp>, <dm>): <symbol/state>
66 'low-speed': 1500000, # 1.5Mb/s (+/- 1.5%)
67 'full-speed': 12000000, # 12Mb/s (+/- 0.25%)
73 'SE0': [2, ['SE0', '0']],
74 'SE1': [3, ['SE1', '1']],
77 class SamplerateError(Exception):
80 class Decoder(srd.Decoder):
83 name = 'USB signalling'
84 longname = 'Universal Serial Bus (LS/FS) signalling'
85 desc = 'USB (low-speed and full-speed) signalling protocol.'
88 outputs = ['usb_signalling']
90 {'id': 'dp', 'name': 'D+', 'desc': 'USB D+ signal'},
91 {'id': 'dm', 'name': 'D-', 'desc': 'USB D- signal'},
94 {'id': 'signalling', 'desc': 'Signalling',
95 'default': 'full-speed', 'values': ('full-speed', 'low-speed')},
98 ('sym-j', 'J symbol'),
99 ('sym-k', 'K symbol'),
100 ('sym-se0', 'SE0 symbol'),
101 ('sym-se1', 'SE1 symbol'),
102 ('sop', 'Start of packet (SOP)'),
103 ('eop', 'End of packet (EOP)'),
105 ('stuffbit', 'Stuff bit'),
109 ('bits', 'Bits', (4, 5, 6, 7, 8)),
110 ('symbols', 'Symbols', (0, 1, 2, 3)),
114 self.samplerate = None
115 self.oldsym = 'J' # The "idle" state is J.
120 self.samplepos = None
121 self.samplenum_target = None
122 self.samplenum_edge = None
123 self.samplenum_lastedge = 0
126 self.consecutive_ones = 0
130 self.out_python = self.register(srd.OUTPUT_PYTHON)
131 self.out_ann = self.register(srd.OUTPUT_ANN)
133 def metadata(self, key, value):
134 if key == srd.SRD_CONF_SAMPLERATE:
135 self.samplerate = value
136 self.bitrate = bitrates[self.options['signalling']]
137 self.bitwidth = float(self.samplerate) / float(self.bitrate)
139 def putpx(self, data):
140 s = self.samplenum_edge
141 self.put(s, s, self.out_python, data)
143 def putx(self, data):
144 s = self.samplenum_edge
145 self.put(s, s, self.out_ann, data)
147 def putpm(self, data):
148 e = self.samplenum_edge
149 self.put(self.ss_block, e, self.out_python, data)
151 def putm(self, data):
152 e = self.samplenum_edge
153 self.put(self.ss_block, e, self.out_ann, data)
155 def putpb(self, data):
156 s, e = self.samplenum_lastedge, self.samplenum_edge
157 self.put(s, e, self.out_python, data)
159 def putb(self, data):
160 s, e = self.samplenum_lastedge, self.samplenum_edge
161 self.put(s, e, self.out_ann, data)
163 def set_new_target_samplenum(self):
164 self.samplepos += self.bitwidth;
165 self.samplenum_target = int(self.samplepos)
166 self.samplenum_lastedge = self.samplenum_edge
167 self.samplenum_edge = int(self.samplepos - (self.bitwidth / 2))
169 def wait_for_sop(self, sym):
170 # Wait for a Start of Packet (SOP), i.e. a J->K symbol change.
174 self.consecutive_ones = 0
175 self.samplepos = self.samplenum - (self.bitwidth / 2) + 0.5
176 self.set_new_target_samplenum()
177 self.putpx(['SOP', None])
178 self.putx([4, ['SOP', 'S']])
179 self.state = 'GET BIT'
181 def handle_bit(self, b):
182 if self.consecutive_ones == 6:
185 self.putpb(['STUFF BIT', None])
186 self.putb([7, ['Stuff bit: 0', 'SB: 0', '0']])
187 self.consecutive_ones = 0
189 self.putpb(['ERR', None])
190 self.putb([8, ['Bit stuff error', 'BS ERR', 'B']])
193 # Normal bit (not a stuff bit).
194 self.putpb(['BIT', b])
195 self.putb([6, ['%s' % b]])
197 self.consecutive_ones += 1
199 self.consecutive_ones = 0
201 def get_eop(self, sym):
202 # EOP: SE0 for >= 1 bittime (usually 2 bittimes), then J.
203 self.set_new_target_samplenum()
204 self.putpb(['SYM', sym])
205 self.putb(sym_annotation[sym])
211 self.putpm(['EOP', None])
212 self.putm([5, ['EOP', 'E']])
214 self.bitwidth = float(self.samplerate) / float(self.bitrate)
216 self.putpm(['ERR', None])
217 self.putm([8, ['EOP Error', 'EErr', 'E']])
220 def get_bit(self, sym):
221 self.set_new_target_samplenum()
223 # Start of an EOP. Change state, save edge
224 self.state = 'GET EOP'
225 self.ss_block = self.samplenum_lastedge
227 b = '0' if self.oldsym != sym else '1'
229 self.putpb(['SYM', sym])
230 self.putb(sym_annotation[sym])
231 if self.oldsym != sym:
232 edgesym = symbols[self.options['signalling']][tuple(self.edgepins)]
233 if edgesym not in ('SE0', 'SE1'):
235 self.bitwidth = self.bitwidth - (0.001 * self.bitwidth)
236 self.samplepos = self.samplepos - (0.01 * self.bitwidth)
238 self.bitwidth = self.bitwidth + (0.001 * self.bitwidth)
239 self.samplepos = self.samplepos + (0.01 * self.bitwidth)
242 def decode(self, ss, es, data):
243 if not self.samplerate:
244 raise SamplerateError('Cannot decode without samplerate.')
245 for (self.samplenum, pins) in data:
247 if self.state == 'IDLE':
248 # Ignore identical samples early on (for performance reasons).
249 if self.oldpins == pins:
252 sym = symbols[self.options['signalling']][tuple(pins)]
253 self.wait_for_sop(sym)
255 elif self.state in ('GET BIT', 'GET EOP'):
256 # Wait until we're in the middle of the desired bit.
257 if self.samplenum == self.samplenum_edge:
259 if self.samplenum < self.samplenum_target:
261 sym = symbols[self.options['signalling']][tuple(pins)]
262 if self.state == 'GET BIT':
264 elif self.state == 'GET EOP':