13 |
13 |
14 """ |
14 """ |
15 import struct |
15 import struct |
16 import re |
16 import re |
17 import gpib |
17 import gpib |
|
18 import numpy |
18 |
19 |
19 ######################################## |
20 ######################################## |
20 # HP3562A internal binary types decoders |
21 # HP3562A internal binary types decoders |
21 |
22 |
22 def decode_float(s): |
23 def decode_float(s): |
23 assert len(s) in [4,8] |
24 if len(s) == 4: |
24 # exponential term |
25 i1, i2, e = struct.unpack('>hbb', s) |
25 e = ord(s[-1]) |
26 i2 = i2 * 2**(-23) |
26 if e & 0x80: |
27 return (i1/32768. + i2)*2**e |
27 e = e - 256 |
28 else: |
28 |
29 i1, i2, i3, i4, e = struct.unpack('>hhhbb', s) |
29 # mantissa |
30 if i2 < 0: |
30 m = [ord(x) for x in s[:-1]] |
31 i2 = (i2+32768.)*2**(-15) |
31 M = 0. |
32 else: |
32 for i in range(len(s)-1): |
33 i2 = i2*2**(-15) |
33 #M += m[i]<<(i*8) |
34 if i3 < 0: |
34 M += float(m[i])/2**((i+1)*8) |
35 i3 = (i3+32768.)*2**(-30) |
35 # XXX how do we deal negative numbers? |
36 else: |
36 #if m[0] & 0x80: |
37 i3 = i3*2**(-15) |
37 # M = M - 2^(len(s)) |
38 i4 = i4 * 2**(-38) |
38 return M * 2**(e+1) |
39 return (i1+i2+i3+i4)*2**(e-15) |
|
40 |
|
41 # def decode_float(s): |
|
42 # assert len(s) in [4,8] |
|
43 # # exponential term |
|
44 # e = ord(s[-1]) |
|
45 # if e & 0x80: |
|
46 # e = e - 256 |
|
47 |
|
48 # # mantissa |
|
49 # m = [ord(x) for x in s[:-1]] |
|
50 # M = 0. |
|
51 # for i in range(len(s)-1): |
|
52 # #M += m[i]<<(i*8) |
|
53 # M += float(m[i])/2**((i+1)*8) |
|
54 # # XXX how do we deal negative numbers? |
|
55 # #if m[0] & 0x80: |
|
56 # # M = M - 2^(len(s)) |
|
57 # return M * 2**(e+1) |
39 |
58 |
40 def decode_string(s): |
59 def decode_string(s): |
41 nb = ord(s[0]) |
60 nb = ord(s[0]) |
42 s = s[1:nb+2] |
61 s = s[1:nb+2] |
43 r = "" |
62 r = "" |
57 |
76 |
58 todisp = [] |
77 todisp = [] |
59 for row in head_struct: |
78 for row in head_struct: |
60 key = row[0] |
79 key = row[0] |
61 typ = row[1] |
80 typ = row[1] |
|
81 if typ is None: |
|
82 continue |
62 val = header.get(key, "N/A") |
83 val = header.get(key, "N/A") |
63 if isinstance(val, basestring): |
84 if isinstance(val, basestring): |
64 val = repr(val) |
85 val = repr(val) |
65 elif typ is bool and isinstance(val, typ): |
86 elif typ is bool and isinstance(val, typ): |
66 m = bool_re.match(key) |
87 m = bool_re.match(key) |
81 maxk = max([len(k) for k, v in todisp]) |
102 maxk = max([len(k) for k, v in todisp]) |
82 maxv = max([len(v) for k, v in todisp]) |
103 maxv = max([len(v) for k, v in todisp]) |
83 fmt = "%%-%ds %%-%ds"%(maxk, maxv) |
104 fmt = "%%-%ds %%-%ds"%(maxk, maxv) |
84 w = maxk+maxv+4 |
105 w = maxk+maxv+4 |
85 ncols = columns/w |
106 ncols = columns/w |
86 nrows = len(todisp)/ncols |
107 if ncols: |
|
108 nrows = len(todisp)/ncols |
|
109 else: |
|
110 nrows = len(todisp) |
87 res = "" |
111 res = "" |
88 for i in range(nrows): |
112 for i in range(nrows): |
89 res += "| ".join([fmt%todisp[j*nrows+i] for j in range(ncols)]) + "\n" |
113 res += "| ".join([fmt%todisp[j*nrows+i] for j in range(ncols)]) + "\n" |
90 return res |
114 return res |
91 |
115 |
92 def decode_header(data, header_struct): |
116 def decode_header(data, header_struct, idx=0): |
93 d = data |
117 d = data |
94 typ = d[:2] |
118 if d[idx:].startswith('#'): |
95 assert typ == "#A" |
119 # we have a preliminary header here... |
96 |
120 typ = d[idx:idx+2] |
97 totlen = struct.unpack('>h', d[2:4])[0] |
121 assert typ == "#A" |
98 idx = 4 |
122 idx += 2 |
|
123 totlen = struct.unpack('>h', d[idx:idx+2])[0] |
|
124 idx += 2 |
99 tt=0 |
125 tt=0 |
100 header = {} |
126 header = {} |
101 for i, (nam, dtype, fmt, nbytes) in enumerate(header_struct): |
127 for i, (nam, dtype, fmt, nbytes) in enumerate(header_struct): |
102 if dtype == str: |
128 if dtype is None: |
|
129 idx += nbytes |
|
130 continue |
|
131 elif dtype == str: |
103 val = decode_string(d[idx:]) |
132 val = decode_string(d[idx:]) |
104 else: |
133 else: |
105 if fmt: |
134 if fmt: |
106 v = struct.unpack('>'+fmt, d[idx: idx+nbytes])[0] |
135 v = struct.unpack('>'+fmt, d[idx: idx+nbytes])[0] |
107 if isinstance(dtype, dict): |
136 if isinstance(dtype, dict): |
112 val = dtype(d[idx: idx+nbytes]) |
141 val = dtype(d[idx: idx+nbytes]) |
113 header[nam] = val |
142 header[nam] = val |
114 idx += nbytes |
143 idx += nbytes |
115 return header, idx |
144 return header, idx |
116 |
145 |
|
146 def read_trace(data, idx, nelts): |
|
147 assert len(data[idx:]) >= (nelts*4), "data[idx:] is too small (%s for %s)"%(len(data[idx:]), (nelts*4)) |
|
148 resu = [] |
|
149 for i in range(nelts): |
|
150 resu.append(decode_float(data[idx: idx+4])) |
|
151 idx += 4 |
|
152 return numpy.array(resu, dtype=float) |
|
153 |
117 ##################### |
154 ##################### |
118 # HP3562A constants |
155 # HP3562A constants |
119 |
156 |
120 # GPIB buffer size is 3x80 characters lines |
157 # GPIB buffer size is 3x80 characters lines |
121 class STATUS_BYTE(gpib.Constants): |
158 class STATUS_BYTE(gpib.Constants): |