DynExp
Highly flexible laboratory automation for dynamically changing experiments.
Loading...
Searching...
No Matches
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
6namespace 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 ") +
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
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 ")
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 ")
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);
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);
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
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
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
void ExitFuncImpl(dispatch_tag< FunctionGeneratorTasks::ExitTask >, DynExp::InstrumentInstance &Instance) override final
Deinitializes the respective instrument within the instrument inheritance hierarchy....
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...
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...
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...
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...
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...
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...
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...
void UpdateFuncImpl(dispatch_tag< FunctionGeneratorTasks::UpdateTask >, DynExp::InstrumentInstance &Instance) override final
Updates the respective instrument within the instrument inheritance hierarchy. Call UpdateFuncImpl() ...
virtual Util::OptionalBool IsRunning() const override
Determines whether the underlying hardware adapter is running a data acquisition or writing data.
void ResetImpl(dispatch_tag< FunctionGenerator >) override final
Refer to DynExp::Object::Reset(). Using tag dispatch mechanism to ensure that ResetImpl() of every de...
RS_SMC100A(const std::thread::id OwnerThreadID, DynExp::ParamsBasePtrType &&Params)
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...
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.
virtual void SetSineFunction(const FunctionGeneratorDefs::SineFunctionDescType &FunctionDesc, bool PersistParams=false, bool Autostart=false, DynExp::TaskBase::CallbackType CallbackFunc=nullptr) const override
Generates a sine function.
virtual void ForceTrigger(DynExp::TaskBase::CallbackType CallbackFunc=nullptr) const override
Forces the generation of the waveform ignoring the trigger.
static const char * TriggerModeToCmdString(FunctionGeneratorDefs::TriggerDescType::TriggerModeType TriggerMode) noexcept
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.
Refer to DynExp::ParamsBase::dispatch_tag.
Refer to DynExp::ParamsBase::dispatch_tag.
InstrumentDataTypeSyncPtrType GetInstrumentData(const std::chrono::milliseconds Timeout=GetInstrumentDataTimeoutDefault)
Locks the mutex of the instrument data class instance InstrumentData assigned to this InstrumentBase ...
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.
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
DynExp's instrument namespace contains the implementation of DynExp instruments which extend DynExp's...
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...
@ ExternStep
Advance by a single (sweep) sample after an external trigger signal has been detected.
@ Continuous
Run continuously disabling the trigger.
@ ExternSingle
Run once after an external trigger signal has been detected.