C++ Instrument Catalog
VISAInstrument.cpp
Go to the documentation of this file.
1 
5 // Personal includes
6 #include "VISAInstrument.h"
7 #include "OSDefines.h"
8 #include "Helpers.h"
9 
10 // Standard includes
11 #include <string>
12 #include <cstring>
13 
14 // Constants
15 #define VI_STATUS_DESC_MAX_LEN 256
16 // Definitions
17 #define READ_STB_WORKAROUND_POLL_PERIOD_MS 10
18 #define ACTIVATE_READ_STB_WORKAROUND 1
19 
20 // Definitions
21 #define DEBUG_MTL_VISA_INSTRUMENT 0
22 #define DEBUG_MTL_VISA_INSTRUMENT_ERRORS_ONLY 0
23 #if (defined(_DEBUG) && defined(DEBUG_MTL_VISA_INSTRUMENT) && DEBUG_MTL_VISA_INSTRUMENT)
24 #if (defined(DEBUG_MTL_VISA_INSTRUMENT_ERRORS_ONLY) && DEBUG_MTL_VISA_INSTRUMENT_ERRORS_ONLY)
25 #define MTL_VISA_INSTRUMENT_DEBUG_COUT(__X__)
26 #else
27 #define MTL_VISA_INSTRUMENT_DEBUG_COUT(__X__) COUT(__X__)
28 #endif
29 #define MTL_VISA_INSTRUMENT_DEBUG_CERR(__X__) CERR(__X__)
30 #else
31 #define MTL_VISA_INSTRUMENT_DEBUG_COUT(__X__)
32 #define MTL_VISA_INSTRUMENT_DEBUG_CERR(__X__)
33 #endif
34 
35 using namespace MTL::Instrument;
36 
37 //----------------------------------------------------------------------//
38 // Error Handling //
39 //----------------------------------------------------------------------//
40 std::string MTL::Instrument::StatusDescription(ViSession Session, ViStatus Status)
41 {
42  // According to the NI-VISA Programmer Reference Manual:
43  // "If the string cannot be interpreted, the operation returns the warning
44  // code VI_WARN_UNKNOWN_STATUS. However, the output string desc is valid
45  // regardless of the status return value."
46  // So, regardless of the return error code, we return the description.
47  static ViChar Desc[VI_STATUS_DESC_MAX_LEN];
48  viStatusDesc(Session, Status, Desc);
49  return std::string(Desc);
50 }
51 #if (defined(DEBUG_MTL_VISA_INSTRUMENT) && DEBUG_MTL_VISA_INSTRUMENT)
52 static void l_DebugCheckStatus(ViSession Session, ViStatus Status)
53 {
54  if (VI_SUCCESS != Status)
55  {
56  MTL_VISA_INSTRUMENT_DEBUG_CERR(StatusDescription(Session, Status) << std::endl);
57  }
58 }
59 #else
60 #define l_DebugCheckStatus(__X__, __Y__)
61 #endif
62 
63 //----------------------------------------------------------------------//
64 // Resource Manager //
65 //----------------------------------------------------------------------//
66 //------------------------------------------//
67 // Constructors / destructors
69  : m_DefaultRM(0), m_Status(VI_SUCCESS)
70 {
71 
72 }
74 {
75  CLockGuard<CMutex> l_LockGuard(m_Lock);
76 
77  viClose(m_DefaultRM);
78 }
79 
80 //------------------------------------------//
81 // Initialization / Info
83 {
84  MTL_VISA_INSTRUMENT_DEBUG_COUT(MTL__FUNCTION_NAME__ << std::endl);
85  CLockGuard<CMutex> l_LockGuard(m_Lock);
86 
87  try {
88  if (0 != m_DefaultRM)
89  throw VI_SUCCESS; // Already initialized
90 
91  m_Status = viOpenDefaultRM(&m_DefaultRM);
92  if (VI_SUCCESS != m_Status)
93  {
94  m_DefaultRM = static_cast<ViSession>(NULL);
95  throw m_Status;
96  }
97  }
98  catch (ViStatus & rS)
99  {
100  MTL_Unused(rS);
101  l_DebugCheckStatus(m_DefaultRM, rS);
102  return false;
103  }
104 
105  return true;
106 }
107 
109 {
110  return m_Status;
111 }
112 const ViSession & CVISAResourceManager::Session()
113 {
114  CLockGuard<CMutex> l_LockGuard(m_Lock);
115 
116  return m_DefaultRM;
117 }
118 
119 //------------------------------------------//
120 // Resource utilities
121 bool CVISAResourceManager::FindResources(CResourceList & rList, std::string Filter)
122 {
123  MTL_VISA_INSTRUMENT_DEBUG_COUT(MTL__FUNCTION_NAME__ << std::endl);
124  CLockGuard<CMutex> l_LockGuard(m_Lock);
125 
126  bool l_Ret = true;
127  rList.clear();
128  ViFindList fList;
129 
130  try
131  {
132  ViChar rsrcName[VI_FIND_BUFLEN];
133  ViUInt32 numInstrs;
134 
135  // Find all instruments
136  ViString l_Filter = const_cast<ViString>(Filter.c_str());
137  m_Status = viFindRsrc(m_DefaultRM, l_Filter, &fList, &numInstrs, rsrcName);
138  if (VI_SUCCESS != m_Status && VI_ERROR_RSRC_NFOUND != m_Status)
139  throw m_Status;
140 
141  while (numInstrs-- && m_Status == VI_SUCCESS)
142  {
143  rList.push_back(tResourceName(rsrcName));
144  m_Status = viFindNext(fList, rsrcName);
145  if (VI_SUCCESS != m_Status && VI_ERROR_RSRC_NFOUND != m_Status)
146  throw m_Status;
147  }
148  }
149  catch (ViStatus & rS)
150  {
151  switch (rS)
152  {
153  case VI_ERROR_INV_OBJECT: // The given session reference is invalid
154  case VI_ERROR_NSUP_OPER: // The given sesn does not support this operation.This operation is supported only by a Resource Manager session
155  case VI_ERROR_INV_EXPR: // Invalid expression specified for search
156  default:
157  l_DebugCheckStatus(m_DefaultRM, rS);
158  l_Ret = false;
159  break;
160 
161  case VI_SUCCESS:
162  case VI_ERROR_RSRC_NFOUND: // Specified expression does not match any devices
163  l_Ret = true;
164  break;
165  }
166  }
167 
168  viClose(fList);
169  return l_Ret;
170 }
172 {
173  MTL_VISA_INSTRUMENT_DEBUG_COUT(MTL__FUNCTION_NAME__ << std::endl);
174  CLockGuard<CMutex> l_LockGuard(m_Lock);
175 
176  bool l_Ret = true;
177  rList.clear();
178  ViFindList fList;
179 
180  try
181  {
182  ViChar rsrcName[VI_FIND_BUFLEN];
183  ViUInt32 numInstrs;
184 
185  // Find all instruments
186  ViString l_Filter = const_cast<ViString>(Filter.c_str());
187  m_Status = viFindRsrc(m_DefaultRM, l_Filter, &fList, &numInstrs, rsrcName);
188  if (VI_SUCCESS != m_Status && VI_ERROR_RSRC_NFOUND != m_Status)
189  throw m_Status;
190 
191  while (numInstrs-- && m_Status == VI_SUCCESS)
192  {
193  ViUInt16 l_Type, l_Number;
194  ViChar l_Class[100], l_ExpName[100], l_Alias[100];
195  m_Status = viParseRsrcEx(m_DefaultRM, static_cast<ViRsrc>(rsrcName), &l_Type, &l_Number, l_Class, l_ExpName, l_Alias);
196  if (VI_SUCCESS == m_Status)
197  {
198  tResourceName l_ResourceName(rsrcName);
199  VISAResourceInfo l_VISAResourceInfo( static_cast<eInterfaceType>(l_Type),
200  static_cast<tInterfaceNumber>(l_Number),
201  static_cast<VISAResourceInfo::tClass>(l_Class),
202  static_cast<VISAResourceInfo::tExpandedName>(l_ExpName),
203  static_cast<VISAResourceInfo::tAlias>(l_Alias));
204  rList.push_back(sParsedResource(l_ResourceName, l_VISAResourceInfo));
205 
206  m_Status = viFindNext(fList, rsrcName);
207  if (VI_SUCCESS != m_Status && VI_ERROR_RSRC_NFOUND != m_Status)
208  throw m_Status;
209  }
210  else if (VI_ERROR_RSRC_NFOUND != m_Status)
211  throw m_Status;
212  }
213  }
214  catch (ViStatus & rS)
215  {
216  switch (rS)
217  {
218  default:
219  l_DebugCheckStatus(m_DefaultRM, rS);
220  l_Ret = false;
221  break;
222 
223  case VI_SUCCESS:
224  case VI_ERROR_RSRC_NFOUND: // Specified expression does not match any devices
225  l_Ret = true;
226  break;
227  }
228  }
229 
230  viClose(fList);
231  return l_Ret;
232 }
234 {
235  MTL_VISA_INSTRUMENT_DEBUG_COUT(MTL__FUNCTION_NAME__ << std::endl);
236  CLockGuard<CMutex> l_LockGuard(m_Lock);
237 
238  bool l_Ret = true;
239  try
240  {
241  ViUInt16 l_Type, l_Number;
242  m_Status = viParseRsrc(m_DefaultRM, const_cast<ViRsrc>(rRsrc.c_str()), &l_Type, &l_Number);
243  if (VI_SUCCESS != m_Status)
244  throw m_Status;
245 
246  rIntfType = static_cast<eInterfaceType>(l_Type);
247  rIntfNumber = static_cast<tInterfaceNumber>(l_Number);
248  }
249 
250  catch (ViStatus & rS)
251  {
252  switch (rS)
253  {
254  case VI_SUCCESS:
255  l_Ret = true;
256  break;
257  case VI_ERROR_INV_OBJECT: // The given session reference is invalid
258  case VI_ERROR_NSUP_OPER: // The given sesn does not support this operation. For VISA, this operation is supported only by the Default Resource Manager session.
259  case VI_ERROR_INV_RSRC_NAME: // Invalid resource reference specified. Parsing error.
260  case VI_ERROR_RSRC_NFOUND: // Insufficient location information or resource not present in the system.
261  case VI_ERROR_ALLOC: // Insufficient system resources to parse the string.
262  case VI_ERROR_LIBRARY_NFOUND: // A code library required by VISA could not be located or loaded.
263  case VI_ERROR_INTF_NUM_NCONFIG: // The interface type is valid, but the specified interface number is not configured.
264  default:
265  l_DebugCheckStatus(m_DefaultRM, rS);
266  l_Ret = false;
267  break;
268  }
269  }
270 
271  return l_Ret;
272 }
274 {
275  MTL_VISA_INSTRUMENT_DEBUG_COUT(MTL__FUNCTION_NAME__ << std::endl);
276  CLockGuard<CMutex> l_LockGuard(m_Lock);
277 
278  bool l_Ret = true;
279  try
280  {
281  ViUInt16 l_Type, l_Number;
282  ViChar l_Class[100], l_ExpName[100], l_Alias[100];
283  m_Status = viParseRsrcEx(m_DefaultRM, const_cast<ViRsrc>(rRsrc.c_str()), &l_Type, &l_Number, l_Class, l_ExpName, l_Alias);
284  if (VI_SUCCESS != m_Status)
285  throw m_Status;
286  rReturnedInfo = VISAResourceInfo(
287  static_cast<eInterfaceType>(l_Type),
288  static_cast<tInterfaceNumber>(l_Number),
289  static_cast<VISAResourceInfo::tClass>(l_Class),
290  static_cast<VISAResourceInfo::tExpandedName>(l_ExpName),
291  static_cast<VISAResourceInfo::tAlias>(l_Alias));
292  }
293  catch (ViStatus & rS)
294  {
295  switch (rS)
296  {
297  case VI_SUCCESS:
298  case VI_WARN_EXT_FUNC_NIMPL: // The operation succeeded, but a lower level driver did not implement the extended functionality.
299  l_Ret = true;
300  break;
301  case VI_ERROR_INV_OBJECT: // The given session reference is invalid
302  case VI_ERROR_NSUP_OPER: // The given sesn does not support this operation. For VISA, this operation is supported only by the Default Resource Manager session.
303  case VI_ERROR_INV_RSRC_NAME: // Invalid resource reference specified. Parsing error.
304  case VI_ERROR_RSRC_NFOUND: // Insufficient location information or resource not present in the system.
305  case VI_ERROR_ALLOC: // Insufficient system resources to parse the string.
306  case VI_ERROR_LIBRARY_NFOUND: // A code library required by VISA could not be located or loaded.
307  case VI_ERROR_INTF_NUM_NCONFIG: // The interface type is valid, but the specified interface number is not configured.
308  default:
309  l_DebugCheckStatus(m_DefaultRM, rS);
310  l_Ret = false;
311  break;
312  }
313  }
314  return l_Ret;
315 }
316 
317 //----------------------------------------------------------------------//
318 // Instrument //
319 //----------------------------------------------------------------------//
320 //------------------------------------------//
321 // Constructors / destructors
323  : m_rRrsrcMan(rRM), m_Rsrc(Rsrc), m_InstrSession(NULL), m_Status(VI_SUCCESS)
324 {
325 }
327 {
328  CLockGuard<CRecursiveMutex> l_LockGuard(m_Lock);
329 
330  viClose(m_InstrSession);
331 }
332 
333 //------------------------------------------//
334 // Connexion
335 bool CVISAInstrument::Open(eOpenAccessMode AccessMode, ViUInt32 Timeout_ms)
336 {
337  MTL_VISA_INSTRUMENT_DEBUG_COUT(MTL__FUNCTION_NAME__ << std::endl);
338  CLockGuard<CRecursiveMutex> l_LockGuard(m_Lock);
339 
340  try {
341  if (!IsOpen())
342  {
343  m_Status = viOpen(m_rRrsrcMan.Session(), const_cast<ViRsrc>(m_Rsrc.c_str()), static_cast<ViAccessMode>(AccessMode), Timeout_ms, &m_InstrSession);
344  if (VI_SUCCESS != m_Status)
345  throw m_Status;
346  }
347  }
348  catch (ViStatus & rS)
349  {
350  MTL_Unused(rS);
352  return false;
353  }
354  return true;
355 }
357 {
358  MTL_VISA_INSTRUMENT_DEBUG_COUT(MTL__FUNCTION_NAME__ << std::endl);
359  CLockGuard<CRecursiveMutex> l_LockGuard(m_Lock);
360 
361  if (IsOpen())
362  {
363  m_Status = viClose(m_InstrSession);
364  MTL_Assert(VI_SUCCESS == m_Status || VI_WARN_NULL_OBJECT == m_Status);
365  m_InstrSession = 0;
367  }
368 }
370 {
371  CLockGuard<CRecursiveMutex> l_LockGuard(m_Lock);
372 
373  return (0 != m_InstrSession);
374 }
375 
376 //------------------------------------------//
377 // Info
378 const ViStatus & CVISAInstrument::Status()
379 {
380  CLockGuard<CRecursiveMutex> l_LockGuard(m_Lock);
381 
382  return m_Status;
383 }
384 const ViSession & CVISAInstrument::Session()
385 {
386  CLockGuard<CRecursiveMutex> l_LockGuard(m_Lock);
387 
388  return m_InstrSession;
389 }
390 
391 //------------------------------------------//
392 // Write / Read
393 bool CVISAInstrument::Write(const char * Str)
394 {
395  CLockGuard<CRecursiveMutex> l_LockGuard(m_Lock);
396 
397  return Write(reinterpret_cast<ViBuf>(const_cast<char *>(Str)), static_cast<ViUInt32>(std::strlen(Str)));
398 }
399 bool CVISAInstrument::Write(const std::string & rStr)
400 {
401  CLockGuard<CRecursiveMutex> l_LockGuard(m_Lock);
402 
403  return Write(reinterpret_cast<ViBuf>(const_cast<char *>(rStr.c_str())), static_cast<ViUInt32>(rStr.length()));
404 }
406 {
407  CLockGuard<CRecursiveMutex> l_LockGuard(m_Lock);
408 
409  return Write(reinterpret_cast<ViBuf>(const_cast<char *>(rBuf.data())), static_cast<ViUInt32>(rBuf.size()));
410 }
411 bool CVISAInstrument::Write(const ViBuf WriteBuf, ViUInt32 BuffLen)
412 {
413  MTL_VISA_INSTRUMENT_DEBUG_COUT(MTL__FUNCTION_NAME__ << std::endl);
414  CLockGuard<CRecursiveMutex> l_LockGuard(m_Lock);
415 
416  ViUInt32 retCount;
417  try {
418  m_Status = viWrite(m_InstrSession, WriteBuf, BuffLen, &retCount);
419  if (VI_SUCCESS != m_Status)
420  throw m_Status;
421  }
422  catch (ViStatus & rS)
423  {
424  MTL_Unused(rS);
426  return false;
427  }
428  return (m_Status == VI_SUCCESS && BuffLen == retCount);
429 }
430 bool CVISAInstrument::Read(CVISABuffer & rBuf, bool Append)
431 {
432  CLockGuard<CRecursiveMutex> l_LockGuard(m_Lock);
433 
434  bool l_Ret;
435  ViUInt32 l_RetLen;
436  if (!Append)
437  {
438  l_Ret = Read(reinterpret_cast<ViPBuf>(rBuf.data()), static_cast<ViUInt32>(rBuf.capacity()), l_RetLen);
439  rBuf.resize(l_RetLen);
440  }
441  else
442  {
443  l_Ret = Read(reinterpret_cast<ViPBuf>(rBuf.data() + rBuf.size()), static_cast<ViUInt32>(rBuf.capacity() - rBuf.size()), l_RetLen);
444  rBuf.resize(rBuf.size() + l_RetLen);
445  }
446  return l_Ret;
447 }
448 bool CVISAInstrument::Read(ViPBuf ReadBuf, ViUInt32 ReadLen, ViUInt32 & rRetLen)
449 {
450  MTL_VISA_INSTRUMENT_DEBUG_COUT(MTL__FUNCTION_NAME__ << std::endl);
451  CLockGuard<CRecursiveMutex> l_LockGuard(m_Lock);
452 
453  m_Status = viRead(m_InstrSession, ReadBuf, ReadLen, &rRetLen);
454  switch (m_Status)
455  {
456  case VI_SUCCESS: // The operation completed successfully and the END indicator was received(for interfaces that have END indicators).This completion code is returned regardless of whether the termination character is received or the number of bytes read is equal to count.
457  case VI_SUCCESS_TERM_CHAR: // The specified termination character was read but no END indicator was received. This completion code is returned regardless of whether the number of bytes read is equal to count.
458  case VI_SUCCESS_MAX_CNT: // The number of bytes read is equal to count.No END indicator was received and no termination character was read.
459  return true;
460  default:
462  return false;
463  }
464 }
465 
466 //------------------------------------------//
467 // Other operations
468 bool CVISAInstrument::SetTimeout(ViUInt32 Timeout)
469 {
470  MTL_VISA_INSTRUMENT_DEBUG_COUT(MTL__FUNCTION_NAME__ << std::endl);
471  CLockGuard<CRecursiveMutex> l_LockGuard(m_Lock);
472 
473  m_Status = viSetAttribute(m_InstrSession, VI_ATTR_TMO_VALUE, Timeout);
475  return (m_Status == VI_SUCCESS);
476 }
478 {
479  MTL_VISA_INSTRUMENT_DEBUG_COUT(MTL__FUNCTION_NAME__ << std::endl);
480  CLockGuard<CRecursiveMutex> l_LockGuard(m_Lock);
481 
482  m_Status = viClear(m_InstrSession);
484  return (m_Status == VI_SUCCESS);
485 }
486 bool CVISAInstrument::ReadSTB(ViUInt16 & rSTB)
487 {
488  MTL_VISA_INSTRUMENT_DEBUG_COUT(MTL__FUNCTION_NAME__ << std::endl);
489  CLockGuard<CRecursiveMutex> l_LockGuard(m_Lock);
490 
491 #if (defined(ACTIVATE_READ_STB_WORKAROUND) && ACTIVATE_READ_STB_WORKAROUND)
492  // A bug was introduced in VISA 14. Despite our efforts to convince NI to fix the bug, we today have to deal with it...
493  // This bug is a timeout error returned sometimes by the VISA Read STB VI.When the problem occurs, the VI spends the current timeout time to finally return the above error code.
494  // Our workaround :
495  // We reduce the timeout to 10 ms to avoid blocking into the Read STB VI for a long time.
496  // If we get the timeout error, we allow 10 retries to retrieve the STB before giving up.Actually, 1 retry seems to be enough to get the Read STB working.
497  // To prevent from asking the STB right after if failed, a 5ms delay is performed between each retry.
498  try {
499  // Save current timeout
500  ViUInt32 l_CurrentTimeout;
501  m_Status = viGetAttribute(m_InstrSession, VI_ATTR_TMO_VALUE, &l_CurrentTimeout);
502  if (m_Status != VI_SUCCESS) throw false;
503  // Set current timeout to avoid blocking too long
504  m_Status = viSetAttribute(m_InstrSession, VI_ATTR_TMO_VALUE, READ_STB_WORKAROUND_POLL_PERIOD_MS);
505  if (m_Status != VI_SUCCESS) throw false;
506  // Try to read STB while there is a known error
507  bool l_ReadSTBSuccess = false;
508  for (unsigned char l_NbRetries = 5; l_NbRetries > 0 && !l_ReadSTBSuccess; l_NbRetries--)
509  {
510  m_Status = viReadSTB(m_InstrSession, &rSTB);
511  switch (m_Status)
512  {
513  case VI_SUCCESS:
514  // We succeeded in reading STB
515  l_ReadSTBSuccess = true;
516  break;
517  case VI_ERROR_TMO:
518  case VI_ERROR_INV_PROT:
519  default:
520  // Could not read STB. Sleep for 5 ms in case of error to reduce polling period.
521  {
523  MTL_VISA_INSTRUMENT_DEBUG_CERR("CVISAInstrument::ReadSTB failed. Retrying." << std::endl);
525  break;
526  }
527  }
528  }
529  // Revert initial timeout value
530  m_Status = viSetAttribute(m_InstrSession, VI_ATTR_TMO_VALUE, l_CurrentTimeout);
531  if (m_Status != VI_SUCCESS || !l_ReadSTBSuccess) throw false;
532  }
533  catch (bool & rE)
534  {
535  MTL_Unused(rE);
537  return false;
538  }
539 #else
540  m_Status = viReadSTB(m_InstrSession, &rSTB);
541 #endif
543  return (m_Status == VI_SUCCESS);
544 }
546 {
547  MTL_VISA_INSTRUMENT_DEBUG_COUT(MTL__FUNCTION_NAME__ << std::endl);
548  CLockGuard<CRecursiveMutex> l_LockGuard(m_Lock);
549 
550  m_Status = viAssertTrigger(m_InstrSession, static_cast<ViUInt16>(Protocol));
552  return (m_Status == VI_SUCCESS);
553 }
554 
555 //------------------------------------------//
556 // Lock / Unlock
557 bool CVISAInstrument::LockExclusive(ViUInt32 Timeout)
558 {
559  MTL_VISA_INSTRUMENT_DEBUG_COUT(MTL__FUNCTION_NAME__ << std::endl);
560  CLockGuard<CRecursiveMutex> l_LockGuard(m_Lock);
561 
562  m_Status = viLock(m_InstrSession, VI_EXCLUSIVE_LOCK, Timeout, VI_NULL, VI_NULL);
563  switch (m_Status)
564  {
565  case VI_SUCCESS:
566  case VI_SUCCESS_NESTED_EXCLUSIVE:
567  case VI_SUCCESS_NESTED_SHARED:
568  return true;
569  default:
571  return false;
572  }
573 }
574 bool CVISAInstrument::LockShared(ViUInt32 Timeout, ViKeyId RequestedKey, ViChar AccessKey[])
575 {
576  MTL_VISA_INSTRUMENT_DEBUG_COUT(MTL__FUNCTION_NAME__ << std::endl);
577  CLockGuard<CRecursiveMutex> l_LockGuard(m_Lock);
578 
579  m_Status = viLock(m_InstrSession, VI_SHARED_LOCK, Timeout, RequestedKey, AccessKey);
580  switch (m_Status)
581  {
582  case VI_SUCCESS: // Lock successfully relinquished.
583  case VI_SUCCESS_NESTED_EXCLUSIVE: // Call succeeded, but this session still has nested exclusive locks.
584  case VI_SUCCESS_NESTED_SHARED: // Call succeeded, but this session still has nested shared locks.
585  return true;
586  default:
588  return false;
589  }
590 }
592 {
593  MTL_VISA_INSTRUMENT_DEBUG_COUT(MTL__FUNCTION_NAME__ << std::endl);
594  CLockGuard<CRecursiveMutex> l_LockGuard(m_Lock);
595 
596  m_Status = viUnlock(m_InstrSession);
597  switch (m_Status)
598  {
599  case VI_SUCCESS: // Lock successfully relinquished.
600  case VI_SUCCESS_NESTED_EXCLUSIVE: // Call succeeded, but this session still has nested exclusive locks.
601  case VI_SUCCESS_NESTED_SHARED: // Call succeeded, but this session still has nested shared locks.
602  case VI_ERROR_SESN_NLOCKED: // The current session did not have any lock on the resource.
603  return true;
604  default:
606  return false;
607  }
608 }
609 
610 //------------------------------------------//
611 // Events
613 {
614  MTL_VISA_INSTRUMENT_DEBUG_COUT(MTL__FUNCTION_NAME__ << std::endl);
615  CLockGuard<CRecursiveMutex> l_LockGuard(m_Lock);
616 
617  m_Status = viEnableEvent(m_InstrSession, static_cast<ViEventType>(Type), static_cast<ViUInt16>(Mechanism), VI_NULL);
618  switch (m_Status)
619  {
620  case VI_SUCCESS: // Event enabled successfully.
621  case VI_SUCCESS_EVENT_EN: // Specified event is already enabled for at least one of the specified mechanisms.
622  return true;
623  default:
625  return false;
626  }
627 }
629 {
630  MTL_VISA_INSTRUMENT_DEBUG_COUT(MTL__FUNCTION_NAME__ << std::endl);
631  CLockGuard<CRecursiveMutex> l_LockGuard(m_Lock);
632 
633  m_Status = viDisableEvent(m_InstrSession, static_cast<ViEventType>(Type), static_cast<ViUInt16>(Mechanism));
634  switch (m_Status)
635  {
636  case VI_SUCCESS: // Event disabled successfully.
637  case VI_SUCCESS_EVENT_DIS: // Specified event is already disabled for at least one of the specified mechanisms.
638  return true;
639  default:
641  return false;
642  }
643 }
644 bool CVISAInstrument::WaitOnEvent(eEventType Type, ViUInt32 Timeout)
645 {
646  MTL_VISA_INSTRUMENT_DEBUG_COUT(MTL__FUNCTION_NAME__ << std::endl);
647  CLockGuard<CRecursiveMutex> l_LockGuard(m_Lock);
648 
649  m_Status = viWaitOnEvent(m_InstrSession, static_cast<ViEventType>(Type), Timeout, VI_NULL, VI_NULL);
650  switch (m_Status)
651  {
652  case VI_SUCCESS: // Wait terminated successfully on receipt of an event occurrence.The queue is empty.
653  case VI_SUCCESS_QUEUE_NEMPTY: // Wait terminated successfully on receipt of an event notification.There is still at least one more event occurrence of the type specified by inEventType available for this session.
654  return true;
655  default:
657  return false;
658  }
659 }
660 bool CVISAInstrument::WaitOnAllEvents(ViUInt32 Timeout)
661 {
662  MTL_VISA_INSTRUMENT_DEBUG_COUT(MTL__FUNCTION_NAME__ << std::endl);
663  CLockGuard<CRecursiveMutex> l_LockGuard(m_Lock);
664 
665  m_Status = viWaitOnEvent(m_InstrSession, VI_ALL_ENABLED_EVENTS, Timeout, VI_NULL, VI_NULL);
666  switch (m_Status)
667  {
668  case VI_SUCCESS: // Wait terminated successfully on receipt of an event occurrence.The queue is empty.
669  case VI_SUCCESS_QUEUE_NEMPTY: // Wait terminated successfully on receipt of an event notification.There is still at least one more event occurrence of the type specified by inEventType available for this session.
670  return true;
671  default:
673  return false;
674  }
675 }
677 {
678  MTL_VISA_INSTRUMENT_DEBUG_COUT(MTL__FUNCTION_NAME__ << std::endl);
679  CLockGuard<CRecursiveMutex> l_LockGuard(m_Lock);
680 
681  m_Status = viDiscardEvents(m_InstrSession, static_cast<ViEventType>(Type), static_cast<ViUInt16>(Mechanism));
682  switch (m_Status)
683  {
684  case VI_SUCCESS: // Event queue flushed successfully.
685  case VI_SUCCESS_QUEUE_EMPTY: // Operation completed successfully, but queue was already empty.
686  return true;
687  default:
689  return false;
690  }
691 }
692 
693 //------------------------------------------//
694 // Attributes
695 bool CVISAInstrument::GetAttribute(ViAttr Attribute, void * Value)
696 {
697  MTL_VISA_INSTRUMENT_DEBUG_COUT(MTL__FUNCTION_NAME__ << std::endl);
698  CLockGuard<CRecursiveMutex> l_LockGuard(m_Lock);
699 
700  m_Status = viGetAttribute(m_InstrSession, Attribute, Value);
701  switch (m_Status)
702  {
703  case VI_SUCCESS: // Event queue flushed successfully.
704  return true;
705  case VI_ERROR_INV_OBJECT: // The given object reference is invalid.
706  case VI_ERROR_NSUP_ATTR: // The specified attribute is not defined by the referenced object.
707  default:
709  return false;
710  }
711 }
712 
713 //------------------------------------------//
714 // USB
715 bool CVISAInstrument::UsbControlIn(ViInt16 bmRequestType, ViInt16 bRequest, ViUInt16 wValue, ViUInt16 wIndex, ViUInt16 wLength, ViPBuf buf, ViUInt16 & rretCnt)
716 {
717  MTL_VISA_INSTRUMENT_DEBUG_COUT(MTL__FUNCTION_NAME__ << std::endl);
718  CLockGuard<CRecursiveMutex> l_LockGuard(m_Lock);
719 
720  m_Status = viUsbControlIn(m_InstrSession, bmRequestType, bRequest, wValue, wIndex, wLength, buf, &rretCnt);
721  switch (m_Status)
722  {
723  case VI_SUCCESS:
724  return true;
725  case VI_ERROR_INV_OBJECT: // The given session reference is invalid.
726  case VI_ERROR_RSRC_LOCKED: // Specified operation could not be performed because the resource identified by vi has been locked for this kind of access.
727  case VI_ERROR_TMO: // Timeout expired before operation completed.
728  case VI_ERROR_INV_SETUP: // Unable to start write operation because setup is invalid(due to attributes being set to an inconsistent state).
729  case VI_ERROR_IO: // An unknown I/O error occurred during transfer.
730  case VI_ERROR_CONN_LOST: // The I/O connection for the given session has been lost.
731  case VI_ERROR_INV_PARAMETER: // The value of some parameter—which parameter is not known—is invalid.
732  case VI_ERROR_INV_MASK: // The bmRequestType parameter contains an invalid mask.
733  default:
735  return false;
736  }
737 }
738 
739 bool CVISAInstrument::UsbControlOut(ViInt16 bmRequestType, ViInt16 bRequest, ViUInt16 wValue, ViUInt16 wIndex, ViUInt16 wLength, ViBuf buf)
740 {
741  MTL_VISA_INSTRUMENT_DEBUG_COUT(MTL__FUNCTION_NAME__ << std::endl);
742  CLockGuard<CRecursiveMutex> l_LockGuard(m_Lock);
743 
744  m_Status = viUsbControlOut(m_InstrSession, bmRequestType, bRequest, wValue, wIndex, wLength, buf);
745  switch (m_Status)
746  {
747  case VI_SUCCESS:
748  return true;
749  case VI_ERROR_INV_OBJECT: // The given session reference is invalid.
750  case VI_ERROR_RSRC_LOCKED: // Specified operation could not be performed because the resource identified by vi has been locked for this kind of access.
751  case VI_ERROR_TMO: // Timeout expired before operation completed.
752  case VI_ERROR_INV_SETUP: // Unable to start write operation because setup is invalid(due to attributes being set to an inconsistent state).
753  case VI_ERROR_IO: // An unknown I/O error occurred during transfer.
754  case VI_ERROR_CONN_LOST: // The I/O connection for the given session has been lost.
755  case VI_ERROR_INV_PARAMETER: // The value of some parameter—which parameter is not known—is invalid.
756  case VI_ERROR_INV_MASK: // The bmRequestType parameter contains an invalid mask.
757  default:
759  return false;
760  }
761 }
762 
763 //------------------------------------------//
764 //Serial (ASRL)
766 {
767  MTL_VISA_INSTRUMENT_DEBUG_COUT(MTL__FUNCTION_NAME__ << std::endl);
768  CLockGuard<CRecursiveMutex> l_LockGuard(m_Lock);
769 
770  try {
771  // set Baud Rate
772  m_Status = viSetAttribute(m_InstrSession, VI_ATTR_ASRL_BAUD, static_cast<ViAttrState>(rPortSettings.Baudrate));
773  if (m_Status != VI_SUCCESS) throw false;
774 
775  // set Data Bits length
776  m_Status = viSetAttribute(m_InstrSession, VI_ATTR_ASRL_DATA_BITS, static_cast<ViAttrState>(rPortSettings.DataBits));
777  if (m_Status != VI_SUCCESS) throw false;
778 
779  // set Parity
780  m_Status = viSetAttribute(m_InstrSession, VI_ATTR_ASRL_PARITY, static_cast<ViAttrState>(rPortSettings.Parity));
781  if (m_Status != VI_SUCCESS) throw false;
782 
783  // set Stop bits
784  m_Status = viSetAttribute(m_InstrSession, VI_ATTR_ASRL_STOP_BITS, static_cast<ViAttrState>(rPortSettings.StopBits));
785  if (m_Status != VI_SUCCESS) throw false;
786 
787  // set Flow control
788  m_Status = viSetAttribute(m_InstrSession, VI_ATTR_ASRL_FLOW_CNTRL, static_cast<ViAttrState>(rPortSettings.Handshake));
789  if (m_Status != VI_SUCCESS) throw false;
790 
791  // set Read Termination Character Mode
792  m_Status = viSetAttribute(m_InstrSession, VI_ATTR_ASRL_END_IN, static_cast<ViAttrState>(rPortSettings.ReadTermMode));
793  if (m_Status != VI_SUCCESS) throw false;
794 
795  if (rPortSettings.ReadTermMode == eSerialTermMode::kEndTermChar)
796  {
797  // set a specific Read Termination Character
798  m_Status = viSetAttribute(m_InstrSession, VI_ATTR_TERMCHAR, static_cast<ViAttrState>(rPortSettings.ReadTermChar));
799  if (m_Status != VI_SUCCESS) throw false;
800 
801  // Enable specific Read Termination Character
802  m_Status = viSetAttribute(m_InstrSession, VI_ATTR_TERMCHAR_EN, static_cast<ViAttrState>(true));
803  if (m_Status != VI_SUCCESS) throw false;
804  }
805  else
806  {
807  // Disable specific Read Termination Character
808  m_Status = viSetAttribute(m_InstrSession, VI_ATTR_TERMCHAR_EN, static_cast<ViAttrState>(false));
809  if (m_Status != VI_SUCCESS) throw false;
810  }
811  }
812  catch (bool & rE)
813  {
814  MTL_Unused(rE);
816  return false;
817  }
818 
819  return true;
820 }
MTL::Instrument::CVISAResourceManager::CVISAResourceManager
CVISAResourceManager()
Definition: VISAInstrument.cpp:68
VI_STATUS_DESC_MAX_LEN
#define VI_STATUS_DESC_MAX_LEN
Definition: VISAInstrument.cpp:15
MTL::Instrument::CVISAInstrument::ConfigSerialPort
bool ConfigSerialPort(const sSerialPortSettings &rPortSettings)
Definition: VISAInstrument.cpp:765
MTL::Instrument::CResourceList
Definition: VISAInstrumentTypes.h:23
MTL::Instrument::CVISAInstrument::ReadSTB
bool ReadSTB(ViUInt16 &rSTB)
Definition: VISAInstrument.cpp:486
MTL::Instrument::CVISAResourceManager::ResourceInfo
bool ResourceInfo(tResourceName &rRsrc, eInterfaceType &rIntfType, tInterfaceNumber &rIntfNumber)
Definition: VISAInstrument.cpp:233
MTL_VISA_INSTRUMENT_DEBUG_COUT
#define MTL_VISA_INSTRUMENT_DEBUG_COUT(__X__)
Definition: VISAInstrument.cpp:31
l_DebugCheckStatus
#define l_DebugCheckStatus(__X__, __Y__)
Definition: VISAInstrument.cpp:60
MTL::Instrument::sSerialPortSettings::Handshake
eSerialHandshake Handshake
Definition: VISAInstrumentTypes.h:178
MTL::Instrument::CVISAInstrument::UsbControlOut
bool UsbControlOut(ViInt16 bmRequestType, ViInt16 bRequest, ViUInt16 wValue, ViUInt16 wIndex, ViUInt16 wLength, ViBuf buf)
Definition: VISAInstrument.cpp:739
MTL::Instrument::CVISAInstrument::UsbControlIn
bool UsbControlIn(ViInt16 bmRequestType, ViInt16 bRequest, ViUInt16 wValue, ViUInt16 wIndex, ViUInt16 wLength, ViPBuf buf, ViUInt16 &rretCnt)
Definition: VISAInstrument.cpp:715
MTL::Instrument::CVISAResourceManager::FindResources
bool FindResources(CResourceList &rList, std::string Filter="?*")
Definition: VISAInstrument.cpp:121
MTL::Instrument::CVISAInstrument::DisableEvent
bool DisableEvent(eEventType Type, eEventMechanism Mechanism)
Definition: VISAInstrument.cpp:628
MTL::Instrument::CVISAInstrument::GetAttribute
bool GetAttribute(ViAttr Attribute, void *Value)
Definition: VISAInstrument.cpp:695
MTL::Instrument::sSerialPortSettings::ReadTermMode
eSerialTermMode ReadTermMode
Definition: VISAInstrumentTypes.h:179
MTL::Instrument::CVISAInstrument::Session
const ViSession & Session()
Definition: VISAInstrument.cpp:384
MTL::Instrument::CVISAInstrument::Read
bool Read(CVISABuffer &rBuf, bool Append=false)
Definition: VISAInstrument.cpp:430
MTL::Instrument::CVISAInstrument::EnableEvent
bool EnableEvent(eEventType Type, eEventMechanism Mechanism)
Definition: VISAInstrument.cpp:612
MTL::Instrument::sSerialPortSettings::Baudrate
eSerialBaudrate Baudrate
Definition: VISAInstrumentTypes.h:174
MTL::Instrument::CVISAInstrument::WaitOnAllEvents
bool WaitOnAllEvents(ViUInt32 Timeout)
Definition: VISAInstrument.cpp:660
MTL::Instrument::CVISAInstrument::m_rRrsrcMan
CVISAResourceManager & m_rRrsrcMan
Definition: VISAInstrument.h:64
MTL::Instrument::eEventMechanism
eEventMechanism
Definition: VISAInstrumentTypes.h:88
MTL::Instrument::VISAResourceInfo
Definition: VISAInstrumentTypes.h:193
MTL_SleepMs
#define MTL_SleepMs(_ms_)
Definition: Helpers.h:46
MTL::Instrument::sSerialPortSettings
Definition: VISAInstrumentTypes.h:173
MTL::Instrument::CVISAResourceManager::Status
ViStatus Status()
Definition: VISAInstrument.cpp:108
MTL::Instrument::CVISABuffer::resize
void resize(size_t size)
Definition: VISAInstrumentBuffer.h:74
MTL::Instrument::CVISAInstrument::SetTimeout
bool SetTimeout(ViUInt32 Timeout)
Definition: VISAInstrument.cpp:468
MTL::Instrument::eEventType
eEventType
Definition: VISAInstrumentTypes.h:95
MTL::Instrument::CVISAInstrument::m_Lock
CRecursiveMutex m_Lock
Definition: VISAInstrument.h:63
MTL::Instrument::eInterfaceType
eInterfaceType
Definition: VISAInstrumentTypes.h:57
Helpers.h
Collection of utility macros for error messages.
MTL_Assert
#define MTL_Assert
Definition: Helpers.h:44
MTL::Instrument::CVISAInstrument::LockExclusive
bool LockExclusive(ViUInt32 Timeout)
Definition: VISAInstrument.cpp:557
MTL::Instrument::CVISABuffer::capacity
size_t capacity() const
Definition: VISAInstrumentBuffer.h:92
MTL::Instrument::CVISAInstrument::m_Rsrc
tResourceName m_Rsrc
Definition: VISAInstrument.h:65
MTL::Instrument::StatusDescription
std::string StatusDescription(ViSession Session, ViStatus Status)
Return user-readable description of the given status code.
Definition: VISAInstrument.cpp:40
MTL::Instrument::CVISAInstrument::Write
bool Write(const char *Str)
Definition: VISAInstrument.cpp:393
MTL::Instrument
Definition: MFC3045.h:25
MTL::Instrument::sParsedResource
Definition: VISAInstrumentTypes.h:234
MTL::Instrument::CVISAInstrument::Close
void Close()
Definition: VISAInstrument.cpp:356
MTL::Instrument::CVISAInstrument::~CVISAInstrument
virtual ~CVISAInstrument()
Definition: VISAInstrument.cpp:326
MTL::Instrument::eSerialTermMode::kEndTermChar
@ kEndTermChar
MTL::Instrument::CVISAResourceManager::Session
const ViSession & Session()
Definition: VISAInstrument.cpp:112
MTL::Instrument::CVISAResourceManager::~CVISAResourceManager
virtual ~CVISAResourceManager()
Definition: VISAInstrument.cpp:73
MTL::Instrument::CVISAInstrument::DiscardEvents
bool DiscardEvents(eEventType Type, eEventMechanism Mechanism)
Definition: VISAInstrument.cpp:676
MTL::Instrument::CVISAInstrument::IsOpen
bool IsOpen()
Definition: VISAInstrument.cpp:369
MTL::Instrument::CVISAInstrument::WaitOnEvent
bool WaitOnEvent(eEventType Type, ViUInt32 Timeout)
Definition: VISAInstrument.cpp:644
MTL::Instrument::sSerialPortSettings::DataBits
eSerialDataBits DataBits
Definition: VISAInstrumentTypes.h:175
MTL::Instrument::eTriggerProtocol
eTriggerProtocol
Definition: VISAInstrumentTypes.h:114
MTL::Instrument::CVISAInstrument::Open
bool Open(eOpenAccessMode AccessMode=eOpenAccessMode::NoLock, ViUInt32 Timeout_ms=0)
Definition: VISAInstrument.cpp:335
MTL::Instrument::sSerialPortSettings::Parity
eSerialParity Parity
Definition: VISAInstrumentTypes.h:176
MTL::Instrument::tInterfaceNumber
ViUInt16 tInterfaceNumber
Definition: VISAInstrumentTypes.h:67
MTL::Instrument::CVISAInstrument::m_Status
ViStatus m_Status
Definition: VISAInstrument.h:67
MTL::Instrument::CVISAInstrument::m_InstrSession
ViSession m_InstrSession
Definition: VISAInstrument.h:66
MTL::Instrument::tResourceName
std::string tResourceName
Definition: VISAInstrumentTypes.h:21
MTL::Instrument::CVISABuffer
Definition: VISAInstrumentBuffer.h:37
MTL::Instrument::VISAResourceInfo::tAlias
std::string tAlias
Definition: VISAInstrumentTypes.h:198
MTL::Instrument::CVISAInstrument::CVISAInstrument
CVISAInstrument(CVISAResourceManager &rRM, tResourceName Rsrc)
Definition: VISAInstrument.cpp:322
MTL::Instrument::sSerialPortSettings::ReadTermChar
char ReadTermChar
Definition: VISAInstrumentTypes.h:180
MTL::Instrument::CVISAInstrument::Status
const ViStatus & Status()
Definition: VISAInstrument.cpp:378
MTL::Instrument::eOpenAccessMode
eOpenAccessMode
Definition: VISAInstrumentTypes.h:79
VISAInstrument.h
C++ wrapper for NI-VISA: interface definition.
MTL::Instrument::CVISABuffer::data
MTL_VISA_BUFFER_TYPE * data() noexcept
Definition: VISAInstrumentBuffer.h:124
MTL::Synchronization::CLockGuard
Lock.
Definition: Synchronization.h:62
OSDefines.h
Platform Dependent Definitions.
MTL::Instrument::sSerialPortSettings::StopBits
eSerialStopBits StopBits
Definition: VISAInstrumentTypes.h:177
MTL::Instrument::CVISAInstrument::LockShared
bool LockShared(ViUInt32 Timeout, ViKeyId RequestedKey, ViChar AccessKey[])
Definition: VISAInstrument.cpp:574
READ_STB_WORKAROUND_POLL_PERIOD_MS
#define READ_STB_WORKAROUND_POLL_PERIOD_MS
Definition: VISAInstrument.cpp:17
MTL_Unused
#define MTL_Unused(x)
Definition: Helpers.h:47
MTL::Instrument::VISAResourceInfo::tExpandedName
std::string tExpandedName
Definition: VISAInstrumentTypes.h:197
MTL::Instrument::CVISAInstrument::AssertTrigger
bool AssertTrigger(eTriggerProtocol Protocol)
Definition: VISAInstrument.cpp:545
MTL::Instrument::CVISABuffer::size
size_t size() const
Definition: VISAInstrumentBuffer.h:86
MTL::Instrument::CVISAResourceManager
VISA Resource Manager class.
Definition: VISAInstrument.h:35
MTL::Instrument::VISAResourceInfo::tClass
std::string tClass
Definition: VISAInstrumentTypes.h:196
MTL::Instrument::CParsedResourceList
Definition: VISAInstrumentTypes.h:253
MTL::Instrument::CVISAInstrument::Clear
bool Clear()
Definition: VISAInstrument.cpp:477
MTL_VISA_INSTRUMENT_DEBUG_CERR
#define MTL_VISA_INSTRUMENT_DEBUG_CERR(__X__)
Definition: VISAInstrument.cpp:32
MTL::Instrument::CVISAResourceManager::Initialize
bool Initialize()
Definition: VISAInstrument.cpp:82
MTL::Instrument::CVISAInstrument::Unlock
bool Unlock()
Definition: VISAInstrument.cpp:591