diff --git a/include/libm2k/enums.hpp b/include/libm2k/enums.hpp index 4e277a75..5104698b 100644 --- a/include/libm2k/enums.hpp +++ b/include/libm2k/enums.hpp @@ -176,6 +176,19 @@ namespace libm2k { }; + /** + * @enum M2K_TRIGGER_OUT_SOURCE + * @brief Select the triggering source for a DeviceOut + */ + enum M2K_TRIGGER_OUT_SOURCE { + SRC_OUT_NONE = 0, ///< SRC_OUT_NONE - no trigger events + SRC_OUT_TRIGGER_IN = 1, ///< SRC_OUT_TRIGGER_IN - trigger events on the TI(trigger in) pin trigger the Output interface + SRC_OUT_TRIGGER_OUT = 2, ///< SRC_OUT_TRIGGER_OUT - trigger events on the TO(trigger out) pin trigger the Output interface + SRC_OUT_ANALOG_IN = 3, ///< SRC_OUT_ANALOG_IN - trigger events on the AnalogIn interface trigger the Output interface + SRC_OUT_DIGITAL_IN = 4, ///< SRC_OUT_DIGITAL_IN - trigger events on the DigitalIn interface trigger the Output interface + }; + + /** * @struct SETTINGS * @brief Triggering system diff --git a/include/libm2k/m2khardwaretrigger.hpp b/include/libm2k/m2khardwaretrigger.hpp index b66a4e91..b641415c 100644 --- a/include/libm2k/m2khardwaretrigger.hpp +++ b/include/libm2k/m2khardwaretrigger.hpp @@ -404,6 +404,90 @@ class LIBM2K_API M2kHardwareTrigger * @note Only available from firmware v0.24. */ virtual M2K_TRIGGER_SOURCE_DIGITAL getDigitalSource() const; + + + /** + * @brief Select which interface triggers the DigitalOut. + * @param src: of type M2K_TRIGGER_OUT_SOURCE:\n + * SRC_OUT_NONE - no trigger events + * SRC_OUT_TRIGGER_IN - trigger events on the TI(trigger in) pin trigger the DigitalOut interface;\n + * SRC_OUT_TRIGGER_OUT - trigger events on the TO(trigger out) pin trigger the DigitalOut interface;\n + * SRC_OUT_ANALOG_IN - trigger events on the AnalogIn interface trigger the DigitalOut interface;\n + * SRC_OUT_DIGITAL_IN - trigger events on the DigitalIn interface trigger the DigitalOut interface;\n + * @note Only available from firmware v0.26. + */ + virtual void setDigitalOutSource(M2K_TRIGGER_OUT_SOURCE src) = 0; + + + /** + * @brief Retrieve the source of the DigitalOut interface trigger event. + * @return M2K_TRIGGER_OUT_SOURCE :\n + * SRC_OUT_NONE;\n + * SRC_OUT_TRIGGER_IN;\n + * SRC_OUT_TRIGGER_OUT;\n + * SRC_OUT_ANALOG_IN;\n + * SRC_OUT_DIGITAL_IN;\n + * @note Only available from firmware v0.26. + */ + virtual M2K_TRIGGER_OUT_SOURCE getDigitalOutSource() const = 0; + + + /** + * @brief Set the trigger condition for the TI/TO in order to trigger the DigitalOut interface + * @param cond the specific trigger condition + * + * @note to have any effect the digital out source must be set to TI or TO + */ + virtual void setDigitalOutCondition(M2K_TRIGGER_CONDITION_DIGITAL cond) = 0; + + + /** + * @brief Get the trigger condition of the TI/TO pins that triggers the DigitalOut interface + * @return the trigger condition + */ + virtual M2K_TRIGGER_CONDITION_DIGITAL getDigitalOutCondition() const = 0; + + + /** + * @brief Select which interface triggers the AnalogOut. + * @param src: of type M2K_TRIGGER_OUT_SOURCE:\n + * SRC_OUT_NONE - no trigger events + * SRC_OUT_TRIGGER_IN - trigger events on the TI(trigger in) pin trigger the DigitalOut interface;\n + * SRC_OUT_TRIGGER_OUT - trigger events on the TO(trigger out) pin trigger the DigitalOut interface;\n + * SRC_OUT_ANALOG_IN - trigger events on the AnalogIn interface trigger the DigitalOut interface;\n + * SRC_OUT_DIGITAL_IN - trigger events on the DigitalIn interface trigger the DigitalOut interface;\n + * @note Only available from firmware v0.26. + */ + virtual void setAnalogOutSource(M2K_TRIGGER_OUT_SOURCE src) = 0; + + + /** + * @brief Retrieve the source of the AnalogOut interface trigger event. + * @return M2K_TRIGGER_OUT_SOURCE :\n + * SRC_OUT_NONE;\n + * SRC_OUT_TRIGGER_IN;\n + * SRC_OUT_TRIGGER_OUT;\n + * SRC_OUT_ANALOG_IN;\n + * SRC_OUT_DIGITAL_IN;\n + * @note Only available from firmware v0.26. + */ + virtual M2K_TRIGGER_OUT_SOURCE getAnalogOutSource() const = 0; + + + /** + * @brief Set the trigger condition for the TI/TO in order to trigger the AnalogOut interface + * @param cond the specific trigger condition + * + * @note to have any effect the digital out source must be set to TI or TO + */ + virtual void setAnalogOutCondition(M2K_TRIGGER_CONDITION_DIGITAL cond) = 0; + + + /** + * @brief Get the trigger condition of the TI/TO pins that triggers the AnalogOut interface + * @return the trigger condition + */ + virtual M2K_TRIGGER_CONDITION_DIGITAL getAnalogOutCondition() const = 0; }; } diff --git a/src/m2k_impl.cpp b/src/m2k_impl.cpp index cf59a050..62beae0e 100644 --- a/src/m2k_impl.cpp +++ b/src/m2k_impl.cpp @@ -26,6 +26,7 @@ #include #include "m2khardwaretrigger_impl.hpp" #include "m2khardwaretrigger_v0.24_impl.hpp" +#include "m2khardwaretrigger_v0.26_impl.hpp" #include "m2kcalibration_impl.hpp" #include #include "utils/channel.hpp" @@ -69,11 +70,16 @@ M2kImpl::M2kImpl(std::string uri, iio_context* ctx, std::string name, bool sync) m_firmware_version = getFirmwareVersion(); - int diff = Utils::compareVersions(m_firmware_version, "v0.24"); - if (diff < 0) { //m_firmware_version < 0.24 + int diff_v024 = Utils::compareVersions(m_firmware_version, "v0.24"); + if (diff_v024 < 0) { //m_firmware_version < 0.24 m_trigger = new M2kHardwareTriggerImpl(ctx); } else { - m_trigger = new M2kHardwareTriggerV024Impl(ctx); + int diff_v026 = Utils::compareVersions(m_firmware_version, "v0.26"); + if (diff_v026 < 0) { // firmware version 0.24, 0.25 + m_trigger = new M2kHardwareTriggerV024Impl(ctx); + } else { //firmware version >= 0.26 + m_trigger = new M2kHardwareTriggerV026Impl(ctx); + } } if (!m_trigger) { diff --git a/src/m2khardwaretrigger_impl.cpp b/src/m2khardwaretrigger_impl.cpp index cfc54b1f..4a91731e 100644 --- a/src/m2khardwaretrigger_impl.cpp +++ b/src/m2khardwaretrigger_impl.cpp @@ -570,3 +570,51 @@ void M2kHardwareTriggerImpl::setCalibParameters(unsigned int chnIdx, double scal m_scaling[chnIdx] = scaling; m_offset[chnIdx] = offset; } + +void M2kHardwareTriggerImpl::setDigitalOutSource(M2K_TRIGGER_OUT_SOURCE src) +{ + UNUSED(src); + THROW_M2K_EXCEPTION("Invalid firmware version. Minimum required version: v0.26", libm2k::EXC_INVALID_FIRMWARE_VERSION); +} + +M2K_TRIGGER_OUT_SOURCE M2kHardwareTriggerImpl::getDigitalOutSource() const +{ + THROW_M2K_EXCEPTION("Invalid firmware version. Minimum required version: v0.26", libm2k::EXC_INVALID_FIRMWARE_VERSION); + return SRC_OUT_NONE; +} + +void M2kHardwareTriggerImpl::setDigitalOutCondition(M2K_TRIGGER_CONDITION_DIGITAL cond) +{ + UNUSED(cond); + THROW_M2K_EXCEPTION("Invalid firmware version. Minimum required version: v0.26", libm2k::EXC_INVALID_FIRMWARE_VERSION); +} + +M2K_TRIGGER_CONDITION_DIGITAL M2kHardwareTriggerImpl::getDigitalOutCondition() const +{ + THROW_M2K_EXCEPTION("Invalid firmware version. Minimum required version: v0.26", libm2k::EXC_INVALID_FIRMWARE_VERSION); + return NO_TRIGGER_DIGITAL; +} + +void M2kHardwareTriggerImpl::setAnalogOutSource(M2K_TRIGGER_OUT_SOURCE src) +{ + UNUSED(src); + THROW_M2K_EXCEPTION("Invalid firmware version. Minimum required version: v0.26", libm2k::EXC_INVALID_FIRMWARE_VERSION); +} + +M2K_TRIGGER_OUT_SOURCE M2kHardwareTriggerImpl::getAnalogOutSource() const +{ + THROW_M2K_EXCEPTION("Invalid firmware version. Minimum required version: v0.26", libm2k::EXC_INVALID_FIRMWARE_VERSION); + return SRC_OUT_NONE; +} + +void M2kHardwareTriggerImpl::setAnalogOutCondition(M2K_TRIGGER_CONDITION_DIGITAL cond) +{ + UNUSED(cond); + THROW_M2K_EXCEPTION("Invalid firmware version. Minimum required version: v0.26", libm2k::EXC_INVALID_FIRMWARE_VERSION); +} + +M2K_TRIGGER_CONDITION_DIGITAL M2kHardwareTriggerImpl::getAnalogOutCondition() const +{ + THROW_M2K_EXCEPTION("Invalid firmware version. Minimum required version: v0.26", libm2k::EXC_INVALID_FIRMWARE_VERSION); + return NO_TRIGGER_DIGITAL; +} diff --git a/src/m2khardwaretrigger_impl.hpp b/src/m2khardwaretrigger_impl.hpp index 9abeb401..c7c05715 100644 --- a/src/m2khardwaretrigger_impl.hpp +++ b/src/m2khardwaretrigger_impl.hpp @@ -107,6 +107,15 @@ class M2kHardwareTriggerImpl : public M2kHardwareTrigger M2K_TRIGGER_CONDITION_DIGITAL getDigitalCondition(DIO_CHANNEL chn); void setDigitalCondition(DIO_CHANNEL chn, M2K_TRIGGER_CONDITION_DIGITAL cond); + void setDigitalOutSource(M2K_TRIGGER_OUT_SOURCE src) override; + M2K_TRIGGER_OUT_SOURCE getDigitalOutSource() const override; + void setDigitalOutCondition(M2K_TRIGGER_CONDITION_DIGITAL cond) override; + M2K_TRIGGER_CONDITION_DIGITAL getDigitalOutCondition() const override; + void setAnalogOutSource(M2K_TRIGGER_OUT_SOURCE src) override; + M2K_TRIGGER_OUT_SOURCE getAnalogOutSource() const override; + void setAnalogOutCondition(M2K_TRIGGER_CONDITION_DIGITAL cond) override; + M2K_TRIGGER_CONDITION_DIGITAL getAnalogOutCondition() const override; + protected: struct iio_device *m_trigger_device; std::vector m_analog_channels; diff --git a/src/m2khardwaretrigger_v0.26_impl.cpp b/src/m2khardwaretrigger_v0.26_impl.cpp new file mode 100644 index 00000000..c8962790 --- /dev/null +++ b/src/m2khardwaretrigger_v0.26_impl.cpp @@ -0,0 +1,180 @@ +/* + * Copyright (c) 2020 Analog Devices Inc. + * + * This file is part of libm2k + * (see http://www.github.com/analogdevicesinc/libm2k). + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 2.1 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + * + */ + +#include "m2khardwaretrigger_v0.26_impl.hpp" +#include +#include + + +const std::string libm2k::M2kHardwareTriggerV026Impl::m_source_attr = "trigger_src"; +const std::string libm2k::M2kHardwareTriggerV026Impl::m_condition_attr = "trigger_condition"; + + +std::vector libm2k::M2kHardwareTriggerV026Impl::m_trigger_source = { + "none", + "trigger-i_0", + "trigger-i_1", + "trigger-adc", + "trigger-la", +}; + +std::vector libm2k::M2kHardwareTriggerV026Impl::m_trigger_cond = { + "edge-rising", + "edge-falling", + "level-low", + "level-high", + "edge-any", + "none" +}; + +libm2k::M2kHardwareTriggerV026Impl::M2kHardwareTriggerV026Impl(struct iio_context *ctx, bool init) : + M2kHardwareTriggerV024Impl(ctx) +{ + bool hasTriggerSource; + bool hasTriggerCondition; + m_digital_trigger_device = make_shared(ctx, "m2k-logic-analyzer-tx"); + // both dac a and dac b share the same trigger + m_analog_trigger_device = make_shared(ctx, "m2k-dac-a"); + if (!m_digital_trigger_device) { + THROW_M2K_EXCEPTION("No digital TX trigger available", libm2k::EXC_RUNTIME_ERROR); + } + if (!m_analog_trigger_device) { + THROW_M2K_EXCEPTION("No analog TX trigger available", libm2k::EXC_RUNTIME_ERROR); + } + + hasTriggerSource = m_digital_trigger_device->hasGlobalAttribute(m_source_attr); + hasTriggerCondition = m_digital_trigger_device->hasGlobalAttribute(m_condition_attr); + if (!hasTriggerSource || !hasTriggerCondition) { + THROW_M2K_EXCEPTION("Analog TX trigger is not available", libm2k::EXC_RUNTIME_ERROR); + } + + hasTriggerSource = m_analog_trigger_device->hasGlobalAttribute(m_source_attr); + hasTriggerCondition = m_analog_trigger_device->hasGlobalAttribute(m_condition_attr); + if (!hasTriggerSource || !hasTriggerCondition) { + THROW_M2K_EXCEPTION("Analog TX trigger is not available", libm2k::EXC_RUNTIME_ERROR); + } + + if (init) { + reset(); + } +} + +void libm2k::M2kHardwareTriggerV026Impl::reset() { + M2kHardwareTriggerV024Impl::reset(); + setDigitalOutSource(SRC_OUT_NONE); + setDigitalOutCondition(NO_TRIGGER_DIGITAL); + setAnalogOutSource(SRC_OUT_NONE); + setAnalogOutCondition(NO_TRIGGER_DIGITAL); +} + +void libm2k::M2kHardwareTriggerV026Impl::setDigitalOutSource(libm2k::M2K_TRIGGER_OUT_SOURCE src) +{ + setTriggerOutSource(src, m_digital_trigger_device); +} + +libm2k::M2K_TRIGGER_OUT_SOURCE libm2k::M2kHardwareTriggerV026Impl::getDigitalOutSource() const +{ + return getTriggerOutSource(m_digital_trigger_device); +} + +void libm2k::M2kHardwareTriggerV026Impl::setDigitalOutCondition(libm2k::M2K_TRIGGER_CONDITION_DIGITAL cond) +{ + setTriggerOutCondition(cond, m_digital_trigger_device); +} + +libm2k::M2K_TRIGGER_CONDITION_DIGITAL libm2k::M2kHardwareTriggerV026Impl::getDigitalOutCondition() const +{ + return getTriggerOutCondition(m_digital_trigger_device); +} + +void libm2k::M2kHardwareTriggerV026Impl::setAnalogOutSource(libm2k::M2K_TRIGGER_OUT_SOURCE src) +{ + setTriggerOutSource(src, m_analog_trigger_device); +} + +libm2k::M2K_TRIGGER_OUT_SOURCE libm2k::M2kHardwareTriggerV026Impl::getAnalogOutSource() const +{ + return getTriggerOutSource(m_analog_trigger_device); +} + +void libm2k::M2kHardwareTriggerV026Impl::setAnalogOutCondition(libm2k::M2K_TRIGGER_CONDITION_DIGITAL cond) +{ + setTriggerOutCondition(cond, m_analog_trigger_device); +} + +libm2k::M2K_TRIGGER_CONDITION_DIGITAL libm2k::M2kHardwareTriggerV026Impl::getAnalogOutCondition() const +{ + return getTriggerOutCondition(m_analog_trigger_device); +} + +void libm2k::M2kHardwareTriggerV026Impl::setTriggerOutSource(libm2k::M2K_TRIGGER_OUT_SOURCE src, + const std::shared_ptr& device) +{ + if (src >= m_trigger_source.size()) { + THROW_M2K_EXCEPTION("M2kHardwareTrigger: " + "the provided source is not supported on " + "the current board; Check the firmware version.", + libm2k::EXC_INVALID_PARAMETER); + } + std::string src_str = m_trigger_source[src]; + device->setStringValue(m_source_attr, src_str); +} + +libm2k::M2K_TRIGGER_OUT_SOURCE +libm2k::M2kHardwareTriggerV026Impl::getTriggerOutSource(const std::shared_ptr& device) const +{ + std::string buf = device->getStringValue(m_source_attr); + + auto it = std::find(m_trigger_source.begin(), + m_trigger_source.end(), buf.c_str()); + if (it == m_trigger_source.end()) { + THROW_M2K_EXCEPTION("Unexpected value read from attribute: " + m_source_attr, libm2k::EXC_INVALID_PARAMETER); + } + + return static_cast(it - m_trigger_source.begin()); +} + +void libm2k::M2kHardwareTriggerV026Impl::setTriggerOutCondition( + libm2k::M2K_TRIGGER_CONDITION_DIGITAL cond, const std::shared_ptr& device) +{ + if (cond >= m_trigger_cond.size()) { + THROW_M2K_EXCEPTION("M2kHardwareTrigger: " + "the provided condition is not supported on " + "the current board; Check the firmware version.", + libm2k::EXC_INVALID_PARAMETER); + } + std::string src_str = m_trigger_cond[cond]; + device->setStringValue(m_condition_attr, src_str); +} + +libm2k::M2K_TRIGGER_CONDITION_DIGITAL +libm2k::M2kHardwareTriggerV026Impl::getTriggerOutCondition(const std::shared_ptr& device) const +{ + std::string buf = device->getStringValue(m_condition_attr); + + auto it = std::find(m_trigger_cond.begin(), + m_trigger_cond.end(), buf.c_str()); + if (it == m_trigger_cond.end()) { + THROW_M2K_EXCEPTION("Unexpected value read from attribute: " + m_condition_attr, libm2k::EXC_INVALID_PARAMETER); + } + + return static_cast(it - m_trigger_cond.begin()); +} diff --git a/src/m2khardwaretrigger_v0.26_impl.hpp b/src/m2khardwaretrigger_v0.26_impl.hpp new file mode 100644 index 00000000..44e7333d --- /dev/null +++ b/src/m2khardwaretrigger_v0.26_impl.hpp @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2020 Analog Devices Inc. + * + * This file is part of libm2k + * (see http://www.github.com/analogdevicesinc/libm2k). + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 2.1 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + * + */ + +#ifndef M2KOUTHARDWARETRIGGER_IMPL_HPP +#define M2KOUTHARDWARETRIGGER_IMPL_HPP + +#include "m2khardwaretrigger_v0.24_impl.hpp" +#include "utils/deviceout.hpp" + + +namespace libm2k { + +class M2kHardwareTriggerV026Impl : public M2kHardwareTriggerV024Impl { +public: + explicit M2kHardwareTriggerV026Impl(struct iio_context *ctx, bool init = true); + + ~M2kHardwareTriggerV026Impl() override = default; + + void reset() override; + + void setDigitalOutSource(M2K_TRIGGER_OUT_SOURCE src) override; + + M2K_TRIGGER_OUT_SOURCE getDigitalOutSource() const override; + + void setDigitalOutCondition(M2K_TRIGGER_CONDITION_DIGITAL cond) override; + + M2K_TRIGGER_CONDITION_DIGITAL getDigitalOutCondition() const override; + + void setAnalogOutSource(M2K_TRIGGER_OUT_SOURCE src) override; + + M2K_TRIGGER_OUT_SOURCE getAnalogOutSource() const override; + + void setAnalogOutCondition(M2K_TRIGGER_CONDITION_DIGITAL cond) override; + + M2K_TRIGGER_CONDITION_DIGITAL getAnalogOutCondition() const override; + +protected: + void setTriggerOutSource(M2K_TRIGGER_OUT_SOURCE src, const std::shared_ptr& device); + M2K_TRIGGER_OUT_SOURCE getTriggerOutSource(const std::shared_ptr& device) const; + void setTriggerOutCondition(M2K_TRIGGER_CONDITION_DIGITAL cond, const std::shared_ptr& device); + M2K_TRIGGER_CONDITION_DIGITAL getTriggerOutCondition(const std::shared_ptr& device) const; + + std::shared_ptr m_digital_trigger_device; + std::shared_ptr m_analog_trigger_device; + + static std::vector m_trigger_source; + static std::vector m_trigger_cond; + + static const std::string m_source_attr; + static const std::string m_condition_attr; +}; +} + +#endif //M2KOUTHARDWARETRIGGER_IMPL_HPP