WIP: synchronization

This commit is contained in:
Jan Käberich 2022-08-08 18:08:40 +02:00
parent 7b3aa6e158
commit 73e26a25c4
41 changed files with 439 additions and 163 deletions

View file

@ -423,8 +423,9 @@ void AmplitudeCalDialog::AutomaticMeasurementDialog()
}
}
void AmplitudeCalDialog::ReceivedMeasurement(Protocol::SpectrumAnalyzerResult res)
void AmplitudeCalDialog::ReceivedMeasurement(Device *dev, Protocol::SpectrumAnalyzerResult res)
{
Q_UNUSED(dev)
MeasurementResult m = {.port1 = Util::SparamTodB(res.port1), .port2 = Util::SparamTodB(res.port2)};
sweepMeasurements.push_back(m);
if(res.pointNum == automaticSweepPoints - 1) {
@ -529,8 +530,9 @@ void AmplitudeCalDialog::SetupNextAutomaticPoint(bool isSourceCal)
sweepMeasurements.reserve(automaticSweepPoints);
}
void AmplitudeCalDialog::ReceivedAutomaticMeasurementResult(Protocol::SpectrumAnalyzerResult res)
void AmplitudeCalDialog::ReceivedAutomaticMeasurementResult(Device *dev, Protocol::SpectrumAnalyzerResult res)
{
Q_UNUSED(dev)
if(res.pointNum != automaticSweepPoints - 1) {
// ignore everything except end of sweep
return;

View file

@ -78,7 +78,7 @@ protected slots:
bool AddPoint(double frequency);
void AddPointDialog();
void AutomaticMeasurementDialog();
void ReceivedMeasurement(Protocol::SpectrumAnalyzerResult res);
void ReceivedMeasurement(Device *dev, Protocol::SpectrumAnalyzerResult res);
signals:
void pointsUpdated();
void newPointCreated(CorrectionPoint& p);
@ -108,7 +108,7 @@ protected:
CalibrationMode mode;
void SetupNextAutomaticPoint(bool isSourceCal);
void ReceivedAutomaticMeasurementResult(Protocol::SpectrumAnalyzerResult res);
void ReceivedAutomaticMeasurementResult(Device *dev, Protocol::SpectrumAnalyzerResult res);
struct {
QDialog *dialog;
std::vector<CorrectionPoint> points;

View file

@ -122,6 +122,15 @@ bool TileWidget::allLimitsPassing()
}
}
void TileWidget::setSplitPercentage(int percentage)
{
if(!isSplit) {
return;
}
splitter->setStretchFactor(0, percentage);
splitter->setStretchFactor(1, 100 - percentage);
}
void TileWidget::splitVertically(bool moveContentToSecondChild)
{
if(isSplit) {

View file

@ -32,6 +32,8 @@ public:
// check potential trace limits on graphs, only returns true if all traces in all graphs are within limits
bool allLimitsPassing();
void setSplitPercentage(int percentage);
public slots:
void splitVertically(bool moveContentToSecondChild = false);
void splitHorizontally(bool moveContentToSecondChild = false);

View file

@ -326,7 +326,6 @@ std::set<QString> Device::GetDevices()
void Device::SetTrigger(bool set)
{
qDebug() << "Trigger" << set << "to" << this;
if(set) {
SendCommandWithoutPayload(Protocol::PacketType::SetTrigger);
} else {
@ -479,13 +478,13 @@ void Device::ReceivedData()
dataBuffer->removeBytes(handled_len);
switch(packet.type) {
case Protocol::PacketType::VNADatapoint:
emit DatapointReceived(packet.VNAdatapoint);
emit DatapointReceived(this, packet.VNAdatapoint);
break;
case Protocol::PacketType::ManualStatusV1:
emit ManualStatusReceived(packet.manualStatusV1);
break;
case Protocol::PacketType::SpectrumAnalyzerResult:
emit SpectrumResultReceived(packet.spectrumResult);
emit SpectrumResultReceived(this, packet.spectrumResult);
break;
case Protocol::PacketType::SourceCalPoint:
case Protocol::PacketType::ReceiverCalPoint:
@ -500,11 +499,11 @@ void Device::ReceivedData()
info = packet.info;
}
infoValid = true;
emit DeviceInfoUpdated();
emit DeviceInfoUpdated(this);
break;
case Protocol::PacketType::DeviceStatusV1:
status.v1 = packet.statusV1;
emit DeviceStatusUpdated();
emit DeviceStatusUpdated(this);
break;
case Protocol::PacketType::Ack:
emit AckReceived();
@ -518,11 +517,9 @@ void Device::ReceivedData()
emit FrequencyCorrectionReceived(packet.frequencyCorrection.ppm);
break;
case Protocol::PacketType::SetTrigger:
qDebug() << "Trigger" << true << "from" << this;
emit TriggerReceived(true);
break;
case Protocol::PacketType::ClearTrigger:
qDebug() << "Trigger" << false << "from" << this;
emit TriggerReceived(false);
break;
default:

View file

@ -78,13 +78,13 @@ public:
// Returns serial numbers of all connected devices
static std::set<QString> GetDevices();
signals:
void DatapointReceived(Protocol::VNADatapoint<32>*);
void DatapointReceived(Device*, Protocol::VNADatapoint<32>*);
void ManualStatusReceived(Protocol::ManualStatusV1);
void SpectrumResultReceived(Protocol::SpectrumAnalyzerResult);
void SpectrumResultReceived(Device*, Protocol::SpectrumAnalyzerResult);
void AmplitudeCorrectionPointReceived(Protocol::AmplitudeCorrectionPoint);
void FrequencyCorrectionReceived(float ppm);
void DeviceInfoUpdated();
void DeviceStatusUpdated();
void DeviceInfoUpdated(Device*);
void DeviceStatusUpdated(Device*);
void ConnectionLost();
void AckReceived();
void NackReceived();

View file

@ -147,18 +147,10 @@ VirtualDevice::VirtualDevice(QString serial)
connect(dev, &Device::LogLineReceived, [=](QString line){
emit LogLineReceived(line.prepend(dev->serial()+": "));
});
connect(dev, &Device::DeviceInfoUpdated, [=](){
compoundInfoUpdated(dev);
});
connect(dev, &Device::DeviceStatusUpdated, [=](){
compoundStatusUpdated(dev);
});
connect(dev, &Device::DatapointReceived, [=](Protocol::VNADatapoint<32> *data){
compoundDatapointReceivecd(data, dev);
});
connect(dev, &Device::SpectrumResultReceived, [=](Protocol::SpectrumAnalyzerResult res) {
compoundSpectrumResultReceived(res, dev);
});
connect(dev, &Device::DeviceInfoUpdated, this, &VirtualDevice::compoundInfoUpdated, Qt::QueuedConnection);
connect(dev, &Device::DeviceStatusUpdated, this, &VirtualDevice::compoundStatusUpdated, Qt::QueuedConnection);
connect(dev, &Device::DatapointReceived, this, &VirtualDevice::compoundDatapointReceivecd, Qt::QueuedConnection);
connect(dev, &Device::SpectrumResultReceived, this, &VirtualDevice::compoundSpectrumResultReceived, Qt::QueuedConnection);
}
if(cdev->sync == CompoundDevice::Synchronization::USB) {
// create trigger connections for USB synchronization
@ -283,6 +275,7 @@ bool VirtualDevice::setVNA(const VirtualDevice::VNASettings &s, std::function<vo
sd.port1Stage = find(s.excitedPorts.begin(), s.excitedPorts.end(), 0) - s.excitedPorts.begin();
sd.port2Stage = find(s.excitedPorts.begin(), s.excitedPorts.end(), 1) - s.excitedPorts.begin();
sd.syncMode = 0;
sd.syncMaster = 0;
return devices[0]->Configure(sd, [=](Device::TransmissionResult r){
if(cb) {
cb(r == Device::TransmissionResult::Ack);
@ -306,6 +299,7 @@ bool VirtualDevice::setVNA(const VirtualDevice::VNASettings &s, std::function<vo
for(unsigned int i=0;i<devices.size();i++) {
sd.port1Stage = CompoundDevice::PortMapping::findActiveStage(activeMapping, i, 0);
sd.port2Stage = CompoundDevice::PortMapping::findActiveStage(activeMapping, i, 1);
sd.syncMaster = i == 0 ? 1 : 0;
success &= devices[i]->Configure(sd, [=](Device::TransmissionResult r){
if(cb) {
results[devices[i]] = r;
@ -342,34 +336,65 @@ bool VirtualDevice::setSA(const VirtualDevice::SASettings &s, std::function<void
}
zerospan = s.freqStart == s.freqStop;
auto pref = Preferences::getInstance();
Protocol::SpectrumAnalyzerSettings sd;
sd.f_start = s.freqStart;
sd.f_stop = s.freqStop;
sd.pointNum = s.points;
sd.RBW = s.RBW;
sd.WindowType = (int) s.window;
sd.SignalID = s.signalID ? 1 : 0;
sd.Detector = (int) s.detector;
sd.UseDFT = 0;
if(!s.trackingGenerator && pref.Acquisition.useDFTinSAmode && s.RBW <= pref.Acquisition.RBWLimitForDFT) {
sd.UseDFT = 1;
}
sd.applyReceiverCorrection = 1;
sd.trackingGeneratorOffset = s.trackingOffset;
sd.trackingPower = s.trackingPower;
if(!isCompoundDevice()) {
Protocol::SpectrumAnalyzerSettings sd;
sd.f_start = s.freqStart;
sd.f_stop = s.freqStop;
sd.pointNum = s.points;
sd.RBW = s.RBW;
sd.WindowType = (int) s.window;
sd.SignalID = s.signalID ? 1 : 0;
sd.Detector = (int) s.detector;
sd.UseDFT = 0;
if(!s.trackingGenerator && pref.Acquisition.useDFTinSAmode && s.RBW <= pref.Acquisition.RBWLimitForDFT) {
sd.UseDFT = 1;
}
sd.applyReceiverCorrection = 1;
sd.trackingGenerator = s.trackingGenerator ? 1 : 0;
sd.applySourceCorrection = 1;
sd.trackingGeneratorPort = s.trackingPort;
sd.trackingGeneratorOffset = s.trackingOffset;
sd.trackingPower = s.trackingPower;
sd.syncMode = 0;
sd.syncMaster = 0;
return devices[0]->Configure(sd, [=](Device::TransmissionResult r){
if(cb) {
cb(r == Device::TransmissionResult::Ack);
}
});
} else {
// TODO
return false;
// set the synchronization mode
switch(cdev->sync) {
case CompoundDevice::Synchronization::USB: sd.syncMode = 1; break;
case CompoundDevice::Synchronization::ExtRef: sd.syncMode = 2; break;
case CompoundDevice::Synchronization::Trigger: sd.syncMode = 3; break;
}
// Configure the devices
results.clear();
bool success = true;
for(unsigned int i=0;i<devices.size();i++) {
if(s.trackingGenerator) {
if(CompoundDevice::PortMapping::findActiveStage(cdev->portMapping, i, 0) == s.trackingPort) {
sd.trackingGenerator = 1;
sd.trackingGeneratorPort = 0;
} else if(CompoundDevice::PortMapping::findActiveStage(cdev->portMapping, i, 1) == s.trackingPort) {
sd.trackingGenerator = 1;
sd.trackingGeneratorPort = 1;
}
} else {
// not used
sd.trackingGenerator = 0;
sd.trackingGeneratorPort = 0;
}
sd.syncMaster = i == 0 ? 1 : 0;
success &= devices[i]->Configure(sd, [=](Device::TransmissionResult r){
if(cb) {
results[devices[i]] = r;
checkIfAllTransmissionsComplete(cb);
}
});
}
return success;
}
}
@ -520,8 +545,9 @@ VirtualDevice *VirtualDevice::getConnected()
return connected;
}
void VirtualDevice::singleDatapointReceived(Protocol::VNADatapoint<32> *res)
void VirtualDevice::singleDatapointReceived(Device *dev, Protocol::VNADatapoint<32> *res)
{
Q_UNUSED(dev)
VNAMeasurement m;
m.pointNum = res->pointNum;
m.Z0 = 50.0;
@ -548,7 +574,7 @@ void VirtualDevice::singleDatapointReceived(Protocol::VNADatapoint<32> *res)
emit VNAmeasurementReceived(m);
}
void VirtualDevice::compoundDatapointReceivecd(Protocol::VNADatapoint<32> *data, Device *dev)
void VirtualDevice::compoundDatapointReceivecd(Device *dev, Protocol::VNADatapoint<32> *data)
{
if(!compoundVNABuffer.count(data->pointNum)) {
compoundVNABuffer[data->pointNum] = std::map<Device*, Protocol::VNADatapoint<32>*>();
@ -600,18 +626,25 @@ void VirtualDevice::compoundDatapointReceivecd(Protocol::VNADatapoint<32> *data,
emit VNAmeasurementReceived(m);
// Clear this and all incomplete older datapoint buffers
for(auto p : compoundVNABuffer) {
for(auto d : p.second) {
delete d.second;
// Clear this and all (incomplete) older datapoint buffers
int pointNum = data->pointNum;
auto it = compoundVNABuffer.begin();
while(it != compoundVNABuffer.end()) {
if(it->first <= pointNum) {
for(auto d : it->second) {
delete d.second;
}
it = compoundVNABuffer.erase(it);
} else {
it++;
}
}
compoundVNABuffer.clear();
}
}
void VirtualDevice::singleSpectrumResultReceived(Protocol::SpectrumAnalyzerResult res)
void VirtualDevice::singleSpectrumResultReceived(Device *dev, Protocol::SpectrumAnalyzerResult res)
{
Q_UNUSED(dev)
SAMeasurement m;
m.pointNum = res.pointNum;
if(zerospan) {
@ -624,9 +657,47 @@ void VirtualDevice::singleSpectrumResultReceived(Protocol::SpectrumAnalyzerResul
emit SAmeasurementReceived(m);
}
void VirtualDevice::compoundSpectrumResultReceived(Protocol::SpectrumAnalyzerResult res, Device *dev)
void VirtualDevice::compoundSpectrumResultReceived(Device *dev, Protocol::SpectrumAnalyzerResult res)
{
if(!compoundSABuffer.count(res.pointNum)) {
compoundSABuffer[res.pointNum] = std::map<Device*, Protocol::SpectrumAnalyzerResult>();
}
auto &buf = compoundSABuffer[res.pointNum];
buf[dev] = res;
if(buf.size() == devices.size()) {
// Got datapoints from all devices, can create merged VNA result
SAMeasurement m;
m.pointNum = res.pointNum;
if(zerospan) {
m.us = res.us;
} else {
m.frequency = res.frequency;
}
// assemble data
for(unsigned int port=0;port<cdev->portMapping.size();port++) {
auto device = devices[cdev->portMapping[port].device];
auto devicePort = cdev->portMapping[port].port;
QString name = "PORT"+QString::number(port+1);
if(devicePort == 0) {
m.measurements[name] = buf[device].port1;
} else {
m.measurements[name] = buf[device].port2;
}
}
emit SAmeasurementReceived(m);
// Clear this and all (incomplete) older datapoint buffers
auto it = compoundSABuffer.begin();
while(it != compoundSABuffer.end()) {
if(it->first <= res.pointNum) {
it = compoundSABuffer.erase(it);
} else {
it++;
}
}
}
}
void VirtualDevice::compoundInfoUpdated(Device *dev)
@ -778,7 +849,7 @@ VirtualDevice::Info::Info(Device *dev)
Limits.mindBm = (double) info.limits_cdbm_min / 100;
Limits.maxdBm = (double) info.limits_cdbm_max / 100;
Limits.minRBW = info.limits_minRBW;
Limits.maxRBW = info.limits_minRBW;
Limits.maxRBW = info.limits_maxRBW;
}
void VirtualDevice::Info::subset(const VirtualDevice::Info &merge)

View file

@ -141,7 +141,6 @@ public:
struct {
// for non-zero span
double frequency;
double cdbm;
};
struct {
// for zero span
@ -184,10 +183,10 @@ signals:
void NeedsFirmwareUpdate(int usedProtocol, int requiredProtocol);
private slots:
void singleDatapointReceived(Protocol::VNADatapoint<32> *res);
void compoundDatapointReceivecd(Protocol::VNADatapoint<32> *data, Device *dev);
void singleSpectrumResultReceived(Protocol::SpectrumAnalyzerResult res);
void compoundSpectrumResultReceived(Protocol::SpectrumAnalyzerResult res, Device *dev);
void singleDatapointReceived(Device *dev, Protocol::VNADatapoint<32> *res);
void compoundDatapointReceivecd(Device *dev, Protocol::VNADatapoint<32> *data);
void singleSpectrumResultReceived(Device *dev, Protocol::SpectrumAnalyzerResult res);
void compoundSpectrumResultReceived(Device *dev, Protocol::SpectrumAnalyzerResult res);
void compoundInfoUpdated(Device *dev);
void compoundStatusUpdated(Device *dev);
private:

View file

@ -53,6 +53,11 @@ void Generator::fromJSON(nlohmann::json j)
central->fromJSON(j);
}
void Generator::preset()
{
}
void Generator::updateDevice()
{
if(!window->getDevice() || isActive != true) {

View file

@ -21,6 +21,8 @@ public:
void setAveragingMode(Averaging::Mode mode) override {Q_UNUSED(mode)}
void preset() override;
private slots:
void updateDevice();

View file

@ -60,20 +60,7 @@ SpectrumAnalyzer::SpectrumAnalyzer(AppWindow *window, QString name)
traceModel.setSource(TraceModel::DataSource::SA);
// Create default traces
auto tPort1 = new Trace("Port1", Qt::yellow);
tPort1->fromLivedata(Trace::LivedataType::Overwrite, "PORT1");
traceModel.addTrace(tPort1);
auto tPort2 = new Trace("Port2", Qt::blue);
tPort2->fromLivedata(Trace::LivedataType::Overwrite, "PORT2");
traceModel.addTrace(tPort2);
auto traceXY = new TraceXYPlot(traceModel);
traceXY->enableTrace(tPort1, true);
traceXY->enableTrace(tPort2, true);
traceXY->setYAxis(0, YAxis::Type::Magnitude, false, false, -120,0,10);
traceXY->setYAxis(1, YAxis::Type::Disabled, false, true, 0,0,1);
central->setPlot(traceXY);
preset();
// Create menu entries and connections
// Sweep toolbar
@ -1153,11 +1140,42 @@ void SpectrumAnalyzer::StoreSweepSettings()
s.setValue("SASignalID", static_cast<bool>(settings.signalID));
}
void SpectrumAnalyzer::createDefaultTracesAndGraphs(int ports)
{
central->clear();
auto traceXY = new TraceXYPlot(traceModel);
traceXY->setYAxis(0, YAxis::Type::Magnitude, false, false, -120,0,10);
traceXY->setYAxis(1, YAxis::Type::Disabled, false, true, 0,0,1);
traceXY->updateSpan(settings.freqStart, settings.freqStop);
central->setPlot(traceXY);
QColor defaultColors[] = {Qt::yellow, Qt::blue, Qt::red, Qt::green, Qt::gray, Qt::cyan, Qt::magenta, Qt::white};
for(int i=0;i<ports;i++) {
QString param = "PORT"+QString::number(i+1);
auto trace = new Trace(param, defaultColors[i], param);
traceModel.addTrace(trace);
traceXY->enableTrace(trace, true);
}
}
void SpectrumAnalyzer::setAveragingMode(Averaging::Mode mode)
{
average.setMode(mode);
}
void SpectrumAnalyzer::preset()
{
for(auto t : traceModel.getTraces()) {
if(Trace::isSAParameter(t->name())) {
traceModel.removeTrace(t);
}
}
// Create default traces
createDefaultTracesAndGraphs(VirtualDevice::getInfo(window->getDevice()).ports);
}
QString SpectrumAnalyzer::WindowToString(VirtualDevice::SASettings::Window w)
{
switch(w) {

View file

@ -31,6 +31,7 @@ public:
void updateGraphColors();
void setAveragingMode(Averaging::Mode mode) override;
void preset() override;
private:
static QString WindowToString(VirtualDevice::SASettings::Window w);
@ -74,6 +75,8 @@ private:
void LoadSweepSettings();
void StoreSweepSettings();
void createDefaultTracesAndGraphs(int ports);
VirtualDevice::SASettings settings;
bool changingSettings;
unsigned int averages;

View file

@ -48,11 +48,29 @@ void TraceModel::removeTrace(unsigned int index)
}
}
void TraceModel::removeTrace(Trace *t)
{
auto index = findIndex(t);
if(index >= 0) {
removeTrace(index);
}
}
Trace *TraceModel::trace(unsigned int index)
{
return traces.at(index);
}
int TraceModel::findIndex(Trace *t)
{
for(int i=0;i<traces.size();i++) {
if(traces[i] == t) {
return i;
}
}
return -1;
}
void TraceModel::toggleVisibility(unsigned int index)
{
if (index < traces.size()) {
@ -184,7 +202,7 @@ void TraceModel::fromJSON(nlohmann::json j)
{
// clear old traces
while(traces.size()) {
removeTrace(0);
removeTrace((int) 0);
}
for(auto jt : j) {
auto trace = new Trace();

View file

@ -33,7 +33,9 @@ public:
void addTrace(Trace *t);
void removeTrace(unsigned int index);
void removeTrace(Trace *t);
Trace *trace(unsigned int index);
int findIndex(Trace *t);
void toggleVisibility(unsigned int index);
void togglePause(unsigned int index);
void toggleMath(unsigned int index);

View file

@ -105,7 +105,7 @@ class TraceSmithChart : public TracePlot
public:
TraceSmithChart(TraceModel &model, QWidget *parent = 0);
virtual Type getType() override { return Type::SmithChart;};
virtual Type getType() override { return Type::SmithChart;}
virtual nlohmann::json toJSON() override;
virtual void fromJSON(nlohmann::json j) override;

View file

@ -21,6 +21,7 @@ public:
QVariant value() {
return QVariant(variant.type(), ptr);
}
void* getPtr(){return ptr;}
private:
void *ptr;
QVariant variant;

View file

@ -71,40 +71,10 @@ VNA::VNA(AppWindow *window, QString name)
traceModel.setSource(TraceModel::DataSource::VNA);
// Create default traces
auto tS11 = new Trace("S11", Qt::yellow);
tS11->fromLivedata(Trace::LivedataType::Overwrite, "S11");
traceModel.addTrace(tS11);
auto tS12 = new Trace("S12", Qt::blue);
tS12->fromLivedata(Trace::LivedataType::Overwrite, "S12");
traceModel.addTrace(tS12);
auto tS21 = new Trace("S21", Qt::green);
tS21->fromLivedata(Trace::LivedataType::Overwrite, "S21");
traceModel.addTrace(tS21);
auto tS22 = new Trace("S22", Qt::red);
tS22->fromLivedata(Trace::LivedataType::Overwrite, "S22");
traceModel.addTrace(tS22);
auto tracesmith1 = new TraceSmithChart(traceModel);
tracesmith1->enableTrace(tS11, true);
auto tracesmith2 = new TraceSmithChart(traceModel);
tracesmith2->enableTrace(tS22, true);
auto traceXY1 = new TraceXYPlot(traceModel);
traceXY1->enableTrace(tS12, true);
auto traceXY2 = new TraceXYPlot(traceModel);
traceXY2->enableTrace(tS21, true);
createDefaultTracesAndGraphs(2);
connect(&traceModel, &TraceModel::requiredExcitation, this, &VNA::ExcitationRequired);
central->splitVertically();
central->Child1()->splitHorizontally();
central->Child2()->splitHorizontally();
central->Child1()->Child1()->setPlot(tracesmith1);
central->Child1()->Child2()->setPlot(traceXY1);
central->Child2()->Child1()->setPlot(traceXY2);
central->Child2()->Child2()->setPlot(tracesmith2);
// Create menu entries and connections
auto calMenu = new QMenu("Calibration", window);
window->menuBar()->insertMenu(window->getUi()->menuWindow->menuAction(), calMenu);
@ -924,7 +894,7 @@ void VNA::SettingsChanged(bool resetTraces, std::function<void (bool)> cb)
// assemble VNA protocol settings
VirtualDevice::VNASettings s = {};
s.IFBW = settings.bandwidth;
if(Preferences::getInstance().Acquisition.alwaysExciteBothPorts) {
if(Preferences::getInstance().Acquisition.alwaysExciteAllPorts) {
for(int i=0;i<VirtualDevice::getInfo(window->getDevice()).ports;i++) {
s.excitedPorts.push_back(i);
}
@ -1183,7 +1153,7 @@ void VNA::SetAveraging(unsigned int averages)
void VNA::ExcitationRequired()
{
if(!Preferences::getInstance().Acquisition.alwaysExciteBothPorts) {
if(!Preferences::getInstance().Acquisition.alwaysExciteAllPorts) {
for(int i=1;i<VirtualDevice::getInfo(window->getDevice()).ports;i++) {
auto required = traceModel.PortExcitationRequired(i);
auto set = find(settings.excitedPorts.begin(), settings.excitedPorts.end(), i) != settings.excitedPorts.end();
@ -1624,6 +1594,92 @@ void VNA::UpdateCalWidget()
calLabel->setToolTip(getCalToolTip());
}
void VNA::createDefaultTracesAndGraphs(int ports)
{
auto getDefaultColor = [](int ports, int i, int j)->QColor {
// Default colors for up to four ports, ensures that e.g. S21 always has the same color
const array<vector<QColor>, 4> defaultColors = {{
{Qt::yellow},
{Qt::yellow, Qt::blue, Qt::green, Qt::red},
{Qt::yellow, Qt::blue, Qt::cyan, Qt::green, Qt::red, Qt::darkGreen, Qt::darkBlue, Qt::darkYellow, Qt::magenta},
{Qt::yellow, Qt::blue, Qt::cyan, Qt::darkCyan, Qt::green, Qt::red, Qt::darkGreen, Qt::gray, Qt::darkBlue, Qt::darkYellow, Qt::magenta, Qt::darkMagenta, Qt::cyan, Qt::darkGray, Qt::lightGray, Qt::darkRed},
}};
if(ports >= 1 && ports <= 4) {
return defaultColors[ports-1][i*ports+j];
} else {
// not enough predefined colors available for all ports, just cycle through list
const array<QColor, 16> list = {{
Qt::yellow, Qt::blue, Qt::green, Qt::red, Qt::cyan, Qt::magenta, Qt::yellow, Qt::darkRed, Qt::darkGreen, Qt::darkBlue, Qt::gray, Qt::darkCyan, Qt::darkMagenta, Qt::darkYellow, Qt::darkGray, Qt::lightGray
}};
auto index = (i*ports+j) % list.size();
return list[index];
}
};
vector<vector<TracePlot*>> plots;
for(int i=0;i<ports;i++) {
plots.push_back(vector<TracePlot*>());
for(int j=0;j<ports;j++) {
QString param = "S"+QString::number(i+1)+QString::number(j+1);
auto trace = new Trace(param, getDefaultColor(ports, i, j), param);
traceModel.addTrace(trace);
TracePlot *plot;
if(i == j) {
plot = new TraceSmithChart(traceModel);
} else {
plot = new TraceXYPlot(traceModel);
}
plot->updateSpan(settings.Freq.start, settings.Freq.stop);
plot->enableTrace(trace, true);
plots[i].push_back(plot);
}
}
// Add created graphs to tiles
central->clear();
TileWidget *tile = central;
for(int i=0;i<ports;i++) {
TileWidget *row;
if(i != ports - 1) {
// this is not the last row, split tile
tile->splitVertically();
row = tile->Child1();
tile = tile->Child2();
} else {
row = tile;
}
for(int j=0;j<ports;j++) {
TileWidget *graphTile;
if(j != ports - 1) {
row->splitHorizontally();
graphTile = row->Child1();
row = row->Child2();
} else {
graphTile = row;
}
graphTile->setPlot(plots[i][j]);
}
}
if(ports >= 3) {
// default split at the middle does not result in all plots being the same size, adjust
tile = central;
for(int i=0;i<ports;i++) {
TileWidget *rowTile;
if(i < ports - 1) {
tile->setSplitPercentage(100 / (ports - i));
rowTile = tile->Child1();
} else {
rowTile = tile;
}
for(int j=0;j<ports-1;j++) {
rowTile->setSplitPercentage(100 / (ports - j));
rowTile = rowTile->Child2();
}
tile = tile->Child2();
}
}
}
void VNA::EnableDeembedding(bool enable)
{
deembedding_active = enable;
@ -1637,6 +1693,17 @@ void VNA::setAveragingMode(Averaging::Mode mode)
average.setMode(mode);
}
void VNA::preset()
{
for(auto t : traceModel.getTraces()) {
if(Trace::isVNAParameter(t->name())) {
traceModel.removeTrace(t);
}
}
// Create default traces
createDefaultTracesAndGraphs(VirtualDevice::getInfo(window->getDevice()).ports);
}
QString VNA::SweepTypeToString(VNA::SweepType sw)
{
switch(sw) {

View file

@ -33,6 +33,8 @@ public:
void updateGraphColors();
void setAveragingMode(Averaging::Mode mode) override;
void preset() override;
enum class SweepType {
Frequency = 0,
Power = 1,
@ -121,6 +123,8 @@ private:
void StopSweep();
void StartCalibrationDialog(Calibration::Type type = Calibration::Type::None);
void UpdateCalWidget();
void createDefaultTracesAndGraphs(int ports);
private slots:
void EnableDeembedding(bool enable);
void UpdateStatusbar();

View file

@ -236,6 +236,11 @@ void AppWindow::SetupMenu()
connect(ui->actionSource_Calibration, &QAction::triggered, this, &AppWindow::SourceCalibrationDialog);
connect(ui->actionReceiver_Calibration, &QAction::triggered, this, &AppWindow::ReceiverCalibrationDialog);
connect(ui->actionFrequency_Calibration, &QAction::triggered, this, &AppWindow::FrequencyCalibrationDialog);
connect(ui->actionPreset, &QAction::triggered, [=](){
modeHandler->getActiveMode()->preset();
});
connect(ui->actionPreferences, &QAction::triggered, [=](){
// save previous SCPI settings in case they change
auto &p = Preferences::getInstance();
@ -338,6 +343,7 @@ bool AppWindow::ConnectToDevice(QString serial)
ui->actionReceiver_Calibration->setEnabled(true);
ui->actionFrequency_Calibration->setEnabled(true);
}
ui->actionPreset->setEnabled(true);
UpdateAcquisitionFrequencies();
@ -368,6 +374,7 @@ void AppWindow::DisconnectDevice()
ui->actionSource_Calibration->setEnabled(false);
ui->actionReceiver_Calibration->setEnabled(false);
ui->actionFrequency_Calibration->setEnabled(false);
ui->actionPreset->setEnabled(false);
for(auto a : deviceActionGroup->actions()) {
a->setChecked(false);
}

View file

@ -82,8 +82,15 @@
</property>
<addaction name="actionAbout"/>
</widget>
<widget class="QMenu" name="menuView">
<property name="title">
<string>View</string>
</property>
<addaction name="actionPreset"/>
</widget>
<addaction name="menuFile"/>
<addaction name="menuDevice"/>
<addaction name="menuView"/>
<addaction name="menuWindow"/>
<addaction name="menuHelp"/>
</widget>
@ -209,6 +216,14 @@
<string>Frequency Calibration</string>
</property>
</action>
<action name="actionPreset">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Preset</string>
</property>
</action>
</widget>
<resources>
<include location="icons.qrc"/>

View file

@ -43,6 +43,8 @@ public:
virtual void setAveragingMode(Averaging::Mode mode) = 0;
virtual void preset() = 0;
signals:
void statusbarMessage(QString msg);
protected:

View file

@ -138,6 +138,10 @@ PreferencesDialog::PreferencesDialog(Preferences *pref, QWidget *parent) :
auto index = ui->compoundList->currentRow();
if(index >= 0 && index < p->compoundDevices.size()) {
auto d = new CompoundDeviceEditDialog(p->compoundDevices[index]);
connect(d, &QDialog::accepted, [=](){
ui->compoundList->item(index)->setText(p->compoundDevices[index]->getDesription());
p->nonTrivialWriting();
});
d->show();
}
});
@ -276,7 +280,7 @@ void PreferencesDialog::setInitialGUIState()
ui->StartupSAAveraging->setValue(p->Startup.SA.averaging);
ui->StartupSASignalID->setChecked(p->Startup.SA.signalID);
ui->AcquisitionAlwaysExciteBoth->setChecked(p->Acquisition.alwaysExciteBothPorts);
ui->AcquisitionAlwaysExciteBoth->setChecked(p->Acquisition.alwaysExciteAllPorts);
ui->AcquisitionSuppressPeaks->setChecked(p->Acquisition.suppressPeaks);
ui->AcquisitionAdjustPowerLevel->setChecked(p->Acquisition.adjustPowerLevel);
ui->AcquisitionUseHarmonic->setChecked(p->Acquisition.harmonicMixing);
@ -346,7 +350,7 @@ void PreferencesDialog::updateFromGUI()
p->Startup.SA.detector = ui->StartupSADetector->currentIndex();
p->Startup.SA.signalID = ui->StartupSASignalID->isChecked();
p->Acquisition.alwaysExciteBothPorts = ui->AcquisitionAlwaysExciteBoth->isChecked();
p->Acquisition.alwaysExciteAllPorts = ui->AcquisitionAlwaysExciteBoth->isChecked();
p->Acquisition.suppressPeaks = ui->AcquisitionSuppressPeaks->isChecked();
p->Acquisition.adjustPowerLevel = ui->AcquisitionAdjustPowerLevel->isChecked();
p->Acquisition.harmonicMixing = ui->AcquisitionUseHarmonic->isChecked();
@ -379,6 +383,8 @@ void PreferencesDialog::updateFromGUI()
p->SCPIServer.enabled = ui->SCPIServerEnabled->isChecked();
p->SCPIServer.port = ui->SCPIServerPort->value();
p->nonTrivialWriting();
}
void Preferences::load()

View file

@ -83,7 +83,7 @@ public:
} SA;
} Startup;
struct {
bool alwaysExciteBothPorts;
bool alwaysExciteAllPorts;
bool suppressPeaks;
bool adjustPowerLevel;
bool harmonicMixing;
@ -145,7 +145,9 @@ public:
private:
Preferences() :
TCPoverride(false) {}
TCPoverride(false) {
qDebug() << "Pref constructor: " << &compoundDeviceJSON;
}
static Preferences instance;
const std::vector<Savable::SettingDescription> descr = {{
@ -174,7 +176,7 @@ private:
{&Startup.SA.detector, "Startup.SA.detector", 0},
{&Startup.SA.averaging, "Startup.SA.averaging", 1},
{&Startup.SA.signalID, "Startup.SA.signalID", true},
{&Acquisition.alwaysExciteBothPorts, "Acquisition.alwaysExciteBothPorts", true},
{&Acquisition.alwaysExciteAllPorts, "Acquisition.alwaysExciteBothPorts", true},
{&Acquisition.suppressPeaks, "Acquisition.suppressPeaks", true},
{&Acquisition.adjustPowerLevel, "Acquisition.adjustPowerLevel", false},
{&Acquisition.harmonicMixing, "Acquisition.harmonicMixing", false},

View file

@ -84,7 +84,7 @@
<x>0</x>
<y>0</y>
<width>687</width>
<height>884</height>
<height>938</height>
</rect>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_12">
@ -103,7 +103,7 @@
</size>
</property>
<property name="currentIndex">
<number>5</number>
<number>1</number>
</property>
<widget class="QWidget" name="Startup">
<layout class="QHBoxLayout" name="horizontalLayout_4">
@ -714,7 +714,7 @@
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;If only S11/S21 or S22/S12 are enabled, faster sweeps are possible by only exciting one port. Checking this option forces the device to always excite both ports even when the measurements from one port will not be used.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>Always perform full 2-port measurement</string>
<string>Always create the stimulus signal at all ports</string>
</property>
</widget>
</item>