diff --git a/packages/adrv9009/plugins/adrv9009plugin/include/adrv9009plugin/adrv9009advanced.h b/packages/adrv9009/plugins/adrv9009plugin/include/adrv9009plugin/adrv9009advanced.h index 13dae9c947..5459b337ce 100644 --- a/packages/adrv9009/plugins/adrv9009plugin/include/adrv9009plugin/adrv9009advanced.h +++ b/packages/adrv9009/plugins/adrv9009plugin/include/adrv9009plugin/adrv9009advanced.h @@ -33,6 +33,8 @@ namespace scopy::adrv9009 { +class AgcSetupWidget; + class SCOPY_ADRV9009PLUGIN_EXPORT Adrv9009Advanced : public QWidget { Q_OBJECT @@ -74,7 +76,7 @@ class SCOPY_ADRV9009PLUGIN_EXPORT Adrv9009Advanced : public QWidget QWidget *m_fhmSetup = nullptr; QWidget *m_paProtection = nullptr; QWidget *m_gainSetup = nullptr; - QWidget *m_agcSetup = nullptr; + AgcSetupWidget *m_agcSetup = nullptr; QWidget *m_gpioConfig = nullptr; QWidget *m_auxDac = nullptr; QWidget *m_jesd204Settings = nullptr; @@ -87,4 +89,4 @@ class SCOPY_ADRV9009PLUGIN_EXPORT Adrv9009Advanced : public QWidget }; } // namespace scopy::adrv9009 -#endif // ADRV9009ADVANCED_H \ No newline at end of file +#endif // ADRV9009ADVANCED_H diff --git a/packages/adrv9009/plugins/adrv9009plugin/include/adrv9009plugin/advanced/agcsetupwidget.h b/packages/adrv9009/plugins/adrv9009plugin/include/adrv9009plugin/advanced/agcsetupwidget.h new file mode 100644 index 0000000000..1e051b9bf6 --- /dev/null +++ b/packages/adrv9009/plugins/adrv9009plugin/include/adrv9009plugin/advanced/agcsetupwidget.h @@ -0,0 +1,52 @@ +/* + * 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 . + */ + +#ifndef AGCSETUPWIDGET_H +#define AGCSETUPWIDGET_H + +#include +#include +#include + +namespace scopy::adrv9009 { + +class AgcSetupWidget : public QWidget +{ + Q_OBJECT + +public: + explicit AgcSetupWidget(iio_device *device, QWidget *parent = nullptr); + ~AgcSetupWidget(); + +Q_SIGNALS: + void readRequested(); + +private: + void setupUi(); + QWidget *createRxTddPowerGroup(int channel, QWidget *parent); + QWidget *createAgcRxChannelGroup(const QString &baseAttr, const QString &displayName, const QString &range, + QWidget *parent); + + iio_device *m_device; +}; + +} // namespace scopy::adrv9009 + +#endif // AGCSETUPWIDGET_H diff --git a/packages/adrv9009/plugins/adrv9009plugin/src/adrv9009advanced.cpp b/packages/adrv9009/plugins/adrv9009plugin/src/adrv9009advanced.cpp index a4c4de63e5..7c9c4e99a1 100644 --- a/packages/adrv9009/plugins/adrv9009plugin/src/adrv9009advanced.cpp +++ b/packages/adrv9009/plugins/adrv9009plugin/src/adrv9009advanced.cpp @@ -19,6 +19,7 @@ */ #include "adrv9009advanced.h" +#include "advanced/agcsetupwidget.h" #include #include #include @@ -237,7 +238,7 @@ void Adrv9009Advanced::createContentWidgets() m_fhmSetup = createPlaceholderWidget("FHM Setup"); m_paProtection = createPlaceholderWidget("PA Protection"); m_gainSetup = createPlaceholderWidget("GAIN Setup"); - m_agcSetup = createPlaceholderWidget("AGC Setup"); + m_agcSetup = new AgcSetupWidget(m_device, this); m_gpioConfig = createPlaceholderWidget("GPIO Config"); m_auxDac = createPlaceholderWidget("AUX DAC"); m_jesd204Settings = createPlaceholderWidget("JESD204 Settings"); @@ -260,6 +261,10 @@ void Adrv9009Advanced::createContentWidgets() // Set first widget as current (CLK Settings) m_centralWidget->setCurrentWidget(m_clkSettings); + + if(m_agcSetup) { + connect(this, &Adrv9009Advanced::readRequested, m_agcSetup, &AgcSetupWidget::readRequested); + } } QWidget *Adrv9009Advanced::createPlaceholderWidget(const QString §ionName) diff --git a/packages/adrv9009/plugins/adrv9009plugin/src/advanced/agcsetupwidget.cpp b/packages/adrv9009/plugins/adrv9009plugin/src/advanced/agcsetupwidget.cpp new file mode 100644 index 0000000000..8633a8ce13 --- /dev/null +++ b/packages/adrv9009/plugins/adrv9009plugin/src/advanced/agcsetupwidget.cpp @@ -0,0 +1,622 @@ +/* + * 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 . + */ + +#include "advanced/agcsetupwidget.h" +#include "adrv9009widgetfactory.h" +#include +#include +#include +#include +#include +#include +#include +#include + +Q_LOGGING_CATEGORY(CAT_AGCSETUP, "AgcSetup") + +using namespace scopy; +using namespace scopy::adrv9009; + +AgcSetupWidget::AgcSetupWidget(iio_device *device, QWidget *parent) + : QWidget(parent) + , m_device(device) +{ + if(!m_device) { + qWarning(CAT_AGCSETUP) << "No device provided to AGC Setup widget"; + return; + } + + setupUi(); +} + +AgcSetupWidget::~AgcSetupWidget() {} + +void AgcSetupWidget::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); + + // 1. AGC Config section (19 attributes - adi,rxagc-agc-* only) + MenuSectionCollapseWidget *agcConfigSection = new MenuSectionCollapseWidget( + "AGC Config", MenuCollapseSection::MHCW_ARROW, MenuCollapseSection::MHW_BASEWIDGET, contentWidget); + + // Peak Wait Time - Range Widget [0 1 31] + auto peakWaitTime = Adrv9009WidgetFactory::createRangeWidget(m_device, "adi,rxagc-agc-peak-wait-time", + "[0 1 31]", "Peak Wait Time"); + if(peakWaitTime) { + agcConfigSection->contentLayout()->addWidget(peakWaitTime); + connect(this, &AgcSetupWidget::readRequested, peakWaitTime, &IIOWidget::readAsync); + } + + // RX1/RX2 MAX GAIN INDEX - Two-column layout [0 1 255] + auto maxGainIndexGroup = createAgcRxChannelGroup("adi,rxagc-agc-rx%1-max-gain-index", "MAX GAIN INDEX", + "[0 1 255]", agcConfigSection); + agcConfigSection->contentLayout()->addWidget(maxGainIndexGroup); + + // RX1/RX2 MIN GAIN INDEX - Two-column layout [0 1 255] + auto minGainIndexGroup = createAgcRxChannelGroup("adi,rxagc-agc-rx%1-min-gain-index", "MIN GAIN INDEX", + "[0 1 255]", agcConfigSection); + agcConfigSection->contentLayout()->addWidget(minGainIndexGroup); + + // Gain Update Counter (us) - Range Widget [0 1 16000000] + auto gainUpdateCounter = Adrv9009WidgetFactory::createRangeWidget( + m_device, "adi,rxagc-agc-gain-update-counter_us", "[0 1 16000000]", "Gain Update Counter (us)"); + if(gainUpdateCounter) { + agcConfigSection->contentLayout()->addWidget(gainUpdateCounter); + connect(this, &AgcSetupWidget::readRequested, gainUpdateCounter, &IIOWidget::readAsync); + } + + // RX1/RX2 ATTACK DELAY - Two-column layout [0 1 63] + auto attackDelayGroup = createAgcRxChannelGroup("adi,rxagc-agc-rx%1-attack-delay", "ATTACK DELAY", "[0 1 63]", + agcConfigSection); + agcConfigSection->contentLayout()->addWidget(attackDelayGroup); + + // Slow Loop Settling Delay - Range Widget [0 1 127] + auto slowLoopSettlingDelay = Adrv9009WidgetFactory::createRangeWidget( + m_device, "adi,rxagc-agc-slow-loop-settling-delay", "[0 1 127]", "Slow Loop Settling Delay"); + if(slowLoopSettlingDelay) { + agcConfigSection->contentLayout()->addWidget(slowLoopSettlingDelay); + connect(this, &AgcSetupWidget::readRequested, slowLoopSettlingDelay, &IIOWidget::readAsync); + } + + // Low Thresh Prevent Gain - Checkbox + auto lowThreshPreventGain = Adrv9009WidgetFactory::createCheckboxWidget( + m_device, "adi,rxagc-agc-low-thresh-prevent-gain", "Low Thresh Prevent Gain"); + if(lowThreshPreventGain) { + agcConfigSection->contentLayout()->addWidget(lowThreshPreventGain); + connect(this, &AgcSetupWidget::readRequested, lowThreshPreventGain, &IIOWidget::readAsync); + } + + // Change Gain If Thresh High - Checkbox + auto changeGainIfThreshHigh = Adrv9009WidgetFactory::createCheckboxWidget( + m_device, "adi,rxagc-agc-change-gain-if-thresh-high", "Change Gain If Thresh High"); + if(changeGainIfThreshHigh) { + agcConfigSection->contentLayout()->addWidget(changeGainIfThreshHigh); + connect(this, &AgcSetupWidget::readRequested, changeGainIfThreshHigh, &IIOWidget::readAsync); + } + + // Peak Thresh Gain Control Mode - Checkbox + auto peakThreshGainControlMode = Adrv9009WidgetFactory::createCheckboxWidget( + m_device, "adi,rxagc-agc-peak-thresh-gain-control-mode", "Peak Thresh Gain Control Mode"); + if(peakThreshGainControlMode) { + agcConfigSection->contentLayout()->addWidget(peakThreshGainControlMode); + connect(this, &AgcSetupWidget::readRequested, peakThreshGainControlMode, &IIOWidget::readAsync); + } + + // Reset On RXON - Checkbox + auto resetOnRxon = + Adrv9009WidgetFactory::createCheckboxWidget(m_device, "adi,rxagc-agc-reset-on-rxon", "Reset On RXON"); + if(resetOnRxon) { + agcConfigSection->contentLayout()->addWidget(resetOnRxon); + connect(this, &AgcSetupWidget::readRequested, resetOnRxon, &IIOWidget::readAsync); + } + + // Enable Sync Pulse For Gain Counter - Checkbox + auto enableSyncPulseForGainCounter = Adrv9009WidgetFactory::createCheckboxWidget( + m_device, "adi,rxagc-agc-enable-sync-pulse-for-gain-counter", "Enable Sync Pulse For Gain Counter"); + if(enableSyncPulseForGainCounter) { + agcConfigSection->contentLayout()->addWidget(enableSyncPulseForGainCounter); + connect(this, &AgcSetupWidget::readRequested, enableSyncPulseForGainCounter, &IIOWidget::readAsync); + } + + // Enable IP3 Optimization Thresh - Checkbox + auto enableIp3OptimizationThresh = Adrv9009WidgetFactory::createCheckboxWidget( + m_device, "adi,rxagc-agc-enable-ip3-optimization-thresh", "Enable IP3 Optimization Thresh"); + if(enableIp3OptimizationThresh) { + agcConfigSection->contentLayout()->addWidget(enableIp3OptimizationThresh); + connect(this, &AgcSetupWidget::readRequested, enableIp3OptimizationThresh, &IIOWidget::readAsync); + } + + // IP3 Over Range Thresh - Range Widget [0 1 63] + auto ip3OverRangeThresh = Adrv9009WidgetFactory::createRangeWidget(m_device, "adi,rxagc-ip3-over-range-thresh", + "[0 1 63]", "IP3 Over Range Thresh"); + if(ip3OverRangeThresh) { + agcConfigSection->contentLayout()->addWidget(ip3OverRangeThresh); + connect(this, &AgcSetupWidget::readRequested, ip3OverRangeThresh, &IIOWidget::readAsync); + } + + // IP3 Over Range Thresh Index - Range Widget [0 1 255] + auto ip3OverRangeThreshIndex = Adrv9009WidgetFactory::createRangeWidget( + m_device, "adi,rxagc-ip3-over-range-thresh-index", "[0 1 255]", "IP3 Over Range Thresh Index"); + if(ip3OverRangeThreshIndex) { + agcConfigSection->contentLayout()->addWidget(ip3OverRangeThreshIndex); + connect(this, &AgcSetupWidget::readRequested, ip3OverRangeThreshIndex, &IIOWidget::readAsync); + } + + // IP3 Peak Exceeded Count - Range Widget [0 1 255] + auto ip3PeakExceededCnt = Adrv9009WidgetFactory::createRangeWidget(m_device, "adi,rxagc-ip3-peak-exceeded-cnt", + "[0 1 255]", "IP3 Peak Exceeded Count"); + if(ip3PeakExceededCnt) { + agcConfigSection->contentLayout()->addWidget(ip3PeakExceededCnt); + connect(this, &AgcSetupWidget::readRequested, ip3PeakExceededCnt, &IIOWidget::readAsync); + } + + // Enable Fast Recovery Loop - Checkbox + auto enableFastRecoveryLoop = Adrv9009WidgetFactory::createCheckboxWidget( + m_device, "adi,rxagc-agc-enable-fast-recovery-loop", "Enable Fast Recovery Loop"); + if(enableFastRecoveryLoop) { + agcConfigSection->contentLayout()->addWidget(enableFastRecoveryLoop); + connect(this, &AgcSetupWidget::readRequested, enableFastRecoveryLoop, &IIOWidget::readAsync); + } + + contentLayout->addWidget(agcConfigSection); + + // 2. Analog Peak Detector section (29 attributes - adi,rxagc-peak-* including HB2) + MenuSectionCollapseWidget *apdSection = + new MenuSectionCollapseWidget("Analog Peak Detector", MenuCollapseSection::MHCW_ARROW, + MenuCollapseSection::MHW_BASEWIDGET, contentWidget); + + // Under Range Low Interval (ns) - Range Widget [0 1 4294967295] + auto underRangeLowInterval = + Adrv9009WidgetFactory::createRangeWidget(m_device, "adi,rxagc-peak-agc-under-range-low-interval_ns", + "[0 1 4294967295]", "Under Range Low Interval (ns)"); + if(underRangeLowInterval) { + apdSection->contentLayout()->addWidget(underRangeLowInterval); + } + + // Under Range Mid Interval - Range Widget [0 1 63] + auto underRangeMidInterval = Adrv9009WidgetFactory::createRangeWidget( + m_device, "adi,rxagc-peak-agc-under-range-mid-interval", "[0 1 63]", "Under Range Mid Interval"); + if(underRangeMidInterval) { + apdSection->contentLayout()->addWidget(underRangeMidInterval); + } + + // Under Range High Interval - Range Widget [0 1 63] + auto underRangeHighInterval = Adrv9009WidgetFactory::createRangeWidget( + m_device, "adi,rxagc-peak-agc-under-range-high-interval", "[0 1 63]", "Under Range High Interval"); + if(underRangeHighInterval) { + apdSection->contentLayout()->addWidget(underRangeHighInterval); + } + + // APD High Thresh - Range Widget [7 1 49] + auto apdHighThresh = Adrv9009WidgetFactory::createRangeWidget(m_device, "adi,rxagc-peak-apd-high-thresh", + "[7 1 49]", "APD High Thresh"); + if(apdHighThresh) { + apdSection->contentLayout()->addWidget(apdHighThresh); + } + + // APD Low Gain Mode High Thresh - Range Widget [7 1 49] + auto apdLowGainModeHighThresh = Adrv9009WidgetFactory::createRangeWidget( + m_device, "adi,rxagc-peak-apd-low-gain-mode-high-thresh", "[7 1 49]", "APD Low Gain Mode High Thresh"); + if(apdLowGainModeHighThresh) { + apdSection->contentLayout()->addWidget(apdLowGainModeHighThresh); + } + + // APD Low Thresh - Range Widget [7 1 49] + auto apdLowThresh = Adrv9009WidgetFactory::createRangeWidget(m_device, "adi,rxagc-peak-apd-low-thresh", + "[7 1 49]", "APD Low Thresh"); + if(apdLowThresh) { + apdSection->contentLayout()->addWidget(apdLowThresh); + } + + // APD Low Gain Mode Low Thresh - Range Widget [7 1 49] + auto apdLowGainModeLowThresh = Adrv9009WidgetFactory::createRangeWidget( + m_device, "adi,rxagc-peak-apd-low-gain-mode-low-thresh", "[7 1 49]", "APD Low Gain Mode Low Thresh"); + if(apdLowGainModeLowThresh) { + apdSection->contentLayout()->addWidget(apdLowGainModeLowThresh); + } + + // APD Upper Thresh Peak Exceeded Count - Range Widget [0 1 255] + auto apdUpperThreshPeakExceededCnt = + Adrv9009WidgetFactory::createRangeWidget(m_device, "adi,rxagc-peak-apd-upper-thresh-peak-exceeded-cnt", + "[0 1 255]", "APD Upper Thresh Peak Exceeded Count"); + if(apdUpperThreshPeakExceededCnt) { + apdSection->contentLayout()->addWidget(apdUpperThreshPeakExceededCnt); + } + + // APD Lower Thresh Peak Exceeded Count - Range Widget [0 1 255] + auto apdLowerThreshPeakExceededCnt = + Adrv9009WidgetFactory::createRangeWidget(m_device, "adi,rxagc-peak-apd-lower-thresh-peak-exceeded-cnt", + "[0 1 255]", "APD Lower Thresh Peak Exceeded Count"); + if(apdLowerThreshPeakExceededCnt) { + apdSection->contentLayout()->addWidget(apdLowerThreshPeakExceededCnt); + } + + // APD Gain Step Attack - Range Widget [0 1 31] + auto apdGainStepAttack = Adrv9009WidgetFactory::createRangeWidget( + m_device, "adi,rxagc-peak-apd-gain-step-attack", "[0 1 31]", "APD Gain Step Attack"); + if(apdGainStepAttack) { + apdSection->contentLayout()->addWidget(apdGainStepAttack); + } + + // APD Gain Step Recovery - Range Widget [0 1 31] + auto apdGainStepRecovery = Adrv9009WidgetFactory::createRangeWidget( + m_device, "adi,rxagc-peak-apd-gain-step-recovery", "[0 1 31]", "APD Gain Step Recovery"); + if(apdGainStepRecovery) { + apdSection->contentLayout()->addWidget(apdGainStepRecovery); + connect(this, &AgcSetupWidget::readRequested, apdGainStepRecovery, &IIOWidget::readAsync); + } + + // === ALL HB2 ATTRIBUTES (MOVED TO CORRECT ANALOG PEAK DETECTOR SECTION) === + + // Enable HB2 Overload - Checkbox + auto enableHb2Overload = Adrv9009WidgetFactory::createCheckboxWidget( + m_device, "adi,rxagc-peak-enable-hb2-overload", "Enable HB2 Overload"); + if(enableHb2Overload) { + apdSection->contentLayout()->addWidget(enableHb2Overload); + connect(this, &AgcSetupWidget::readRequested, enableHb2Overload, &IIOWidget::readAsync); + } + + // HB2 Overload Duration Count - Range Widget [0 1 6] + auto hb2OverloadDurationCnt = Adrv9009WidgetFactory::createRangeWidget( + m_device, "adi,rxagc-peak-hb2-overload-duration-cnt", "[0 1 6]", "HB2 Overload Duration Count"); + if(hb2OverloadDurationCnt) { + apdSection->contentLayout()->addWidget(hb2OverloadDurationCnt); + connect(this, &AgcSetupWidget::readRequested, hb2OverloadDurationCnt, &IIOWidget::readAsync); + } + + // HB2 Overload Thresh Count - Range Widget [1 1 15] + auto hb2OverloadThreshCnt = Adrv9009WidgetFactory::createRangeWidget( + m_device, "adi,rxagc-peak-hb2-overload-thresh-cnt", "[1 1 15]", "HB2 Overload Thresh Count"); + if(hb2OverloadThreshCnt) { + apdSection->contentLayout()->addWidget(hb2OverloadThreshCnt); + connect(this, &AgcSetupWidget::readRequested, hb2OverloadThreshCnt, &IIOWidget::readAsync); + } + + // HB2 High Thresh - Range Widget [0 1 255] + auto hb2HighThresh = Adrv9009WidgetFactory::createRangeWidget(m_device, "adi,rxagc-peak-hb2-high-thresh", + "[0 1 255]", "HB2 High Thresh"); + if(hb2HighThresh) { + apdSection->contentLayout()->addWidget(hb2HighThresh); + connect(this, &AgcSetupWidget::readRequested, hb2HighThresh, &IIOWidget::readAsync); + } + + // HB2 Under Range Low Thresh - Range Widget [0 1 255] + auto hb2UnderRangeLowThresh = Adrv9009WidgetFactory::createRangeWidget( + m_device, "adi,rxagc-peak-hb2-under-range-low-thresh", "[0 1 255]", "HB2 Under Range Low Thresh"); + if(hb2UnderRangeLowThresh) { + apdSection->contentLayout()->addWidget(hb2UnderRangeLowThresh); + connect(this, &AgcSetupWidget::readRequested, hb2UnderRangeLowThresh, &IIOWidget::readAsync); + } + + // HB2 Under Range Mid Thresh - Range Widget [0 1 255] + auto hb2UnderRangeMidThresh = Adrv9009WidgetFactory::createRangeWidget( + m_device, "adi,rxagc-peak-hb2-under-range-mid-thresh", "[0 1 255]", "HB2 Under Range Mid Thresh"); + if(hb2UnderRangeMidThresh) { + apdSection->contentLayout()->addWidget(hb2UnderRangeMidThresh); + connect(this, &AgcSetupWidget::readRequested, hb2UnderRangeMidThresh, &IIOWidget::readAsync); + } + + // HB2 Under Range High Thresh - Range Widget [0 1 255] + auto hb2UnderRangeHighThresh = Adrv9009WidgetFactory::createRangeWidget( + m_device, "adi,rxagc-peak-hb2-under-range-high-thresh", "[0 1 255]", "HB2 Under Range High Thresh"); + if(hb2UnderRangeHighThresh) { + apdSection->contentLayout()->addWidget(hb2UnderRangeHighThresh); + connect(this, &AgcSetupWidget::readRequested, hb2UnderRangeHighThresh, &IIOWidget::readAsync); + } + + // HB2 Upper Thresh Peak Exceeded Count - Range Widget [0 1 255] + auto hb2UpperThreshPeakExceededCnt = + Adrv9009WidgetFactory::createRangeWidget(m_device, "adi,rxagc-peak-hb2-upper-thresh-peak-exceeded-cnt", + "[0 1 255]", "HB2 Upper Thresh Peak Exceeded Count"); + if(hb2UpperThreshPeakExceededCnt) { + apdSection->contentLayout()->addWidget(hb2UpperThreshPeakExceededCnt); + connect(this, &AgcSetupWidget::readRequested, hb2UpperThreshPeakExceededCnt, &IIOWidget::readAsync); + } + + // HB2 Lower Thresh Peak Exceeded Count - Range Widget [0 1 255] + auto hb2LowerThreshPeakExceededCnt = + Adrv9009WidgetFactory::createRangeWidget(m_device, "adi,rxagc-peak-hb2-lower-thresh-peak-exceeded-cnt", + "[0 1 255]", "HB2 Lower Thresh Peak Exceeded Count"); + if(hb2LowerThreshPeakExceededCnt) { + apdSection->contentLayout()->addWidget(hb2LowerThreshPeakExceededCnt); + connect(this, &AgcSetupWidget::readRequested, hb2LowerThreshPeakExceededCnt, &IIOWidget::readAsync); + } + + // HB2 Gain Step High Recovery - Range Widget [0 1 31] + auto hb2GainStepHighRecovery = Adrv9009WidgetFactory::createRangeWidget( + m_device, "adi,rxagc-peak-hb2-gain-step-high-recovery", "[0 1 31]", "HB2 Gain Step High Recovery"); + if(hb2GainStepHighRecovery) { + apdSection->contentLayout()->addWidget(hb2GainStepHighRecovery); + connect(this, &AgcSetupWidget::readRequested, hb2GainStepHighRecovery, &IIOWidget::readAsync); + } + + // HB2 Gain Step Low Recovery - Range Widget [0 1 31] + auto hb2GainStepLowRecovery = Adrv9009WidgetFactory::createRangeWidget( + m_device, "adi,rxagc-peak-hb2-gain-step-low-recovery", "[0 1 31]", "HB2 Gain Step Low Recovery"); + if(hb2GainStepLowRecovery) { + apdSection->contentLayout()->addWidget(hb2GainStepLowRecovery); + connect(this, &AgcSetupWidget::readRequested, hb2GainStepLowRecovery, &IIOWidget::readAsync); + } + + // HB2 Gain Step Mid Recovery - Range Widget [0 1 31] + auto hb2GainStepMidRecovery = Adrv9009WidgetFactory::createRangeWidget( + m_device, "adi,rxagc-peak-hb2-gain-step-mid-recovery", "[0 1 31]", "HB2 Gain Step Mid Recovery"); + if(hb2GainStepMidRecovery) { + apdSection->contentLayout()->addWidget(hb2GainStepMidRecovery); + connect(this, &AgcSetupWidget::readRequested, hb2GainStepMidRecovery, &IIOWidget::readAsync); + } + + // HB2 Gain Step Attack - Range Widget [0 1 31] + auto hb2GainStepAttack = Adrv9009WidgetFactory::createRangeWidget( + m_device, "adi,rxagc-peak-hb2-gain-step-attack", "[0 1 31]", "HB2 Gain Step Attack"); + if(hb2GainStepAttack) { + apdSection->contentLayout()->addWidget(hb2GainStepAttack); + connect(this, &AgcSetupWidget::readRequested, hb2GainStepAttack, &IIOWidget::readAsync); + } + + // HB2 Overload Power Mode - Checkbox + auto hb2OverloadPowerMode = Adrv9009WidgetFactory::createCheckboxWidget( + m_device, "adi,rxagc-peak-hb2-overload-power-mode", "HB2 Overload Power Mode"); + if(hb2OverloadPowerMode) { + apdSection->contentLayout()->addWidget(hb2OverloadPowerMode); + connect(this, &AgcSetupWidget::readRequested, hb2OverloadPowerMode, &IIOWidget::readAsync); + } + + // HB2 OVRG Sel - Checkbox + auto hb2OvrgSel = + Adrv9009WidgetFactory::createCheckboxWidget(m_device, "adi,rxagc-peak-hb2-ovrg-sel", "HB2 OVRG Sel"); + if(hb2OvrgSel) { + apdSection->contentLayout()->addWidget(hb2OvrgSel); + connect(this, &AgcSetupWidget::readRequested, hb2OvrgSel, &IIOWidget::readAsync); + } + + // HB2 Thresh Config - Checkbox + auto hb2ThreshConfig = Adrv9009WidgetFactory::createCheckboxWidget(m_device, "adi,rxagc-peak-hb2-thresh-config", + "HB2 Thresh Config"); + if(hb2ThreshConfig) { + apdSection->contentLayout()->addWidget(hb2ThreshConfig); + connect(this, &AgcSetupWidget::readRequested, hb2ThreshConfig, &IIOWidget::readAsync); + } + + contentLayout->addWidget(apdSection); + + // 3. Power Measurement Detector section (15 attributes - adi,rxagc-power-* only) + MenuSectionCollapseWidget *powerSection = + new MenuSectionCollapseWidget("Power Measurement Detector", MenuCollapseSection::MHCW_ARROW, + MenuCollapseSection::MHW_BASEWIDGET, contentWidget); + + // Power Enable Measurement - Checkbox + auto powerEnableMeasurement = Adrv9009WidgetFactory::createCheckboxWidget( + m_device, "adi,rxagc-power-power-enable-measurement", "Power Enable Measurement"); + if(powerEnableMeasurement) { + powerSection->contentLayout()->addWidget(powerEnableMeasurement); + connect(this, &AgcSetupWidget::readRequested, powerEnableMeasurement, &IIOWidget::readAsync); + } + + // Power Use RFIR Out - Checkbox + auto powerUseRfirOut = Adrv9009WidgetFactory::createCheckboxWidget( + m_device, "adi,rxagc-power-power-use-rfir-out", "Power Use RFIR Out"); + if(powerUseRfirOut) { + powerSection->contentLayout()->addWidget(powerUseRfirOut); + connect(this, &AgcSetupWidget::readRequested, powerUseRfirOut, &IIOWidget::readAsync); + } + + // Power Use BBDC2 - Checkbox + auto powerUseBbdc2 = Adrv9009WidgetFactory::createCheckboxWidget(m_device, "adi,rxagc-power-power-use-bbdc2", + "Power Use BBDC2"); + if(powerUseBbdc2) { + powerSection->contentLayout()->addWidget(powerUseBbdc2); + connect(this, &AgcSetupWidget::readRequested, powerUseBbdc2, &IIOWidget::readAsync); + } + + // Under Range High Power Thresh - Range Widget [0 1 127] + auto underRangeHighPowerThresh = + Adrv9009WidgetFactory::createRangeWidget(m_device, "adi,rxagc-power-under-range-high-power-thresh", + "[0 1 127]", "Under Range High Power Thresh"); + if(underRangeHighPowerThresh) { + powerSection->contentLayout()->addWidget(underRangeHighPowerThresh); + connect(this, &AgcSetupWidget::readRequested, underRangeHighPowerThresh, &IIOWidget::readAsync); + } + + // Under Range Low Power Thresh - Range Widget [0 1 31] + auto underRangeLowPowerThresh = Adrv9009WidgetFactory::createRangeWidget( + m_device, "adi,rxagc-power-under-range-low-power-thresh", "[0 1 31]", "Under Range Low Power Thresh"); + if(underRangeLowPowerThresh) { + powerSection->contentLayout()->addWidget(underRangeLowPowerThresh); + connect(this, &AgcSetupWidget::readRequested, underRangeLowPowerThresh, &IIOWidget::readAsync); + } + + // Under Range High Power Gain Step Recovery - Range Widget [0 1 31] + auto underRangeHighPowerGainStepRecovery = Adrv9009WidgetFactory::createRangeWidget( + m_device, "adi,rxagc-power-under-range-high-power-gain-step-recovery", "[0 1 31]", + "Under Range High Power Gain Step Recovery"); + if(underRangeHighPowerGainStepRecovery) { + powerSection->contentLayout()->addWidget(underRangeHighPowerGainStepRecovery); + connect(this, &AgcSetupWidget::readRequested, underRangeHighPowerGainStepRecovery, + &IIOWidget::readAsync); + } + + // Under Range Low Power Gain Step Recovery - Range Widget [0 1 31] + auto underRangeLowPowerGainStepRecovery = Adrv9009WidgetFactory::createRangeWidget( + m_device, "adi,rxagc-power-under-range-low-power-gain-step-recovery", "[0 1 31]", + "Under Range Low Power Gain Step Recovery"); + if(underRangeLowPowerGainStepRecovery) { + powerSection->contentLayout()->addWidget(underRangeLowPowerGainStepRecovery); + connect(this, &AgcSetupWidget::readRequested, underRangeLowPowerGainStepRecovery, + &IIOWidget::readAsync); + } + + // Power Measurement Duration - Range Widget [0 1 31] + auto powerMeasurementDuration = Adrv9009WidgetFactory::createRangeWidget( + m_device, "adi,rxagc-power-power-measurement-duration", "[0 1 31]", "Power Measurement Duration"); + if(powerMeasurementDuration) { + powerSection->contentLayout()->addWidget(powerMeasurementDuration); + connect(this, &AgcSetupWidget::readRequested, powerMeasurementDuration, &IIOWidget::readAsync); + } + + // RX1/RX2 TDD Power Controls - Two-column layout + QHBoxLayout *tddColumnsLayout = new QHBoxLayout(); + tddColumnsLayout->setContentsMargins(0, 0, 0, 0); + tddColumnsLayout->setSpacing(20); + + // Create RX1 TDD column (left) + QWidget *rx1TddColumn = createRxTddPowerGroup(1, powerSection); + tddColumnsLayout->addWidget(rx1TddColumn); + + // Create RX2 TDD column (right) + QWidget *rx2TddColumn = createRxTddPowerGroup(2, powerSection); + tddColumnsLayout->addWidget(rx2TddColumn); + + // Create container widget for TDD columns layout + QWidget *tddColumnsContainer = new QWidget(); + tddColumnsContainer->setLayout(tddColumnsLayout); + + // Add TDD columns container to power section + powerSection->contentLayout()->addWidget(tddColumnsContainer); + + // Upper0 Power Thresh - Range Widget [0 1 127] + auto upper0PowerThresh = Adrv9009WidgetFactory::createRangeWidget( + m_device, "adi,rxagc-power-upper0-power-thresh", "[0 1 127]", "Upper0 Power Thresh"); + if(upper0PowerThresh) { + powerSection->contentLayout()->addWidget(upper0PowerThresh); + connect(this, &AgcSetupWidget::readRequested, upper0PowerThresh, &IIOWidget::readAsync); + } + + // Upper1 Power Thresh - Range Widget [0 1 15] + auto upper1PowerThresh = Adrv9009WidgetFactory::createRangeWidget( + m_device, "adi,rxagc-power-upper1-power-thresh", "[0 1 15]", "Upper1 Power Thresh"); + if(upper1PowerThresh) { + powerSection->contentLayout()->addWidget(upper1PowerThresh); + connect(this, &AgcSetupWidget::readRequested, upper1PowerThresh, &IIOWidget::readAsync); + } + + // Power Log Shift - Checkbox + auto powerLogShift = Adrv9009WidgetFactory::createCheckboxWidget(m_device, "adi,rxagc-power-power-log-shift", + "Power Log Shift"); + if(powerLogShift) { + powerSection->contentLayout()->addWidget(powerLogShift); + connect(this, &AgcSetupWidget::readRequested, powerLogShift, &IIOWidget::readAsync); + } + + contentLayout->addWidget(powerSection); + + // 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); + + qDebug(CAT_AGCSETUP) << "AGC Setup widget created with 63 attributes in 3 collapsible sections"; +} + +QWidget *AgcSetupWidget::createRxTddPowerGroup(int channel, QWidget *parent) +{ + // Create container widget for RX channel TDD power controls + QWidget *channelWidget = new QWidget(parent); + Style::setStyle(channelWidget, style::properties::widget::border); + + // Create vertical layout for this channel + QVBoxLayout *channelLayout = new QVBoxLayout(channelWidget); + channelLayout->setContentsMargins(10, 10, 10, 10); + channelLayout->setSpacing(10); + + // Add header label + QLabel *headerLabel = new QLabel(QString("RX%1").arg(channel)); + Style::setStyle(headerLabel, style::properties::label::menuMedium); + headerLabel->setAlignment(Qt::AlignCenter); + channelLayout->addWidget(headerLabel); + + // Create widgets based on channel number + QString durationAttr = QString("adi,rxagc-power-rx%1-tdd-power-meas-duration").arg(channel); + QString delayAttr = QString("adi,rxagc-power-rx%1-tdd-power-meas-delay").arg(channel); + + // TDD Power Meas Duration - Range Widget [0 1 65535] + auto durationWidget = Adrv9009WidgetFactory::createRangeWidget(m_device, durationAttr, "[0 1 65535]", + "TDD POWER MEAS DURATION"); + if(durationWidget) { + channelLayout->addWidget(durationWidget); + connect(this, &AgcSetupWidget::readRequested, durationWidget, &IIOWidget::readAsync); + } + + // TDD Power Meas Delay - Range Widget [0 1 65535] + auto delayWidget = + Adrv9009WidgetFactory::createRangeWidget(m_device, delayAttr, "[0 1 65535]", "TDD POWER MEAS DELAY"); + if(delayWidget) { + channelLayout->addWidget(delayWidget); + connect(this, &AgcSetupWidget::readRequested, delayWidget, &IIOWidget::readAsync); + } + + return channelWidget; +} + +QWidget *AgcSetupWidget::createAgcRxChannelGroup(const QString &baseAttr, const QString &displayName, + const QString &range, QWidget *parent) +{ + // Create container widget with proper Scopy styling + QWidget *channelWidget = new QWidget(parent); + Style::setStyle(channelWidget, style::properties::widget::border); + + // Create horizontal layout for RX1/RX2 columns + QHBoxLayout *channelLayout = new QHBoxLayout(channelWidget); + channelLayout->setContentsMargins(10, 10, 10, 10); + channelLayout->setSpacing(20); + + // Add combined label with proper Scopy styling hierarchy + QLabel *headerLabel = new QLabel(QString("RX1/RX2 %1").arg(displayName)); + Style::setStyle(headerLabel, style::properties::label::menuMedium); + headerLabel->setAlignment(Qt::AlignCenter); + channelLayout->addWidget(headerLabel); + + // Create RX1 widget + QString rx1Attr = QString(baseAttr).arg(1); + auto rx1Widget = + Adrv9009WidgetFactory::createRangeWidget(m_device, rx1Attr, range, QString("RX1 %1").arg(displayName)); + if(rx1Widget) { + channelLayout->addWidget(rx1Widget); + connect(this, &AgcSetupWidget::readRequested, rx1Widget, &IIOWidget::readAsync); + } + + // Create RX2 widget + QString rx2Attr = QString(baseAttr).arg(2); + auto rx2Widget = + Adrv9009WidgetFactory::createRangeWidget(m_device, rx2Attr, range, QString("RX2 %1").arg(displayName)); + if(rx2Widget) { + channelLayout->addWidget(rx2Widget); + connect(this, &AgcSetupWidget::readRequested, rx2Widget, &IIOWidget::readAsync); + } + + return channelWidget; +}