THM1176InstrumentDriver 1.1
C++ API for Metrolab THM1176
Loading...
Searching...
No Matches
VISAInstrument.cpp
Go to the documentation of this file.
1// Copyright (c) 2020 Metrolab Technology S.A., Geneva, Switzerland (www.metrolab.com)
2// See the included file LICENSE.txt for the licensing conditions.
3
7
8// Personal includes
9#include "VISAInstrument.h"
10#include "OSDefines.h"
11#include "Helpers.h"
12
13// Standard includes
14#include <string>
15#include <cstring>
16
17// Constants
18#define VI_STATUS_DESC_MAX_LEN 256
19// Definitions
20#define READ_STB_WORKAROUND_POLL_PERIOD_MS 10
21
22// Definitions
23#define DEBUG_MTL_VISA_INSTRUMENT 0
24#define DEBUG_MTL_VISA_INSTRUMENT_ERRORS_ONLY 0
25#if (defined(_DEBUG) && defined(DEBUG_MTL_VISA_INSTRUMENT) && DEBUG_MTL_VISA_INSTRUMENT)
26#if (defined(DEBUG_MTL_VISA_INSTRUMENT_ERRORS_ONLY) && DEBUG_MTL_VISA_INSTRUMENT_ERRORS_ONLY)
27#define MTL_VISA_INSTRUMENT_DEBUG_COUT(__X__)
28#else
29#define MTL_VISA_INSTRUMENT_DEBUG_COUT(__X__) COUT(__X__)
30#endif
31#define MTL_VISA_INSTRUMENT_DEBUG_CERR(__X__) CERR(__X__)
32#else
33#define MTL_VISA_INSTRUMENT_DEBUG_COUT(__X__)
34#define MTL_VISA_INSTRUMENT_DEBUG_CERR(__X__)
35#endif
36
37using namespace MTL::Instrument;
38
39//----------------------------------------------------------------------//
40// Error Handling //
41//----------------------------------------------------------------------//
42std::string MTL::Instrument::StatusDescription(ViSession Session, ViStatus Status)
43{
44 // According to the NI-VISA Programmer Reference Manual:
45 // "If the string cannot be interpreted, the operation returns the warning
46 // code VI_WARN_UNKNOWN_STATUS. However, the output string desc is valid
47 // regardless of the status return value."
48 // So, regardless of the return error code, we return the description.
49 static ViChar Desc[VI_STATUS_DESC_MAX_LEN];
50 viStatusDesc(Session, Status, Desc);
51 return std::string(Desc);
52}
53#if (defined(DEBUG_MTL_VISA_INSTRUMENT) && DEBUG_MTL_VISA_INSTRUMENT)
54static void l_DebugCheckStatus(ViSession Session, ViStatus Status)
55{
56 if (VI_SUCCESS != Status)
57 {
58 MTL_VISA_INSTRUMENT_DEBUG_CERR(StatusDescription(Session, Status) << std::endl);
59 }
60}
61#else
62#define l_DebugCheckStatus(__X__, __Y__)
63#endif
64
65//----------------------------------------------------------------------//
66// Resource Manager //
67//----------------------------------------------------------------------//
68//------------------------------------------//
69// Constructors / destructors
71 : m_DefaultRM(0)
72{
73 m_Status = VI_SUCCESS;
74}
76{
77 CLockGuard<CMutex> l_LockGuard(m_Lock);
78
79 viClose(m_DefaultRM);
80}
81
82//------------------------------------------//
83// Initialization / Info
85{
86 MTL_VISA_INSTRUMENT_DEBUG_COUT(MTL__FUNCTION_NAME__ << std::endl);
87 CLockGuard<CMutex> l_LockGuard(m_Lock);
88
89 try {
90 if (0 != m_DefaultRM)
91 throw VI_SUCCESS; // Already initialized
92
93 m_Status = viOpenDefaultRM(&m_DefaultRM);
94 if (VI_SUCCESS != m_Status)
95 {
96 m_DefaultRM = static_cast<ViSession>(NULL);
97 throw m_Status;
98 }
99 }
100 catch (I32 & rS)
101 {
102 MTL_Unused(rS);
103 l_DebugCheckStatus(m_DefaultRM, rS);
104 return false;
105 }
106
107 return true;
108}
109
111{
112 return static_cast<ViStatus>(CIEEE488ResourceManager::Status());
113}
114
116{
117 CLockGuard<CMutex> l_LockGuard(m_Lock);
118
119 // According to the NI-VISA Programmer Reference Manual:
120 // "If the string cannot be interpreted, the operation returns the warning
121 // code VI_WARN_UNKNOWN_STATUS. However, the output string desc is valid
122 // regardless of the status return value."
123 // So, regardless of the return error code, we return the description.
124 static ViChar Desc[VI_STATUS_DESC_MAX_LEN];
125 viStatusDesc(m_DefaultRM, Status, Desc);
126 return std::string(Desc);
127}
128
130{
131 CLockGuard<CMutex> l_LockGuard(m_Lock);
132
133 return m_DefaultRM;
134}
136{
137 CLockGuard<CMutex> l_LockGuard(m_Lock);
138
139 return m_Status == VI_ERROR_TMO;
140}
141
142//------------------------------------------//
143// Resource utilities
144bool CVISAResourceManager::FindResources(CResourceList & rList, std::string Filter)
145{
146 MTL_VISA_INSTRUMENT_DEBUG_COUT(MTL__FUNCTION_NAME__ << std::endl);
147 CLockGuard<CMutex> l_LockGuard(m_Lock);
148
149 bool l_Ret = true;
150 rList.clear();
151 ViFindList fList;
152
153 try
154 {
155 ViChar rsrcName[VI_FIND_BUFLEN];
156 ViUInt32 numInstrs;
157
158 // Find all instruments
159 ViString l_Filter = const_cast<ViString>(Filter.c_str());
160 m_Status = viFindRsrc(m_DefaultRM, l_Filter, &fList, &numInstrs, rsrcName);
161 if (VI_SUCCESS != m_Status && VI_ERROR_RSRC_NFOUND != m_Status)
162 throw m_Status;
163
164 while (numInstrs-- && m_Status == VI_SUCCESS)
165 {
166 rList.push_back(tResourceName(rsrcName));
167 m_Status = viFindNext(fList, rsrcName);
168 if (VI_SUCCESS != m_Status && VI_ERROR_RSRC_NFOUND != m_Status)
169 throw m_Status;
170 }
171
172 if (rList.size() > 0)
173 m_Status = VI_SUCCESS;
174 }
175 catch (I32 & rS)
176 {
177 switch (rS)
178 {
179 case VI_ERROR_INV_OBJECT: // The given session reference is invalid
180 case VI_ERROR_NSUP_OPER: // The given sesn does not support this operation.This operation is supported only by a Resource Manager session
181 case VI_ERROR_INV_EXPR: // Invalid expression specified for search
182 default:
183 l_DebugCheckStatus(m_DefaultRM, rS);
184 l_Ret = false;
185 break;
186
187 case VI_SUCCESS:
188 case VI_ERROR_RSRC_NFOUND: // Specified expression does not match any devices
189 l_Ret = true;
190 break;
191 }
192 }
193
194 viClose(fList);
195 return l_Ret;
196}
198{
199 MTL_VISA_INSTRUMENT_DEBUG_COUT(MTL__FUNCTION_NAME__ << std::endl);
200 CLockGuard<CMutex> l_LockGuard(m_Lock);
201
202 bool l_Ret = true;
203 rList.clear();
204 ViFindList fList;
205
206 try
207 {
208 ViChar rsrcName[VI_FIND_BUFLEN];
209 ViUInt32 numInstrs;
210
211 // Find all instruments
212 ViString l_Filter = const_cast<ViString>(Filter.c_str());
213 m_Status = viFindRsrc(m_DefaultRM, l_Filter, &fList, &numInstrs, rsrcName);
214 if (VI_SUCCESS != m_Status && VI_ERROR_RSRC_NFOUND != m_Status)
215 throw m_Status;
216
217 while (numInstrs-- && m_Status == VI_SUCCESS)
218 {
219 ViUInt16 l_Type, l_Number;
220 ViChar l_Class[100], l_ExpName[100], l_Alias[100];
221 m_Status = viParseRsrcEx(m_DefaultRM, static_cast<ViRsrc>(rsrcName), &l_Type, &l_Number, l_Class, l_ExpName, l_Alias);
222 if (VI_SUCCESS == m_Status)
223 {
224 tResourceName l_ResourceName(rsrcName);
225 VISAResourceInfo l_VISAResourceInfo( static_cast<eInterfaceType>(l_Type),
226 static_cast<tInterfaceNumber>(l_Number),
227 static_cast<VISAResourceInfo::tClass>(l_Class),
228 static_cast<VISAResourceInfo::tExpandedName>(l_ExpName),
229 static_cast<VISAResourceInfo::tAlias>(l_Alias));
230 rList.push_back(sParsedResource(l_ResourceName, l_VISAResourceInfo));
231
232 m_Status = viFindNext(fList, rsrcName);
233 if (VI_SUCCESS != m_Status && VI_ERROR_RSRC_NFOUND != m_Status)
234 throw m_Status;
235 }
236 else if (VI_ERROR_RSRC_NFOUND != m_Status)
237 throw m_Status;
238 }
239 }
240 catch (I32 & rS)
241 {
242 switch (rS)
243 {
244 default:
245 l_DebugCheckStatus(m_DefaultRM, rS);
246 l_Ret = false;
247 break;
248
249 case VI_SUCCESS:
250 case VI_ERROR_RSRC_NFOUND: // Specified expression does not match any devices
251 l_Ret = true;
252 break;
253 }
254 }
255
256 viClose(fList);
257 return l_Ret;
258}
260{
261 MTL_VISA_INSTRUMENT_DEBUG_COUT(MTL__FUNCTION_NAME__ << std::endl);
262 CLockGuard<CMutex> l_LockGuard(m_Lock);
263
264 bool l_Ret = true;
265 try
266 {
267 ViUInt16 l_Type, l_Number;
268 m_Status = viParseRsrc(m_DefaultRM, const_cast<ViRsrc>(rRsrc.c_str()), &l_Type, &l_Number);
269 if (VI_SUCCESS != m_Status)
270 throw m_Status;
271
272 rIntfType = static_cast<eInterfaceType>(l_Type);
273 rIntfNumber = static_cast<tInterfaceNumber>(l_Number);
274 }
275
276 catch (I32 & rS)
277 {
278 switch (rS)
279 {
280 case VI_SUCCESS:
281 l_Ret = true;
282 break;
283 case VI_ERROR_INV_OBJECT: // The given session reference is invalid
284 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.
285 case VI_ERROR_INV_RSRC_NAME: // Invalid resource reference specified. Parsing error.
286 case VI_ERROR_RSRC_NFOUND: // Insufficient location information or resource not present in the system.
287 case VI_ERROR_ALLOC: // Insufficient system resources to parse the string.
288 case VI_ERROR_LIBRARY_NFOUND: // A code library required by VISA could not be located or loaded.
289 case VI_ERROR_INTF_NUM_NCONFIG: // The interface type is valid, but the specified interface number is not configured.
290 default:
291 l_DebugCheckStatus(m_DefaultRM, rS);
292 l_Ret = false;
293 break;
294 }
295 }
296
297 return l_Ret;
298}
300{
301 MTL_VISA_INSTRUMENT_DEBUG_COUT(MTL__FUNCTION_NAME__ << std::endl);
302 CLockGuard<CMutex> l_LockGuard(m_Lock);
303
304 bool l_Ret = true;
305 try
306 {
307 ViUInt16 l_Type, l_Number;
308 ViChar l_Class[100], l_ExpName[100], l_Alias[100];
309 m_Status = viParseRsrcEx(m_DefaultRM, const_cast<ViRsrc>(rRsrc.c_str()), &l_Type, &l_Number, l_Class, l_ExpName, l_Alias);
310 if (VI_SUCCESS != m_Status)
311 throw m_Status;
312 rReturnedInfo = VISAResourceInfo(
313 static_cast<eInterfaceType>(l_Type),
314 static_cast<tInterfaceNumber>(l_Number),
315 static_cast<VISAResourceInfo::tClass>(l_Class),
316 static_cast<VISAResourceInfo::tExpandedName>(l_ExpName),
317 static_cast<VISAResourceInfo::tAlias>(l_Alias));
318 }
319 catch (I32 & rS)
320 {
321 switch (rS)
322 {
323 case VI_SUCCESS:
324 case VI_WARN_EXT_FUNC_NIMPL: // The operation succeeded, but a lower level driver did not implement the extended functionality.
325 l_Ret = true;
326 break;
327 case VI_ERROR_INV_OBJECT: // The given session reference is invalid
328 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.
329 case VI_ERROR_INV_RSRC_NAME: // Invalid resource reference specified. Parsing error.
330 case VI_ERROR_RSRC_NFOUND: // Insufficient location information or resource not present in the system.
331 case VI_ERROR_ALLOC: // Insufficient system resources to parse the string.
332 case VI_ERROR_LIBRARY_NFOUND: // A code library required by VISA could not be located or loaded.
333 case VI_ERROR_INTF_NUM_NCONFIG: // The interface type is valid, but the specified interface number is not configured.
334 default:
335 l_DebugCheckStatus(m_DefaultRM, rS);
336 l_Ret = false;
337 break;
338 }
339 }
340 return l_Ret;
341}
342
343//----------------------------------------------------------------------//
344// Instrument //
345//----------------------------------------------------------------------//
346//------------------------------------------//
347// Constructors / destructors
349 : CIEEE488Instrument(rRM, Rsrc), m_InstrSession(static_cast<ViSession>(NULL)), m_ExclusiveLock(false)
350{
351 m_Status = VI_SUCCESS;
352}
354{
356
357 viClose(m_InstrSession);
358}
359
360//------------------------------------------//
361// Connexion
363{
364 return Open(eOpenAccessMode::NoLock, 0);
365}
366bool CVISAInstrument::Open(eOpenAccessMode AccessMode, ViUInt32 Timeout_ms)
367{
368 MTL_VISA_INSTRUMENT_DEBUG_COUT(MTL__FUNCTION_NAME__ << std::endl);
370
371 try {
372 if (!IsOpen())
373 {
374 ViSession l_Session = dynamic_cast<CVISAResourceManager *>(&m_rRrsrcMan)->Session();
375 m_Status = viOpen(l_Session, const_cast<ViRsrc>(m_Rsrc.c_str()), static_cast<ViAccessMode>(AccessMode), Timeout_ms, &m_InstrSession);
376 if (VI_SUCCESS != m_Status)
377 throw m_Status;
378 }
379 }
380 catch (I32 & rS)
381 {
382 MTL_Unused(rS);
383 l_DebugCheckStatus(m_InstrSession, rS);
384 return false;
385 }
386 return true;
387}
389{
390 MTL_VISA_INSTRUMENT_DEBUG_COUT(MTL__FUNCTION_NAME__ << std::endl);
392
393 if (IsOpen())
394 {
395 m_Status = viClose(m_InstrSession);
396 MTL_Assert(VI_SUCCESS == m_Status || VI_ERROR_CLOSING_FAILED == m_Status);
397 m_InstrSession = 0;
398 l_DebugCheckStatus(m_InstrSession, m_Status);
399 }
400}
402{
403 return (0 != m_InstrSession);
404}
405
406//------------------------------------------//
407// Info
409{
411
412 // According to the NI-VISA Programmer Reference Manual:
413 // "If the string cannot be interpreted, the operation returns the warning
414 // code VI_WARN_UNKNOWN_STATUS. However, the output string desc is valid
415 // regardless of the status return value."
416 // So, regardless of the return error code, we return the description.
417 static ViChar Desc[VI_STATUS_DESC_MAX_LEN];
418 viStatusDesc(m_InstrSession, Status, Desc);
419 return std::string(Desc);
420}
421
422const ViSession & CVISAInstrument::Session()
423{
425
426 return m_InstrSession;
427}
429{
431
432 return m_Status == VI_ERROR_TMO;
433}
434
435//------------------------------------------//
436// Write / Read
437bool CVISAInstrument::Write(const char * Str)
438{
440
441 return Write(reinterpret_cast<ViBuf>(const_cast<char *>(Str)), static_cast<ViUInt32>(std::strlen(Str)));
442}
443bool CVISAInstrument::Write(const std::string & rStr)
444{
446
447 return Write(reinterpret_cast<ViBuf>(const_cast<char *>(rStr.c_str())), static_cast<ViUInt32>(rStr.length()));
448}
450{
452
453 return Write(reinterpret_cast<ViBuf>(const_cast<char *>(rBuf.data())), static_cast<ViUInt32>(rBuf.size()));
454}
455bool CVISAInstrument::Write(const ViBuf WriteBuf, ViUInt32 BuffLen)
456{
457 MTL_VISA_INSTRUMENT_DEBUG_COUT(MTL__FUNCTION_NAME__ << std::endl);
459
460 ViUInt32 retCount;
461 try {
462 m_Status = viWrite(m_InstrSession, WriteBuf, BuffLen, &retCount);
463 if (VI_SUCCESS != m_Status)
464 throw m_Status;
465 }
466 catch (I32 & rS)
467 {
468 MTL_Unused(rS);
469 l_DebugCheckStatus(m_InstrSession, rS);
470 viClear(m_InstrSession);
471 return false;
472 }
473 return (m_Status == VI_SUCCESS && BuffLen == retCount);
474}
475bool CVISAInstrument::Read(CSCPIBuffer & rBuf, bool Append)
476{
478
479 bool l_Ret;
480 ViUInt32 l_RetLen;
481 if (!Append)
482 {
483 l_Ret = Read(reinterpret_cast<ViPBuf>(rBuf.data()), static_cast<ViUInt32>(rBuf.capacity()), l_RetLen);
484 rBuf.resize(l_RetLen);
485 }
486 else
487 {
488 // Append. First increase capacity if buffer is full.
489 size_t l_Size = rBuf.size();
490 size_t l_Capacity = rBuf.capacity();
491 if (l_Size >= l_Capacity)
492 {
493 l_Capacity *= 2;
494 rBuf.reserve(l_Capacity);
495 }
496 l_Ret = Read(reinterpret_cast<ViPBuf>(rBuf.data() + l_Size), static_cast<ViUInt32>(l_Capacity - l_Size), l_RetLen);
497 rBuf.resize(l_Size + l_RetLen);
498 }
499 return l_Ret;
500}
501bool CVISAInstrument::Read(ViPBuf ReadBuf, ViUInt32 ReadLen, ViUInt32 & rRetLen)
502{
503 MTL_VISA_INSTRUMENT_DEBUG_COUT(MTL__FUNCTION_NAME__ << std::endl);
505
506 m_Status = viRead(m_InstrSession, ReadBuf, ReadLen, &rRetLen);
507 switch (m_Status)
508 {
509 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.
510 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.
511 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.
512 return true;
513 default:
514 l_DebugCheckStatus(m_InstrSession, m_Status);
515 return false;
516 }
517}
518
519//------------------------------------------//
520// Other operations
522{
523 MTL_VISA_INSTRUMENT_DEBUG_COUT(MTL__FUNCTION_NAME__ << std::endl);
525
526 m_Status = viSetAttribute(m_InstrSession, VI_ATTR_TMO_VALUE, Timeout);
527 if (m_Status == VI_SUCCESS)
529
530 l_DebugCheckStatus(m_InstrSession, m_Status);
531 return (m_Status == VI_SUCCESS);
532}
534{
535 MTL_VISA_INSTRUMENT_DEBUG_COUT(MTL__FUNCTION_NAME__ << std::endl);
537
538 m_Status = viClear(m_InstrSession);
539 l_DebugCheckStatus(m_InstrSession, m_Status);
540 return (m_Status == VI_SUCCESS);
541}
542bool CVISAInstrument::ReadSTB(ViUInt16 & rSTB)
543{
544 MTL_VISA_INSTRUMENT_DEBUG_COUT(MTL__FUNCTION_NAME__ << std::endl);
546
547#if (defined(ACTIVATE_READ_STB_WORKAROUND) && ACTIVATE_READ_STB_WORKAROUND)
548 // A bug was introduced in VISA 14. Despite our efforts to convince NI to fix the bug, we today have to deal with it...
549 // 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.
550 // Our workaround :
551 // We reduce the timeout to 10 ms to avoid blocking into the Read STB VI for a long time.
552 // 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.
553 // To prevent from asking the STB right after if failed, a 5ms delay is performed between each retry.
554 try {
555 // Save current timeout
556 ViUInt32 l_CurrentTimeout;
557 m_Status = viGetAttribute(m_InstrSession, VI_ATTR_TMO_VALUE, &l_CurrentTimeout);
558 if (m_Status != VI_SUCCESS) throw false;
559 // Set current timeout to avoid blocking too long
560 m_Status = viSetAttribute(m_InstrSession, VI_ATTR_TMO_VALUE, READ_STB_WORKAROUND_POLL_PERIOD_MS);
561 if (m_Status != VI_SUCCESS) throw false;
562 // Try to read STB while there is a known error
563 for (unsigned char NoRetries = 5; NoRetries > 0; NoRetries--)
564 {
565 m_Status = viReadSTB(m_InstrSession, &rSTB);
566 // Sleep for 5 ms in case of error to reduce polling period
567 if (m_Status == VI_ERROR_TMO || m_Status == VI_ERROR_INV_PROT)
568 {
569 l_DebugCheckStatus(m_InstrSession, m_Status);
570 MTL_VISA_INSTRUMENT_DEBUG_CERR("CVISAInstrument::ReadSTB failed. Retrying." << std::endl);
572 }
573 // Break the loop if we finally got our STB
574 else
575 {
576 break;
577 }
578 }
579 m_Status = viSetAttribute(m_InstrSession, VI_ATTR_TMO_VALUE, l_CurrentTimeout);
580 if (m_Status != VI_SUCCESS) throw false;
581 }
582 catch (bool & rE)
583 {
584 MTL_Unused(rE);
585 l_DebugCheckStatus(m_InstrSession, m_Status);
586 return false;
587 }
588#else
589 m_Status = viReadSTB(m_InstrSession, &rSTB);
590#endif
591 l_DebugCheckStatus(m_InstrSession, m_Status);
592 return (m_Status == VI_SUCCESS);
593}
599{
600 MTL_VISA_INSTRUMENT_DEBUG_COUT(MTL__FUNCTION_NAME__ << std::endl);
602
603 m_Status = viAssertTrigger(m_InstrSession, static_cast<ViUInt16>(Protocol));
604 l_DebugCheckStatus(m_InstrSession, m_Status);
605 return (m_Status == VI_SUCCESS);
606}
607
608//------------------------------------------//
609// Lock / Unlock
611{
612 MTL_VISA_INSTRUMENT_DEBUG_COUT(MTL__FUNCTION_NAME__ << std::endl);
614
615 m_Status = viLock(m_InstrSession, VI_EXCLUSIVE_LOCK, static_cast<ViUInt32>(Timeout), nullptr, nullptr);
616 switch (m_Status)
617 {
618 case VI_SUCCESS:
619 case VI_SUCCESS_NESTED_EXCLUSIVE:
620 case VI_SUCCESS_NESTED_SHARED:
621 m_ExclusiveLock = true;
622 return true;
623 default:
624 l_DebugCheckStatus(m_InstrSession, m_Status);
625 return false;
626 }
627}
628bool CVISAInstrument::LockShared(ViUInt32 Timeout, ViKeyId RequestedKey, ViChar AccessKey[])
629{
630 MTL_VISA_INSTRUMENT_DEBUG_COUT(MTL__FUNCTION_NAME__ << std::endl);
632
633 m_Status = viLock(m_InstrSession, VI_SHARED_LOCK, Timeout, RequestedKey, AccessKey);
634 switch (m_Status)
635 {
636 case VI_SUCCESS: // Lock successfully relinquished.
637 case VI_SUCCESS_NESTED_EXCLUSIVE: // Call succeeded, but this session still has nested exclusive locks.
638 case VI_SUCCESS_NESTED_SHARED: // Call succeeded, but this session still has nested shared locks.
639 return true;
640 default:
641 l_DebugCheckStatus(m_InstrSession, m_Status);
642 return false;
643 }
644}
646{
647 MTL_VISA_INSTRUMENT_DEBUG_COUT(MTL__FUNCTION_NAME__ << std::endl);
649
650 m_Status = viUnlock(m_InstrSession);
651 switch (m_Status)
652 {
653 case VI_SUCCESS: // Lock successfully relinquished.
654 case VI_SUCCESS_NESTED_EXCLUSIVE: // Call succeeded, but this session still has nested exclusive locks.
655 case VI_SUCCESS_NESTED_SHARED: // Call succeeded, but this session still has nested shared locks.
656 m_ExclusiveLock = false;
657 return true;
658 default:
659 l_DebugCheckStatus(m_InstrSession, m_Status);
660 return false;
661 }
662}
664{
665 return m_ExclusiveLock;
666}
667
668//------------------------------------------//
669// Events
687{
688 MTL_VISA_INSTRUMENT_DEBUG_COUT(MTL__FUNCTION_NAME__ << std::endl);
690
691 m_Status = viEnableEvent(m_InstrSession, static_cast<ViEventType>(Type), static_cast<ViUInt16>(Mechanism), VI_NULL);
692 switch (m_Status)
693 {
694 case VI_SUCCESS: // Event enabled successfully.
695 case VI_SUCCESS_EVENT_EN: // Specified event is already enabled for at least one of the specified mechanisms.
696 return true;
697 default:
698 l_DebugCheckStatus(m_InstrSession, m_Status);
699 return false;
700 }
701}
703{
704 MTL_VISA_INSTRUMENT_DEBUG_COUT(MTL__FUNCTION_NAME__ << std::endl);
706
707 m_Status = viDisableEvent(m_InstrSession, static_cast<ViEventType>(Type), static_cast<ViUInt16>(Mechanism));
708 switch (m_Status)
709 {
710 case VI_SUCCESS: // Event disabled successfully.
711 case VI_SUCCESS_EVENT_DIS: // Specified event is already disabled for at least one of the specified mechanisms.
712 return true;
713 default:
714 l_DebugCheckStatus(m_InstrSession, m_Status);
715 return false;
716 }
717}
719{
720 MTL_VISA_INSTRUMENT_DEBUG_COUT(MTL__FUNCTION_NAME__ << std::endl);
722
723 m_Status = viWaitOnEvent(m_InstrSession, static_cast<ViEventType>(Type), Timeout, nullptr, nullptr);
724 switch (m_Status)
725 {
726 case VI_SUCCESS: // Wait terminated successfully on receipt of an event occurrence.The queue is empty.
727 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.
728 return true;
729 default:
730 l_DebugCheckStatus(m_InstrSession, m_Status);
731 return false;
732 }
733}
735{
736 MTL_VISA_INSTRUMENT_DEBUG_COUT(MTL__FUNCTION_NAME__ << std::endl);
738
739 m_Status = viWaitOnEvent(m_InstrSession, VI_ALL_ENABLED_EVENTS, Timeout, nullptr, nullptr);
740 switch (m_Status)
741 {
742 case VI_SUCCESS: // Wait terminated successfully on receipt of an event occurrence.The queue is empty.
743 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.
744 return true;
745 default:
746 l_DebugCheckStatus(m_InstrSession, m_Status);
747 return false;
748 }
749}
751{
752 MTL_VISA_INSTRUMENT_DEBUG_COUT(MTL__FUNCTION_NAME__ << std::endl);
754
755 m_Status = viDiscardEvents(m_InstrSession, static_cast<ViEventType>(Type), static_cast<ViUInt16>(Mechanism));
756 switch (m_Status)
757 {
758 case VI_SUCCESS: // Event queue flushed successfully.
759 case VI_SUCCESS_QUEUE_EMPTY: // Operation completed successfully, but queue was already empty.
760 return true;
761 default:
762 l_DebugCheckStatus(m_InstrSession, m_Status);
763 return false;
764 }
765}
766
767//------------------------------------------//
768// Attributes
769bool CVISAInstrument::GetAttribute(ViAttr Attribute, void * Value)
770{
771 MTL_VISA_INSTRUMENT_DEBUG_COUT(MTL__FUNCTION_NAME__ << std::endl);
773
774 m_Status = viGetAttribute(m_InstrSession, Attribute, Value);
775 switch (m_Status)
776 {
777 case VI_SUCCESS: // Event queue flushed successfully.
778 return true;
779 case VI_ERROR_INV_OBJECT: // The given object reference is invalid.
780 case VI_ERROR_NSUP_ATTR: // The specified attribute is not defined by the referenced object.
781 default:
782 l_DebugCheckStatus(m_InstrSession, m_Status);
783 return false;
784 }
785}
786
787//------------------------------------------//
788// USB
789bool CVISAInstrument::UsbControlIn(ViInt16 bmRequestType, ViInt16 bRequest, ViUInt16 wValue, ViUInt16 wIndex, ViUInt16 wLength, ViPBuf buf, ViUInt16 & rretCnt)
790{
791 MTL_VISA_INSTRUMENT_DEBUG_COUT(MTL__FUNCTION_NAME__ << std::endl);
793
794 m_Status = viUsbControlIn(m_InstrSession, bmRequestType, bRequest, wValue, wIndex, wLength, buf, &rretCnt);
795 switch (m_Status)
796 {
797 case VI_SUCCESS:
798 return true;
799 case VI_ERROR_INV_OBJECT: // The given session reference is invalid.
800 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.
801 case VI_ERROR_TMO: // Timeout expired before operation completed.
802 case VI_ERROR_INV_SETUP: // Unable to start write operation because setup is invalid(due to attributes being set to an inconsistent state).
803 case VI_ERROR_IO: // An unknown I/O error occurred during transfer.
804 case VI_ERROR_CONN_LOST: // The I/O connection for the given session has been lost.
805 case VI_ERROR_INV_PARAMETER: // The value of some parameter�which parameter is not known�is invalid.
806 case VI_ERROR_INV_MASK: // The bmRequestType parameter contains an invalid mask.
807 default:
808 l_DebugCheckStatus(m_InstrSession, m_Status);
809 return false;
810 }
811}
812
813bool CVISAInstrument::UsbControlOut(ViInt16 bmRequestType, ViInt16 bRequest, ViUInt16 wValue, ViUInt16 wIndex, ViUInt16 wLength, ViBuf buf)
814{
815 MTL_VISA_INSTRUMENT_DEBUG_COUT(MTL__FUNCTION_NAME__ << std::endl);
817
818 m_Status = viUsbControlOut(m_InstrSession, bmRequestType, bRequest, wValue, wIndex, wLength, buf);
819 switch (m_Status)
820 {
821 case VI_SUCCESS:
822 return true;
823 case VI_ERROR_INV_OBJECT: // The given session reference is invalid.
824 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.
825 case VI_ERROR_TMO: // Timeout expired before operation completed.
826 case VI_ERROR_INV_SETUP: // Unable to start write operation because setup is invalid(due to attributes being set to an inconsistent state).
827 case VI_ERROR_IO: // An unknown I/O error occurred during transfer.
828 case VI_ERROR_CONN_LOST: // The I/O connection for the given session has been lost.
829 case VI_ERROR_INV_PARAMETER: // The value of some parameter�which parameter is not known�is invalid.
830 case VI_ERROR_INV_MASK: // The bmRequestType parameter contains an invalid mask.
831 default:
832 l_DebugCheckStatus(m_InstrSession, m_Status);
833 return false;
834 }
835}
836
837//------------------------------------------//
838//Serial (ASRL)
840{
841 MTL_VISA_INSTRUMENT_DEBUG_COUT(MTL__FUNCTION_NAME__ << std::endl);
843
844 try {
845 // set Baud Rate
846 m_Status = viSetAttribute(m_InstrSession, VI_ATTR_ASRL_BAUD, static_cast<ViAttrState>(rPortSettings.Baudrate));
847 if (m_Status != VI_SUCCESS) throw false;
848
849 // set Data Bits length
850 m_Status = viSetAttribute(m_InstrSession, VI_ATTR_ASRL_DATA_BITS, static_cast<ViAttrState>(rPortSettings.DataBits));
851 if (m_Status != VI_SUCCESS) throw false;
852
853 // set Parity
854 m_Status = viSetAttribute(m_InstrSession, VI_ATTR_ASRL_PARITY, static_cast<ViAttrState>(rPortSettings.Parity));
855 if (m_Status != VI_SUCCESS) throw false;
856
857 // set Stop bits
858 m_Status = viSetAttribute(m_InstrSession, VI_ATTR_ASRL_STOP_BITS, static_cast<ViAttrState>(rPortSettings.StopBits));
859 if (m_Status != VI_SUCCESS) throw false;
860
861 // set Flow control
862 m_Status = viSetAttribute(m_InstrSession, VI_ATTR_ASRL_FLOW_CNTRL, static_cast<ViAttrState>(rPortSettings.Handshake));
863 if (m_Status != VI_SUCCESS) throw false;
864
865 // set Read Termination Character Mode
866 m_Status = viSetAttribute(m_InstrSession, VI_ATTR_ASRL_END_IN, static_cast<ViAttrState>(rPortSettings.ReadTermMode));
867 if (m_Status != VI_SUCCESS) throw false;
868
869 if (rPortSettings.ReadTermMode == eSerialTermMode::kEndTermChar)
870 {
871 // set a specific Read Termination Character
872 m_Status = viSetAttribute(m_InstrSession, VI_ATTR_TERMCHAR, static_cast<ViAttrState>(rPortSettings.ReadTermChar));
873 if (m_Status != VI_SUCCESS) throw false;
874
875 // Enable specific Read Termination Character
876 m_Status = viSetAttribute(m_InstrSession, VI_ATTR_TERMCHAR_EN, static_cast<ViAttrState>(true));
877 if (m_Status != VI_SUCCESS) throw false;
878 }
879 else
880 {
881 // Disable specific Read Termination Character
882 m_Status = viSetAttribute(m_InstrSession, VI_ATTR_TERMCHAR_EN, static_cast<ViAttrState>(false));
883 if (m_Status != VI_SUCCESS) throw false;
884 }
885 }
886 catch (bool & rE)
887 {
888 MTL_Unused(rE);
889 l_DebugCheckStatus(m_InstrSession, m_Status);
890 return false;
891 }
892
893 return true;
894}
Collection of utility macros for error messages.
#define MTL_Assert
Definition Helpers.h:44
#define MTL_Unused(x)
Definition Helpers.h:47
Platform Dependent Definitions.
int I32
32-bit signed integer.
Definition OSDefines.h:27
unsigned int U32
32-bit unsigned integer.
Definition OSDefines.h:31
#define MTL_VISA_INSTRUMENT_DEBUG_CERR(__X__)
#define READ_STB_WORKAROUND_POLL_PERIOD_MS
#define VI_STATUS_DESC_MAX_LEN
#define MTL_VISA_INSTRUMENT_DEBUG_COUT(__X__)
#define l_DebugCheckStatus(__X__, __Y__)
C++ wrapper for NI-VISA: interface definition.
CRecursiveMutex m_Lock
Lock onto the class interface.
tResourceName m_Rsrc
Resource name of the instrument.
CIEEE488ResourceManager & m_rRrsrcMan
Reference to the associated resource manager.
bool SetTimeout(U32 Timeout)
Set the timeout for this instrument.
CIEEE488Instrument(CIEEE488ResourceManager &rRM, tResourceName Rsrc)
Constructor.
I32 m_Status
Status of last operation.
CMutex m_Lock
Lock onto the resource manager.
I32 m_Status
Status of last operation.
Parsed resource information for a list of instruments.
List of VISA resource names.
void resize(size_t size)
Resize the buffer.
MTL_INSTRUMENT_BUFFER_TYPE * data() noexcept
Return a pointer to the data.
void reserve(size_t capacity)
Allocate at least a given amount of space.
size_t capacity() const
Return the buffer capacity (allocated size).
size_t size() const
Return the buffer size.
virtual bool Unlock()
Unlock the session.
virtual bool Open(void)
Open a session to this VISA instrument.
const ViSession & Session()
Return instrument session identifier.
virtual ~CVISAInstrument()
Destructor.
virtual bool LockExclusive(U32 Timeout)
Obtain an exclusive lock for this session.
virtual bool Read(CSCPIBuffer &rBuf, bool Append=false)
Read from a VISA instrument: SCPI buffer class variant.
virtual bool Timeout()
Last operation timed out.
virtual bool Clear()
Clear the instrument.
virtual bool ReadSTB(ViUInt16 &rSTB)
Read status byte.
virtual bool LockedExclusive()
Check whether session is locked exclusively.
virtual bool DiscardEvents(void)
Discard service requests.
bool WaitOnAllEvents(ViUInt32 Timeout)
Wait for all events.
virtual void Close()
Close session to this VISA instrument.
virtual bool IsOpen()
Check whether a session to this instrument is open.
bool ConfigSerialPort(const sSerialPortSettings &rPortSettings)
Set all the instrument attributes to configure the serial communication.
virtual bool AssertTrigger(void)
Assert a trigger.
virtual bool Write(const char *Str)
Write to a VISA instrument: C string variant.
virtual bool SetTimeout(ViUInt32 Timeout)
Set the timeout for this instrument session.
virtual bool DisableEvent(void)
Disable service requests.
bool UsbControlIn(ViInt16 bmRequestType, ViInt16 bRequest, ViUInt16 wValue, ViUInt16 wIndex, ViUInt16 wLength, ViPBuf buf, ViUInt16 &rretCnt)
Performs a USB control pipe transfer from the instrument.
bool LockShared(ViUInt32 Timeout, ViKeyId RequestedKey, ViChar AccessKey[])
Obtain a shared lock for this session.
bool UsbControlOut(ViInt16 bmRequestType, ViInt16 bRequest, ViUInt16 wValue, ViUInt16 wIndex, ViUInt16 wLength, ViBuf buf)
Performs a USB control pipe transfer to the instrument.
virtual bool WaitOnEvent(U32 Timeout)
Wait for a service request.
bool GetAttribute(ViAttr Attribute, void *Value)
Retrieves the state of an attribute.
virtual std::string StatusDescription(I32 Status)
Return description of status word.
CVISAInstrument(CVISAResourceManager &rRM, tResourceName Rsrc)
Constructor.
virtual bool EnableEvent(void)
Enable service requests.
VISA Resource Manager class.
virtual bool Initialize()
Initialize the Resource Manager.
const ViSession & Session()
Return Resource Manager session identifier.
virtual std::string StatusDescription(I32 Status)
Return description of status word.
virtual bool Timeout()
Last operation timed out.
ViStatus Status()
Return Resource Manager status.
bool ResourceInfo(tResourceName &rRsrc, eInterfaceType &rIntfType, tInterfaceNumber &rIntfNumber)
Get the interface type and number for the given VISA resource name.
virtual bool FindResources(CResourceList &rList, std::string Filter="?*")
Find VISA resources.
Information about a VISA resource.
std::string tClass
Class: INSTR / RAW / ...
std::string tExpandedName
Full resource name.
std::string tResourceName
IEEE488 resource name.
eEventMechanism
Event mechanisms.
@ Queue
Enable the session to queue events.
std::string StatusDescription(ViSession Session, ViStatus Status)
Return user-readable description of the given status code.
ViUInt16 tInterfaceNumber
Interface number.
eOpenAccessMode
Access modes for VISA resources.
@ NoLock
Open session without using an exclusive lock or loading configuration information.
eInterfaceType
VISA interface types.
eTriggerProtocol
Trigger protocols.
@ kEndTermChar
Set termination character to the one specified by VI_ATTR_TERMCHAR()
@ ServiceRequest
Service request was received from device or interface.
Parsed information about a VISA resource.
eSerialDataBits DataBits
[-] Number of transmitted bits per packet
eSerialHandshake Handshake
[-] Handshake configuration of the serial communication
eSerialBaudrate Baudrate
[bd] Speed of the serial communication
eSerialStopBits StopBits
[-] Stop bit configuration of the serial communication
eSerialParity Parity
[-] Parity configuration of the serial communication
eSerialTermMode ReadTermMode
[-] Termination Read mode of the serial communication
char ReadTermChar
[-] Specific termination character when readTermMode = kEndTermChar