9 : Pulses(std::move(Other.Pulses)), Offset(Other.Offset)
15 : Pulses(std::move(Pulses)), Offset(0.0)
23 if (PulseStarts.size() != PulseAmplitudes.size())
26 std::transform(PulseStarts.cbegin(), PulseStarts.cend(), PulseAmplitudes.cbegin(),
28 [](
typename PulsesType::key_type key,
typename PulsesType::mapped_type value) { return std::make_pair(key, value); });
33 Pulses = std::move(Other.Pulses);
34 Offset = Other.Offset;
49 return std::fmod(Phase, 2.0 * std::numbers::pi) <= 2.0 * std::numbers::pi * DutyCycle;
55 return std::fmod(Phase, 2.0 * std::numbers::pi) > 2.0 * std::numbers::pi * DutyCycle;
64 constexpr
double MaxPrecision = 1e-6;
65 RiseFallRatio = std::min(1.0 - MaxPrecision, RiseFallRatio);
66 RiseFallRatio = std::max(MaxPrecision, RiseFallRatio);
68 return RectFunc(RiseFallRatio, Phase) * std::fmod(Phase, 2.0 * std::numbers::pi) / (std::numbers::pi * RiseFallRatio)
69 +
InvRectFunc(RiseFallRatio, Phase) * (std::fmod(-Phase, 2.0 * std::numbers::pi) + 2.0 * std::numbers::pi) / (std::numbers::pi * (1 - RiseFallRatio))
82 auto InstrParams = DynExp::dynamic_Params_cast<FunctionGenerator>(Instance.
ParamsGetter());
83 auto InstrData = DynExp::dynamic_InstrumentData_cast<FunctionGenerator>(Instance.
InstrumentDataGetter());
84 auto Owner = DynExp::dynamic_Object_cast<FunctionGenerator>(&Instance.
GetOwner());
88 InstrParams->FrequencyInHz, InstrParams->Amplitude, InstrParams->Offset, InstrParams->PhaseInRad),
89 false, InstrParams->Autostart.Get());
92 InstrParams->FrequencyInHz, InstrParams->Amplitude, InstrParams->Offset, InstrParams->PhaseInRad, InstrParams->DutyCycle),
93 false, InstrParams->Autostart.Get());
96 InstrParams->FrequencyInHz, InstrParams->Amplitude, InstrParams->Offset, InstrParams->PhaseInRad, InstrParams->DutyCycle),
97 false, InstrParams->Autostart.Get());
100 InstrParams->PulseStarts.Get(), InstrParams->PulseAmplitudes.Get(), InstrParams->Offset),
101 false, InstrParams->Autostart.Get());
105 InstrParams->TriggerMode, InstrParams->TriggerEdge),
112 auto InstrData = DynExp::dynamic_InstrumentData_cast<FunctionGenerator>(Instance.
InstrumentDataGetter());
113 if (InstrData->DataHasBeenUpdated)
114 if (InstrData->GetSampleStream()->GetNumSamplesWritten() >= InstrData->GetSampleStream()->GetStreamSizeWrite())
116 DynExp::dynamic_Object_cast<FunctionGenerator>(&Instance.
GetOwner())->WriteData();
117 InstrData->DataHasBeenUpdated =
false;
119 if (InstrData->ShouldAutostart)
120 DynExp::dynamic_Object_cast<FunctionGenerator>(&Instance.
GetOwner())->Start();
129 auto InstrData = DynExp::dynamic_InstrumentData_cast<FunctionGenerator>(Instance.
InstrumentDataGetter());
131 auto SampleStream = InstrData->GetSampleStream();
132 SampleStream->Clear();
134 auto NumSamples = SampleStream->GetStreamSizeWrite();
135 for (decltype(NumSamples) i = 0; i < NumSamples; ++i)
138 double Value = FunctionDesc.Amplitude * std::sin(FunctionDesc.FrequencyInHz * 2 * std::numbers::pi
139 * t.count() + FunctionDesc.PhaseInRad) + FunctionDesc.Offset;
141 SampleStream->WriteBasicSample({ Value, t.count() });
144 InstrData->DataHasBeenUpdated =
true;
146 InstrData->CurrentFrequencyInHz = FunctionDesc.FrequencyInHz;
147 InstrData->CurrentAmplitude = FunctionDesc.Amplitude;
148 InstrData->CurrentOffset = FunctionDesc.Offset;
149 InstrData->CurrentPhaseInRad = FunctionDesc.PhaseInRad;
150 InstrData->ShouldAutostart = Autostart;
157 auto InstrData = DynExp::dynamic_InstrumentData_cast<FunctionGenerator>(Instance.
InstrumentDataGetter());
159 auto SampleStream = InstrData->GetSampleStream();
160 SampleStream->Clear();
162 auto NumSamples = SampleStream->GetStreamSizeWrite();
163 for (decltype(NumSamples) i = 0; i < NumSamples; ++i)
167 FunctionDesc.FrequencyInHz * 2 * std::numbers::pi * t.count() + FunctionDesc.PhaseInRad) + FunctionDesc.Offset;
169 SampleStream->WriteBasicSample({ Value, t.count() });
172 InstrData->DataHasBeenUpdated =
true;
174 InstrData->CurrentFrequencyInHz = FunctionDesc.FrequencyInHz;
175 InstrData->CurrentAmplitude = FunctionDesc.Amplitude;
176 InstrData->CurrentOffset = FunctionDesc.Offset;
177 InstrData->CurrentPhaseInRad = FunctionDesc.PhaseInRad;
178 InstrData->CurrentDutyCycle = FunctionDesc.DutyCycle;
179 InstrData->ShouldAutostart = Autostart;
186 auto InstrData = DynExp::dynamic_InstrumentData_cast<FunctionGenerator>(Instance.
InstrumentDataGetter());
188 auto SampleStream = InstrData->GetSampleStream();
189 SampleStream->Clear();
191 auto NumSamples = SampleStream->GetStreamSizeWrite();
192 for (decltype(NumSamples) i = 0; i < NumSamples; ++i)
196 FunctionDesc.FrequencyInHz * 2 * std::numbers::pi * t.count() + FunctionDesc.PhaseInRad) + FunctionDesc.Offset;
198 SampleStream->WriteBasicSample({ Value, t.count() });
201 InstrData->DataHasBeenUpdated =
true;
203 InstrData->CurrentFrequencyInHz = FunctionDesc.FrequencyInHz;
204 InstrData->CurrentAmplitude = FunctionDesc.Amplitude;
205 InstrData->CurrentOffset = FunctionDesc.Offset;
206 InstrData->CurrentPhaseInRad = FunctionDesc.PhaseInRad;
207 InstrData->CurrentDutyCycle = FunctionDesc.RiseFallRatio;
208 InstrData->ShouldAutostart = Autostart;
215 auto InstrData = DynExp::dynamic_InstrumentData_cast<FunctionGenerator>(Instance.
InstrumentDataGetter());
217 if (FunctionDesc.Pulses.size() > 1)
219 auto SampleStream = InstrData->GetSampleStream();
220 SampleStream->Clear();
222 auto NumSamples = SampleStream->GetStreamSizeWrite();
223 auto StartTime = FunctionDesc.Pulses.cbegin()->first;
224 auto TimePerSample = (std::prev(FunctionDesc.Pulses.cend())->first - StartTime) / (NumSamples - 1);
225 auto PulseIt = FunctionDesc.Pulses.cbegin();
226 for (decltype(NumSamples) i = 0; i < NumSamples; ++i)
228 auto t = StartTime + i * TimePerSample;
229 while (std::next(PulseIt) != FunctionDesc.Pulses.cend() && t >= std::next(PulseIt)->first)
232 SampleStream->WriteBasicSample({ PulseIt->second + FunctionDesc.Offset, t });
236 InstrData->DataHasBeenUpdated =
true;
238 InstrData->CurrentPulses = FunctionDesc.Pulses;
239 InstrData->ShouldAutostart = Autostart;
246 auto InstrData = DynExp::dynamic_InstrumentData_cast<FunctionGenerator>(Instance.
InstrumentDataGetter());
248 auto SampleStream = InstrData->GetSampleStream();
249 SampleStream->Clear();
250 SampleStream->SetStreamSize(Samples.size());
251 SampleStream->WriteBasicSamples(Samples);
253 InstrData->DataHasBeenUpdated =
true;
255 InstrData->ShouldAutostart = Autostart;
262 auto InstrData = DynExp::dynamic_InstrumentData_cast<FunctionGenerator>(Instance.
InstrumentDataGetter());
264 InstrData->CurrentTriggerMode = TriggerDesc.TriggerMode;
265 InstrData->CurrentTriggerEdge = TriggerDesc.TriggerEdge;
272 DataHasBeenUpdated =
false;
278 CurrentPhaseInRad = 0;
279 CurrentDutyCycle = .5;
282 ShouldAutostart =
false;
284 CurrentPulses.Reset();
304 if (!GetWaveformCaps().Test(WaveformCapsType::UserDefined))
306 "The function generator of type " + GetCategoryAndName() +
" is not capable to generate a user-defined function.",
Util::ErrorType::Error);
310 auto InstrParams = DynExp::dynamic_Params_cast<FunctionGenerator>(GetNonConstParams());
313 InstrParams->Amplitude = FunctionDesc.
Amplitude;
314 InstrParams->Offset = FunctionDesc.
Offset;
315 InstrParams->PhaseInRad = IsPhaseAdjustable() ? FunctionDesc.
PhaseInRad : 0;
316 InstrParams->DutyCycle = .5;
317 InstrParams->Autostart = Autostart;
320 MakeAndEnqueueTask<FunctionGeneratorTasks::SetSineFunctionTask>(FunctionDesc, Autostart, CallbackFunc);
327 if (!GetWaveformCaps().Test(WaveformCapsType::UserDefined))
329 "The function generator of type " + GetCategoryAndName() +
" is not capable to generate a user-defined function.",
Util::ErrorType::Error);
333 auto InstrParams = DynExp::dynamic_Params_cast<FunctionGenerator>(GetNonConstParams());
336 InstrParams->Amplitude = FunctionDesc.
Amplitude;
337 InstrParams->Offset = FunctionDesc.
Offset;
338 InstrParams->PhaseInRad = IsPhaseAdjustable() ? FunctionDesc.
PhaseInRad : 0;
339 InstrParams->DutyCycle = FunctionDesc.
DutyCycle;
340 InstrParams->Autostart = Autostart;
343 MakeAndEnqueueTask<FunctionGeneratorTasks::SetRectFunctionTask>(FunctionDesc, Autostart, CallbackFunc);
350 if (!GetWaveformCaps().Test(WaveformCapsType::UserDefined))
352 "The function generator of type " + GetCategoryAndName() +
" is not capable to generate a user-defined function.",
Util::ErrorType::Error);
356 auto InstrParams = DynExp::dynamic_Params_cast<FunctionGenerator>(GetNonConstParams());
359 InstrParams->Amplitude = FunctionDesc.
Amplitude;
360 InstrParams->Offset = FunctionDesc.
Offset;
361 InstrParams->PhaseInRad = IsPhaseAdjustable() ? FunctionDesc.
PhaseInRad : 0;
363 InstrParams->Autostart = Autostart;
366 MakeAndEnqueueTask<FunctionGeneratorTasks::SetRampFunctionTask>(FunctionDesc, Autostart, CallbackFunc);
373 if (!GetWaveformCaps().Test(WaveformCapsType::UserDefined))
375 "The function generator of type " + GetCategoryAndName() +
" is not capable to generate a user-defined function.",
Util::ErrorType::Error);
378 if (FunctionDesc.
Pulses.size() < 1)
383 auto InstrParams = DynExp::dynamic_Params_cast<FunctionGenerator>(GetNonConstParams());
385 InstrParams->Offset = FunctionDesc.
Offset;
387 auto PulsesKeys = std::views::keys(FunctionDesc.
Pulses);
388 auto PulsesValues = std::views::values(FunctionDesc.
Pulses);
389 InstrParams->PulseStarts = { PulsesKeys.begin(), PulsesKeys.end() };
390 InstrParams->PulseAmplitudes = { PulsesValues.begin(), PulsesValues.end() };
392 InstrParams->Autostart = Autostart;
395 MakeAndEnqueueTask<FunctionGeneratorTasks::SetPulseFunctionTask>(FunctionDesc, Autostart, CallbackFunc);
402 if (!GetWaveformCaps().Test(WaveformCapsType::UserDefined))
404 "The function generator of type " + GetCategoryAndName() +
" is not capable to generate a user-defined function.",
Util::ErrorType::Error);
406 MakeAndEnqueueTask<FunctionGeneratorTasks::SetArbitraryFunctionTask>(std::move(Samples), Autostart, CallbackFunc);
427 auto InstrParams = DynExp::dynamic_Params_cast<FunctionGenerator>(GetNonConstParams());
428 InstrParams->TriggerMode = TriggerDesc.
TriggerMode;
429 InstrParams->TriggerEdge = TriggerDesc.
TriggerEdge;
433 MakeAndEnqueueTask<FunctionGeneratorTasks::SetTriggerTask>(TriggerDesc);
435 SetTriggerChild(TriggerDesc, PersistParams, CallbackFunc);
Implementation of a function generator meta instrument to generate waveforms.
std::vector< BasicSample > BasicSampleListType
Type of a list containing data stream samples of type BasicSample.
virtual ~FunctionGeneratorConfigurator()=0
void ResetImpl(dispatch_tag< DataStreamInstrumentData >) override final
virtual ~FunctionGeneratorParams()=0
void InitFuncImpl(dispatch_tag< DataStreamInstrumentTasks::InitTask >, DynExp::InstrumentInstance &Instance) override final
Initializes 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...
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< DataStreamInstrumentTasks::UpdateTask >, DynExp::InstrumentInstance &Instance) override final
Updates the respective instrument within the instrument inheritance hierarchy. Call UpdateFuncImpl() ...
virtual void ForceTriggerSync() const
Synchronized version of ForceTrigger(), which blocks until the task enqueued by ForceTrigger() has be...
virtual void SetModulation(const FunctionGeneratorDefs::ModulationDescType &ModulationDesc, bool PersistParams=false, DynExp::TaskBase::CallbackType CallbackFunc=nullptr) const
Configures the function generator to perform a modulation.
void ResetImpl(dispatch_tag< DataStreamInstrument >) override final
Refer to DynExp::Object::Reset(). Using tag dispatch mechanism to ensure that ResetImpl() of every de...
virtual ~FunctionGenerator()=0
virtual void SetRampFunction(const FunctionGeneratorDefs::RampFunctionDescType &FunctionDesc, bool PersistParams=false, bool Autostart=false, DynExp::TaskBase::CallbackType CallbackFunc=nullptr) const
Generates a ramp function.
virtual void SetRectFunction(const FunctionGeneratorDefs::RectFunctionDescType &FunctionDesc, bool PersistParams=false, bool Autostart=false, DynExp::TaskBase::CallbackType CallbackFunc=nullptr) const
Generates a rectangular function.
virtual void SetTriggerChild(const FunctionGeneratorDefs::TriggerDescType &TriggerDesc, bool PersistParams, DynExp::TaskBase::CallbackType CallbackFunc) const
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
Configures the function generator to perform a sweep.
virtual void SetPulseFunction(const FunctionGeneratorDefs::PulsesDescType &FunctionDesc, bool PersistParams=false, bool Autostart=false, DynExp::TaskBase::CallbackType CallbackFunc=nullptr) const
Generates a function consisting of pulse segments.
@ CanConfigure
Trigger settings can be adjusted by the software.
virtual void SetSineFunction(const FunctionGeneratorDefs::SineFunctionDescType &FunctionDesc, bool PersistParams=false, bool Autostart=false, DynExp::TaskBase::CallbackType CallbackFunc=nullptr) const
Generates a sine function.
virtual void ForceTrigger(DynExp::TaskBase::CallbackType CallbackFunc=nullptr) const
Forces the generation of the waveform ignoring the trigger.
virtual void SetArbitraryFunction(DataStreamBase::BasicSampleListType &&Samples, bool Autostart=false, DynExp::TaskBase::CallbackType CallbackFunc=nullptr) const
Generates an arbitrary function defined by the function samples.
void SetTrigger(const FunctionGeneratorDefs::TriggerDescType &TriggerDesc, bool PersistParams=false, DynExp::TaskBase::CallbackType CallbackFunc=nullptr) const
SetTrigger() configures the function generator's trigger, which determines when the waveform generati...
Refer to DynExp::ParamsBase::dispatch_tag.
Refer to ParamsBase::dispatch_tag.
Defines data for a thread belonging to a InstrumentBase instance. Refer to RunnableInstance.
const InstrumentBase::InstrumentDataGetterType InstrumentDataGetter
Getter for instrument's data. Refer to InstrumentBase::InstrumentDataGetterType.
Refer to ParamsBase::dispatch_tag.
const Object::ParamsGetterType ParamsGetter
Invoke to obtain the parameters (derived from ParamsBase) of Owner.
const auto & GetOwner() const noexcept
Returns Owner.
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....
Defines the return type of task functions.
Refer to DynExp::ParamsBase::dispatch_tag.
An invalid argument like a null pointer has been passed to a function.
Thrown when some operation or feature is temporarily or permanently not available.
Thrown when a requested feature is either under development and thus not implemented yet or when a sp...
double RectFunc(double DutyCycle, double Phase)
Calculates the value of a rectangular function depending on the current Phase.
constexpr Util::seconds PeriodFromFunctionDesc(const FunctionDescType &FunctionDesc)
Calculates the period from the given function description.
double InvRectFunc(double DutyCycle, double Phase)
Calculates the value of an inverse rectangular function depending on the current Phase.
@ Rect
Rectangular waveform.
@ Pulse
Manually defined pulses.
@ None
Unspecified/arbitrary waveform.
double RampFunc(double RiseFallRatio, double Phase)
Calculates the value of a ramp function depending on the current Phase.
constexpr FunctionDescType GetDefaultDefaultFunctionDesc()
Determines default values to assign to a description of a generic periodic function.
@ Rise
Trigger on rising edge.
@ Continuous
Run continuously disabling the trigger.
DynExp's instrument namespace contains the implementation of DynExp instruments which extend DynExp's...
std::chrono::duration< double > seconds
Extends std::chrono by a duration data type for seconds capable of storing fractions of seconds.
Accumulates include statements to provide a precompiled header.
Type describing a generic periodic function.
double Offset
Offset of the function to be added to each sample.
double FrequencyInHz
Frequency of the function in Hz.
double Amplitude
Amplitude of the function.
Type describing modulation parameters for a waveform.
Type describing function consisting of a series of pulses.
double Offset
Offset of the function to be added to each sample.
PulsesDescType & operator=(PulsesDescType &&Other)
Move assignment operator. Reset() is called on Other after the operation.
PulsesType Pulses
Series of segments forming the pulse sequence. The resulting function stays constant during a segment...
std::map< double, double > PulsesType
Type containing pulses as tuples (time [s], value). The time refers to the beginning of a segment whe...
Type describing a ramp function.
double PhaseInRad
Phase of the function in radians.
double RiseFallRatio
Ratio between the ramp's falling and rising edge lengths (in between 0 and 1)
Type describing a rectangular function.
double PhaseInRad
Phase of the function in radians.
double DutyCycle
Duty cycle of the function (in between 0 and 1)
Type describing a sine function.
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 TriggerMode
Trigger mode.
TriggerEdgeType TriggerEdge
Edge to trigger on.