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 Decoder(srd.Decoder):
79 name = 'USB signalling'
80 longname = 'Universal Serial Bus (LS/FS) signalling'
81 desc = 'USB (low-speed and full-speed) signalling protocol.'
84 outputs = ['usb_signalling']
86 {'id': 'dp', 'name': 'D+', 'desc': 'USB D+ signal'},
87 {'id': 'dm', 'name': 'D-', 'desc': 'USB D- signal'},
90 {'id': 'signalling', 'desc': 'Signalling',
91 'default': 'full-speed', 'values': ('full-speed', 'low-speed')},
94 ('sym-j', 'J symbol'),
95 ('sym-k', 'K symbol'),
96 ('sym-se0', 'SE0 symbol'),
97 ('sym-se1', 'SE1 symbol'),
98 ('sop', 'Start of packet (SOP)'),
99 ('eop', 'End of packet (EOP)'),
101 ('stuffbit', 'Stuff bit'),
104 ('bits', 'Bits', (4, 5, 6, 7)),
105 ('symbols', 'Symbols', (0, 1, 2, 3)),
109 self.samplerate = None
110 self.oldsym = 'J' # The "idle" state is J.
118 self.samplenum_target = None
120 self.consecutive_ones = 0
124 self.out_python = self.register(srd.OUTPUT_PYTHON)
125 self.out_ann = self.register(srd.OUTPUT_ANN)
127 def metadata(self, key, value):
128 if key == srd.SRD_CONF_SAMPLERATE:
129 self.samplerate = value
130 self.bitrate = bitrates[self.options['signalling']]
131 self.bitwidth = float(self.samplerate) / float(self.bitrate)
132 self.halfbit = int(self.bitwidth / 2)
134 def putpx(self, data):
135 self.put(self.samplenum, self.samplenum, self.out_python, data)
137 def putx(self, data):
138 self.put(self.samplenum, self.samplenum, self.out_ann, data)
140 def putpm(self, data):
141 s, h = self.samplenum, self.halfbit
142 self.put(self.ss_block - h, s + h, self.out_python, data)
144 def putm(self, data):
145 s, h = self.samplenum, self.halfbit
146 self.put(self.ss_block - h, s + h, self.out_ann, data)
148 def putpb(self, data):
149 s, h = self.samplenum, self.halfbit
150 self.put(s - h, s + h, self.out_python, data)
152 def putb(self, data):
153 s, h = self.samplenum, self.halfbit
154 self.put(s - h, s + h, self.out_ann, data)
156 def set_new_target_samplenum(self):
157 bitpos = self.ss_sop + (self.bitwidth / 2)
158 bitpos += self.bitnum * self.bitwidth
159 self.samplenum_target = int(bitpos)
161 def wait_for_sop(self, sym):
162 # Wait for a Start of Packet (SOP), i.e. a J->K symbol change.
166 self.ss_sop = self.samplenum
167 self.set_new_target_samplenum()
168 self.putpx(['SOP', None])
169 self.putx([4, ['SOP', 'S']])
170 self.state = 'GET BIT'
172 def handle_bit(self, sym, b):
173 if self.consecutive_ones == 6 and b == '0':
175 self.putpb(['STUFF BIT', None])
176 self.putb([7, ['Stuff bit: %s' % b, 'SB: %s' % b, '%s' % b]])
177 self.putb([sym_idx[sym], ['%s' % sym]])
178 self.consecutive_ones = 0
180 # Normal bit (not a stuff bit).
181 self.putpb(['BIT', b])
182 self.putb([6, ['%s' % b]])
183 self.putb([sym_idx[sym], ['%s' % sym]])
185 self.consecutive_ones += 1
187 self.consecutive_ones = 0
189 def get_eop(self, sym):
190 # EOP: SE0 for >= 1 bittime (usually 2 bittimes), then J.
191 self.syms.append(sym)
192 self.putpb(['SYM', sym])
193 self.putb([sym_idx[sym], ['%s' % sym, '%s' % sym[0]]])
195 self.set_new_target_samplenum()
197 if self.syms[-2:] == ['SE0', 'J']:
199 self.putpm(['EOP', None])
200 self.putm([5, ['EOP', 'E']])
201 self.bitnum, self.syms, self.state = 0, [], 'IDLE'
202 self.consecutive_ones = 0
204 def get_bit(self, sym):
206 # Start of an EOP. Change state, run get_eop() for this bit.
207 self.state = 'GET EOP'
208 self.ss_block = self.samplenum
211 self.syms.append(sym)
212 self.putpb(['SYM', sym])
213 b = '0' if self.oldsym != sym else '1'
214 self.handle_bit(sym, b)
216 self.set_new_target_samplenum()
219 def decode(self, ss, es, data):
220 if self.samplerate is None:
221 raise Exception("Cannot decode without samplerate.")
222 for (self.samplenum, pins) in data:
224 if self.state == 'IDLE':
225 # Ignore identical samples early on (for performance reasons).
226 if self.oldpins == pins:
229 sym = symbols[self.options['signalling']][tuple(pins)]
230 self.wait_for_sop(sym)
231 elif self.state in ('GET BIT', 'GET EOP'):
232 # Wait until we're in the middle of the desired bit.
233 if self.samplenum < self.samplenum_target:
235 sym = symbols[self.options['signalling']][tuple(pins)]
236 if self.state == 'GET BIT':
238 elif self.state == 'GET EOP':
241 raise Exception('Invalid state: %s' % self.state)