7 import time |
7 import time |
8 |
8 |
9 class ConnectionError(Exception): |
9 class ConnectionError(Exception): |
10 pass |
10 pass |
11 |
11 |
12 GPIB_CONTROLLER = 1 |
12 class Constants(object): |
13 GPIB_DEVICE = 0 |
13 def __init__(self): |
|
14 self.constants = {} |
|
15 self.descriptions = {} |
|
16 self.rev_constants = {} |
|
17 for v, k, m in self._constants: |
|
18 self.k = v |
|
19 self.constants[v] = k |
|
20 self.rev_constants[k] = v |
|
21 self.descriptions[v] = m |
|
22 |
|
23 def __getitem__(self, k): |
|
24 if isinstance(k, basestring): |
|
25 return self.rev_constants[k] |
|
26 else: |
|
27 return self.constants[k] |
14 |
28 |
15 # IEEE 488.2 Status Byte constants |
29 def get_description(self, k): |
16 MAV = 0x10 # Message AVailable: bit 4 of the Status Byte |
30 if isinstance(k, basestring): |
17 ESB = 0x20 # Event Status Bit: bit 5 of the Status Byte |
31 k = self.rev_constants[k] |
18 MSS = 0x40 # Master Summary Status bit: bit 6 of the Status Byte (NOT |
32 return self.descriptions[k] |
19 # sent in response to a serial poll) |
33 |
20 RQS = 0x40 # Request Service: bit 6 of the Status Byte (when sent in |
|
21 # response to a serial poll) |
|
22 |
34 |
23 # SESR constants (Standard Event Status Register) |
35 class MODE(Constants): |
24 PON = 0x80 # Power On: Power has been turned On since last register |
36 _constants = [(1, "CONTROLLER", "Set device as Controller in Charge"), |
25 # read access |
37 (0, "DEVICE", "Set device as simple listener"), |
26 URQ = 0x40 # User Request: the user has activated some device control |
38 ] |
27 # (whatever the Remote Local state is) |
39 # TODO |
28 CME = 0x20 # Command Error |
40 # class STATUS_BYTE(Constants): |
29 EXE = 0x10 # Execution Error |
41 # # IEEE 488.2 Status Byte constants |
30 DDE = 0x08 # Device Dependant Error |
42 # MAV = 0x10 # Message AVailable: bit 4 of the Status Byte |
31 QYE = 0x04 # QuerY Error (attempt to read data while Output Queue is |
43 # ESB = 0x20 # Event Status Bit: bit 5 of the Status Byte |
32 # empty, or data in the OQ was lost) |
44 # MSS = 0x40 # Master Summary Status bit: bit 6 of the Status Byte (NOT |
33 RQC = 0x02 # Request Control: tell the CiC that the device wants to |
45 # # sent in response to a serial poll) |
34 # become the CiC |
46 # RQS = 0x40 # Request Service: bit 6 of the Status Byte (when sent in |
35 OPC = 0x01 # Operation Complete: device has completed any pending |
47 # # response to a serial poll) |
36 # operation (ready to accept new commands). This bit is |
48 # class SESR(Constants): |
37 # generated in response to a OPC command. |
49 # # SESR constants (Standard Event Status Register) |
38 |
50 # PON = 0x80 # Power On: Power has been turned On since last register |
39 ##################### |
51 # # read access |
40 # HP3562A constants |
52 # URQ = 0x40 # User Request: the user has activated some device control |
41 |
53 # # (whatever the Remote Local state is) |
42 # GPIB buffer size is 3x80 characters lines |
54 # CME = 0x20 # Command Error |
43 |
55 # EXE = 0x10 # Execution Error |
44 # HP3562A Status Byte |
56 # DDE = 0x08 # Device Dependant Error |
45 RQS = 0x40 # Request Service: when sent in response to a serial poll |
57 # QYE = 0x04 # QuerY Error (attempt to read data while Output Queue is |
46 ERR = 0x20 # ERRor: GPIB error |
58 # # empty, or data in the OQ was lost) |
47 RDY = 0x10 #ReaDY: ready to accept GPIB commands |
59 # RQC = 0x02 # Request Control: tell the CiC that the device wants to |
48 |
60 # # become the CiC |
49 |
61 # OPC = 0x01 # Operation Complete: device has completed any pending |
50 class GPIB(object): |
62 # # operation (ready to accept new commands). This bit is |
51 _retries = 15 |
63 # # generated in response to a OPC command. |
52 def __init__(self, device="/dev/ttyUSB0", baudrate=115200, timeout=0.1, |
|
53 address=0, mode=1): |
|
54 """ |
|
55 Create a new GPIB controller for the Prologix USB-GPIB device |
|
56 located on serial device 'device'. |
|
57 """ |
|
58 self._cnx = serial.Serial(port=device, baudrate=baudrate, timeout=timeout) |
|
59 self._timeout = timeout |
|
60 |
|
61 self.set_mode(mode) |
|
62 self.set_address(address) |
|
63 |
|
64 def set_address(self, address): |
|
65 """ |
|
66 Set the address of the GPIB device: |
|
67 |
|
68 - if the device is the Controller In Charge, this is the |
|
69 address of the device commands are sent to, |
|
70 |
|
71 - if the device is in GPIB_DEVICE mode, this is its address. |
|
72 """ |
|
73 self._set_cmd('addr', address) |
|
74 self._adress = address |
|
75 |
|
76 def set_mode(self, mode): |
|
77 """ |
|
78 Set GPIB device mode to 'mode': |
|
79 |
|
80 - GPIB_CONTROLLER: set the device as the Controller In Charge |
|
81 on the GPIB bus |
|
82 |
|
83 - GPIB_DEVICE: set the device as a standard GPIB device on the |
|
84 bus. |
|
85 """ |
|
86 self._set_cmd('mode', mode) |
|
87 self._mode = mode |
|
88 |
|
89 def set_controler(self): |
|
90 """ |
|
91 Set GPIB device the Controller In Charge on the GPIB bus. |
|
92 """ |
|
93 self.set_mode(1) |
|
94 |
|
95 def set_device(self): |
|
96 """ |
|
97 Set the GPIB device as a simple device on the GPIB bus. |
|
98 """ |
|
99 self.set_mode(0) |
|
100 |
|
101 def send_command(self, cmd): |
|
102 """ |
|
103 Send the specified GPIB command on the bus (must be the CIC), |
|
104 and read the answer. |
|
105 """ |
|
106 assert self._mode == 1 |
|
107 self._cnx.write(cmd+'\r') |
|
108 time.sleep(self._timeout) # required? |
|
109 ret = self._cnx.readlines() |
|
110 return ''.join(ret) |
|
111 |
|
112 def check_srq(self): |
|
113 """ |
|
114 Check the SRQ line |
|
115 """ |
|
116 assert self._mode == 1, "must be the Controller In Charge" |
|
117 self._cnx.write('++srq\r') |
|
118 ret = self._cnx.readline().strip() |
|
119 if ret: |
|
120 return bool(int(ret)) |
|
121 return None |
|
122 |
|
123 def poll(self): |
|
124 """ |
|
125 Poll every address, and return a dictionnary |
|
126 {add: status, ...} |
|
127 """ |
|
128 assert self._mode == 1, "must be the Controller In Charge" |
|
129 dico = {} |
|
130 for add in range(31): |
|
131 self._cnx.write('++spoll %d\r'%i) |
|
132 ret = self._cnx.readline().strip() |
|
133 if ret: |
|
134 dico[i] = int(ret) |
|
135 return dico |
|
136 |
64 |
137 def _read(self): |
|
138 for i in range(self._retries): |
|
139 rdata = self._cnx.readline() |
|
140 if rdata.strip() != "": |
|
141 break |
|
142 time.sleep(self._timeout) |
|
143 return rdata |
|
144 |
|
145 def _set_cmd(self, cmd, value): |
|
146 self._cnx.write('++%s %d\r'%(cmd, value)) |
|
147 self._cnx.write('++%s\r'%(cmd)) |
|
148 rval = self._read().strip() |
|
149 if not rval.isdigit() or int(rval) != value: |
|
150 raise ConnectionError("Can't set GPIB %s to %s [ret=%s]"%(cmd, value, repr(rval))) |
|
151 |
|