mirror of
https://github.com/jankae/LibreVNA.git
synced 2026-04-04 14:07:30 +00:00
Merge branch 'master' of github.com:jankae/LibreVNA
This commit is contained in:
commit
4243e64f7f
45 changed files with 710 additions and 400 deletions
|
|
@ -253,7 +253,7 @@ void AmplitudeCalDialog::RemoveAllPoints()
|
|||
|
||||
bool AmplitudeCalDialog::AddPoint(AmplitudeCalDialog::CorrectionPoint &p)
|
||||
{
|
||||
if (points.size() >= Device::Info().limits_maxAmplitudePoints) {
|
||||
if (points.size() >= Device::Info(dev).limits_maxAmplitudePoints) {
|
||||
// already at limit
|
||||
return false;
|
||||
}
|
||||
|
|
@ -299,8 +299,8 @@ void AmplitudeCalDialog::AddPointDialog()
|
|||
ui->stopFreq->setUnit("Hz");
|
||||
ui->stopFreq->setPrefixes(" kMG");
|
||||
ui->frequency->setValue(1000000000.0);
|
||||
ui->startFreq->setValue(Device::Info().limits_minFreq);
|
||||
ui->stopFreq->setValue(Device::Info().limits_maxFreq);
|
||||
ui->startFreq->setValue(Device::Info(dev).limits_minFreq);
|
||||
ui->stopFreq->setValue(Device::Info(dev).limits_maxFreq);
|
||||
connect(ui->singlePoint, &QRadioButton::toggled, [=](bool single) {
|
||||
ui->stopFreq->setEnabled(!single);
|
||||
ui->startFreq->setEnabled(!single);
|
||||
|
|
|
|||
|
|
@ -120,16 +120,6 @@ static constexpr Protocol::DeviceInfo defaultInfo = {
|
|||
.FW_minor = 0,
|
||||
.FW_patch = 0,
|
||||
.HW_Revision = '0',
|
||||
.extRefAvailable = 0,
|
||||
.extRefInUse = 0,
|
||||
.FPGA_configured = 0,
|
||||
.source_locked = 0,
|
||||
.LO1_locked = 0,
|
||||
.ADC_overload = 0,
|
||||
.unlevel = 0,
|
||||
.temp_source = 0,
|
||||
.temp_LO1 = 0,
|
||||
.temp_MCU = 0,
|
||||
.limits_minFreq = 0,
|
||||
.limits_maxFreq = 6000000000,
|
||||
.limits_minIFBW = 10,
|
||||
|
|
@ -143,14 +133,25 @@ static constexpr Protocol::DeviceInfo defaultInfo = {
|
|||
.limits_maxFreqHarmonic = 18000000000,
|
||||
};
|
||||
|
||||
Protocol::DeviceInfo Device::lastInfo = defaultInfo;
|
||||
static constexpr Protocol::DeviceStatusV1 defaultStatusV1 = {
|
||||
.extRefAvailable = 0,
|
||||
.extRefInUse = 0,
|
||||
.FPGA_configured = 0,
|
||||
.source_locked = 0,
|
||||
.LO1_locked = 0,
|
||||
.ADC_overload = 0,
|
||||
.unlevel = 0,
|
||||
.temp_source = 0,
|
||||
.temp_LO1 = 0,
|
||||
.temp_MCU = 0,
|
||||
};
|
||||
|
||||
Device::Device(QString serial)
|
||||
{
|
||||
lastInfo = defaultInfo;
|
||||
info = defaultInfo;
|
||||
|
||||
m_handle = nullptr;
|
||||
lastInfoValid = false;
|
||||
infoValid = false;
|
||||
libusb_init(&m_context);
|
||||
#if LIBUSB_API_VERSION >= 0x01000106
|
||||
libusb_set_option(m_context, LIBUSB_OPTION_LOG_LEVEL, LIBUSB_LOG_LEVEL_INFO);
|
||||
|
|
@ -261,10 +262,10 @@ bool Device::Configure(Protocol::SpectrumAnalyzerSettings settings)
|
|||
return SendPacket(p);
|
||||
}
|
||||
|
||||
bool Device::SetManual(Protocol::ManualControl manual)
|
||||
bool Device::SetManual(Protocol::ManualControlV1 manual)
|
||||
{
|
||||
Protocol::PacketInfo p;
|
||||
p.type = Protocol::PacketType::ManualControl;
|
||||
p.type = Protocol::PacketType::ManualControlV1;
|
||||
p.manual = manual;
|
||||
return SendPacket(p);
|
||||
}
|
||||
|
|
@ -393,25 +394,48 @@ void Device::SearchDevices(std::function<bool (libusb_device_handle *, QString)>
|
|||
|
||||
const Protocol::DeviceInfo &Device::Info()
|
||||
{
|
||||
return lastInfo;
|
||||
return info;
|
||||
}
|
||||
|
||||
const Protocol::DeviceInfo &Device::Info(Device *dev)
|
||||
{
|
||||
if(dev) {
|
||||
return dev->Info();
|
||||
} else {
|
||||
return defaultInfo;
|
||||
}
|
||||
}
|
||||
|
||||
Protocol::DeviceStatusV1 &Device::StatusV1()
|
||||
{
|
||||
return status.v1;
|
||||
}
|
||||
|
||||
const Protocol::DeviceStatusV1 &Device::StatusV1(Device *dev)
|
||||
{
|
||||
if(dev) {
|
||||
return dev->StatusV1();
|
||||
} else {
|
||||
return defaultStatusV1;
|
||||
}
|
||||
}
|
||||
|
||||
QString Device::getLastDeviceInfoString()
|
||||
{
|
||||
QString ret;
|
||||
if(!lastInfoValid) {
|
||||
if(!infoValid) {
|
||||
ret.append("No device information available yet");
|
||||
} else {
|
||||
ret.append("HW Rev.");
|
||||
ret.append(lastInfo.HW_Revision);
|
||||
ret.append(" FW "+QString::number(lastInfo.FW_major)+"."+QString::number(lastInfo.FW_minor)+"."+QString::number(lastInfo.FW_patch));
|
||||
ret.append(" Temps: "+QString::number(lastInfo.temp_source)+"°C/"+QString::number(lastInfo.temp_LO1)+"°C/"+QString::number(lastInfo.temp_MCU)+"°C");
|
||||
ret.append(info.HW_Revision);
|
||||
ret.append(" FW "+QString::number(info.FW_major)+"."+QString::number(info.FW_minor)+"."+QString::number(info.FW_patch));
|
||||
ret.append(" Temps: "+QString::number(status.v1.temp_source)+"°C/"+QString::number(status.v1.temp_LO1)+"°C/"+QString::number(status.v1.temp_MCU)+"°C");
|
||||
ret.append(" Reference:");
|
||||
if(lastInfo.extRefInUse) {
|
||||
if(status.v1.extRefInUse) {
|
||||
ret.append("External");
|
||||
} else {
|
||||
ret.append("Internal");
|
||||
if(lastInfo.extRefAvailable) {
|
||||
if(status.v1.extRefAvailable) {
|
||||
ret.append(" (External available)");
|
||||
}
|
||||
}
|
||||
|
|
@ -431,8 +455,8 @@ void Device::ReceivedData()
|
|||
case Protocol::PacketType::Datapoint:
|
||||
emit DatapointReceived(packet.datapoint);
|
||||
break;
|
||||
case Protocol::PacketType::Status:
|
||||
emit ManualStatusReceived(packet.status);
|
||||
case Protocol::PacketType::ManualStatusV1:
|
||||
emit ManualStatusReceived(packet.manualStatusV1);
|
||||
break;
|
||||
case Protocol::PacketType::SpectrumAnalyzerResult:
|
||||
emit SpectrumResultReceived(packet.spectrumResult);
|
||||
|
|
@ -443,15 +467,19 @@ void Device::ReceivedData()
|
|||
break;
|
||||
case Protocol::PacketType::DeviceInfo:
|
||||
if(packet.info.ProtocolVersion != Protocol::Version) {
|
||||
if(!lastInfoValid) {
|
||||
if(!infoValid) {
|
||||
emit NeedsFirmwareUpdate(packet.info.ProtocolVersion, Protocol::Version);
|
||||
}
|
||||
} else {
|
||||
lastInfo = packet.info;
|
||||
info = packet.info;
|
||||
}
|
||||
lastInfoValid = true;
|
||||
infoValid = true;
|
||||
emit DeviceInfoUpdated();
|
||||
break;
|
||||
case Protocol::PacketType::DeviceStatusV1:
|
||||
status.v1 = packet.statusV1;
|
||||
emit DeviceStatusUpdated();
|
||||
break;
|
||||
case Protocol::PacketType::Ack:
|
||||
emit AckReceived();
|
||||
emit receivedAnswer(TransmissionResult::Ack);
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@
|
|||
#include <QTimer>
|
||||
|
||||
Q_DECLARE_METATYPE(Protocol::Datapoint);
|
||||
Q_DECLARE_METATYPE(Protocol::ManualStatus);
|
||||
Q_DECLARE_METATYPE(Protocol::ManualStatusV1);
|
||||
Q_DECLARE_METATYPE(Protocol::SpectrumAnalyzerResult);
|
||||
Q_DECLARE_METATYPE(Protocol::AmplitudeCorrectionPoint);
|
||||
|
||||
|
|
@ -61,23 +61,27 @@ public:
|
|||
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 SetManual(Protocol::ManualControl manual);
|
||||
bool SetManual(Protocol::ManualControlV1 manual);
|
||||
bool SetIdle();
|
||||
bool SendFirmwareChunk(Protocol::FirmwarePacket &fw);
|
||||
bool SendCommandWithoutPayload(Protocol::PacketType type);
|
||||
QString serial() const;
|
||||
static const Protocol::DeviceInfo& Info();
|
||||
const Protocol::DeviceInfo& Info();
|
||||
static const Protocol::DeviceInfo& Info(Device *dev);
|
||||
Protocol::DeviceStatusV1& StatusV1();
|
||||
static const Protocol::DeviceStatusV1& StatusV1(Device *dev);
|
||||
QString getLastDeviceInfoString();
|
||||
|
||||
// Returns serial numbers of all connected devices
|
||||
static std::set<QString> GetDevices();
|
||||
signals:
|
||||
void DatapointReceived(Protocol::Datapoint);
|
||||
void ManualStatusReceived(Protocol::ManualStatus);
|
||||
void ManualStatusReceived(Protocol::ManualStatusV1);
|
||||
void SpectrumResultReceived(Protocol::SpectrumAnalyzerResult);
|
||||
void AmplitudeCorrectionPointReceived(Protocol::AmplitudeCorrectionPoint);
|
||||
void FrequencyCorrectionReceived(float ppm);
|
||||
void DeviceInfoUpdated();
|
||||
void DeviceStatusUpdated();
|
||||
void ConnectionLost();
|
||||
void AckReceived();
|
||||
void NackReceived();
|
||||
|
|
@ -122,8 +126,11 @@ private:
|
|||
QString m_serial;
|
||||
bool m_connected;
|
||||
std::thread *m_receiveThread;
|
||||
static Protocol::DeviceInfo lastInfo;
|
||||
bool lastInfoValid;
|
||||
Protocol::DeviceInfo info;
|
||||
bool infoValid;
|
||||
union {
|
||||
Protocol::DeviceStatusV1 v1;
|
||||
} status;
|
||||
};
|
||||
|
||||
#endif // DEVICE_H
|
||||
|
|
|
|||
|
|
@ -580,7 +580,7 @@ double ManualControlDialog::getRefPhase()
|
|||
return ui->refphase->text().toDouble();
|
||||
}
|
||||
|
||||
void ManualControlDialog::NewStatus(Protocol::ManualStatus status)
|
||||
void ManualControlDialog::NewStatus(Protocol::ManualStatusV1 status)
|
||||
{
|
||||
// ADC values
|
||||
ui->port1min->setText(QString::number(status.port1min));
|
||||
|
|
@ -616,7 +616,7 @@ void ManualControlDialog::NewStatus(Protocol::ManualStatus status)
|
|||
|
||||
void ManualControlDialog::UpdateDevice()
|
||||
{
|
||||
Protocol::ManualControl m;
|
||||
Protocol::ManualControlV1 m;
|
||||
// Source highband
|
||||
m.SourceHighCE = ui->SourceCE->isChecked();
|
||||
m.SourceHighRFEN = ui->SourceRFEN->isChecked();
|
||||
|
|
|
|||
|
|
@ -103,7 +103,7 @@ public:
|
|||
double getRefPhase();
|
||||
|
||||
public slots:
|
||||
void NewStatus(Protocol::ManualStatus status);
|
||||
void NewStatus(Protocol::ManualStatusV1 status);
|
||||
|
||||
private:
|
||||
void UpdateDevice();
|
||||
|
|
|
|||
|
|
@ -2,11 +2,10 @@
|
|||
|
||||
#include <QSettings>
|
||||
|
||||
Generator::Generator(AppWindow *window)
|
||||
: Mode(window, "Signal Generator")
|
||||
, SCPINode("GENerator")
|
||||
Generator::Generator(AppWindow *window, QString name)
|
||||
: Mode(window, name, "GENerator")
|
||||
{
|
||||
central = new SignalgeneratorWidget(window);
|
||||
central = new SignalgeneratorWidget(window->getDevice(), window);
|
||||
|
||||
auto pref = Preferences::getInstance();
|
||||
|
||||
|
|
|
|||
|
|
@ -5,13 +5,15 @@
|
|||
#include "signalgenwidget.h"
|
||||
#include "scpi.h"
|
||||
|
||||
class Generator : public Mode, public SCPINode
|
||||
class Generator : public Mode
|
||||
{
|
||||
public:
|
||||
Generator(AppWindow *window);
|
||||
Generator(AppWindow *window, QString name = "Signal Generator");
|
||||
void deactivate() override;
|
||||
void initializeDevice() override;
|
||||
|
||||
virtual Type getType() override { return Type::SG;}
|
||||
|
||||
// Nothing to do for now
|
||||
virtual nlohmann::json toJSON() override;
|
||||
virtual void fromJSON(nlohmann::json j) override;
|
||||
|
|
|
|||
|
|
@ -2,9 +2,10 @@
|
|||
|
||||
#include "ui_signalgenwidget.h"
|
||||
|
||||
SignalgeneratorWidget::SignalgeneratorWidget(QWidget *parent) :
|
||||
SignalgeneratorWidget::SignalgeneratorWidget(Device *&dev, QWidget *parent) :
|
||||
QWidget(parent),
|
||||
ui(new Ui::SignalgeneratorWidget)
|
||||
ui(new Ui::SignalgeneratorWidget),
|
||||
dev(dev)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
ui->frequency->setUnit("Hz");
|
||||
|
|
@ -31,16 +32,16 @@ SignalgeneratorWidget::SignalgeneratorWidget(QWidget *parent) :
|
|||
ui->steps->setPrecision(0);
|
||||
|
||||
connect(ui->frequency, &SIUnitEdit::valueChanged, [=](double newval) {
|
||||
if(newval < Device::Info().limits_minFreq) {
|
||||
newval = Device::Info().limits_minFreq;
|
||||
} else if (newval > Device::Info().limits_maxFreq) {
|
||||
newval = Device::Info().limits_maxFreq;
|
||||
if(newval < Device::Info(dev).limits_minFreq) {
|
||||
newval = Device::Info(dev).limits_minFreq;
|
||||
} else if (newval > Device::Info(dev).limits_maxFreq) {
|
||||
newval = Device::Info(dev).limits_maxFreq;
|
||||
}
|
||||
ui->frequency->setValueQuiet(newval);
|
||||
if (newval < ui->span->value()/2)
|
||||
ui->span->setValueQuiet(newval/2);
|
||||
if (newval + ui->span->value()/2 > Device::Info().limits_maxFreq)
|
||||
ui->span->setValueQuiet((Device::Info().limits_maxFreq - newval)*2);
|
||||
if (newval + ui->span->value()/2 > Device::Info(dev).limits_maxFreq)
|
||||
ui->span->setValueQuiet((Device::Info(dev).limits_maxFreq - newval)*2);
|
||||
newval = ui->frequency->value() - ui->span->value()/2;
|
||||
ui->current->setValueQuiet(newval);
|
||||
emit SettingsChanged();
|
||||
|
|
@ -49,8 +50,8 @@ SignalgeneratorWidget::SignalgeneratorWidget(QWidget *parent) :
|
|||
connect(ui->span, &SIUnitEdit::valueChanged, [=](double newval) {
|
||||
if(newval < 0 ) {
|
||||
newval = 0;
|
||||
} else if (newval > Device::Info().limits_maxFreq - Device::Info().limits_minFreq) {
|
||||
newval = Device::Info().limits_maxFreq - Device::Info().limits_minFreq;
|
||||
} else if (newval > Device::Info(dev).limits_maxFreq - Device::Info(dev).limits_minFreq) {
|
||||
newval = Device::Info(dev).limits_maxFreq - Device::Info(dev).limits_minFreq;
|
||||
}
|
||||
ui->span->setValueQuiet(newval);
|
||||
|
||||
|
|
@ -59,8 +60,8 @@ SignalgeneratorWidget::SignalgeneratorWidget(QWidget *parent) :
|
|||
ui->frequency->setValueQuiet(ui->span->value()/2);
|
||||
}
|
||||
newF = ui->frequency->value() + ui->span->value()/2;
|
||||
if (newF > Device::Info().limits_maxFreq) {
|
||||
ui->frequency->setValueQuiet(Device::Info().limits_maxFreq - ui->span->value()/2);
|
||||
if (newF > Device::Info(dev).limits_maxFreq) {
|
||||
ui->frequency->setValueQuiet(Device::Info(dev).limits_maxFreq - ui->span->value()/2);
|
||||
}
|
||||
|
||||
newval = ui->frequency->value() - ui->span->value()/2;
|
||||
|
|
@ -71,8 +72,8 @@ SignalgeneratorWidget::SignalgeneratorWidget(QWidget *parent) :
|
|||
connect(ui->current, &SIUnitEdit::valueChanged, [=](double newval) {
|
||||
if(newval < 0 ) {
|
||||
newval = 0;
|
||||
} else if (newval > Device::Info().limits_maxFreq - Device::Info().limits_minFreq) {
|
||||
newval = Device::Info().limits_maxFreq - Device::Info().limits_minFreq;
|
||||
} else if (newval > Device::Info(dev).limits_maxFreq - Device::Info(dev).limits_minFreq) {
|
||||
newval = Device::Info(dev).limits_maxFreq - Device::Info(dev).limits_minFreq;
|
||||
}
|
||||
ui->current->setValueQuiet(newval);
|
||||
emit SettingsChanged();
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ class SignalgeneratorWidget : public QWidget, public Savable
|
|||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit SignalgeneratorWidget(QWidget *parent = nullptr);
|
||||
explicit SignalgeneratorWidget(Device*&dev, QWidget *parent = nullptr);
|
||||
~SignalgeneratorWidget();
|
||||
|
||||
Protocol::GeneratorSettings getDeviceStatus();
|
||||
|
|
@ -36,6 +36,7 @@ protected:
|
|||
private:
|
||||
Ui::SignalgeneratorWidget *ui;
|
||||
int m_timerId;
|
||||
Device*&dev;
|
||||
};
|
||||
|
||||
#endif // SIGNALGENERATOR_H
|
||||
|
|
|
|||
|
|
@ -45,9 +45,8 @@
|
|||
#include <fstream>
|
||||
#include <QDateTime>
|
||||
|
||||
SpectrumAnalyzer::SpectrumAnalyzer(AppWindow *window)
|
||||
: Mode(window, "Spectrum Analyzer"),
|
||||
SCPINode("SA"),
|
||||
SpectrumAnalyzer::SpectrumAnalyzer(AppWindow *window, QString name)
|
||||
: Mode(window, name, "SA"),
|
||||
central(new TileWidget(traceModel, window))
|
||||
{
|
||||
averages = 1;
|
||||
|
|
@ -422,6 +421,10 @@ using namespace std;
|
|||
|
||||
void SpectrumAnalyzer::NewDatapoint(Protocol::SpectrumAnalyzerResult d)
|
||||
{
|
||||
if(Mode::getActiveMode() != this) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(d.pointNum >= settings.pointNum) {
|
||||
qWarning() << "Ignoring point with too large point number (" << d.pointNum << ")";
|
||||
return;
|
||||
|
|
@ -555,14 +558,14 @@ void SpectrumAnalyzer::SetStopFreq(double freq)
|
|||
void SpectrumAnalyzer::SetCenterFreq(double freq)
|
||||
{
|
||||
auto old_span = settings.f_stop - settings.f_start;
|
||||
if (freq - old_span / 2 <= Device::Info().limits_minFreq) {
|
||||
if (freq - old_span / 2 <= Device::Info(window->getDevice()).limits_minFreq) {
|
||||
// would shift start frequency below minimum
|
||||
settings.f_start = 0;
|
||||
settings.f_stop = 2 * freq;
|
||||
} else if(freq + old_span / 2 >= Device::Info().limits_maxFreq) {
|
||||
} else if(freq + old_span / 2 >= Device::Info(window->getDevice()).limits_maxFreq) {
|
||||
// would shift stop frequency above maximum
|
||||
settings.f_start = 2 * freq - Device::Info().limits_maxFreq;
|
||||
settings.f_stop = Device::Info().limits_maxFreq;
|
||||
settings.f_start = 2 * freq - Device::Info(window->getDevice()).limits_maxFreq;
|
||||
settings.f_stop = Device::Info(window->getDevice()).limits_maxFreq;
|
||||
} else {
|
||||
settings.f_start = freq - old_span / 2;
|
||||
settings.f_stop = freq + old_span / 2;
|
||||
|
|
@ -573,14 +576,14 @@ void SpectrumAnalyzer::SetCenterFreq(double freq)
|
|||
void SpectrumAnalyzer::SetSpan(double span)
|
||||
{
|
||||
auto old_center = (settings.f_start + settings.f_stop) / 2;
|
||||
if(old_center < Device::Info().limits_minFreq + span / 2) {
|
||||
if(old_center < Device::Info(window->getDevice()).limits_minFreq + span / 2) {
|
||||
// would shift start frequency below minimum
|
||||
settings.f_start = Device::Info().limits_minFreq;
|
||||
settings.f_stop = Device::Info().limits_minFreq + span;
|
||||
} else if(old_center > Device::Info().limits_maxFreq - span / 2) {
|
||||
settings.f_start = Device::Info(window->getDevice()).limits_minFreq;
|
||||
settings.f_stop = Device::Info(window->getDevice()).limits_minFreq + span;
|
||||
} else if(old_center > Device::Info(window->getDevice()).limits_maxFreq - span / 2) {
|
||||
// would shift stop frequency above maximum
|
||||
settings.f_start = Device::Info().limits_maxFreq - span;
|
||||
settings.f_stop = Device::Info().limits_maxFreq;
|
||||
settings.f_start = Device::Info(window->getDevice()).limits_maxFreq - span;
|
||||
settings.f_stop = Device::Info(window->getDevice()).limits_maxFreq;
|
||||
} else {
|
||||
settings.f_start = old_center - span / 2;
|
||||
settings.f_stop = settings.f_start + span;
|
||||
|
|
@ -590,8 +593,8 @@ void SpectrumAnalyzer::SetSpan(double span)
|
|||
|
||||
void SpectrumAnalyzer::SetFullSpan()
|
||||
{
|
||||
settings.f_start = Device::Info().limits_minFreq;
|
||||
settings.f_stop = Device::Info().limits_maxFreq;
|
||||
settings.f_start = Device::Info(window->getDevice()).limits_minFreq;
|
||||
settings.f_stop = Device::Info(window->getDevice()).limits_maxFreq;
|
||||
ConstrainAndUpdateFrequencies();
|
||||
}
|
||||
|
||||
|
|
@ -619,10 +622,10 @@ void SpectrumAnalyzer::SpanZoomOut()
|
|||
|
||||
void SpectrumAnalyzer::SetRBW(double bandwidth)
|
||||
{
|
||||
if(bandwidth > Device::Info().limits_maxRBW) {
|
||||
bandwidth = Device::Info().limits_maxRBW;
|
||||
} else if(bandwidth < Device::Info().limits_minRBW) {
|
||||
bandwidth = Device::Info().limits_minRBW;
|
||||
if(bandwidth > Device::Info(window->getDevice()).limits_maxRBW) {
|
||||
bandwidth = Device::Info(window->getDevice()).limits_maxRBW;
|
||||
} else if(bandwidth < Device::Info(window->getDevice()).limits_minRBW) {
|
||||
bandwidth = Device::Info(window->getDevice()).limits_minRBW;
|
||||
}
|
||||
settings.RBW = bandwidth;
|
||||
emit RBWChanged(settings.RBW);
|
||||
|
|
@ -690,10 +693,10 @@ void SpectrumAnalyzer::SetTGPort(int port)
|
|||
|
||||
void SpectrumAnalyzer::SetTGLevel(double level)
|
||||
{
|
||||
if(level > Device::Info().limits_cdbm_max / 100.0) {
|
||||
level = Device::Info().limits_cdbm_max / 100.0;
|
||||
} else if(level < Device::Info().limits_cdbm_min / 100.0) {
|
||||
level = Device::Info().limits_cdbm_min / 100.0;
|
||||
if(level > Device::Info(window->getDevice()).limits_cdbm_max / 100.0) {
|
||||
level = Device::Info(window->getDevice()).limits_cdbm_max / 100.0;
|
||||
} else if(level < Device::Info(window->getDevice()).limits_cdbm_min / 100.0) {
|
||||
level = Device::Info(window->getDevice()).limits_cdbm_min / 100.0;
|
||||
}
|
||||
emit TGLevelChanged(level);
|
||||
settings.trackingPower = level * 100;
|
||||
|
|
@ -1015,24 +1018,24 @@ void SpectrumAnalyzer::UpdateAverageCount()
|
|||
|
||||
void SpectrumAnalyzer::ConstrainAndUpdateFrequencies()
|
||||
{
|
||||
if(settings.f_stop > Device::Info().limits_maxFreq) {
|
||||
settings.f_stop = Device::Info().limits_maxFreq;
|
||||
if(settings.f_stop > Device::Info(window->getDevice()).limits_maxFreq) {
|
||||
settings.f_stop = Device::Info(window->getDevice()).limits_maxFreq;
|
||||
}
|
||||
if(settings.f_start > settings.f_stop) {
|
||||
settings.f_start = settings.f_stop;
|
||||
}
|
||||
if(settings.f_start < Device::Info().limits_minFreq) {
|
||||
settings.f_start = Device::Info().limits_minFreq;
|
||||
if(settings.f_start < Device::Info(window->getDevice()).limits_minFreq) {
|
||||
settings.f_start = Device::Info(window->getDevice()).limits_minFreq;
|
||||
}
|
||||
|
||||
bool trackingOffset_limited = false;
|
||||
if(settings.f_stop + settings.trackingGeneratorOffset > Device::Info().limits_maxFreq) {
|
||||
if(settings.f_stop + settings.trackingGeneratorOffset > Device::Info(window->getDevice()).limits_maxFreq) {
|
||||
trackingOffset_limited = true;
|
||||
settings.trackingGeneratorOffset = Device::Info().limits_maxFreq - settings.f_stop;
|
||||
settings.trackingGeneratorOffset = Device::Info(window->getDevice()).limits_maxFreq - settings.f_stop;
|
||||
}
|
||||
if((long) settings.f_start + settings.trackingGeneratorOffset < (long) Device::Info().limits_minFreq) {
|
||||
if((long) settings.f_start + settings.trackingGeneratorOffset < (long) Device::Info(window->getDevice()).limits_minFreq) {
|
||||
trackingOffset_limited = true;
|
||||
settings.trackingGeneratorOffset = Device::Info().limits_minFreq - settings.f_start;
|
||||
settings.trackingGeneratorOffset = Device::Info(window->getDevice()).limits_minFreq - settings.f_start;
|
||||
}
|
||||
if(trackingOffset_limited) {
|
||||
InformationBox::ShowMessage("Warning", "The selected tracking generator offset is not reachable for all frequencies with the current span. "
|
||||
|
|
|
|||
|
|
@ -12,15 +12,17 @@
|
|||
#include <QComboBox>
|
||||
#include <QCheckBox>
|
||||
|
||||
class SpectrumAnalyzer : public Mode, public SCPINode
|
||||
class SpectrumAnalyzer : public Mode
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
SpectrumAnalyzer(AppWindow *window);
|
||||
SpectrumAnalyzer(AppWindow *window, QString name = "Spectrum Analyzer");
|
||||
|
||||
void deactivate() override;
|
||||
void initializeDevice() override;
|
||||
|
||||
virtual Type getType() override { return Type::SA;}
|
||||
|
||||
// Only save/load user changeable stuff, no need to save the widgets/mode name etc.
|
||||
virtual nlohmann::json toJSON() override;
|
||||
virtual void fromJSON(nlohmann::json j) override;
|
||||
|
|
|
|||
|
|
@ -51,9 +51,8 @@
|
|||
#include <QErrorMessage>
|
||||
#include <QDebug>
|
||||
|
||||
VNA::VNA(AppWindow *window)
|
||||
: Mode(window, "Vector Network Analyzer"),
|
||||
SCPINode("VNA"),
|
||||
VNA::VNA(AppWindow *window, QString name)
|
||||
: Mode(window, name, "VNA"),
|
||||
deembedding(traceModel),
|
||||
deembedding_active(false),
|
||||
central(new TileWidget(traceModel))
|
||||
|
|
@ -790,6 +789,11 @@ using namespace std;
|
|||
|
||||
void VNA::NewDatapoint(Protocol::Datapoint d)
|
||||
{
|
||||
if(Mode::getActiveMode() != this) {
|
||||
// ignore
|
||||
return;
|
||||
}
|
||||
|
||||
if(changingSettings) {
|
||||
// already setting new sweep settings, ignore incoming points from old settings
|
||||
return;
|
||||
|
|
@ -997,14 +1001,14 @@ void VNA::SetStopFreq(double freq)
|
|||
void VNA::SetCenterFreq(double freq)
|
||||
{
|
||||
auto old_span = settings.Freq.stop - settings.Freq.start;
|
||||
if (freq - old_span / 2 <= Device::Info().limits_minFreq) {
|
||||
if (freq - old_span / 2 <= Device::Info(window->getDevice()).limits_minFreq) {
|
||||
// would shift start frequency below minimum
|
||||
settings.Freq.start = 0;
|
||||
settings.Freq.stop = 2 * freq;
|
||||
} else if(freq + old_span / 2 >= Device::Info().limits_maxFreq) {
|
||||
} else if(freq + old_span / 2 >= Device::Info(window->getDevice()).limits_maxFreq) {
|
||||
// would shift stop frequency above maximum
|
||||
settings.Freq.start = 2 * freq - Device::Info().limits_maxFreq;
|
||||
settings.Freq.stop = Device::Info().limits_maxFreq;
|
||||
settings.Freq.start = 2 * freq - Device::Info(window->getDevice()).limits_maxFreq;
|
||||
settings.Freq.stop = Device::Info(window->getDevice()).limits_maxFreq;
|
||||
} else {
|
||||
settings.Freq.start = freq - old_span / 2;
|
||||
settings.Freq.stop = freq + old_span / 2;
|
||||
|
|
@ -1014,12 +1018,12 @@ void VNA::SetCenterFreq(double freq)
|
|||
|
||||
void VNA::SetSpan(double span)
|
||||
{
|
||||
auto maxFreq = Preferences::getInstance().Acquisition.harmonicMixing ? Device::Info().limits_maxFreqHarmonic : Device::Info().limits_maxFreq;
|
||||
auto maxFreq = Preferences::getInstance().Acquisition.harmonicMixing ? Device::Info(window->getDevice()).limits_maxFreqHarmonic : Device::Info(window->getDevice()).limits_maxFreq;
|
||||
auto old_center = (settings.Freq.start + settings.Freq.stop) / 2;
|
||||
if(old_center < Device::Info().limits_minFreq + span / 2) {
|
||||
if(old_center < Device::Info(window->getDevice()).limits_minFreq + span / 2) {
|
||||
// would shift start frequency below minimum
|
||||
settings.Freq.start = Device::Info().limits_minFreq;
|
||||
settings.Freq.stop = Device::Info().limits_minFreq + span;
|
||||
settings.Freq.start = Device::Info(window->getDevice()).limits_minFreq;
|
||||
settings.Freq.stop = Device::Info(window->getDevice()).limits_minFreq + span;
|
||||
} else if(old_center > maxFreq - span / 2) {
|
||||
// would shift stop frequency above maximum
|
||||
settings.Freq.start = maxFreq - span;
|
||||
|
|
@ -1033,8 +1037,8 @@ void VNA::SetSpan(double span)
|
|||
|
||||
void VNA::SetFullSpan()
|
||||
{
|
||||
settings.Freq.start = Device::Info().limits_minFreq;
|
||||
settings.Freq.stop = Device::Info().limits_maxFreq;
|
||||
settings.Freq.start = Device::Info(window->getDevice()).limits_minFreq;
|
||||
settings.Freq.stop = Device::Info(window->getDevice()).limits_maxFreq;
|
||||
ConstrainAndUpdateFrequencies();
|
||||
}
|
||||
|
||||
|
|
@ -1072,10 +1076,10 @@ void VNA::SetLogSweep(bool log)
|
|||
|
||||
void VNA::SetSourceLevel(double level)
|
||||
{
|
||||
if(level > Device::Info().limits_cdbm_max / 100.0) {
|
||||
level = Device::Info().limits_cdbm_max / 100.0;
|
||||
} else if(level < Device::Info().limits_cdbm_min / 100.0) {
|
||||
level = Device::Info().limits_cdbm_min / 100.0;
|
||||
if(level > Device::Info(window->getDevice()).limits_cdbm_max / 100.0) {
|
||||
level = Device::Info(window->getDevice()).limits_cdbm_max / 100.0;
|
||||
} else if(level < Device::Info(window->getDevice()).limits_cdbm_min / 100.0) {
|
||||
level = Device::Info(window->getDevice()).limits_cdbm_min / 100.0;
|
||||
}
|
||||
emit sourceLevelChanged(level);
|
||||
settings.Freq.excitation_power = level;
|
||||
|
|
@ -1105,15 +1109,15 @@ void VNA::SetPowerSweepFrequency(double freq)
|
|||
|
||||
void VNA::SetPoints(unsigned int points)
|
||||
{
|
||||
unsigned int maxPoints = Preferences::getInstance().Acquisition.allowSegmentedSweep ? UINT16_MAX : Device::Info().limits_maxPoints;
|
||||
unsigned int maxPoints = Preferences::getInstance().Acquisition.allowSegmentedSweep ? UINT16_MAX : Device::Info(window->getDevice()).limits_maxPoints;
|
||||
if(points > maxPoints) {
|
||||
points = maxPoints;
|
||||
} else if (points < 2) {
|
||||
points = 2;
|
||||
}
|
||||
if (points > Device::Info().limits_maxPoints) {
|
||||
if (points > Device::Info(window->getDevice()).limits_maxPoints) {
|
||||
// needs segmented sweep
|
||||
settings.segments = ceil((double) points / Device::Info().limits_maxPoints);
|
||||
settings.segments = ceil((double) points / Device::Info(window->getDevice()).limits_maxPoints);
|
||||
settings.activeSegment = 0;
|
||||
} else {
|
||||
// can fit all points into one segment
|
||||
|
|
@ -1127,10 +1131,10 @@ void VNA::SetPoints(unsigned int points)
|
|||
|
||||
void VNA::SetIFBandwidth(double bandwidth)
|
||||
{
|
||||
if(bandwidth > Device::Info().limits_maxIFBW) {
|
||||
bandwidth = Device::Info().limits_maxIFBW;
|
||||
} else if(bandwidth < Device::Info().limits_minIFBW) {
|
||||
bandwidth = Device::Info().limits_minIFBW;
|
||||
if(bandwidth > Device::Info(window->getDevice()).limits_maxIFBW) {
|
||||
bandwidth = Device::Info(window->getDevice()).limits_maxIFBW;
|
||||
} else if(bandwidth < Device::Info(window->getDevice()).limits_minIFBW) {
|
||||
bandwidth = Device::Info(window->getDevice()).limits_minIFBW;
|
||||
}
|
||||
settings.bandwidth = bandwidth;
|
||||
emit IFBandwidthChanged(settings.bandwidth);
|
||||
|
|
@ -1478,9 +1482,9 @@ void VNA::ConstrainAndUpdateFrequencies()
|
|||
auto pref = Preferences::getInstance();
|
||||
double maxFreq;
|
||||
if(pref.Acquisition.harmonicMixing) {
|
||||
maxFreq = Device::Info().limits_maxFreqHarmonic;
|
||||
maxFreq = Device::Info(window->getDevice()).limits_maxFreqHarmonic;
|
||||
} else {
|
||||
maxFreq = Device::Info().limits_maxFreq;
|
||||
maxFreq = Device::Info(window->getDevice()).limits_maxFreq;
|
||||
}
|
||||
if(settings.Freq.stop > maxFreq) {
|
||||
settings.Freq.stop = maxFreq;
|
||||
|
|
@ -1488,8 +1492,8 @@ void VNA::ConstrainAndUpdateFrequencies()
|
|||
if(settings.Freq.start > settings.Freq.stop) {
|
||||
settings.Freq.start = settings.Freq.stop;
|
||||
}
|
||||
if(settings.Freq.start < Device::Info().limits_minFreq) {
|
||||
settings.Freq.start = Device::Info().limits_minFreq;
|
||||
if(settings.Freq.start < Device::Info(window->getDevice()).limits_minFreq) {
|
||||
settings.Freq.start = Device::Info(window->getDevice()).limits_minFreq;
|
||||
}
|
||||
emit startFreqChanged(settings.Freq.start);
|
||||
emit stopFreqChanged(settings.Freq.stop);
|
||||
|
|
|
|||
|
|
@ -13,17 +13,19 @@
|
|||
#include <QWidget>
|
||||
#include <functional>
|
||||
|
||||
class VNA : public Mode, public SCPINode
|
||||
class VNA : public Mode
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
VNA(AppWindow *window);
|
||||
VNA(AppWindow *window, QString name = "Vector Network Analyzer");
|
||||
|
||||
void deactivate() override;
|
||||
void initializeDevice() override;
|
||||
void deviceDisconnected() override;
|
||||
void shutdown() override;
|
||||
|
||||
virtual Type getType() override { return Type::VNA;}
|
||||
|
||||
// Only save/load user changeable stuff, no need to save the widgets/mode name etc.
|
||||
virtual nlohmann::json toJSON() override;
|
||||
virtual void fromJSON(nlohmann::json j) override;
|
||||
|
|
|
|||
|
|
@ -134,9 +134,9 @@ AppWindow::AppWindow(QWidget *parent)
|
|||
// Create GUI modes
|
||||
central = new QStackedWidget;
|
||||
setCentralWidget(central);
|
||||
vna = new VNA(this);
|
||||
generator = new Generator(this);
|
||||
spectrumAnalyzer = new SpectrumAnalyzer(this);
|
||||
auto vna = new VNA(this);
|
||||
auto generator = new Generator(this);
|
||||
auto spectrumAnalyzer = new SpectrumAnalyzer(this);
|
||||
|
||||
// UI connections
|
||||
connect(ui->actionUpdate_Device_List, &QAction::triggered, this, &AppWindow::UpdateDeviceList);
|
||||
|
|
@ -235,7 +235,7 @@ AppWindow::AppWindow(QWidget *parent)
|
|||
vna->activate();
|
||||
|
||||
qRegisterMetaType<Protocol::Datapoint>("Datapoint");
|
||||
qRegisterMetaType<Protocol::ManualStatus>("Manual");
|
||||
qRegisterMetaType<Protocol::ManualStatusV1>("ManualV1");
|
||||
qRegisterMetaType<Protocol::SpectrumAnalyzerResult>("SpectrumAnalyzerResult");
|
||||
qRegisterMetaType<Protocol::AmplitudeCorrectionPoint>("AmplitudeCorrection");
|
||||
|
||||
|
|
@ -278,9 +278,9 @@ void AppWindow::closeEvent(QCloseEvent *event)
|
|||
if(pref.Startup.UseSetupFile && pref.Startup.AutosaveSetupFile) {
|
||||
SaveSetup(pref.Startup.SetupFile);
|
||||
}
|
||||
vna->shutdown();
|
||||
generator->shutdown();
|
||||
spectrumAnalyzer->shutdown();
|
||||
for(auto m : Mode::getModes()) {
|
||||
m->shutdown();
|
||||
}
|
||||
delete device;
|
||||
QSettings settings;
|
||||
settings.setValue("geometry", saveGeometry());
|
||||
|
|
@ -309,7 +309,7 @@ bool AppWindow::ConnectToDevice(QString serial)
|
|||
UpdateStatusBar(AppWindow::DeviceStatusBar::Connected);
|
||||
connect(device, &Device::LogLineReceived, &deviceLog, &DeviceLog::addLine);
|
||||
connect(device, &Device::ConnectionLost, this, &AppWindow::DeviceConnectionLost);
|
||||
connect(device, &Device::DeviceInfoUpdated, this, &AppWindow::DeviceInfoUpdated);
|
||||
connect(device, &Device::DeviceStatusUpdated, this, &AppWindow::DeviceStatusUpdated);
|
||||
connect(device, &Device::NeedsFirmwareUpdate, this, &AppWindow::DeviceNeedsUpdate);
|
||||
ui->actionDisconnect->setEnabled(true);
|
||||
ui->actionManual_Control->setEnabled(true);
|
||||
|
|
@ -465,7 +465,7 @@ void AppWindow::SetupSCPI()
|
|||
}
|
||||
return "";
|
||||
}, [=](QStringList) -> QString {
|
||||
switch(Device::Info().extRefInUse) {
|
||||
switch(Device::StatusV1(getDevice()).extRefInUse) {
|
||||
case 0: return "INT";
|
||||
case 1: return "EXT";
|
||||
default: return "ERROR";
|
||||
|
|
@ -475,88 +475,89 @@ void AppWindow::SetupSCPI()
|
|||
if (params.size() != 1) {
|
||||
return "ERROR";
|
||||
}
|
||||
Mode *mode = nullptr;
|
||||
if (params[0] == "VNA") {
|
||||
vna->activate();
|
||||
mode = Mode::findFirstOfType(Mode::Type::VNA);
|
||||
} else if(params[0] == "GEN") {
|
||||
generator->activate();
|
||||
mode = Mode::findFirstOfType(Mode::Type::SG);
|
||||
} else if(params[0] == "SA") {
|
||||
spectrumAnalyzer->activate();
|
||||
mode = Mode::findFirstOfType(Mode::Type::SA);
|
||||
} else {
|
||||
return "INVALID MDOE";
|
||||
}
|
||||
return "";
|
||||
}, [=](QStringList) -> QString {
|
||||
auto active = Mode::getActiveMode();
|
||||
if(active == vna) {
|
||||
return "VNA";
|
||||
} else if(active == generator) {
|
||||
return "GEN";
|
||||
} else if(active == spectrumAnalyzer) {
|
||||
return "SA";
|
||||
if(mode) {
|
||||
mode->activate();
|
||||
return "";
|
||||
} else {
|
||||
return "ERROR";
|
||||
}
|
||||
}, [=](QStringList) -> QString {
|
||||
auto active = Mode::getActiveMode();
|
||||
if(active) {
|
||||
switch(active->getType()) {
|
||||
case Mode::Type::VNA: return "VNA";
|
||||
case Mode::Type::SG: return "SG";
|
||||
case Mode::Type::SA: return "SA";
|
||||
}
|
||||
}
|
||||
return "ERROR";
|
||||
}));
|
||||
auto scpi_status = new SCPINode("STAtus");
|
||||
scpi_dev->add(scpi_status);
|
||||
scpi_status->add(new SCPICommand("UNLOcked", nullptr, [=](QStringList){
|
||||
bool locked = Device::Info().source_locked && Device::Info().LO1_locked;
|
||||
bool locked = Device::StatusV1(getDevice()).source_locked && Device::StatusV1(getDevice()).LO1_locked;
|
||||
return locked ? "FALSE" : "TRUE";
|
||||
}));
|
||||
scpi_status->add(new SCPICommand("ADCOVERload", nullptr, [=](QStringList){
|
||||
return Device::Info().ADC_overload ? "TRUE" : "FALSE";
|
||||
return Device::StatusV1(getDevice()).ADC_overload ? "TRUE" : "FALSE";
|
||||
}));
|
||||
scpi_status->add(new SCPICommand("UNLEVel", nullptr, [=](QStringList){
|
||||
return Device::Info().unlevel ? "TRUE" : "FALSE";
|
||||
return Device::StatusV1(getDevice()).unlevel ? "TRUE" : "FALSE";
|
||||
}));
|
||||
auto scpi_info = new SCPINode("INFo");
|
||||
scpi_dev->add(scpi_info);
|
||||
scpi_info->add(new SCPICommand("FWREVision", nullptr, [=](QStringList){
|
||||
return QString::number(Device::Info().FW_major)+"."+QString::number(Device::Info().FW_minor)+"."+QString::number(Device::Info().FW_patch);
|
||||
return QString::number(Device::Info(getDevice()).FW_major)+"."+QString::number(Device::Info(getDevice()).FW_minor)+"."+QString::number(Device::Info(getDevice()).FW_patch);
|
||||
}));
|
||||
scpi_info->add(new SCPICommand("HWREVision", nullptr, [=](QStringList){
|
||||
return QString(Device::Info().HW_Revision);
|
||||
return QString(Device::Info(getDevice()).HW_Revision);
|
||||
}));
|
||||
scpi_info->add(new SCPICommand("TEMPeratures", nullptr, [=](QStringList){
|
||||
return QString::number(Device::Info().temp_source)+"/"+QString::number(Device::Info().temp_LO1)+"/"+QString::number(Device::Info().temp_MCU);
|
||||
return QString::number(Device::StatusV1(getDevice()).temp_source)+"/"+QString::number(Device::StatusV1(getDevice()).temp_LO1)+"/"+QString::number(Device::StatusV1(getDevice()).temp_MCU);
|
||||
}));
|
||||
auto scpi_limits = new SCPINode("LIMits");
|
||||
scpi_info->add(scpi_limits);
|
||||
scpi_limits->add(new SCPICommand("MINFrequency", nullptr, [=](QStringList){
|
||||
return QString::number(Device::Info().limits_minFreq);
|
||||
return QString::number(Device::Info(getDevice()).limits_minFreq);
|
||||
}));
|
||||
scpi_limits->add(new SCPICommand("MAXFrequency", nullptr, [=](QStringList){
|
||||
return QString::number(Device::Info().limits_maxFreq);
|
||||
return QString::number(Device::Info(getDevice()).limits_maxFreq);
|
||||
}));
|
||||
scpi_limits->add(new SCPICommand("MINIFBW", nullptr, [=](QStringList){
|
||||
return QString::number(Device::Info().limits_minIFBW);
|
||||
return QString::number(Device::Info(getDevice()).limits_minIFBW);
|
||||
}));
|
||||
scpi_limits->add(new SCPICommand("MAXIFBW", nullptr, [=](QStringList){
|
||||
return QString::number(Device::Info().limits_maxIFBW);
|
||||
return QString::number(Device::Info(getDevice()).limits_maxIFBW);
|
||||
}));
|
||||
scpi_limits->add(new SCPICommand("MAXPoints", nullptr, [=](QStringList){
|
||||
return QString::number(Device::Info().limits_maxPoints);
|
||||
return QString::number(Device::Info(getDevice()).limits_maxPoints);
|
||||
}));
|
||||
scpi_limits->add(new SCPICommand("MINPOWer", nullptr, [=](QStringList){
|
||||
return QString::number(Device::Info().limits_cdbm_min / 100.0);
|
||||
return QString::number(Device::Info(getDevice()).limits_cdbm_min / 100.0);
|
||||
}));
|
||||
scpi_limits->add(new SCPICommand("MAXPOWer", nullptr, [=](QStringList){
|
||||
return QString::number(Device::Info().limits_cdbm_max / 100.0);
|
||||
return QString::number(Device::Info(getDevice()).limits_cdbm_max / 100.0);
|
||||
}));
|
||||
scpi_limits->add(new SCPICommand("MINRBW", nullptr, [=](QStringList){
|
||||
return QString::number(Device::Info().limits_minRBW);
|
||||
return QString::number(Device::Info(getDevice()).limits_minRBW);
|
||||
}));
|
||||
scpi_limits->add(new SCPICommand("MAXRBW", nullptr, [=](QStringList){
|
||||
return QString::number(Device::Info().limits_maxRBW);
|
||||
return QString::number(Device::Info(getDevice()).limits_maxRBW);
|
||||
}));
|
||||
scpi_limits->add(new SCPICommand("MAXHARMonicfrequency", nullptr, [=](QStringList){
|
||||
return QString::number(Device::Info().limits_maxFreqHarmonic);
|
||||
return QString::number(Device::Info(getDevice()).limits_maxFreqHarmonic);
|
||||
}));
|
||||
|
||||
scpi.add(vna);
|
||||
scpi.add(generator);
|
||||
scpi.add(spectrumAnalyzer);
|
||||
|
||||
auto scpi_manual = new SCPINode("MANual");
|
||||
scpi_manual->add(new SCPICommand("STArt",[=](QStringList) -> QString {
|
||||
StartManualControl();
|
||||
|
|
@ -798,6 +799,11 @@ void AppWindow::StopTCPServer()
|
|||
server = nullptr;
|
||||
}
|
||||
|
||||
SCPI* AppWindow::getSCPI()
|
||||
{
|
||||
return &scpi;
|
||||
}
|
||||
|
||||
int AppWindow::UpdateDeviceList()
|
||||
{
|
||||
deviceActionGroup->setExclusive(true);
|
||||
|
|
@ -918,7 +924,7 @@ void AppWindow::DeviceNeedsUpdate(int reported, int expected)
|
|||
}
|
||||
}
|
||||
|
||||
void AppWindow::DeviceInfoUpdated()
|
||||
void AppWindow::DeviceStatusUpdated()
|
||||
{
|
||||
UpdateStatusBar(DeviceStatusBar::Updated);
|
||||
}
|
||||
|
|
@ -963,10 +969,18 @@ void AppWindow::SaveSetup(QString filename)
|
|||
nlohmann::json AppWindow::SaveSetup()
|
||||
{
|
||||
nlohmann::json j;
|
||||
j["activeMode"] = Mode::getActiveMode()->getName().toStdString();
|
||||
j["VNA"] = vna->toJSON();
|
||||
j["Generator"] = generator->toJSON();
|
||||
j["SpectrumAnalyzer"] = spectrumAnalyzer->toJSON();
|
||||
nlohmann::json jm;
|
||||
for(auto m : Mode::getModes()) {
|
||||
nlohmann::json jmode;
|
||||
jmode["type"] = Mode::TypeToName(m->getType()).toStdString();
|
||||
jmode["name"] = m->getName().toStdString();
|
||||
jmode["settings"] = m->toJSON();
|
||||
jm.push_back(jmode);
|
||||
}
|
||||
j["Modes"] = jm;
|
||||
if(Mode::getActiveMode()) {
|
||||
j["activeMode"] = Mode::getActiveMode()->getName().toStdString();
|
||||
}
|
||||
nlohmann::json ref;
|
||||
ref["Mode"] = toolbars.reference.type->currentText().toStdString();
|
||||
ref["Output"] = toolbars.reference.outFreq->currentText().toStdString();
|
||||
|
|
@ -1003,20 +1017,36 @@ void AppWindow::LoadSetup(nlohmann::json j)
|
|||
toolbars.reference.type->setCurrentText(QString::fromStdString(j["Reference"].value("Mode", "Int")));
|
||||
toolbars.reference.outFreq->setCurrentText(QString::fromStdString(j["Reference"].value("Output", "Off")));
|
||||
}
|
||||
while(Mode::getModes().size() > 0) {
|
||||
delete Mode::getModes()[0];
|
||||
}
|
||||
|
||||
// old style VNA/Generator/Spectrum Analyzer settings
|
||||
if(j.contains("VNA")) {
|
||||
auto vna = new VNA(this);
|
||||
vna->fromJSON(j["VNA"]);
|
||||
}
|
||||
if(j.contains("Generator")) {
|
||||
auto generator = new Generator(this);
|
||||
generator->fromJSON(j["Generator"]);
|
||||
}
|
||||
if(j.contains("SpectrumAnalyzer")) {
|
||||
auto spectrumAnalyzer = new SpectrumAnalyzer(this);
|
||||
spectrumAnalyzer->fromJSON(j["SpectrumAnalyzer"]);
|
||||
}
|
||||
if(j.contains("Modes")) {
|
||||
for(auto jm : j["Modes"]) {
|
||||
auto type = Mode::TypeFromName(QString::fromStdString(jm.value("type", "Invalid")));
|
||||
if(type != Mode::Type::Last && jm.contains("settings")) {
|
||||
auto m = Mode::createNew(this, QString::fromStdString(jm.value("name", "")), type);
|
||||
m->fromJSON(jm["settings"]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// activate the correct mode
|
||||
QString modeName = QString::fromStdString(j.value("activeMode", ""));
|
||||
std::vector<Mode*> modes = {vna, generator, spectrumAnalyzer};
|
||||
for(auto m : modes) {
|
||||
for(auto m : Mode::getModes()) {
|
||||
if(m->getName() == modeName) {
|
||||
m->activate();
|
||||
break;
|
||||
|
|
@ -1024,7 +1054,7 @@ void AppWindow::LoadSetup(nlohmann::json j)
|
|||
}
|
||||
}
|
||||
|
||||
Device *AppWindow::getDevice() const
|
||||
Device *&AppWindow::getDevice()
|
||||
{
|
||||
return device;
|
||||
}
|
||||
|
|
@ -1104,14 +1134,12 @@ void AppWindow::UpdateStatusBar(DeviceStatusBar status)
|
|||
break;
|
||||
case DeviceStatusBar::Updated:
|
||||
lDeviceInfo.setText(device->getLastDeviceInfoString());
|
||||
lADCOverload.setVisible(device->Info().ADC_overload);
|
||||
lUnlevel.setVisible(device->Info().unlevel);
|
||||
lUnlock.setVisible(!device->Info().LO1_locked || !device->Info().source_locked);
|
||||
lADCOverload.setVisible(device->StatusV1().ADC_overload);
|
||||
lUnlevel.setVisible(device->StatusV1().unlevel);
|
||||
lUnlock.setVisible(!device->StatusV1().LO1_locked || !device->StatusV1().source_locked);
|
||||
break;
|
||||
default:
|
||||
// invalid status
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,13 +41,15 @@ public:
|
|||
|
||||
Ui::MainWindow *getUi() const;
|
||||
QStackedWidget *getCentral() const;
|
||||
Device *getDevice() const;
|
||||
Device*&getDevice();
|
||||
|
||||
const QString& getAppVersion() const;
|
||||
const QString& getAppGitHash() const;
|
||||
|
||||
static bool showGUI();
|
||||
|
||||
SCPI* getSCPI();
|
||||
|
||||
protected:
|
||||
void closeEvent(QCloseEvent *event) override;
|
||||
private slots:
|
||||
|
|
@ -59,7 +61,7 @@ private slots:
|
|||
void UpdateAcquisitionFrequencies();
|
||||
void StartFirmwareUpdateDialog();
|
||||
void DeviceNeedsUpdate(int reported, int expected);
|
||||
void DeviceInfoUpdated();
|
||||
void DeviceStatusUpdated();
|
||||
void SourceCalibrationDialog();
|
||||
void ReceiverCalibrationDialog();
|
||||
void FrequencyCalibrationDialog();
|
||||
|
|
@ -100,11 +102,6 @@ private:
|
|||
|
||||
ManualControlDialog *manual;
|
||||
|
||||
// Modes
|
||||
VNA *vna;
|
||||
Generator *generator;
|
||||
SpectrumAnalyzer *spectrumAnalyzer;
|
||||
|
||||
// Status bar widgets
|
||||
QLabel lConnectionStatus;
|
||||
QLabel lDeviceInfo;
|
||||
|
|
|
|||
|
|
@ -1,44 +1,115 @@
|
|||
#include "mode.h"
|
||||
|
||||
#include "Generator/generator.h"
|
||||
#include "VNA/vna.h"
|
||||
#include "SpectrumAnalyzer/spectrumanalyzer.h"
|
||||
#include "CustomWidgets/informationbox.h"
|
||||
|
||||
#include "ui_main.h"
|
||||
|
||||
#include <QPushButton>
|
||||
#include <QSettings>
|
||||
#include <QDebug>
|
||||
#include <QFileDialog>
|
||||
#include <QInputDialog>
|
||||
|
||||
std::vector<Mode*> Mode::modes;
|
||||
Mode* Mode::activeMode = nullptr;
|
||||
QTabBar* Mode::tabbar = nullptr;
|
||||
QWidget* Mode::cornerWidget = nullptr;
|
||||
QButtonGroup* Mode::modeButtonGroup = nullptr;
|
||||
//QButtonGroup* Mode::modeButtonGroup = nullptr;
|
||||
|
||||
Mode::Mode(AppWindow *window, QString name)
|
||||
Mode::Mode(AppWindow *window, QString name, QString SCPIname)
|
||||
: QObject(window),
|
||||
SCPINode(SCPIname),
|
||||
window(window),
|
||||
name(name),
|
||||
central(nullptr)
|
||||
{
|
||||
{
|
||||
if(!nameAllowed(name)) {
|
||||
throw std::runtime_error("Unable to create mode, name already taken");
|
||||
}
|
||||
// Create mode switch button
|
||||
auto modeSwitch = new QPushButton(name);
|
||||
modeSwitch->setCheckable(true);
|
||||
modeSwitch->setMaximumHeight(window->menuBar()->height());
|
||||
if(!cornerWidget) {
|
||||
// this is the first created mode, initialize corner widget and set this mode as active
|
||||
modeSwitch->setChecked(true);
|
||||
cornerWidget = new QWidget;
|
||||
cornerWidget = new QWidget();
|
||||
cornerWidget->setLayout(new QHBoxLayout);
|
||||
cornerWidget->layout()->setSpacing(0);
|
||||
cornerWidget->layout()->setMargin(0);
|
||||
cornerWidget->layout()->setContentsMargins(0,0,0,0);
|
||||
window->menuBar()->setCornerWidget(cornerWidget);
|
||||
modeButtonGroup = new QButtonGroup;
|
||||
// window->menuBar()->setMaximumHeight(window->menuBar()->height());
|
||||
}
|
||||
cornerWidget->layout()->addWidget(modeSwitch);
|
||||
modeButtonGroup->addButton(modeSwitch);
|
||||
cornerWidget->setMaximumHeight(window->menuBar()->height());
|
||||
|
||||
connect(modeSwitch, &QPushButton::clicked, [=](){
|
||||
activate();
|
||||
});
|
||||
tabbar = new QTabBar;
|
||||
tabbar->setTabsClosable(true);
|
||||
tabbar->setStyleSheet("QTabBar::tab { height: "+QString::number(window->menuBar()->height())+"px;}");
|
||||
cornerWidget->layout()->addWidget(tabbar);
|
||||
|
||||
auto bAdd = new QPushButton();
|
||||
QIcon icon;
|
||||
QString iconThemeName = QString::fromUtf8("list-add");
|
||||
if (QIcon::hasThemeIcon(iconThemeName)) {
|
||||
icon = QIcon::fromTheme(iconThemeName);
|
||||
} else {
|
||||
icon.addFile(QString::fromUtf8(":/icons/add.png"), QSize(), QIcon::Normal, QIcon::Off);
|
||||
}
|
||||
bAdd->setIcon(icon);
|
||||
|
||||
auto mAdd = new QMenu();
|
||||
for(unsigned int i=0;i<(int) Type::Last;i++) {
|
||||
auto type = (Type) i;
|
||||
auto action = new QAction(TypeToName(type));
|
||||
mAdd->addAction(action);
|
||||
connect(action, &QAction::triggered, [=](){
|
||||
bool ok;
|
||||
QString text = QInputDialog::getText(window, "Create new "+TypeToName(type)+" tab",
|
||||
"Name:", QLineEdit::Normal,
|
||||
TypeToName(type), &ok);
|
||||
if(ok) {
|
||||
if(!nameAllowed(text)) {
|
||||
InformationBox::ShowError("Name collision", "Unable to create tab, no duplicate names allowed");
|
||||
} else {
|
||||
auto mode = Mode::createNew(window, text, type);
|
||||
mode->activate();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
bAdd->setMenu(mAdd);
|
||||
bAdd->setMaximumHeight(window->menuBar()->height());
|
||||
bAdd->setMaximumWidth(40);
|
||||
cornerWidget->layout()->addWidget(bAdd);
|
||||
|
||||
window->menuBar()->setCornerWidget(cornerWidget);
|
||||
|
||||
connect(tabbar, &QTabBar::currentChanged, [=](int index){
|
||||
modes[index]->activate();
|
||||
});
|
||||
connect(tabbar, &QTabBar::tabCloseRequested, [=](int index){
|
||||
delete modes[index];
|
||||
});
|
||||
}
|
||||
modes.push_back(this);
|
||||
tabbar->blockSignals(true);
|
||||
tabbar->insertTab(tabbar->count(), name);
|
||||
tabbar->blockSignals(false);
|
||||
window->getSCPI()->add(this);
|
||||
}
|
||||
|
||||
Mode::~Mode()
|
||||
{
|
||||
window->getSCPI()->remove(this);
|
||||
if(activeMode == this) {
|
||||
deactivate();
|
||||
}
|
||||
auto index = findTabIndex();
|
||||
tabbar->blockSignals(true);
|
||||
tabbar->removeTab(index);
|
||||
tabbar->blockSignals(false);
|
||||
modes.erase(modes.begin() + index);
|
||||
if(modes.size() > 0) {
|
||||
modes[tabbar->currentIndex()]->activate();
|
||||
}
|
||||
window->getCentral()->removeWidget(central);
|
||||
}
|
||||
|
||||
void Mode::activate()
|
||||
|
|
@ -89,14 +160,10 @@ void Mode::activate()
|
|||
}
|
||||
|
||||
activeMode = this;
|
||||
// force activation of correct pushbutton in case the mode switch was done via script/setup load.
|
||||
// This will trigger a second activation of this mode in the signal of the button, but since it is
|
||||
// force activation of correct tab in case the mode switch was done via script/setup load.
|
||||
// This will trigger a second activation of this mode in the signal of the tab bar, but since it is
|
||||
// already the active mode, this function will just return -> no recursion
|
||||
for(auto b : modeButtonGroup->buttons()) {
|
||||
if(b->text() == name) {
|
||||
b->click();
|
||||
}
|
||||
}
|
||||
tabbar->setCurrentIndex(findTabIndex());
|
||||
|
||||
if(window->getDevice()) {
|
||||
initializeDevice();
|
||||
|
|
@ -131,6 +198,9 @@ void Mode::deactivate()
|
|||
}
|
||||
|
||||
qDebug() << "Deactivated mode" << name;
|
||||
if(window->getDevice()) {
|
||||
window->getDevice()->SetIdle();
|
||||
}
|
||||
activeMode = nullptr;
|
||||
}
|
||||
|
||||
|
|
@ -139,6 +209,26 @@ Mode *Mode::getActiveMode()
|
|||
return activeMode;
|
||||
}
|
||||
|
||||
QString Mode::TypeToName(Mode::Type t)
|
||||
{
|
||||
switch(t) {
|
||||
case Type::VNA: return "Vector Network Analyzer";
|
||||
case Type::SG: return "Signal Generator";
|
||||
case Type::SA: return "Spectrum Analyzer";
|
||||
default: return "Invalid";
|
||||
}
|
||||
}
|
||||
|
||||
Mode::Type Mode::TypeFromName(QString s)
|
||||
{
|
||||
for(unsigned int i=0;i<(int)Type::Last;i++) {
|
||||
if(s == TypeToName((Type) i)) {
|
||||
return (Type) i;
|
||||
}
|
||||
}
|
||||
return Type::Last;
|
||||
}
|
||||
|
||||
void Mode::saveSreenshot()
|
||||
{
|
||||
auto filename = QFileDialog::getSaveFileName(nullptr, "Save plot image", "", "PNG image files (*.png)", nullptr, QFileDialog::DontUseNativeDialog);
|
||||
|
|
@ -153,6 +243,27 @@ void Mode::saveSreenshot()
|
|||
central->grab().save(filename);
|
||||
}
|
||||
|
||||
Mode *Mode::createNew(AppWindow *window, QString name, Mode::Type t)
|
||||
{
|
||||
switch(t) {
|
||||
case Type::VNA: return new VNA(window, name);
|
||||
case Type::SG: return new Generator(window, name);
|
||||
case Type::SA: return new SpectrumAnalyzer(window, name);
|
||||
default: return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
bool Mode::nameAllowed(QString name)
|
||||
{
|
||||
for(auto m : modes) {
|
||||
if(m->getName() == name) {
|
||||
// name already taken, no duplicates allowed
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void Mode::finalize(QWidget *centralWidget)
|
||||
{
|
||||
central = centralWidget;
|
||||
|
|
@ -176,6 +287,27 @@ void Mode::finalize(QWidget *centralWidget)
|
|||
}
|
||||
}
|
||||
|
||||
int Mode::findTabIndex()
|
||||
{
|
||||
auto it = std::find(modes.begin(), modes.end(), this);
|
||||
return it - modes.begin();
|
||||
}
|
||||
|
||||
std::vector<Mode *> Mode::getModes()
|
||||
{
|
||||
return modes;
|
||||
}
|
||||
|
||||
Mode *Mode::findFirstOfType(Mode::Type t)
|
||||
{
|
||||
for(auto m : modes) {
|
||||
if(m->getType() == t) {
|
||||
return m;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void Mode::setStatusbarMessage(QString msg)
|
||||
{
|
||||
statusbarMsg = msg;
|
||||
|
|
@ -188,3 +320,14 @@ QString Mode::getName() const
|
|||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
void Mode::setName(const QString &value)
|
||||
{
|
||||
if(!nameAllowed(value)) {
|
||||
// unable to use this name
|
||||
return;
|
||||
}
|
||||
name = value;
|
||||
tabbar->setTabText(findTabIndex(), name);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3,30 +3,50 @@
|
|||
|
||||
#include "appwindow.h"
|
||||
#include "savable.h"
|
||||
#include "scpi.h"
|
||||
|
||||
#include <QString>
|
||||
#include <QWidget>
|
||||
#include <QButtonGroup>
|
||||
#include <QToolBar>
|
||||
#include <QTabBar>
|
||||
#include <QDockWidget>
|
||||
#include <set>
|
||||
|
||||
class Mode : public QObject, public Savable
|
||||
class Mode : public QObject, public Savable, public SCPINode
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
Mode(AppWindow *window, QString name);
|
||||
enum class Type {
|
||||
VNA,
|
||||
SG,
|
||||
SA,
|
||||
Last,
|
||||
};
|
||||
|
||||
Mode(AppWindow *window, QString name, QString SCPIname);
|
||||
~Mode();
|
||||
|
||||
virtual void activate(); // derived classes must call Mode::activate before doing anything
|
||||
virtual void deactivate(); // derived classes must call Mode::deactivate before returning
|
||||
virtual void shutdown(){}; // called when the application is about to exit
|
||||
QString getName() const;
|
||||
void setName(const QString &value);
|
||||
static Mode *getActiveMode();
|
||||
static QString TypeToName(Type t);
|
||||
static Type TypeFromName(QString s);
|
||||
virtual Type getType() = 0;
|
||||
|
||||
virtual void initializeDevice() = 0;
|
||||
virtual void deviceDisconnected(){};
|
||||
|
||||
virtual void saveSreenshot();
|
||||
|
||||
static Mode *createNew(AppWindow *window, QString name, Type t);
|
||||
static bool nameAllowed(QString name);
|
||||
static std::vector<Mode *> getModes();
|
||||
static Mode* findFirstOfType(Type t);
|
||||
|
||||
signals:
|
||||
void statusbarMessage(QString msg);
|
||||
protected:
|
||||
|
|
@ -39,10 +59,13 @@ protected:
|
|||
std::set<QDockWidget*> docks;
|
||||
|
||||
private:
|
||||
int findTabIndex();
|
||||
static std::vector<Mode*> modes;
|
||||
static Mode *activeMode;
|
||||
static QTabBar *tabbar;
|
||||
static QWidget *cornerWidget;
|
||||
static QButtonGroup *modeButtonGroup;
|
||||
const QString name;
|
||||
// static QButtonGroup *modeButtonGroup;
|
||||
QString name;
|
||||
QString statusbarMsg;
|
||||
QWidget *central;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -106,6 +106,17 @@ bool SCPINode::add(SCPINode *node)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool SCPINode::remove(SCPINode *node)
|
||||
{
|
||||
auto it = std::find(subnodes.begin(), subnodes.end(), node);
|
||||
if(it != subnodes.end()) {
|
||||
subnodes.erase(it);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool SCPINode::add(SCPICommand *cmd)
|
||||
{
|
||||
if(nameCollision(cmd->name())) {
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ public:
|
|||
name(name){}
|
||||
|
||||
bool add(SCPINode *node);
|
||||
bool remove(SCPINode *node);
|
||||
bool add(SCPICommand *cmd);
|
||||
|
||||
private:
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
<provider-reference id="org.eclipse.cdt.core.ReferencedProjectsLanguageSettingsProvider" ref="shared-provider"/>
|
||||
<provider-reference id="org.eclipse.cdt.managedbuilder.core.MBSLanguageSettingsProvider" ref="shared-provider"/>
|
||||
<provider copy-of="extension" id="org.eclipse.cdt.managedbuilder.core.GCCBuildCommandParser"/>
|
||||
<provider class="com.st.stm32cube.ide.mcu.toolchain.armnone.setup.CrossBuiltinSpecsDetector" console="false" env-hash="-1671998965483228530" id="com.st.stm32cube.ide.mcu.toolchain.armnone.setup.CrossBuiltinSpecsDetector" keep-relative-paths="false" name="MCU ARM GCC Built-in Compiler Settings" parameter="${COMMAND} ${FLAGS} -E -P -v -dD "${INPUTS}"" prefer-non-shared="true">
|
||||
<provider class="com.st.stm32cube.ide.mcu.toolchain.armnone.setup.CrossBuiltinSpecsDetector" console="false" env-hash="1949595105660943601" id="com.st.stm32cube.ide.mcu.toolchain.armnone.setup.CrossBuiltinSpecsDetector" keep-relative-paths="false" name="MCU ARM GCC Built-in Compiler Settings" parameter="${COMMAND} ${FLAGS} -E -P -v -dD "${INPUTS}"" prefer-non-shared="true">
|
||||
<language-scope id="org.eclipse.cdt.core.gcc"/>
|
||||
<language-scope id="org.eclipse.cdt.core.g++"/>
|
||||
</provider>
|
||||
|
|
@ -18,7 +18,7 @@
|
|||
<provider-reference id="org.eclipse.cdt.core.ReferencedProjectsLanguageSettingsProvider" ref="shared-provider"/>
|
||||
<provider-reference id="org.eclipse.cdt.managedbuilder.core.MBSLanguageSettingsProvider" ref="shared-provider"/>
|
||||
<provider copy-of="extension" id="org.eclipse.cdt.managedbuilder.core.GCCBuildCommandParser"/>
|
||||
<provider class="com.st.stm32cube.ide.mcu.toolchain.armnone.setup.CrossBuiltinSpecsDetector" console="false" env-hash="-1671998965483228530" id="com.st.stm32cube.ide.mcu.toolchain.armnone.setup.CrossBuiltinSpecsDetector" keep-relative-paths="false" name="MCU ARM GCC Built-in Compiler Settings" parameter="${COMMAND} ${FLAGS} -E -P -v -dD "${INPUTS}"" prefer-non-shared="true">
|
||||
<provider class="com.st.stm32cube.ide.mcu.toolchain.armnone.setup.CrossBuiltinSpecsDetector" console="false" env-hash="1949595105660943601" id="com.st.stm32cube.ide.mcu.toolchain.armnone.setup.CrossBuiltinSpecsDetector" keep-relative-paths="false" name="MCU ARM GCC Built-in Compiler Settings" parameter="${COMMAND} ${FLAGS} -E -P -v -dD "${INPUTS}"" prefer-non-shared="true">
|
||||
<language-scope id="org.eclipse.cdt.core.gcc"/>
|
||||
<language-scope id="org.eclipse.cdt.core.g++"/>
|
||||
</provider>
|
||||
|
|
|
|||
|
|
@ -117,7 +117,7 @@ inline void App_Process() {
|
|||
sweepActive = VNA::Setup(recv_packet.settings);
|
||||
Communication::SendWithoutPayload(Protocol::PacketType::Ack);
|
||||
break;
|
||||
case Protocol::PacketType::ManualControl:
|
||||
case Protocol::PacketType::ManualControlV1:
|
||||
sweepActive = false;
|
||||
last_measure_packet = recv_packet;
|
||||
Manual::Setup(recv_packet.manual);
|
||||
|
|
@ -145,12 +145,21 @@ inline void App_Process() {
|
|||
SA::Setup(recv_packet.spectrumSettings);
|
||||
Communication::SendWithoutPayload(Protocol::PacketType::Ack);
|
||||
break;
|
||||
case Protocol::PacketType::RequestDeviceInfo:
|
||||
case Protocol::PacketType::RequestDeviceInfo: {
|
||||
Communication::SendWithoutPayload(Protocol::PacketType::Ack);
|
||||
Protocol::PacketInfo p;
|
||||
p.type = Protocol::PacketType::DeviceInfo;
|
||||
HW::fillDeviceInfo(&p.info);
|
||||
p.info = HW::Info;
|
||||
Communication::Send(p);
|
||||
}
|
||||
break;
|
||||
case Protocol::PacketType::RequestDeviceStatus: {
|
||||
Communication::SendWithoutPayload(Protocol::PacketType::Ack);
|
||||
Protocol::PacketInfo p;
|
||||
p.type = Protocol::PacketType::DeviceStatusV1;
|
||||
HW::getDeviceStatus(&p.statusV1);
|
||||
Communication::Send(p);
|
||||
}
|
||||
break;
|
||||
case Protocol::PacketType::SetIdle:
|
||||
HW::SetMode(HW::Mode::Idle);
|
||||
|
|
|
|||
|
|
@ -91,8 +91,9 @@ uint16_t Protocol::EncodePacket(const PacketInfo &packet, uint8_t *dest, uint16_
|
|||
case PacketType::SweepSettings: payload_size = sizeof(packet.settings); break;
|
||||
case PacketType::Reference: payload_size = sizeof(packet.reference); break;
|
||||
case PacketType::DeviceInfo: payload_size = sizeof(packet.info); break;
|
||||
case PacketType::Status: payload_size = sizeof(packet.status); break;
|
||||
case PacketType::ManualControl: payload_size = sizeof(packet.manual); break;
|
||||
case PacketType::DeviceStatusV1: payload_size = sizeof(packet.statusV1); break;
|
||||
case PacketType::ManualStatusV1: payload_size = sizeof(packet.manualStatusV1); break;
|
||||
case PacketType::ManualControlV1: payload_size = sizeof(packet.manual); break;
|
||||
case PacketType::FirmwarePacket: payload_size = sizeof(packet.firmware); break;
|
||||
case PacketType::Generator: payload_size = sizeof(packet.generator); break;
|
||||
case PacketType::SpectrumAnalyzerSettings: payload_size = sizeof(packet.spectrumSettings); break;
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
namespace Protocol {
|
||||
|
||||
static constexpr uint16_t Version = 9;
|
||||
static constexpr uint16_t Version = 10;
|
||||
|
||||
#pragma pack(push, 1)
|
||||
|
||||
|
|
@ -50,17 +50,8 @@ using DeviceInfo = struct _deviceInfo {
|
|||
uint8_t FW_major;
|
||||
uint8_t FW_minor;
|
||||
uint8_t FW_patch;
|
||||
uint8_t hardware_version;
|
||||
char HW_Revision;
|
||||
uint8_t extRefAvailable:1;
|
||||
uint8_t extRefInUse:1;
|
||||
uint8_t FPGA_configured:1;
|
||||
uint8_t source_locked:1;
|
||||
uint8_t LO1_locked:1;
|
||||
uint8_t ADC_overload:1;
|
||||
uint8_t unlevel:1;
|
||||
uint8_t temp_source;
|
||||
uint8_t temp_LO1;
|
||||
uint8_t temp_MCU;
|
||||
uint64_t limits_minFreq;
|
||||
uint64_t limits_maxFreq;
|
||||
uint32_t limits_minIFBW;
|
||||
|
|
@ -74,7 +65,21 @@ using DeviceInfo = struct _deviceInfo {
|
|||
uint64_t limits_maxFreqHarmonic;
|
||||
};
|
||||
|
||||
using ManualStatus = struct _manualstatus {
|
||||
using DeviceStatusV1 = struct _deviceStatusV1 {
|
||||
uint8_t extRefAvailable:1;
|
||||
uint8_t extRefInUse:1;
|
||||
uint8_t FPGA_configured:1;
|
||||
uint8_t source_locked:1;
|
||||
uint8_t LO1_locked:1;
|
||||
uint8_t ADC_overload:1;
|
||||
uint8_t unlevel:1;
|
||||
uint8_t temp_source;
|
||||
uint8_t temp_LO1;
|
||||
uint8_t temp_MCU;
|
||||
};
|
||||
|
||||
|
||||
using ManualStatusV1 = struct _manualstatusV1 {
|
||||
int16_t port1min, port1max;
|
||||
int16_t port2min, port2max;
|
||||
int16_t refmin, refmax;
|
||||
|
|
@ -87,7 +92,7 @@ using ManualStatus = struct _manualstatus {
|
|||
uint8_t LO_locked :1;
|
||||
};
|
||||
|
||||
using ManualControl = struct _manualControl {
|
||||
using ManualControlV1 = struct _manualControlV1 {
|
||||
// Highband Source
|
||||
uint8_t SourceHighCE :1;
|
||||
uint8_t SourceHighRFEN :1;
|
||||
|
|
@ -170,8 +175,8 @@ enum class PacketType : uint8_t {
|
|||
None = 0,
|
||||
Datapoint = 1,
|
||||
SweepSettings = 2,
|
||||
Status = 3,
|
||||
ManualControl = 4,
|
||||
ManualStatusV1 = 3,
|
||||
ManualControlV1 = 4,
|
||||
DeviceInfo = 5,
|
||||
FirmwarePacket = 6,
|
||||
Ack = 7,
|
||||
|
|
@ -192,6 +197,8 @@ enum class PacketType : uint8_t {
|
|||
FrequencyCorrection = 22,
|
||||
RequestAcquisitionFrequencySettings = 23,
|
||||
AcquisitionFrequencySettings = 24,
|
||||
DeviceStatusV1 = 25,
|
||||
RequestDeviceStatus = 26,
|
||||
};
|
||||
|
||||
using PacketInfo = struct _packetinfo {
|
||||
|
|
@ -201,10 +208,11 @@ using PacketInfo = struct _packetinfo {
|
|||
SweepSettings settings;
|
||||
ReferenceSettings reference;
|
||||
GeneratorSettings generator;
|
||||
DeviceStatusV1 statusV1;
|
||||
DeviceInfo info;
|
||||
ManualControl manual;
|
||||
ManualControlV1 manual;
|
||||
FirmwarePacket firmware;
|
||||
ManualStatus status;
|
||||
ManualStatusV1 manualStatusV1;
|
||||
SpectrumAnalyzerSettings spectrumSettings;
|
||||
SpectrumAnalyzerResult spectrumResult;
|
||||
AmplitudeCorrectionPoint amplitudePoint;
|
||||
|
|
|
|||
|
|
@ -130,6 +130,17 @@ void FPGA::SetSamplesPerPoint(uint32_t nsamples) {
|
|||
WriteRegister(Reg::SamplesPerPoint, nsamples);
|
||||
}
|
||||
|
||||
void FPGA::SetupSweep(uint8_t stages, uint8_t port1_stage, uint8_t port2_stage, bool individual_halt) {
|
||||
uint16_t value = 0x0000;
|
||||
value |= (uint16_t) (stages & 0x07) << 13;
|
||||
if(individual_halt) {
|
||||
value |= 0x1000;
|
||||
}
|
||||
value |= (port1_stage & 0x07) << 3;
|
||||
value |= (port2_stage & 0x07) << 0;
|
||||
WriteRegister(Reg::SweepSetup, value);
|
||||
}
|
||||
|
||||
void FPGA::Enable(Periphery p, bool enable) {
|
||||
if (enable) {
|
||||
SysCtrlReg |= (uint16_t) p;
|
||||
|
|
@ -282,7 +293,7 @@ void HAL_SPI_TxRxCpltCallback(SPI_HandleTypeDef *hspi) {
|
|||
result.RefI = assembleSampleResultValue(&raw[8]);
|
||||
result.RefQ = assembleSampleResultValue(&raw[2]);
|
||||
result.pointNum = (uint16_t)(raw[38]&0x1F) << 8 | raw[39];
|
||||
result.activePort = raw[38] & 0x80 ? 1 : 0;
|
||||
result.stageNum = (raw[38] & 0xE0) >> 5;
|
||||
High(CS);
|
||||
busy_reading = false;
|
||||
if ((status & 0x0004) && callback) {
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ enum class Reg {
|
|||
SystemControl = 0x03,
|
||||
ADCPrescaler = 0x04,
|
||||
PhaseIncrement = 0x05,
|
||||
SweepSetup = 0x06,
|
||||
MAX2871Def0LSB = 0x08,
|
||||
MAX2871Def0MSB = 0x09,
|
||||
MAX2871Def1LSB = 0x0A,
|
||||
|
|
@ -33,8 +34,8 @@ using SamplingResult = struct _samplingresult {
|
|||
int64_t P1I, P1Q;
|
||||
int64_t P2I, P2Q;
|
||||
int64_t RefI, RefQ;
|
||||
uint16_t pointNum :15;
|
||||
uint16_t activePort :1;
|
||||
uint16_t pointNum :13;
|
||||
uint16_t stageNum :3;
|
||||
};
|
||||
|
||||
using DFTResult = struct _dftresult {
|
||||
|
|
@ -59,8 +60,7 @@ enum class Periphery {
|
|||
DebugLED = 0x0080,
|
||||
SourceChip = 0x0010,
|
||||
LO1Chip = 0x0008,
|
||||
ExcitePort2 = 0x0004,
|
||||
ExcitePort1 = 0x0002,
|
||||
|
||||
PortSwitch = 0x0001,
|
||||
};
|
||||
|
||||
|
|
@ -113,6 +113,7 @@ bool Init(HaltedCallback cb = nullptr);
|
|||
void WriteRegister(FPGA::Reg reg, uint16_t value);
|
||||
void SetNumberOfPoints(uint16_t npoints);
|
||||
void SetSamplesPerPoint(uint32_t nsamples);
|
||||
void SetupSweep(uint8_t stages, uint8_t port1_stage, uint8_t port2_stage, bool individual_halt = false);
|
||||
void Enable(Periphery p, bool enable = true);
|
||||
void Disable(Periphery p);
|
||||
bool IsEnabled(Periphery p);
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ void Generator::Setup(Protocol::GeneratorSettings g) {
|
|||
HW::SetIdle();
|
||||
return;
|
||||
}
|
||||
Protocol::ManualControl m;
|
||||
Protocol::ManualControlV1 m;
|
||||
// LOs not required
|
||||
m.LO1CE = 0;
|
||||
m.LO1Frequency = 1000000000;
|
||||
|
|
|
|||
|
|
@ -299,9 +299,7 @@ void HW::SetOutputUnlevel(bool unlev) {
|
|||
unlevel = unlev;
|
||||
}
|
||||
|
||||
void HW::fillDeviceInfo(Protocol::DeviceInfo *info, bool updateEvenWhenBusy) {
|
||||
// copy constant default values
|
||||
memcpy(info, &HW::Info, sizeof(HW::Info));
|
||||
void HW::getDeviceStatus(Protocol::DeviceStatusV1 *status, bool updateEvenWhenBusy) {
|
||||
if(activeMode == Mode::Idle || updateEvenWhenBusy) {
|
||||
// updating values from FPGA allowed
|
||||
|
||||
|
|
@ -318,21 +316,21 @@ void HW::fillDeviceInfo(Protocol::DeviceInfo *info, bool updateEvenWhenBusy) {
|
|||
if(limits.P1min < -ADC_LIMIT || limits.P1max > ADC_LIMIT
|
||||
|| limits.P2min < -ADC_LIMIT || limits.P2max > ADC_LIMIT
|
||||
|| limits.Rmin < -ADC_LIMIT || limits.Rmax > ADC_LIMIT) {
|
||||
info->ADC_overload = true;
|
||||
status->ADC_overload = true;
|
||||
} else {
|
||||
info->ADC_overload = false;
|
||||
status->ADC_overload = false;
|
||||
}
|
||||
auto status = FPGA::GetStatus();
|
||||
info->LO1_locked = (status & (int) FPGA::Interrupt::LO1Unlock) ? 0 : 1;
|
||||
info->source_locked = (status & (int) FPGA::Interrupt::SourceUnlock) ? 0 : 1;
|
||||
info->extRefAvailable = Ref::available();
|
||||
info->extRefInUse = extRefInUse;
|
||||
info->unlevel = unlevel;
|
||||
info->temp_LO1 = tempLO;
|
||||
info->temp_source = tempSource;
|
||||
auto FPGA_status = FPGA::GetStatus();
|
||||
status->LO1_locked = (FPGA_status & (int) FPGA::Interrupt::LO1Unlock) ? 0 : 1;
|
||||
status->source_locked = (FPGA_status & (int) FPGA::Interrupt::SourceUnlock) ? 0 : 1;
|
||||
status->extRefAvailable = Ref::available();
|
||||
status->extRefInUse = extRefInUse;
|
||||
status->unlevel = unlevel;
|
||||
status->temp_LO1 = tempLO;
|
||||
status->temp_source = tempSource;
|
||||
FPGA::ResetADCLimits();
|
||||
}
|
||||
info->temp_MCU = STM::getTemperature();
|
||||
status->temp_MCU = STM::getTemperature();
|
||||
}
|
||||
|
||||
bool HW::Ref::available() {
|
||||
|
|
|
|||
|
|
@ -70,17 +70,8 @@ static constexpr Protocol::DeviceInfo Info = {
|
|||
.FW_major = FW_MAJOR,
|
||||
.FW_minor = FW_MINOR,
|
||||
.FW_patch = FW_PATCH,
|
||||
.hardware_version = 1,
|
||||
.HW_Revision = HW_REVISION,
|
||||
.extRefAvailable = 0,
|
||||
.extRefInUse = 0,
|
||||
.FPGA_configured = 0,
|
||||
.source_locked = 0,
|
||||
.LO1_locked = 0,
|
||||
.ADC_overload = 0,
|
||||
.unlevel = 0,
|
||||
.temp_source = 0,
|
||||
.temp_LO1 = 0,
|
||||
.temp_MCU = 0,
|
||||
.limits_minFreq = 0,
|
||||
.limits_maxFreq = 6000000000,
|
||||
.limits_minIFBW = DefaultADCSamplerate / MaxSamples,
|
||||
|
|
@ -120,7 +111,7 @@ using AmplitudeSettings = struct _amplitudeSettings {
|
|||
AmplitudeSettings GetAmplitudeSettings(int16_t cdbm, uint64_t freq = 0, bool applyCorrections = false, bool port2 = false);
|
||||
|
||||
bool GetTemps(uint8_t *source, uint8_t *lo);
|
||||
void fillDeviceInfo(Protocol::DeviceInfo *info, bool updateEvenWhenBusy = false);
|
||||
void getDeviceStatus(Protocol::DeviceStatusV1 *status, bool updateEvenWhenBusy = false);
|
||||
namespace Ref {
|
||||
bool available();
|
||||
bool usingExternal();
|
||||
|
|
|
|||
|
|
@ -6,11 +6,11 @@
|
|||
|
||||
static bool active = false;
|
||||
static uint32_t samples;
|
||||
static Protocol::ManualStatus status;
|
||||
static Protocol::ManualStatusV1 status;
|
||||
|
||||
using namespace HWHAL;
|
||||
|
||||
void Manual::Setup(Protocol::ManualControl m) {
|
||||
void Manual::Setup(Protocol::ManualControlV1 m) {
|
||||
HW::SetMode(HW::Mode::Manual);
|
||||
samples = m.Samples;
|
||||
FPGA::AbortSweep();
|
||||
|
|
@ -69,8 +69,7 @@ void Manual::Setup(Protocol::ManualControl m) {
|
|||
FPGA::Enable(FPGA::Periphery::Port1Mixer, m.Port1EN);
|
||||
FPGA::Enable(FPGA::Periphery::Port2Mixer, m.Port2EN);
|
||||
FPGA::Enable(FPGA::Periphery::RefMixer, m.RefEN);
|
||||
FPGA::Enable(FPGA::Periphery::ExcitePort1, m.PortSwitch == 0);
|
||||
FPGA::Enable(FPGA::Periphery::ExcitePort2, m.PortSwitch == 1);
|
||||
FPGA::SetupSweep(0, m.PortSwitch == 1, m.PortSwitch == 0);
|
||||
FPGA::Enable(FPGA::Periphery::PortSwitch);
|
||||
|
||||
// Enable new data and sweep halt interrupt
|
||||
|
|
@ -100,38 +99,38 @@ void Manual::Work() {
|
|||
return;
|
||||
}
|
||||
Protocol::PacketInfo p;
|
||||
p.type = Protocol::PacketType::Status;
|
||||
p.status = status;
|
||||
p.type = Protocol::PacketType::ManualStatusV1;
|
||||
p.manualStatusV1 = status;
|
||||
uint16_t isr_flags = FPGA::GetStatus();
|
||||
if (!(isr_flags & 0x0002)) {
|
||||
p.status.source_locked = 1;
|
||||
p.manualStatusV1.source_locked = 1;
|
||||
} else {
|
||||
p.status.source_locked = 0;
|
||||
p.manualStatusV1.source_locked = 0;
|
||||
}
|
||||
if (!(isr_flags & 0x0001)) {
|
||||
p.status.LO_locked = 1;
|
||||
p.manualStatusV1.LO_locked = 1;
|
||||
} else {
|
||||
p.status.LO_locked = 0;
|
||||
p.manualStatusV1.LO_locked = 0;
|
||||
}
|
||||
auto limits = FPGA::GetADCLimits();
|
||||
FPGA::ResetADCLimits();
|
||||
p.status.port1min = limits.P1min;
|
||||
p.status.port1max = limits.P1max;
|
||||
p.status.port2min = limits.P2min;
|
||||
p.status.port2max = limits.P2max;
|
||||
p.status.refmin = limits.Rmin;
|
||||
p.status.refmax = limits.Rmax;
|
||||
HW::GetTemps(&p.status.temp_source, &p.status.temp_LO);
|
||||
p.manualStatusV1.port1min = limits.P1min;
|
||||
p.manualStatusV1.port1max = limits.P1max;
|
||||
p.manualStatusV1.port2min = limits.P2min;
|
||||
p.manualStatusV1.port2max = limits.P2max;
|
||||
p.manualStatusV1.refmin = limits.Rmin;
|
||||
p.manualStatusV1.refmax = limits.Rmax;
|
||||
HW::GetTemps(&p.manualStatusV1.temp_source, &p.manualStatusV1.temp_LO);
|
||||
Communication::Send(p);
|
||||
HW::Ref::update();
|
||||
Protocol::PacketInfo packet;
|
||||
packet.type = Protocol::PacketType::DeviceInfo;
|
||||
packet.type = Protocol::PacketType::DeviceStatusV1;
|
||||
// Enable PLL chips for temperature reading
|
||||
bool srcEn = FPGA::IsEnabled(FPGA::Periphery::SourceChip);
|
||||
bool LOEn = FPGA::IsEnabled(FPGA::Periphery::LO1Chip);
|
||||
FPGA::Enable(FPGA::Periphery::SourceChip);
|
||||
FPGA::Enable(FPGA::Periphery::LO1Chip);
|
||||
HW::fillDeviceInfo(&packet.info, true);
|
||||
HW::getDeviceStatus(&packet.statusV1, true);
|
||||
// restore PLL state
|
||||
FPGA::Enable(FPGA::Periphery::SourceChip, srcEn);
|
||||
FPGA::Enable(FPGA::Periphery::LO1Chip, LOEn);
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
namespace Manual {
|
||||
|
||||
void Setup(Protocol::ManualControl m);
|
||||
void Setup(Protocol::ManualControlV1 m);
|
||||
bool MeasurementDone(const FPGA::SamplingResult &result);
|
||||
void Work();
|
||||
void Stop();
|
||||
|
|
|
|||
|
|
@ -209,8 +209,7 @@ void SA::Setup(Protocol::SpectrumAnalyzerSettings settings) {
|
|||
FPGA::SetWindow((FPGA::Window) s.WindowType);
|
||||
FPGA::Enable(FPGA::Periphery::LO1Chip);
|
||||
FPGA::Enable(FPGA::Periphery::LO1RF);
|
||||
FPGA::Enable(FPGA::Periphery::ExcitePort1, s.trackingGeneratorPort == 0);
|
||||
FPGA::Enable(FPGA::Periphery::ExcitePort2, s.trackingGeneratorPort == 1);
|
||||
FPGA::SetupSweep(0, s.trackingGeneratorPort == 1, s.trackingGeneratorPort == 0);
|
||||
FPGA::Enable(FPGA::Periphery::PortSwitch, s.trackingGenerator);
|
||||
FPGA::Enable(FPGA::Periphery::Amplifier, s.trackingGenerator);
|
||||
FPGA::Enable(FPGA::Periphery::Port1Mixer);
|
||||
|
|
@ -386,8 +385,8 @@ void SA::Work() {
|
|||
// send device info every nth point
|
||||
FPGA::Enable(FPGA::Periphery::SourceChip); // needs to enable the chip to get a valid temperature reading
|
||||
Protocol::PacketInfo packet;
|
||||
packet.type = Protocol::PacketType::DeviceInfo;
|
||||
HW::fillDeviceInfo(&packet.info, true);
|
||||
packet.type = Protocol::PacketType::DeviceStatusV1;
|
||||
HW::getDeviceStatus(&packet.statusV1, true);
|
||||
FPGA::Disable(FPGA::Periphery::SourceChip);
|
||||
Communication::Send(packet);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,8 +21,9 @@
|
|||
|
||||
static Protocol::SweepSettings settings;
|
||||
static uint16_t pointCnt;
|
||||
static uint8_t stageCnt;
|
||||
static uint8_t stages;
|
||||
static double logMultiplier, logFrequency;
|
||||
static bool excitingPort1;
|
||||
static Protocol::Datapoint data;
|
||||
static bool active = false;
|
||||
static Si5351C::DriveStrength fixedPowerLowband;
|
||||
|
|
@ -278,12 +279,22 @@ bool VNA::Setup(Protocol::SweepSettings s) {
|
|||
FPGA::Enable(FPGA::Periphery::SourceRF);
|
||||
FPGA::Enable(FPGA::Periphery::LO1Chip);
|
||||
FPGA::Enable(FPGA::Periphery::LO1RF);
|
||||
FPGA::Enable(FPGA::Periphery::ExcitePort1, s.excitePort1);
|
||||
FPGA::Enable(FPGA::Periphery::ExcitePort2, s.excitePort2);
|
||||
if(s.excitePort1 && s.excitePort2) {
|
||||
// two stages, port 1 first, followed by port 2
|
||||
FPGA::SetupSweep(1, 0, 1);
|
||||
stages = 2;
|
||||
} else if(s.excitePort1) {
|
||||
// one stage, port 1 only
|
||||
FPGA::SetupSweep(0, 0, 1);
|
||||
stages = 1;
|
||||
} else {
|
||||
// one stage, port 2 only
|
||||
FPGA::SetupSweep(0, 1, 0);
|
||||
stages = 1;
|
||||
}
|
||||
FPGA::Enable(FPGA::Periphery::PortSwitch);
|
||||
pointCnt = 0;
|
||||
// starting port depends on whether port 1 is active in sweep
|
||||
excitingPort1 = s.excitePort1;
|
||||
stageCnt = 0;
|
||||
IFTableIndexCnt = 0;
|
||||
adcShifted = false;
|
||||
active = true;
|
||||
|
|
@ -306,8 +317,8 @@ bool VNA::MeasurementDone(const FPGA::SamplingResult &result) {
|
|||
if(!active) {
|
||||
return false;
|
||||
}
|
||||
if(result.pointNum != pointCnt || !result.activePort != excitingPort1) {
|
||||
LOG_WARN("Indicated point does not match (%u != %u, %d != %d)", result.pointNum, pointCnt, result.activePort, !excitingPort1);
|
||||
if(result.pointNum != pointCnt || result.stageNum != stageCnt) {
|
||||
LOG_WARN("Indicated point does not match (%u != %u, %d != %d)", result.pointNum, pointCnt, result.stageNum, stageCnt);
|
||||
FPGA::AbortSweep();
|
||||
return false;
|
||||
}
|
||||
|
|
@ -320,29 +331,24 @@ bool VNA::MeasurementDone(const FPGA::SamplingResult &result) {
|
|||
data.pointNum = pointCnt;
|
||||
data.frequency = getPointFrequency(pointCnt);
|
||||
data.cdbm = settings.cdbm_excitation_start + (settings.cdbm_excitation_stop - settings.cdbm_excitation_start) * pointCnt / (settings.points - 1);
|
||||
if(excitingPort1) {
|
||||
if(stageCnt == 0 && settings.excitePort1) {
|
||||
// stimulus is present at port 1
|
||||
data.real_S11 = port1.real();
|
||||
data.imag_S11 = port1.imag();
|
||||
data.real_S21 = port2.real();
|
||||
data.imag_S21 = port2.imag();
|
||||
} else {
|
||||
// stimulus is present at port 2
|
||||
data.real_S12 = port1.real();
|
||||
data.imag_S12 = port1.imag();
|
||||
data.real_S22 = port2.real();
|
||||
data.imag_S22 = port2.imag();
|
||||
}
|
||||
// figure out whether this sweep point is complete and which port gets excited next
|
||||
bool pointComplete = false;
|
||||
if(settings.excitePort1 == 1 && settings.excitePort2 == 1) {
|
||||
// point is complete when port 2 was active
|
||||
pointComplete = !excitingPort1;
|
||||
// next measurement will be from other port
|
||||
excitingPort1 = !excitingPort1;
|
||||
} else {
|
||||
// only one port active, point is complete after every measurement
|
||||
pointComplete = true;
|
||||
}
|
||||
if(pointComplete) {
|
||||
// figure out whether this sweep point is complete
|
||||
stageCnt++;
|
||||
if(stageCnt == stages) {
|
||||
// point is complete
|
||||
stageCnt = 0;
|
||||
STM::DispatchToInterrupt(PassOnData);
|
||||
pointCnt++;
|
||||
if (pointCnt >= settings.points) {
|
||||
|
|
@ -361,8 +367,8 @@ void VNA::Work() {
|
|||
HW::Ref::update();
|
||||
// Compile info packet
|
||||
Protocol::PacketInfo packet;
|
||||
packet.type = Protocol::PacketType::DeviceInfo;
|
||||
HW::fillDeviceInfo(&packet.info, true);
|
||||
packet.type = Protocol::PacketType::DeviceStatusV1;
|
||||
HW::getDeviceStatus(&packet.statusV1, true);
|
||||
Communication::Send(packet);
|
||||
// do not reset unlevel flag here, as it is calculated only once at the setup of the sweep
|
||||
// Start next sweep
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue