Add firmware for the ATUSB IEEE 802.15.4 USB Adapter
[linux-libre-firmware.git] / atusb / an / dec.py
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 dp = wv[0].digitize(1.5, 1.8)
60 dm = 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"))