Root/m1/usb/dec.py

1#!/usr/bin/python
2
3from tmc.wave import *
4from tmc.dxplore import dxplore
5from tmc.decode import d_usb_stream
6
7
8#
9# Clock recovery: we assume that each change in the wave is triggered by a
10# clock edge. We know the clock's nominal period and resynchronize on each
11# edge. Additionally, we can obtain a list of times when a timing violation
12# has occurred.
13#
14# Note that the timing violations logic doesn't make much sense in its present
15# form, since it mainly measures noise (particularly if we're digitizing slow
16# edges) and not clock drift.
17#
18# A more useful metric would be accumulated error from some point of reference
19# or at least the timing of same edges, to eliminate (generally harmless) time
20# offsets introduced by digitizing.
21#
22# So it would probably make more sense for "recover" not to check for timing
23# violations at all, and leave this to more specialized functions.
24#
25def recover(self, period, min = None, max = None, t0 = None):
26    if t0 is None:
27    t0 = self.data[0]
28    v = not self.initial
29    res = []
30    violations = []
31    for t in self.data:
32    v = not v
33    if t <= t0:
34        continue
35    n = 0
36    while t0 < t-period/2:
37        res.append(t0)
38        t0 += period
39        n += 1
40    if min is not None:
41        if t0-t > n*min:
42        violations.append(t)
43    if max is not None:
44        if t-t0 > n*max:
45        violations.append(t)
46    t0 = t
47    return res, violations
48
49
50#
51# Load the analog waves saved by get.py
52#
53wv = waves()
54wv.load("_wv")
55
56#
57# Digitize the waves and save the result.
58#
59dm = wv[0].digitize(1.5, 1.8)
60dp = wv[1].digitize(1.5, 1.8)
61wv = waves(dp, dm, dp-dm)
62wv.save("_dig")
63
64#
65# Also record the differential signal.
66#
67wd = wv[1]-wv[0]
68dd = wd.digitize(-0.5, 0.5)
69wd.save("_diff")
70
71#
72# Run clock recovery on D+/D-. We only need one, but check both to be sure.
73#
74#p = 1/1.5e6
75p = 1/12e6
76dp_t, viol = recover(dp, p, p*0.9, p*1.1)
77print viol
78dm_t, viol = recover(dm, p, p*.9, p*1.1, t0 = dp.data[0])
79print viol
80
81#
82# Shift the clock by half a period, add a few periods to get steady state and
83# SE0s (if any), and then sample the data lines.
84#
85clk = map(lambda t: t+p/2, dp_t)
86clk.extend((clk[-1]+p, clk[-1]+2*p, clk[-1]+3*p))
87dp_bv = dp.get(clk)
88dm_bv = dm.get(clk)
89
90#
91# Save a wave with the recovered clock to make it easier to find the bits in
92# analog graphs.
93#
94dd.data = dp_t;
95dd.save("_clk")
96
97#
98# For decoding, we need a fake bit clock. We generate it by doubling each data
99# bit and generating a L->H transition during this bit.
100#
101dpd = []
102dmd = []
103dck = []
104
105# err, silly, seems that we've mixed up D+ and D- all over the place :-)
106print d_usb_stream(dm_bv[:], dp_bv[:])
107
108for v in dp_bv:
109    dpd.append(v)
110    dpd.append(v)
111    dck.append(0)
112    dck.append(1)
113
114for v in dm_bv:
115    dmd.append(v)
116    dmd.append(v)
117
118#
119# Display the reconstructed digital signal. Note that the absolute time is only
120# correct at the beginning and that relative time is only accurate over
121# intervals in which no significant clock resynchronization has occurred.
122#
123# In fact, dxplore should probably have an option to either turn off time
124# entirely or to display a user-provided time axis. The latter may be a bit
125# tricky to implement.
126#
127dxplore((dmd, dpd, dck), 0, p/2, labels = ("D+", "D-", "CLK"))
128

Archive Download this file

Branches:
master



interactive