Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
#include <tooltemplate.h>
#include <animatedrefreshbtn.h>
#include <iio.h>
#include <advanced/auxdacwidget.h>

// Forward declarations for section widgets
namespace scopy::adrv9009 {
Expand Down Expand Up @@ -90,7 +91,7 @@ class SCOPY_ADRV9009PLUGIN_EXPORT Adrv9009Advanced : public QWidget
TxSettingsWidget *m_txSettings = nullptr;
RxSettingsWidget *m_rxSettings = nullptr;
OrxSettingsWidget *m_orxSettings = nullptr;
QWidget *m_auxDac = nullptr;
AuxDacWidget *m_auxDac = nullptr;
QWidget *m_jesd204Settings = nullptr;
QWidget *m_bist = nullptr;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,15 @@ class SCOPY_ADRV9009PLUGIN_EXPORT Adrv9009WidgetFactory
static IIOWidget *createReadOnlyWidget(iio_channel *channel, QString attr, QString title,
bool compactMode = true, QWidget *parent = nullptr);

// Debug attribute widgets (for advanced plugin features like aux DAC)
static IIOWidget *createDebugRangeWidget(iio_device *device, QString attr, QString range, QString title,
QWidget *parent = nullptr);
static IIOWidget *createDebugCustomComboWidget(iio_device *device, QString attr,
QMap<QString, QString> *optionsMap, QString title,
QWidget *parent = nullptr);
static IIOWidget *createDebugCheckboxWidget(iio_device *device, QString attr, QString title,
QWidget *parent = nullptr);

private:
Adrv9009WidgetFactory() = delete; // Static class, no instances
};
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/*
* Copyright (c) 2025 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 <https://www.gnu.org/licenses/>.
*/

#ifndef AUXDACWIDGET_H
#define AUXDACWIDGET_H

#include "scopy-adrv9009plugin_export.h"
#include <QWidget>
#include <QScrollArea>
#include <QVBoxLayout>
#include <QCheckBox>
#include <iio.h>
#include <iio-widgets/iiowidget.h>
#include <gui/widgets/menusectionwidget.h>

namespace scopy::adrv9009 {

class SCOPY_ADRV9009PLUGIN_EXPORT AuxDacWidget : public QWidget
{
Q_OBJECT

public:
explicit AuxDacWidget(iio_device *device, QWidget *parent = nullptr);
~AuxDacWidget();

Q_SIGNALS:
void readRequested();

private:
void setupUi();
QWidget *createAuxDacControls(QWidget *parent);

iio_device *m_device;
QList<IIOWidget *> m_iioWidgets;
const int AUX_DAC_FULL_CONFIG_COUNT = 10; // DACs 0-9 have value+resolution+vref
const int AUX_DAC_TOTAL_COUNT = 12; // DACs 10-11 have value only
};

} // namespace scopy::adrv9009

#endif // AUXDACWIDGET_H
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,7 @@ void Adrv9009Advanced::createContentWidgets()
m_txSettings = new TxSettingsWidget(m_device, this);
m_rxSettings = new RxSettingsWidget(m_device, this);
m_orxSettings = new OrxSettingsWidget(m_device, this);
m_auxDac = createPlaceholderWidget("AUX DAC");
m_auxDac = new AuxDacWidget(m_device, this);
m_jesd204Settings = createPlaceholderWidget("JESD204 Settings");
m_bist = createPlaceholderWidget("BIST");

Expand All @@ -270,6 +270,11 @@ void Adrv9009Advanced::createContentWidgets()
m_centralWidget->addWidget(m_jesd204Settings);
m_centralWidget->addWidget(m_bist);

// Connect auxDac widget readRequested signal
if(m_auxDac) {
connect(this, &Adrv9009Advanced::readRequested, m_auxDac, &AuxDacWidget::readRequested);
}

// Set first widget as current (CLK Settings)
m_centralWidget->setCurrentWidget(m_clkSettings);
if(m_txSettings) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -195,3 +195,72 @@ IIOWidget *Adrv9009WidgetFactory::createReadOnlyWidget(iio_channel *channel, QSt
}
return widget;
}

// Debug attribute widgets (following proper porting rules)
IIOWidget *Adrv9009WidgetFactory::createDebugRangeWidget(iio_device *device, QString attr, QString range, QString title,
QWidget *parent)
{
IIOWidget *widget = IIOWidgetBuilder(parent)
.device(device)
.attribute(attr)
.optionsValues(range)
.title(title)
.uiStrategy(IIOWidgetBuilder::RangeUi) // UI strategy auto-sets data strategy
.includeDebugAttributes(true)
.buildSingle();
return widget;
}

IIOWidget *Adrv9009WidgetFactory::createDebugCustomComboWidget(iio_device *device, QString attr,
QMap<QString, QString> *optionsMap, QString title,
QWidget *parent)
{
// Build space-separated display string from optionsMap values (following Template 2B)
auto values = optionsMap->values();
QString optionsValues = "";
for(int i = 0; i < values.size(); i++) {
if(i > 0)
optionsValues += " ";
// Use underscores in display values as per porting rules
QString value = values.at(i);
optionsValues += value.replace(" ", "_");
}

// Create widget with ComboUi strategy (following porting rules)
IIOWidget *widget = IIOWidgetBuilder(parent)
.device(device)
.attribute(attr)
.title(title)
.uiStrategy(IIOWidgetBuilder::ComboUi) // UI strategy auto-sets data strategy
.optionsValues(optionsValues)
.includeDebugAttributes(true)
.buildSingle();

// Set bidirectional conversion functions using IIOWidgetUtils (as per Template 2B)
if(widget) {
widget->setUItoDataConversion([optionsMap](QString data) {
return IIOWidgetUtils::comboUiToDataConversionFunction(data, optionsMap);
});
widget->setDataToUIConversion([optionsMap](QString data) {
return IIOWidgetUtils::comboDataToUiConversionFunction(data, optionsMap);
});
}

return widget;
}

IIOWidget *Adrv9009WidgetFactory::createDebugCheckboxWidget(iio_device *device, QString attr, QString title,
QWidget *parent)
{
IIOWidget *widget = IIOWidgetBuilder(parent)
.device(device)
.attribute(attr)
.title(title)
.uiStrategy(IIOWidgetBuilder::CheckBoxUi) // UI strategy auto-sets data strategy
.includeDebugAttributes(true)
.buildSingle();
if(widget) {
widget->showProgressBar(false);
}
return widget;
}
178 changes: 178 additions & 0 deletions packages/adrv9009/plugins/adrv9009plugin/src/advanced/auxdacwidget.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
/*
* Copyright (c) 2025 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 <https://www.gnu.org/licenses/>.
*/

#include "advanced/auxdacwidget.h"
#include "adrv9009widgetfactory.h"

#include <QLabel>
#include <QGridLayout>
#include <QGroupBox>
#include <QCheckBox>

#include <iio-widgets/iiowidget.h>
#include <gui/style.h>
#include <gui/widgets/menucollapsesection.h>

using namespace scopy::adrv9009;
using namespace scopy;

AuxDacWidget::AuxDacWidget(iio_device *device, QWidget *parent)
: QWidget(parent)
, m_device(device)
{
if(m_device != nullptr) {
setupUi();
}
}

AuxDacWidget::~AuxDacWidget() {}

void AuxDacWidget::setupUi()
{
// Main layout for this widget
QVBoxLayout *mainLayout = new QVBoxLayout(this);
mainLayout->setContentsMargins(0, 0, 0, 0);
mainLayout->setSpacing(0);

// Create scroll area for all sections
QScrollArea *scrollArea = new QScrollArea();
scrollArea->setWidgetResizable(true);
scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
scrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);

// Create content widget for scroll area
QWidget *contentWidget = new QWidget();
QVBoxLayout *contentLayout = new QVBoxLayout(contentWidget);
contentLayout->setContentsMargins(10, 10, 10, 10);
contentLayout->setSpacing(15);

// Add AUX PLL section
contentLayout->addWidget(createAuxDacControls(contentWidget));

// Add spacer to push sections to top
contentLayout->addItem(new QSpacerItem(20, 40, QSizePolicy::Minimum, QSizePolicy::Expanding));

// Set up scroll area
scrollArea->setWidget(contentWidget);
mainLayout->addWidget(scrollArea);
}

QWidget *AuxDacWidget::createAuxDacControls(QWidget *parent)
{
// Create AUX DAC section header
MenuSectionCollapseWidget *auxDacControlls = new MenuSectionCollapseWidget(
"AUX DAC", MenuCollapseSection::MHCW_ARROW, MenuCollapseSection::MHW_BASEWIDGET, parent);

QWidget *widget = new QWidget(parent);
QGridLayout *configGrid = new QGridLayout(widget);
configGrid->setContentsMargins(10, 10, 10, 10);
configGrid->setSpacing(10);
widget->setLayout(configGrid);

auxDacControlls->contentLayout()->addWidget(widget);
Style::setBackgroundColor(widget, json::theme::background_primary);
Style::setStyle(widget, style::properties::widget::border_interactive);

// Table headers
configGrid->addWidget(new QLabel("DAC"), 0, 0);
QLabel *valueHeader = new QLabel("VALUE");
valueHeader->setAlignment(Qt::AlignCenter);
configGrid->addWidget(valueHeader, 0, 1);

QLabel *resHeader = new QLabel("RES");
resHeader->setAlignment(Qt::AlignCenter);
configGrid->addWidget(resHeader, 0, 2);

QLabel *refHeader = new QLabel("REF");
refHeader->setAlignment(Qt::AlignCenter);
configGrid->addWidget(refHeader, 0, 3);

// DAC 0-9: Full configuration (value + resolution + vref)
for(int i = 0; i < AUX_DAC_FULL_CONFIG_COUNT; i++) {
int row = i + 1;

// DAC number label
QLabel *dacLabel = new QLabel(QString("DAC %1").arg(i));
configGrid->addWidget(dacLabel, row, 0);

// Value widget - use CORRECT attribute name following iio-oscilloscope reference
QString valueAttr = QString("adi,aux-dac-values%1").arg(i);
IIOWidget *valueWidget = Adrv9009WidgetFactory::createDebugRangeWidget(
m_device, valueAttr, "[0 1023 1]", QString("DAC %1 Value").arg(i), this);
configGrid->addWidget(valueWidget, row, 1);
if(valueWidget) {
m_iioWidgets.append(valueWidget);
connect(this, &AuxDacWidget::readRequested, valueWidget, &IIOWidget::readAsync);
}

// Resolution widget - use CORRECT attribute name and proper Template 2B pattern
QString resolutionAttr = QString("adi,aux-dac-resolution%1").arg(i);
QMap<QString, QString> *resolutionMap = new QMap<QString, QString>();
(*resolutionMap)["0"] = "8_bit";
(*resolutionMap)["1"] = "10_bit";
(*resolutionMap)["2"] = "12_bit";
IIOWidget *resolutionWidget = Adrv9009WidgetFactory::createDebugCustomComboWidget(
m_device, resolutionAttr, resolutionMap, QString("DAC %1 Resolution").arg(i), this);
configGrid->addWidget(resolutionWidget, row, 2);
if(resolutionWidget) {
m_iioWidgets.append(resolutionWidget);
connect(this, &AuxDacWidget::readRequested, resolutionWidget, &IIOWidget::readAsync);
}

// Vref widget - use CORRECT attribute name and proper Template 2B pattern
QString vrefAttr = QString("adi,aux-dac-vref%1").arg(i);
QMap<QString, QString> *vrefMap = new QMap<QString, QString>();
(*vrefMap)["0"] = "Internal_1.25V";
(*vrefMap)["1"] = "External_Vref";
(*vrefMap)["2"] = "Internal_2.5V";
(*vrefMap)["3"] = "Reserved";
IIOWidget *vrefWidget = Adrv9009WidgetFactory::createDebugCustomComboWidget(
m_device, vrefAttr, vrefMap, QString("DAC %1 Vref").arg(i), this);
configGrid->addWidget(vrefWidget, row, 3);
if(vrefWidget) {
m_iioWidgets.append(vrefWidget);
connect(this, &AuxDacWidget::readRequested, vrefWidget, &IIOWidget::readAsync);
}
}

// DAC 10-11: Value only (no resolution/vref controls per iio-oscilloscope reference)
for(int i = AUX_DAC_FULL_CONFIG_COUNT; i < AUX_DAC_TOTAL_COUNT; i++) {
int row = i + 1;

QLabel *dacLabel = new QLabel(QString("DAC %1").arg(i));
configGrid->addWidget(dacLabel, row, 0);

// Value widget only for DAC 10-11
QString valueAttr = QString("adi,aux-dac-values%1").arg(i);
IIOWidget *valueWidget = Adrv9009WidgetFactory::createDebugRangeWidget(
m_device, valueAttr, "[0 1023 1]", QString("DAC %1 Value").arg(i), this);
configGrid->addWidget(valueWidget, row, 1);
if(valueWidget) {
m_iioWidgets.append(valueWidget);
connect(this, &AuxDacWidget::readRequested, valueWidget, &IIOWidget::readAsync);
}

// Empty cells for consistency
configGrid->addWidget(new QLabel("N/A"), row, 2);
configGrid->addWidget(new QLabel("N/A"), row, 3);
}

return auxDacControlls;
}