DynExp
Highly flexible laboratory automation for dynamically changing experiments.
RS_SMB100B.cpp
Go to the documentation of this file.
1 // This file is part of DynExp.
2 
3 #include "stdafx.h"
4 #include "RS_SMB100B.h"
5 
6 namespace DynExpInstr
7 {
9  {
10  auto InstrParams = DynExp::dynamic_Params_cast<RS_SMB100B>(Instance.ParamsGetter());
11  auto InstrData = DynExp::dynamic_InstrumentData_cast<RS_SMB100B>(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_SMB100B>(Instance.InstrumentDataGetter());
23 
24  Instance.UnlockObject(InstrData->HardwareAdapter);
25  }
26 
28  {
29  try
30  {
31  auto InstrData = DynExp::dynamic_InstrumentData_cast<RS_SMB100B>(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_SMB100B 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_SMB100B>(Instance.InstrumentDataGetter());
72 
73  *InstrData->HardwareAdapter << "OUTPut1:STATe ON";
74 
75  return {};
76  }
77 
79  {
80  auto InstrData = DynExp::dynamic_InstrumentData_cast<RS_SMB100B>(Instance.InstrumentDataGetter());
81 
82  *InstrData->HardwareAdapter << "OUTPut1:STATe OFF";
83 
84  return {};
85  }
86 
88  {
89  auto InstrData = DynExp::dynamic_InstrumentData_cast<RS_SMB100B>(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_SMB100BTasks::StartTask>(nullptr));
98 
99  return {};
100  }
101 
103  {
104  auto InstrData = DynExp::dynamic_InstrumentData_cast<RS_SMB100B>(Instance.InstrumentDataGetter());
105 
108  {
109  *InstrData->HardwareAdapter << std::string("SOURce1:LFOutput1:SHAPe SINE");
110  *InstrData->HardwareAdapter << std::string("SOURce1:LFOutput1:FREQuency ")
111  + Util::ToStr(ModulationDesc.FrequencyInHz, 0) + " Hz";
112  }
115  {
116  *InstrData->HardwareAdapter << std::string("SOURce1:LFOutput1:SHAPe PULSe");
117  *InstrData->HardwareAdapter << std::string("SOURce1:LFOutput1:SHAPe:PULSe:PERiod ")
118  + Util::ToStr(1 / ModulationDesc.FrequencyInHz, 8) + " s";
119  *InstrData->HardwareAdapter << std::string("SOURce1:LFOutput1:SHAPe:PULSe:DCYCle ")
120  + Util::ToStr(ModulationDesc.PulseDutyCycle * 100, 3);
121  }
122 
124  {
125  *InstrData->HardwareAdapter << std::string("SOURce1:FM1:SOURce LF1");
126  *InstrData->HardwareAdapter << std::string("SOURce1:FM1:DEViation ")
127  + Util::ToStr(ModulationDesc.Depth, 0) + " Hz";
128 
129  *InstrData->HardwareAdapter << "SOURce1:AM1:STATe 0";
130  *InstrData->HardwareAdapter << "SOURce1:PM1:STATe 0";
131  *InstrData->HardwareAdapter << "SOURce1:FM1:STATe 1";
132  }
134  {
135  *InstrData->HardwareAdapter << std::string("SOURce1:AM1:SOURce LF1");
136  *InstrData->HardwareAdapter << std::string("SOURce1:AM1:DEPTh ")
137  + Util::ToStr(ModulationDesc.Depth, 0);
138 
139  *InstrData->HardwareAdapter << "SOURce1:FM1:STATe 0";
140  *InstrData->HardwareAdapter << "SOURce1:PM1:STATe 0";
141  *InstrData->HardwareAdapter << "SOURce1:AM1:STATe 1";
142  }
144  {
145  *InstrData->HardwareAdapter << std::string("SOURce1:PM1:SOURce LF1");
146  *InstrData->HardwareAdapter << std::string("SOURce1:PM1:DEViation ")
147  + Util::ToStr(ModulationDesc.Depth, 0);
148 
149  *InstrData->HardwareAdapter << "SOURce1:AM1:STATe 0";
150  *InstrData->HardwareAdapter << "SOURce1:FM1:STATe 0";
151  *InstrData->HardwareAdapter << "SOURce1:PM1:STATe 1";
152  }
153  else
154  {
155  *InstrData->HardwareAdapter << "SOURce1:AM1:STATe 0";
156  *InstrData->HardwareAdapter << "SOURce1:FM1:STATe 0";
157  *InstrData->HardwareAdapter << "SOURce1:PM1:STATe 0";
158  }
159 
160  return {};
161  }
162 
164  {
165  auto InstrData = DynExp::dynamic_InstrumentData_cast<RS_SMB100B>(Instance.InstrumentDataGetter());
166 
168  {
169  *InstrData->HardwareAdapter << std::string("SOURce1:SWEep:FREQuency:RETRace ")
170  + (SweepDesc.Retrace ? "1" : "0");
171  *InstrData->HardwareAdapter << std::string("SOURce1:SWEep:FREQuency:DWELl ")
172  + Util::ToStr(SweepDesc.TimeDiffPerSample_ms, 3) + " ms";
173  *InstrData->HardwareAdapter << std::string("SOURce1:FREQuency:STARt ")
174  + Util::ToStr(SweepDesc.Min, 0) + " Hz";
175  *InstrData->HardwareAdapter << std::string("SOURce1:FREQuency:STOP ")
176  + Util::ToStr(SweepDesc.Max, 0) + " Hz";
177  *InstrData->HardwareAdapter << std::string("SOURce1:SWEep:FREQuency:SPACing LINear");
178  *InstrData->HardwareAdapter << std::string("SOURce1:SWEep:FREQuency:SHAPe SAWTooth");
179  *InstrData->HardwareAdapter << std::string("SOURce1:SWEep:FREQuency:STEP:LINear ")
180  + Util::ToStr(SweepDesc.ValueDiffPerSample, 0) + " Hz";
181 
182  *InstrData->HardwareAdapter << "SOURce1:POWer:MODE CW";
183  *InstrData->HardwareAdapter << "SOURce1:FREQuency:MODE SWEep";
184 
186  }
188  {
189  *InstrData->HardwareAdapter << std::string("SOURce1:SWEep:POWer:RETRace ")
190  + (SweepDesc.Retrace ? "1" : "0");
191  *InstrData->HardwareAdapter << std::string("SOURce1:SWEep:POWer:DWELl ")
192  + Util::ToStr(SweepDesc.TimeDiffPerSample_ms, 3) + " ms";
193  *InstrData->HardwareAdapter << std::string("SOURce1:POWer:STARt ")
194  + Util::ToStr(SweepDesc.Min, 2) + " dBm";
195  *InstrData->HardwareAdapter << std::string("SOURce1:POWer:STOP ")
196  + Util::ToStr(SweepDesc.Max, 2) + " dBm";
197  *InstrData->HardwareAdapter << std::string("SOURce1:SWEep:POWer:SPACing LINear");
198  *InstrData->HardwareAdapter << std::string("SOURce1:SWEep:POWer:SHAPe SAWTooth");
199  *InstrData->HardwareAdapter << std::string("SOURce1:SWEep:POWer:STEP ")
200  + Util::ToStr(SweepDesc.ValueDiffPerSample, 2) + " dB";
201 
202  *InstrData->HardwareAdapter << "SOURce1:FREQuency:MODE CW";
203  *InstrData->HardwareAdapter << "SOURce1:POWer:MODE SWEep";
204 
206  }
207  else
208  {
209  *InstrData->HardwareAdapter << "SOURce1:FREQuency:MODE CW";
210  *InstrData->HardwareAdapter << "SOURce1:POWer:MODE CW";
211 
212  InstrData->CurrentSweepType = FunctionGeneratorDefs::SweepDescType::SweepType::Disabled;
213  }
214 
215  return {};
216  }
217 
219  {
220  auto InstrData = DynExp::dynamic_InstrumentData_cast<RS_SMB100B>(Instance.InstrumentDataGetter());
221 
222  if (InstrData->GetCurrentSweepType() == FunctionGeneratorDefs::SweepDescType::SweepType::Frequency)
223  {
224  *InstrData->HardwareAdapter << std::string("TRIGger1:FSWeep:SOURce ")
225  + RS_SMB100B::TriggerModeToCmdString(FunctionGeneratorDefs::TriggerDescType::TriggerModeType::Manual);
226  *InstrData->HardwareAdapter << "SOURce1:SWEep:FREQuency:MODE AUTO";
227 
228  *InstrData->HardwareAdapter << "SOURce1:SWEep:FREQuency:EXECute";
229  }
230  else if (InstrData->GetCurrentSweepType() == FunctionGeneratorDefs::SweepDescType::SweepType::Amplitude)
231  {
232  *InstrData->HardwareAdapter << std::string("TRIGger1:PSWeep:SOURce ")
233  + RS_SMB100B::TriggerModeToCmdString(FunctionGeneratorDefs::TriggerDescType::TriggerModeType::Manual);
234  *InstrData->HardwareAdapter << "SOURce1:SWEep:POWer:MODE AUTO";
235 
236  *InstrData->HardwareAdapter << "SOURce1:SWEep:POWer:EXECute";
237  }
238 
239  return {};
240  }
241 
243  {
244  auto InstrData = DynExp::dynamic_InstrumentData_cast<RS_SMB100B>(Instance.InstrumentDataGetter());
245 
246  if (InstrData->GetCurrentSweepType() == FunctionGeneratorDefs::SweepDescType::SweepType::Frequency)
247  {
248  *InstrData->HardwareAdapter << std::string("TRIGger1:FSWeep:SOURce ")
249  + RS_SMB100B::TriggerModeToCmdString(TriggerDesc.TriggerMode);
250  if (TriggerDesc.TriggerMode == FunctionGeneratorDefs::TriggerDescType::TriggerModeType::ExternStep)
251  *InstrData->HardwareAdapter << "SOURce1:SWEep:FREQuency:MODE STEP";
252  else
253  *InstrData->HardwareAdapter << "SOURce1:SWEep:FREQuency:MODE AUTO";
254  }
255  else if (InstrData->GetCurrentSweepType() == FunctionGeneratorDefs::SweepDescType::SweepType::Amplitude)
256  {
257  *InstrData->HardwareAdapter << std::string("TRIGger1:PSWeep:SOURce ")
258  + RS_SMB100B::TriggerModeToCmdString(TriggerDesc.TriggerMode);
259  if (TriggerDesc.TriggerMode == FunctionGeneratorDefs::TriggerDescType::TriggerModeType::ExternStep)
260  *InstrData->HardwareAdapter << "SOURce1:SWEep:POWer:MODE STEP";
261  else
262  *InstrData->HardwareAdapter << "SOURce1:SWEep:POWer:MODE AUTO";
263  }
264 
265  *InstrData->HardwareAdapter << std::string("SOURce:INPut:TRIGger:SLOPe ") +
266  (TriggerDesc.TriggerEdge == FunctionGeneratorDefs::TriggerDescType::TriggerEdgeType::Fall ? "NEGative" : "POSitive");
267 
268  return {};
269  }
270 
272  {
273  NumFailedStatusUpdateAttempts = 0;
274  Running = false;
276 
277  ResetImpl(dispatch_tag<RS_SMB100BData>());
278  }
279 
281  {
282  switch (TriggerMode)
283  {
286  case FunctionGeneratorDefs::TriggerDescType::TriggerModeType::ExternStep: return "EXTernal";
287  case FunctionGeneratorDefs::TriggerDescType::TriggerModeType::Manual: return "SINGle";
288  default: return "";
289  }
290  }
291 
292  RS_SMB100B::RS_SMB100B(const std::thread::id OwnerThreadID, DynExp::ParamsBasePtrType&& Params)
293  : FunctionGenerator(OwnerThreadID, std::move(Params))
294  {
295  }
296 
298  bool PersistParams, bool Autostart, DynExp::TaskBase::CallbackType CallbackFunc) const
299  {
300  if (PersistParams)
301  {
302  auto InstrParams = DynExp::dynamic_Params_cast<FunctionGenerator>(GetNonConstParams());
303  InstrParams->WaveformType = FunctionGeneratorDefs::WaveformTypes::Sine;
304  InstrParams->FrequencyInHz = FunctionDesc.FrequencyInHz;
305  InstrParams->Amplitude = FunctionDesc.Amplitude;
306  InstrParams->Offset = 0;
307  InstrParams->PhaseInRad = FunctionDesc.PhaseInRad;
308  InstrParams->DutyCycle = 0;
309  InstrParams->Autostart = Autostart;
310  } // InstrParams unlocked here.
311 
312  MakeAndEnqueueTask<RS_SMB100BTasks::SetSineFunctionTask>(FunctionDesc, Autostart, CallbackFunc);
313  }
314 
316  bool PersistParams, DynExp::TaskBase::CallbackType CallbackFunc) const
317  {
318  MakeAndEnqueueTask<RS_SMB100BTasks::SetModulationTask>(ModulationDesc, CallbackFunc);
319  }
320 
322  bool PersistParams, DynExp::TaskBase::CallbackType CallbackFunc) const
323  {
324  MakeAndEnqueueTask<RS_SMB100BTasks::SetSweepTask>(SweepDesc, CallbackFunc);
325  }
326 
328  {
329  MakeAndEnqueueTask<RS_SMB100BTasks::ForceTriggerTask>(CallbackFunc);
330  }
331 
333  {
334  auto InstrData = DynExp::dynamic_InstrumentData_cast<RS_SMB100B>(GetInstrumentData());
335 
336  return InstrData->IsRunning();
337  }
338 
340  {
342  }
343 
345  bool PersistParams, DynExp::TaskBase::CallbackType CallbackFunc) const
346  {
347  MakeAndEnqueueTask<RS_SMB100BTasks::SetTriggerTask>(TriggerDesc, CallbackFunc);
348  }
349 }
Implementation of an instrument to control the Rohde & Schwarz SMB100B 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_SMB100B.cpp:271
void ExitFuncImpl(dispatch_tag< FunctionGeneratorTasks::ExitTask >, DynExp::InstrumentInstance &Instance) override final
Deinitializes the respective instrument within the instrument inheritance hierarchy....
Definition: RS_SMB100B.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_SMB100B.cpp:218
void InitFuncImpl(dispatch_tag< FunctionGeneratorTasks::InitTask >, DynExp::InstrumentInstance &Instance) override final
Initializes the respective instrument within the instrument inheritance hierarchy....
Definition: RS_SMB100B.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_SMB100B.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_SMB100B.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_SMB100B.cpp:163
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_SMB100B.cpp:242
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_SMB100B.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_SMB100B.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_SMB100B.cpp:27
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_SMB100B.cpp:344
RS_SMB100B(const std::thread::id OwnerThreadID, DynExp::ParamsBasePtrType &&Params)
Definition: RS_SMB100B.cpp:292
virtual Util::OptionalBool IsRunning() const override
Determines whether the underlying hardware adapter is running a data acquisition or writing data.
Definition: RS_SMB100B.cpp:332
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_SMB100B.cpp:297
virtual void ForceTrigger(DynExp::TaskBase::CallbackType CallbackFunc=nullptr) const override
Forces the generation of the waveform ignoring the trigger.
Definition: RS_SMB100B.cpp:327
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_SMB100B.cpp:321
static const char * TriggerModeToCmdString(FunctionGeneratorDefs::TriggerDescType::TriggerModeType TriggerMode) noexcept
Definition: RS_SMB100B.cpp:280
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_SMB100B.cpp:339
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_SMB100B.cpp:315
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
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...