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.
120 self.samplepos = None
121 self.samplenum_target = None
122 self.samplenum_edge = None
125 self.consecutive_ones = 0
129 self.out_python = self.register(srd.OUTPUT_PYTHON)
130 self.out_ann = self.register(srd.OUTPUT_ANN)
132 def metadata(self, key, value):
133 if key == srd.SRD_CONF_SAMPLERATE:
134 self.samplerate = value
135 self.bitrate = bitrates[self.options['signalling']]
136 self.bitwidth = float(self.samplerate) / float(self.bitrate)
137 self.halfbit = int(self.bitwidth / 2)
139 def putpx(self, data):
140 self.put(self.samplenum, self.samplenum, self.out_python, data)
142 def putx(self, data):
143 self.put(self.samplenum, self.samplenum, self.out_ann, data)
145 def putpm(self, data):
146 s, h = self.samplenum, self.halfbit
147 self.put(self.ss_block - h, s + h, self.out_python, data)
149 def putm(self, data):
150 s, h = self.samplenum, self.halfbit
151 self.put(self.ss_block - h, s + h, self.out_ann, data)
153 def putpb(self, data):
154 s, h = self.samplenum, self.halfbit
155 self.put(self.samplenum_edge, s + h, self.out_python, data)
157 def putb(self, data):
158 s, h = self.samplenum, self.halfbit
159 self.put(self.samplenum_edge, s + h, self.out_ann, data)
161 def set_new_target_samplenum(self):
162 self.samplepos += self.bitwidth;
163 self.samplenum_target = int(self.samplepos)
164 self.samplenum_edge = int(self.samplepos - (self.bitwidth / 2))
166 def wait_for_sop(self, sym):
167 # Wait for a Start of Packet (SOP), i.e. a J->K symbol change.
171 self.ss_sop = self.samplenum
172 self.samplepos = self.ss_sop - (self.bitwidth / 2) + 0.5
173 self.set_new_target_samplenum()
174 self.putpx(['SOP', None])
175 self.putx([4, ['SOP', 'S']])
176 self.state = 'GET BIT'
178 def handle_bit(self, sym, b):
179 if self.consecutive_ones == 6 and b == '0':
181 self.putpb(['STUFF BIT', None])
182 self.putb([7, ['Stuff bit: %s' % b, 'SB: %s' % b, '%s' % b]])
183 self.putb([sym_idx[sym], ['%s' % sym]])
184 self.consecutive_ones = 0
186 # Normal bit (not a stuff bit).
187 self.putpb(['BIT', b])
188 self.putb([6, ['%s' % b]])
189 self.putb([sym_idx[sym], ['%s' % sym]])
191 self.consecutive_ones += 1
193 self.consecutive_ones = 0
195 def get_eop(self, sym):
196 # EOP: SE0 for >= 1 bittime (usually 2 bittimes), then J.
197 self.syms.append(sym)
198 self.putpb(['SYM', sym])
199 self.putb([sym_idx[sym], ['%s' % sym, '%s' % sym[0]]])
200 self.set_new_target_samplenum()
202 if self.syms[-2:] == ['SE0', 'J']:
204 self.putpm(['EOP', None])
205 self.putm([5, ['EOP', 'E']])
206 self.syms, self.state = [], 'IDLE'
207 self.consecutive_ones = 0
208 self.bitwidth = float(self.samplerate) / float(self.bitrate)
210 def get_bit(self, sym):
212 # Start of an EOP. Change state, run get_eop() for this bit.
213 self.state = 'GET EOP'
214 self.ss_block = self.samplenum
217 self.syms.append(sym)
218 self.putpb(['SYM', sym])
219 b = '0' if self.oldsym != sym else '1'
220 if (self.oldsym != sym):
222 edgesym = symbols[self.options['signalling']][tuple(self.edgepins)]
223 if (edgesym not in ('SE0', 'SE1')):
225 self.bitwidth = self.bitwidth - (0.001 * self.bitwidth)
226 self.samplepos = self.samplepos - (0.01 * self.bitwidth)
228 self.bitwidth = self.bitwidth + (0.001 * self.bitwidth)
229 self.samplepos = self.samplepos + (0.01 * self.bitwidth)
230 self.handle_bit(sym, b)
231 self.set_new_target_samplenum()
234 def decode(self, ss, es, data):
235 if not self.samplerate:
236 raise SamplerateError('Cannot decode without samplerate.')
237 for (self.samplenum, pins) in data:
239 if self.state == 'IDLE':
240 # Ignore identical samples early on (for performance reasons).
241 if self.oldpins == pins:
244 sym = symbols[self.options['signalling']][tuple(pins)]
245 self.wait_for_sop(sym)
247 elif self.state in ('GET BIT', 'GET EOP'):
248 # Wait until we're in the middle of the desired bit.
249 if self.samplenum == self.samplenum_edge:
251 if self.samplenum < self.samplenum_target:
253 sym = symbols[self.options['signalling']][tuple(pins)]
254 if self.state == 'GET BIT':
256 elif self.state == 'GET EOP':