Werner's Miscellanea
Sign in or create your account | Project List | Help
Werner's Miscellanea Git Source Tree
Root/
Source at commit ebb0d2708b542ee20929375d9a22d37d86b100a5 created 10 years 1 month ago. By Werner Almesberger, ircstat/README: change date format from MMYY to YYMM | |
---|---|
1 | #!/usr/bin/python |
2 | |
3 | from tmc.wave import * |
4 | from tmc.dxplore import dxplore |
5 | from 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 | # |
25 | def 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 | # |
53 | wv = waves() |
54 | wv.load("_wv") |
55 | |
56 | # |
57 | # Digitize the waves and save the result. |
58 | # |
59 | dm = wv[0].digitize(1.5, 1.8) |
60 | dp = wv[1].digitize(1.5, 1.8) |
61 | wv = waves(dp, dm, dp-dm) |
62 | wv.save("_dig") |
63 | |
64 | # |
65 | # Also record the differential signal. |
66 | # |
67 | wd = wv[1]-wv[0] |
68 | dd = wd.digitize(-0.5, 0.5) |
69 | wd.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 |
75 | p = 1/12e6 |
76 | dp_t, viol = recover(dp, p, p*0.9, p*1.1) |
77 | print viol |
78 | dm_t, viol = recover(dm, p, p*.9, p*1.1, t0 = dp.data[0]) |
79 | print 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 | # |
85 | clk = map(lambda t: t+p/2, dp_t) |
86 | clk.extend((clk[-1]+p, clk[-1]+2*p, clk[-1]+3*p)) |
87 | dp_bv = dp.get(clk) |
88 | dm_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 | # |
94 | dd.data = dp_t; |
95 | dd.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 | # |
101 | dpd = [] |
102 | dmd = [] |
103 | dck = [] |
104 | |
105 | # err, silly, seems that we've mixed up D+ and D- all over the place :-) |
106 | print d_usb_stream(dm_bv[:], dp_bv[:]) |
107 | |
108 | for v in dp_bv: |
109 | dpd.append(v) |
110 | dpd.append(v) |
111 | dck.append(0) |
112 | dck.append(1) |
113 | |
114 | for 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 | # |
127 | dxplore((dmd, dpd, dck), 0, p/2, labels = ("D+", "D-", "CLK")) |
128 |
Branches:
master