DynExp
Highly flexible laboratory automation for dynamically changing experiments.
Loading...
Searching...
No Matches
HardwareAdapterZILabOne.cpp
Go to the documentation of this file.
1// This file is part of DynExp.
2
3#include "stdafx.h"
5
6namespace DynExpHardware
7{
9 {
10 ZILabOneHardwareAdapterSyms::ZIConnection TempConnection;
11 auto Result = ZILabOneHardwareAdapterSyms::ziAPIInit(&TempConnection);
12 if (Result != ZILabOneHardwareAdapterSyms::ZI_INFO_SUCCESS)
13 throw ZILabOneException("Error enumerating ZI instruments.", Result);
14
15 std::string DeviceList;
16 for (int i = 1; i < 100; ++i)
17 {
18 DeviceList.resize(i * 256);
19
20 // Since C++17, writing to std::string's internal buffer is allowed.
21 Result = ZILabOneHardwareAdapterSyms::ziAPIDiscoveryFindAll(TempConnection, DeviceList.data(), Util::NumToT<uint32_t>(DeviceList.size()));
22 if (Result != ZILabOneHardwareAdapterSyms::ZI_ERROR_LENGTH)
23 break;
24 }
25
26 ZILabOneHardwareAdapterSyms::ziAPIDestroy(TempConnection);
27
28 // Check result of ziAPIDiscoveryFindAll() here.
29 if (Result != ZILabOneHardwareAdapterSyms::ZI_INFO_SUCCESS)
30 throw ZILabOneException("Error enumerating ZI instruments.", Result);
31
32 // All descriptors are separated by '\n'. Replace that by ' ' and use std::istringstream to split by ' '.
33 std::vector<std::string> DeviceDescriptors;
34 if (DeviceList[0] != '\0')
35 {
36 std::replace(DeviceList.begin(), DeviceList.end(), '\n', ' ');
37 std::string DeviceListRemovedZeros;
38 std::remove_copy(DeviceList.begin(), DeviceList.end(), std::back_inserter(DeviceListRemovedZeros), '\0');
39 std::istringstream ss(DeviceListRemovedZeros);
40 DeviceDescriptors = { std::istream_iterator<std::string>(ss), std::istream_iterator<std::string>() };
41 }
42
43 return DeviceDescriptors;
44 }
45
47 {
48 auto ZILabOneHardwareAdapterDevices = ZILabOneHardwareAdapter::Enumerate();
49 if (!DeviceDescriptor.Get().empty() &&
50 std::find(ZILabOneHardwareAdapterDevices.cbegin(), ZILabOneHardwareAdapterDevices.cend(), DeviceDescriptor) == std::cend(ZILabOneHardwareAdapterDevices))
51 ZILabOneHardwareAdapterDevices.push_back(DeviceDescriptor);
52 if (ZILabOneHardwareAdapterDevices.empty())
53 throw Util::EmptyException("There is not any available ZILabOneHardwareAdapter controller.");
54
55 DeviceDescriptor.SetTextList(std::move(ZILabOneHardwareAdapterDevices));
56
58 }
59
61 : HardwareAdapterBase(OwnerThreadID, std::move(Params))
62 {
63 Init();
64 }
65
67 {
68 // Not locking, since the object is being destroyed. This should be inherently thread-safe.
70 ZILabOneHardwareAdapterSyms::ziAPIDestroy(ZIConnection);
71 }
72
73 void ZILabOneHardwareAdapter::ConfigureInput(SignalInputType SignalInput, uint8_t Demodulator) const
74 {
76
77 ConfigureInputUnsafe(SignalInput, Demodulator);
78 }
79
80 double ZILabOneHardwareAdapter::StartAcquisition(uint8_t Demodulator, size_t NumSamples, size_t NumRuns, bool AverageRuns) const
81 {
83
84 StartAcquisitionUnsafe(Demodulator, NumSamples, NumRuns, AverageRuns);
85
86 return static_cast<double>(NumSamples) / GetDemodSamplingRateUnsafe(Demodulator);
87 }
88
95
102
109
116
123
124 std::vector<DynExpInstr::LockinAmplifierDefs::LockinSample> ZILabOneHardwareAdapter::GetAcquiredData() const
125 {
127
128 return GetAcquiredDataUnsafe();
129 }
130
132 {
134
135 return GetInputRangeUnsafe(SignalInput);
136 }
137
138 void ZILabOneHardwareAdapter::SetInputRange(SignalInputType SignalInput, double InputRange) const
139 {
141
142 SetInputRangeUnsafe(SignalInput, InputRange);
143 }
144
151
153 {
155
156 return IsInputOverloadUnsafe(SignalInput);
157 }
158
160 {
162
163 return GetNegInputLoadUnsafe(SignalInput);
164 }
165
167 {
169
170 return GetPosInputLoadUnsafe(SignalInput);
171 }
172
173 double ZILabOneHardwareAdapter::GetDemodPhase(uint8_t Demodulator) const
174 {
176
177 return GetDemodPhaseUnsafe(Demodulator);
178 }
179
180 void ZILabOneHardwareAdapter::SetDemodPhase(uint8_t Demodulator, double Phase) const
181 {
183
184 SetDemodPhaseUnsafe(Demodulator, Phase);
185 }
186
187 void ZILabOneHardwareAdapter::AutoAdjustDemodPhase(uint8_t Demodulator) const
188 {
190
191 AutoAdjustDemodPhaseUnsafe(Demodulator);
192 }
193
194 double ZILabOneHardwareAdapter::GetDemodTimeConstant(uint8_t Demodulator) const
195 {
197
198 return GetDemodTimeConstantUnsafe(Demodulator);
199 }
200
201 void ZILabOneHardwareAdapter::SetDemodTimeConstant(uint8_t Demodulator, double TimeConstant) const
202 {
204
205 SetDemodTimeConstantUnsafe(Demodulator, TimeConstant);
206 }
207
208 uint8_t ZILabOneHardwareAdapter::GetDemodFilterOrder(uint8_t Demodulator) const
209 {
211
212 return GetDemodFilterOrderUnsafe(Demodulator);
213 }
214
215 void ZILabOneHardwareAdapter::SetDemodFilterOrder(uint8_t Demodulator, uint8_t FilterOrder) const
216 {
218
219 SetDemodFilterOrderUnsafe(Demodulator, FilterOrder);
220 }
221
228
229 void ZILabOneHardwareAdapter::SetTriggerMode(DynExpInstr::LockinAmplifierDefs::TriggerModeType TriggerMode, uint8_t Demodulator, uint8_t TriggerChannel) const
230 {
232
233 SetTriggerModeUnsafe(TriggerMode, Demodulator, TriggerChannel);
234 }
235
242
249
250 double ZILabOneHardwareAdapter::GetDemodSamplingRate(uint8_t Demodulator) const
251 {
253
254 return GetDemodSamplingRateUnsafe(Demodulator);
255 }
256
257 void ZILabOneHardwareAdapter::SetDemodSamplingRate(uint8_t Demodulator, double SamplingRate) const
258 {
260
261 SetDemodSamplingRateUnsafe(Demodulator, SamplingRate);
262 }
263
264 bool ZILabOneHardwareAdapter::GetEnabled(uint8_t Demodulator) const
265 {
267
268 return GetEnabledUnsafe(Demodulator);
269 }
270
271 void ZILabOneHardwareAdapter::SetEnabled(uint8_t Demodulator, bool Enabled) const
272 {
274
275 SetEnabledUnsafe(Demodulator, Enabled);
276 }
277
278 double ZILabOneHardwareAdapter::GetOscillatorFrequency(uint8_t Oscillator) const
279 {
281
282 return GetOscillatorFrequencyUnsafe(Oscillator);
283 }
284
286 {
287 auto Result = ZILabOneHardwareAdapterSyms::ziAPIInit(&ZIConnection);
288 CheckError(Result);
289
290 Opened = false;
291
292 auto DerivedParams = dynamic_Params_cast<ZILabOneHardwareAdapter>(GetParams());
293 DeviceDescriptor = DerivedParams->DeviceDescriptor;
294 Interface = DerivedParams->Interface;
295 Clockbase = 1;
296 }
297
299 {
300 // auto lock = AcquireLock(); not necessary here, since DynExp ensures that Object::Reset() can only
301 // be called if respective object is not in use.
302
303 CloseUnsafe();
304 ZILabOneHardwareAdapterSyms::ziAPIDestroy(ZIConnection);
305
306 Init();
307
309 }
310
317
319 {
321
322 auto Exception = GetExceptionUnsafe();
323 Util::ForwardException(Exception);
324
325 return IsOpened();
326 }
327
329 {
330 return IsOpened();
331 }
332
333 void ZILabOneHardwareAdapter::CheckError(const ZILabOneHardwareAdapterSyms::ZIResult_enum Result, const std::source_location Location) const
334 {
335 if (Result == ZILabOneHardwareAdapterSyms::ZI_INFO_SUCCESS)
336 return;
337
338 char* ErrorString = nullptr;
339 ZILabOneHardwareAdapterSyms::ziAPIGetError(Result, &ErrorString, nullptr);
340
341 // AcquireLock() has already been called by an (in)direct caller of this function.
342 if (ErrorString)
343 ThrowExceptionUnsafe(std::make_exception_ptr(ZILabOneException(ErrorString, Result, Location)));
344 else
345 ThrowExceptionUnsafe(std::make_exception_ptr(ZILabOneException("< No description available. >", Result, Location)));
346 }
347
349 {
350 if (IsOpened())
351 return;
352
353 const char* DeviceID = nullptr;
354 const char* ServerAddress;
355 ZILabOneHardwareAdapterSyms::ZIIntegerData Port = 0;
356 ZILabOneHardwareAdapterSyms::ZIIntegerData APILevel = 6;
357
358 auto Result = ZILabOneHardwareAdapterSyms::ziAPIDiscoveryFind(ZIConnection, DeviceDescriptor.c_str(), &DeviceID);
359 CheckError(Result);
360 if (DeviceID)
361 DeviceDescriptor = DeviceID; // To get rid of some trailing zeros.
362
363 Result = ZILabOneHardwareAdapterSyms::ziAPIDiscoveryGetValueS(ZIConnection, DeviceDescriptor.c_str(), "serveraddress", &ServerAddress);
364 CheckError(Result);
365 Result = ZILabOneHardwareAdapterSyms::ziAPIDiscoveryGetValueI(ZIConnection, DeviceDescriptor.c_str(), "serverport", &Port);
366 CheckError(Result);
367 Result = ZILabOneHardwareAdapterSyms::ziAPIDiscoveryGetValueI(ZIConnection, DeviceDescriptor.c_str(), "apilevel", &APILevel);
368 CheckError(Result);
369 Result = ZILabOneHardwareAdapterSyms::ziAPIConnectEx(ZIConnection, ServerAddress, static_cast<uint16_t>(Port),
370 static_cast<ZILabOneHardwareAdapterSyms::ZIAPIVersion_enum>(APILevel), nullptr);
371 CheckError(Result);
372
373 const char* Connected;
374 Result = ZILabOneHardwareAdapterSyms::ziAPIDiscoveryGetValueS(ZIConnection, DeviceDescriptor.c_str(), "connected", &Connected);
375 CheckError(Result);
376 if (std::string(Connected).empty())
377 {
378 // Connect to data server if not connected yet.
379 const char* Interfaces;
380 ZILabOneHardwareAdapterSyms::ziAPIDiscoveryGetValueS(ZIConnection, DeviceDescriptor.c_str(), "interfaces", &Interfaces);
381 CheckError(Result);
382
383 // All descriptors are separated by '\n'. Replace that by ' ' and use std::istringstream to split by ' '.
384 std::string InterfacesStr(Interfaces);
385 std::replace(InterfacesStr.begin(), InterfacesStr.end(), '\n', ' ');
386 std::istringstream ss(InterfacesStr);
387 std::vector<std::string> InterfacesList{ std::istream_iterator<std::string>(ss), std::istream_iterator<std::string>() };
388 if (InterfacesList.empty())
389 ThrowExceptionUnsafe(std::make_exception_ptr(Util::EmptyException(
390 "The interface list of the selected ZI instrument is empty.")));
391 if (std::find(InterfacesList.cbegin(), InterfacesList.cend(), Interface) == InterfacesList.cend())
392 ThrowExceptionUnsafe(std::make_exception_ptr(Util::NotFoundException(
393 "The ZI instrument does not support the specified interface for establishing a connection.")));
394
395 Result = ZILabOneHardwareAdapterSyms::ziAPIConnectDevice(ZIConnection, DeviceDescriptor.c_str(), Util::ToLower(Interface).c_str(), nullptr);
396 CheckError(Result);
397 }
398
399 Result = ZILabOneHardwareAdapterSyms::ziAPIModCreate(ZIConnection, &DAQModuleHandle, "dataAcquisitionModule");
400 CheckError(Result);
401 Result = ZILabOneHardwareAdapterSyms::ziAPIModSetString(ZIConnection, DAQModuleHandle, "device", DeviceDescriptor.c_str());
402 CheckError(Result);
403 Result = ZILabOneHardwareAdapterSyms::ziAPIModSetIntegerData(ZIConnection, DAQModuleHandle, "historylength", 1);
404 CheckError(Result);
405 Result = ZILabOneHardwareAdapterSyms::ziAPIModSetDoubleData(ZIConnection, DAQModuleHandle, "bandwidth", 0);
406 CheckError(Result);
407 Result = ZILabOneHardwareAdapterSyms::ziAPIModSetDoubleData(ZIConnection, DAQModuleHandle, "level", 1);
408 CheckError(Result);
409 Result = ZILabOneHardwareAdapterSyms::ziAPIModSetDoubleData(ZIConnection, DAQModuleHandle, "hysteresis", .01);
410 CheckError(Result);
411 Result = ZILabOneHardwareAdapterSyms::ziAPIModSetIntegerData(ZIConnection, DAQModuleHandle, "count", 1);
412 CheckError(Result);
413 Result = ZILabOneHardwareAdapterSyms::ziAPIModSetIntegerData(ZIConnection, DAQModuleHandle, "preview", 1);
414 CheckError(Result);
415
417
418 Clockbase = ReadDoubleUnsafe("clockbase");
419
420 Opened = true;
421 }
422
424 {
425 if (IsOpened())
426 {
427 // Handles now considered invalid, even if disconnecting fails.
428 Opened = false;
429
430 auto Result = ZILabOneHardwareAdapterSyms::ziAPIModClear(ZIConnection, DAQModuleHandle);
431 CheckError(Result);
432 Result = ZILabOneHardwareAdapterSyms::ziAPIDisconnectDevice(ZIConnection, DeviceDescriptor.c_str());
433 CheckError(Result);
434 Result = ZILabOneHardwareAdapterSyms::ziAPIDisconnect(ZIConnection);
435 CheckError(Result);
436 }
437 }
438
439 void ZILabOneHardwareAdapter::ConfigureInputUnsafe(SignalInputType SignalInput, uint8_t Demodulator) const
440 {
441 WriteIntUnsafe("demods/" + Util::ToStr(Demodulator) + "/adcselect", SignalInput == SignalInputType::Current);
442 if (SignalInput != SignalInputType::Current)
443 WriteIntUnsafe(SignalInputTypeToCmdStr(SignalInput) + "/0/diff", SignalInput == SignalInputType::DifferentialVoltage);
444 }
445
446 void ZILabOneHardwareAdapter::StartAcquisitionUnsafe(uint8_t Demodulator, size_t NumSamples, size_t NumRuns, bool AverageRuns) const
447 {
448 auto Result = ZILabOneHardwareAdapterSyms::ziAPIModSetIntegerData(ZIConnection, DAQModuleHandle, "grid/mode", 4); // Exact (on-grid)
449 CheckError(Result);
450 Result = ZILabOneHardwareAdapterSyms::ziAPIModSetIntegerData(ZIConnection, DAQModuleHandle, "grid/cols", NumSamples);
451 CheckError(Result);
452 Result = ZILabOneHardwareAdapterSyms::ziAPIModSetIntegerData(ZIConnection, DAQModuleHandle, "grid/rows", 1);
453 CheckError(Result);
454 Result = ZILabOneHardwareAdapterSyms::ziAPIModSetIntegerData(ZIConnection, DAQModuleHandle, "grid/repetitions", NumRuns);
455 CheckError(Result);
456 Result = ZILabOneHardwareAdapterSyms::ziAPIModSetIntegerData(ZIConnection, DAQModuleHandle, "grid/overwrite", !AverageRuns);
457 CheckError(Result);
458 Result = ZILabOneHardwareAdapterSyms::ziAPIModSetIntegerData(ZIConnection, DAQModuleHandle, "endless", 0);
459 CheckError(Result);
460
461 Result = ZILabOneHardwareAdapterSyms::ziAPIModSubscribe(ZIConnection, DAQModuleHandle,
462 ("/" + DeviceDescriptor + "/demods/" + Util::ToStr(Demodulator) + "/sample.x").c_str());
463 Result = ZILabOneHardwareAdapterSyms::ziAPIModSubscribe(ZIConnection, DAQModuleHandle,
464 ("/" + DeviceDescriptor + "/demods/" + Util::ToStr(Demodulator) + "/sample.y").c_str());
465 CheckError(Result);
466 Result = ZILabOneHardwareAdapterSyms::ziAPIModExecute(ZIConnection, DAQModuleHandle);
467 CheckError(Result);
468 }
469
471 {
472 auto Result = ZILabOneHardwareAdapterSyms::ziAPIModFinish(ZIConnection, DAQModuleHandle);
473 CheckError(Result);
474 Result = ZILabOneHardwareAdapterSyms::ziAPIModUnSubscribe(ZIConnection, DAQModuleHandle, "*");
475 CheckError(Result);
476 }
477
479 {
480 ZILabOneHardwareAdapterSyms::ZIIntegerData Finished = false;
481 auto Result = ZILabOneHardwareAdapterSyms::ziAPIModFinished(ZIConnection, DAQModuleHandle, &Finished);
482 CheckError(Result);
483
484 return Finished;
485 }
486
488 {
489 ZILabOneHardwareAdapterSyms::ZIDoubleData Progress{};
490 auto Result = ZILabOneHardwareAdapterSyms::ziAPIModProgress(ZIConnection, DAQModuleHandle, &Progress);
491 CheckError(Result);
492
493 return Progress;
494 }
495
497 {
498 auto Result = ZILabOneHardwareAdapterSyms::ziAPIModSetIntegerData(ZIConnection, DAQModuleHandle, "forcetrigger", 1);
499 CheckError(Result);
500 }
501
503 {
504 auto Result = ZILabOneHardwareAdapterSyms::ziAPIModSetIntegerData(ZIConnection, DAQModuleHandle, "clearhistory", 1);
505 CheckError(Result);
506 }
507
508 std::vector<DynExpInstr::LockinAmplifierDefs::LockinSample> ZILabOneHardwareAdapter::GetAcquiredDataUnsafe() const
509 {
510 std::map<double, DynExpInstr::LockinAmplifierDefs::LockinSample> RawSamples;
511 auto Result = ZILabOneHardwareAdapterSyms::ziAPIModRead(ZIConnection, DAQModuleHandle, "");
512 CheckError(Result);
513
514 std::string NodePath(1024, '\0');
515 ZILabOneHardwareAdapterSyms::ZIModuleEventPtr EventPtr = nullptr;
516 ZILabOneHardwareAdapterSyms::ZIValueType_enum EventValueType{};
517 uint64_t NumChunks{};
518 bool ZeroTimestampSet = false;
519 ZILabOneHardwareAdapterSyms::ZITimeStamp ZeroTimestamp{ 0 };
520
521 try
522 {
523 while (true)
524 {
525 Result = ZILabOneHardwareAdapterSyms::ziAPIModNextNode(ZIConnection, DAQModuleHandle,
526 NodePath.data(), Util::NumToT<uint32_t>(NodePath.length()), &EventValueType, &NumChunks);
527 if (Result == ZILabOneHardwareAdapterSyms::ZI_WARNING_NOTFOUND)
528 break;
529 CheckError(Result);
530
531 for (decltype(NumChunks) CurrentChunk = 0; CurrentChunk < NumChunks; ++CurrentChunk)
532 {
533 Result = ZILabOneHardwareAdapterSyms::ziAPIModGetChunk(ZIConnection, DAQModuleHandle, CurrentChunk, &EventPtr);
534 CheckError(Result);
535
536 if (EventPtr->value->valueType == ZILabOneHardwareAdapterSyms::ZI_VALUE_TYPE_DOUBLE_DATA_TS)
537 {
538 ZILabOneHardwareAdapterSyms::ZIEvent& e = *EventPtr->value;
539
540 // Obtain demodulator number from ".../demods/<demodulator number>/sample.<x/y>"
541 std::string Path(e.path, e.path + sizeof(e.path) / sizeof(e.path[0]));
542 auto StartDemodStr = Path.find("demods/") + 7;
543 auto EndDemodStr = Path.find("/sample");
544 auto Demodulator = std::stoul(Path.substr(StartDemodStr, EndDemodStr - StartDemodStr));
545 if (Demodulator > std::numeric_limits<uint8_t>::max())
546 ThrowExceptionUnsafe(std::make_exception_ptr(Util::OverflowException(
547 "A received demodulator number is invalid.")));
548
549 // Obtain x/y channel from ".../demods/<demodulator number>/sample.<x/y>"
550 auto StartChannelStr = Path.find("sample.") + 7;
551 auto Channel = Path.substr(StartChannelStr, 1);
552 if (Channel != "x" && Channel != "y")
553 ThrowExceptionUnsafe(std::make_exception_ptr(Util::InvalidDataException(
554 "A received demodulator channel is invalid.")));
555 bool IsX = Channel == "x";
556
557 for (size_t i = 0; i < e.count; ++i)
558 {
559 if (!ZeroTimestampSet)
560 {
561 ZeroTimestamp = e.value.doubleDataTS[i].timeStamp;
562 ZeroTimestampSet = true;
563 }
564
565 auto Timestamp = static_cast<double>(e.value.doubleDataTS[i].timeStamp - ZeroTimestamp) / Clockbase;
566 RawSamples[Timestamp].Time = Timestamp;
567 RawSamples[Timestamp].Channel = static_cast<uint8_t>(Demodulator);
568
569 if (IsX)
570 RawSamples[Timestamp].CartesianResult.X = e.value.doubleDataTS[i].value;
571 else
572 RawSamples[Timestamp].CartesianResult.Y = e.value.doubleDataTS[i].value;
573 }
574 }
575 }
576 }
577 }
578 catch (...)
579 {
580 // Ignore errors occurring here.
581 if (EventPtr)
582 ZILabOneHardwareAdapterSyms::ziAPIModEventDeallocate(ZIConnection, DAQModuleHandle, EventPtr);
583
584 throw;
585 }
586
587 if (EventPtr)
588 {
589 Result = ZILabOneHardwareAdapterSyms::ziAPIModEventDeallocate(ZIConnection, DAQModuleHandle, EventPtr);
590 CheckError(Result);
591 }
592
593 std::vector<DynExpInstr::LockinAmplifierDefs::LockinSample> Samples;
594 for (auto& Sample : RawSamples)
595 {
596 Sample.second.UpdatePolar();
597 Samples.push_back(Sample.second);
598 }
599
600 return Samples;
601 }
602
604 {
605 switch (SignalInput)
606 {
607 case SignalInputType::Current: return "currins";
608 default: return "sigins";
609 }
610 }
611
613 {
614 return ReadDoubleUnsafe(SignalInputTypeToCmdStr(SignalInput) + "/0/range");
615 }
616
617 void ZILabOneHardwareAdapter::SetInputRangeUnsafe(SignalInputType SignalInput, double InputRange) const
618 {
619 WriteDoubleUnsafe(SignalInputTypeToCmdStr(SignalInput) + "/0/range", InputRange);
620 }
621
623 {
624 WriteIntUnsafe(SignalInputTypeToCmdStr(SignalInput) + "/0/autorange", 1);
625 }
626
631
633 {
634 // Reading this value seems to take relatively much time.
635 return std::abs(ReadDoubleUnsafe(SignalInputTypeToCmdStr(SignalInput) + "/0/min"));
636 }
637
639 {
640 // Reading this value seems to take relatively much time.
641 return std::abs(ReadDoubleUnsafe(SignalInputTypeToCmdStr(SignalInput) + "/0/max"));
642 }
643
644 double ZILabOneHardwareAdapter::GetDemodPhaseUnsafe(uint8_t Demodulator) const
645 {
646 return ReadDoubleUnsafe("demods/" + Util::ToStr(Demodulator) + "/phaseshift") / 180.0 * std::numbers::pi + std::numbers::pi;
647 }
648
649 void ZILabOneHardwareAdapter::SetDemodPhaseUnsafe(uint8_t Demodulator, double Phase) const
650 {
651 WriteDoubleUnsafe("demods/" + Util::ToStr(Demodulator) + "/phaseshift", Phase / std::numbers::pi * 180.0 - 180.0);
652 }
653
655 {
656 WriteIntUnsafe("demods/" + Util::ToStr(Demodulator) + "/phaseadjust", 1);
657 }
658
660 {
661 return ReadDoubleUnsafe("demods/" + Util::ToStr(Demodulator) + "/timeconstant");
662 }
663
664 void ZILabOneHardwareAdapter::SetDemodTimeConstantUnsafe(uint8_t Demodulator, double TimeConstant) const
665 {
666 WriteDoubleUnsafe("demods/" + Util::ToStr(Demodulator) + "/timeconstant", TimeConstant);
667 }
668
669 uint8_t ZILabOneHardwareAdapter::GetDemodFilterOrderUnsafe(uint8_t Demodulator) const
670 {
671 return ReadIntUnsafe("demods/" + Util::ToStr(Demodulator) + "/order");
672 }
673
674 void ZILabOneHardwareAdapter::SetDemodFilterOrderUnsafe(uint8_t Demodulator, uint8_t FilterOrder) const
675 {
676 WriteIntUnsafe("demods/" + Util::ToStr(Demodulator) + "/order", FilterOrder);
677 }
678
680 {
681 std::string Data(1024, '\0');
682 unsigned int Length{};
683
684 auto Result = ZILabOneHardwareAdapterSyms::ziAPIModGetString(ZIConnection, DAQModuleHandle, "triggernode", Data.data(), &Length, Util::NumToT<unsigned int>(Data.length()));
685 CheckError(Result);
686
687 Data.resize(Length);
688
689 return Data.find("/sample.TrigIn") == std::string::npos ? DynExpInstr::LockinAmplifierDefs::TriggerModeType::Continuous
691 }
692
693 void ZILabOneHardwareAdapter::SetTriggerModeUnsafe(DynExpInstr::LockinAmplifierDefs::TriggerModeType TriggerMode, uint8_t Demodulator, uint8_t TriggerChannel) const
694 {
696 {
697 auto Result = ZILabOneHardwareAdapterSyms::ziAPIModSetString(ZIConnection, DAQModuleHandle, "triggernode",
698 ("/" + DeviceDescriptor + "/demods/" + Util::ToStr(Demodulator) + "/sample.TrigIn" + Util::ToStr(TriggerChannel)).c_str());
699 CheckError(Result);
700 Result = ZILabOneHardwareAdapterSyms::ziAPIModSetIntegerData(ZIConnection, DAQModuleHandle, "type", 6); // Trigger on HW (!) edge
701 CheckError(Result);
702 }
704 {
705 auto Result = ZILabOneHardwareAdapterSyms::ziAPIModSetString(ZIConnection, DAQModuleHandle, "triggernode",
706 ("/" + DeviceDescriptor + "/demods/" + Util::ToStr(Demodulator) + "/sample.r").c_str());
707 CheckError(Result);
708 Result = ZILabOneHardwareAdapterSyms::ziAPIModSetIntegerData(ZIConnection, DAQModuleHandle, "type", 0); // Trigger continuously
709 CheckError(Result);
710 }
711 else
712 ThrowExceptionUnsafe(std::make_exception_ptr(Util::InvalidArgException("The given trigger mode is invalid.")));
713 }
714
716 {
717 ZILabOneHardwareAdapterSyms::ZIIntegerData Data;
718 auto Result = ZILabOneHardwareAdapterSyms::ziAPIModGetInteger(ZIConnection, DAQModuleHandle, "edge", &Data);
719 CheckError(Result);
720
722 }
723
725 {
727 ThrowExceptionUnsafe(std::make_exception_ptr(Util::InvalidArgException("The given trigger edge is invalid.")));
728
729 auto Result = ZILabOneHardwareAdapterSyms::ziAPIModSetIntegerData(ZIConnection, DAQModuleHandle, "edge",
731 CheckError(Result);
732 }
733
735 {
736 return ReadDoubleUnsafe("demods/" + Util::ToStr(Demodulator) + "/rate");
737 }
738
739 void ZILabOneHardwareAdapter::SetDemodSamplingRateUnsafe(uint8_t Demodulator, double SamplingRate) const
740 {
741 WriteDoubleUnsafe("demods/" + Util::ToStr(Demodulator) + "/rate", SamplingRate);
742 }
743
744 bool ZILabOneHardwareAdapter::GetEnabledUnsafe(uint8_t Demodulator) const
745 {
746 return ReadIntUnsafe("demods/" + Util::ToStr(Demodulator) + "/enable");
747 }
748
749 void ZILabOneHardwareAdapter::SetEnabledUnsafe(uint8_t Demodulator, bool Enabled) const
750 {
751 WriteIntUnsafe("demods/" + Util::ToStr(Demodulator) + "/enable", Enabled);
752 }
753
755 {
756 return ReadDoubleUnsafe("oscs/" + Util::ToStr(Oscillator) + "/freq");
757 }
758
759 double ZILabOneHardwareAdapter::ReadDoubleUnsafe(const std::string& Path) const
760 {
761 ZILabOneHardwareAdapterSyms::ZIDoubleData Data;
762 auto Result = ZILabOneHardwareAdapterSyms::ziAPIGetValueD(ZIConnection, ("/" + DeviceDescriptor + "/" + Path).c_str(), &Data);
763 CheckError(Result);
764
765 return static_cast<double>(Data);
766 }
767
768 long long ZILabOneHardwareAdapter::ReadIntUnsafe(const std::string& Path) const
769 {
770 ZILabOneHardwareAdapterSyms::ZIIntegerData Data;
771 auto Result = ZILabOneHardwareAdapterSyms::ziAPIGetValueI(ZIConnection, ("/" + DeviceDescriptor + "/" + Path).c_str(), &Data);
772 CheckError(Result);
773
774 return static_cast<long long>(Data);
775 }
776
777 void ZILabOneHardwareAdapter::WriteDoubleUnsafe(const std::string& Path, double Value) const
778 {
779 auto Result = ZILabOneHardwareAdapterSyms::ziAPISetValueD(ZIConnection, ("/" + DeviceDescriptor + "/" + Path).c_str(), Value);
780 CheckError(Result);
781 }
782
783 void ZILabOneHardwareAdapter::WriteIntUnsafe(const std::string& Path, long long Value) const
784 {
785 auto Result = ZILabOneHardwareAdapterSyms::ziAPISetValueI(ZIConnection, ("/" + DeviceDescriptor + "/" + Path).c_str(), Value);
786 CheckError(Result);
787 }
788}
Implementation of a hardware adapter to control Zurich Instruments MFLI hardware.
void ConfigureParamsImpl(dispatch_tag< HardwareAdapterParamsBase >) override final
double GetDemodPhaseUnsafe(uint8_t Demodulator) const
double GetOscillatorFrequency(uint8_t Oscillator) const
bool IsInputOverloadUnsafe(SignalInputType SignalInput) const
void SetTriggerModeUnsafe(DynExpInstr::LockinAmplifierDefs::TriggerModeType TriggerMode, uint8_t Demodulator, uint8_t TriggerChannel) const
bool IsReadyChild() const override final
Returns wheter this Object instance is ready (e.g. it is running or connected to a hardware device) a...
double GetDemodTimeConstantUnsafe(uint8_t Demodulator) const
void SetDemodPhaseUnsafe(uint8_t Demodulator, double Phase) const
double GetDemodSamplingRateUnsafe(uint8_t Demodulator) const
bool IsInputOverload(SignalInputType SignalInput) const
ZILabOneHardwareAdapterSyms::ZIModuleHandle DAQModuleHandle
double GetDemodSamplingRate(uint8_t Demodulator) const
double ReadDoubleUnsafe(const std::string &Path) const
double GetDemodPhase(uint8_t Demodulator) const
ZILabOneHardwareAdapter(const std::thread::id OwnerThreadID, DynExp::ParamsBasePtrType &&Params)
ZILabOneHardwareAdapterSyms::ZIConnection ZIConnection
double GetOscillatorFrequencyUnsafe(uint8_t Oscillator) const
void EnsureReadyStateChild() override final
Ensures that this Object instance is ready by possibly starting its worker thread or by opening conne...
void SetTriggerEdgeUnsafe(DynExpInstr::LockinAmplifierDefs::TriggerEdgeType TriggerEdge) const
long long ReadIntUnsafe(const std::string &Path) const
void AutoAdjustDemodPhase(uint8_t Demodulator) const
void ResetImpl(dispatch_tag< HardwareAdapterBase >) override final
double GetDemodTimeConstant(uint8_t Demodulator) const
double GetPosInputLoad(SignalInputType SignalInput) const
void ConfigureInput(SignalInputType SignalInput, uint8_t Demodulator) const
double GetInputRangeUnsafe(SignalInputType SignalInput) const
void AutoAdjustDemodPhaseUnsafe(uint8_t Demodulator) const
double GetInputRange(SignalInputType SignalInput) const
void AutoAdjustInputRangeUnsafe(SignalInputType SignalInput) const
void SetDemodFilterOrder(uint8_t Demodulator, uint8_t FilterOrder) const
std::vector< DynExpInstr::LockinAmplifierDefs::LockinSample > GetAcquiredDataUnsafe() const
void SetTriggerEdge(DynExpInstr::LockinAmplifierDefs::TriggerEdgeType TriggerEdge) const
uint8_t GetDemodFilterOrder(uint8_t Demodulator) const
double GetPosInputLoadUnsafe(SignalInputType SignalInput) const
DynExpInstr::LockinAmplifierDefs::TriggerModeType GetTriggerMode() const
void SetDemodTimeConstantUnsafe(uint8_t Demodulator, double TimeConstant) const
bool GetEnabledUnsafe(uint8_t Demodulator) const
void WriteDoubleUnsafe(const std::string &Path, double Value) const
DynExpInstr::LockinAmplifierDefs::TriggerEdgeType GetTriggerEdgeUnsafe() const
void SetDemodTimeConstant(uint8_t Demodulator, double TimeConstant) const
void AutoAdjustInputRange(SignalInputType SignalInput) const
void SetTriggerMode(DynExpInstr::LockinAmplifierDefs::TriggerModeType TriggerMode, uint8_t Demodulator=0, uint8_t TriggerChannel=1) const
void SetDemodPhase(uint8_t Demodulator, double Phase) const
void SetDemodSamplingRate(uint8_t Demodulator, double SamplingRate) const
void SetEnabledUnsafe(uint8_t Demodulator, bool Enabled) const
double StartAcquisition(uint8_t Demodulator, size_t NumSamples, size_t NumRuns=1, bool AverageRuns=false) const
double GetNegInputLoadUnsafe(SignalInputType SignalInput) const
double GetNegInputLoad(SignalInputType SignalInput) const
void SetDemodSamplingRateUnsafe(uint8_t Demodulator, double SamplingRate) const
DynExpInstr::LockinAmplifierDefs::TriggerEdgeType GetTriggerEdge() const
DynExpInstr::LockinAmplifierDefs::TriggerModeType GetTriggerModeUnsafe() const
void CheckError(const ZILabOneHardwareAdapterSyms::ZIResult_enum Result, const std::source_location Location=std::source_location::current()) const
void SetInputRangeUnsafe(SignalInputType SignalInput, double InputRange) const
std::vector< DynExpInstr::LockinAmplifierDefs::LockinSample > GetAcquiredData() const
void SetDemodFilterOrderUnsafe(uint8_t Demodulator, uint8_t FilterOrder) const
bool IsConnectedChild() const noexcept override final
Determines the connection status of the hardware interface.
std::string SignalInputTypeToCmdStr(SignalInputType SignalInput) const
void ConfigureInputUnsafe(SignalInputType SignalInput, uint8_t Demodulator) const
uint8_t GetDemodFilterOrderUnsafe(uint8_t Demodulator) const
void StartAcquisitionUnsafe(uint8_t Demodulator, size_t NumSamples, size_t NumRuns, bool AverageRuns) const
void SetInputRange(SignalInputType SignalInput, double InputRange) const
void WriteIntUnsafe(const std::string &Path, long long Value) const
static constexpr bool DetermineOverload(double PosInputLoad, double NegInputLoad)
void SetEnabled(uint8_t Demodulator, bool Enabled) const
static constexpr auto HardwareOperationTimeout
Default timeout used to lock the mutex provided by the base class Util::ILockable to synchronize acce...
void ThrowExceptionUnsafe(std::exception_ptr Exception) const
Stores Exception in LastException, wraps it in a Util::ForwardedException and throws the wrapped exce...
auto GetExceptionUnsafe() const
Getter for LastException.
ParamsConstTypeSyncPtrType GetParams(const std::chrono::milliseconds Timeout=GetParamsTimeoutDefault) const
Locks the mutex of the parameter class instance Params assigned to this Object instance and returns a...
Definition Object.cpp:436
Refer to ParamsBase::dispatch_tag.
Definition Object.h:2018
Tag for function dispatching mechanism within this class used when derived classes are not intended t...
Definition Object.h:349
Thrown when a list is expected to contain entries and when a query results in an empty answer or an e...
Definition Exception.h:224
LockType AcquireLock(const std::chrono::milliseconds Timeout=DefaultTimeout) const
Locks the internal mutex. Blocks until the mutex is locked or until the timeout duration is exceeded.
Definition Util.cpp:8
An invalid argument like a null pointer has been passed to a function.
Definition Exception.h:137
Data to operate on is invalid for a specific purpose. This indicates a corrupted data structure or fu...
Definition Exception.h:163
Thrown when a requested ressource does not exist.
Definition Exception.h:236
Thrown when a numeric operation would result in an overflow (e.g. due to incompatible data types)
Definition Exception.h:199
DynExp's hardware namespace contains the implementation of DynExp hardware adapters which extend DynE...
TriggerEdgeType
Type to determine at which edge of a trigger signal to trigger. Not a strongly-typed enum to allow us...
@ Rise
Trigger on rising edge.
@ Fall
Trigger on falling edge.
TriggerModeType
Type to determine the trigger mode. Not a strongly-typed enum to allow using the enumeration in a Dyn...
@ ExternSingle
Run once after an external trigger signal has been detected.
@ Continuous
Run continuously disabling the trigger.
std::unique_ptr< ParamsBase > ParamsBasePtrType
Alias for a pointer to the parameter system base class ParamsBase.
Definition Object.h:1807
std::string ToStr(const T &Value, int Precision=-1)
Converts a (numeric) value of type T to a std::string using operator<< of std::stringstream.
Definition Util.h:625
void ForwardException(std::exception_ptr e)
Wraps the exception passed to the function in a ForwardedException and throws the ForwardedException....
Definition Exception.cpp:30
std::string ToLower(std::string_view Str)
Transforms a string into lower case.
Definition Util.cpp:208
Accumulates include statements to provide a precompiled header.