several improvements; add an internal state reader

Tue, 18 Dec 2007 00:23:10 +0100

author
David Douard <david.douard@logilab.fr>
date
Tue, 18 Dec 2007 00:23:10 +0100
changeset 14
07e2cbf140df
parent 13
78e3e839658b
child 15
b930440af354

several improvements; add an internal state reader

HP3562A/__init__.py file | annotate | diff | comparison | revisions
HP3562A/dump_datablock.py file | annotate | diff | comparison | revisions
HP3562A/dump_trace.py file | annotate | diff | comparison | revisions
HP3562A/enum_types.py file | annotate | diff | comparison | revisions
HP3562A/read_trace.py file | annotate | diff | comparison | revisions
HP3562A/state_decoder.py file | annotate | diff | comparison | revisions
HP3562A/trace_decoder.py file | annotate | diff | comparison | revisions
bin/dump_datablock file | annotate | diff | comparison | revisions
bin/read_state file | annotate | diff | comparison | revisions
bin/read_trace file | annotate | diff | comparison | revisions
prologix.py file | annotate | diff | comparison | revisions
--- a/HP3562A/__init__.py	Mon Dec 17 18:59:45 2007 +0100
+++ b/HP3562A/__init__.py	Tue Dec 18 00:23:10 2007 +0100
@@ -12,8 +12,90 @@
 ---------
 
 """
+import struct
+import gpib
 
-from gpib import gpib
+########################################
+# HP3562A internal binary types decoders
+
+def decode_float(s):
+    assert len(s) in [4,8]
+    # exponential term 
+    e = ord(s[-1])
+    if e & 0x80:
+        e = e - 256
+
+    # mantissa
+    m = [ord(x) for x in s[:-1]]
+    M = 0.
+    for i in range(len(s)-1):
+        #M += m[i]<<(i*8)
+        M += float(m[i])/2**((i+1)*8)
+    # XXX how do we deal negative numbers?
+    #if m[0] & 0x80:
+    #    M = M - 2^(len(s))
+    return M * 2**(e+1)
+
+def decode_string(s):
+    nb = ord(s[0])
+    s = s[1:nb+2]
+    r = ""
+    # XXX why do we need to do this? It's not described in the manual...
+    for c in s:
+        r += chr(ord(c) & 0x7F)
+    return r
+
+
+###
+# Some useful functions
+def format_header(header, head_struct, columns=80):
+    """
+    Pretty print a data block (trace, state or coord) 
+    """
+    todisp = []
+    for row in head_struct:
+        key = row[0]        
+        val = header.get(key, "N/A")
+        if isinstance(val, basestring):
+            val = repr(val)
+        else:
+            val = str(val)
+        todisp.append((key+":", val))
+    maxk = max([len(k) for k, v in todisp])
+    maxv = max([len(v) for k, v in todisp])
+    fmt = "%%-%ds %%-%ds"%(maxk, maxv)
+    w = maxk+maxv+4
+    ncols = columns/w
+    nrows = len(todisp)/ncols
+    res = ""
+    for i in range(nrows):
+        res += "| ".join([fmt%todisp[j*nrows+i] for j in range(ncols)]) + "\n"
+    return res
+
+def decode_header(data, header_struct):    
+    d = data
+    typ = d[:2]
+    assert typ == "#A"
+
+    totlen = struct.unpack('>h', d[2:4])[0]
+    idx = 4
+    tt=0
+    header = {}
+    for i, (nam, dtype, fmt, nbytes) in enumerate(header_struct):
+        if dtype == str:
+            val = decode_string(d[idx:])
+        else:
+            if fmt:
+                v = struct.unpack('>'+fmt, d[idx: idx+nbytes])[0]
+                if isinstance(dtype, dict):
+                    val = dtype.get(int(v), "N/A")
+                else:
+                    val = dtype(v)
+            else:
+                val = dtype(d[idx: idx+nbytes])
+        header[nam] = val
+        idx += nbytes
+    return header, idx
 
 #####################
 # HP3562A constants
@@ -102,3 +184,5 @@
                   (0x40, "ACDA", "Accept date"),
                   #...
                   ]
+
+    
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HP3562A/dump_datablock.py	Tue Dec 18 00:23:10 2007 +0100
@@ -0,0 +1,78 @@
+import sys
+import time
+import gpib
+import prologix
+
+
+class HP3562dumper(prologix.GPIB):
+
+    MODES = {'trace': 'DD',
+             'state': 'DS',
+             'coord': 'DC',
+             }
+    
+    FORMATS = {'binary': 'BN',
+               'ascii': 'AS',
+               'ansi': 'AN'}
+            
+    def __init__(self, device="/dev/ttyUSB0", baudrate=115200, timeout=0.1,
+                 address=0):
+        super(HP3562dumper, self).__init__(device, baudrate, timeout, address, mode=1)
+
+    def dump(self, mode='trace', format="binary"): 
+        format = format.lower()
+        mode = mode.lower()
+        assert mode in self.MODES
+        assert format in self.FORMATS
+        cmd = self.MODES[mode] + self.FORMATS[format]
+
+        res = ""
+        print "command = ", cmd
+        self._cnx.write('%s\r'%cmd)
+        i = 0
+        while i<self._retries:
+            l = self._cnx.readline()
+            if l.strip() == "":
+                i += 1
+                time.sleep(self._timeout)
+                continue
+            res += l 
+            i = 0
+        return res
+
+    
+
+def main():
+    import optparse
+    opt = optparse.OptionParser("A simple tool for dumping the current trace")
+    opt.add_option('-f', '--filename', default=None,
+                   dest='filename',
+                   help='Output filename. If not set, write to stdout')
+    opt.add_option('-d', '--device', default='/dev/ttyUSB0',
+                   dest='device',
+                   help='Device of the RS232 connection (default: /dev/ttyUSB0)',
+                   )
+    opt.add_option('-a', '--address', default=0,
+                   dest='address',
+                   help='GPIB address of the device',
+                   )
+    opt.add_option('-b', '--block', default='trace',
+                   dest='block',
+                   help='Data block to dump (may be "trace" [default], "state" or "coord")',
+                   )
+    opt.add_option('-m', '--mode', default='binary',
+                   dest='mode',
+                   help='Dumping mode (may be "binary" [default], "ascii" or "ansi")',
+                   )
+    options, argv = opt.parse_args(sys.argv)
+
+    cnx = HP3562dumper(device=options.device, address=int(options.address))
+    res = cnx.dump(mode=options.block, format=options.mode)
+    sys.stderr.write("read %s bytes\n"%(len(res)))
+    if options.filename:
+        open(options.filename, 'w').write(res)
+    else:
+        print res
+    
+if __name__=='__main__':
+    main()
--- a/HP3562A/dump_trace.py	Mon Dec 17 18:59:45 2007 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,74 +0,0 @@
-import sys
-import time
-import gpib
-
-class HP3562dumper(gpib.GPIB):
-
-    MODES = {'trace': 'DD',
-             'state': 'DS',
-             'coord': 'DC',
-             }
-    
-    FORMATS = {'binary': 'BN',
-               'ascii': 'AS',
-               'ansi': 'AN'}
-            
-    def __init__(self, device="/dev/ttyUSB0", baudrate=115200, timeout=0.1,
-                 address=0):
-        super(HP3562dumper, self).__init__(device, baudrate, timeout, address, mode=1)
-
-    def dump(self, mode='trace', format="binary"): 
-        format = format.lower()
-        mode = mode.lower()
-        assert mode in self.MODES
-        assert format in self.FORMATS
-        cmd = self.MODES[mode] + self.FORMATS[format]
-
-        res = ""
-        print "command = ", cmd
-        self._cnx.write('%s\r'%cmd)
-        i = 0
-        while i<self._retries:
-            l = self._cnx.readline()
-            if l.strip() == "":
-                i += 1
-                time.sleep(self._timeout)
-                continue
-            res += l 
-            i = 0
-        return res
-
-    
-
-if __name__=='__main__':
-    import optparse
-    opt = optparse.OptionParser("A simple tool for dumping the current trace")
-    opt.add_option('-f', '--filename', default=None,
-                   dest='filename',
-                   help='Output filename. If not set, write to stdout')
-    opt.add_option('-d', '--device', default='/dev/ttyUSB0',
-                   dest='device',
-                   help='Device of the RS232 connection (default: /dev/ttyUSB0)',
-                   )
-    opt.add_option('-a', '--address', default=0,
-                   dest='address',
-                   help='GPIB address of the device',
-                   )
-    opt.add_option('-b', '--block', default='trace',
-                   dest='block',
-                   help='Data block to dump (may be "trace" [default], "state" or "coord")',
-                   )
-    opt.add_option('-m', '--mode', default='binary',
-                   dest='mode',
-                   help='Dumping mode (may be "binary" [default], "ascii" or "ansi")',
-                   )
-    options, argv = opt.parse_args(sys.argv)
-
-    cnx = HP3562dumper(device=options.device, address=int(options.address))
-    res = cnx.dump(mode=options.block, format=options.mode)
-    sys.stderr.write("read %s bytes\n"%(len(res)))
-    if options.filename:
-        open(options.filename, 'w').write(res)
-    else:
-        print res
-    
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HP3562A/enum_types.py	Tue Dec 18 00:23:10 2007 +0100
@@ -0,0 +1,248 @@
+# -*- coding: utf-8 -*-
+
+EDSP = {0: "No data",
+        1: "Frequency response",
+        2: "Power spectrum 1",
+        3: "Power spectrum 2",
+        4: "Coherence",
+        5: "Cross spectrum",
+        6: "Input time 1",
+        7: "Input time 2",
+        8: "Input linear spectrum 1",
+        9: "Input linear spectrum 2",
+        10: "Impulse response",
+        11: "Cross correlation",
+        12: "Auto correlation 1",
+        13: "Auto correlation 2",
+        14: "Histogram 1",
+        15: "Histogram 2",
+        16: "Cumulative density function 1",
+        17: "Cumulative density function 2",
+        18: "Probability density function 1",
+        19: "Probability density function 2",
+        20: "Average linear spectrum 1",
+        21: "Average linear spectrum 2",
+        22: "Average time record 1",
+        23: "Average time record 2",
+        24: "Synthesis pole-zeros",
+        25: "Synthesis pole-residue",
+        26: "Synthesis polynomial",
+        27: "Synthesis constant",
+        28: "Windowed time record 1",
+        29: "Windowed time record 2",
+        30: "Windowed linear spectrum 1",
+        31: "Windowed linear spectrum 2",
+        32: "Filtered time record 1",
+        33: "Filtered time record 2",
+        34: "Filtered linear spectrum 1",
+        35: "Filtered linear spectrum 2",
+        36: "Time capture buffer",
+        37: "Captured linear spectrum",
+        38: "Captured time record",
+        39: "Throughput time record 1",
+        40: "Throughput time record 2",
+        41: "Curve fit",
+        42: "Weighted function",
+        43: "Not used",
+        44: "Orbits",
+        45: "Demodulation polar",
+        46: "Preview demod record 1",
+        47: "Preview demod record 2",
+        48: "Preview demod linear spectrum 1",
+        49: "Preview demod linear spectrum 2",
+        }
+
+ECH = {0: "Channel 1",
+       1: "Channel 2",
+       2: "Channel 1&2",
+       3: "No channel",
+       }
+
+EOVR = ECH
+
+EDOM = {0: 'Time',
+        1: 'Frequency',
+        2: 'Voltage (amplitude)',
+        }
+
+EVLT = {0: "Peak",
+        1: "RMS",
+        2: "Volt (indicates peak only)",
+        }
+
+EAMP = {0: "Volts",
+        1: "Volts squared",
+        2: "PSD (V²/Hz)",
+        3: "ESD (V²s/Hz)",
+        4: "PSD¹² (V/Hz¹²)",
+        5: "No unit",
+        6: "Unit volts",
+        7: "Unit volts²",
+        }
+        
+EXAXIS= {0: "No units",
+         1: "Hertz",
+         2: "RPM",
+         3: "Orders",
+         4: "Seconds",
+         5: "Revs",
+         6: "Degrees",
+         7: "dB",
+         8: "dBV",
+         9: "Volts",
+         10: "V Hz¹²",
+         11: "Hz/s",
+         12: "V/EU",
+         13: "Vrms",
+         14: "V²/Hz",
+         15: "%",
+         16: "Points",
+         17: "Records",
+         18: "Ohms",
+         19: "Hertz/octave",
+         20: "Pulse/Rev",
+         21: "Decades",
+         22: "Minutes",
+         23: "V²s/Hz",
+         24: "Octave",
+         25: "Seconds/Decade",
+         26: "Seconds/Octave",
+         27: "Hz/Point",
+         28: "Points/Sweep",
+         29: "Points/Decade",
+         30: "Points/Octave",
+         31: "V/Vrms",
+         32: "V²",
+         33: "EU referenced to chan 1",
+         34: "EU referenced to chan 2",
+         35: "EU value",
+         }
+
+EMEAS = {0: "Linear resolution",
+         1: "Log resolution",
+         2: "Swept sine",
+         3: "Time capture",
+         4: "Linear resolution throughput",
+         }
+
+EDEMOD = {45: "AM",
+          46: "FM",
+          47: "PM",
+          }
+
+EAVG = {0: "No data",
+        1: "Not averaged",
+        2: "Averaged",}
+
+EWIN = {0: "N/A",
+        1: "Hann",
+        2: "Flat top",
+        3: "Uniforme",
+        4: "Exponential",
+        5: "Force",
+        6: "Force chan 1/expon chan 2",
+        7: "Expon chan 1/force chan 2",
+        8: "User",
+        }
+
+EMTYP = {0: "Frequency responce",
+         1: "Cross correlation",
+         2: "Power spectrum",
+         3: "Auto correlation",
+         4: "Histogram",
+         5: "No measurement",
+         }
+
+EWINTYP = { 11: "Hanning",
+            12: "Flat top",
+            13: "Uniform",
+            14: "User window",
+            15: "Force/Exponential",
+            }
+
+EFEXPW = { 0: "Force",
+           1: "Exponential",
+           }
+
+EAVGTYP = { 6: "Stable",
+            7: "Exponential",
+            8: "Peak",
+            9: "Continuous peak",
+            10: "Averaging off",
+            }
+
+ETRGTYP = { 18: "Free run",
+            19: "Channel 1",
+            20: "Channel 2",
+            21: "External",
+            22: "Source trigger",
+            23: "HP-IB trigger",
+            }
+
+ETRGSLP = { 16: "Positive",
+            17: "Negative",
+            }
+
+EPRVTYP = { 0: "Manual preview",
+            1: "Timed preview",
+            2: "Preview off",
+            }
+
+ESMPTYP = { 24: "Internal sample",
+            25: "External sample",
+            }
+
+ERNGUNT = EXAXIS
+
+ERNGTYP = { 26: "Auto range on",
+            27: "Auto range off",
+            28: "Auto range set",
+            }
+
+EINCPL = { 29: "AC",
+           30: "DC",
+           }
+
+ESRCTYP = { 31: "Source off",
+            32: "Random noise",
+            33: "Burst random",
+            34: "Periodic chirp",
+            35: "Burst chirp",
+            36: "Swept sine",
+            37: "Fixed sine",
+            }
+
+ESWPDIR = { 41: "Up",
+            42: "Sweep hold",
+            43: "Manual sweep",
+            44: "Down",
+            }
+
+ESWPMOD = { 39: "Linear sweep",
+            40: "Log sweep",
+            }
+
+EEXTSMPFREQUNT = EXAXIS
+
+EBNDUNT = EXAXIS
+
+ESWPRATEUNT = EXAXIS
+
+EAUGAINREFCH = { 0: "Channel 1",
+                 1: "Channel 2",
+                 2: "Not used",
+                 3: "No channel",
+                 }
+EDEMODCH = {  0: "Channel 1",
+              1: "Channel 2",
+              2: "Both channels",
+              3: "No channel",
+              }
+
+ESRCLVLUNT = EXAXIS
+
+ESRCDCOFFST = EXAXIS
+
+ETRGLVLUNT = EXAXIS
+
+ECPTLGHUNT = EXAXIS
--- a/HP3562A/read_trace.py	Mon Dec 17 18:59:45 2007 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,346 +0,0 @@
-# -*- coding: utf-8 -*-
-
-import struct
-import numpy
-
-
-def decode_float(s):
-    assert len(s) in [4,8]
-    # exponential term 
-    e = ord(s[-1])
-    if e & 0x80:
-        e = e - 256
-
-    # mantissa
-    m = [ord(x) for x in s[:-1]]
-    M = 0.
-    for i in range(len(s)-1):
-        #M += m[i]<<(i*8)
-        M += float(m[i])/2**((i+1)*8)
-    # XXX how do we deal negative numbers?
-    #if m[0] & 0x80:
-    #    M = M - 2^(len(s))
-    return M * 2**(e+1)
-
-def decode_string(s):
-    nb = ord(s[0])
-    s = s[1:nb+2]
-    r = ""
-    # XXX why do we need to do this? It's not described in the manual...
-    for c in s:
-        r += chr(ord(c) & 0x7F)
-    return r
-
-EDSP = {0: "No data",
-        1: "Frequency response",
-        2: "Power spectrum 1",
-        3: "Power spectrum 2",
-        4: "Coherence",
-        5: "Cross spectrum",
-        6: "Input time 1",
-        7: "Input time 2",
-        8: "Input linear spectrum 1",
-        9: "Input linear spectrum 2",
-        10: "Impulse response",
-        11: "Cross correlation",
-        12: "Auto correlation 1",
-        13: "Auto correlation 2",
-        14: "Histogram 1",
-        15: "Histogram 2",
-        16: "Cumulative density function 1",
-        17: "Cumulative density function 2",
-        18: "Probability density function 1",
-        19: "Probability density function 2",
-        20: "Average linear spectrum 1",
-        21: "Average linear spectrum 2",
-        22: "Average time record 1",
-        23: "Average time record 2",
-        24: "Synthesis pole-zeros",
-        25: "Synthesis pole-residue",
-        26: "Synthesis polynomial",
-        27: "Synthesis constant",
-        28: "Windowed time record 1",
-        29: "Windowed time record 2",
-        30: "Windowed linear spectrum 1",
-        31: "Windowed linear spectrum 2",
-        32: "Filtered time record 1",
-        33: "Filtered time record 2",
-        34: "Filtered linear spectrum 1",
-        35: "Filtered linear spectrum 2",
-        36: "Time capture buffer",
-        37: "Captured linear spectrum",
-        38: "Captured time record",
-        39: "Throughput time record 1",
-        40: "Throughput time record 2",
-        41: "Curve fit",
-        42: "Weighted function",
-        43: "Not used",
-        44: "Orbits",
-        45: "Demodulation polar",
-        46: "Preview demod record 1",
-        47: "Preview demod record 2",
-        48: "Preview demod linear spectrum 1",
-        49: "Preview demod linear spectrum 2",
-        }
-
-ECH = {0: "Channel 1",
-       1: "Channel 2",
-       2: "Channel 1&2",
-       3: "No channel",
-       }
-
-EOVR = ECH
-
-EDOM = {0: 'Time',
-        1: 'Frequency',
-        2: 'Voltage (amplitude)',
-        }
-
-EVLT = {0: "Peak",
-        1: "RMS",
-        2: "Volt (indicates peak only)",
-        }
-
-EAMP = {0: "Volts",
-        1: "Volts squared",
-        2: "PSD (V²/Hz)",
-        3: "ESD (V²s/Hz)",
-        4: "PSD¹² (V/Hz¹²)",
-        5: "No unit",
-        6: "Unit volts",
-        7: "Unit volts²",
-        }
-        
-EXAXIS= {0: "No units",
-         1: "Hertz",
-         2: "RPM",
-         3: "Orders",
-         4: "Seconds",
-         5: "Revs",
-         6: "Degrees",
-         7: "dB",
-         8: "dBV",
-         9: "Volts",
-         10: "V Hz¹²",
-         11: "Hz/s",
-         12: "V/EU",
-         13: "Vrms",
-         14: "V²/Hz",
-         15: "%",
-         16: "Points",
-         17: "Records",
-         18: "Ohms",
-         19: "Hertz/octave",
-         20: "Pulse/Rev",
-         21: "Decades",
-         22: "Minutes",
-         23: "V²s/Hz",
-         24: "Octave",
-         25: "Seconds/Decade",
-         26: "Seconds/Octave",
-         27: "Hz/Point",
-         28: "Points/Sweep",
-         29: "Points/Decade",
-         30: "Points/Octave",
-         31: "V/Vrms",
-         32: "V²",
-         33: "EU referenced to chan 1",
-         34: "EU referenced to chan 2",
-         35: "EU value",
-         }
-
-EMEAS = {0: "Linear resolution",
-         1: "Log resolution",
-         2: "Swept sine",
-         3: "Time capture",
-         4: "Linear resolution throughput",
-         }
-
-EDEMOD1 = {45: "AM",
-           46: "FM",
-           47: "PM",
-           }
-
-EDEMOD2 = EDEMOD1
-
-EAVG = {0: "No data",
-        1: "Not averaged",
-        2: "Averaged",}
-
-
-
-EWIN = {0: "N/A",
-        1: "Hann",
-        2: "Flat top",
-        3: "Uniforme",
-        4: "Exponential",
-        5: "Force",
-        6: "Force chan 1/expon chan 2",
-        7: "Expon chan 1/force chan 2",
-        8: "User",
-        }
-
-HEADER = [ ("Display function", EDSP, 'h', 2),
-           ('Number of elements', int, 'h', 2),
-           ('Displayed elements', int, 'h', 2),
-           ('Number of averages', int, 'h', 2),
-           ('Channel selection', ECH, 'h', 2),
-           ('Overflow status', EOVR, 'h', 2),
-           ('Overlap percentage', int, 'h', 2),
-           ('Domain', EDOM, 'h', 2),
-           ('Volts peak/rms', EVLT, 'h', 2),
-           ('Amplitude units', EAMP, 'h', 2),
-           ('X axis units', EXAXIS, 'h', 2),
-           ('Auto math label', str, 's', 14),
-           ('Trace label', str, 's', 22),
-           ('EU label 1', str, 's', 6),
-           ('EU label 2', str, 's', 6),
-           ('Float/Interger', bool, 'h', 2),
-           ('Complex/Real', bool, 'h', 2),
-           ('Live/Recalled', bool, 'h', 2),
-           ('Math result', bool, 'h', 2),
-           ('Real/Complex input', bool, 'h', 2),
-           ('Log/Linear data', bool, 'h', 2),
-           ('Auto math', bool, 'h', 2),
-           ('Real time status', bool, 'h', 2),
-           ('Measurement mode', EMEAS, 'h', 2),
-           ('Window', EWIN, 'h', 2),
-           ('Demod type channel 1', EDEMOD1, 'h', 2),
-           ('Demod type channel 2', EDEMOD2, 'h', 2),
-           ('Demod active channel 1', bool, 'h', 2),
-           ('Demod active channel 2', bool, 'h', 2),
-           ('Average status', EAVG, 'h', 2),
-           ('Not used', int, 'hh', 4),
-           ('Samp freq/2 (real)', decode_float, None, 4),
-           ('Samp freq/2 (imag)', decode_float, None, 4),
-           ('Not used', decode_float, None, 4),
-           ('Delta X-axis', decode_float, None, 4),
-           ('Max range', decode_float, None, 4),
-           ('Start time value', decode_float, None, 4),
-           ('Expon wind const 1', decode_float, None, 4),
-           ('Expon wind const 2', decode_float, None, 4),
-           ('EU value chan 1', decode_float, None, 4),
-           ('EU value chan 2', decode_float, None, 4),
-           ('Trig delay chan 1', decode_float, None, 4),
-           ('Trig delay chan 2', decode_float, None, 4),
-           ('Start freq value', decode_float, None, 8),
-           ('Start data value', decode_float, None, 8),
-           ]
-
-def decode_trace(data):    
-    d = data
-
-    typ = d[:2]
-    assert typ == "#A"
-
-    totlen = struct.unpack('>h', d[2:4])[0]
-    idx = 4
-    tt=0
-    header = {}
-    for i, (nam, dtype, fmt, nbytes) in enumerate(HEADER):
-        if dtype == str:
-            val = decode_string(d[idx:])
-        else:
-            if fmt:
-                v = struct.unpack('>'+fmt, d[idx: idx+nbytes])[0]
-                if isinstance(dtype, dict):
-                    val = dtype.get(int(v), "N/A")
-                else:
-                    val = dtype(v)
-            else:
-                val = dtype(d[idx: idx+nbytes])
-        header[nam] = val
-        idx += nbytes
-    resu = []
-    for i in range(header["Number of elements"]):
-        resu.append(decode_float(d[idx: idx+4]))
-        idx += 4
-    return header, numpy.array(resu, dtype=float)
-    
-def format_header(header, head_struct, columns=80):
-    todisp = []
-    for row in head_struct:
-        key = row[0]        
-        val = header.get(key, "N/A")
-        if isinstance(val, basestring):
-            val = repr(val)
-        else:
-            val = str(val)
-        todisp.append((key+":", val))
-    maxk = max([len(k) for k, v in todisp])
-    maxv = max([len(v) for k, v in todisp])
-    fmt = "%%-%ds %%-%ds"%(maxk, maxv)
-    w = maxk+maxv+4
-    ncols = columns/w
-    nrows = len(todisp)/ncols
-    print "w=", w
-    print "ncols=", ncols
-    print "nrows=", nrows
-    res = ""
-    for i in range(nrows):
-        res += "| ".join([fmt%todisp[j*nrows+i] for j in range(ncols)]) + "\n"
-    return res
-          
-
-if __name__ == "__main__":
-    import sys
-    import optparse
-    opt = optparse.OptionParser("A simple tool for tracing a dumped trace")
-    opt.add_option('-f', '--filename', default=None,
-                   dest='filename',
-                   help='Output filename. If not set, read from stdin')
-    opt.add_option('-m', '--mode', default='binary',
-                   dest='mode',
-                   help='Dumping mode (may be "binary" [default], "ascii" or "ansi")',
-                   )
-    opt.add_option('-d', '--display-header', default=False,
-                   action="store_true",
-                   dest="displayheader",
-                   help="Display the trace header")
-    opt.add_option('-P', '--noplot-trace', default=True,
-                   action="store_false",
-                   dest="plot",
-                   help="Do not display the plot of the trace")
-    opt.add_option('-x', '--xmode', default='lin',
-                   dest='xmode',
-                   help='X coordinate mode (may be "lin" [default] or "log")')
-    opt.add_option('-y', '--ymode', default='lin',
-                   dest='ymode',
-                   help='Y coordinate mode (may be "lin" [default], "log" or "db")')
-    
-    options, argv = opt.parse_args(sys.argv)
-
-
-    if options.filename is None:
-        print "Can't deal stdin for now..."
-        sys.exit(1)
-    try:
-        header, data = decode_trace(open(options.filename, 'rb').read())
-    except Exception, e:
-        print "ERROR: can't read %s an interpret it as a HP3562 trace"%options.filename
-        print e
-        sys.exit(1)
-
-    if options.displayheader:
-        print format_header(header, HEADER, 100)
-    if options.plot:
-        f0 = header['Start freq value']
-        dx = header['Delta X-axis']
-        n = header['Number of elements']
-        x = numpy.linspace(f0, f0+dx*n, len(data)) 
-        y = data.copy()
-
-        import pylab
-        if options.ymode != "lin":
-            minv = min(y[y>0])
-            y[y==0] = minv
-            y = numpy.log10(y)
-        if options.ymode == "db":
-            y = y*10
-            pylab.ylabel('db')
-        pylab.grid()
-        pylab.plot(x, y)
-        pylab.xlabel('frequency')
-        pylab.show()
-    
-          
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HP3562A/state_decoder.py	Tue Dec 18 00:23:10 2007 +0100
@@ -0,0 +1,151 @@
+# -*- coding: utf-8 -*-
+"""
+state_decoder
+=============
+
+Module for decoding the internal state of the HP3562A DSA, using the
+GPIB command "DSBN" (Dump State BiNary).
+
+This file can be exectued as a python script. Use '-h' for more informations. 
+"""
+from HP3562A import format_header, decode_float, decode_string, decode_header
+
+from HP3562A.enum_types import *
+
+HEADER = [("Measurement mode", EMEAS, 'h', 2),
+          ("Measurement 1", EMTYP, 'h', 2),
+          ("Measurement 2", EMTYP, 'h', 2),
+          ("Window type", EWINTYP, 'h', 2),
+          ("Force/Expon window 1", EFEXPW, 'h', 2),
+          ("Force/Expon window 2", EFEXPW, 'h', 2),
+          ("Average type", EAVGTYP, 'h', 2),
+          ("Overlap percentage", int, 'h', 2),
+          ("Number of averages", int, 'h', 2),
+          ("Sweep # of averages", int, 'h', 2),
+          ("Trigger type", ETRGTYP, 'h', 2),
+          ("Trigger slope", ETRGSLP, 'h', 2),
+          ("Preview type", EPRVTYP, 'h', 2),
+          ("Sample type", ESMPTYP, 'h', 2),
+          ("Range units chan 1", ERNGUNT, 'h', 2),
+          ("Range units chan 2", ERNGUNT, 'h', 2),
+          ("Range type 1", ERNGTYP, 'h', 2),
+          ("Range type 2", ERNGTYP, 'h', 2),
+          ("Input coupling 1", EINCPL, 'h', 2),
+          ("Input coupling 2", EINCPL, 'h', 2),
+          ("Source type", ESRCTYP, 'h', 2),
+          ("Chirp percent", int, 'h', 2),
+          ("Burst percent", int, 'h', 2),
+          ("Sweep direction", ESWPDIR, 'h', 2),
+          ("Sweep mode", ESWPMOD, 'h', 2),
+          ("Ext sample freq untis", EXAXIS, 'h', 2),
+          ("Bandwidth units", EXAXIS, 'h', 2),
+          ("Log span index", int, 'h', 2),
+          ("Log start index", int, 'h', 2),
+          ("Sweep rate units", EXAXIS, 'h', 2),
+          ("Auto gain ref chan", EDEMODCH, 'h', 2),
+          ("Demod channels", EDEMODCH, 'h', 2),
+          ("Demod type chan 1", EDEMOD, 'h', 2),
+          ("Demod type chan 2", EDEMOD, 'h', 2),
+          ("Source level units", EXAXIS, 'h', 2),
+          ("Source offset units", EXAXIS, 'h', 2),
+          ("Trigger level units", EXAXIS, 'h', 2),
+          ("Capt/thru length units", EXAXIS, 'h', 2),
+          ("EU label 1", str, 's', 6),
+          ("EU label 2", str, 's', 6),
+          ("Auto carrier on/off", bool, 'h', 2),
+          ("Time average on/off", bool, 'h', 2),
+          ("Auto/fixed resolution", bool, 'h', 2),
+          ("Auto gain on/off", bool, 'h', 2),
+          ("Auto/fixed integrate",bool, 'h', 2),
+          ("Fast average on/off", bool, 'h', 2),
+          ("Overload reject on/off", bool, 'h', 2),
+          ("Chan 1 float/ground", bool, 'h', 2),
+          ("Chan 2 float/ground", bool, 'h', 2),
+          ("Time throughput on/off", bool, 'h', 2),
+          ("Demodulation on/off", bool, 'h', 2),
+          ("EU/volts chan 1", bool, 'h', 2),
+          ("EU/volts chan 2", bool, 'h', 2),
+          ("Manual/auto arm", bool, 'h', 2),
+          ("Demod preview on/off", bool, 'h', 2),
+          ("Delete freq on/off", bool, 'h', 2),
+          ("Lin res Fstart pegged", bool, 'h', 2),
+          ("Swept Fstart pegged", bool, 'h', 2),
+          ("Force length chan 1", decode_float, None, 4),
+          ("Force length chan 2", decode_float, None, 4),
+          ("Expon time constant 1", decode_float, None, 4),
+          ("Expon time constant 2", decode_float, None, 4),
+          ("Sweep time", decode_float, None, 4),
+          ("Sweep rate", decode_float, None, 4),
+          ("Sweep resolution", decode_float, None, 4),
+          ("Sweep integrate time", decode_float, None, 4),
+          ("Auto gain level", decode_float, None, 4),
+          ("Auto gain limit", decode_float, None, 4),
+          ("Source level", decode_float, None, 4),
+          ("EU value chan 1", decode_float, None, 4),
+          ("EU value chan 2", decode_float, None, 4),
+          ("Trigger delay chan 1", decode_float, None, 4),
+          ("Trigger delay chan 2", decode_float, None, 4),
+          ("Integrate var thresh", decode_float, None, 4),
+          ("Capt/thru length", decode_float, None, 4),
+          ("Frequency span", decode_float, None, 4),
+          ("Time record length", decode_float, None, 4),
+          ("Frequency resolution", decode_float, None, 4),
+          ("Time resolution", decode_float, None, 4),
+          ("External sample rate", decode_float, None, 4),
+          ("Sample rate (actual)", decode_float, None, 4),
+          ("Range channel 1", decode_float, None, 4),
+          ("Range channel 2", decode_float, None, 4),
+          ("Preview time", decode_float, None, 4),
+          ("Trigger level", decode_float, None, 4),
+          ("Source dc offset", decode_float, None, 4),
+          ("Fixed sine frequency", decode_float, None, 8),
+          ("Start frequency", decode_float, None, 8),
+          ("Center frequency", decode_float, None, 8),
+          ("Sweep start", decode_float, None, 8),
+          ("Sweep end", decode_float, None, 8),
+          ("Carrier frequency", decode_float, None, 8),
+          ]
+          
+def decode_state(data):
+    """
+    Decode the data (as generated by the HP3562A DSA in response to a
+    "DSBN" command), and returns a dict (header)
+
+    header is the dictionnary of the header of the dumped data block,
+    """
+    header, idx = decode_header(data, HEADER)
+    return header
+    
+
+def main():
+    import sys
+    import optparse
+    opt = optparse.OptionParser("A simple tool for tracing a dumped trace")
+    opt.add_option('-f', '--filename', default=None,
+                   dest='filename',
+                   help='Output filename. If not set, read from stdin')
+    opt.add_option('-m', '--mode', default='binary',
+                   dest='mode',
+                   help='Dumping mode (may be "binary" [default], "ascii" or "ansi")',
+                   )
+    
+    options, argv = opt.parse_args(sys.argv)
+
+
+    if options.filename is None:
+        print "Can't deal stdin for now..."
+        sys.exit(1)
+    #try:
+    if 1:
+        header = decode_state(open(options.filename, 'rb').read())
+    else:
+    #except Exception, e:
+        print "ERROR: can't read %s an interpret it as a HP3562 trace"%options.filename
+        print e
+        sys.exit(1)
+
+    print format_header(header, HEADER, 100)
+    
+if __name__ == "__main__":
+    main()
+          
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HP3562A/trace_decoder.py	Tue Dec 18 00:23:10 2007 +0100
@@ -0,0 +1,145 @@
+# -*- coding: utf-8 -*-
+"""
+trace_decoder
+=============
+
+Module for decoding a trace generated by the HP3562A DSA, using the
+GPIB command "DDBN" (Dump Data BiNary).
+
+This file can be exectued as a python script. Use '-h' for more informations. 
+"""
+import struct
+import numpy
+from HP3562A import format_header, decode_float, decode_string, decode_header
+from HP3562A.enum_types import *
+
+
+HEADER = [ ("Display function", EDSP, 'h', 2),
+           ('Number of elements', int, 'h', 2),
+           ('Displayed elements', int, 'h', 2),
+           ('Number of averages', int, 'h', 2),
+           ('Channel selection', ECH, 'h', 2),
+           ('Overflow status', EOVR, 'h', 2),
+           ('Overlap percentage', int, 'h', 2),
+           ('Domain', EDOM, 'h', 2),
+           ('Volts peak/rms', EVLT, 'h', 2),
+           ('Amplitude units', EAMP, 'h', 2),
+           ('X axis units', EXAXIS, 'h', 2),
+           ('Auto math label', str, 's', 14),
+           ('Trace label', str, 's', 22),
+           ('EU label 1', str, 's', 6),
+           ('EU label 2', str, 's', 6),
+           ('Float/Interger', bool, 'h', 2),
+           ('Complex/Real', bool, 'h', 2),
+           ('Live/Recalled', bool, 'h', 2),
+           ('Math result', bool, 'h', 2),
+           ('Real/Complex input', bool, 'h', 2),
+           ('Log/Linear data', bool, 'h', 2),
+           ('Auto math', bool, 'h', 2),
+           ('Real time status', bool, 'h', 2),
+           ('Measurement mode', EMEAS, 'h', 2),
+           ('Window', EWIN, 'h', 2),
+           ('Demod type channel 1', EDEMOD, 'h', 2),
+           ('Demod type channel 2', EDEMOD, 'h', 2),
+           ('Demod active channel 1', bool, 'h', 2),
+           ('Demod active channel 2', bool, 'h', 2),
+           ('Average status', EAVG, 'h', 2),
+           ('Not used', int, 'hh', 4),
+           ('Samp freq/2 (real)', decode_float, None, 4),
+           ('Samp freq/2 (imag)', decode_float, None, 4),
+           ('Not used', decode_float, None, 4),
+           ('Delta X-axis', decode_float, None, 4),
+           ('Max range', decode_float, None, 4),
+           ('Start time value', decode_float, None, 4),
+           ('Expon wind const 1', decode_float, None, 4),
+           ('Expon wind const 2', decode_float, None, 4),
+           ('EU value chan 1', decode_float, None, 4),
+           ('EU value chan 2', decode_float, None, 4),
+           ('Trig delay chan 1', decode_float, None, 4),
+           ('Trig delay chan 2', decode_float, None, 4),
+           ('Start freq value', decode_float, None, 8),
+           ('Start data value', decode_float, None, 8),
+           ]
+
+def decode_trace(data):
+    """
+    Decode the data (as generated by the HP3562A DSA in response to a
+    "DDBN" command), and returns a couple (header, values).
+
+    header is the dictionnary of the header of the dumped data block,
+    value is a numpy array holding the trace (vector of float or
+    complex values).
+    """
+    header, idx = decode_header(data, HEADER)
+    resu = []
+    for i in range(header["Number of elements"]):
+        resu.append(decode_float(data[idx: idx+4]))
+        idx += 4
+    return header, numpy.array(resu, dtype=float)
+
+
+
+def main():
+    import sys
+    import optparse
+    opt = optparse.OptionParser("A simple tool for tracing a dumped trace")
+    opt.add_option('-f', '--filename', default=None,
+                   dest='filename',
+                   help='Output filename. If not set, read from stdin')
+    opt.add_option('-m', '--mode', default='binary',
+                   dest='mode',
+                   help='Dumping mode (may be "binary" [default], "ascii" or "ansi")',
+                   )
+    opt.add_option('-d', '--display-header', default=False,
+                   action="store_true",
+                   dest="displayheader",
+                   help="Display the trace header")
+    opt.add_option('-P', '--noplot-trace', default=True,
+                   action="store_false",
+                   dest="plot",
+                   help="Do not display the plot of the trace")
+    opt.add_option('-x', '--xmode', default='lin',
+                   dest='xmode',
+                   help='X coordinate mode (may be "lin" [default] or "log")')
+    opt.add_option('-y', '--ymode', default='lin',
+                   dest='ymode',
+                   help='Y coordinate mode (may be "lin" [default], "log" or "db")')
+    
+    options, argv = opt.parse_args(sys.argv)
+
+
+    if options.filename is None:
+        print "Can't deal stdin for now..."
+        sys.exit(1)
+    try:
+        header, data = decode_trace(open(options.filename, 'rb').read())
+    except Exception, e:
+        print "ERROR: can't read %s an interpret it as a HP3562 trace"%options.filename
+        print e
+        sys.exit(1)
+
+    if options.displayheader:
+        print format_header(header, HEADER, 100)
+    if options.plot:
+        f0 = header['Start freq value']
+        dx = header['Delta X-axis']
+        n = header['Number of elements']
+        x = numpy.linspace(f0, f0+dx*n, len(data)) 
+        y = data.copy()
+
+        import pylab
+        if options.ymode != "lin":
+            minv = min(y[y>0])
+            y[y==0] = minv
+            y = numpy.log10(y)
+        if options.ymode == "db":
+            y = y*10
+            pylab.ylabel('db')
+        pylab.grid()
+        pylab.plot(x, y)
+        pylab.xlabel('frequency')
+        pylab.show()
+    
+          
+if __name__ == "__main__":
+    main()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bin/dump_datablock	Tue Dec 18 00:23:10 2007 +0100
@@ -0,0 +1,4 @@
+#!/usr/bin/python
+
+from HP3562A.dump_datablock import main
+main()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bin/read_state	Tue Dec 18 00:23:10 2007 +0100
@@ -0,0 +1,4 @@
+#!/usr/bin/python
+
+from HP3562A.state_decoder import main
+main()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bin/read_trace	Tue Dec 18 00:23:10 2007 +0100
@@ -0,0 +1,4 @@
+#!/usr/bin/python
+
+from HP3562A.trace_decoder import main
+main()
--- a/prologix.py	Mon Dec 17 18:59:45 2007 +0100
+++ b/prologix.py	Tue Dec 18 00:23:10 2007 +0100
@@ -1,5 +1,5 @@
 """
-Prologix
+prologix
 ========
 
 Module defining a communication object to talk to Prologix USB-GPIB controler.

mercurial