From 60a097fa896ded78430f89fcd43bb758f88df0fe Mon Sep 17 00:00:00 2001 From: "andrei.danila" Date: Thu, 21 Mar 2024 09:02:39 +0200 Subject: [PATCH] plugins/swiotrefactor: Added faults instrument. I removed the ToolView bindings and I used ToolTemplate instead. Removed .ui files. Cleaned the code. Signed-off-by: andrei.danila --- gui/include/gui/stylehelper.h | 3 + gui/src/stylehelper.cpp | 40 ++ plugins/swiotrefactor/CMakeLists.txt | 4 + .../include/swiotrefactor/faults.h | 16 - .../include/swiotrefactor/faults/faults.h | 74 ++++ .../swiotrefactor/faults/faultsdevice.h | 99 +++++ .../swiotrefactor/faults/faultsgroup.h | 77 ++++ .../include/swiotrefactor/faults/faultspage.h | 54 +++ .../swiotrefactor/faults/faultwidget.h | 85 +++++ plugins/swiotrefactor/src/faults.cpp | 7 - plugins/swiotrefactor/src/faults/faults.cpp | 152 ++++++++ .../swiotrefactor/src/faults/faultsdevice.cpp | 355 ++++++++++++++++++ .../swiotrefactor/src/faults/faultsgroup.cpp | 245 ++++++++++++ .../swiotrefactor/src/faults/faultspage.cpp | 97 +++++ .../swiotrefactor/src/faults/faultwidget.cpp | 131 +++++++ plugins/swiotrefactor/src/swiotrefactor.cpp | 4 +- plugins/swiotrefactor/ui/faultsdevice.ui | 274 -------------- plugins/swiotrefactor/ui/faultsgroup.ui | 87 ----- plugins/swiotrefactor/ui/faultspage.ui | 108 ------ plugins/swiotrefactor/ui/faultwidget.ui | 142 ------- plugins/swiotrefactor/ui/swiotfaults.ui | 39 -- 21 files changed, 1418 insertions(+), 675 deletions(-) delete mode 100644 plugins/swiotrefactor/include/swiotrefactor/faults.h create mode 100644 plugins/swiotrefactor/include/swiotrefactor/faults/faults.h create mode 100644 plugins/swiotrefactor/include/swiotrefactor/faults/faultsdevice.h create mode 100644 plugins/swiotrefactor/include/swiotrefactor/faults/faultsgroup.h create mode 100644 plugins/swiotrefactor/include/swiotrefactor/faults/faultspage.h create mode 100644 plugins/swiotrefactor/include/swiotrefactor/faults/faultwidget.h delete mode 100644 plugins/swiotrefactor/src/faults.cpp create mode 100644 plugins/swiotrefactor/src/faults/faults.cpp create mode 100644 plugins/swiotrefactor/src/faults/faultsdevice.cpp create mode 100644 plugins/swiotrefactor/src/faults/faultsgroup.cpp create mode 100644 plugins/swiotrefactor/src/faults/faultspage.cpp create mode 100644 plugins/swiotrefactor/src/faults/faultwidget.cpp delete mode 100644 plugins/swiotrefactor/ui/faultsdevice.ui delete mode 100644 plugins/swiotrefactor/ui/faultsgroup.ui delete mode 100644 plugins/swiotrefactor/ui/faultspage.ui delete mode 100644 plugins/swiotrefactor/ui/faultwidget.ui delete mode 100644 plugins/swiotrefactor/ui/swiotfaults.ui diff --git a/gui/include/gui/stylehelper.h b/gui/include/gui/stylehelper.h index 27d790027c..a2db4f2328 100644 --- a/gui/include/gui/stylehelper.h +++ b/gui/include/gui/stylehelper.h @@ -103,6 +103,9 @@ class SCOPY_GUI_EXPORT StyleHelper : public QObject static void WarningLabel(QLabel *w, QString objectName = ""); static void NoBackgroundIconButton(QPushButton *w, QIcon icon, QString objectName = ""); static void OrangeWidget(QWidget *w, QString objectName = ""); + static void ActiveStoredLabel(QLabel *w, QString objectName = ""); + static void FaultsFrame(QFrame *w, QString objectName = ""); + static void FaultsExplanation(QWidget *w, QString objectName = ""); private: QMap colorMap; diff --git a/gui/src/stylehelper.cpp b/gui/src/stylehelper.cpp index c4f9e5e4d4..e8fafa155c 100644 --- a/gui/src/stylehelper.cpp +++ b/gui/src/stylehelper.cpp @@ -52,6 +52,7 @@ void StyleHelper::initColorMap() sh->colorMap.insert("ProgressBarBusy", "#F8E71C"); sh->colorMap.insert("WarningText", "#FFC904"); + sh->colorMap.insert("GrayText", "#5c5c5c"); } QString StyleHelper::getColor(QString id) @@ -1276,4 +1277,43 @@ void StyleHelper::OrangeWidget(QWidget *w, QString objectName) w->setStyleSheet(style); } +void StyleHelper::ActiveStoredLabel(QLabel *w, QString objectName) +{ + if(!objectName.isEmpty()) + w->setObjectName(objectName); + QString style = QString(R"css( + QLabel{ + background-color: transparent; width: 40px; height: 14px; border: 2px solid ; border-radius: 8px; border-color: white; + } + QLabel[high=false] { border-color: white; background-color: transparent; } + QLabel[high=true] { border-color: white; background-color: white; } + )css"); + w->setStyleSheet(style); +} + +void StyleHelper::FaultsFrame(QFrame *w, QString objectName) +{ + if(!objectName.isEmpty()) + w->setObjectName(objectName); + QString style = QString(R"css( + QFrame[pressed=true] { background-color: &&elementHighlight&&; border: 1px solid &&elementBackground&&; border-radius:5px; } + )css"); + style.replace("&&elementHighlight&&", StyleHelper::getColor("UIElementHighlight")); + style.replace("&&elementBackground&&", StyleHelper::getColor("UIElementBackground")); + + w->setStyleSheet(style); +} + +void StyleHelper::FaultsExplanation(QWidget *w, QString objectName) +{ + if(!objectName.isEmpty()) + w->setObjectName(objectName); + QString style = QString(R"css( + QWidget[highlighted=true]{color:white;} + QWidget{color:&&defaultColor&&;} + )css"); + style.replace("&&defaultColor&&", StyleHelper::getColor("GrayText")); + w->setStyleSheet(style); +} + #include "moc_stylehelper.cpp" diff --git a/plugins/swiotrefactor/CMakeLists.txt b/plugins/swiotrefactor/CMakeLists.txt index a2445a6696..f709b18ad2 100644 --- a/plugins/swiotrefactor/CMakeLists.txt +++ b/plugins/swiotrefactor/CMakeLists.txt @@ -33,6 +33,8 @@ file( # some of these will eventually be moved to the core/gui directories src/max14906/*.cpp src/max14906/*.cc + src/faults/*.cpp + src/faults/*.cc src/*.cpp src/*.cc model/* @@ -45,6 +47,8 @@ file( include/${SCOPY_MODULE}/*.hpp include/${SCOPY_MODULE}/max14906/*.h include/${SCOPY_MODULE}/max14906/*.hpp + include/${SCOPY_MODULE}/faults/*.h + include/${SCOPY_MODULE}/faults/*.hpp ) file(GLOB UI_LIST ui/*.ui) diff --git a/plugins/swiotrefactor/include/swiotrefactor/faults.h b/plugins/swiotrefactor/include/swiotrefactor/faults.h deleted file mode 100644 index 4d8b99d356..0000000000 --- a/plugins/swiotrefactor/include/swiotrefactor/faults.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef FAULTS_H -#define FAULTS_H - -#include "scopy-swiotrefactor_export.h" -#include - -namespace scopy::swiotrefactor { -class SCOPY_SWIOTREFACTOR_EXPORT Faults : public QWidget -{ - Q_OBJECT -public: - Faults(QWidget *parent = nullptr); - ~Faults(); -}; -} // namespace scopy::swiotrefactor -#endif // FAULTS_H diff --git a/plugins/swiotrefactor/include/swiotrefactor/faults/faults.h b/plugins/swiotrefactor/include/swiotrefactor/faults/faults.h new file mode 100644 index 0000000000..35a1568cd8 --- /dev/null +++ b/plugins/swiotrefactor/include/swiotrefactor/faults/faults.h @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2023 Analog Devices Inc. + * + * This file is part of Scopy + * (see https://www.github.com/analogdevicesinc/scopy). + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef FAULTS_H +#define FAULTS_H + +#include "scopy-swiotrefactor_export.h" +#include "faultspage.h" +#include + +#include +#include + +#include +#include +#include +#include + +namespace scopy::swiotrefactor { +class SCOPY_SWIOTREFACTOR_EXPORT Faults : public QWidget +{ + Q_OBJECT +public: + explicit Faults(QString uri, ToolMenuEntry *tme, QWidget *parent = nullptr); + ~Faults(); + + void pollFaults(); + +Q_SIGNALS: + void backBtnPressed(); + +public Q_SLOTS: + void runButtonClicked(bool toggled); + void singleButtonClicked(); + +private Q_SLOTS: + void onBackBtnPressed(); + +private: + void connectSignalsAndSlots(); + void initTutorialProperties(); + QPushButton *createConfigBtn(QWidget *parent); + + ToolTemplate *m_tool; + RunBtn *m_runBtn; + SingleShotBtn *m_singleBtn; + QPushButton *m_configBtn; + + QTimer *m_timer; + QThread *m_thread; + + FaultsPage *m_faultsPage; + + ToolMenuEntry *m_tme; +}; +} // namespace scopy::swiotrefactor +#endif // FAULTS_H diff --git a/plugins/swiotrefactor/include/swiotrefactor/faults/faultsdevice.h b/plugins/swiotrefactor/include/swiotrefactor/faults/faultsdevice.h new file mode 100644 index 0000000000..6e43858418 --- /dev/null +++ b/plugins/swiotrefactor/include/swiotrefactor/faults/faultsdevice.h @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2023 Analog Devices Inc. + * + * This file is part of Scopy + * (see https://www.github.com/analogdevicesinc/scopy). + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef FAULTSDEVICE_H +#define FAULTSDEVICE_H + +#include "scopy-swiotrefactor_export.h" +#include "faultsgroup.h" +#include +#include +#include +#include + +#include +#include + +namespace scopy::swiotrefactor { +class FaultsGroup; + +class SCOPY_SWIOTREFACTOR_EXPORT FaultsDevice : public QWidget +{ + Q_OBJECT +public: + explicit FaultsDevice(const QString &name, QString path, QString uri, QVector ®isters, + QWidget *parent = nullptr); + ~FaultsDevice(); + + void update(); + + void readRegister(); +public Q_SLOTS: + void resetStored(); + void updateExplanations(); + void updateExplanation(int index); + void onFaultNumericUpdated(); + void onFaultRegisterRead(int iReg, uint32_t value); + +Q_SIGNALS: + void specialFaultsUpdated(int index, QString channelFunction); + void faultNumericUpdated(); + void faultRegisterRead(int iReg, uint32_t value); + +private Q_SLOTS: + void updateMinimumHeight(); + void deviceConfigCmdFinished(scopy::Command *cmd); + void functionConfigCmdFinished(scopy::Command *cmd); + +private: + void establishConnection(QString name); + void initSpecialFaults(); + void initTutorialProperties(); + void connectSignalsAndSlots(); + QWidget *createTopWidget(QWidget *parent); + QWidget *createExplanationSection(QWidget *parent); + + QLineEdit *m_registerNoLineEdit; + QPushButton *m_resetBtn; + QPushButton *m_clearBtn; + QWidget *m_faultsExplanation; + + QString m_uri; + CommandQueue *m_cmdQueue; + + FaultsGroup *m_faultsGroup; + QVector m_faultExplanationWidgets; + + QString m_name; + + struct iio_device *m_device; + struct iio_device *m_swiot; + struct iio_context *m_context; + + uint32_t m_faultNumeric = 0; + QVector m_registers; + QVector m_registerValues; + QVector m_deviceConfigCmds; + QVector m_functionConfigCmds; +}; + +} // namespace scopy::swiotrefactor + +#endif // FAULTSDEVICE_H diff --git a/plugins/swiotrefactor/include/swiotrefactor/faults/faultsgroup.h b/plugins/swiotrefactor/include/swiotrefactor/faults/faultsgroup.h new file mode 100644 index 0000000000..f3bba1d936 --- /dev/null +++ b/plugins/swiotrefactor/include/swiotrefactor/faults/faultsgroup.h @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2023 Analog Devices Inc. + * + * This file is part of Scopy + * (see https://www.github.com/analogdevicesinc/scopy). + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef FAULTSGROUP_H +#define FAULTSGROUP_H + +#include "scopy-swiotrefactor_export.h" +#include "faultwidget.h" +#include +#include +#include + +namespace scopy::swiotrefactor { +class SCOPY_SWIOTREFACTOR_EXPORT FaultsGroup : public QWidget +{ + Q_OBJECT +public: + explicit FaultsGroup(QString name, const QString &path, QWidget *parent = nullptr); + ~FaultsGroup() override; + + const QVector &getFaults() const; + + const QString &getName() const; + void setName(const QString &name); + + void clearSelection(); + void update(uint32_t faults_numeric); + QStringList getExplanations(); + QString getExplanation(unsigned int id); + std::set getSelectedIndexes(); + std::set getActiveIndexes(); + +Q_SIGNALS: + void selectionUpdated(); + void minimumSizeChanged(); + void specialFaultsUpdated(unsigned int index, QString channelFunction); + void specialFaultExplanationChanged(unsigned int, QString); + +private Q_SLOTS: + void layoutUpdate(); + void onFaultSelected(unsigned int id); + +protected: + QWidget *buildActiveStoredWidget(); + QJsonArray *getJsonArray(const QString &path); + +private: + void createFaultWidgets(const QString &path); + + int m_maxFaults; + QString m_name; + QVector m_faults; + std::set m_currentlySelected; + std::set m_actives; + FlexGridLayout *m_customColGrid; + QWidget *m_activeStoredWidget; +}; +} // namespace scopy::swiotrefactor + +#endif // FAULTSGROUP_H diff --git a/plugins/swiotrefactor/include/swiotrefactor/faults/faultspage.h b/plugins/swiotrefactor/include/swiotrefactor/faults/faultspage.h new file mode 100644 index 0000000000..9c84832297 --- /dev/null +++ b/plugins/swiotrefactor/include/swiotrefactor/faults/faultspage.h @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2023 Analog Devices Inc. + * + * This file is part of Scopy + * (see https://www.github.com/analogdevicesinc/scopy). + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef FAULTSPAGE_H +#define FAULTSPAGE_H + +#include "scopy-swiotrefactor_export.h" +#include "faultsdevice.h" + +#include +#include +#include +#include + +namespace scopy::swiotrefactor { +class FaultsDevice; + +class SCOPY_SWIOTREFACTOR_EXPORT FaultsPage : public QWidget +{ + Q_OBJECT +public: + explicit FaultsPage(QString uri, QWidget *parent = nullptr); + ~FaultsPage(); + + void update(); + +private: + QString m_uri; + struct iio_context *m_context; + + FaultsDevice *m_ad74413rFaultsDevice = nullptr; + FaultsDevice *m_max14906FaultsDevice = nullptr; + + void setupDevices(); +}; +} // namespace scopy::swiotrefactor +#endif // FAULTSPAGE_H diff --git a/plugins/swiotrefactor/include/swiotrefactor/faults/faultwidget.h b/plugins/swiotrefactor/include/swiotrefactor/faults/faultwidget.h new file mode 100644 index 0000000000..5eb99f2549 --- /dev/null +++ b/plugins/swiotrefactor/include/swiotrefactor/faults/faultwidget.h @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2023 Analog Devices Inc. + * + * This file is part of Scopy + * (see https://www.github.com/analogdevicesinc/scopy). + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef SCOPY_FAULTWIDGET_H +#define SCOPY_FAULTWIDGET_H + +#include "scopy-swiotrefactor_export.h" + +#include +#include +#include +#include + +namespace scopy::swiotrefactor { +class SCOPY_SWIOTREFACTOR_EXPORT FaultWidget : public QFrame +{ + Q_OBJECT + +public: + explicit FaultWidget(unsigned int id, QString name, QString faultExplanation, QWidget *parent = nullptr); + ~FaultWidget() override; + + unsigned int getId() const; + void setId(unsigned int id); + + bool isStored() const; + void setStored(bool stored); + + bool isActive() const; + void setActive(bool active); + + const QString &getName() const; + void setName(const QString &name); + + const QString &getFaultExplanation() const; + void setFaultExplanation(const QString &faultExplanation); + + void setFaultExplanationOptions(QJsonObject options); + + bool isPressed() const; + void setPressed(bool pressed); + +public Q_SLOTS: + void specialFaultUpdated(int index, QString channelFunction); + +Q_SIGNALS: + void faultSelected(unsigned int id); + void specialFaultExplanationChanged(unsigned int, QString); + +protected: + bool eventFilter(QObject *object, QEvent *event) override; + +private: + QLabel *m_activeLabel; + QLabel *m_storedLabel; + QLabel *m_titleLabel; + + bool m_stored = false; + bool m_active = false; + bool m_pressed = false; + unsigned int m_id{}; + QString m_name; + QString m_faultExplanation; + QJsonObject m_faultExplanationOptions; +}; +} // namespace scopy::swiotrefactor + +#endif // SCOPY_FAULTWIDGET_H diff --git a/plugins/swiotrefactor/src/faults.cpp b/plugins/swiotrefactor/src/faults.cpp deleted file mode 100644 index 9061a958ba..0000000000 --- a/plugins/swiotrefactor/src/faults.cpp +++ /dev/null @@ -1,7 +0,0 @@ -#include "faults.h" - -using namespace scopy::swiotrefactor; - -Faults::Faults(QWidget *parent) {} - -Faults::~Faults() {} diff --git a/plugins/swiotrefactor/src/faults/faults.cpp b/plugins/swiotrefactor/src/faults/faults.cpp new file mode 100644 index 0000000000..494e226fc1 --- /dev/null +++ b/plugins/swiotrefactor/src/faults/faults.cpp @@ -0,0 +1,152 @@ +/* + * Copyright (c) 2023 Analog Devices Inc. + * + * This file is part of Scopy + * (see https://www.github.com/analogdevicesinc/scopy). + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "faults/faults.h" + +#include "swiot_logging_categories.h" + +#include +#include +#include +#include +#include + +using namespace scopy::swiotrefactor; + +#define POLLING_INTERVAL 1000 + +Faults::Faults(QString uri, ToolMenuEntry *tme, QWidget *parent) + : QWidget(parent) + , m_timer(new QTimer()) + , m_thread(new QThread(this)) + , m_tme(tme) +{ + qInfo(CAT_SWIOT_FAULTS) << "Initialising SWIOT faults page."; + QHBoxLayout *layout = new QHBoxLayout(this); + layout->setContentsMargins(0, 0, 0, 0); + setLayout(layout); + + // tool template configuration + m_tool = new ToolTemplate(this); + m_tool->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); + m_tool->topContainerMenuControl()->setVisible(false); + m_tool->centralContainer()->setVisible(true); + m_tool->topContainer()->setVisible(true); + + layout->addWidget(m_tool); + + m_configBtn = createConfigBtn(this); + m_runBtn = new RunBtn(this); + m_singleBtn = new SingleShotBtn(this); + + m_tool->addWidgetToTopContainerHelper(m_configBtn, TTA_LEFT); + m_tool->addWidgetToTopContainerHelper(m_runBtn, TTA_RIGHT); + m_tool->addWidgetToTopContainerHelper(m_singleBtn, TTA_RIGHT); + + m_faultsPage = new FaultsPage(uri, this); + m_tool->addWidgetToCentralContainerHelper(m_faultsPage); + + connectSignalsAndSlots(); + initTutorialProperties(); +} + +Faults::~Faults() +{ + if(m_thread) { + m_thread->quit(); + m_thread->wait(); + delete m_thread; + } +} + +void Faults::connectSignalsAndSlots() +{ + QObject::connect(m_runBtn, &QPushButton::toggled, this, &Faults::runButtonClicked); + QObject::connect(m_singleBtn, &QPushButton::clicked, this, &Faults::singleButtonClicked); + QObject::connect(m_configBtn, &QPushButton::clicked, this, &Faults::onBackBtnPressed); + + QObject::connect(m_timer, &QTimer::timeout, this, &Faults::pollFaults); + QObject::connect(m_thread, &QThread::started, this, [&]() { + qDebug(CAT_SWIOT_FAULTS) << "Faults reader thread started"; + m_timer->start(POLLING_INTERVAL); + }); + + QObject::connect(m_tme, &ToolMenuEntry::runToggled, m_runBtn, &QPushButton::setChecked); +} + +void Faults::onBackBtnPressed() +{ + + m_thread->quit(); + m_thread->wait(); + Q_EMIT backBtnPressed(); +} + +void Faults::runButtonClicked(bool toggled) +{ + m_singleBtn->setChecked(false); + if(toggled) { + m_thread->start(); + if(!m_tme->running()) { + m_tme->setRunning(true); + } + } else { + if(m_thread->isRunning()) { + m_thread->quit(); + } + if(m_tme->running()) { + m_tme->setRunning(false); + } + m_timer->stop(); + } +} + +void Faults::singleButtonClicked() +{ + qDebug(CAT_SWIOT_FAULTS) << "Single button clicked"; + m_runBtn->setChecked(false); + m_timer->stop(); + pollFaults(); + m_singleBtn->setChecked(false); +} + +void Faults::pollFaults() +{ + qDebug(CAT_SWIOT_FAULTS) << "Polling faults..."; + m_faultsPage->update(); +} + +QPushButton *Faults::createConfigBtn(QWidget *parent) +{ + QPushButton *configBtn = new QPushButton(parent); + StyleHelper::BlueGrayButton(configBtn, "back_btn"); + configBtn->setFixedWidth(128); + configBtn->setCheckable(false); + configBtn->setText("Config"); + return configBtn; +} + +void Faults::initTutorialProperties() +{ + // initialize components that might be used for the Faults tutorial + m_singleBtn->setProperty("tutorial_name", "SINGLE_BUTTON"); + m_runBtn->setProperty("tutorial_name", "RUN_BUTTON"); + m_configBtn->setProperty("tutorial_name", "CONFIG_BUTTON"); +} diff --git a/plugins/swiotrefactor/src/faults/faultsdevice.cpp b/plugins/swiotrefactor/src/faults/faultsdevice.cpp new file mode 100644 index 0000000000..3f2de1a753 --- /dev/null +++ b/plugins/swiotrefactor/src/faults/faultsdevice.cpp @@ -0,0 +1,355 @@ +/* + * Copyright (c) 2023 Analog Devices Inc. + * + * This file is part of Scopy + * (see https://www.github.com/analogdevicesinc/scopy). + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "faults/faultsdevice.h" +#include "faults/faultsgroup.h" +#include "swiot_logging_categories.h" + +#include +#include +#include +#include + +#include +#include +#include +#include + +#define FAULT_CHANNEL_NAME "voltage" +#define SWIOT_NB_CHANNELS 4 + +using namespace scopy::swiotrefactor; + +FaultsDevice::FaultsDevice(const QString &name, QString path, QString uri, QVector ®isters, + QWidget *parent) + : QWidget(parent) + , m_uri(uri) + , m_name(name.toUpper()) + , m_registers(registers) +{ + QVBoxLayout *layout = new QVBoxLayout(this); + setLayout(layout); + + establishConnection(name); + initSpecialFaults(); + + if(m_device == nullptr) { + qCritical(CAT_SWIOT_FAULTS) << "No device was found"; + } + m_faultsGroup = new FaultsGroup(name, path, this); + + QWidget *topWidget = createTopWidget(this); + QWidget *faultsWidget = new QWidget(this); + faultsWidget->setLayout(new QHBoxLayout(faultsWidget)); + faultsWidget->layout()->setContentsMargins(0, 0, 0, 0); + faultsWidget->layout()->addWidget(m_faultsGroup); + QWidget *explanationSection = createExplanationSection(this); + + layout->addWidget(topWidget); + layout->addWidget(faultsWidget); + layout->addWidget(explanationSection); + layout->addItem(new QSpacerItem(0, 0, QSizePolicy::Minimum, QSizePolicy::Expanding)); + + // initialize components that might be used for the Faults tutorial + if(m_name == "AD74413R") { + initTutorialProperties(); + } + + connect(this, &FaultsDevice::specialFaultsUpdated, m_faultsGroup, &FaultsGroup::specialFaultsUpdated); + connect(m_faultsGroup, &FaultsGroup::specialFaultExplanationChanged, this, &FaultsDevice::updateExplanation); + connect(this, &FaultsDevice::faultNumericUpdated, this, &FaultsDevice::onFaultNumericUpdated, + Qt::QueuedConnection); + connect(this, &FaultsDevice::faultRegisterRead, this, &FaultsDevice::onFaultRegisterRead, Qt::QueuedConnection); + + connectSignalsAndSlots(); + + m_faultsExplanation->ensurePolished(); + onFaultNumericUpdated(); +} + +FaultsDevice::~FaultsDevice() { ConnectionProvider::close(m_uri); } + +void FaultsDevice::resetStored() +{ + for(auto fault : m_faultsGroup->getFaults()) { + fault->setStored(false); + } + updateExplanations(); +} + +void FaultsDevice::update() { readRegister(); } + +void FaultsDevice::updateExplanation(int index) +{ + QLabel *lbl = dynamic_cast(m_faultExplanationWidgets[index]); + if(lbl) { + QString updatedText = m_faultsGroup->getExplanation(index); + lbl->setText(updatedText); + } + m_faultsExplanation->ensurePolished(); +} + +void FaultsDevice::updateExplanations() +{ + std::set selected = m_faultsGroup->getSelectedIndexes(); + std::set actives = m_faultsGroup->getActiveIndexes(); + if(selected.empty()) { + for(int i = 0; i < m_faultExplanationWidgets.size(); ++i) { + m_faultExplanationWidgets[i]->show(); + + if(actives.contains(i)) { + setDynamicProperty(m_faultExplanationWidgets[i], "highlighted", true); + } else { + setDynamicProperty(m_faultExplanationWidgets[i], "highlighted", false); + } + } + } else { + for(int i = 0; i < m_faultExplanationWidgets.size(); ++i) { + if(selected.contains(i)) { + m_faultExplanationWidgets[i]->show(); + } else { + m_faultExplanationWidgets[i]->hide(); + } + + if(actives.contains(i)) { + setDynamicProperty(m_faultExplanationWidgets[i], "highlighted", true); + } else { + setDynamicProperty(m_faultExplanationWidgets[i], "highlighted", false); + } + } + } + + m_faultsExplanation->ensurePolished(); +} + +void FaultsDevice::updateMinimumHeight() +{ + ensurePolished(); + m_faultsExplanation->ensurePolished(); + m_faultsGroup->ensurePolished(); +} + +void FaultsDevice::connectSignalsAndSlots() +{ + connect(m_clearBtn, &QPushButton::clicked, m_faultsGroup, &FaultsGroup::clearSelection); + connect(m_resetBtn, &QPushButton::clicked, this, &FaultsDevice::resetStored); + connect(m_faultsGroup, &FaultsGroup::selectionUpdated, this, &FaultsDevice::updateExplanations); + connect(m_faultsGroup, &FaultsGroup::minimumSizeChanged, this, &FaultsDevice::updateMinimumHeight); +} + +void FaultsDevice::onFaultNumericUpdated() +{ + m_registerNoLineEdit->setText(QString("0x%1").arg(m_faultNumeric, 8, 16, QLatin1Char('0'))); + m_faultsGroup->update(m_faultNumeric); + updateExplanations(); +} + +void FaultsDevice::onFaultRegisterRead(int iReg, uint32_t value) +{ + m_registerValues.insert(iReg, value); + if(m_registerValues.size() == m_registers.size()) { + uint32_t faultRegisterValue = 0; + for(int i = 0; i < m_registerValues.size(); i++) { + faultRegisterValue |= (m_registerValues.at(i) << (i * 8)); + } + m_faultNumeric = faultRegisterValue; + Q_EMIT faultNumericUpdated(); + m_registerValues.clear(); + } +} + +void FaultsDevice::readRegister() +{ + for(int i = 0; i < m_registers.size(); i++) { + uint32_t reg_val; + uint32_t address = m_registers.at(i); + Command *readRegisterCommand = new IioRegisterRead(m_device, address, nullptr); + connect( + readRegisterCommand, &scopy::Command::finished, this, + [=, this](scopy::Command *cmd) { + IioRegisterRead *tcmd = dynamic_cast(cmd); + if(!tcmd) { + qCritical(CAT_SWIOT_FAULTS) << m_name << "faults register could not be read."; + return; + } + uint32_t reg = tcmd->getResult(); + + if(tcmd->getReturnCode() < 0) { + qCritical(CAT_SWIOT_FAULTS) << m_name << "faults register could not be read."; + } else { + qDebug(CAT_SWIOT_FAULTS) << m_name << "faults register read val:" << reg; + try { + Q_EMIT faultRegisterRead(i, reg); + } catch(std::invalid_argument &exception) { + qCritical(CAT_SWIOT_FAULTS) + << m_name << "faults register could not be read."; + } + } + }, + Qt::QueuedConnection); + m_cmdQueue->enqueue(readRegisterCommand); + } +} + +void FaultsDevice::functionConfigCmdFinished(scopy::Command *cmd) +{ + IioDeviceAttributeRead *tcmd = dynamic_cast(cmd); + if(!tcmd) { + qCritical(CAT_SWIOT_FAULTS) << "Error: cannot read swiot special fault property"; + return; + } + + if(tcmd->getReturnCode() < 0) { + qCritical(CAT_SWIOT_FAULTS) << "Error: cannot read swiot special fault property"; + } else { + int cmdIndex = m_functionConfigCmds.indexOf(cmd); + char *readFunction = tcmd->getResult(); + Q_EMIT specialFaultsUpdated(cmdIndex, QString(readFunction)); + disconnect(cmd, &scopy::Command::finished, this, &FaultsDevice::deviceConfigCmdFinished); + } +} + +void FaultsDevice::deviceConfigCmdFinished(scopy::Command *cmd) +{ + IioDeviceAttributeRead *tcmd = dynamic_cast(cmd); + if(!tcmd) { + qCritical(CAT_SWIOT_FAULTS) << "Error: cannot read swiot special fault config property"; + return; + } + + if(tcmd->getReturnCode() < 0) { + qCritical(CAT_SWIOT_FAULTS) << "Error: cannot read swiot special fault config property"; + } else { + char *readDevice = tcmd->getResult(); + int cmdIndex = m_deviceConfigCmds.indexOf(cmd); + if(std::string(readDevice) == "ad74413r") { + QString function = "ch" + QString::number(cmdIndex) + "_function"; + + m_functionConfigCmds[cmdIndex] = + new IioDeviceAttributeRead(m_swiot, function.toStdString().c_str(), m_cmdQueue); + connect(m_functionConfigCmds.at(cmdIndex), &scopy::Command::finished, this, + &FaultsDevice::functionConfigCmdFinished, Qt::QueuedConnection); + disconnect(cmd, &scopy::Command::finished, this, &FaultsDevice::deviceConfigCmdFinished); + m_cmdQueue->enqueue(m_functionConfigCmds.at(cmdIndex)); + } + } +} + +void FaultsDevice::establishConnection(QString name) +{ + Connection *conn = ConnectionProvider::open(m_uri); + m_context = conn->context(); + m_cmdQueue = conn->commandQueue(); + m_device = iio_context_find_device(m_context, name.toStdString().c_str()); + m_swiot = iio_context_find_device(m_context, "swiot"); +} + +void FaultsDevice::initSpecialFaults() +{ + if(!m_name.contains("MAX")) { + for(int i = 0; i < SWIOT_NB_CHANNELS; ++i) { + std::string device = "ch" + std::to_string(i) + "_device"; + m_deviceConfigCmds.push_back(new IioDeviceAttributeRead(m_swiot, device.c_str(), m_cmdQueue)); + connect(m_deviceConfigCmds.at(i), &scopy::Command::finished, this, + &FaultsDevice::deviceConfigCmdFinished, Qt::QueuedConnection); + m_functionConfigCmds.push_back(nullptr); + m_cmdQueue->enqueue(m_deviceConfigCmds.at(i)); + } + } +} + +QWidget *FaultsDevice::createTopWidget(QWidget *parent) +{ + QWidget *w = new QWidget(parent); + w->setMinimumSize(700, 60); + QHBoxLayout *layout = new QHBoxLayout(w); + layout->setContentsMargins(0, 0, 0, 0); + + QLabel *deviceNameLabel = new QLabel(w); + StyleHelper::MenuLargeLabel(deviceNameLabel); + deviceNameLabel->setText(m_name); + + m_registerNoLineEdit = new QLineEdit(w); + StyleHelper::MenuLineEdit(m_registerNoLineEdit); + m_registerNoLineEdit->setFixedWidth(140); + m_registerNoLineEdit->setPlaceholderText("0x0"); + m_registerNoLineEdit->setFocusPolicy(Qt::NoFocus); + m_registerNoLineEdit->setReadOnly(true); + + m_resetBtn = new QPushButton(w); + StyleHelper::BlueButton(m_resetBtn); + m_resetBtn->setFixedWidth(110); + m_resetBtn->setCheckable(false); + m_resetBtn->setText("RESET\nSTORED"); + + m_clearBtn = new QPushButton(w); + StyleHelper::BlueButton(m_clearBtn); + m_clearBtn->setFixedWidth(110); + m_clearBtn->setCheckable(false); + m_clearBtn->setText("CLEAR\nSELECTION"); + + layout->addWidget(deviceNameLabel); + layout->addWidget(m_registerNoLineEdit); + layout->addWidget(m_resetBtn); + layout->addWidget(m_clearBtn); + layout->addItem(new QSpacerItem(40, 10, QSizePolicy::Expanding, QSizePolicy::Minimum)); + + return w; +} + +QWidget *FaultsDevice::createExplanationSection(QWidget *parent) +{ + m_faultsExplanation = new QWidget(this); + m_faultsExplanation->setLayout(new QVBoxLayout(m_faultsExplanation)); + m_faultsExplanation->layout()->setContentsMargins(0, 0, 0, 0); + m_faultsExplanation->layout()->setSpacing(0); + m_faultsExplanation->layout()->setSizeConstraint(QLayout::SetMinimumSize); + + QStringList l = m_faultsGroup->getExplanations(); + for(const auto &item : l) { + auto widget = new QLabel(item, m_faultsExplanation); + widget->setTextFormat(Qt::PlainText); + widget->setWordWrap(true); + StyleHelper::FaultsExplanation(widget); + + m_faultExplanationWidgets.push_back(widget); + m_faultsExplanation->layout()->addWidget(widget); + } + m_faultsExplanation->ensurePolished(); + + MenuCollapseSection *explanationSection = + new MenuCollapseSection("Faults explanation", MenuCollapseSection::MHCW_ONOFF, this); + explanationSection->setLayout(new QVBoxLayout()); + explanationSection->contentLayout()->setSpacing(10); + explanationSection->contentLayout()->setMargin(0); + + explanationSection->contentLayout()->addWidget(m_faultsExplanation); + + return explanationSection; +} + +void FaultsDevice::initTutorialProperties() +{ + m_registerNoLineEdit->setProperty("tutorial_name", "AD74413R_NUMERIC"); + m_resetBtn->setProperty("tutorial_name", "AD74413R_RESET_STORED"); + m_clearBtn->setProperty("tutorial_name", "AD74413R_CLEAR_SELECTION"); + m_faultsGroup->setProperty("tutorial_name", "AD74413R_FAULTS_GROUP"); + m_faultsExplanation->setProperty("tutorial_name", "AD74413R_EXPLANATIONS"); +} diff --git a/plugins/swiotrefactor/src/faults/faultsgroup.cpp b/plugins/swiotrefactor/src/faults/faultsgroup.cpp new file mode 100644 index 0000000000..06def5c7e6 --- /dev/null +++ b/plugins/swiotrefactor/src/faults/faultsgroup.cpp @@ -0,0 +1,245 @@ +/* + * Copyright (c) 2023 Analog Devices Inc. + * + * This file is part of Scopy + * (see https://www.github.com/analogdevicesinc/scopy). + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "faults/faultsgroup.h" +#include "swiot_logging_categories.h" + +#include +#include +#include +#include +#include +#include + +#include + +using namespace scopy::swiotrefactor; + +#define MAX_COLS_IN_GRID 100 + +FaultsGroup::FaultsGroup(QString name, const QString &path, QWidget *parent) + : QWidget(parent) + , m_name(std::move(name)) +{ + setMinimumSize(700, 90); + QHBoxLayout *layout = new QHBoxLayout(this); + layout->setContentsMargins(0, 0, 0, 0); + setLayout(layout); + + m_activeStoredWidget = new QWidget(this); + m_activeStoredWidget->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); + QVBoxLayout *activeStoredLay = new QVBoxLayout(m_activeStoredWidget); + activeStoredLay->setContentsMargins(0, 0, 0, 0); + activeStoredLay->setSpacing(0); + activeStoredLay->setAlignment(Qt::AlignCenter); + m_activeStoredWidget->setLayout(activeStoredLay); + + m_customColGrid = new FlexGridLayout(MAX_COLS_IN_GRID, this); + layout->addWidget(m_activeStoredWidget); + layout->addWidget(m_customColGrid); + + connect(m_customColGrid, &FlexGridLayout::reqestLayoutUpdate, this, &FaultsGroup::layoutUpdate); + + createFaultWidgets(path); + + m_customColGrid->toggleAll(true); + m_customColGrid->itemSizeChanged(); +} + +FaultsGroup::~FaultsGroup() {} + +const QVector &FaultsGroup::getFaults() const { return m_faults; } + +const QString &FaultsGroup::getName() const { return m_name; } + +void FaultsGroup::setName(const QString &name_) { FaultsGroup::m_name = name_; } + +void FaultsGroup::clearSelection() +{ + for(unsigned int i : m_currentlySelected) { + m_faults[(int)(i)]->setPressed(false); + } + + m_currentlySelected.clear(); + Q_EMIT selectionUpdated(); +} + +void FaultsGroup::update(uint32_t faultsNumeric) +{ + for(int i = 0; i < m_faults.size(); i++) { + bool bit = (bool)((faultsNumeric >> i) & 0b1); + if(m_faults.at(i)->isActive() && bit) { // if we get 2 active signals, we set the stored to 1 + m_faults.at(i)->setStored(true); + } + m_faults.at(i)->setActive(bit); + + if(bit) { + m_actives.insert(i); + } else { + m_actives.erase(i); + } + } +} + +QStringList FaultsGroup::getExplanations() +{ + QStringList res; + for(auto fault : qAsConst(m_faults)) { + res += getExplanation(fault->getId()); + } + + return res; +} + +QString FaultsGroup::getExplanation(unsigned int id) +{ + QString res = ""; + auto fault = m_faults.at(id); + if(fault) { + res += QString("Bit%1 (%2): %3") + .arg(QString::number(fault->getId()), fault->getName(), fault->getFaultExplanation()); + } + + return res; +} + +QWidget *FaultsGroup::buildActiveStoredWidget() +{ + auto widget = new QWidget(this); + auto storedLabel = new QLabel(this); + storedLabel->setText("Stored"); + storedLabel->setContentsMargins(0, 0, 0, 0); + storedLabel->setAlignment(Qt::AlignLeft); + StyleHelper::MenuMediumLabel(storedLabel); + auto activeLabel = new QLabel(this); + activeLabel->setText("Active"); + activeLabel->setContentsMargins(0, 0, 0, 0); + activeLabel->setAlignment(Qt::AlignLeft); + StyleHelper::MenuMediumLabel(activeLabel); + auto spacer = new QSpacerItem(0, 30, QSizePolicy::Fixed, QSizePolicy::Fixed); + + widget->setLayout(new QVBoxLayout(widget)); + widget->layout()->addWidget(storedLabel); + widget->layout()->addWidget(activeLabel); + widget->layout()->addItem(spacer); + widget->layout()->setContentsMargins(0, 9, 0, 9); + + return widget; +} + +QJsonArray *FaultsGroup::getJsonArray(const QString &path) +{ + QString contents; + QFile file; + file.setFileName(path); + file.open(QIODevice::ReadOnly | QIODevice::Text); + if(!file.isOpen()) { + qCritical(CAT_SWIOT_FAULTS) << "File could not be opened (read): " << path; + } else { + qDebug(CAT_SWIOT_FAULTS) << "File opened (read): " << path; + } + contents = file.readAll(); + file.close(); + + QJsonParseError parseError{}; + QJsonDocument document = QJsonDocument::fromJson(contents.toUtf8(), &parseError); + if(document.isNull()) { + qCritical(CAT_SWIOT_FAULTS) << "Invalid json: " << parseError.errorString(); + } + + QJsonObject documentObject = document.object(); + QJsonValue deviceValue = documentObject.value(m_name); + if(deviceValue == QJsonValue::Undefined) { + qCritical(CAT_SWIOT_FAULTS) << "Invalid json: Could not extract value " << m_name; + } + + QJsonObject deviceObject = deviceValue.toObject(); + QJsonValue maxFaultsValue = deviceObject["max_faults"]; // max number of faults + m_maxFaults = maxFaultsValue.toInt(-1); + + QJsonValue faultsJson = deviceObject["faults"]; + + auto *array = new QJsonArray(); + *array = faultsJson.toArray(); + + return array; +} + +std::set FaultsGroup::getSelectedIndexes() { return m_currentlySelected; } + +std::set FaultsGroup::getActiveIndexes() { return m_actives; } + +void FaultsGroup::layoutUpdate() +{ + if(m_activeStoredWidget->layout()->count() != m_customColGrid->rows()) { + while(m_activeStoredWidget->layout()->count() < m_customColGrid->rows()) { + m_activeStoredWidget->layout()->addWidget(buildActiveStoredWidget()); + } + while(m_activeStoredWidget->layout()->count() > m_customColGrid->rows()) { + QWidget *widgetToDelete = m_activeStoredWidget->layout() + ->itemAt(m_activeStoredWidget->layout()->count() - 1) + ->widget(); + m_activeStoredWidget->layout()->removeWidget(widgetToDelete); + delete widgetToDelete; + } + } + m_activeStoredWidget->setMaximumHeight(m_customColGrid->sizeHint().height()); + m_activeStoredWidget->updateGeometry(); + setMaximumHeight(sizeHint().height() + 1); + + Q_EMIT minimumSizeChanged(); +} + +void FaultsGroup::onFaultSelected(unsigned int id) +{ + bool added = m_currentlySelected.insert(id).second; + if(!added) { + m_currentlySelected.erase(id); + m_faults.at((int)(id))->setPressed(false); + } + Q_EMIT selectionUpdated(); +} + +void FaultsGroup::createFaultWidgets(const QString &path) +{ + QJsonArray *faultsObj = getJsonArray(path); + m_maxFaults = faultsObj->size(); + + for(int i = 0; i < m_maxFaults; ++i) { + QJsonObject faultObject = faultsObj->at(i).toObject(); + QString faultName = faultObject.value("name").toString(); + QString faultDescription = faultObject.value("description").toString(); + auto faultWidget = new FaultWidget(i, faultName, faultDescription, this); + + if(faultObject.contains("condition")) { + QJsonObject condition = faultObject["condition"].toObject(); + faultWidget->setFaultExplanationOptions(condition); + connect(this, &FaultsGroup::specialFaultsUpdated, faultWidget, + &FaultWidget::specialFaultUpdated); + connect(faultWidget, &FaultWidget::specialFaultExplanationChanged, this, + &FaultsGroup::specialFaultExplanationChanged); + } + connect(faultWidget, &FaultWidget::faultSelected, this, &FaultsGroup::onFaultSelected); + + m_faults.push_back(faultWidget); + m_customColGrid->addQWidgetToList(faultWidget); + } + delete faultsObj; +} diff --git a/plugins/swiotrefactor/src/faults/faultspage.cpp b/plugins/swiotrefactor/src/faults/faultspage.cpp new file mode 100644 index 0000000000..2a4b7f695c --- /dev/null +++ b/plugins/swiotrefactor/src/faults/faultspage.cpp @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2023 Analog Devices Inc. + * + * This file is part of Scopy + * (see https://www.github.com/analogdevicesinc/scopy). + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "faults/faultspage.h" +#include "swiot_logging_categories.h" +#include +#include +#include + +using namespace scopy::swiotrefactor; + +FaultsPage::FaultsPage(QString uri, QWidget *parent) + : QWidget(parent) + , m_uri(uri) +{ + Connection *conn = ConnectionProvider::open(m_uri); + m_context = conn->context(); + setupDevices(); + + StyleHelper::BackgroundWidget(this); + QVBoxLayout *layout = new QVBoxLayout(this); + layout->setContentsMargins(0, 0, 0, 0); + setLayout(layout); + + QScrollArea *scrollArea = new QScrollArea(this); + QWidget *scrollWidget = new QWidget(scrollArea); + QVBoxLayout *layScroll = new QVBoxLayout(scrollWidget); + layScroll->setMargin(0); + layScroll->setContentsMargins(0, 0, 0, 0); + scrollWidget->setLayout(layScroll); + + scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + scrollArea->setWidgetResizable(true); + scrollArea->setWidget(scrollWidget); + + // needed for subsection separator resize + m_ad74413rFaultsDevice->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); + m_max14906FaultsDevice->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); + + layScroll->addWidget(m_ad74413rFaultsDevice); + layScroll->addWidget(m_max14906FaultsDevice); + layScroll->addItem(new QSpacerItem(0, 0, QSizePolicy::Preferred, QSizePolicy::Expanding)); + + layout->addWidget(scrollArea); +} + +FaultsPage::~FaultsPage() { ConnectionProvider::close(m_uri); } + +void FaultsPage::update() +{ + m_ad74413rFaultsDevice->update(); + m_max14906FaultsDevice->update(); +} + +void FaultsPage::setupDevices() +{ + struct iio_device *ad74413r = iio_context_find_device(m_context, "ad74413r"); + struct iio_device *max14906 = iio_context_find_device(m_context, "max14906"); + struct iio_device *swiot = iio_context_find_device(m_context, "swiot"); + + if(swiot) { + if(ad74413r) { + QVector faultRegistersAddr = {0x02e}; + m_ad74413rFaultsDevice = new FaultsDevice("ad74413r", ":/swiot/swiot_faults.json", m_uri, + faultRegistersAddr, this); + } else { + qCritical(CAT_SWIOT_FAULTS) << "Error: did not find ad74413r device."; + } + + if(max14906) { + QVector faultRegistersAddr = {0x04, 0x05, 0x06, 0x07}; + m_max14906FaultsDevice = new FaultsDevice("max14906", ":/swiot/swiot_faults.json", m_uri, + faultRegistersAddr, this); + } else { + qCritical(CAT_SWIOT_FAULTS) << "Error: did not find max14906 device."; + } + } else { + qCritical(CAT_SWIOT_FAULTS) << "Error: did not find swiot device."; + } +} diff --git a/plugins/swiotrefactor/src/faults/faultwidget.cpp b/plugins/swiotrefactor/src/faults/faultwidget.cpp new file mode 100644 index 0000000000..0f135d0d14 --- /dev/null +++ b/plugins/swiotrefactor/src/faults/faultwidget.cpp @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2023 Analog Devices Inc. + * + * This file is part of Scopy + * (see https://www.github.com/analogdevicesinc/scopy). + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "faults/faultwidget.h" + +#include +#include +#include + +using namespace scopy::swiotrefactor; + +FaultWidget::FaultWidget(unsigned int id, QString name, QString faultExplanation, QWidget *parent) + : QFrame(parent) + , m_id(id) + , m_name(std::move(name)) + , m_faultExplanation(std::move(faultExplanation)) +{ + setFrameShape(StyledPanel); + setFrameShadow(Raised); + + QVBoxLayout *layout = new QVBoxLayout(this); + setLayout(layout); + + m_activeLabel = new QLabel(this); + m_activeLabel->setMinimumSize(50, 20); + StyleHelper::ActiveStoredLabel(m_activeLabel); + + m_storedLabel = new QLabel(this); + m_storedLabel->setMinimumSize(50, 20); + StyleHelper::ActiveStoredLabel(m_storedLabel); + + m_titleLabel = new QLabel(this); + m_titleLabel->setText("Bit" + QString::number(m_id)); + StyleHelper::MenuSmallLabel(m_titleLabel); + + layout->addWidget(m_activeLabel, 0, Qt::AlignCenter); + layout->addWidget(m_storedLabel, 0, Qt::AlignCenter); + layout->addWidget(m_titleLabel, 0, Qt::AlignCenter); + + installEventFilter(this); + StyleHelper::FaultsFrame(this); +} + +FaultWidget::~FaultWidget() {} + +bool FaultWidget::isStored() const { return m_stored; } + +void FaultWidget::setStored(bool stored) +{ + FaultWidget::m_stored = stored; + m_storedLabel->setProperty("high", m_stored); + m_storedLabel->setStyle(m_storedLabel->style()); +} + +bool FaultWidget::isActive() const { return m_active; } + +void FaultWidget::setActive(bool active) +{ + FaultWidget::m_active = active; + m_activeLabel->setProperty("high", m_active); + m_activeLabel->setStyle(m_activeLabel->style()); +} + +const QString &FaultWidget::getName() const { return m_name; } + +void FaultWidget::setName(const QString &name) { FaultWidget::m_name = name; } + +const QString &FaultWidget::getFaultExplanation() const { return m_faultExplanation; } + +void FaultWidget::setFaultExplanation(const QString &faultExplanation) +{ + FaultWidget::m_faultExplanation = faultExplanation; +} + +void FaultWidget::setFaultExplanationOptions(QJsonObject options) { m_faultExplanationOptions = options; } + +unsigned int FaultWidget::getId() const { return m_id; } + +void FaultWidget::setId(unsigned int id) { FaultWidget::m_id = id; } + +bool FaultWidget::isPressed() const { return m_pressed; } + +void FaultWidget::setPressed(bool pressed) +{ + FaultWidget::m_pressed = pressed; + scopy::setDynamicProperty(this, "pressed", pressed); +} + +void FaultWidget::specialFaultUpdated(int index, QString channelFunction) +{ + if(index == m_id) { + QString option = m_faultExplanationOptions[channelFunction].toString(); + if(option.isEmpty()) { + option = "channel configured as: " + channelFunction; + } + setFaultExplanation(option); + Q_EMIT specialFaultExplanationChanged(m_id, m_faultExplanation); + } +} + +bool FaultWidget::eventFilter(QObject *object, QEvent *event) +{ + if(event->type() == QEvent::MouseButtonPress) { + setPressed(!scopy::getDynamicProperty(this, "pressed")); + + Q_EMIT faultSelected(m_id); + } + + if(event->type() == QEvent::ToolTip) { + setToolTip(m_name); + } + + return QWidget::eventFilter(object, event); +} diff --git a/plugins/swiotrefactor/src/swiotrefactor.cpp b/plugins/swiotrefactor/src/swiotrefactor.cpp index 935aeb4d1a..edb76dd790 100644 --- a/plugins/swiotrefactor/src/swiotrefactor.cpp +++ b/plugins/swiotrefactor/src/swiotrefactor.cpp @@ -4,7 +4,7 @@ #include #include "max14906/max14906.h" -#include "faults.h" +#include "faults/faults.h" Q_LOGGING_CATEGORY(CAT_SWIOTREFACTOR, "SWIOTREFACTORPlugin") using namespace scopy::swiotrefactor; @@ -79,7 +79,7 @@ bool SWIOTREFACTORPlugin::onConnect() m_toolList[0]->setEnabled(true); m_toolList[0]->setRunBtnVisible(true); - Faults *faults = new Faults(); + Faults *faults = new Faults(m_param, m_toolList[1]); m_toolList[1]->setTool(faults); m_toolList[1]->setEnabled(true); m_toolList[1]->setRunBtnVisible(true); diff --git a/plugins/swiotrefactor/ui/faultsdevice.ui b/plugins/swiotrefactor/ui/faultsdevice.ui deleted file mode 100644 index 84f8ab6999..0000000000 --- a/plugins/swiotrefactor/ui/faultsdevice.ui +++ /dev/null @@ -1,274 +0,0 @@ - - - FaultsDevice - - - - 0 - 0 - 692 - 301 - - - - - 0 - 0 - - - - Form - - - - - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - - 0 - 0 - - - - - 6 - - - 9 - - - 9 - - - 9 - - - 9 - - - - - QLayout::SetMinimumSize - - - - - - 0 - 0 - - - - device name - - - - - - - - 0 - 0 - - - - Qt::AlignCenter - - - - - - - - - - - - true - - - - 100 - 0 - - - - - 100 - 0 - - - - QPushButton { - width: 80px; - height: 40px; - border-radius: 4px; - color: white; - - font-weight: bold; - - padding-left: 20px; - padding-right: 20px; -} - - - RESET -STORED - - - - - - - true - - - - 100 - 0 - - - - - 100 - 0 - - - - QPushButton { - width: 80px; - height: 40px; - border-radius: 4px; - color: white; - - font-weight: bold; - - padding-left: 20px; - padding-right: 20px; -} - - - CLEAR -SELECTION - - - - - - - Qt::Horizontal - - - - 217 - 20 - - - - - - - - - - - - 0 - 0 - - - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - - 0 - 0 - - - - - 100 - 50 - - - - - - - - 0 - - - QLayout::SetDefaultConstraint - - - 0 - - - 0 - - - 0 - - - 0 - - - - - - - - - - - - 0 - 0 - - - - - QLayout::SetDefaultConstraint - - - - - - - - - diff --git a/plugins/swiotrefactor/ui/faultsgroup.ui b/plugins/swiotrefactor/ui/faultsgroup.ui deleted file mode 100644 index 4fe5209a83..0000000000 --- a/plugins/swiotrefactor/ui/faultsgroup.ui +++ /dev/null @@ -1,87 +0,0 @@ - - - FaultsGroup - - - - 0 - 0 - 920 - 120 - - - - - 0 - 0 - - - - - 0 - 91 - - - - Form - - - - - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - - 0 - 0 - - - - - 30 - 0 - - - - - 0 - - - QLayout::SetMinAndMaxSize - - - 0 - - - 0 - - - 0 - - - 0 - - - - - - - - - diff --git a/plugins/swiotrefactor/ui/faultspage.ui b/plugins/swiotrefactor/ui/faultspage.ui deleted file mode 100644 index 0d8ceddac1..0000000000 --- a/plugins/swiotrefactor/ui/faultspage.ui +++ /dev/null @@ -1,108 +0,0 @@ - - - FaultsPage - - - - 0 - 0 - 749 - 380 - - - - - 0 - 0 - - - - Form - - - - - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - QFrame::StyledPanel - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - - - - Qt::ScrollBarAsNeeded - - - Qt::ScrollBarAlwaysOff - - - QAbstractScrollArea::AdjustIgnored - - - true - - - - - 0 - 0 - 745 - 376 - - - - - 0 - 0 - - - - - - - - - - - - - - diff --git a/plugins/swiotrefactor/ui/faultwidget.ui b/plugins/swiotrefactor/ui/faultwidget.ui deleted file mode 100644 index c0c7c97f6c..0000000000 --- a/plugins/swiotrefactor/ui/faultwidget.ui +++ /dev/null @@ -1,142 +0,0 @@ - - - FaultWidget - - - - 0 - 0 - 87 - 91 - - - - - 0 - 0 - - - - - 70 - 90 - - - - - 87 - 91 - - - - FaultWidget - - - true - - - - - - - 0 - - - QLayout::SetDefaultConstraint - - - 0 - - - 0 - - - 0 - - - 0 - - - - - - 0 - 0 - - - - QFrame#mainFrame[hover=true]:hover { background-color: rgba(0, 0, 0, 60); border: 1px solid rgba(0, 0, 0, 30); border-radius: 5px; } -QFrame#mainFrame[pressed=true] { background-color: rgba(0, 0, 0, 60); border: 1px solid rgba(0, 0, 0, 30); border-radius:5px; } -QLabel#active, QLabel#stored { width: 40px; height: 14px; border: 2px solid ; border-radius: 8px; border-color: white; } -QLabel[high=false] { border-color: white; background-color: transparent; } -QLabel[high=true] { border-color: white; background-color: white; } - - - QFrame::StyledPanel - - - QFrame::Raised - - - 0 - - - false - - - - QLayout::SetDefaultConstraint - - - 9 - - - 9 - - - 9 - - - 9 - - - - - - - - - - - - - - - false - - - - - - - - - - - - - TextLabel - - - Qt::AlignCenter - - - - - - - - - - - diff --git a/plugins/swiotrefactor/ui/swiotfaults.ui b/plugins/swiotrefactor/ui/swiotfaults.ui deleted file mode 100644 index f49bacaab4..0000000000 --- a/plugins/swiotrefactor/ui/swiotfaults.ui +++ /dev/null @@ -1,39 +0,0 @@ - - - Faults - - - - 0 - 0 - 1103 - 603 - - - - Form - - - - - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - -