diff --git a/Documentation/DeveloperInfo/USB_protocol_v12.pdf b/Documentation/DeveloperInfo/USB_protocol_v12.pdf index a765f10..2b1323e 100644 Binary files a/Documentation/DeveloperInfo/USB_protocol_v12.pdf and b/Documentation/DeveloperInfo/USB_protocol_v12.pdf differ diff --git a/Documentation/DeveloperInfo/USB_protocol_v12.tex b/Documentation/DeveloperInfo/USB_protocol_v12.tex index a4757cd..854db97 100644 --- a/Documentation/DeveloperInfo/USB_protocol_v12.tex +++ b/Documentation/DeveloperInfo/USB_protocol_v12.tex @@ -250,6 +250,7 @@ The following packet types are available: 29 & ClearTrigger & D$\leftrightarrow$H & Updates the trigger status for synchronization over USB & None\\ 30 & StopStatusUpdates & H$\rightarrow$D & Stops the automatic transmission of device status packets & None\\ 31 & StartStatusUpdates & H$\rightarrow$D & Starts the automatic transmission of device status packets & None\\ +32 & InitiateSweep & H$\rightarrow$D & Initiates a single sweep when configured for standby operation & None\\ \end{longtable} \end{ThreePartTable} An Ack is transmitted by the device for every received command after it has been handled successfully. If additional responses are triggered by the command, they are transmitted after this Ack. @@ -299,7 +300,7 @@ The packet contains the following fields: \rwbits{12}{1}{FP} \rwbits{13}{1}{SP} \rwbits{14}{1}{SM} -\robits{15}{1}{} +\rwbits{15}{1}{SO} \end{tikzpicture} \end{center} \begin{itemize} @@ -337,6 +338,15 @@ Setting & Behavior\\ \end{tabularx} \end{center} \item \textbf{SM:} Sync Master. Must be set to 1 at exactly one device when multiple devices are synchronized. Set to 0 when synchronization is disabled. +\item \textbf{SO:} Standby Operation. Indicates whether the VNA will begin sweep immediately, or wait in the configured state to be triggered manually by InitiateSweep packets. Standy operation allows for lower latency of intermittent single sweeps. +\begin{center} +\begin{tabularx}{\textwidth}{ c|X } +Setting & Behavior\\ + \hline +0 & VNA will begin sweep immediately and timeout to idle mode 1000ms after sweep is completed or 100ms after entering the halted state. \\ +1 & VNA will wait in a configured state for InitiateSweep packets. The host application is responsible for putting the VNA into idle mode with a SetIdle packet.\\ +\end{tabularx} +\end{center} \end{itemize} \subsection{ManualStatusV1} @@ -1018,4 +1028,7 @@ This packet instructs the device to stop sending automatically scheduled DeviceS \subsection{StartStatusUpdates} This packet instructs the device to start sending automatically scheduled DeviceStatusV1 packets. This restores default update behaviour if a StopStatusUpdates packet has previously been sent. +\subsection{InitiateSweep} +This packet instructs the device to initiate a new single sweep when the VNA is configured for standby operation. This triggering method can be used for fast intermittent single sweeps with minimum latency. If the SweepSettings are not configured for standby operation, this packet will result in a Nack response. + \end{document} diff --git a/Software/PC_Application/.gitignore b/Software/PC_Application/.gitignore index f5c9271..273a686 100644 --- a/Software/PC_Application/.gitignore +++ b/Software/PC_Application/.gitignore @@ -75,6 +75,8 @@ Application /build-* /LibreVNA-GUI/LibreVNA-GUI /LibreVNA-Test/LibreVNA-Test +/LibreVNA-GUI/users*appdatalocaltemp* + diff --git a/Software/PC_Application/LibreVNA-GUI/Calibration/calstandard.cpp b/Software/PC_Application/LibreVNA-GUI/Calibration/calstandard.cpp index b96447e..0c84a11 100644 --- a/Software/PC_Application/LibreVNA-GUI/Calibration/calstandard.cpp +++ b/Software/PC_Application/LibreVNA-GUI/Calibration/calstandard.cpp @@ -619,7 +619,7 @@ void Through::edit(std::function finishedCallback) QObject::connect(ui->touchstoneImport, &TouchstoneImport::statusChanged, ui->updateFile, &QPushButton::setEnabled); - ui->touchstoneImport->setPorts(1); + ui->touchstoneImport->setPorts(2); if(touchstone) { ui->measurement->setChecked(true); ui->touchstoneImport->setFile(touchstone->getFilename()); @@ -628,7 +628,7 @@ void Through::edit(std::function finishedCallback) } QObject::connect(ui->updateFile, &QPushButton::clicked, [=](){ - setMeasurement(ui->touchstoneImport->getTouchstone(), ui->touchstoneImport->getPorts()[0]); + setMeasurement(ui->touchstoneImport->getTouchstone(), ui->touchstoneImport->getPorts()[0], ui->touchstoneImport->getPorts()[1]); updateMeasurementLabel(); }); diff --git a/Software/PC_Application/LibreVNA-GUI/Traces/Math/tracemath.h b/Software/PC_Application/LibreVNA-GUI/Traces/Math/tracemath.h index 3a043b9..08d06dc 100644 --- a/Software/PC_Application/LibreVNA-GUI/Traces/Math/tracemath.h +++ b/Software/PC_Application/LibreVNA-GUI/Traces/Math/tracemath.h @@ -110,7 +110,7 @@ public: void assignInput(TraceMath *input); DataType getDataType() const; - std::vector& rData() { return data;} + virtual std::vector& rData() { return data;} Status getStatus() const; QString getStatusDescription() const; virtual Type getType() = 0; diff --git a/Software/PC_Application/LibreVNA-GUI/Traces/trace.cpp b/Software/PC_Application/LibreVNA-GUI/Traces/trace.cpp index fd39af7..1573f8e 100644 --- a/Software/PC_Application/LibreVNA-GUI/Traces/trace.cpp +++ b/Software/PC_Application/LibreVNA-GUI/Traces/trace.cpp @@ -1490,6 +1490,15 @@ unsigned int Trace::numSamples() } } +std::vector &Trace::rData() +{ + if(deembeddingActive && deembeddingAvailable()) { + return deembeddingData; + } else { + return TraceMath::rData(); + } +} + double Trace::getUnwrappedPhase(unsigned int index) { if(index >= size()) { diff --git a/Software/PC_Application/LibreVNA-GUI/Traces/trace.h b/Software/PC_Application/LibreVNA-GUI/Traces/trace.h index a4ac197..bfdb76d 100644 --- a/Software/PC_Application/LibreVNA-GUI/Traces/trace.h +++ b/Software/PC_Application/LibreVNA-GUI/Traces/trace.h @@ -93,6 +93,7 @@ public: virtual Data getSample(unsigned int index) override; virtual Data getInterpolatedSample(double x) override; virtual unsigned int numSamples() override; + virtual std::vector& rData() override; double getUnwrappedPhase(unsigned int index); // returns a (possibly interpolated sample) at a specified frequency/time/power diff --git a/Software/PC_Application/LibreVNA-GUI/test.setup b/Software/PC_Application/LibreVNA-GUI/test.setup deleted file mode 100644 index f49f626..0000000 --- a/Software/PC_Application/LibreVNA-GUI/test.setup +++ /dev/null @@ -1,362 +0,0 @@ -{ - "Modes": [ - { - "name": "Vector Network Analyzer", - "settings": { - "de-embedding": null, - "de-embedding_enabled": false, - "markers": null, - "sweep": { - "IFBW": 10000.0, - "frequency": { - "log": false, - "power": -10.0, - "start": 1000000.0, - "stop": 6000000000.0 - }, - "points": 1001, - "power": { - "frequency": 1000000000.0, - "start": -30.0, - "stop": -10.0 - }, - "single": false, - "type": "Frequency" - }, - "tiles": { - "orientation": "vertical", - "sizes": [ - 343, - 343 - ], - "split": true, - "tile1": { - "orientation": "horizontal", - "sizes": [ - 773, - 772 - ], - "split": true, - "tile1": { - "plot": "smithchart", - "plotsettings": { - "Z0": 50.0, - "constantLines": null, - "cursorFormat": "real + imag", - "edge_reflection": 1.0, - "frequency_override": false, - "limit_to_edge": true, - "limit_to_span": true, - "offset_axis_x": 0.0, - "offset_axis_y": 0.0, - "override_max": 6000000000.0, - "override_min": 0.0, - "traces": [ - 3896420666 - ] - }, - "split": false - }, - "tile2": { - "plot": "XY-plot", - "plotsettings": { - "XAxis": { - "div": 500000000.0, - "log": false, - "max": 6000000000.0, - "min": 1000000.0, - "mode": "Use Span", - "type": "Frequency" - }, - "YPrimary": { - "autorange": false, - "div": 10.0, - "log": false, - "max": 20.0, - "min": -120.0, - "traces": [ - 4241508620 - ], - "type": "Magnitude" - }, - "YSecondary": { - "autorange": false, - "div": 30.0, - "log": false, - "max": 180.0, - "min": -180.0, - "traces": [ - 4241508620 - ], - "type": "Phase" - }, - "limitLines": null - }, - "split": false - } - }, - "tile2": { - "orientation": "horizontal", - "sizes": [ - 773, - 772 - ], - "split": true, - "tile1": { - "plot": "XY-plot", - "plotsettings": { - "XAxis": { - "div": 1e-07, - "log": false, - "max": 9.999166736105324e-07, - "min": 0.0, - "mode": "Fit Traces", - "type": "Time" - }, - "YPrimary": { - "autorange": true, - "div": 20.0, - "log": false, - "max": 2.1792987877018692, - "min": -164.04811006538517, - "traces": [ - 4176942550 - ], - "type": "Impulse Response (Magnitude)" - }, - "YSecondary": { - "autorange": true, - "div": 0.0, - "log": false, - "max": 1.0, - "min": -1.0, - "traces": null, - "type": "Disabled" - }, - "limitLines": null - }, - "split": false - }, - "tile2": { - "plot": "smithchart", - "plotsettings": { - "Z0": 50.0, - "constantLines": null, - "cursorFormat": "real + imag", - "edge_reflection": 1.0, - "frequency_override": false, - "limit_to_edge": true, - "limit_to_span": true, - "offset_axis_x": 0.0, - "offset_axis_y": 0.0, - "override_max": 6000000000.0, - "override_min": 0.0, - "traces": [ - 1327145634 - ] - }, - "split": false - } - } - }, - "traces": [ - { - "color": "#ffff00", - "deembeddingActive": false, - "deembeddingData": null, - "hash": 3896420666, - "livetype": 0, - "math": null, - "math_enabled": false, - "name": "S11", - "parameter": "S11", - "paused": false, - "reflection": true, - "type": "Live", - "velocityFactor": 0.66, - "visible": true - }, - { - "color": "#0000ff", - "deembeddingActive": false, - "deembeddingData": null, - "hash": 4241508620, - "livetype": 0, - "math": null, - "math_enabled": false, - "name": "S12", - "parameter": "S12", - "paused": false, - "reflection": false, - "type": "Live", - "velocityFactor": 0.66, - "visible": true - }, - { - "color": "#00ff00", - "deembeddingActive": false, - "deembeddingData": null, - "hash": 4176942550, - "livetype": 0, - "math": [ - { - "enabled": true, - "operation": "TDR", - "settings": { - "automatic_DC": true, - "bandpass_mode": false, - "step_response": true, - "window": { - "type": "Hamming" - } - } - } - ], - "math_enabled": true, - "name": "S21", - "parameter": "S21", - "paused": false, - "reflection": false, - "type": "Live", - "velocityFactor": 0.66, - "visible": true - }, - { - "color": "#ff0000", - "deembeddingActive": false, - "deembeddingData": null, - "hash": 1327145634, - "livetype": 0, - "math": null, - "math_enabled": false, - "name": "S22", - "parameter": "S22", - "paused": false, - "reflection": true, - "type": "Live", - "velocityFactor": 0.66, - "visible": true - } - ] - }, - "type": "Vector Network Analyzer" - }, - { - "name": "Signal Generator", - "settings": { - "frequency": 1000000000.0, - "port": 0, - "power": 0.0, - "sweep": { - "dwell": 1.0, - "enabled": false, - "span": 0.0, - "steps": 100.0 - } - }, - "type": "Signal Generator" - }, - { - "name": "Spectrum Analyzer", - "settings": { - "markers": null, - "sweep": { - "acquisition": { - "RBW": 100000.0, - "detector": "+Peak", - "signal ID": false, - "window": "Kaiser" - }, - "frequency": { - "start": 37000000.0, - "stop": 4000000000.0 - }, - "single": false, - "trackingGenerator": { - "enabled": false, - "offset": 0.0, - "port": 1, - "power": -20.0 - } - }, - "tiles": { - "plot": "XY-plot", - "plotsettings": { - "XAxis": { - "div": 200000000.0, - "log": false, - "max": 4000000000.0, - "min": 37000000.0, - "mode": "Use Span", - "type": "Frequency" - }, - "YPrimary": { - "autorange": false, - "div": 10.0, - "log": false, - "max": 0.0, - "min": -120.0, - "traces": [ - 2411279292, - 2178442625 - ], - "type": "Magnitude" - }, - "YSecondary": { - "autorange": true, - "div": 0.0, - "log": false, - "max": 1.0, - "min": -1.0, - "traces": null, - "type": "Disabled" - }, - "limitLines": null - }, - "split": false - }, - "traces": [ - { - "color": "#ffff00", - "deembeddingActive": false, - "deembeddingData": null, - "hash": 2411279292, - "livetype": 0, - "math": null, - "math_enabled": false, - "name": "PORT1", - "parameter": "PORT1", - "paused": false, - "reflection": false, - "type": "Live", - "velocityFactor": 0.66, - "visible": true - }, - { - "color": "#0000ff", - "deembeddingActive": false, - "deembeddingData": null, - "hash": 2178442625, - "livetype": 0, - "math": null, - "math_enabled": false, - "name": "PORT2", - "parameter": "PORT2", - "paused": false, - "reflection": false, - "type": "Live", - "velocityFactor": 0.66, - "visible": true - } - ] - }, - "type": "Spectrum Analyzer" - } - ], - "Reference": { - "Mode": "Internal", - "Output": "Off" - }, - "activeMode": "Vector Network Analyzer", - "version": "1.5.0-alpha.2-4568be8ff" -} diff --git a/Software/PC_Application/LibreVNA-GUI/usersjanappdatalocaltemptmpqaohp7 b/Software/PC_Application/LibreVNA-GUI/usersjanappdatalocaltemptmpqaohp7 deleted file mode 100644 index e69de29..0000000 diff --git a/Software/VNA_embedded/Application/App.cpp b/Software/VNA_embedded/Application/App.cpp index 34e78d9..2ac489b 100644 --- a/Software/VNA_embedded/Application/App.cpp +++ b/Software/VNA_embedded/Application/App.cpp @@ -181,6 +181,16 @@ inline void App_Process() { case Protocol::PacketType::StartStatusUpdates: { HW::setStatusUpdateFlag(true); Communication::SendWithoutPayload(Protocol::PacketType::Ack); + } + break; + case Protocol::PacketType::InitiateSweep: { + if(VNA::GetStandbyMode()) { + VNA::InitiateSweep(); + Communication::SendWithoutPayload(Protocol::PacketType::Ack); + } else { + Communication::SendWithoutPayload(Protocol::PacketType::Nack); + } + } break; case Protocol::PacketType::SetIdle: diff --git a/Software/VNA_embedded/Application/Communication/Protocol.cpp b/Software/VNA_embedded/Application/Communication/Protocol.cpp index e302a33..f16f621 100644 --- a/Software/VNA_embedded/Application/Communication/Protocol.cpp +++ b/Software/VNA_embedded/Application/Communication/Protocol.cpp @@ -125,6 +125,7 @@ uint16_t Protocol::EncodePacket(const PacketInfo &packet, uint8_t *dest, uint16_ case PacketType::ClearTrigger: case PacketType::StopStatusUpdates: case PacketType::StartStatusUpdates: + case PacketType::InitiateSweep: // no payload break; case PacketType::VNADatapoint: payload_size = packet.VNAdatapoint->requiredBufferSize(); break; diff --git a/Software/VNA_embedded/Application/Communication/Protocol.hpp b/Software/VNA_embedded/Application/Communication/Protocol.hpp index f50f7af..11f9f02 100644 --- a/Software/VNA_embedded/Application/Communication/Protocol.hpp +++ b/Software/VNA_embedded/Application/Communication/Protocol.hpp @@ -159,7 +159,7 @@ using SweepSettings = struct _sweepSettings { uint16_t points; uint32_t if_bandwidth; int16_t cdbm_excitation_start; // in 1/100 dbm - uint16_t unused:1; + uint16_t standby:1; uint16_t syncMaster:1; uint16_t suppressPeaks:1; uint16_t fixedPowerSetting:1; // if set the attenuator and source PLL power will not be changed across the sweep @@ -366,6 +366,7 @@ enum class PacketType : uint8_t { ClearTrigger = 29, StopStatusUpdates = 30, StartStatusUpdates = 31, + InitiateSweep = 32 }; using PacketInfo = struct _packetinfo { diff --git a/Software/VNA_embedded/Application/Hardware.cpp b/Software/VNA_embedded/Application/Hardware.cpp index f45fb78..3d0da00 100644 --- a/Software/VNA_embedded/Application/Hardware.cpp +++ b/Software/VNA_embedded/Application/Hardware.cpp @@ -250,6 +250,8 @@ void HW::SetIdle() { FPGA::Enable(FPGA::Periphery::RefMixer, false); FPGA::Enable(FPGA::Periphery::PortSwitch, false); activeMode = Mode::Idle; + VNA::SetWaitingInStandby(false); + } HW::AmplitudeSettings HW::GetAmplitudeSettings(int16_t cdbm, uint64_t freq, bool applyCorrections, bool port2) { @@ -303,7 +305,7 @@ bool HW::TimedOut() { auto bufISR = lastISR; uint64_t now = Delay::get_us(); uint64_t timeSinceLast = now - bufISR; - if(activeMode != Mode::Idle && activeMode != Mode::Generator && timeSinceLast > timeout) { + if(activeMode != Mode::Idle && activeMode != Mode::Generator && !VNA::IsWaitingInStandby() && timeSinceLast > timeout) { LOG_WARN("Timed out, last ISR was at %lu%06lu, now %lu%06lu" , (uint32_t) (bufISR / 1000000), (uint32_t)(bufISR%1000000) , (uint32_t) (now / 1000000), (uint32_t)(now%1000000)); diff --git a/Software/VNA_embedded/Application/VNA.cpp b/Software/VNA_embedded/Application/VNA.cpp index 5dc7cd0..192a99f 100644 --- a/Software/VNA_embedded/Application/VNA.cpp +++ b/Software/VNA_embedded/Application/VNA.cpp @@ -27,6 +27,7 @@ static uint32_t last_LO2; static double logMultiplier, logFrequency; static Protocol::VNADatapoint<32> data; static bool active = false; +static bool waitingInStandby = false; static Si5351C::DriveStrength fixedPowerLowband; static bool adcShifted; static uint32_t actualBandwidth; @@ -258,12 +259,38 @@ bool VNA::Setup(Protocol::SweepSettings s) { // Enable new data and sweep halt interrupt FPGA::EnableInterrupt(FPGA::Interrupt::NewData); FPGA::EnableInterrupt(FPGA::Interrupt::SweepHalted); - // Start the sweep + // Start the sweep if not configured for standby firstPoint = true; - FPGA::StartSweep(); + if (settings.standby) { + waitingInStandby = true; + } + else { + FPGA::StartSweep(); + } return true; } +void VNA::InitiateSweep() { + // Invoked by a host via InitiateSweep packet + if(waitingInStandby){ + // make sure that SweepSettings have been configured for standby operation + FPGA::StartSweep(); + waitingInStandby = false; + } +} + +bool VNA::GetStandbyMode() { + return settings.standby; +} + +bool VNA::IsWaitingInStandby() { + return waitingInStandby; +} + +void VNA::SetWaitingInStandby(bool waiting) { + waitingInStandby = waiting; +} + static void PassOnData() { Protocol::PacketInfo info; info.type = Protocol::PacketType::VNADatapoint; @@ -330,8 +357,14 @@ void VNA::Work() { Communication::Send(packet); } // do not reset unlevel flag here, as it is calculated only once at the setup of the sweep - // Start next sweep - FPGA::StartSweep(); + // Start next sweep if not configured for standby + if (settings.standby) { + waitingInStandby = true; + } + else { + FPGA::StartSweep(); + } + } void VNA::SweepHalted() { diff --git a/Software/VNA_embedded/Application/VNA.hpp b/Software/VNA_embedded/Application/VNA.hpp index 2960c95..a411085 100644 --- a/Software/VNA_embedded/Application/VNA.hpp +++ b/Software/VNA_embedded/Application/VNA.hpp @@ -7,6 +7,10 @@ namespace VNA { bool Setup(Protocol::SweepSettings s); +void InitiateSweep(); +bool GetStandbyMode(); +bool IsWaitingInStandby(); +void SetWaitingInStandby(bool waiting); bool MeasurementDone(const FPGA::SamplingResult &result); void Work(); void SweepHalted();