IEEE 802.15.4 subsystem
Sign in or create your account | Project List | Help
IEEE 802.15.4 subsystem Git Source Tree
Root/
| Source at commit 8c574484b889c7b17d2ba4b6929947050f87d91e created 6 years 3 months ago. By Josef Filzmaier, atusb/fw: Introduce DEBUG flag | |
|---|---|
| 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")) |
| 128 | |
