1 /////////////////////////////////////////////////////////////////////////////
2 // Name:        gpibx.cpp
3 // Purpose:
4 // Author:      Joachim Buermann
5 // Id:          $Id: gpibx.cpp,v 1.1.1.1 2004/11/24 10:30:11 jb Exp $
6 // Copyright:   (c) 2001,2004 Joachim Buermann
7 // Licence:     wxWindows licence
8 /////////////////////////////////////////////////////////////////////////////
9 
10 #include "ctb-0.16/gpib.h"
11 #include "ctb-0.16/timer.h"
12 #include <stdio.h>
13 #include <string.h>
14 #ifdef WIN32
15 # include "ctb-0.16/win32/gpib-32.h"
16 #if _MSC_VER < 1900
17 # define snprintf _snprintf
18 #endif
19 #elif __GNUG__
20 # include <gpib/ib.h>
21 #endif
22 
23 namespace ctb {
24 
25     const char* GPIB1 = "gpib1";
26     const char* GPIB2 = "gpib2";
27 
28     struct gpibErr_t {
29 	   int m_errno;
30 	   const char* m_notation;
31 	   const char* m_description;
32     };
33 
34     static gpibErr_t gpibErrors[] = {
35 	   {0,"EDVR","DOS Error"},
36 	   {1,"ECIC","Specified GPIB Interface Board is Not Active Controller"},
37 	   {2,"ENOL","No present listing device"},
38 	   {3,"EADR","GPIB Board has not been addressed properly"},
39 	   {4,"EARG","Invalid argument"},
40 	   {5,"ESAC","Specified GPIB Interface Board is not System Controller"},
41 	   {6,"EABO","I/O operation aborted (time-out)"},
42 	   {7,"ENEB","Non-existent GPIB board"},
43 	   {10,"EOIP","Routine not allowed during asynchronous I/O operation"},
44 	   {11,"ECAP","No capability for operation"},
45 	   {12,"EFSO","File System Error"},
46 	   {14,"EBUS","Command byte transfer error"},
47 	   {15,"ESTB","Serial poll status byte lost"},
48 	   {16,"ESQR","SRQ stuck in ON position"},
49 	   {20,"ETAB","Table problem"},
50 	   {247,"EINT","No interrupt configured on board"},
51 	   {248,"EWMD","Windows is not in Enhanced mode"},
52 	   {249,"EVDD","GPIB driver is not installed"},
53 	   {250,"EOVR","Buffer Overflow"},
54 	   {251,"ESML","Two library calls running simultaneously"},
55 	   {252,"ECFG","Board type does not match GPIB.CFG"},
56 	   {253,"ETMR","No Windows timers available"},
57 	   {254,"ESLC","No Windows selectors available"},
58 	   {255,"EBRK","Control-Break pressed"}
59     };
60 
GetSettings()61     char* Gpib_DCS::GetSettings()
62     {
63 	   const char* to[] = {
64 		  "None","10us","30us","100us","300us","1ms","3ms","10ms","30ms",
65 		  "100ms","300ms","1s","3s","10s","30s","100s","300s","1000s"
66 	   };
67 	   memset(m_buf,0,sizeof(m_buf));
68 	   snprintf(m_buf,sizeof(m_buf)-1,"Adr: (%i,%i) to:%s",
69 			  m_address1,
70 			  m_address2,
71 			  to[m_timeout]);
72 	   return m_buf;
73     };
74 
CloseDevice()75     int GpibDevice::CloseDevice()
76     {
77 	   if(m_hd != -1) {
78 		  // goto local...
79 		  ibloc(m_hd);
80 		  // ...and switch device offline
81 		  ibonl(m_hd,0);
82 		  m_hd = -1;
83 		  m_board = -1;
84 	   }
85 	   return 0;
86     };
87 
GetErrorString(int error,bool detailed)88     const char* GpibDevice::GetErrorString(int error,bool detailed)
89     {
90 	   for(size_t i=0;i<(sizeof(gpibErrors)/sizeof(gpibErr_t));i++) {
91 		  if(gpibErrors[i].m_errno == error) {
92 			 if(detailed) {
93 				return gpibErrors[i].m_description;
94 			 }
95 			 else {
96 				return gpibErrors[i].m_notation;
97 			 }
98 		  }
99 	   }
100 	   return 0;
101     };
102 
103 // This is only for internal usage
Ibrd(char * buf,size_t len)104     int GpibDevice::Ibrd(char* buf,size_t len)
105     {
106 	   return ibrd(m_hd,buf,len);
107     };
108 
109 // This is only for internal usage
Ibwrt(char * buf,size_t len)110     int GpibDevice::Ibwrt(char* buf,size_t len)
111     {
112 	   return ibwrt(m_hd,buf,len);
113     };
114 
Ioctl(int cmd,void * args)115     int GpibDevice::Ioctl(int cmd,void* args)
116     {
117 	   switch(cmd) {
118 	   case CTB_RESET:
119 		  if(m_hd >= 0) {
120 			 ibclr(m_hd);
121 			 return 0;
122 		  }
123 		  return -1;
124 	   case CTB_GPIB_GETRSP: {
125 		  char spr = 0;
126 		  if(m_hd >= 0) {
127 			 ibrsp(m_hd,&spr);
128 			 *(int*)args = (int)spr;
129 			 return 0;
130 		  }
131 		  return 1; }
132 	   case CTB_GPIB_GETSTA:
133 		  *(int*)args = m_state;
134 		  return 0;
135 	   case CTB_GPIB_GETERR:
136 		  *(int*)args = m_error;
137 		  return 0;
138 	   case CTB_GPIB_GETLINES: {
139 		  short state = 0;
140 		  if(m_hd >= 0) {
141 			 iblines(m_board,&state);
142 			 *(int*)args = (int)state;
143 			 return 0;
144 		  }
145 		  return -1; }
146 	   case CTB_GPIB_SETTIMEOUT: {
147 		  if(m_hd >= 0) {
148 			 GpibTimeout timeout;
149 			 unsigned long to = *(unsigned long*)args;
150 			 // convert the timeout in ms (given by args) into the
151 			 // traditional NI-488.2 timeout period
152 			 if(to > 1000000) timeout = GpibTimeout1000s;
153 			 else if(to >= 300000) timeout = GpibTimeout300s;
154 			 else if(to >= 100000) timeout = GpibTimeout100s;
155 			 else if(to >= 30000) timeout = GpibTimeout30s;
156 			 else if(to >= 10000) timeout = GpibTimeout10s;
157 			 else if(to >= 3000) timeout = GpibTimeout3s;
158 			 else if(to >= 1000) timeout = GpibTimeout1s;
159 			 else if(to >= 300) timeout = GpibTimeout300ms;
160 			 else if(to >= 100) timeout = GpibTimeout100ms;
161 			 else if(to >= 30) timeout = GpibTimeout30ms;
162 			 else if(to >= 10) timeout = GpibTimeout10ms;
163 			 else if(to >= 3) timeout = GpibTimeout3ms;
164 			 else if(to >= 1) timeout = GpibTimeout1ms;
165 			 else timeout = GpibTimeoutNone;
166 			 ibtmo(m_hd,timeout);
167 			 return 0;
168 		  }
169 		  return -1; }
170 	   case CTB_GPIB_GTL:
171 		  // Forces the specified device to go to local program mode
172 		  if(m_hd >= 0) {
173 			 ibloc(m_hd);
174 			 return 0;
175 		  }
176 		  return -1;
177 	   case CTB_GPIB_REN:
178 		  // This routine can only be used if the specified GPIB
179 		  // Interface Board is the System Controller.
180 		  // Remember that even though the REN line is asserted,
181 		  // the device(s) will not be put into remote state until is
182 		  // addressed to listen by the Active Controller
183 		  if(m_hd) {
184 			 char adr = (char)m_dcs.m_address1;
185 			 ibsre(m_board,1);
186 			 ibcmd(m_board,&adr,1);
187 			 return 0;
188 		  }
189 		  return -1;
190 	   case CTB_GPIB_RESET_BUS:
191 		  ibsic(m_board);
192 		  return 0;
193 	   case CTB_GPIB_GET_EOS_CHAR:
194 		  if( m_hd ) {
195 			 *(int*)args = (int)m_dcs.m_eosChar;
196 			 return 0;
197 		  }
198 		  return -1;
199 	   case CTB_GPIB_SET_EOS_CHAR:
200 #ifdef __GNUG__
201 		  // FIXME!
202 		  // Doesn't work with linux-gpib-3.2.08. All EOS beside 0x00
203 		  // are blocking during sending data to the device. (Look at
204 		  // function my_ibwrt in linux-gpib-3.2.08/lib/ibWrt.c
205 		  if( m_hd ) {
206 			 m_dcs.m_eosChar = (char)*(int*)args;
207 			 ibeos(m_hd,(m_dcs.m_eosMode << 8) | m_dcs.m_eosChar);
208 			 return 0;
209 		  }
210 #endif
211 		  return -1;
212 	   case CTB_GPIB_GET_EOS_MODE:
213 		  if( m_hd ) {
214 			 *(int*)args = (int)m_dcs.m_eosMode;
215 			 return 0;
216 		  }
217 		  return -1;
218 	   case CTB_GPIB_SET_EOS_MODE:
219 		  if( m_hd ) {
220 			 m_dcs.m_eosMode = (char)*(int*)args;
221 			 ibeos(m_hd,(m_dcs.m_eosMode << 8) | m_dcs.m_eosChar);
222 			 return 0;
223 		  }
224 		  return -1;
225 	   }
226 	   // error or unknown command
227 	   return -1;
228     };
229 
FindListeners(int board)230     int GpibDevice::FindListeners(int board)
231     {
232 	   int listeners = 0;
233 	   if((unsigned int)board > 1) {
234 		  return -1;
235 	   }
236 	   // reset the GPIB, otherwise no connected device is found (linux)
237 	   SendIFC(board);
238 	   // list of primary addresses to searching for. Must be terminated
239 	   // with NOADDR.
240 	   Addr4882_t addrlist[31];
241 	   // The range of valid addresses is 1...30, 0 is reservated by the
242 	   // controller, 31 is not valid
243 	   for(int i = 0;i < 30; i++) addrlist[i] = (Addr4882_t) i + 1;
244 	   addrlist[30] = NOADDR;
245 	   // place to store the results
246 	   Addr4882_t results[31];
247 	   memset(results,0,sizeof(results));
248 	   FindLstn(board, addrlist, results, 31);
249 	   if(ibsta & ERR) {
250 		  return -1;
251 	   }
252 	   for(int i=0;i<=30;i++) {
253 		  if(results[i]) {
254 			 listeners |= 1 << results[i];
255 		  }
256 	   }
257 	   return listeners;
258     };
259 
Open(const char * devname,int address)260     int GpibDevice::Open( const char* devname, int address )
261     {
262 	   m_dcs.m_address1 = address;
263 
264 	   return OpenDevice( devname, &m_dcs );
265     }
266 
267 
OpenDevice(const char * devname,void * dcs)268     int GpibDevice::OpenDevice(const char* devname, void* dcs)
269     {
270 	   // if dcs isn't NULL, type cast
271 	   if(dcs) m_dcs = *(Gpib_DCS*)dcs;
272 
273 	   if(strncmp(devname,"gpib1",5) == 0) m_board = 0;
274 	   else if(strncmp(devname,"gpib2",5) == 0) m_board = 1;
275 	   if(m_board < 0) {
276 		  return -1;
277 	   }
278 	   // check for a valid timeout
279 	   if((unsigned int)m_dcs.m_timeout > GpibTimeout1000s) {
280 		  m_dcs.m_timeout = GpibTimeout10us;
281 	   }
282 
283 	   m_hd = ibdev(m_board,
284 				 m_dcs.m_address1,
285 				 m_dcs.m_address2,
286 				 m_dcs.m_timeout,
287 				 m_dcs.m_eot,
288 #ifdef __GNUG__
289 				 // FIXME!
290 				 // linux-gpib-3.2.08 doesn't work with any EOS (blocks).
291 				 // Because we always has to add an EOS on the message
292 				 // (independent of the m_eosChar setting), we can ignore it!
293 				 0
294 #else
295 				 (m_dcs.m_eosMode << 8) | m_dcs.m_eosChar
296 #endif
297 		  );
298 	   if(m_hd < 0) {
299 		  // no gpib controller installed (not found)
300 		  return -2;
301 	   }
302 	   // test for a connected listener (device with given address)
303 	   short int listen = 0;
304 	   ibln(m_board,m_dcs.m_address1,NO_SAD,&listen);
305 	   if(!listen) {
306 		  // no listener at the given address
307 		  CloseDevice();
308 		  return -3;
309 	   }
310 	   // reset device
311 	   ibclr(m_hd);
312 	   // save state, error and count
313 	   m_state = ThreadIbsta();
314 	   m_count = ThreadIbcnt();
315 	   m_error = ThreadIberr();
316 	   // no error
317 	   return 0;
318     };
319 
Read(char * buf,size_t len)320     int GpibDevice::Read(char* buf,size_t len)
321     {
322 	   // if something is in the fifo, first read that
323 	   if(m_fifo->items() > 0) {
324 		  return m_fifo->read(buf,len);
325 	   }
326 	   m_state = ibrd(m_hd,buf,len);
327 	   m_error = ThreadIberr();
328 	   m_count = ThreadIbcnt();
329 	   return m_count;
330     };
331 
Write(char * buf,size_t len)332     int GpibDevice::Write(char* buf,size_t len)
333     {
334 	   m_state = ibwrt(m_hd,buf,len);
335 	   m_error = ThreadIberr();
336 	   m_count = ThreadIbcnt();
337 	   return m_count;
338     };
339 
340 } // namespace ctb
341