From d7ec129f6fecc0c05640fe68fc6c82e7e8eb613b Mon Sep 17 00:00:00 2001 From: Nico Stuurman Date: Fri, 5 Jun 2026 12:32:10 -0700 Subject: [PATCH 1/2] NIDAQ: Make Voltage property sequenceable. --- DeviceAdapters/NIDAQ/NIAnalogOutputPort.cpp | 55 +++++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/DeviceAdapters/NIDAQ/NIAnalogOutputPort.cpp b/DeviceAdapters/NIDAQ/NIAnalogOutputPort.cpp index f62812321..8bc21e089 100644 --- a/DeviceAdapters/NIDAQ/NIAnalogOutputPort.cpp +++ b/DeviceAdapters/NIDAQ/NIAnalogOutputPort.cpp @@ -346,6 +346,61 @@ int NIAnalogOutputPort::OnVoltage(MM::PropertyBase* pProp, MM::ActionType eAct) if (err != DEVICE_OK) return err; } + else if (eAct == MM::IsSequenceable) + { + // Initialize to false: IsDASequenceable leaves the out-param + // untouched when neverSequenceable_ is set. + bool isSeq = false; + int err = IsDASequenceable(isSeq); + if (err != DEVICE_OK) + return err; + long maxLen = 0; + if (isSeq) + { + err = GetDASequenceMaxLength(maxLen); + if (err != DEVICE_OK) + return err; + } + pProp->SetSequenceable(isSeq ? maxLen : 0); + } + else if (eAct == MM::AfterLoadSequence) + { + std::vector sequence = pProp->GetSequence(); + int err = ClearDASequence(); + if (err != DEVICE_OK) + return err; + for (std::vector::const_iterator it = sequence.begin(), + end = sequence.end(); it != end; ++it) + { + double volts; + try + { + volts = std::stod(*it); + } + catch (const std::exception&) + { + return DEVICE_ERR; + } + err = AddToDASequence(volts); + if (err != DEVICE_OK) + return err; + } + err = SendDASequence(); + if (err != DEVICE_OK) + return err; + } + else if (eAct == MM::StartSequence) + { + int err = StartDASequence(); + if (err != DEVICE_OK) + return err; + } + else if (eAct == MM::StopSequence) + { + int err = StopDASequence(); + if (err != DEVICE_OK) + return err; + } return DEVICE_OK; } From d86702bc80b0a4ef3ccd7802e5e372479520c15a Mon Sep 17 00:00:00 2001 From: Nico Stuurman Date: Fri, 5 Jun 2026 12:42:04 -0700 Subject: [PATCH 2/2] NIDAQ: Address CoPilot comments. --- DeviceAdapters/NIDAQ/NIAnalogOutputPort.cpp | 27 ++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/DeviceAdapters/NIDAQ/NIAnalogOutputPort.cpp b/DeviceAdapters/NIDAQ/NIAnalogOutputPort.cpp index 8bc21e089..decc7d6fe 100644 --- a/DeviceAdapters/NIDAQ/NIAnalogOutputPort.cpp +++ b/DeviceAdapters/NIDAQ/NIAnalogOutputPort.cpp @@ -365,8 +365,21 @@ int NIAnalogOutputPort::OnVoltage(MM::PropertyBase* pProp, MM::ActionType eAct) } else if (eAct == MM::AfterLoadSequence) { + if (sequenceRunning_) + return ERR_SEQUENCE_RUNNING; + std::vector sequence = pProp->GetSequence(); - int err = ClearDASequence(); + if (sequence.empty()) + return ERR_SEQUENCE_ZERO_LENGTH; + + long maxLength = 0; + int err = GetDASequenceMaxLength(maxLength); + if (err != DEVICE_OK) + return err; + if (static_cast(sequence.size()) > maxLength) + return ERR_SEQUENCE_TOO_LONG; + + err = ClearDASequence(); if (err != DEVICE_OK) return err; for (std::vector::const_iterator it = sequence.begin(), @@ -375,11 +388,14 @@ int NIAnalogOutputPort::OnVoltage(MM::PropertyBase* pProp, MM::ActionType eAct) double volts; try { - volts = std::stod(*it); + std::size_t idx = 0; + volts = std::stod(*it, &idx); + if (idx != it->size()) + return DEVICE_INVALID_PROPERTY_VALUE; } catch (const std::exception&) { - return DEVICE_ERR; + return DEVICE_INVALID_PROPERTY_VALUE; } err = AddToDASequence(volts); if (err != DEVICE_OK) @@ -391,6 +407,11 @@ int NIAnalogOutputPort::OnVoltage(MM::PropertyBase* pProp, MM::ActionType eAct) } else if (eAct == MM::StartSequence) { + if (sequenceRunning_) + return ERR_SEQUENCE_RUNNING; + if (sentSequence_.empty()) + return ERR_SEQUENCE_ZERO_LENGTH; + int err = StartDASequence(); if (err != DEVICE_OK) return err;