DynExp
Highly flexible laboratory automation for dynamically changing experiments.
HardwareAdapterZILabOne.cpp
Go to the documentation of this file.
1 // This file is part of DynExp.
2 
3 #include "stdafx.h"
5 
6 namespace 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 
60  ZILabOneHardwareAdapter::ZILabOneHardwareAdapter(const std::thread::id OwnerThreadID, DynExp::ParamsBasePtrType&& Params)
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.
69  CloseUnsafe();
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 
90  {
92 
94  }
95 
97  {
99 
101  }
102 
104  {
106 
108  }
109 
111  {
113 
115  }
116 
118  {
120 
122  }
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 
146  {
148 
149  AutoAdjustInputRangeUnsafe(SignalInput);
150  }
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 
223  {
225 
226  return GetTriggerModeUnsafe();
227  }
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 
237  {
239 
240  return GetTriggerEdgeUnsafe();
241  }
242 
244  {
246 
247  SetTriggerEdgeUnsafe(TriggerEdge);
248  }
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 
312  {
314 
315  OpenUnsafe();
316  }
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 
628  {
629  return DetermineOverload(GetPosInputLoadUnsafe(SignalInput), GetNegInputLoadUnsafe(SignalInput));
630  }
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 
659  double ZILabOneHardwareAdapter::GetDemodTimeConstantUnsafe(uint8_t Demodulator) const
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 
734  double ZILabOneHardwareAdapter::GetDemodSamplingRateUnsafe(uint8_t Demodulator) const
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
constexpr static bool DetermineOverload(double PosInputLoad, double NegInputLoad)
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
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.