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
38 - 'J', 'K', 'SE0', or 'SE1'
42 - Note: Symbols like SE0, SE1, and the J that's part of EOP don't yield 'BIT'.
45 # Low-/full-speed symbols.
46 # Note: Low-speed J and K are inverted compared to the full-speed J and K!
49 # (<dp>, <dm>): <symbol/state>
56 # (<dp>, <dm>): <symbol/state>
65 'low-speed': 1500000, # 1.5Mb/s (+/- 1.5%)
66 'full-speed': 12000000, # 12Mb/s (+/- 0.25%)
76 class SamplerateError(Exception):
79 class Decoder(srd.Decoder):
82 name = 'USB signalling'
83 longname = 'Universal Serial Bus (LS/FS) signalling'
84 desc = 'USB (low-speed and full-speed) signalling protocol.'
87 outputs = ['usb_signalling']
89 {'id': 'dp', 'name': 'D+', 'desc': 'USB D+ signal'},
90 {'id': 'dm', 'name': 'D-', 'desc': 'USB D- signal'},
93 {'id': 'signalling', 'desc': 'Signalling',
94 'default': 'full-speed', 'values': ('full-speed', 'low-speed')},
97 ('sym-j', 'J symbol'),
98 ('sym-k', 'K symbol'),
99 ('sym-se0', 'SE0 symbol'),
100 ('sym-se1', 'SE1 symbol'),
101 ('sop', 'Start of packet (SOP)'),
102 ('eop', 'End of packet (EOP)'),
104 ('stuffbit', 'Stuff bit'),
107 ('bits', 'Bits', (4, 5, 6, 7)),
108 ('symbols', 'Symbols', (0, 1, 2, 3)),
112 self.samplerate = None
113 self.oldsym = 'J' # The "idle" state is J.
121 self.samplenum_target = None
123 self.consecutive_ones = 0
127 self.out_python = self.register(srd.OUTPUT_PYTHON)
128 self.out_ann = self.register(srd.OUTPUT_ANN)
130 def metadata(self, key, value):
131 if key == srd.SRD_CONF_SAMPLERATE:
132 self.samplerate = value
133 self.bitrate = bitrates[self.options['signalling']]
134 self.bitwidth = float(self.samplerate) / float(self.bitrate)
135 self.halfbit = int(self.bitwidth / 2)
137 def putpx(self, data):
138 self.put(self.samplenum, self.samplenum, self.out_python, data)
140 def putx(self, data):
141 self.put(self.samplenum, self.samplenum, self.out_ann, data)
143 def putpm(self, data):
144 s, h = self.samplenum, self.halfbit
145 self.put(self.ss_block - h, s + h, self.out_python, data)
147 def putm(self, data):
148 s, h = self.samplenum, self.halfbit
149 self.put(self.ss_block - h, s + h, self.out_ann, data)
151 def putpb(self, data):
152 s, h = self.samplenum, self.halfbit
153 self.put(s - h, s + h, self.out_python, data)
155 def putb(self, data):
156 s, h = self.samplenum, self.halfbit
157 self.put(s - h, s + h, self.out_ann, data)
159 def set_new_target_samplenum(self):
160 bitpos = self.ss_sop + (self.bitwidth / 2)
161 bitpos += self.bitnum * self.bitwidth
162 self.samplenum_target = int(bitpos)
164 def wait_for_sop(self, sym):
165 # Wait for a Start of Packet (SOP), i.e. a J->K symbol change.
169 self.ss_sop = self.samplenum
170 self.set_new_target_samplenum()
171 self.putpx(['SOP', None])
172 self.putx([4, ['SOP', 'S']])
173 self.state = 'GET BIT'
175 def handle_bit(self, sym, b):
176 if self.consecutive_ones == 6 and b == '0':
178 self.putpb(['STUFF BIT', None])
179 self.putb([7, ['Stuff bit: %s' % b, 'SB: %s' % b, '%s' % b]])
180 self.putb([sym_idx[sym], ['%s' % sym]])
181 self.consecutive_ones = 0
183 # Normal bit (not a stuff bit).
184 self.putpb(['BIT', b])
185 self.putb([6, ['%s' % b]])
186 self.putb([sym_idx[sym], ['%s' % sym]])
188 self.consecutive_ones += 1
190 self.consecutive_ones = 0
192 def get_eop(self, sym):
193 # EOP: SE0 for >= 1 bittime (usually 2 bittimes), then J.
194 self.syms.append(sym)
195 self.putpb(['SYM', sym])
196 self.putb([sym_idx[sym], ['%s' % sym, '%s' % sym[0]]])
198 self.set_new_target_samplenum()
200 if self.syms[-2:] == ['SE0', 'J']:
202 self.putpm(['EOP', None])
203 self.putm([5, ['EOP', 'E']])
204 self.bitnum, self.syms, self.state = 0, [], 'IDLE'
205 self.consecutive_ones = 0
207 def get_bit(self, sym):
209 # Start of an EOP. Change state, run get_eop() for this bit.
210 self.state = 'GET EOP'
211 self.ss_block = self.samplenum
214 self.syms.append(sym)
215 self.putpb(['SYM', sym])
216 b = '0' if self.oldsym != sym else '1'
217 self.handle_bit(sym, b)
219 self.set_new_target_samplenum()
222 def decode(self, ss, es, data):
223 if not self.samplerate:
224 raise SamplerateError('Cannot decode without samplerate.')
225 for (self.samplenum, pins) in data:
227 if self.state == 'IDLE':
228 # Ignore identical samples early on (for performance reasons).
229 if self.oldpins == pins:
232 sym = symbols[self.options['signalling']][tuple(pins)]
233 self.wait_for_sop(sym)
234 elif self.state in ('GET BIT', 'GET EOP'):
235 # Wait until we're in the middle of the desired bit.
236 if self.samplenum < self.samplenum_target:
238 sym = symbols[self.options['signalling']][tuple(pins)]
239 if self.state == 'GET BIT':
241 elif self.state == 'GET EOP':