diff --git a/m1/usb/dec.py b/m1/usb/dec.py new file mode 100755 index 0000000..fae6f32 --- /dev/null +++ b/m1/usb/dec.py @@ -0,0 +1,127 @@ +#!/usr/bin/python + +from tmc.wave import * +from tmc.dxplore import dxplore +from tmc.decode import d_usb_stream + + +# +# Clock recovery: we assume that each change in the wave is triggered by a +# clock edge. We know the clock's nominal period and resynchronize on each +# edge. Additionally, we can obtain a list of times when a timing violation +# has occurred. +# +# Note that the timing violations logic doesn't make much sense in its present +# form, since it mainly measures noise (particularly if we're digitizing slow +# edges) and not clock drift. +# +# A more useful metric would be accumulated error from some point of reference +# or at least the timing of same edges, to eliminate (generally harmless) time +# offsets introduced by digitizing. +# +# So it would probably make more sense for "recover" not to check for timing +# violations at all, and leave this to more specialized functions. +# +def recover(self, period, min = None, max = None, t0 = None): + if t0 is None: + t0 = self.data[0] + v = not self.initial + res = [] + violations = [] + for t in self.data: + v = not v + if t <= t0: + continue + n = 0 + while t0 < t-period/2: + res.append(t0) + t0 += period + n += 1 + if min is not None: + if t0-t > n*min: + violations.append(t) + if max is not None: + if t-t0 > n*max: + violations.append(t) + t0 = t + return res, violations + + +# +# Load the analog waves saved by get.py +# +wv = waves() +wv.load("_wv") + +# +# Digitize the waves and save the result. +# +dm = wv[0].digitize(1.5, 1.8) +dp = wv[1].digitize(1.5, 1.8) +wv = waves(dp, dm, dp-dm) +wv.save("_dig") + +# +# Also record the differential signal. +# +wd = wv[1]-wv[0] +dd = wd.digitize(-0.5, 0.5) +wd.save("_diff") + +# +# Run clock recovery on D+/D-. We only need one, but check both to be sure. +# +#p = 1/1.5e6 +p = 1/12e6 +dp_t, viol = recover(dp, p, p*0.9, p*1.1) +print viol +dm_t, viol = recover(dm, p, p*.9, p*1.1, t0 = dp.data[0]) +print viol + +# +# Shift the clock by half a period, add a few periods to get steady state and +# SE0s (if any), and then sample the data lines. +# +clk = map(lambda t: t+p/2, dp_t) +clk.extend((clk[-1]+p, clk[-1]+2*p, clk[-1]+3*p)) +dp_bv = dp.get(clk) +dm_bv = dm.get(clk) + +# +# Save a wave with the recovered clock to make it easier to find the bits in +# analog graphs. +# +dd.data = dp_t; +dd.save("_clk") + +# +# For decoding, we need a fake bit clock. We generate it by doubling each data +# bit and generating a L->H transition during this bit. +# +dpd = [] +dmd = [] +dck = [] + +# err, silly, seems that we've mixed up D+ and D- all over the place :-) +print d_usb_stream(dm_bv[:], dp_bv[:]) + +for v in dp_bv: + dpd.append(v) + dpd.append(v) + dck.append(0) + dck.append(1) + +for v in dm_bv: + dmd.append(v) + dmd.append(v) + +# +# Display the reconstructed digital signal. Note that the absolute time is only +# correct at the beginning and that relative time is only accurate over +# intervals in which no significant clock resynchronization has occurred. +# +# In fact, dxplore should probably have an option to either turn off time +# entirely or to display a user-provided time axis. The latter may be a bit +# tricky to implement. +# +dxplore((dmd, dpd, dck), 0, p/2, labels = ("D+", "D-", "CLK")) diff --git a/m1/usb/plot b/m1/usb/plot new file mode 100755 index 0000000..edd8a20 --- /dev/null +++ b/m1/usb/plot @@ -0,0 +1,12 @@ +#!/bin/sh +# +# Plot output of "dec" +# +gnuplot -persist <