DynExp
Highly flexible laboratory automation for dynamically changing experiments.
RS_SMC100A.cpp
Go to the documentation of this file.
1 // This file is part of DynExp.
2 
3 #include "stdafx.h"
4 #include "RS_SMC100A.h"
5 
6 namespace DynExpInstr
7 {
9  {
10  auto InstrParams = DynExp::dynamic_Params_cast<RS_SMC100A>(Instance.ParamsGetter());
11  auto InstrData = DynExp::dynamic_InstrumentData_cast<RS_SMC100A>(Instance.InstrumentDataGetter());
12 
13  Instance.LockObject(InstrParams->HardwareAdapter, InstrData->HardwareAdapter);
14 
16  }
17 
19  {
20  ExitFuncImpl(dispatch_tag<ExitTask>(), Instance);
21 
22  auto InstrData = DynExp::dynamic_InstrumentData_cast<RS_SMC100A>(Instance.InstrumentDataGetter());
23 
24  Instance.UnlockObject(InstrData->HardwareAdapter);
25  }
26 
28  {
29  try
30  {
31  auto InstrData = DynExp::dynamic_InstrumentData_cast<RS_SMC100A>(Instance.InstrumentDataGetter());
32  bool UpdateError = false;
33 
34  try
35  {
36  *InstrData->HardwareAdapter << "OUTPut1:STATe?";
37  InstrData->Running = InstrData->HardwareAdapter->WaitForLine(3) == "1";
38  }
39  catch ([[maybe_unused]] const DynExp::SerialCommunicationException& e)
40  {
41  UpdateError = true;
42 
43  // Swallow if just one or two subsequent updates failed.
44  if (InstrData->NumFailedStatusUpdateAttempts++ >= 3)
45  throw;
46  }
47 
48  if (!UpdateError)
49  InstrData->NumFailedStatusUpdateAttempts = 0;
50  }
51  // Issued if a mutex is blocked by another operation.
52  catch (const Util::TimeoutException& e)
53  {
54  Instance.GetOwner().SetWarning(e);
55 
56  return;
57  }
58  // Issued if reading data from RS_SMC100A controller failed.
60  {
61  Instance.GetOwner().SetWarning(e);
62 
63  return;
64  }
65 
66  UpdateFuncImpl(dispatch_tag<UpdateTask>(), Instance);
67  }
68 
70  {
71  auto InstrData = DynExp::dynamic_InstrumentData_cast<RS_SMC100A>(Instance.InstrumentDataGetter());
72 
73  *InstrData->HardwareAdapter << "OUTPut1:STATe ON";
74 
75  return {};
76  }
77 
79  {
80  auto InstrData = DynExp::dynamic_InstrumentData_cast<RS_SMC100A>(Instance.InstrumentDataGetter());
81 
82  *InstrData->HardwareAdapter << "OUTPut1:STATe OFF";
83 
84  return {};
85  }
86 
88  {
89  auto InstrData = DynExp::dynamic_InstrumentData_cast<RS_SMC100A>(Instance.InstrumentDataGetter());
90 
91  *InstrData->HardwareAdapter << "SOURce1:FREQuency:MODE CW";
92  *InstrData->HardwareAdapter << "SOURce1:FREQuency:CW " + Util::ToStr(FunctionDesc.FrequencyInHz);
93  *InstrData->HardwareAdapter << "SOURce1:POWer:MODE CW";
94  *InstrData->HardwareAdapter << "SOURce1:POWer:POWer " + Util::ToStr(FunctionDesc.Amplitude);
95 
96  if (Autostart)
97  InstrData->EnqueueTask(DynExp::MakeTask<RS_SMC100ATasks::StartTask>(nullptr));
98 
99  return {};
100  }
101 
103  {
104  auto InstrData = DynExp::dynamic_InstrumentData_cast<RS_SMC100A>(Instance.InstrumentDataGetter());
105 
108  {
109  *InstrData->HardwareAdapter << std::string("SOURce1:LFOutput1:FREQuency:MODE CW");
110  *InstrData->HardwareAdapter << std::string("SOURce1:LFOutput1:FREQuency ")
111  + Util::ToStr(ModulationDesc.FrequencyInHz, 0) + " Hz";
112  }
115  throw Util::NotImplementedException("This device does not support LF pulse modulation.");
116 
118  {
119  *InstrData->HardwareAdapter << std::string("SOURce1:FM1:SOURce INT");
120  *InstrData->HardwareAdapter << std::string("SOURce1:FM1:DEViation ")
121  + Util::ToStr(ModulationDesc.Depth, 0) + " Hz";
122 
123  *InstrData->HardwareAdapter << "SOURce1:AM1:STATe 0";
124  *InstrData->HardwareAdapter << "SOURce1:PM1:STATe 0";
125  *InstrData->HardwareAdapter << "SOURce1:FM1:STATe 1";
126  }
128  {
129  *InstrData->HardwareAdapter << std::string("SOURce1:AM1:SOURce INT");
130  *InstrData->HardwareAdapter << std::string("SOURce1:AM1:DEPTh ")
131  + Util::ToStr(ModulationDesc.Depth, 0);
132 
133  *InstrData->HardwareAdapter << "SOURce1:FM1:STATe 0";
134  *InstrData->HardwareAdapter << "SOURce1:PM1:STATe 0";
135  *InstrData->HardwareAdapter << "SOURce1:AM1:STATe 1";
136  }
138  {
139  *InstrData->HardwareAdapter << std::string("SOURce1:PM1:SOURce INT");
140  *InstrData->HardwareAdapter << std::string("SOURce1:PM1:DEViation ")
141  + Util::ToStr(ModulationDesc.Depth, 0);
142 
143  *InstrData->HardwareAdapter << "SOURce1:AM1:STATe 0";
144  *InstrData->HardwareAdapter << "SOURce1:FM1:STATe 0";
145  *InstrData->HardwareAdapter << "SOURce1:PM1:STATe 1";
146  }
147  else
148  {
149  *InstrData->HardwareAdapter << "SOURce1:AM1:STATe 0";
150  *InstrData->HardwareAdapter << "SOURce1:FM1:STATe 0";
151  *InstrData->HardwareAdapter << "SOURce1:PM1:STATe 0";
152  }
153 
154  *InstrData->HardwareAdapter << std::string("SOURce1:LFOutput1:STATe ") +
155  (ModulationDesc.Type == FunctionGeneratorDefs::ModulationDescType::ModulationType::Disabled ? "0" : "1");
156 
157  return {};
158  }
159 
161  {
162  auto InstrData = DynExp::dynamic_InstrumentData_cast<RS_SMC100A>(Instance.InstrumentDataGetter());
163 
165  {
166  *InstrData->HardwareAdapter << std::string("SOURce1:SWEep:FREQuency:RETRace ")
167  + (SweepDesc.Retrace ? "1" : "0");
168  *InstrData->HardwareAdapter << std::string("SOURce1:SWEep:FREQuency:DWELl ")
169  + Util::ToStr(SweepDesc.TimeDiffPerSample_ms, 3) + " ms";
170  *InstrData->HardwareAdapter << std::string("SOURce1:FREQuency:STARt ")
171  + Util::ToStr(SweepDesc.Min, 0) + " Hz";
172  *InstrData->HardwareAdapter << std::string("SOURce1:FREQuency:STOP ")
173  + Util::ToStr(SweepDesc.Max, 0) + " Hz";
174  *InstrData->HardwareAdapter << std::string("SOURce1:SWEep:FREQuency:SPACing LINear");
175  *InstrData->HardwareAdapter << std::string("SOURce1:SWEep:FREQuency:SHAPe SAWTooth");
176  *InstrData->HardwareAdapter << std::string("SOURce1:SWEep:FREQuency:STEP:LINear ")
177  + Util::ToStr(SweepDesc.ValueDiffPerSample, 0) + " Hz";
178 
179  *InstrData->HardwareAdapter << "SOURce1:POWer:MODE CW";
180  *InstrData->HardwareAdapter << "SOURce1:FREQuency:MODE SWEep";
181 
183  }
185  {
186  *InstrData->HardwareAdapter << std::string("SOURce1:SWEep:POWer:RETRace ")
187  + (SweepDesc.Retrace ? "1" : "0");
188  *InstrData->HardwareAdapter << std::string("SOURce1:SWEep:POWer:DWELl ")
189  + Util::ToStr(SweepDesc.TimeDiffPerSample_ms, 3) + " ms";
190  *InstrData->HardwareAdapter << std::string("SOURce1:POWer:STARt ")
191  + Util::ToStr(SweepDesc.Min, 2) + " dBm";
192  *InstrData->HardwareAdapter << std::string("SOURce1:POWer:STOP ")
193  + Util::ToStr(SweepDesc.Max, 2) + " dBm";
194  // The level sweep spacing is always linear.
195  *InstrData->HardwareAdapter << std::string("SOURce1:SWEep:POWer:SHAPe SAWTooth");
196  *InstrData->HardwareAdapter << std::string("SOURce1:SWEep:POWer:STEP ")
197  + Util::ToStr(SweepDesc.ValueDiffPerSample, 2) + " dB";
198 
199  *InstrData->HardwareAdapter << "SOURce1:FREQuency:MODE CW";
200  *InstrData->HardwareAdapter << "SOURce1:POWer:MODE SWEep";
201 
203  }
204  else
205  {
206  *InstrData->HardwareAdapter << "SOURce1:FREQuency:MODE CW";
207  *InstrData->HardwareAdapter << "SOURce1:POWer:MODE CW";
208 
209  InstrData->CurrentSweepType = FunctionGeneratorDefs::SweepDescType::SweepType::Disabled;
210  }
211 
212  return {};
213  }
214 
216  {
217  auto InstrData = DynExp::dynamic_InstrumentData_cast<RS_SMC100A>(Instance.InstrumentDataGetter());
218 
219  if (InstrData->GetCurrentSweepType() == FunctionGeneratorDefs::SweepDescType::SweepType::Frequency)
220  {
221  *InstrData->HardwareAdapter << std::string("TRIGger1:FSWeep:SOURce ")
222  + RS_SMC100A::TriggerModeToCmdString(FunctionGeneratorDefs::TriggerDescType::TriggerModeType::Manual);
223  *InstrData->HardwareAdapter << "SOURce1:SWEep:FREQuency:MODE AUTO";
224 
225  *InstrData->HardwareAdapter << "SOURce1:SWEep:FREQuency:EXECute";
226  }
227  else if (InstrData->GetCurrentSweepType() == FunctionGeneratorDefs::SweepDescType::SweepType::Amplitude)
228  {
229  *InstrData->HardwareAdapter << std::string("TRIGger1:PSWeep:SOURce ")
230  + RS_SMC100A::TriggerModeToCmdString(FunctionGeneratorDefs::TriggerDescType::TriggerModeType::Manual);
231  *InstrData->HardwareAdapter << "SOURce1:SWEep:POWer:MODE AUTO";
232 
233  *InstrData->HardwareAdapter << "SOURce1:SWEep:POWer:EXECute";
234  }
235 
236  return {};
237  }
238 
240  {
241  auto InstrData = DynExp::dynamic_InstrumentData_cast<RS_SMC100A>(Instance.InstrumentDataGetter());
242 
243  if (InstrData->GetCurrentSweepType() == FunctionGeneratorDefs::SweepDescType::SweepType::Frequency)
244  {
245  *InstrData->HardwareAdapter << std::string("TRIGger1:FSWeep:SOURce ")
246  + RS_SMC100A::TriggerModeToCmdString(TriggerDesc.TriggerMode);
247  if (TriggerDesc.TriggerMode == FunctionGeneratorDefs::TriggerDescType::TriggerModeType::ExternStep)
248  *InstrData->HardwareAdapter << "SOURce1:SWEep:FREQuency:MODE STEP";
249  else
250  *InstrData->HardwareAdapter << "SOURce1:SWEep:FREQuency:MODE AUTO";
251  }
252  else if (InstrData->GetCurrentSweepType() == FunctionGeneratorDefs::SweepDescType::SweepType::Amplitude)
253  {
254  *InstrData->HardwareAdapter << std::string("TRIGger1:PSWeep:SOURce ")
255  + RS_SMC100A::TriggerModeToCmdString(TriggerDesc.TriggerMode);
256  if (TriggerDesc.TriggerMode == FunctionGeneratorDefs::TriggerDescType::TriggerModeType::ExternStep)
257  *InstrData->HardwareAdapter << "SOURce1:SWEep:POWer:MODE STEP";
258  else
259  *InstrData->HardwareAdapter << "SOURce1:SWEep:POWer:MODE AUTO";
260  }
261 
262  *InstrData->HardwareAdapter << std::string("SOURce:INPut:TRIGger:SLOPe ") +
263  (TriggerDesc.TriggerEdge == FunctionGeneratorDefs::TriggerDescType::TriggerEdgeType::Fall ? "NEGative" : "POSitive");
264 
265  return {};
266  }
267 
269  {
270  NumFailedStatusUpdateAttempts = 0;
271  Running = false;
273 
274  ResetImpl(dispatch_tag<RS_SMC100AData>());
275  }
276 
278  {
279  switch (TriggerMode)
280  {
283  case FunctionGeneratorDefs::TriggerDescType::TriggerModeType::ExternStep: return "EXTernal";
284  case FunctionGeneratorDefs::TriggerDescType::TriggerModeType::Manual: return "SINGle";
285  default: return "";
286  }
287  }
288 
289  RS_SMC100A::RS_SMC100A(const std::thread::id OwnerThreadID, DynExp::ParamsBasePtrType&& Params)
290  : FunctionGenerator(OwnerThreadID, std::move(Params))
291  {
292  }
293 
295  bool PersistParams, bool Autostart, DynExp::TaskBase::CallbackType CallbackFunc) const
296  {
297  if (PersistParams)
298  {
299  auto InstrParams = DynExp::dynamic_Params_cast<FunctionGenerator>(GetNonConstParams());
300  InstrParams->WaveformType = FunctionGeneratorDefs::WaveformTypes::Sine;
301  InstrParams->FrequencyInHz = FunctionDesc.FrequencyInHz;
302  InstrParams->Amplitude = FunctionDesc.Amplitude;
303  InstrParams->Offset = 0;
304  InstrParams->PhaseInRad = FunctionDesc.PhaseInRad;
305  InstrParams->DutyCycle = 0;
306  InstrParams->Autostart = Autostart;
307  } // InstrParams unlocked here.
308 
309  MakeAndEnqueueTask<RS_SMC100ATasks::SetSineFunctionTask>(FunctionDesc, Autostart, CallbackFunc);
310  }
311 
313  bool PersistParams, DynExp::TaskBase::CallbackType CallbackFunc) const
314  {
315  MakeAndEnqueueTask<RS_SMC100ATasks::SetModulationTask>(ModulationDesc, CallbackFunc);
316  }
317 
319  bool PersistParams, DynExp::TaskBase::CallbackType CallbackFunc) const
320  {
321  MakeAndEnqueueTask<RS_SMC100ATasks::SetSweepTask>(SweepDesc, CallbackFunc);
322  }
323 
325  {
326  MakeAndEnqueueTask<RS_SMC100ATasks::ForceTriggerTask>(CallbackFunc);
327  }
328 
330  {
331  auto InstrData = DynExp::dynamic_InstrumentData_cast<RS_SMC100A>(GetInstrumentData());
332 
333  return InstrData->IsRunning();
334  }
335 
337  {
339  }
340 
342  bool PersistParams, DynExp::TaskBase::CallbackType CallbackFunc) const
343  {
344  MakeAndEnqueueTask<RS_SMC100ATasks::SetTriggerTask>(TriggerDesc, CallbackFunc);
345  }
346 }
Implementation of an instrument to control the Rohde & Schwarz SMC100A function generator.
Function generator meta instrument based on the data stream meta instrument to generate waveforms by ...
void ResetImpl(dispatch_tag< FunctionGeneratorData >) override final
Definition: RS_SMC100A.cpp:268
void ExitFuncImpl(dispatch_tag< FunctionGeneratorTasks::ExitTask >, DynExp::InstrumentInstance &Instance) override final
Deinitializes the respective instrument within the instrument inheritance hierarchy....
Definition: RS_SMC100A.cpp:18
virtual DynExp::TaskResultType RunChild(DynExp::InstrumentInstance &Instance) override
Runs the task. Override RunChild() to define a derived task's action(s). Any exception leaving RunChi...
Definition: RS_SMC100A.cpp:215
void InitFuncImpl(dispatch_tag< FunctionGeneratorTasks::InitTask >, DynExp::InstrumentInstance &Instance) override final
Initializes the respective instrument within the instrument inheritance hierarchy....
Definition: RS_SMC100A.cpp:8
virtual DynExp::TaskResultType RunChild(DynExp::InstrumentInstance &Instance) override
Runs the task. Override RunChild() to define a derived task's action(s). Any exception leaving RunChi...
Definition: RS_SMC100A.cpp:102
virtual DynExp::TaskResultType RunChild(DynExp::InstrumentInstance &Instance) override
Runs the task. Override RunChild() to define a derived task's action(s). Any exception leaving RunChi...
Definition: RS_SMC100A.cpp:87
virtual DynExp::TaskResultType RunChild(DynExp::InstrumentInstance &Instance) override
Runs the task. Override RunChild() to define a derived task's action(s). Any exception leaving RunChi...
Definition: RS_SMC100A.cpp:160
virtual DynExp::TaskResultType RunChild(DynExp::InstrumentInstance &Instance) override
Runs the task. Override RunChild() to define a derived task's action(s). Any exception leaving RunChi...
Definition: RS_SMC100A.cpp:239
virtual DynExp::TaskResultType RunChild(DynExp::InstrumentInstance &Instance) override
Runs the task. Override RunChild() to define a derived task's action(s). Any exception leaving RunChi...
Definition: RS_SMC100A.cpp:69
virtual DynExp::TaskResultType RunChild(DynExp::InstrumentInstance &Instance) override
Runs the task. Override RunChild() to define a derived task's action(s). Any exception leaving RunChi...
Definition: RS_SMC100A.cpp:78
void UpdateFuncImpl(dispatch_tag< FunctionGeneratorTasks::UpdateTask >, DynExp::InstrumentInstance &Instance) override final
Updates the respective instrument within the instrument inheritance hierarchy. Call UpdateFuncImpl() ...
Definition: RS_SMC100A.cpp:27
virtual Util::OptionalBool IsRunning() const override
Determines whether the underlying hardware adapter is running a data acquisition or writing data.
Definition: RS_SMC100A.cpp:329
void ResetImpl(dispatch_tag< FunctionGenerator >) override final
Refer to DynExp::Object::Reset(). Using tag dispatch mechanism to ensure that ResetImpl() of every de...
Definition: RS_SMC100A.cpp:336
RS_SMC100A(const std::thread::id OwnerThreadID, DynExp::ParamsBasePtrType &&Params)
Definition: RS_SMC100A.cpp:289
virtual void SetTriggerChild(const FunctionGeneratorDefs::TriggerDescType &TriggerDesc, bool PersistParams, DynExp::TaskBase::CallbackType CallbackFunc) const override
SetTrigger() configures the function generator's trigger, which determines when the waveform generati...
Definition: RS_SMC100A.cpp:341
virtual void SetSweep(const FunctionGeneratorDefs::SweepDescType &SweepDesc, bool PersistParams=false, DynExp::TaskBase::CallbackType CallbackFunc=nullptr) const override
Configures the function generator to perform a sweep.
Definition: RS_SMC100A.cpp:318
virtual void SetSineFunction(const FunctionGeneratorDefs::SineFunctionDescType &FunctionDesc, bool PersistParams=false, bool Autostart=false, DynExp::TaskBase::CallbackType CallbackFunc=nullptr) const override
Generates a sine function.
Definition: RS_SMC100A.cpp:294
virtual void ForceTrigger(DynExp::TaskBase::CallbackType CallbackFunc=nullptr) const override
Forces the generation of the waveform ignoring the trigger.
Definition: RS_SMC100A.cpp:324
static const char * TriggerModeToCmdString(FunctionGeneratorDefs::TriggerDescType::TriggerModeType TriggerMode) noexcept
Definition: RS_SMC100A.cpp:277
virtual void SetModulation(const FunctionGeneratorDefs::ModulationDescType &ModulationDesc, bool PersistParams=false, DynExp::TaskBase::CallbackType CallbackFunc=nullptr) const override
Configures the function generator to perform a modulation.
Definition: RS_SMC100A.cpp:312
Refer to DynExp::ParamsBase::dispatch_tag.
Definition: Instrument.h:1151
Refer to DynExp::ParamsBase::dispatch_tag.
Definition: Instrument.h:1120
InstrumentDataTypeSyncPtrType GetInstrumentData(const std::chrono::milliseconds Timeout=GetInstrumentDataTimeoutDefault)
Locks the mutex of the instrument data class instance InstrumentData assigned to this InstrumentBase ...
Definition: Instrument.cpp:222
Refer to ParamsBase::dispatch_tag.
Definition: Instrument.h:146
Defines data for a thread belonging to a InstrumentBase instance. Refer to RunnableInstance.
Definition: Instrument.h:772
const InstrumentBase::InstrumentDataGetterType InstrumentDataGetter
Getter for instrument's data. Refer to InstrumentBase::InstrumentDataGetterType.
Definition: Instrument.h:791
ParamsTypeSyncPtrType GetNonConstParams(const std::chrono::milliseconds Timeout=GetParamsTimeoutDefault) const
Allows derived Objects to edit their own parameters - even in const task functions (for instruments) ...
Definition: Object.cpp:475
Refer to ParamsBase::dispatch_tag.
Definition: Object.h:2018
const Object::ParamsGetterType ParamsGetter
Invoke to obtain the parameters (derived from ParamsBase) of Owner.
Definition: Object.h:3671
void UnlockObject(LinkedObjectWrapperContainer< ObjectT > &ObjectWrapperContainer)
Unlocks an Object instance stored in the LinkedObjectWrapperContainer ObjectWrapperContainer....
Definition: Object.h:3570
void LockObject(const ParamsBase::Param< ObjectLink< ObjectT >> &LinkParam, LinkedObjectWrapperContainer< ObjectT > &ObjectWrapperContainer, std::chrono::milliseconds Timeout=ObjectLinkBase::LockObjectTimeoutDefault)
Locks an Object instance referenced by a parameter LinkParam of type ParamsBase::Param< ObjectLink< O...
Definition: Object.h:3554
const auto & GetOwner() const noexcept
Returns Owner.
Definition: Object.h:3524
Defines an exception caused by a serial communication operation of a hardware adapter.
std::function< void(const TaskBase &, ExceptionContainer &)> CallbackType
Type of a callback function which is invoked when a task has finished, failed or has been aborted....
Definition: Instrument.h:939
Defines the return type of task functions.
Definition: Instrument.h:824
Refer to DynExp::ParamsBase::dispatch_tag.
Definition: Instrument.h:1182
Thrown when a requested feature is either under development and thus not implemented yet or when a sp...
Definition: Exception.h:299
Data type which stores an optional bool value (unknown, false, true). The type evaluates to bool whil...
Definition: Util.h:549
Thrown when an operation timed out before it could be completed, especially used for locking shared d...
Definition: Exception.h:261
@ Fall
Trigger on falling edge.
@ ExternSingle
Run once after an external trigger signal has been detected.
@ Continuous
Run continuously disabling the trigger.
DynExp's instrument namespace contains the implementation of DynExp instruments which extend DynExp's...
Definition: Instrument.h:1254
constexpr auto Running
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
Accumulates include statements to provide a precompiled header.
double FrequencyInHz
Frequency of the function in Hz.
Type describing modulation parameters for a waveform.
@ Pulse
Pulse (binary) modulation switching the affected quantity between two values.
@ Frequency
Modulation affecting the waveform's frequency.
@ Amplitude
Modulation affecting the waveform's amplitude.
double PhaseInRad
Phase of the function in radians.
Type describing sweep parameters for a waveform.
Type describing trigger parameters determining when the waveform is generated.
TriggerModeType
Type to determine the trigger mode. Not a strongly-typed enum to allow using the enumeration in a Dyn...