From c11630e50a7712872dc573a186c1bb66e20b2124 Mon Sep 17 00:00:00 2001 From: Carl Philipp Klemm Date: Mon, 13 Oct 2025 13:59:35 +0200 Subject: [PATCH 1/2] add trigger support --- CMakeLists.txt | 2 + mainwindow.cpp | 17 +++++++- mainwindow.h | 19 +++++---- triggerwidget.cpp | 105 ++++++++++++++++++++++++++++++++++++++++++++++ triggerwidget.h | 45 ++++++++++++++++++++ 5 files changed, 180 insertions(+), 8 deletions(-) create mode 100644 triggerwidget.cpp create mode 100644 triggerwidget.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 7f22417..c1b9490 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -41,6 +41,8 @@ add_executable(${PROJECT_NAME} mainwindow.ui multiplexer.h multiplexer.cpp + triggerwidget.cpp + triggerwidget.h ) set_target_properties(${PROJECT_NAME} PROPERTIES WIN32_EXECUTABLE ON) target_compile_options(${PROJECT_NAME} PUBLIC "-Wall") diff --git a/mainwindow.cpp b/mainwindow.cpp index b69934e..63ffe7a 100644 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -2,6 +2,7 @@ #include #include "mainwindow.h" #include "ui_mainwindow.h" +#include "triggerwidget.h" MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) @@ -55,6 +56,20 @@ void MainWindow::enumerateDevices() ui->channelLayout->addWidget(widget.get()); } } + + // Add trigger widgets + int triggerCount = eismultiplexer_get_trigger_count(multiplexer.get()); + if (triggerCount > 0) + { + qDebug()<<"Adding triggers from device "< triggerWidget(new TriggerWidget(serial, trigger, multiplexer)); + qDebug()<<"Added trigger widget from device "<channelLayout->addWidget(triggerWidget.get()); + } + } } else { @@ -65,7 +80,7 @@ void MainWindow::enumerateDevices() } ui->channelLayout->addStretch(); - // Second pass: populate gang combos and connect signals + // Second pass: populate gang combos and connect signals for channels for (const auto& widget : channels) { // Populate gang combo with all other channels for (const auto& otherWidget : channels) { diff --git a/mainwindow.h b/mainwindow.h index cb1a19c..248007a 100644 --- a/mainwindow.h +++ b/mainwindow.h @@ -1,3 +1,5 @@ + + #ifndef MAINWINDOW_H #define MAINWINDOW_H @@ -5,6 +7,7 @@ #include #include "channelwidget.h" +#include "triggerwidget.h" namespace Ui { @@ -13,19 +16,21 @@ class MainWindow; class MainWindow : public QMainWindow { - Q_OBJECT - std::vector> channels; - Ui::MainWindow *ui; + Q_OBJECT + std::vector> channels; + std::vector> triggers; + Ui::MainWindow *ui; signals: - void channelStateChanged(uint16_t device, uint16_t channel); + void channelStateChanged(uint16_t device, uint16_t channel); public: - explicit MainWindow(QWidget *parent = nullptr); - ~MainWindow(); + explicit MainWindow(QWidget *parent = nullptr); + ~MainWindow(); private: - void enumerateDevices(); + void enumerateDevices(); }; #endif // MAINWINDOW_H + diff --git a/triggerwidget.cpp b/triggerwidget.cpp new file mode 100644 index 0000000..6143e0e --- /dev/null +++ b/triggerwidget.cpp @@ -0,0 +1,105 @@ + + +#include "triggerwidget.h" +#include +#include + +TriggerWidget::TriggerWidget(uint16_t deviceSerial, uint16_t triggerNumber, + std::shared_ptr multiplexer, + QWidget *parent) + : + QWidget(parent), + deviceSerial(deviceSerial), + triggerNumber(triggerNumber), + multiplexer(multiplexer), + inputCheckbox("Input"), + levelCheckbox("Level"), + devicelabel(QString::asprintf("Device %04u", deviceSerial)), + triggerlabel(QString::asprintf("Trigger %u", triggerNumber)) +{ + hlayout.addLayout(&labellayout); + vlayout.addLayout(&hlayout); + + labellayout.addWidget(&devicelabel); + labellayout.addWidget(&triggerlabel); + + line.setFrameShape(QFrame::HLine); + line.setFrameShadow(QFrame::Sunken); + vlayout.addWidget(&line); + + hlayout.addStretch(); + hlayout.addWidget(&inputCheckbox); + hlayout.addWidget(&levelCheckbox); + + connect(&inputCheckbox, &QCheckBox::toggled, this, &TriggerWidget::onInputToggled); + connect(&levelCheckbox, &QCheckBox::toggled, this, &TriggerWidget::onLevelToggled); + + setFixedHeight(96); + setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); + + setLayout(&vlayout); + + // Initialize trigger state + updateTriggerState(); +} + +TriggerWidget::~TriggerWidget() +{ +} + +uint16_t TriggerWidget::getDeviceSerial() const +{ + return deviceSerial; +} + +uint16_t TriggerWidget::getTriggerNumber() const +{ + return triggerNumber; +} + +void TriggerWidget::onInputToggled(bool checked) +{ + if (checked) { + // Set to input mode + if (eismultiplexer_set_trigger_state(multiplexer.get(), triggerNumber, TRIGGER_INPUT) < 0) { + QMessageBox::warning(this, tr("Trigger Configuration Failed"), + tr("Failed to set trigger %1 on device %2 to input mode").arg(triggerNumber).arg(deviceSerial)); + qWarning() << "Failed to set trigger" << triggerNumber << "on device" << deviceSerial << "to input mode"; + inputCheckbox.blockSignals(true); + inputCheckbox.setChecked(false); + inputCheckbox.blockSignals(false); + } else { + // When input is checked, level should be unchecked and disabled + levelCheckbox.blockSignals(true); + levelCheckbox.setChecked(false); + levelCheckbox.setEnabled(false); + levelCheckbox.blockSignals(false); + } + } else { + // Update the trigger state based on level checkbox + updateTriggerState(); + } +} + +void TriggerWidget::onLevelToggled(bool checked) +{ + if (!inputCheckbox.isChecked()) { + // Only update if not in input mode + updateTriggerState(); + } +} + +void TriggerWidget::updateTriggerState() +{ + trigger_state_t state = TRIGGER_LOW; + if (!inputCheckbox.isChecked() && levelCheckbox.isChecked()) { + state = TRIGGER_HIGH; + } + + if (eismultiplexer_set_trigger_state(multiplexer.get(), triggerNumber, state) < 0) { + QMessageBox::warning(this, tr("Trigger Configuration Failed"), + tr("Failed to set trigger %1 on device %2").arg(triggerNumber).arg(deviceSerial)); + qWarning() << "Failed to set trigger" << triggerNumber << "on device" << deviceSerial; + } +} + diff --git a/triggerwidget.h b/triggerwidget.h new file mode 100644 index 0000000..718ed1b --- /dev/null +++ b/triggerwidget.h @@ -0,0 +1,45 @@ + +#ifndef TRIGGERWIDGET_H +#define TRIGGERWIDGET_H + +#include +#include +#include +#include +#include +#include +#include + +class TriggerWidget : public QWidget +{ + Q_OBJECT + +public: + explicit TriggerWidget(uint16_t deviceSerial, uint16_t triggerNumber, + std::shared_ptr multiplexer, + QWidget *parent = nullptr); + ~TriggerWidget() override; + + uint16_t getDeviceSerial() const; + uint16_t getTriggerNumber() const; + +private slots: + void onInputToggled(bool checked); + void onLevelToggled(bool checked); + void updateTriggerState(); + +private: + uint16_t deviceSerial; + uint16_t triggerNumber; + std::shared_ptr multiplexer; + QCheckBox inputCheckbox; + QCheckBox levelCheckbox; + QLabel devicelabel; + QLabel triggerlabel; + QFrame line; + QVBoxLayout vlayout; + QHBoxLayout hlayout; + QVBoxLayout labellayout; +}; + +#endif // TRIGGERWIDGET_H From fd85e5b6489e84e1f800d7aff27a975e27d63c9c Mon Sep 17 00:00:00 2001 From: Carl Philipp Klemm Date: Mon, 13 Oct 2025 14:08:43 +0200 Subject: [PATCH 2/2] Fix trigger state handling --- triggerwidget.cpp | 48 +++++++++++++++++++---------------------------- 1 file changed, 19 insertions(+), 29 deletions(-) diff --git a/triggerwidget.cpp b/triggerwidget.cpp index 6143e0e..efa6627 100644 --- a/triggerwidget.cpp +++ b/triggerwidget.cpp @@ -3,11 +3,11 @@ #include "triggerwidget.h" #include #include +#include TriggerWidget::TriggerWidget(uint16_t deviceSerial, uint16_t triggerNumber, std::shared_ptr multiplexer, - QWidget *parent) - : + QWidget *parent): QWidget(parent), deviceSerial(deviceSerial), triggerNumber(triggerNumber), @@ -20,6 +20,9 @@ TriggerWidget::TriggerWidget(uint16_t deviceSerial, uint16_t triggerNumber, hlayout.addLayout(&labellayout); vlayout.addLayout(&hlayout); + inputCheckbox.setChecked(true); + levelCheckbox.setEnabled(false); + labellayout.addWidget(&devicelabel); labellayout.addWidget(&triggerlabel); @@ -59,41 +62,28 @@ uint16_t TriggerWidget::getTriggerNumber() const void TriggerWidget::onInputToggled(bool checked) { - if (checked) { - // Set to input mode - if (eismultiplexer_set_trigger_state(multiplexer.get(), triggerNumber, TRIGGER_INPUT) < 0) { - QMessageBox::warning(this, tr("Trigger Configuration Failed"), - tr("Failed to set trigger %1 on device %2 to input mode").arg(triggerNumber).arg(deviceSerial)); - qWarning() << "Failed to set trigger" << triggerNumber << "on device" << deviceSerial << "to input mode"; - inputCheckbox.blockSignals(true); - inputCheckbox.setChecked(false); - inputCheckbox.blockSignals(false); - } else { - // When input is checked, level should be unchecked and disabled - levelCheckbox.blockSignals(true); - levelCheckbox.setChecked(false); - levelCheckbox.setEnabled(false); - levelCheckbox.blockSignals(false); - } - } else { - // Update the trigger state based on level checkbox - updateTriggerState(); - } + updateTriggerState(); } void TriggerWidget::onLevelToggled(bool checked) { - if (!inputCheckbox.isChecked()) { - // Only update if not in input mode - updateTriggerState(); - } + updateTriggerState(); } void TriggerWidget::updateTriggerState() { - trigger_state_t state = TRIGGER_LOW; - if (!inputCheckbox.isChecked() && levelCheckbox.isChecked()) { - state = TRIGGER_HIGH; + trigger_state_t state; + if(inputCheckbox.isChecked()) + { + levelCheckbox.blockSignals(true); + levelCheckbox.setChecked(false); + levelCheckbox.setEnabled(false); + levelCheckbox.blockSignals(false); + } + else + { + levelCheckbox.setEnabled(true); + state = levelCheckbox.isChecked() ? TRIGGER_HIGH : TRIGGER_LOW; } if (eismultiplexer_set_trigger_state(multiplexer.get(), triggerNumber, state) < 0) {