diff --git a/Software/PC_Application/Application b/Software/PC_Application/Application index 8109389..b26a655 100755 Binary files a/Software/PC_Application/Application and b/Software/PC_Application/Application differ diff --git a/Software/PC_Application/Generator/generator.cpp b/Software/PC_Application/Generator/generator.cpp index a1a507b..fa3659d 100644 --- a/Software/PC_Application/Generator/generator.cpp +++ b/Software/PC_Application/Generator/generator.cpp @@ -19,7 +19,9 @@ void Generator::updateDevice() // can't updat if not connected return; } - auto status = central->getDeviceStatus(); // TODO comment in once status is filled with valid values -// window->getDevice()->SetManual(status); + Protocol::PacketInfo p; + p.type = Protocol::PacketType::Generator; + p.generator = central->getDeviceStatus(); + window->getDevice()->SendPacket(p); } diff --git a/Software/PC_Application/Generator/signalgenwidget.cpp b/Software/PC_Application/Generator/signalgenwidget.cpp index 5b67e8f..23fa4ea 100644 --- a/Software/PC_Application/Generator/signalgenwidget.cpp +++ b/Software/PC_Application/Generator/signalgenwidget.cpp @@ -42,10 +42,18 @@ SignalgeneratorWidget::~SignalgeneratorWidget() delete ui; } -Protocol::ManualControl SignalgeneratorWidget::getDeviceStatus() +Protocol::GeneratorSettings SignalgeneratorWidget::getDeviceStatus() { - // TODO - Protocol::ManualControl s = {}; + Protocol::GeneratorSettings s = {}; + s.frequency = ui->frequency->value(); + s.cdbm_level = ui->levelSpin->value() * 100.0; + if(ui->EnablePort1->isChecked()) { + s.activePort = 1; + } else if(ui->EnablePort2->isChecked()) { + s.activePort = 2; + } else { + s.activePort = 0; + } return s; } diff --git a/Software/PC_Application/Generator/signalgenwidget.h b/Software/PC_Application/Generator/signalgenwidget.h index 8ef4e05..4e91aff 100644 --- a/Software/PC_Application/Generator/signalgenwidget.h +++ b/Software/PC_Application/Generator/signalgenwidget.h @@ -16,7 +16,7 @@ public: explicit SignalgeneratorWidget(QWidget *parent = nullptr); ~SignalgeneratorWidget(); - Protocol::ManualControl getDeviceStatus(); + Protocol::GeneratorSettings getDeviceStatus(); signals: void SettingsChanged(); diff --git a/Software/PC_Application/VNA/vna.cpp b/Software/PC_Application/VNA/vna.cpp index 0a72c6f..2091fd2 100644 --- a/Software/PC_Application/VNA/vna.cpp +++ b/Software/PC_Application/VNA/vna.cpp @@ -126,21 +126,31 @@ VNA::VNA(AppWindow *window) auto impedanceMatching = toolsMenu->addAction("Impedance Matching"); connect(impedanceMatching, &QAction::triggered, this, &VNA::StartImpedanceMatching); - connect(window->getUi()->actionAssignDefaultCal, &QAction::triggered, [=](){ + defaultCalMenu = new QMenu("Default Calibration"); + assignDefaultCal = defaultCalMenu->addAction("Assign..."); + removeDefaultCal = defaultCalMenu->addAction("Remove"); + removeDefaultCal->setEnabled(false); + defaultCalMenu->setEnabled(false); + + actions.insert(window->getUi()->menuDevice->addSeparator()); + window->getUi()->menuDevice->addMenu(defaultCalMenu); + actions.insert(defaultCalMenu->menuAction()); + + connect(assignDefaultCal, &QAction::triggered, [=](){ if(window->getDevice()) { auto key = "DefaultCalibration"+window->getDevice()->serial(); QSettings settings; auto filename = QFileDialog::getOpenFileName(nullptr, "Load calibration data", settings.value(key).toString(), "Calibration files (*.cal)", nullptr, QFileDialog::DontUseNativeDialog); if(!filename.isEmpty()) { settings.setValue(key, filename); - window->getUi()->actionRemoveDefaultCal->setEnabled(true); + removeDefaultCal->setEnabled(true); } } }); - connect(window->getUi()->actionRemoveDefaultCal, &QAction::triggered, [=](){ + connect(removeDefaultCal, &QAction::triggered, [=](){ QSettings settings; settings.remove("DefaultCalibration"+window->getDevice()->serial()); - window->getUi()->actionRemoveDefaultCal->setEnabled(false); + removeDefaultCal->setEnabled(false); }); @@ -432,6 +442,7 @@ void VNA::deactivate() void VNA::initializeDevice() { + defaultCalMenu->setEnabled(true); connect(window->getDevice(), &Device::DatapointReceived, this, &VNA::NewDatapoint, Qt::UniqueConnection); // Check if default calibration exists and attempt to load it QSettings s; @@ -443,15 +454,20 @@ void VNA::initializeDevice() cal.openFromFile(filename); ApplyCalibration(cal.getType()); } - window->getUi()->actionRemoveDefaultCal->setEnabled(true); + removeDefaultCal->setEnabled(true); } else { qDebug() << "No default calibration file set for this device"; - window->getUi()->actionRemoveDefaultCal->setEnabled(false); + removeDefaultCal->setEnabled(false); } // Configure initial state of device window->getDevice()->Configure(settings); } +void VNA::deviceDisconnected() +{ + defaultCalMenu->setEnabled(false); +} + using namespace std; void VNA::NewDatapoint(Protocol::Datapoint d) diff --git a/Software/PC_Application/VNA/vna.h b/Software/PC_Application/VNA/vna.h index 27066a1..f4d8f08 100644 --- a/Software/PC_Application/VNA/vna.h +++ b/Software/PC_Application/VNA/vna.h @@ -15,6 +15,7 @@ public: void deactivate() override; void initializeDevice() override; + void deviceDisconnected() override; private slots: void NewDatapoint(Protocol::Datapoint d); void StartImpedanceMatching(); @@ -63,6 +64,9 @@ private: bool calWaitFirst; QProgressDialog calDialog; + QMenu *defaultCalMenu; + QAction *assignDefaultCal, *removeDefaultCal; + // Status Labels QLabel *lStart, *lCenter, *lStop, *lSpan, *lPoints, *lBandwidth; QLabel *lCalibration; diff --git a/Software/PC_Application/appwindow.cpp b/Software/PC_Application/appwindow.cpp index c9f46d4..45f6bb2 100644 --- a/Software/PC_Application/appwindow.cpp +++ b/Software/PC_Application/appwindow.cpp @@ -168,11 +168,19 @@ void AppWindow::ConnectToDevice(QString serial) }); ui->actionDisconnect->setEnabled(true); ui->actionManual_Control->setEnabled(true); - ui->menuDefault_Calibration->setEnabled(true); ui->actionFirmware_Update->setEnabled(true); Mode::getActiveMode()->initializeDevice(); UpdateReference(); + + for(auto d : deviceActionGroup->actions()) { + if(d->text() == device->serial()) { + d->blockSignals(true); + d->setChecked(true); + d->blockSignals(false); + break; + } + } } catch (const runtime_error e) { DisconnectDevice(); UpdateDeviceList(); @@ -187,13 +195,13 @@ void AppWindow::DisconnectDevice() } ui->actionDisconnect->setEnabled(false); ui->actionManual_Control->setEnabled(false); - ui->menuDefault_Calibration->setEnabled(false); ui->actionFirmware_Update->setEnabled(false); if(deviceActionGroup->checkedAction()) { deviceActionGroup->checkedAction()->setChecked(false); } lConnectionStatus.setText("No device connected"); lDeviceInfo.setText("No device information available yet"); + Mode::getActiveMode()->deviceDisconnected(); } void AppWindow::DeviceConnectionLost() diff --git a/Software/PC_Application/main.ui b/Software/PC_Application/main.ui index deacbc8..e00228d 100644 --- a/Software/PC_Application/main.ui +++ b/Software/PC_Application/main.ui @@ -42,22 +42,11 @@ - - - false - - - Default Calibration - - - - - @@ -137,19 +126,6 @@ Dummy - - - Assign... - - - - - false - - - Remove - - false diff --git a/Software/PC_Application/mode.h b/Software/PC_Application/mode.h index 26eecc1..d747c53 100644 --- a/Software/PC_Application/mode.h +++ b/Software/PC_Application/mode.h @@ -19,6 +19,7 @@ public: static Mode *getActiveMode(); virtual void initializeDevice() = 0; + virtual void deviceDisconnected(){}; protected: // call once the derived class is fully initialized diff --git a/Software/VNA_embedded/Application/App.cpp b/Software/VNA_embedded/Application/App.cpp index 8aa10cd..998ca60 100644 --- a/Software/VNA_embedded/Application/App.cpp +++ b/Software/VNA_embedded/Application/App.cpp @@ -166,11 +166,13 @@ void App_Start() { VNA::ConfigureSweep(settings, VNACallback); sweepActive = true; lastNewPoint = HAL_GetTick(); + Communication::SendWithoutPayload(Protocol::PacketType::Ack); break; case Protocol::PacketType::ManualControl: sweepActive = false; manual = packet.manual; VNA::ConfigureManual(manual, VNAStatusCallback); + Communication::SendWithoutPayload(Protocol::PacketType::Ack); break; case Protocol::PacketType::Reference: reference = packet.reference; @@ -178,6 +180,13 @@ void App_Start() { // can update right now VNA::Ref::applySettings(reference); } + Communication::SendWithoutPayload(Protocol::PacketType::Ack); + break; + case Protocol::PacketType::Generator: + sweepActive = false; + LOG_INFO("Updating generator setting"); + VNA::ConfigureGenerator(packet.generator); + Communication::SendWithoutPayload(Protocol::PacketType::Ack); break; #ifdef HAS_FLASH case Protocol::PacketType::ClearFlash: diff --git a/Software/VNA_embedded/Application/Communication/Protocol.cpp b/Software/VNA_embedded/Application/Communication/Protocol.cpp index 2059f8b..1bbe155 100644 --- a/Software/VNA_embedded/Application/Communication/Protocol.cpp +++ b/Software/VNA_embedded/Application/Communication/Protocol.cpp @@ -204,6 +204,23 @@ static int16_t EncodeReferenceSettings(Protocol::ReferenceSettings d, uint8_t *b return e.getSize(); } +static Protocol::GeneratorSettings DecodeGeneratorSettings(uint8_t *buf) { + Protocol::GeneratorSettings d; + Decoder e(buf); + e.get(d.frequency); + e.get(d.cdbm_level); + e.get(d.activePort); + return d; +} +static int16_t EncodeGeneratorSettings(Protocol::GeneratorSettings d, uint8_t *buf, + uint16_t bufSize) { + Encoder e(buf, bufSize); + e.add(d.frequency); + e.add(d.cdbm_level); + e.add(d.activePort); + return e.getSize(); +} + static Protocol::DeviceInfo DecodeDeviceInfo(uint8_t *buf) { Protocol::DeviceInfo d; Decoder e(buf); @@ -420,6 +437,9 @@ uint16_t Protocol::DecodeBuffer(uint8_t *buf, uint16_t len, PacketInfo *info) { case PacketType::FirmwarePacket: info->firmware = DecodeFirmwarePacket(&data[4]); break; + case PacketType::Generator: + info->generator = DecodeGeneratorSettings(&data[4]); + break; case PacketType::Ack: case PacketType::PerformFirmwareUpdate: case PacketType::ClearFlash: @@ -444,7 +464,7 @@ uint16_t Protocol::EncodePacket(PacketInfo packet, uint8_t *dest, uint16_t dests break; case PacketType::Reference: payload_size = EncodeReferenceSettings(packet.reference, &dest[4], destsize - 8); - break; + break; case PacketType::DeviceInfo: payload_size = EncodeDeviceInfo(packet.info, &dest[4], destsize - 8); break; @@ -457,6 +477,9 @@ uint16_t Protocol::EncodePacket(PacketInfo packet, uint8_t *dest, uint16_t dests case PacketType::FirmwarePacket: payload_size = EncodeFirmwarePacket(packet.firmware, &dest[4], destsize - 8); break; + case PacketType::Generator: + payload_size = EncodeGeneratorSettings(packet.generator, &dest[4], destsize - 8); + break; case PacketType::Ack: case PacketType::PerformFirmwareUpdate: case PacketType::ClearFlash: diff --git a/Software/VNA_embedded/Application/Communication/Protocol.hpp b/Software/VNA_embedded/Application/Communication/Protocol.hpp index 0425c0a..a4c6dee 100644 --- a/Software/VNA_embedded/Application/Communication/Protocol.hpp +++ b/Software/VNA_embedded/Application/Communication/Protocol.hpp @@ -29,6 +29,12 @@ using ReferenceSettings = struct _referenceSettings { uint8_t UseExternalRef:1; }; +using GeneratorSettings = struct _generatorSettings { + uint64_t frequency; + int16_t cdbm_level; + uint8_t activePort; +}; + using DeviceInfo = struct _deviceInfo { uint16_t FW_major; uint16_t FW_minor; @@ -109,6 +115,7 @@ enum class PacketType : uint8_t { PerformFirmwareUpdate = 9, Nack = 10, Reference = 11, + Generator = 12, }; using PacketInfo = struct _packetinfo { @@ -117,6 +124,7 @@ using PacketInfo = struct _packetinfo { Datapoint datapoint; SweepSettings settings; ReferenceSettings reference; + GeneratorSettings generator; DeviceInfo info; ManualControl manual; ManualStatus status; diff --git a/Software/VNA_embedded/Application/VNA.cpp b/Software/VNA_embedded/Application/VNA.cpp index 5f9bde0..354d0b8 100644 --- a/Software/VNA_embedded/Application/VNA.cpp +++ b/Software/VNA_embedded/Application/VNA.cpp @@ -490,3 +490,80 @@ bool VNA::Ref::applySettings(Protocol::ReferenceSettings s) { } return false; } + +bool VNA::ConfigureGenerator(Protocol::GeneratorSettings g) { + Protocol::ManualControl m; + // LOs not required + m.LO1CE = 0; + m.LO1Frequency = 1000000000; + m.LO1RFEN = 0; + m.LO1RFEN = 0; + m.LO2EN = 0; + m.LO2Frequency = 60000000; + m.Port1EN = 0; + m.Port2EN = 0; + m.RefEN = 0; + m.Samples = 131072; + // Select correct source + if(g.frequency < BandSwitchFrequency) { + m.SourceLowEN = 1; + m.SourceLowFrequency = g.frequency; + m.SourceHighCE = 0; + m.SourceHighRFEN = 0; + m.SourceHighFrequency = BandSwitchFrequency; + m.SourceHighLowpass = (int) FPGA::LowpassFilter::M947; + m.SourceHighPower = (int) MAX2871::Power::n4dbm; + m.SourceHighband = false; + } else { + m.SourceLowEN = 0; + m.SourceLowFrequency = BandSwitchFrequency; + m.SourceHighCE = 1; + m.SourceHighRFEN = 1; + m.SourceHighFrequency = g.frequency; + if(g.frequency < 900000000UL) { + m.SourceHighLowpass = (int) FPGA::LowpassFilter::M947; + } else if(g.frequency < 1800000000UL) { + m.SourceHighLowpass = (int) FPGA::LowpassFilter::M1880; + } else if(g.frequency < 3500000000UL) { + m.SourceHighLowpass = (int) FPGA::LowpassFilter::M3500; + } else { + m.SourceHighLowpass = (int) FPGA::LowpassFilter::None; + } + m.SourceHighband = true; + } + switch(g.activePort) { + case 0: + // no output signal, disable + m.AmplifierEN = 0; + m.SourceHighCE = 0; + m.SourceHighRFEN = 0; + m.SourceLowEN = 0; + break; + case 1: + m.AmplifierEN = 1; + m.PortSwitch = 0; + break; + case 2: + m.AmplifierEN = 1; + m.PortSwitch = 1; + break; + } + // Set level (not very accurate) + if(g.cdbm_level > -1000) { + // use higher source power (approx 0dbm with no attenuation) + m.SourceHighPower = (int) MAX2871::Power::p5dbm; + m.SourceLowPower = (int) Si5351C::DriveStrength::mA8; + } else { + // use lower source power (approx -10dbm with no attenuation) + m.SourceHighPower = (int) MAX2871::Power::n4dbm; + m.SourceLowPower = (int) Si5351C::DriveStrength::mA2; + g.cdbm_level += 1000; + } + // calculate required attenuation + uint16_t attval = -g.cdbm_level / 25; + if(attval > 127) { + attval = 127; + } + m.attenuator = attval; + return ConfigureManual(m, nullptr); +} diff --git a/Software/VNA_embedded/Application/VNA.hpp b/Software/VNA_embedded/Application/VNA.hpp index 0a90d83..526bc49 100644 --- a/Software/VNA_embedded/Application/VNA.hpp +++ b/Software/VNA_embedded/Application/VNA.hpp @@ -12,6 +12,7 @@ using StatusCallback = void(*)(FPGA::SamplingResult); bool Init(); bool ConfigureSweep(Protocol::SweepSettings s, SweepCallback cb); bool ConfigureManual(Protocol::ManualControl m, StatusCallback cb); +bool ConfigureGenerator(Protocol::GeneratorSettings g); // Only call the following function when the sweep is inactive bool GetTemps(uint8_t *source, uint8_t *lo);