gpib.cpp
1 /***************************************************************************
2  Copyright (C) 2002-2015 Kentaro Kitagawa
3  kitagawa@phys.s.u-tokyo.ac.jp
4 
5  This program is free software; you can redistribute it and/or
6  modify it under the terms of the GNU Library General Public
7  License as published by the Free Software Foundation; either
8  version 2 of the License, or (at your option) any later version.
9 
10  You should have received a copy of the GNU Library General
11  Public License and a list of authors along with this program;
12  see the files COPYING and AUTHORS.
13 ***************************************************************************/
14 #include "gpib.h"
15 
16 #include <errno.h>
17 
18 #include <string.h>
19 
20 #include "support.h"
21 
22 #ifdef HAVE_LINUX_GPIB
23 #define __inline__ __inline
24 #include <gpib/ib.h>
25 #endif
26 
27 #ifdef HAVE_NI488
28  #if defined WINDOWS || defined __WIN32__ || defined _WIN32
29  #define DIRECT_ENTRY_NI488
30  static int load_ni4882dll();
31  static int free_ni4882dll();
32  #endif // WINDOWS || __WIN32__ || defined _WIN32
33  inline int strerror_r(int err, char *buf, size_t len) {return strerror_s(buf,len,err); }
34  #include <ni4882.h>
35  extern "C" {
36  static void (__stdcall *pEnableRemote)(int, const Addr4882_t*);
37  #define EnableRemote (*pEnableRemote)
38  static void (__stdcall *pSendIFC)(int);
39  #define SendIFC (*pSendIFC)
40  static unsigned long(__stdcall *pThreadIbsta)(void);
41  #define ThreadIbsta() (pThreadIbsta())
42  static unsigned long(__stdcall *pThreadIberr)(void);
43  #define ThreadIberr() (pThreadIberr())
44  static unsigned long(__stdcall *pThreadIbcnt)(void);
45  #define ThreadIbcnt() (pThreadIbcnt())
46  unsigned long (__stdcall *pibclr)(int);
47  #define ibclr (*pibclr)
48  unsigned long (__stdcall *pibconfig)(int, int, int );
49  #define ibconfig (*pibconfig)
50  static int(__stdcall *pibdev)(int, int, int, int, int, int);
51  #define ibdev (*pibdev)
52  static int(__stdcall *pibonl)(int, int);
53  #define ibonl (*pibonl)
54  unsigned long (__stdcall *pibrd)(int, void *, size_t);
55  #define ibrd (*pibrd)
56  unsigned long (__stdcall *pibrsp)(int, char *);
57  #define ibrsp (*pibrsp)
58  unsigned long (__stdcall *pibwrt)(int, const void *, size_t);
59  #define ibwrt (*pibwrt)
60  }
61 #endif //HAVE_NI488
62 
63 #define MIN_BUF_SIZE 1024
64 
65 #ifdef GPIB_NI
66 
67 int
68 XNIGPIBPort::s_cntOpened = 0;
69 XMutex
70 XNIGPIBPort::s_lock;
71 
72 XString
73 XNIGPIBPort::gpibStatus(const XString &msg) {
74  XString sta, err, cntl;
75  if(ThreadIbsta() & DCAS) sta += "DCAS ";
76  if(ThreadIbsta() & DTAS) sta += "DTAS ";
77  if(ThreadIbsta() & LACS) sta += "LACS ";
78  if(ThreadIbsta() & TACS) sta += "TACS ";
79  if(ThreadIbsta() & ATN) sta += "ATN ";
80  if(ThreadIbsta() & CIC) sta += "CIC ";
81  if(ThreadIbsta() & REM) sta += "REM ";
82  if(ThreadIbsta() & LOK) sta += "LOK ";
83  if(ThreadIbsta() & CMPL) sta += "CMPL ";
84 #ifdef HAVE_LINUX_GPIB
85  if(ThreadIbsta() & EVENT) sta += "EVENT ";
86  if(ThreadIbsta() & SPOLL) sta += "SPOLL ";
87 #endif //HAVE_LINUX_GPIB
88  if(ThreadIbsta() & RQS) sta += "RQSE ";
89  if(ThreadIbsta() & SRQI) sta += "SRQI ";
90  if(ThreadIbsta() & END) sta += "END ";
91  if(ThreadIbsta() & TIMO) sta += "TIMO ";
92  if(ThreadIbsta() & ERR) sta += "ERR ";
93  switch(ThreadIberr()) {
94  case EDVR: err = "EDVR"; break;
95  case ECIC: err = "ECIC"; break;
96  case ENOL: err = "ENOL"; break;
97  case EADR: err = "EADR"; break;
98  case EARG: err = "EARG"; break;
99  case ESAC: err = "ESAC"; break;
100  case EABO: err = "EABO"; break;
101  case ENEB: err = "ENEB"; break;
102  case EDMA: err = "EDMA"; break;
103  case EOIP: err = "EOIP"; break;
104  case ECAP: err = "ECAP"; break;
105  case EFSO: err = "EFSO"; break;
106  case EBUS: err = "EBUS"; break;
107  case ESTB: err = "ESTB"; break;
108  case ESRQ: err = "ESRQ"; break;
109  case ETAB: err = "ETAB"; break;
110  default: err = formatString("%u",(unsigned int)ThreadIberr()); break;
111  }
112  if((ThreadIberr() == EDVR) || (ThreadIberr() == EFSO)) {
113  char buf[256];
114  #ifdef __linux__
115  char *s = strerror_r(ThreadIbcntl(), buf, sizeof(buf));
116  cntl = formatString("%d",(int)ThreadIbcntl()) + " " + s;
117  #else
118  if(strerror_r(ThreadIbcntl(), buf, sizeof(buf))) {
119  cntl = formatString("%d",(int)ThreadIbcntl());
120  }
121  else {
122  cntl = formatString("%d",(int)ThreadIbcntl()) + " " + buf;
123  }
124  #endif
125  errno = 0;
126  }
127  else {
128  cntl = formatString("%d",(int)ThreadIbcntl());
129  }
130  return QString("GPIB %1: addr %2, sta %3, err %4, cntl %5")
131  .arg(msg)
132  .arg(m_address)
133  .arg(sta)
134  .arg(err)
135  .arg(cntl);
136 }
137 
138 XNIGPIBPort::XNIGPIBPort(XCharInterface *interface)
139  : XPort(interface), m_ud(-1) {
140 
141 }
142 XNIGPIBPort::~XNIGPIBPort() {
143  try {
144  gpib_close();
145  }
146  catch(...) {
147  }
148 }
149 
150 void
151 XNIGPIBPort::gpib_reset() throw (XInterface::XCommError &) {
152  gpib_close();
153  msecsleep(100);
154  gpib_open();
155 }
156 
157 void
158 XNIGPIBPort::open(const XCharInterface *pInterface) throw (XInterface::XCommError &) {
159  Snapshot shot( *pInterface);
160  m_address = shot[ *pInterface->address()];
161  gpib_open();
162  m_gpibWaitBeforeWrite = pInterface->gpibWaitBeforeWrite();
163  m_gpibWaitBeforeRead = pInterface->gpibWaitBeforeRead();
164  m_gpibWaitBeforeSPoll = pInterface->gpibWaitBeforeSPoll();
165  m_bGPIBUseSerialPollOnWrite = pInterface->gpibUseSerialPollOnWrite();
166  m_bGPIBUseSerialPollOnRead = pInterface->gpibUseSerialPollOnRead();
167  m_gpibMAVbit = pInterface->gpibMAVbit();
168 }
169 
170 void
171 XNIGPIBPort::gpib_open() throw (XInterface::XCommError &) {
172  int port = atoi(portString().c_str());
173  {
174  XScopedLock<XMutex> lock(s_lock);
175  if(s_cntOpened == 0) {
176 #ifdef DIRECT_ENTRY_NI488
177  if(load_ni4882dll())
178  throw XInterface::XCommError(i18n("Loading NI4882.DLL has failed."), __FILE__, __LINE__);
179 #endif
180  dbgPrint(i18n("GPIB: Sending IFC"));
181  SendIFC(port);
182  msecsleep(100);
183  }
184  s_cntOpened++;
185  }
186 
187  Addr4882_t addrtbl[2];
188  int ceos = 0;
189  if(eos().length()) {
190  ceos = 0x1400 + eos()[eos().length() - 1];
191  }
192  m_ud = ibdev(port,
193  m_address, 0, T3s, 1, ceos);
194  if(m_ud < 0) {
196  gpibStatus(i18n("opening gpib device faild")), __FILE__, __LINE__);
197  }
198  ibclr(m_ud);
199  ibeos(m_ud, ceos);
200  addrtbl[0] = m_address;
201  addrtbl[1] = NOADDR;
202  EnableRemote(port, addrtbl);
203 
204 }
205 void
206 XNIGPIBPort::gpib_close() throw (XInterface::XCommError &) {
207  if(m_ud >= 0) ibonl(m_ud, 0);
208  m_ud=-1;
209  {
210  XScopedLock<XMutex> lock(s_lock);
211  s_cntOpened--;
212 #ifdef DIRECT_ENTRY_NI488
213  if(s_cntOpened == 0)
214  free_ni4882dll();
215 #endif
216  }
217 }
218 
219 void
220 XNIGPIBPort::send(const char *str) throw (XInterface::XCommError &) {
221  XString buf(str);
222  buf += eos();
223  assert(buf.length() == strlen(str) + eos().length());
224  this->write(buf.c_str(), buf.length());
225 }
226 void
227 XNIGPIBPort::write(const char *sendbuf, int size) throw (XInterface::XCommError &) {
228  gpib_spoll_before_write();
229 
230  for(int i = 0; ; i++) {
231  msecsleep(m_gpibWaitBeforeWrite);
232  int ret = ibwrt(m_ud, const_cast<char*>(sendbuf), size);
233  if(ret & ERR)
234  {
235  switch(ThreadIberr()) {
236  case EDVR:
237  case EFSO:
238  if(i < 2) {
239  dbgPrint("EDVR/EFSO, try to continue");
240  msecsleep(10 * i + 10);
241  continue;
242  }
244  gpibStatus(i18n("too many EDVR/EFSO")), __FILE__, __LINE__);
245  }
246  gErrPrint(gpibStatus(i18n("ibwrt err")));
247  gpib_reset();
248  if(i < 2) {
249  gErrPrint(i18n("try to continue"));
250  continue;
251  }
252  throw XInterface::XCommError(gpibStatus(""), __FILE__, __LINE__);
253  }
254  size -= ThreadIbcntl();
255  if((size == 0) && (ret & CMPL)) {
256  //NI's ibwrt() terminates w/o END.
257  break;
258  }
259  sendbuf += ThreadIbcntl();
260  if(ret & CMPL) {
261  dbgPrint("ibwrt interrupted.");
262  continue;
263  }
264  gErrPrint(gpibStatus(i18n("ibwrt terminated without CMPL")));
265  }
266 }
267 void
268 XNIGPIBPort::receive() throw (XInterface::XCommError &) {
269  unsigned int len = gpib_receive(MIN_BUF_SIZE, 1000000uL);
270  buffer().resize(len + 1);
271  buffer()[len] = '\0';
272 }
273 void
274 XNIGPIBPort::receive(unsigned int length) throw (XInterface::XCommError &) {
275  unsigned int len = gpib_receive(length, length);
276  buffer().resize(len);
277 }
278 
279 unsigned int
280 XNIGPIBPort::gpib_receive(unsigned int est_length, unsigned int max_length)
281  throw (XInterface::XCommError &) {
282 
283  gpib_spoll_before_read();
284  int len = 0;
285  for(int i = 0; ; i++) {
286  unsigned int buf_size = std::min(max_length, len + est_length);
287  if(buffer().size() < buf_size)
288  buffer().resize(buf_size);
289  msecsleep(m_gpibWaitBeforeRead);
290  int ret = ibrd(m_ud, &buffer()[len], buf_size - len);
291  if(ret & ERR) {
292  switch(ThreadIberr()) {
293  case EDVR:
294  case EFSO:
295  if(i < 2) {
296  dbgPrint("EDVR/EFSO, try to continue");
297  msecsleep(10 * i + 10);
298  continue;
299  }
301  gpibStatus(i18n("too many EDVR/EFSO")), __FILE__, __LINE__);
302  }
303  gErrPrint(gpibStatus(i18n("ibrd err")));
304 // gpib_reset();
305  if(i < 2) {
306  gErrPrint(i18n("try to continue"));
307  continue;
308  }
309  throw XInterface::XCommError(gpibStatus(""), __FILE__, __LINE__);
310  }
311  if(ThreadIbcntl() > buf_size - len)
312  throw XInterface::XCommError(gpibStatus(i18n("libgpib error.")), __FILE__, __LINE__);
313  len += ThreadIbcntl();
314  if((ret & END) && (ret & CMPL)) {
315  break;
316  }
317  if(ret & CMPL) {
318  if(len == max_length)
319  break;
320  dbgPrint("ibrd terminated without END");
321  continue;
322  }
323  gErrPrint(gpibStatus(i18n("ibrd terminated without CMPL")));
324  }
325  return len;
326 }
327 void
328 XNIGPIBPort::gpib_spoll_before_read() throw (XInterface::XCommError &) {
329  if(m_bGPIBUseSerialPollOnRead) {
330  for(int i = 0; ; i++) {
331  if(i > 30) {
333  gpibStatus(i18n("too many spoll timeouts")), __FILE__, __LINE__);
334  }
335  msecsleep(m_gpibWaitBeforeSPoll);
336  unsigned char spr;
337  int ret = ibrsp(m_ud,(char*)&spr);
338  if(ret & ERR) {
339  switch(ThreadIberr()) {
340  case EDVR:
341  case EFSO:
342  dbgPrint("EDVR/EFSO, try to continue");
343  msecsleep(10 * i + 10);
344  continue;
345  }
346  gErrPrint(gpibStatus(i18n("ibrsp err")));
347  gpib_reset();
348  throw XInterface::XCommError(gpibStatus(i18n("ibrsp failed")), __FILE__, __LINE__);
349  }
350  if(((spr & m_gpibMAVbit) == 0)) {
351  //MAV isn't detected
352  msecsleep(10 * i + 10);
353  continue;
354  }
355 
356  break;
357  }
358  }
359 }
360 void
361 XNIGPIBPort::gpib_spoll_before_write() throw (XInterface::XCommError &) {
362  if(m_bGPIBUseSerialPollOnWrite) {
363  for(int i = 0; ; i++) {
364  if(i > 10) {
366  gpibStatus(i18n("too many spoll timeouts")), __FILE__, __LINE__);
367  }
368  msecsleep(m_gpibWaitBeforeSPoll);
369  unsigned char spr;
370  int ret = ibrsp(m_ud,(char*)&spr);
371  if(ret & ERR) {
372  switch(ThreadIberr()) {
373  case EDVR:
374  case EFSO:
375  dbgPrint("EDVR/EFSO, try to continue");
376  msecsleep(10 * i + 10);
377  continue;
378  }
379  gErrPrint(gpibStatus(i18n("ibrsp err")));
380  throw XInterface::XCommError(gpibStatus(i18n("ibrsp failed")), __FILE__, __LINE__);
381  }
382  if((spr & m_gpibMAVbit)) {
383  //MAV detected
384  if(i < 2) {
385  msecsleep(5*i + 5);
386  continue;
387  }
388  gErrPrint(gpibStatus(i18n("ibrd before ibwrt asserted")));
389 
390  // clear device's buffer
391  gpib_receive(MIN_BUF_SIZE, 1000000uL);
392  break;
393  }
394 
395  break;
396  }
397  }
398 }
399 
400 #if defined DIRECT_ENTRY_NI488
401 #include <windows.h>
402 
403 static HINSTANCE ni4882dll = NULL;
404 
405 static int load_ni4882dll() {
406  ni4882dll=LoadLibrary(L"NI4882.DLL");
407  if(ni4882dll == NULL) {
408  return -1;
409  }
410 
411  pEnableRemote = (void (__stdcall *)
412  (int, const Addr4882_t*))GetProcAddress(ni4882dll, "EnableRemote");
413  pSendIFC = (void (__stdcall *)(int))GetProcAddress(ni4882dll, "SendIFC");
414  pThreadIbsta = (unsigned long (__stdcall *)(void))GetProcAddress(ni4882dll, "ThreadIbsta");
415  pThreadIberr = (unsigned long (__stdcall *)(void))GetProcAddress(ni4882dll, "ThreadIberr");
416  pThreadIbcnt = (unsigned long (__stdcall *)(void))GetProcAddress(ni4882dll, "ThreadIbcnt");
417  pibclr = (unsigned long (__stdcall *)(int)) GetProcAddress(ni4882dll, "ibclr");
418  pibconfig = (unsigned long (__stdcall *)
419  (int, int, int)) GetProcAddress(ni4882dll, "ibconfig");
420  pibdev = (int (__stdcall *)
421  (int, int, int, int, int, int)) GetProcAddress(ni4882dll, "ibdev");
422  pibonl = (int (__stdcall *)(int, int)) GetProcAddress(ni4882dll, "ibonl");
423  pibrd = (unsigned long (__stdcall *)
424  (int, void *, size_t)) GetProcAddress(ni4882dll, "ibrd");
425  pibrsp = (unsigned long (__stdcall *)
426  (int, char*)) GetProcAddress(ni4882dll, "ibrsp");
427  pibwrt = (unsigned long (__stdcall *)
428  (int, const void *, size_t)) GetProcAddress(ni4882dll, "ibwrt");
429 
430  if((pEnableRemote == NULL) || (pSendIFC == NULL) ||
431  (pThreadIbsta == NULL) || (pThreadIberr == NULL) || (pThreadIbcnt == NULL) ||
432  (pibclr == NULL) || (pibconfig == NULL) || (pibdev == NULL) || (pibonl == NULL) ||
433  (pibrd == NULL) || (pibrsp == NULL) || (pibwrt == NULL)) {
434  free_ni4882dll();
435  ni4882dll = NULL;
436  return -1;
437  }
438  return 0;
439 }
440 
441 static int free_ni4882dll() {
442  if(ni4882dll != NULL)
443  FreeLibrary(ni4882dll);
444  return 0;
445 }
446 #endif // DIRECT_ENTRY_NI488
447 
448 
449 #endif /*GPIB_NI*/

Generated for KAME4 by  doxygen 1.8.3