Added single sweep functionality

This commit is contained in:
Jan Käberich 2022-05-17 20:07:40 +02:00
parent 53dcff8745
commit d84d3e80aa
8 changed files with 124 additions and 11 deletions

View File

@ -382,6 +382,16 @@ Example (assuming <averaging sweep> = 3):
\subsubsection{VNA:ACQuisition:LIMit}
\query{Queries the status of limits that maybe set up on any graph}{VNA:ACQuisition:LIMit?}{None}{PASS or FAIL}
\subsubsection{VNA:ACQuisition:SINGLE}
\event{Configures the VNA for single or continuous sweep}{VNA:ACQuisition:SINGLE}{TRUE or FALSE}
\query{Queries whether the VNA is set up for single sweep}{VNA:ACQuisition:SINGLE?}{None}{TRUE or FALSE}
If single sweep is enabled, the acquisition is stopped when the required number of averages have been reached. There are two ways to trigger a new sweep:
\begin{itemize}
\item Change any sweep setting (e.g. center frequency)
\item Issue the command again (i.e. VNA:ACQ:SINGLE TRUE always triggers a new sweep)
\end{itemize}
\subsubsection{VNA:STIMulus:LVL}
\event{Sets the output power of the stimulus signal when sweep type is frequency}{VNA:STIMulus:LVL}{<power>, in dBm}
\query{Queries the currently selected output power}{VNA:STIMulus:LVL?}{None}{power in dBm}
@ -608,6 +618,16 @@ Example (assuming <averaging sweep> = 3):
\subsubsection{SA:ACQuisition:LIMit}
\query{Queries the status of limits that maybe set up on any graph}{SA:ACQuisition:LIMit?}{None}{PASS or FAIL}
\subsubsection{SA:ACQuisition:SINGLE}
\event{Configures the spectrum analyzer for single or continuous sweep}{SA:ACQuisition:SINGLE}{TRUE or FALSE}
\query{Queries whether the spectrum analyzer is set up for single sweep}{SA:ACQuisition:SINGLE?}{None}{TRUE or FALSE}
If single sweep is enabled, the acquisition is stopped when the required number of averages have been reached. There are two ways to trigger a new sweep:
\begin{itemize}
\item Change any sweep setting (e.g. center frequency)
\item Issue the command again (i.e. SA:ACQ:SINGLE TRUE always triggers a new sweep)
\end{itemize}
\subsubsection{SA:ACQuisition:SIGid}
\event{Enables/disables signal identification}{SA:ACQuisition:SIGid}{<enabled>, option are TRUE, FALSE, 1 or 0}
\query{Queries whether signal identification is enabled}{SA:ACQuisition:SIGid?}{None}{TRUE or FALSE}

View File

@ -256,12 +256,12 @@ bool Device::Configure(Protocol::SweepSettings settings, std::function<void(Tran
return SendPacket(p, cb);
}
bool Device::Configure(Protocol::SpectrumAnalyzerSettings settings)
bool Device::Configure(Protocol::SpectrumAnalyzerSettings settings, std::function<void (Device::TransmissionResult)> cb)
{
Protocol::PacketInfo p;
p.type = Protocol::PacketType::SpectrumAnalyzerSettings;
p.spectrumSettings = settings;
return SendPacket(p);
return SendPacket(p, cb);
}
bool Device::SetManual(Protocol::ManualControlV1 manual)
@ -272,9 +272,9 @@ bool Device::SetManual(Protocol::ManualControlV1 manual)
return SendPacket(p);
}
bool Device::SetIdle()
bool Device::SetIdle(std::function<void(TransmissionResult)> cb)
{
return SendCommandWithoutPayload(Protocol::PacketType::SetIdle);
return SendCommandWithoutPayload(Protocol::PacketType::SetIdle, cb);
}
bool Device::SendFirmwareChunk(Protocol::FirmwarePacket &fw)
@ -285,11 +285,11 @@ bool Device::SendFirmwareChunk(Protocol::FirmwarePacket &fw)
return SendPacket(p);
}
bool Device::SendCommandWithoutPayload(Protocol::PacketType type)
bool Device::SendCommandWithoutPayload(Protocol::PacketType type, std::function<void(TransmissionResult)> cb)
{
Protocol::PacketInfo p;
p.type = type;
return SendPacket(p);
return SendPacket(p, cb);
}
std::set<QString> Device::GetDevices()

View File

@ -60,11 +60,11 @@ public:
~Device();
bool SendPacket(const Protocol::PacketInfo& packet, std::function<void(TransmissionResult)> cb = nullptr, unsigned int timeout = 500);
bool Configure(Protocol::SweepSettings settings, std::function<void(TransmissionResult)> cb = nullptr);
bool Configure(Protocol::SpectrumAnalyzerSettings settings);
bool Configure(Protocol::SpectrumAnalyzerSettings settings, std::function<void(TransmissionResult)> cb = nullptr);
bool SetManual(Protocol::ManualControlV1 manual);
bool SetIdle();
bool SetIdle(std::function<void(TransmissionResult)> cb = nullptr);
bool SendFirmwareChunk(Protocol::FirmwarePacket &fw);
bool SendCommandWithoutPayload(Protocol::PacketType type);
bool SendCommandWithoutPayload(Protocol::PacketType type, std::function<void(TransmissionResult)> cb = nullptr);
QString serial() const;
const Protocol::DeviceInfo& Info();
static const Protocol::DeviceInfo& Info(Device *dev);

View File

@ -50,6 +50,7 @@ SpectrumAnalyzer::SpectrumAnalyzer(AppWindow *window, QString name)
central(new TileWidget(traceModel, window))
{
averages = 1;
singleSweep = false;
settings = {};
normalize.active = false;
normalize.measuring = false;
@ -83,6 +84,14 @@ SpectrumAnalyzer::SpectrumAnalyzer(AppWindow *window, QString name)
// Create menu entries and connections
// Sweep toolbar
auto tb_sweep = new QToolBar("Sweep");
auto bSingle = new QPushButton("Single");
bSingle->setToolTip("Single sweep");
bSingle->setCheckable(true);
connect(bSingle, &QPushButton::toggled, this, &SpectrumAnalyzer::SetSingleSweep);
connect(this, &SpectrumAnalyzer::singleSweepChanged, bSingle, &QPushButton::setChecked);
tb_sweep->addWidget(bSingle);
auto eStart = new SIUnitEdit("Hz", " kMG", 6);
// calculate width required with expected string length
auto width = QFontMetrics(eStart->font()).width("3.00000GHz") + 15;
@ -313,6 +322,7 @@ nlohmann::json SpectrumAnalyzer::toJSON()
freq["start"] = settings.f_start;
freq["stop"] = settings.f_stop;
sweep["frequency"] = freq;
sweep["single"] = singleSweep;
nlohmann::json acq;
acq["RBW"] = settings.RBW;
acq["window"] = WindowToString((Window) settings.WindowType).toStdString();
@ -414,6 +424,7 @@ void SpectrumAnalyzer::fromJSON(nlohmann::json j)
EnableNormalization(false);
}
}
SetSingleSweep(sweep.value("single", singleSweep));
}
}
@ -425,6 +436,19 @@ void SpectrumAnalyzer::NewDatapoint(Protocol::SpectrumAnalyzerResult d)
return;
}
if(changingSettings) {
// already setting new sweep settings, ignore incoming points from old settings
return;
}
if(singleSweep && average.getLevel() == averages) {
changingSettings = true;
// single sweep finished
window->getDevice()->SetIdle([=](Device::TransmissionResult){
changingSettings = false;
});
}
if(d.pointNum >= settings.pointNum) {
qWarning() << "Ignoring point with too large point number (" << d.pointNum << ")";
return;
@ -477,6 +501,7 @@ void SpectrumAnalyzer::NewDatapoint(Protocol::SpectrumAnalyzerResult d)
void SpectrumAnalyzer::SettingsChanged()
{
changingSettings = true;
if(settings.f_stop - settings.f_start >= 1000) {
settings.pointNum = 1001;
} else {
@ -529,7 +554,10 @@ void SpectrumAnalyzer::SettingsChanged()
}
if(window->getDevice() && Mode::getActiveMode() == this) {
window->getDevice()->Configure(settings);
window->getDevice()->Configure(settings, [=](Device::TransmissionResult res){
// device received command
changingSettings = false;
});
}
average.reset(settings.pointNum);
UpdateAverageCount();
@ -620,6 +648,15 @@ void SpectrumAnalyzer::SpanZoomOut()
ConstrainAndUpdateFrequencies();
}
void SpectrumAnalyzer::SetSingleSweep(bool single)
{
if(singleSweep != single) {
singleSweep = single;
emit singleSweepChanged(single);
}
SettingsChanged();
}
void SpectrumAnalyzer::SetRBW(double bandwidth)
{
if(bandwidth > Device::Info(window->getDevice()).limits_maxRBW) {
@ -923,6 +960,17 @@ void SpectrumAnalyzer::SetupSCPI()
}, [=](QStringList) -> QString {
return settings.SignalID ? "TRUE" : "FALSE";
}));
scpi_acq->add(new SCPICommand("SINGLE", [=](QStringList params) -> QString {
bool single;
if(!SCPI::paramToBool(params, 0, single)) {
return "ERROR";
} else {
SetSingleSweep(single);
return "";
}
}, [=](QStringList) -> QString {
return singleSweep ? "TRUE" : "FALSE";
}));
auto scpi_tg = new SCPINode("TRACKing");
SCPINode::add(scpi_tg);
scpi_tg->add(new SCPICommand("ENable", [=](QStringList params) -> QString {

View File

@ -63,6 +63,7 @@ private slots:
void SetFullSpan();
void SpanZoomIn();
void SpanZoomOut();
void SetSingleSweep(bool single);
// Acquisition control
void SetRBW(double bandwidth);
void SetWindow(Window w);
@ -88,7 +89,9 @@ private:
void StoreSweepSettings();
Protocol::SpectrumAnalyzerSettings settings;
bool changingSettings;
unsigned int averages;
bool singleSweep;
TraceModel traceModel;
TraceWidget *traceWidget;
MarkerModel *markerModel;
@ -122,6 +125,7 @@ signals:
void stopFreqChanged(double freq);
void centerFreqChanged(double freq);
void spanChanged(double span);
void singleSweepChanged(bool single);
void RBWChanged(double RBW);
void TGStateChanged(bool enabled);
void TGPortChanged(int port);

View File

@ -1,4 +1,4 @@
#include "vna.h"
#include "vna.h"
#include "unit.h"
#include "CustomWidgets/toggleswitch.h"
@ -58,6 +58,7 @@ VNA::VNA(AppWindow *window, QString name)
central(new TileWidget(traceModel))
{
averages = 1;
singleSweep = false;
calValid = false;
calMeasuring = false;
calWaitFirst = false;
@ -257,6 +258,13 @@ VNA::VNA(AppWindow *window, QString name)
cbSweepType->addItem("Power");
tb_sweep->addWidget(cbSweepType);
auto bSingle = new QPushButton("Single");
bSingle->setToolTip("Single sweep");
bSingle->setCheckable(true);
connect(bSingle, &QPushButton::toggled, this, &VNA::SetSingleSweep);
connect(this, &VNA::singleSweepChanged, bSingle, &QPushButton::setChecked);
tb_sweep->addWidget(bSingle);
auto eStart = new SIUnitEdit("Hz", " kMG", 6);
// calculate width required with expected string length
auto width = QFontMetrics(eStart->font()).width("3.00000GHz") + 15;
@ -719,6 +727,7 @@ nlohmann::json VNA::toJSON()
freq["power"] = settings.Freq.excitation_power;
freq["log"] = settings.Freq.logSweep;
sweep["frequency"] = freq;
sweep["single"] = singleSweep;
nlohmann::json power;
power["start"] = settings.Power.start;
power["stop"] = settings.Power.stop;
@ -782,6 +791,7 @@ void VNA::fromJSON(nlohmann::json j)
type = SweepType::Frequency;
}
SetSweepType(type);
SetSingleSweep(sweep.value("single", singleSweep));
}
}
@ -799,6 +809,14 @@ void VNA::NewDatapoint(Protocol::Datapoint d)
return;
}
if(singleSweep && average.getLevel() == averages) {
changingSettings = true;
// single sweep finished
window->getDevice()->SetIdle([=](Device::TransmissionResult){
changingSettings = false;
});
}
bool needsSegmentUpdate = false;
if (settings.segments > 1) {
// using multiple segments, adjust pointNum
@ -1377,6 +1395,17 @@ void VNA::SetupSCPI()
scpi_acq->add(new SCPICommand("LIMit", nullptr, [=](QStringList) -> QString {
return central->allLimitsPassing() ? "PASS" : "FAIL";
}));
scpi_acq->add(new SCPICommand("SINGLE", [=](QStringList params) -> QString {
bool single;
if(!SCPI::paramToBool(params, 0, single)) {
return "ERROR";
} else {
SetSingleSweep(single);
return "";
}
}, [=](QStringList) -> QString {
return singleSweep ? "TRUE" : "FALSE";
}));
auto scpi_stim = new SCPINode("STIMulus");
SCPINode::add(scpi_stim);
scpi_stim->add(new SCPICommand("LVL", [=](QStringList params) -> QString {
@ -1627,6 +1656,15 @@ void VNA::UpdateStatusbar()
}
}
void VNA::SetSingleSweep(bool single)
{
if(singleSweep != single) {
singleSweep = single;
emit singleSweepChanged(single);
}
SettingsChanged();
}
bool VNA::LoadCalibration(QString filename)
{
cal.openFromFile(filename);

View File

@ -123,6 +123,7 @@ private:
private slots:
void EnableDeembedding(bool enable);
void UpdateStatusbar();
void SetSingleSweep(bool single);
private:
Settings settings;
unsigned int averages;
@ -130,6 +131,7 @@ private:
TraceWidget *traceWidget;
MarkerModel *markerModel;
Averaging average;
bool singleSweep;
// Calibration
Calibration cal;
@ -167,6 +169,7 @@ signals:
void centerFreqChanged(double freq);
void spanChanged(double span);
void logSweepChanged(bool log);
void singleSweepChanged(bool single);
void sourceLevelChanged(double level);
void pointsChanged(unsigned int points);