11 {
"DO 0", OutputChannelType::DO0 },
12 {
"DO 1", OutputChannelType::DO1 },
13 {
"DO 2", OutputChannelType::DO2 },
14 {
"DO 3", OutputChannelType::DO3 },
15 {
"DO 4", OutputChannelType::DO4 },
16 {
"DO 5", OutputChannelType::DO5 },
17 {
"DO 6", OutputChannelType::DO6 },
18 {
"DO 7", OutputChannelType::DO7 },
19 {
"AO 0", OutputChannelType::AO0 },
20 {
"AO 1", OutputChannelType::AO1 }
29 {
"Immediate", TriggerEdgeType::Immediate },
30 {
"Software", TriggerEdgeType::Software },
31 {
"Rising Edge", TriggerEdgeType::RisingEdge },
32 {
"Falling Edge", TriggerEdgeType::FallingEdge },
33 {
"Rising and Falling Edge", TriggerEdgeType::RisingAndFallingEdge }
42 {
"Normal", TriggerModeType::Normal },
43 {
"Single", TriggerModeType::Single }
51 auto Message = std::make_unique<pulse_streamer::PulseMessage>();
53 Message->set_ticks(
ticks);
54 Message->set_digi(
digi);
55 Message->set_ao0(
ao0);
56 Message->set_ao1(
ao1);
63 auto ClippedVoltage = std::min(Voltage, 1.0);
64 ClippedVoltage = std::max(ClippedVoltage, -1.0);
65 ClippedVoltage *=
static_cast<double>(0x7ff);
67 bool IsNeg = ClippedVoltage < 0.0;
68 int16_t Value =
static_cast<int16_t
>(std::floor(std::abs(ClippedVoltage)));
71 return Value * (IsNeg ? int16_t(-1) : int16_t(1));
78 if (
static_cast<std::underlying_type_t<SIPulseStreamerHardwareAdapterParams::OutputChannelType>
>(Channel) <= 7)
79 DOValue |= (
static_cast<bool>(Value) <<
static_cast<std::underlying_type_t<SIPulseStreamerHardwareAdapterParams::OutputChannelType>
>(Channel));
125 const std::vector<SampleType>& NewSamples)
const
198 std::vector<PulseType> Pulses;
200 for (
auto SampleIt =
Samples.cbegin(); SampleIt !=
Samples.cend(); ++SampleIt)
203 uint32_t Duration = (SampleIt + 1) !=
Samples.cend() ? Util::NumToT<uint32_t>(((SampleIt + 1)->Timestamp - SampleIt->Timestamp).count()) : 0;
207 int16_t AO0Value = SampleIt->Channel == SIPulseStreamerHardwareAdapterParams::OutputChannelType::AO0 ? SampleIt->Value : 0;
208 int16_t AO1Value = SampleIt->Channel == SIPulseStreamerHardwareAdapterParams::OutputChannelType::AO1 ? SampleIt->Value : 0;
210 Pulses.emplace_back(Duration, SampleIt->ComposeDOValue(), AO0Value, AO1Value);
214 int16_t AO0Value = SampleIt->Channel == SIPulseStreamerHardwareAdapterParams::OutputChannelType::AO0 ? SampleIt->Value : Pulses.back().ao0;
215 int16_t AO1Value = SampleIt->Channel == SIPulseStreamerHardwareAdapterParams::OutputChannelType::AO1 ? SampleIt->Value : Pulses.back().ao1;
217 uint8_t DOValue = Pulses.back().digi;
218 if (
static_cast<std::underlying_type_t<SIPulseStreamerHardwareAdapterParams::OutputChannelType>
>(SampleIt->Channel) <= 7)
219 DOValue = (DOValue & ~(1 <<
static_cast<std::underlying_type_t<SIPulseStreamerHardwareAdapterParams::OutputChannelType>
>(SampleIt->Channel))) | SampleIt->ComposeDOValue();
221 if (Pulses.back().ao0 == AO0Value && Pulses.back().ao1 == AO1Value && Pulses.back().digi == DOValue && (SampleIt + 1) !=
Samples.cend())
222 Pulses.back().ticks += Duration;
224 Pulses.emplace_back(Duration, DOValue, AO0Value, AO1Value);
233 auto DerivedParams = dynamic_Params_cast<SIPulseStreamerHardwareAdapter>(
GetParams());
248 auto Message =
Pulse.ToPulseMessage();
250 InvokeStubFunc(&pulse_streamer::PulseStreamer::Stub::constant, *Message);
259 const std::vector<SampleType>& NewSamples)
const
261 if (NewSamples.empty())
263 if (std::find_if(NewSamples.cbegin(), NewSamples.cend(), [OutputChannel](
const SampleType& Sample) { return Sample.Channel != OutputChannel; }) !=
266 "The channel of at least one sample in NewSamples does not match the specified OutputChannel.")));
269 Samples.insert(
Samples.end(), NewSamples.cbegin(), NewSamples.cend());
273 const auto FinalPulse = Pulses.back();
278 pulse_streamer::SequenceMessage SequenceMessage;
279 for (
const auto&
Pulse : Pulses)
281 auto PulseMessage = SequenceMessage.add_pulse();
282 *PulseMessage = *
Pulse.ToPulseMessage();
285 SequenceMessage.set_n_runs(
NumRuns);
286 SequenceMessage.set_allocated_final(FinalPulse.ToPulseMessage().release());
288 InvokeStubFunc(&pulse_streamer::PulseStreamer::Stub::stream, SequenceMessage);
302 pulse_streamer::TriggerMessage Message;
306 case SIPulseStreamerHardwareAdapterParams::TriggerEdgeType::Software: Message.set_start(pulse_streamer::TriggerMessage_Start::TriggerMessage_Start_SOFTWARE);
break;
307 case SIPulseStreamerHardwareAdapterParams::TriggerEdgeType::RisingEdge: Message.set_start(pulse_streamer::TriggerMessage_Start::TriggerMessage_Start_HARDWARE_RISING);
break;
308 case SIPulseStreamerHardwareAdapterParams::TriggerEdgeType::FallingEdge: Message.set_start(pulse_streamer::TriggerMessage_Start::TriggerMessage_Start_HARDWARE_FALLING);
break;
309 case SIPulseStreamerHardwareAdapterParams::TriggerEdgeType::RisingAndFallingEdge: Message.set_start(pulse_streamer::TriggerMessage_Start::TriggerMessage_Start_HARDWARE_RISING_AND_FALLING);
break;
310 default: Message.set_start(pulse_streamer::TriggerMessage_Start::TriggerMessage_Start_IMMEDIATE);
315 case SIPulseStreamerHardwareAdapterParams::TriggerModeType::Normal: Message.set_mode(pulse_streamer::TriggerMessage_Mode::TriggerMessage_Mode_NORMAL);
break;
316 default: Message.set_mode(pulse_streamer::TriggerMessage_Mode::TriggerMessage_Mode_SINGLE);
319 InvokeStubFunc(&pulse_streamer::PulseStreamer::Stub::setTrigger, Message);
335 return InvokeStubFunc(&pulse_streamer::PulseStreamer::Stub::isStreaming);
340 return InvokeStubFunc(&pulse_streamer::PulseStreamer::Stub::hasSequence);
345 return InvokeStubFunc(&pulse_streamer::PulseStreamer::Stub::hasFinished);
351 return std::strong_ordering::equal;
353 return std::strong_ordering::greater;
355 return std::strong_ordering::less;
Implementation of a hardware adapter to control Swabian Instruments Pulse Streamer 8/2 hardware.
static Util::TextValueListType< OutputChannelType > OutputChannelTypeStrList()
static Util::TextValueListType< TriggerEdgeType > TriggerEdgeTypeStrList()
static Util::TextValueListType< TriggerModeType > TriggerModeTypeStrList()
void ForceFinalSample() const
void SetNumRuns(int64_t NumRuns=-1) const
void SetTrigger(SIPulseStreamerHardwareAdapterParams::TriggerEdgeType TriggerEdge, SIPulseStreamerHardwareAdapterParams::TriggerModeType TriggerMode=SIPulseStreamerHardwareAdapterParams::TriggerModeType::Normal) const
virtual ~SIPulseStreamerHardwareAdapter()
virtual void OpenUnsafeChild() override
Override to add additional initialization steps. Gets executed after the gRPC connection has been est...
void SetSamples(SIPulseStreamerHardwareAdapterParams::OutputChannelType OutputChannel, const std::vector< SampleType > &NewSamples) const
std::vector< SampleType > Samples
Combined sample vector of all channels. Assumed to be always sorted.
void SetConstantOutput(const PulseType &Pulse={}) const
bool HasSequenceUnsafe() const
void SetSamplesUnsafe(SIPulseStreamerHardwareAdapterParams::OutputChannelType OutputChannel, const std::vector< SampleType > &NewSamples) const
void ResetDeviceUnsafe() const
SIPulseStreamerHardwareAdapter(const std::thread::id OwnerThreadID, DynExp::ParamsBasePtrType &&Params)
int64_t NumRuns
How often to repeat the sample sequence. -1 means indefinitely.
std::vector< PulseType > ComposePulseSequence() const
void SetTriggerUnsafe(SIPulseStreamerHardwareAdapterParams::TriggerEdgeType TriggerEdge, SIPulseStreamerHardwareAdapterParams::TriggerModeType TriggerMode=SIPulseStreamerHardwareAdapterParams::TriggerModeType::Normal) const
bool HasFinishedUnsafe() const
bool IsStreamingUnsafe() const
void RearmTriggerUnsafe() const
void ForceTriggerUnsafe() const
void RearmTrigger() const
void ForceTrigger() const
void SetNumRunsUnsafe(int64_t NumRuns=-1) const
void ForceFinalSampleUnsafe() const
void ResetImpl(dispatch_tag< gRPCHardwareAdapter >) override final
void SetConstantOutputUnsafe(const PulseType &Pulse={}) const
uint32_t InvokeStubFunc(StubFuncPtrType< MessageType > Func, const MessageType &Message) const
This template class provides basic functionality to design hardware adapters for instruments which co...
bool IsOpenedUnsafe() const noexcept
Checks whether the gRPCHardwareAdapter is connected to a server.
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...
const std::thread::id OwnerThreadID
Thread id of the thread which has constructed (and owns) this Object instance.
const ParamsBasePtrType Params
Pointer to the parameter class instance belonging to this Object instance.
Refer to ParamsBase::dispatch_tag.
Thrown when a list is expected to contain entries and when a query results in an empty answer or an e...
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.
Data to operate on is invalid for a specific purpose. This indicates a corrupted data structure or fu...
DynExp's hardware namespace contains the implementation of DynExp hardware adapters which extend DynE...
std::strong_ordering operator<=>(const SIPulseStreamerHardwareAdapter::SampleType &lhs, const SIPulseStreamerHardwareAdapter::SampleType &rhs)
@ Pulse
Manually defined pulses.
std::unique_ptr< ParamsBase > ParamsBasePtrType
Alias for a pointer to the parameter system base class ParamsBase.
std::vector< std::pair< TextType, ValueType > > TextValueListType
Type of a list containing key-value pairs where key is a text of type Util::TextType.
Accumulates include statements to provide a precompiled header.
Swabian Instruments Pulse Streamer 8/2's internal representation of a single pulse.
int16_t ao1
Analog out channel 1 (-0x7FFF is -1.0V, 0x7FFF is 1.0V)
uint32_t ticks
Duration in ns.
uint8_t digi
Digital out bit mask (LSB is channel 0, MSB is channel 7)
std::unique_ptr< pulse_streamer::PulseMessage > ToPulseMessage() const
int16_t ao0
Analog out channel 0 (-0x7FFF is -1.0V, 0x7FFF is 1.0V)
Sample of one output channel.
uint8_t ComposeDOValue() const
std::chrono::nanoseconds Timestamp
SIPulseStreamerHardwareAdapterParams::OutputChannelType Channel
static int16_t MakeValueFromVoltage(const double Voltage)