The LibreVNA implements a ``custom class'' USB device. It uses a VID of 0x0483 and a PID of 0x4121. The custom class contains a single interface with three bulk endpoints:
\item\textbf{Endpoint 0x01:} Communication data from the USB host to the LibreVNA
\item\textbf{Endpoint 0x81:} Communication data from the LibreVNA to the USB host
\item\textbf{Endpoint 0x82:} Debug messages from the LibreVNA
\end{itemize}
Endpoint 0x82 is exclusively used for debug messages. They are transmitted in ASCII format. All protocol packets described in this document are always transmitted over endpoints 0x01 and 0x81.
\section{General packet structure}
The USB traffic through bulk endpoints can be viewed as a stream of bytes. The communication between the LibreVNA and the USB host is done in packets. To detect the packets within the data stream, some framing is needed. This general package structure is described in this section.
Each packet consists of the following fields:
\begin{enumerate}
\item\textbf{Header:} 1 byte, always 0x5A
\item\textbf{Length:} 2 bytes, length of the overall packet in bytes, including the header and the checksum
\item\textbf{Type:} 1 byte, defines the type of packet and subsequently the data encoding within the payload
\item\textbf{Payload:} Any amount of bytes, content depends on the packet type
\item\textbf{CRC:} 4 bytes, CRC32 over all other packet bytes (header, length, type and payload)
\end{enumerate}
\noindent
All values in the USB protocol are little-endian.
\section{Packet types}
The following packet types are available:
\begin{ThreePartTable}
\setlength\tabcolsep{3pt}
\begin{TableNotes}
\item[a] Direction of packet transfer:
\begin{footnotesize}
\begin{itemize}
\item\textbf{D$\rightarrow$H:} Device to host
\item\textbf{H$\rightarrow$D:} Host to device
\item\textbf{D$\leftrightarrow$H:} Both directions used
\end{itemize}
\end{footnotesize}
\item[b] Packet type that will be sent in response to this packet
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.
Received packets from the device are not acknowledged by the host; the host never sends an Ack packet.
\subsection{SweepSettings}
Transmitting this packet will switch the LibreVNA into VNA mode and start the sweep. During the sweep, VNADatapoint packets are generated for each completed point in the sweep.
The sampling for each frequency (or power) point in the sweep is done in stages. In each stage, the stimulus can be active at another port. A typical full two-port sweep would therefore use two stages, with the stimulus being active on port 1 during stage 0 and on port 2 during stage 1. For faster measurements, this could be reduced to a single stage if only a subset of the S-parameters is required. Similarly, more than two stages can be used (with the stimulus inactive during some) when multiple devices are synchronized. Another device in the setup will have to generate the stimulus during the inactive stages.
\item\textbf{syncMode:} Synchronization mode when multiple devices are used together
\begin{center}
\begin{tabular}{ c|c }
Setting & Synchronization\\
\hline
00 & Disabled \\
01 & USB\\
10 & External reference\\
11 & External trigger\\
\end{tabular}
\end{center}
\item\textbf{P1 Stage:} Sets the stage number when the stimulus is active at port 1. Stage number indizes start at 0.
\item\textbf{P2 Stage:} Sets the stage number when the stimulus is active at port 2. Stage number indizes start at 0.
\item\textbf{Stages:} Sets the number of used stages. The number of stages is one more than this value. E.g. set to 1 for 2 stages
\item\textbf{LOG:} Set for a logarithmic sweep (only for frequency, power adjustment during the sweep is always linear)
\item\textbf{FP:} Fixed power setting. This must be enabled for power sweeps (when cdbm\_excitation\_start $\neq$ cdbm\_excitation\_stop)
\begin{center}
\begin{tabularx}{\textwidth}{ c|X }
Setting & Behavior\\
\hline
0 & Attenuator setting is fixed during the sweep. This will result in inaccurate stimulus level but prevent discrete jumps in output power. \\
1 & Attenuator setting is changed during the sweep. This will result in more accurate stimulus level but also create discrete jumps in output power. \\
0 & 2.LO is adjusted to compensate for limited frequency resolution in 1.LO. Slight decrease in maximum sweep speed. \\
1 & 2.LO is kept at its nominal value. Slightly faster sweep but this will result in peaks at frequencies where the 1.LO it too far off the ideal frequency. \\
\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.
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.\\
12 & 4 & FLOAT & port1real & Real part of the complex signal at port 1 \\
16 & 4 & FLOAT & port1imag & Imaginary part of the complex signal at port 1 \\
20 & 4 & FLOAT & port2real & Real part of the complex signal at port 2 \\
24 & 4 & FLOAT & port2imag & Imaginary part of the complex signal at port 2 \\
28 & 4 & FLOAT & refreal & Real part of the complex signal at the reference receiver \\
32 & 4 & FLOAT & refimag & Imaginary part of the complex signal at the reference receiver \\
36 & 1 & UINT8 & temp\_source & Temperature of the source PLL in \si{\celsius}\\
37 & 1 & UINT8 & temp\_LO & Temperature of the LO PLL in \si{\celsius}\\
38 & 1 & UINT8 & Lock status & Bit 0: lock status of source PLL. Bit 1: lock status of LO PLL \\
\end{longtable}
\end{ThreePartTable}
\subsection{ManualControlV1}
This packet switches the LibreVNA to manual control mode. As long as the manual control mode is active, the LibreVNA will generate ManualStatusV1 packets and send them to the host.
31 & 4 & UINT32 & Samples & Number of ADC samples for each complex wave calculation \\
32 & 1 & UINT8 & WindowType & Window selection for the complex wave calculation \\
\end{longtable}
\end{ThreePartTable}
\paragraph{Source High Config:}
\begin{center}
\begin{tikzpicture}
\bitrect{8}{8-\bit}
\robits{0}{2}{}
\rwbits{2}{2}{LP}
\rwbits{4}{2}{Power}
\rwbits{6}{1}{RFEN}
\rwbits{7}{1}{CE}
\end{tikzpicture}
\end{center}
\begin{itemize}
\item\textbf{LP:} Lowpass setting
\begin{center}
\begin{tabular}{ c|c }
Setting & Cut-off frequency\\
\hline
00 &\SI{947}{\mega\hertz}\\
01 &\SI{1.88}{\giga\hertz}\\
10 &\SI{3.5}{\giga\hertz}\\
11 & No filter\\
\end{tabular}
\end{center}
\item\textbf{Power:} Power output of the highband source PLL
\begin{center}
\begin{tabular}{ c|c }
Setting & Power\\
\hline
00 &\SI{-4}{\dBm}\\
01 &\SI{-1}{\dBm}\\
10 &\SI{2}{\dBm}\\
11 &\SI{5}{\dBm}\\
\end{tabular}
\end{center}
\item\textbf{RFEN:} RF output enable
\item\textbf{CE:} Chip enable
\end{itemize}
\paragraph{Source Low Config:}
\begin{center}
\begin{tikzpicture}
\bitrect{8}{8-\bit}
\robits{0}{5}{}
\rwbits{5}{2}{Power}
\rwbits{7}{1}{EN}
\end{tikzpicture}
\end{center}
\begin{itemize}
\item\textbf{Power:} Power output of the lowband source PLL
\begin{center}
\begin{tabular}{ c|c }
Setting & Drive Strength\\
\hline
00 &\SI{2}{\milli\ampere}\\
01 &\SI{4}{\milli\ampere}\\
10 &\SI{6}{\milli\ampere}\\
11 &\SI{8}{\milli\ampere}\\
\end{tabular}
\end{center}
\item\textbf{EN:} Lowband source enable
\end{itemize}
\paragraph{Source Path Config:}
\begin{center}
\begin{tikzpicture}
\bitrect{16}{16-\bit}
\robits{0}{6}{}
\rwbits{6}{1}{PS}
\rwbits{7}{1}{AEN}
\rwbits{8}{1}{BS}
\rwbits{9}{7}{Attenuator}
\end{tikzpicture}
\end{center}
\begin{itemize}
\item\textbf{PS:} Port switch. Set to 1 to route the source signal to port 2, set to 0 to route the source signal to port 1.
\item\textbf{AEN:} Amplifier enable.
\item\textbf{PS:} Band select. Set to 1 to use the highband source, set to 0 to use the lowband source.
\item\textbf{Attenuator:} Attenuation of the source signal in \SI{0.25}{\dBm}.
\end{itemize}
\paragraph{1.LO Config:}
\begin{center}
\begin{tikzpicture}
\bitrect{8}{8-\bit}
\robits{0}{6}{}
\rwbits{6}{1}{RFEN}
\rwbits{7}{1}{CE}
\end{tikzpicture}
\end{center}
\begin{itemize}
\item\textbf{RFEN:} RF output enable
\item\textbf{CE:} Chip enable
\end{itemize}
\paragraph{WindowType:}
\begin{center}
\begin{tabular}{ c|c }
Setting & Window\\
\hline
0 & None \\
1 & Kaiser\\
2 & Hann\\
3 & Flattop\\
\end{tabular}
\end{center}
\subsection{DeviceInfo}
This packet contains information about the connected device. It can be requested by sending a RequestDeviceInfo packet. This request is the first thing that should happen after the device has been enumerated to make sure the right protocol version is used.
41 & 4 & UINT32 & MaxRBW & Maximum supported resolution bandwidth in Hz \\
45 & 1 & UINT8 & MaxAmplitudePoints & Maximum supported number of amplitude calibration points \\
46 & 8 & UINT64 & MaxHarmonicFrequency & Maximum supported frequency when using harmonic mixing \\
\end{longtable}
\end{ThreePartTable}
\subsection{FirmwarePacket}
This packet contains a part of the firmware. When updating the firmware, this packet must be transmitted multiple times until the whole firmware has been transferred.
%\insertTableNotes % tell LaTeX where to insert the table-related notes
\endlastfoot
0 & 4 & UINT32 & Address & Address at which the firmware data starts\\
4 & 256 & UINT8 & Data & Binary firmware data \\
\end{longtable}
\end{ThreePartTable}
\subsection{Ack}
This packet is sent by the device whenever a valid packet has been received. It has no payload.
\subsection{ClearFlash}
This packet must be sent before transferring the first piece of firmware data. It has no payload.
\subsection{PerformFirmwareUpdate}
This packet must be sent after the complete firmware data has been transmitted. It triggers the actual update process. The device will reboot during the update process. It has no payload.
\subsection{Nack}
This packet is sent by the device whenever an error occured while processing a received packet. It has no payload.
\subsection{Reference}
This packet is used to configure the external reference input and output.
%\insertTableNotes % tell LaTeX where to insert the table-related notes
\endlastfoot
0 & 4 & UINT32 & OutputFrequency & Frequency of the external reference output. Not every frequency can be reached by the PLL. Set to 0 to disable the reference output.\\
4 & 1 & UINT8 & ExternalInputConfig &\makecell[l]{Bit 0: Switch to external when signal detected\\Bit 1: Force usage of the external reference}\\
\end{longtable}
\end{ThreePartTable}
\subsection{Generator}
This packet switches the LibreVNA into signal generator mode and configures the output signal.
\item\textbf{AC:} Amplitude correction enable. If set to 1, the source amplitude calibration is used to reach better amplitude accuracy.
\item\textbf{Port:} Port selection:
\begin{center}
\begin{tabular}{ c|c }
Setting & Window\\
\hline
0 & Disabled \\
1 & Output on port 1\\
2 & Output on port 2\\
\end{tabular}
\end{center}
\end{itemize}
\subsection{SpectrumAnalyzerSettings}
Transmitting this packet will switch the LibreVNA into spectrum analyzer mode and start the sweep. During the sweep, SpectrumAnalyzerResult packets are generated for each completed point in the sweep.
20 & 2 & UINT16 & pointNum & Number of reported points in the sweep. The internally used number of points can be higher (depending on the RBW) \\
22 & 2 & UINT16 & Configuration & Bitmap for configuration, see below \\
24 & 8 & INT64 & TrackingOffset & Offset of the tracking generator in Hz \\
32 & 2 & INT16 & TrackingPower & Power of the tracking generator in $\frac{1}{100}$dBm \\
\end{longtable}
\end{ThreePartTable}
\paragraph{Configuration:}
\begin{center}
\begin{tikzpicture}
\bitrect{16}{16-\bit}
\robits{0}{2}{}
\rwbits{2}{1}{SM}
\rwbits{3}{2}{syncMode}
\rwbits{5}{1}{TGP}
\rwbits{6}{1}{ASC}
\rwbits{7}{1}{TGE}
\rwbits{8}{1}{ARC}
\rwbits{9}{1}{DFT}
\rwbits{10}{3}{Detector}
\rwbits{13}{1}{SID}
\rwbits{14}{2}{Window}
\end{tikzpicture}
\end{center}
\begin{itemize}
\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{syncMode:} Synchronization mode when multiple devices are used together
\begin{center}
\begin{tabular}{ c|c }
Setting & Synchronization\\
\hline
00 & Disabled \\
01 & USB\\
10 & External reference\\
11 & External trigger\\
\end{tabular}
\end{center}
\item\textbf{TGP:} Tracking generator port. Set to 1 for port 2. Set to 0 for port 1.
\item\textbf{ASC:} Apply source amplitude corrections. If enabled, the amplitude calibration is used to reach better accuracy of the tracking generator output.
\item\textbf{TGE:} Tracking generator enable.
\item\textbf{ARC:} Apply receiver amplitude corrections. If enabled, the amplitude calibration is used to reach better measurement accuracy.
\item\textbf{DFT:} Use DFT to speed up the acquisition. Can not be used when the tracking generator is enabled. Only useful for low resolution bandwidths.
\item\textbf{Detector:}
\begin{center}
\begin{tabular}{ c|c }
Setting & Detector type\\
\hline
0 & Positive peak \\
1 & Negative peak \\
2 & Sample \\
3 & Normal \\
4 & Average \\
\end{tabular}
\end{center}
\item\textbf{SID:} Signal ID enable.
\item\textbf{Window:}
\begin{center}
\begin{tabular}{ c|c }
Setting & Window\\
\hline
0 & None \\
1 & Kaiser\\
2 & Hann\\
3 & Flattop\\
\end{tabular}
\end{center}
\end{itemize}
\subsection{SpectrumAnalyzerResult}
This packet is transmitted by the LibreVNA for every point in the sweep when in spectrum analyzer mode.
This packet is used to make the device send the DeviceInfo packet. It has no payload.
\subsection{RequestSourceCal}
This packet is used to make the device send the source amplitude calibration. It has no payload. For each source amplitude calibration point one SourceCalPoint packet will be returned.
This packet is used to make the device send the receiver amplitude calibration. It has no payload. For each receiver amplitude calibration point one ReceiverCalPoint packet will be returned.
\subsection{SourceCalPoint}
This packet contains one source calibration point. It can be transmitted in both directions. When reading the source calibration, it is transmitted from the device to the host. When writing the source calibration multiple of these packets are transferred from the host to the device. In both cases the packet for the point with the highest point number must be transmitted last.
%\insertTableNotes % tell LaTeX where to insert the table-related notes
\endlastfoot
0 & 1 & UINT8 & TotalPoints & Amount of total points in the amplitude calibration \\
1 & 1 & UINT8 & PointNum & Number of the calibration point contained in this packet \\
2 & 4 & UINT32 & Frequency & Frequency of the calibration point in \SI{10}{\hertz}\\
6 & 2 & INT16 & Port 1 & Correction value for port 1 in $\frac{1}{100}$dB \\
8 & 2 & INT16 & Port 2 & Correction value for port 2 in $\frac{1}{100}$dB \\
\end{longtable}
\end{ThreePartTable}
\subsection{ReceiverCalPoint}
This packet contains one receiver calibration point. It can be transmitted in both directions. When reading the receiver calibration, it is transmitted from the device to the host. When writing the receiver calibration multiple of these packets are transferred from the host to the device. In both cases the packet for the point with the highest point number must be transmitted last.
The packet payload is identical to the SourceCalPoint packet.
\subsection{SetIdle}
This packet is used to stop any data acquisition from the LibreVNA. It has no payload.
\subsection{RequestFrequencyCorrection}
This packet is used to make the device send the FrequencyCorrection packet. It has no payload.
\subsection{FrequencyCorrection}
This packet contains the frequency correction factor for the internal reference. It can be transmitted in both directions. When reading the frequency correction, it is transmitted from the device to the host. When writing the frequency correction, it is transmitted from the host to the device.
%\insertTableNotes % tell LaTeX where to insert the table-related notes
\endlastfoot
0 & 4 & FLOAT & PPM & Error of the internal TCXO in ppm \\
\end{longtable}
\end{ThreePartTable}
\subsection{RequestAcquisitionFrequencySettings}
This packet is used to make the device send the AcquisitionFrequencySettings packet. It has no payload.
\subsection{AcquisitionFrequencySettings}
This packet contains the configuration of the acquisition hardware. These settings are at default values after the device has booted. It is normally not required to send this packet but changing these settings might be useful in special use cases. It can be transmitted in both directions. When reading the acquisition settings, it is transmitted from the device to the host. When writing the acquisition settings, it is transmitted from the host to the device.
%\insertTableNotes % tell LaTeX where to insert the table-related notes
\endlastfoot
0 & 4 & UINT32 & 1.IF frequency & 1.IF frequency in Hz \\
4 & 1 & UINT8 & ADC prescaler & Prescaler used for the ADC sampling (refer to the FPGA protocol) \\
5 & 2 & UINT16 & DFT phase increment & Phase increment of the DFT between ADC samples (refer to the FPGA protocol). Together with the ADC prescaler it also sets the 2.IF frequency. \\
\end{longtable}
\end{ThreePartTable}
\subsection{DeviceStatusV1}
This packet contains the status of the device. It can be requested by sending a RequestDeviceStatus packet. The device also sends this packet on its own. The interval in which this packet is sent depends on the currently active mode.
%\insertTableNotes % tell LaTeX where to insert the table-related notes
\endlastfoot
0 & 8 & UINT64 & Frequency & Frequency of the sweep point in Hz\\
8 & 2 & INT16 & PowerLevel & Stimulus level of the sweep point in $\frac{1}{100}$dBm \\
10 & 2 & UINT16 & PointNumber & Number of this point in the sweep \\
12 & 4*x & Array of FLOAT & Real values & The real parts of a variable amount of receiver data \\
12+4*x & 4*x & Array of FLOAT & Imag values & The imaginary parts of a variable amount of receiver data \\
12+8*x & 1*x & UINT8 & Array of UINT8 & Variable data description \\
\end{longtable}
\end{ThreePartTable}
The sampling data consists of a variable amount of values. The amount of values depend on the amount of configured stages and also on the hardware architecture (might change in the future). The VNADatapoint contains three arrays of equal length. Two of the arrays contain the real and imaginary parts of the acquired data. The third array contains a bitmask for every value, describing the content. The length of all arrays is not explicitly transmitted and must be inferred from the overall packet length.
\paragraph{Data description bitmask:}
\begin{center}
\begin{tikzpicture}
\bitrect{8}{8-\bit}
\rwbits{0}{3}{Stage}
\rwbits{3}{1}{Ref}
\rwbits{4}{1}{P4}
\rwbits{5}{1}{P3}
\rwbits{6}{1}{P2}
\rwbits{7}{1}{P1}
\end{tikzpicture}
\end{center}
\begin{itemize}
\item\textbf{Stage:} The active stage when the value was acquired. The port on which the stimulus was active during this stage is known from the SweepSettings packet that was used to set up the currently active sweep.
\item\textbf{Ref:} The value is from a reference receiver.
\item\textbf{P4:} The value is from a port 4 receiver.
\item\textbf{P3:} The value is from a port 3 receiver.
\item\textbf{P2:} The value is from a port 2 receiver.
\item\textbf{P1:} The value is from a port 1 receiver.
\end{itemize}
As the LibreVNA 1.0 only has two ports, P3 and P4 are never used and reserved for future developments.
In case of a three receiver architecture (as the LibreVNA 1.0 has), multiple port bits can be set for reference receiver values. For a typical full two-port sweep, the LibreVNA 1.0 will generate six values for every sweep point:
%\insertTableNotes % tell LaTeX where to insert the table-related notes
\endlastfoot
1 & 0x01 & Port 1 receiver signal during stage 0 \\
2 & 0x02 & Port 2 receiver signal during stage 0 \\
3 & 0x13 & Reference receiver signal during stage 0 \\
4 & 0x21 & Port 1 receiver signal during stage 1 \\
5 & 0x22 & Port 2 receiver signal during stage 1 \\
6 & 0x33 & Reference receiver signal during stage 1 \\
\end{longtable}
\end{ThreePartTable}
\subsection{SetTrigger}
This packet is used when multiple devices are synchronized over USB and can be transmitted in both directions. It has no payload. Synchronized devices must be logically organized in a closed loop. When a SetTrigger packet is received from any devices in the loop it must be passed on to the next device in the loop.
\subsection{ClearTrigger}
This packet is used when multiple devices are synchronized over USB and can be transmitted in both directions. It has no payload. Synchronized devices must be logically organized in a closed loop. When a ClearTrigger packet is received from any devices in the loop it must be passed on to the next device in the loop.
This packet instructs the device to stop sending automatically scheduled DeviceStatusV1 packets. Device status can still be requested explicitly via RequestDeviceStatus packets.
\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.
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.