mirror of
https://github.com/jankae/LibreVNA.git
synced 2025-12-06 07:12:10 +01:00
Compare commits
10 commits
d853571aea
...
6a7b985fa9
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6a7b985fa9 | ||
|
|
7bdbcde9be | ||
|
|
fbef4b364f | ||
|
|
da1228c9b1 | ||
|
|
3aac724298 | ||
|
|
0f9510e7a0 | ||
|
|
65bc247a65 | ||
|
|
d0c8a1ae8e | ||
|
|
9923038d6c | ||
|
|
72d547eb08 |
Binary file not shown.
|
|
@ -123,6 +123,7 @@
|
|||
\usepackage{xifthen}
|
||||
\newcommand{\vna}{LibreVNA}
|
||||
\newcommand{\gui}{\vna{}-GUI}
|
||||
\newcommand{\subsubsubsection}[1]{\paragraph{#1}\mbox{}\\\\}
|
||||
|
||||
\newcommand{\screenshot}[2]{\begin{center}
|
||||
\includegraphics[width=#1\textwidth]{Screenshots/#2}
|
||||
|
|
@ -462,6 +463,21 @@ If single sweep is enabled, the acquisition is stopped when the required number
|
|||
\item Issue the command again (i.e. VNA:ACQ:SINGLE TRUE always triggers a new sweep)
|
||||
\end{itemize}
|
||||
|
||||
\subsubsection{VNA:ACQuisition:FREQuency}
|
||||
\query{Returns the current frequency of the sweep}{VNA:ACQuisition:FREQuency?}{None}{<Frequency in Hz>}
|
||||
|
||||
This command only returns valid data when a sweep is running and the the sweep is a frequency sweep.
|
||||
|
||||
\subsubsection{VNA:ACQuisition:POWer}
|
||||
\query{Returns the current power of the sweep}{VNA:ACQuisition:POWer?}{None}{<Power in dBm>}
|
||||
|
||||
This command only returns valid data when a sweep is running and the the sweep is a power sweep.
|
||||
|
||||
\subsubsection{VNA:ACQuisition:TIME}
|
||||
\query{Returns the current time of the sweep}{VNA:ACQuisition:TIME?}{None}{<Time in seconds>}
|
||||
|
||||
This command only returns valid data when a sweep is running and the the sweep is a zero-span sweep.
|
||||
|
||||
\subsubsection{VNA:STIMulus:LVL}
|
||||
\event{Sets the output power of the stimulus signal when sweep type is frequency}{VNA:STIMulus:LVL}{<power>, in dBm}
|
||||
\query{Queries the currently selected output power}{VNA:STIMulus:LVL?}{None}{power in dBm}
|
||||
|
|
@ -601,6 +617,9 @@ If no de-embedding is configured for the selected trace, enabling the de-embeddi
|
|||
\hspace{1cm}LOAD\\
|
||||
\hspace{1cm}THROUGH\\
|
||||
\hspace{1cm}ISOLATION\\
|
||||
\hspace{1cm}SLIDINGLOAD\\
|
||||
\hspace{1cm}REFLECT\\
|
||||
\hspace{1cm}LINE\\
|
||||
{[<standard>]}, calibration kit standard name, optional\\}
|
||||
|
||||
\subsubsection{VNA:CALibration:TYPE}
|
||||
|
|
@ -609,7 +628,10 @@ If no de-embedding is configured for the selected trace, enabling the de-embeddi
|
|||
\hspace{1cm}SHORT\\
|
||||
\hspace{1cm}LOAD\\
|
||||
\hspace{1cm}THROUGH\\
|
||||
\hspace{1cm}ISOLATION\\}
|
||||
\hspace{1cm}ISOLATION\\
|
||||
\hspace{1cm}SLIDINGLOAD\\
|
||||
\hspace{1cm}REFLECT\\
|
||||
\hspace{1cm}LINE\\}
|
||||
|
||||
\subsubsection{VNA:CALibration:PORT}
|
||||
\event{Sets the port for the specified measurement}{VNA:CALibration:PORT}{<measurement number> <port number>}
|
||||
|
|
@ -637,6 +659,23 @@ Important points when saving/loading calibration files through SCPI commands:
|
|||
\subsubsection{VNA:CALibration:LOAD}
|
||||
\query{Loads a calibration file}{VNA:CALibration:LOAD?}{<filename>}{TRUE or FALSE}
|
||||
|
||||
\subsubsection{VNA:CALibration:KIT:MANufacturer}
|
||||
\event{Sets the manufacturer name of the calibration kit}{VNA:CALibration:KIT:MANufacturer}{<manufacturer>}
|
||||
\query{Returns the manufacturer name of the calibration kit}{VNA:CALibration:KIT:MANufacturer?}{None}{<manufacturer>}
|
||||
|
||||
\subsubsection{VNA:CALibration:KIT:SERial}
|
||||
\event{Sets the serial number of the calibration kit}{VNA:CALibration:KIT:SERial}{<serial number>}
|
||||
\query{Returns the serial number of the calibration kit}{VNA:CALibration:KIT:SERial?}{None}{<serial number>}
|
||||
|
||||
\subsubsection{VNA:CALibration:KIT:DESCription}
|
||||
\event{Sets the description of the calibration kit}{VNA:CALibration:KIT:DESCription}{<description>}
|
||||
\query{Returns the description of the calibration kit}{VNA:CALibration:KIT:DESCription?}{None}{<description>}
|
||||
|
||||
\subsubsection{VNA:CALibration:KIT:FILEname}
|
||||
\query{Returns the filename of the calibration kit}{VNA:CALibration:KIT:FILEname?}{None}{<filename>}
|
||||
|
||||
The filename is only available if the calibration kit was loaded from a dedicated file. If it was loaded as part of a calibration file or has not been loaded since the GUI started, no filename will be returned.
|
||||
|
||||
\subsubsection{VNA:CALibration:KIT:SAVE}
|
||||
\event{Saves the active calibration kit to a file}{VNA:CALibration:KIT:SAVE}{<filename>}
|
||||
Important points when saving/loading calibration kit files through SCPI commands:
|
||||
|
|
@ -648,6 +687,343 @@ Important points when saving/loading calibration kit files through SCPI commands
|
|||
\subsubsection{VNA:CALibration:KIT:LOAD}
|
||||
\query{Loads a calibration kit file}{VNA:CALibration:KIT:LOAD?}{<filename>}{TRUE or FALSE}
|
||||
|
||||
\subsubsection{Common calibration kit standards commands}
|
||||
The calibration kit supports an arbitrary amount of standards. This requires a flexible SCPI API which adjusts to the currently configured standards.
|
||||
|
||||
A few calibration kit standard commands are always available and they can be used to create and delete calibration standards. Every created calibration standard adds their own commands. They can be accessed by including the calibration standard number in the command (shown as ``x'' in the following commands).
|
||||
|
||||
\subsubsubsection{VNA:CALibration:KIT:STAndard:CLEAR}
|
||||
\event{Resets the calibration kit to default values (ideal standards)}{VNA:CALibration:KIT:STAndard:CLEAR}{None}
|
||||
|
||||
\subsubsubsection{VNA:CALibration:KIT:STAndard:NUMber}
|
||||
\query{Returns the number of configured calibration standards}{VNA:CALibration:KIT:STAndard:NUMber?}{None}{<number of calibration standards>}
|
||||
|
||||
\subsubsubsection{VNA:CALibration:KIT:STAndard:TYPE}
|
||||
\query{Returns the type of a created calibration standard}{VNA:CALibration:KIT:STAndard:TYPE?}{<x> Number of calibration standard}{Type of standard, one of:\\
|
||||
\hspace{1cm}Open\\
|
||||
\hspace{1cm}Short\\
|
||||
\hspace{1cm}Load\\
|
||||
\hspace{1cm}Reflect\\
|
||||
\hspace{1cm}Through\\
|
||||
\hspace{1cm}Line\\}
|
||||
|
||||
\subsubsubsection{VNA:CALibration:KIT:STAndard:NEW}
|
||||
\event{Adds a new calibration standard}{VNA:CALibration:KIT:STAndard:NEW}{<type> Type of calibration standard, one of:\\
|
||||
\hspace{1cm}Open\\
|
||||
\hspace{1cm}Short\\
|
||||
\hspace{1cm}Load\\
|
||||
\hspace{1cm}Reflect\\
|
||||
\hspace{1cm}Through\\
|
||||
\hspace{1cm}Line\\
|
||||
<name> User selectable name of new standard}
|
||||
|
||||
\subsubsubsection{VNA:CALibration:KIT:STAndard:DELete}
|
||||
\event{Removes a calibration standard}{VNA:CALibration:KIT:STAndard:DELete}{<x> Number of standard to delete}
|
||||
|
||||
\subsubsection{OPEN standard commands}
|
||||
The following commands are only valid for a calibration standard of type ``Open''. The ``x'' in the command names must be replaced with the calibration standard number.
|
||||
|
||||
\subsubsubsection{VNA:CALibration:KIT:STAndard:x:NAME}
|
||||
\event{Sets the name of the standard}{VNA:CALibration:KIT:STAndard:x:NAME}{<name> User selectable name}
|
||||
\query{Queries the name of the standard}{VNA:CALibration:KIT:STAndard:x:NAME?}{None}{<name> User selectable name}
|
||||
|
||||
\subsubsubsection{VNA:CALibration:KIT:STAndard:x:Z0}
|
||||
\event{Sets the characteristic impedance of the standard}{VNA:CALibration:KIT:STAndard:x:Z0}{<Z> Characteristic impedance in Ohm}
|
||||
\query{Queries the characteristic impedance of the standard}{VNA:CALibration:KIT:STAndard:x:Z0?}{None}{<Z> Characteristic impedance in Ohm}
|
||||
|
||||
\subsubsubsection{VNA:CALibration:KIT:STAndard:x:DELAY}
|
||||
\event{Sets the delay of the standard}{VNA:CALibration:KIT:STAndard:x:DELAY}{<delay> Delay in \unit{\pico\second}}
|
||||
\query{Queries the delay of the standard}{VNA:CALibration:KIT:STAndard:x:DELAY?}{None}{<delay> Delay in \unit{\pico\second}}
|
||||
|
||||
\subsubsubsection{VNA:CALibration:KIT:STAndard:x:LOSS}
|
||||
\event{Sets the loss of the standard}{VNA:CALibration:KIT:STAndard:x:LOSS}{<loss> Loss in \unit{\giga\ohm\per\second}}
|
||||
\query{Queries the loss of the standard}{VNA:CALibration:KIT:STAndard:x:LOSS?}{None}{<loss> Loss in \unit{\giga\ohm\per\second}}
|
||||
|
||||
\subsubsubsection{VNA:CALibration:KIT:STAndard:x:C0}
|
||||
\event{Sets the fringing capacitance polynom term 0 of the standard}{VNA:CALibration:KIT:STAndard:x:C0}{<C0> in \num{d-15}\unit{\farad}}
|
||||
\query{Queries the fringing capacitance polynom term 0 of the standard}{VNA:CALibration:KIT:STAndard:x:C0?}{None}{<C0> in \num{d-15}\unit{\farad}}
|
||||
|
||||
\subsubsubsection{VNA:CALibration:KIT:STAndard:x:C1}
|
||||
\event{Sets the fringing capacitance polynom term 1 of the standard}{VNA:CALibration:KIT:STAndard:x:C1}{<C1> in \num{d-27}\unit{\farad\per\hertz}}
|
||||
\query{Queries the fringing capacitance polynom term 1 of the standard}{VNA:CALibration:KIT:STAndard:x:C1?}{None}{<C1> in \num{d-27}\unit{\farad\per\hertz}}
|
||||
|
||||
\subsubsubsection{VNA:CALibration:KIT:STAndard:x:C2}
|
||||
\event{Sets the fringing capacitance polynom term 2 of the standard}{VNA:CALibration:KIT:STAndard:x:C2}{<C2> in \num{d-36}\unit{\farad\per\hertz\squared}}
|
||||
\query{Queries the fringing capacitance polynom term 2 of the standard}{VNA:CALibration:KIT:STAndard:x:C2?}{None}{<C2> in \num{d-36}\unit{\farad\per\hertz\squared}}
|
||||
|
||||
\subsubsubsection{VNA:CALibration:KIT:STAndard:x:C3}
|
||||
\event{Sets the fringing capacitance polynom term 3 of the standard}{VNA:CALibration:KIT:STAndard:x:C3}{<C3> in \num{d-45}\unit{\farad\per\hertz\cubed}}
|
||||
\query{Queries the fringing capacitance polynom term 3 of the standard}{VNA:CALibration:KIT:STAndard:x:C3?}{None}{<C3> in \num{d-45}\unit{\farad\per\hertz\cubed}}
|
||||
|
||||
\subsubsubsection{VNA:CALibration:KIT:STAndard:x:FILE}
|
||||
\event{Loads the coefficients for the calibration standard from a touchstone file}{VNA:CALibration:KIT:STAndard:x:FILE}{<filename>\\<port> sets the port from the file which is used to define the standard, optional}
|
||||
|
||||
\subsubsection{SHORT standard commands}
|
||||
The following commands are only valid for a calibration standard of type ``Short''. The ``x'' in the command names must be replaced with the calibration standard number.
|
||||
|
||||
\subsubsubsection{VNA:CALibration:KIT:STAndard:x:NAME}
|
||||
\event{Sets the name of the standard}{VNA:CALibration:KIT:STAndard:x:NAME}{<name> User selectable name}
|
||||
\query{Queries the name of the standard}{VNA:CALibration:KIT:STAndard:x:NAME?}{None}{<name> User selectable name}
|
||||
|
||||
\subsubsubsection{VNA:CALibration:KIT:STAndard:x:Z0}
|
||||
\event{Sets the characteristic impedance of the standard}{VNA:CALibration:KIT:STAndard:x:Z0}{<Z> Characteristic impedance in Ohm}
|
||||
\query{Queries the characteristic impedance of the standard}{VNA:CALibration:KIT:STAndard:x:Z0?}{None}{<Z> Characteristic impedance in Ohm}
|
||||
|
||||
\subsubsubsection{VNA:CALibration:KIT:STAndard:x:DELAY}
|
||||
\event{Sets the delay of the standard}{VNA:CALibration:KIT:STAndard:x:DELAY}{<delay> Delay in \unit{\pico\second}}
|
||||
\query{Queries the delay of the standard}{VNA:CALibration:KIT:STAndard:x:DELAY?}{None}{<delay> Delay in \unit{\pico\second}}
|
||||
|
||||
\subsubsubsection{VNA:CALibration:KIT:STAndard:x:LOSS}
|
||||
\event{Sets the loss of the standard}{VNA:CALibration:KIT:STAndard:x:LOSS}{<loss> Loss in \unit{\giga\ohm\per\second}}
|
||||
\query{Queries the loss of the standard}{VNA:CALibration:KIT:STAndard:x:LOSS?}{None}{<loss> Loss in \unit{\giga\ohm\per\second}}
|
||||
|
||||
\subsubsubsection{VNA:CALibration:KIT:STAndard:x:L0}
|
||||
\event{Sets the residual inductance polynom term 0 of the standard}{VNA:CALibration:KIT:STAndard:x:L0}{<L0> in \num{d-12}\unit{\henry}}
|
||||
\query{Queries the residual inductance polynom term 0 of the standard}{VNA:CALibration:KIT:STAndard:x:L0?}{None}{<L0> in \num{d-12}\unit{\henry}}
|
||||
|
||||
\subsubsubsection{VNA:CALibration:KIT:STAndard:x:L1}
|
||||
\event{Sets the residual inductance polynom term 1 of the standard}{VNA:CALibration:KIT:STAndard:x:L1}{<L1> in \num{d-24}\unit{\henry\per\hertz}}
|
||||
\query{Queries the residual inductance polynom term 1 of the standard}{VNA:CALibration:KIT:STAndard:x:L1?}{None}{<L1> in \num{d-24}\unit{\henry\per\hertz}}
|
||||
|
||||
\subsubsubsection{VNA:CALibration:KIT:STAndard:x:L2}
|
||||
\event{Sets the residual inductance polynom term 2 of the standard}{VNA:CALibration:KIT:STAndard:x:L2}{<L2> in \num{d-33}\unit{\henry\per\hertz\squared}}
|
||||
\query{Queries the residual inductance polynom term 2 of the standard}{VNA:CALibration:KIT:STAndard:x:L2?}{None}{<L2> in \num{d-33}\unit{\henry\per\hertz\squared}}
|
||||
|
||||
\subsubsubsection{VNA:CALibration:KIT:STAndard:x:L3}
|
||||
\event{Sets the residual inductance polynom term 3 of the standard}{VNA:CALibration:KIT:STAndard:x:L3}{<L3> in \num{d-42}\unit{\henry\per\hertz\cubed}}
|
||||
\query{Queries the residual inductance polynom term 3 of the standard}{VNA:CALibration:KIT:STAndard:x:L3?}{None}{<L3> in \num{d-42}\unit{\henry\per\hertz\cubed}}
|
||||
|
||||
\subsubsubsection{VNA:CALibration:KIT:STAndard:x:FILE}
|
||||
\event{Loads the coefficients for the calibration standard from a touchstone file}{VNA:CALibration:KIT:STAndard:x:FILE}{<filename>\\<port> sets the port from the file which is used to define the standard, optional}
|
||||
|
||||
\subsubsection{LOAD standard commands}
|
||||
The following commands are only valid for a calibration standard of type ``Load''. The ``x'' in the command names must be replaced with the calibration standard number.
|
||||
|
||||
\subsubsubsection{VNA:CALibration:KIT:STAndard:x:NAME}
|
||||
\event{Sets the name of the standard}{VNA:CALibration:KIT:STAndard:x:NAME}{<name> User selectable name}
|
||||
\query{Queries the name of the standard}{VNA:CALibration:KIT:STAndard:x:NAME?}{None}{<name> User selectable name}
|
||||
|
||||
\subsubsubsection{VNA:CALibration:KIT:STAndard:x:RESistance}
|
||||
\event{Sets the resistance of the standard}{VNA:CALibration:KIT:STAndard:x:RESistance}{<R> in \unit{\ohm}}
|
||||
\query{Queries the resistance of the standard}{VNA:CALibration:KIT:STAndard:x:RESistance?}{None}{<R> in \unit{\ohm}}
|
||||
|
||||
\subsubsubsection{VNA:CALibration:KIT:STAndard:x:Z0}
|
||||
\event{Sets the characteristic impedance of the standard}{VNA:CALibration:KIT:STAndard:x:Z0}{<Z> Characteristic impedance in Ohm}
|
||||
\query{Queries the characteristic impedance of the standard}{VNA:CALibration:KIT:STAndard:x:Z0?}{None}{<Z> Characteristic impedance in Ohm}
|
||||
|
||||
\subsubsubsection{VNA:CALibration:KIT:STAndard:x:DELAY}
|
||||
\event{Sets the delay of the standard}{VNA:CALibration:KIT:STAndard:x:DELAY}{<delay> Delay in \unit{\pico\second}}
|
||||
\query{Queries the delay of the standard}{VNA:CALibration:KIT:STAndard:x:DELAY?}{None}{<delay> Delay in \unit{\pico\second}}
|
||||
|
||||
\subsubsubsection{VNA:CALibration:KIT:STAndard:x:LOSS}
|
||||
\event{Sets the loss of the standard}{VNA:CALibration:KIT:STAndard:x:LOSS}{<loss> Loss in \unit{\giga\ohm\per\second}}
|
||||
\query{Queries the loss of the standard}{VNA:CALibration:KIT:STAndard:x:LOSS?}{None}{<loss> Loss in \unit{\giga\ohm\per\second}}
|
||||
|
||||
\subsubsubsection{VNA:CALibration:KIT:STAndard:x:CARallel}
|
||||
\event{Sets the residual capacitance polynom of the standard}{VNA:CALibration:KIT:STAndard:x:CARallel}{<C> in \unit{\farad}}
|
||||
\query{Queries the residual capacitance of the standard}{VNA:CALibration:KIT:STAndard:x:CARallel?}{None}{<C> in \unit{\farad}}
|
||||
|
||||
\subsubsubsection{VNA:CALibration:KIT:STAndard:x:LSERies}
|
||||
\event{Sets the residual inductance of the standard}{VNA:CALibration:KIT:STAndard:x:LSERies}{<L> in \unit{\henry}}
|
||||
\query{Queries the residual inductance of the standard}{VNA:CALibration:KIT:STAndard:x:LSERies?}{None}{<L> in \unit{\henry}}
|
||||
|
||||
\subsubsubsection{VNA:CALibration:KIT:STAndard:x:CFIRST}
|
||||
\event{Sets the order of residual capacitance/inductance}{VNA:CALibration:KIT:STAndard:x:CFIRST}{TRUE or FALSE}
|
||||
\query{Queries the order of residual capacitance/inductance}{VNA:CALibration:KIT:STAndard:x:CFIRST?}{None}{TRUE or FALSE}
|
||||
|
||||
\subsubsubsection{VNA:CALibration:KIT:STAndard:x:FILE}
|
||||
\event{Loads the coefficients for the calibration standard from a touchstone file}{VNA:CALibration:KIT:STAndard:x:FILE}{<filename>\\<port> sets the port from the file which is used to define the standard, optional}
|
||||
|
||||
\subsubsection{REFLECT standard commands}
|
||||
The following commands are only valid for a calibration standard of type ``Reflect''. The ``x'' in the command names must be replaced with the calibration standard number.
|
||||
|
||||
\subsubsubsection{VNA:CALibration:KIT:STAndard:x:NAME}
|
||||
\event{Sets the name of the standard}{VNA:CALibration:KIT:STAndard:x:NAME}{<name> User selectable name}
|
||||
\query{Queries the name of the standard}{VNA:CALibration:KIT:STAndard:x:NAME?}{None}{<name> User selectable name}
|
||||
|
||||
\subsubsubsection{VNA:CALibration:KIT:STAndard:x:SHORT}
|
||||
\event{Sets the type of reflection standard}{VNA:CALibration:KIT:STAndard:x:SHORT}{TRUE for short standard or FALSE for open standard}
|
||||
\query{Queries the type of reflection standard}{VNA:CALibration:KIT:STAndard:x:SHORT?}{None}{TRUE for short standard or FALSE for open standard}
|
||||
|
||||
\subsubsection{THROUGH standard commands}
|
||||
The following commands are only valid for a calibration standard of type ``Through''. The ``x'' in the command names must be replaced with the calibration standard number.
|
||||
|
||||
\subsubsubsection{VNA:CALibration:KIT:STAndard:x:NAME}
|
||||
\event{Sets the name of the standard}{VNA:CALibration:KIT:STAndard:x:NAME}{<name> User selectable name}
|
||||
\query{Queries the name of the standard}{VNA:CALibration:KIT:STAndard:x:NAME?}{None}{<name> User selectable name}
|
||||
|
||||
\subsubsubsection{VNA:CALibration:KIT:STAndard:x:Z0}
|
||||
\event{Sets the characteristic impedance of the standard}{VNA:CALibration:KIT:STAndard:x:Z0}{<Z> Characteristic impedance in Ohm}
|
||||
\query{Queries the characteristic impedance of the standard}{VNA:CALibration:KIT:STAndard:x:Z0?}{None}{<Z> Characteristic impedance in Ohm}
|
||||
|
||||
\subsubsubsection{VNA:CALibration:KIT:STAndard:x:DELAY}
|
||||
\event{Sets the delay of the standard}{VNA:CALibration:KIT:STAndard:x:DELAY}{<delay> Delay in \unit{\pico\second}}
|
||||
\query{Queries the delay of the standard}{VNA:CALibration:KIT:STAndard:x:DELAY?}{None}{<delay> Delay in \unit{\pico\second}}
|
||||
|
||||
\subsubsubsection{VNA:CALibration:KIT:STAndard:x:LOSS}
|
||||
\event{Sets the loss of the standard}{VNA:CALibration:KIT:STAndard:x:LOSS}{<loss> Loss in \unit{\giga\ohm\per\second}}
|
||||
\query{Queries the loss of the standard}{VNA:CALibration:KIT:STAndard:x:LOSS?}{None}{<loss> Loss in \unit{\giga\ohm\per\second}}
|
||||
|
||||
\subsubsubsection{VNA:CALibration:KIT:STAndard:x:FILE}
|
||||
\event{Loads the coefficients for the calibration standard from a touchstone file}{VNA:CALibration:KIT:STAndard:x:FILE}{<filename>\\
|
||||
<port1> selects the first port from the file which is used to define the standard\\
|
||||
<port1> selects the second port from the file which is used to define the standard}
|
||||
|
||||
\subsubsection{LINE standard commands}
|
||||
The following commands are only valid for a calibration standard of type ``Line''. The ``x'' in the command names must be replaced with the calibration standard number.
|
||||
|
||||
\subsubsubsection{VNA:CALibration:KIT:STAndard:x:NAME}
|
||||
\event{Sets the name of the standard}{VNA:CALibration:KIT:STAndard:x:NAME}{<name> User selectable name}
|
||||
\query{Queries the name of the standard}{VNA:CALibration:KIT:STAndard:x:NAME?}{None}{<name> User selectable name}
|
||||
|
||||
\subsubsubsection{VNA:CALibration:KIT:STAndard:x:Z0}
|
||||
\event{Sets the characteristic impedance of the standard}{VNA:CALibration:KIT:STAndard:x:Z0}{<Z> Characteristic impedance in Ohm}
|
||||
\query{Queries the characteristic impedance of the standard}{VNA:CALibration:KIT:STAndard:x:Z0?}{None}{<Z> Characteristic impedance in Ohm}
|
||||
|
||||
\subsubsubsection{VNA:CALibration:KIT:STAndard:x:DELAY}
|
||||
\event{Sets the delay of the standard}{VNA:CALibration:KIT:STAndard:x:DELAY}{<delay> Delay in \unit{\pico\second}}
|
||||
\query{Queries the delay of the standard}{VNA:CALibration:KIT:STAndard:x:DELAY?}{None}{<delay> Delay in \unit{\pico\second}}
|
||||
|
||||
\subsubsubsection{VNA:CALibration:KIT:STAndard:x:FILE}
|
||||
\event{Loads the coefficients for the calibration standard from a touchstone file}{VNA:CALibration:KIT:STAndard:x:FILE}{<filename>\\
|
||||
<port1> selects the first port from the file which is used to define the standard\\
|
||||
<port1> selects the second port from the file which is used to define the standard}
|
||||
|
||||
\subsubsection{Common Deembedding Commands}
|
||||
The VNA supports various deembedding options which can also be configured through the SCPI API. Because the deembedding system is flexible and supports any number of deembedding options at the same time, the SCPI API is also flexible. Instead of fixed commands, the available commands change depending on the configured deembedding options.
|
||||
|
||||
A few deembedding commands are always available and they can be used to create, delete and swap deembedding options. Every created deembedding option adds their own commands. They can be accessed by including the option number in the command (shown as ``x'' in the following commands).
|
||||
|
||||
\subsubsubsection{VNA:DEEMBedding:NUMber}
|
||||
\query{Returns the number of configured deembedding options}{VNA:DEEMBedding:NUMber?}{None}{<number of deembedding options>}
|
||||
|
||||
\subsubsubsection{VNA:DEEMBedding:TYPE}
|
||||
\query{Returns the type of a configured deembedding option}{VNA:DEEMBedding:TYPE?}{<x> Number of deembedding option}{Type of option, one of:\\
|
||||
\hspace{1cm}Port\_Extension\\
|
||||
\hspace{1cm}2xThru\\
|
||||
\hspace{1cm}Matching\_Network\\
|
||||
\hspace{1cm}Impedance\_Renormalization\\}
|
||||
|
||||
\subsubsubsection{VNA:DEEMBedding:NEW}
|
||||
\event{Adds a new deembedding option}{VNA:DEEMBedding:NEW}{<type> Type of option, one of:\\
|
||||
\hspace{1cm}Port\_Extension\\
|
||||
\hspace{1cm}2xThru\\
|
||||
\hspace{1cm}Matching\_Network\\
|
||||
\hspace{1cm}Impedance\_Renormalization\\}
|
||||
|
||||
\subsubsubsection{VNA:DEEMBedding:DELete}
|
||||
\event{Removes a deembedding option}{VNA:DEEMBedding:DELete}{<x> Number of option to delete}
|
||||
|
||||
\subsubsubsection{VNA:DEEMBedding:SWAP}
|
||||
\event{Swaps the order of two deembedding options}{VNA:DEEMBedding:SWAP}{<x1> Number of option 1 to swap\\<x2> Number of option 2 to swap}
|
||||
|
||||
\subsubsubsection{VNA:DEEMBedding:CLEAR}
|
||||
\event{Delete all deembedding options}{VNA:DEEMBedding:CLEAR}{None}
|
||||
|
||||
\subsubsection{Port Extension Deembedding Commands}
|
||||
The following commands are only valid for a deembedding option of type ``Port\_Extension''. The ``x'' in the command names must be replaced with the option number.
|
||||
|
||||
\subsubsubsection{VNA:DEEMBedding:x:PORT}
|
||||
\event{Sets the port}{VNA:DEEMBedding:x:PORT}{<port>, 1...n}
|
||||
\query{Queries the selected port}{VNA:DEEMBedding:x:PORT?}{None}{<port>, 1...n}
|
||||
|
||||
\subsubsubsection{VNA:DEEMBedding:x:DELAY}
|
||||
\event{Sets the delay of the port extension}{VNA:DEEMBedding:x:DELAY}{<delay> Delay in seconds}
|
||||
\query{Queries the delay of the port extension}{VNA:DEEMBedding:x:DELAY?}{None}{<delay> Delay in seconds}
|
||||
|
||||
\subsubsubsection{VNA:DEEMBedding:x:DCLOSS}
|
||||
\event{Sets the DC loss of the port extension}{VNA:DEEMBedding:x:DCLOSS}{<loss> Loss at DC in dB}
|
||||
\query{Queries the DC loss of the port extension}{VNA:DEEMBedding:x:DCLOSS?}{None}{<loss> Loss at DC in dB}
|
||||
|
||||
\subsubsubsection{VNA:DEEMBedding:x:LOSS}
|
||||
\event{Sets the loss of the port extension at the configured frequency}{VNA:DEEMBedding:x:LOSS}{<loss> Loss at frequency in dB}
|
||||
\query{Queries the loss of the port extension at the configured frequency}{VNA:DEEMBedding:x:LOSS?}{None}{<loss> Loss at frequency in dB}
|
||||
|
||||
\subsubsubsection{VNA:DEEMBedding:x:FREQuency}
|
||||
\event{Sets the frequency for the specified loss of the port extension}{VNA:DEEMBedding:x:FREQuency}{<freq> Frequency for loss in Hz}
|
||||
\query{Queries the frequency for the specified loss of the port extension}{VNA:DEEMBedding:x:FREQuency?}{None}{<freq> Frequency for loss in Hz}
|
||||
|
||||
\subsubsection{2xThru Deembedding Commands}
|
||||
The 2xThru deembedding does not have a SCPI API so far because it requires the user to manually make specific connections and take additional measurements.
|
||||
|
||||
\subsubsection{Matching Network Deembedding Commands}
|
||||
The following commands are only valid for a deembedding option of type ``Matching\_Network''. The ``x'' in the command names must be replaced with the option number.
|
||||
|
||||
Similarly to the deembedding options, the matching network itself is also flexible and requires a flexible API as well. A similar approach is used where components in the matching network are given a number. This number is shown as ``y'' in the following commands.
|
||||
|
||||
\subsubsubsection{VNA:DEEMBedding:x:PORT}
|
||||
\event{Sets the port at which the matching network is added}{VNA:DEEMBedding:x:PORT}{<port>, 1...n}
|
||||
\query{Queries the port at which the matching network is added}{VNA:DEEMBedding:x:PORT?}{None}{<port>, 1...n}
|
||||
|
||||
\subsubsubsection{VNA:DEEMBedding:x:ADD}
|
||||
\event{Selects whether the network is added or removed during the deembedding}{VNA:DEEMBedding:x:ADD}{TRUE if the effect of the network should be added. FALSE if the effect of the\\
|
||||
\hspace{1cm}network should be subtracted}
|
||||
\query{Queries whether the network is added or removed during the deembedding}{VNA:DEEMBedding:x:ADD?}{None}{TRUE or FALSE}
|
||||
|
||||
\subsubsubsection{VNA:DEEMBedding:x:NUMber}
|
||||
\query{Returns the number of configured matching network components}{VNA:DEEMBedding:x:NUMber?}{None}{<number of matching network components>}
|
||||
|
||||
\subsubsubsection{VNA:DEEMBedding:x:TYPE}
|
||||
\query{Returns the type of a configured matching network component}{VNA:DEEMBedding:x:TYPE? <y>}{<y> Number of matching component}{Type of component, one of:\\
|
||||
\hspace{1cm}SeriesR\\
|
||||
\hspace{1cm}SeriesL\\
|
||||
\hspace{1cm}SeriesC\\
|
||||
\hspace{1cm}ParallelR\\
|
||||
\hspace{1cm}ParallelL\\
|
||||
\hspace{1cm}ParallelC\\
|
||||
\hspace{1cm}Touchstone\_Through\\
|
||||
\hspace{1cm}Touchstone\_Shunt\\}
|
||||
|
||||
\subsubsubsection{VNA:DEEMBedding:x:NEW}
|
||||
\event{Adds a new matching network component}{VNA:DEEMBedding:x:NEW}{<type> Type of component, one of:\\
|
||||
\hspace{1cm}SeriesR\\
|
||||
\hspace{1cm}SeriesL\\
|
||||
\hspace{1cm}SeriesC\\
|
||||
\hspace{1cm}ParallelR\\
|
||||
\hspace{1cm}ParallelL\\
|
||||
\hspace{1cm}ParallelC\\
|
||||
\hspace{1cm}Touchstone\_Through\\
|
||||
\hspace{1cm}Touchstone\_Shunt\\
|
||||
<pos> position at which the component will be added. A value of 0 adds the\\
|
||||
\hspace{1cm}component closest to the port. This parameter is optional. If it is omitted,\\
|
||||
\hspace{1cm}the component is added closest to the DUT}
|
||||
|
||||
\subsubsubsection{VNA:DEEMBedding:x:DELete}
|
||||
\event{Removes a matching network component}{VNA:DEEMBedding:x:DELete}{<y> Number of component to delete}
|
||||
|
||||
\subsubsubsection{VNA:DEEMBedding:x:CLEAR}
|
||||
\event{Removes all matching network components}{VNA:DEEMBedding:x:DELete}{None}
|
||||
|
||||
\subsubsection{Impedance Renormalization Deembedding Commands}
|
||||
The following commands are only valid for a deembedding option of type ``Impedance\_Renormalization''. The ``x'' in the command names must be replaced with the option number.
|
||||
|
||||
\subsubsubsection{VNA:DEEMBedding:x:IMPedance}
|
||||
\event{Sets the target impedance}{VNA:DEEMBedding:x:IMPedance}{<impedance> Impedance in Ohm}
|
||||
\query{Queries the target impedance}{VNA:DEEMBedding:x:IMPedance?}{None}{<impedance> Impedance in Ohm}
|
||||
|
||||
\subsubsubsection{VNA:DEEMBedding:x:y:VALue}
|
||||
\event{Sets the value of a matching network component}{VNA:DEEMBedding:x:y:VALue}{<value>, either in Ohm, Farad or Henry}
|
||||
\query{Queries the value of a matching network component}{VNA:DEEMBedding:x:y:VALue?}{None}{<port>, either in Ohm, Farad or Henry}
|
||||
|
||||
This command is only available for a component of these types:
|
||||
\begin{itemize}
|
||||
\item SeriesR
|
||||
\item SeriesL
|
||||
\item SeriesC
|
||||
\item ParallelR
|
||||
\item ParallelL
|
||||
\item ParallelC
|
||||
\end{itemize}
|
||||
|
||||
\subsubsubsection{VNA:DEEMBedding:x:y:FILE}
|
||||
\event{Loads a matching network component values from a Touchstone file}{VNA:DEEMBedding:x:y:FILE}{<filename>}
|
||||
|
||||
This command is only available for a component of these types:
|
||||
\begin{itemize}
|
||||
\item Touchstone\_Through
|
||||
\item Touchstone\_Shunt
|
||||
\end{itemize}
|
||||
|
||||
\subsection{Signal Generator Commands}
|
||||
These commands change or query signal generator settings. Although most of them are available regardless of the current device mode, they usually only have an effect once the generator mode is active.
|
||||
|
||||
|
|
@ -760,6 +1136,16 @@ If single sweep is enabled, the acquisition is stopped when the required number
|
|||
\event{Enables/disables signal identification}{SA:ACQuisition:SIGid}{<enabled>, option are TRUE, FALSE, 1 or 0}
|
||||
\query{Queries whether signal identification is enabled}{SA:ACQuisition:SIGid?}{None}{TRUE or FALSE}
|
||||
|
||||
\subsubsection{SA:ACQuisition:FREQuency}
|
||||
\query{Returns the current frequency of the sweep}{SA:ACQuisition:FREQuency?}{None}{<Frequency in Hz>}
|
||||
|
||||
This command only returns valid data when a sweep is running and the the sweep is a frequency sweep.
|
||||
|
||||
\subsubsection{SA:ACQuisition:TIME}
|
||||
\query{Returns the current time of the sweep}{SA:ACQuisition:TIME?}{None}{<Time in seconds>}
|
||||
|
||||
This command only returns valid data when a sweep is running and the the sweep is a zero-span sweep.
|
||||
|
||||
\subsubsection{SA:TRACKing:ENable}
|
||||
\event{Enables/disables the tracking generator}{SA:TRACKing:ENable}{<enabled>, option are TRUE, FALSE, 1 or 0}
|
||||
\query{Queries whether tracking generator is enabled}{SA:TRACKing:ENable?}{None}{TRUE or FALSE}
|
||||
|
|
|
|||
|
|
@ -1708,10 +1708,8 @@ bool Calibration::fromFile(QString filename)
|
|||
}
|
||||
calkit_file.append(".calkit");
|
||||
qDebug() << "Associated calibration kit expected in" << calkit_file;
|
||||
try {
|
||||
kit = Calkit::fromFile(calkit_file);
|
||||
} catch (runtime_error &e) {
|
||||
qDebug() << "Parsing of calibration kit failed while opening calibration file: " << e.what() << " (ignore for calibration format >= 3)";
|
||||
if(!kit.fromFile(calkit_file)) {
|
||||
qDebug() << "Parsing of calibration kit failed while opening calibration file (ignore for calibration format >= 3)";
|
||||
}
|
||||
|
||||
ifstream file;
|
||||
|
|
|
|||
|
|
@ -16,13 +16,47 @@ using json = nlohmann::json;
|
|||
using namespace std;
|
||||
|
||||
Calkit::Calkit()
|
||||
: SCPINode("KIT")
|
||||
: SCPINode("KIT"), scpi_std("STAndard")
|
||||
{
|
||||
// set default values
|
||||
filename = "";
|
||||
for(auto e : descr) {
|
||||
e.var.setValue(e.def);
|
||||
}
|
||||
|
||||
add(new SCPICommand("MANufacturer", [=](QStringList params) -> QString {
|
||||
if(params.size() != 1 ) {
|
||||
// no new value given
|
||||
return SCPI::getResultName(SCPI::Result::Error);
|
||||
}
|
||||
manufacturer = params[0];
|
||||
return SCPI::getResultName(SCPI::Result::Empty);
|
||||
}, [=](QStringList) -> QString {
|
||||
return manufacturer;
|
||||
}, false));
|
||||
add(new SCPICommand("SERial", [=](QStringList params) -> QString {
|
||||
if(params.size() != 1 ) {
|
||||
// no new value given
|
||||
return SCPI::getResultName(SCPI::Result::Error);
|
||||
}
|
||||
serialnumber = params[0];
|
||||
return SCPI::getResultName(SCPI::Result::Empty);
|
||||
}, [=](QStringList) -> QString {
|
||||
return serialnumber;
|
||||
}, false));
|
||||
add(new SCPICommand("DESCription", [=](QStringList params) -> QString {
|
||||
if(params.size() != 1 ) {
|
||||
// no new value given
|
||||
return SCPI::getResultName(SCPI::Result::Error);
|
||||
}
|
||||
description = params[0];
|
||||
return SCPI::getResultName(SCPI::Result::Empty);
|
||||
}, [=](QStringList) -> QString {
|
||||
return description;
|
||||
}, false));
|
||||
add(new SCPICommand("FILEname", nullptr, [=](QStringList) -> QString {
|
||||
return filename;
|
||||
}));
|
||||
add(new SCPICommand("SAVE", [=](QStringList params) -> QString {
|
||||
if(params.size() != 1 ) {
|
||||
// no filename given or no calibration active
|
||||
|
|
@ -30,19 +64,65 @@ Calkit::Calkit()
|
|||
}
|
||||
toFile(params[0]);
|
||||
return SCPI::getResultName(SCPI::Result::Empty);
|
||||
}, nullptr));
|
||||
}, nullptr, false));
|
||||
add(new SCPICommand("LOAD", nullptr, [=](QStringList params) -> QString {
|
||||
if(params.size() != 1) {
|
||||
// no filename given or no calibration active
|
||||
return SCPI::getResultName(SCPI::Result::False);
|
||||
}
|
||||
try {
|
||||
*this = fromFile(params[0]);
|
||||
if(this->fromFile(params[0])) {
|
||||
return SCPI::getResultName(SCPI::Result::True);
|
||||
} catch (runtime_error &e) {
|
||||
} else {
|
||||
return SCPI::getResultName(SCPI::Result::False);
|
||||
}
|
||||
}, false));
|
||||
scpi_std.add(new SCPICommand("CLEAR", [=](QStringList params) -> QString {
|
||||
Q_UNUSED(params);
|
||||
setIdealDefault();
|
||||
return SCPI::getResultName(SCPI::Result::Empty);
|
||||
}, nullptr));
|
||||
scpi_std.add(new SCPICommand("NUMber", nullptr, [=](QStringList params) -> QString {
|
||||
Q_UNUSED(params);
|
||||
return QString::number(standards.size());
|
||||
}));
|
||||
scpi_std.add(new SCPICommand("NEW", [=](QStringList params) -> QString {
|
||||
if(params.size() != 2) {
|
||||
return SCPI::getResultName(SCPI::Result::Error);
|
||||
}
|
||||
auto type = CalStandard::Virtual::TypeFromString(params[0]);
|
||||
if(type == CalStandard::Virtual::Type::Last) {
|
||||
return SCPI::getResultName(SCPI::Result::Error);
|
||||
}
|
||||
auto s = CalStandard::Virtual::create(type);
|
||||
if(!s) {
|
||||
return SCPI::getResultName(SCPI::Result::Error);
|
||||
}
|
||||
s->setName(params[1]);
|
||||
addStandard(s);
|
||||
return SCPI::getResultName(SCPI::Result::Empty);
|
||||
}, nullptr, false));
|
||||
scpi_std.add(new SCPICommand("DELete", [=](QStringList params) -> QString {
|
||||
unsigned long long index;
|
||||
if(!SCPI::paramToULongLong(params, 0, index)) {
|
||||
return SCPI::getResultName(SCPI::Result::Error);
|
||||
}
|
||||
if(index < 1 || index > standards.size()) {
|
||||
return SCPI::getResultName(SCPI::Result::Error);
|
||||
}
|
||||
removeStandard(standards[index-1]);
|
||||
return SCPI::getResultName(SCPI::Result::Empty);
|
||||
}, nullptr));
|
||||
scpi_std.add(new SCPICommand("TYPE", nullptr, [=](QStringList params) -> QString {
|
||||
unsigned long long index = 0;
|
||||
if(!SCPI::paramToULongLong(params, 0, index)) {
|
||||
return SCPI::getResultName(SCPI::Result::Error);
|
||||
}
|
||||
if(index < 1 || index > standards.size()) {
|
||||
return SCPI::getResultName(SCPI::Result::Error);
|
||||
}
|
||||
return CalStandard::Virtual::TypeToString(standards[index-1]->getType()).replace(" ", "_");
|
||||
}));
|
||||
add(&scpi_std);
|
||||
}
|
||||
|
||||
void Calkit::toFile(QString filename)
|
||||
|
|
@ -57,6 +137,7 @@ void Calkit::toFile(QString filename)
|
|||
file.open(filename.toStdString());
|
||||
file << setw(4) << toJSON() << endl;
|
||||
file.close();
|
||||
this->filename = filename;
|
||||
}
|
||||
|
||||
static QString readLine(ifstream &file) {
|
||||
|
|
@ -65,27 +146,29 @@ static QString readLine(ifstream &file) {
|
|||
return QString::fromStdString(line).simplified();
|
||||
}
|
||||
|
||||
Calkit Calkit::fromFile(QString filename)
|
||||
bool Calkit::fromFile(QString filename)
|
||||
{
|
||||
qDebug() << "Opening calkit to file" << filename;
|
||||
qDebug() << "Opening calkit from file" << filename;
|
||||
|
||||
auto c = Calkit();
|
||||
ifstream file;
|
||||
file.open(filename.toStdString());
|
||||
if(!file.is_open()) {
|
||||
throw runtime_error("Unable to open file");
|
||||
qWarning() << "Unable to open file: " << filename;
|
||||
return false;
|
||||
}
|
||||
|
||||
json j;
|
||||
try {
|
||||
file >> j;
|
||||
} catch (exception &e) {
|
||||
throw runtime_error("JSON parsing error: " + string(e.what()));
|
||||
qWarning() << "JSON parsing error: " << QString(e.what());
|
||||
return false;
|
||||
}
|
||||
c.clearStandards();
|
||||
clearStandards();
|
||||
this->filename = "";
|
||||
if(j.contains("standards")) {
|
||||
qDebug() << "new JSON format detected";
|
||||
c.fromJSON(j);
|
||||
fromJSON(j);
|
||||
} else {
|
||||
// older format is used
|
||||
struct {
|
||||
|
|
@ -133,7 +216,7 @@ Calkit Calkit::fromFile(QString filename)
|
|||
if(j.contains("SOLT")) {
|
||||
qDebug() << "old JSON format detected";
|
||||
// calkit file uses json format, parse
|
||||
Savable::parseJSON(j, c.descr);
|
||||
Savable::parseJSON(j, descr);
|
||||
const std::vector<Savable::SettingDescription> descr_deprecated = {{
|
||||
{&SOLT.open_m.Z0, "SOLT.Open.Param.Z0", 50.0},
|
||||
{&SOLT.open_m.delay, "SOLT.Open.Param.Delay", 0.0},
|
||||
|
|
@ -286,7 +369,7 @@ Calkit Calkit::fromFile(QString filename)
|
|||
ts.fromFile(SOLT.open_m.file.toStdString());
|
||||
open_m->setMeasurement(ts, SOLT.open_m.Sparam);
|
||||
}
|
||||
c.addStandard(open_m);
|
||||
addStandard(open_m);
|
||||
if(SOLT.separate_male_female) {
|
||||
auto open_f = new CalStandard::Open("Default female standard", SOLT.open_f.Z0, SOLT.open_f.delay, SOLT.open_f.loss, SOLT.open_f.C0, SOLT.open_f.C1, SOLT.open_f.C2, SOLT.open_f.C3);
|
||||
if(SOLT.open_f.useMeasurements) {
|
||||
|
|
@ -294,7 +377,7 @@ Calkit Calkit::fromFile(QString filename)
|
|||
ts.fromFile(SOLT.open_f.file.toStdString());
|
||||
open_m->setMeasurement(ts, SOLT.open_f.Sparam);
|
||||
}
|
||||
c.addStandard(open_f);
|
||||
addStandard(open_f);
|
||||
}
|
||||
|
||||
auto short_m = new CalStandard::Short(SOLT.separate_male_female ? "Default male standard" : "Default standard", SOLT.short_m.Z0, SOLT.short_m.delay, SOLT.short_m.loss, SOLT.short_m.L0, SOLT.short_m.L1, SOLT.short_m.L2, SOLT.short_m.L3);
|
||||
|
|
@ -303,7 +386,7 @@ Calkit Calkit::fromFile(QString filename)
|
|||
ts.fromFile(SOLT.short_m.file.toStdString());
|
||||
short_m->setMeasurement(ts, SOLT.short_m.Sparam);
|
||||
}
|
||||
c.addStandard(short_m);
|
||||
addStandard(short_m);
|
||||
if(SOLT.separate_male_female) {
|
||||
auto short_f = new CalStandard::Short("Default female standard", SOLT.short_f.Z0, SOLT.short_f.delay, SOLT.short_f.loss, SOLT.short_f.L0, SOLT.short_f.L1, SOLT.short_f.L2, SOLT.short_f.L3);
|
||||
if(SOLT.short_f.useMeasurements) {
|
||||
|
|
@ -311,7 +394,7 @@ Calkit Calkit::fromFile(QString filename)
|
|||
ts.fromFile(SOLT.short_f.file.toStdString());
|
||||
short_m->setMeasurement(ts, SOLT.short_f.Sparam);
|
||||
}
|
||||
c.addStandard(short_f);
|
||||
addStandard(short_f);
|
||||
}
|
||||
|
||||
auto load_m = new CalStandard::Load(SOLT.separate_male_female ? "Default male standard" : "Default standard", SOLT.load_m.Z0, SOLT.load_m.delay, 0.0, SOLT.load_m.resistance, SOLT.load_m.Cparallel, SOLT.load_m.Lseries, SOLT.loadModelCFirst);
|
||||
|
|
@ -320,7 +403,7 @@ Calkit Calkit::fromFile(QString filename)
|
|||
ts.fromFile(SOLT.load_m.file.toStdString());
|
||||
load_m->setMeasurement(ts, SOLT.load_m.Sparam);
|
||||
}
|
||||
c.addStandard(load_m);
|
||||
addStandard(load_m);
|
||||
if(SOLT.separate_male_female) {
|
||||
auto load_f = new CalStandard::Load("Default female standard", SOLT.load_m.Z0, SOLT.load_f.delay, 0.0, SOLT.load_f.resistance, SOLT.load_f.Cparallel, SOLT.load_f.Lseries, SOLT.loadModelCFirst);
|
||||
if(SOLT.load_f.useMeasurements) {
|
||||
|
|
@ -328,7 +411,7 @@ Calkit Calkit::fromFile(QString filename)
|
|||
ts.fromFile(SOLT.load_f.file.toStdString());
|
||||
load_m->setMeasurement(ts, SOLT.load_f.Sparam);
|
||||
}
|
||||
c.addStandard(load_f);
|
||||
addStandard(load_f);
|
||||
}
|
||||
|
||||
auto through = new CalStandard::Through("Default standard", SOLT.Through.Z0, SOLT.Through.delay, SOLT.Through.loss);
|
||||
|
|
@ -337,7 +420,7 @@ Calkit Calkit::fromFile(QString filename)
|
|||
ts.fromFile(SOLT.Through.file.toStdString());
|
||||
through->setMeasurement(ts, SOLT.Through.Sparam1, SOLT.Through.Sparam2);
|
||||
}
|
||||
c.addStandard(through);
|
||||
addStandard(through);
|
||||
|
||||
InformationBox::ShowMessage("Loading calkit file", "The file \"" + filename + "\" is stored in a deprecated"
|
||||
" calibration kit format. Future versions of this application might not support"
|
||||
|
|
@ -345,8 +428,10 @@ Calkit Calkit::fromFile(QString filename)
|
|||
}
|
||||
|
||||
file.close();
|
||||
this->filename = filename;
|
||||
updateSCPINames();
|
||||
|
||||
return c;
|
||||
return true;
|
||||
}
|
||||
|
||||
void Calkit::edit(std::function<void (void)> updateCal)
|
||||
|
|
@ -364,10 +449,24 @@ void Calkit::edit(std::function<void (void)> updateCal)
|
|||
|
||||
void Calkit::clearStandards()
|
||||
{
|
||||
for(auto s : standards) {
|
||||
delete s;
|
||||
while(standards.size() > 0) {
|
||||
removeStandard(standards[0]);
|
||||
}
|
||||
}
|
||||
|
||||
void Calkit::updateSCPINames()
|
||||
{
|
||||
// Need to remove all standards from the subnode list first, otherwise
|
||||
// name changes wouldn't work due to temporarily name collisions
|
||||
for(auto &s : standards) {
|
||||
scpi_std.remove(s);
|
||||
}
|
||||
unsigned int i=1;
|
||||
for(auto &s : standards) {
|
||||
s->changeName(QString::number(i));
|
||||
scpi_std.add(s);
|
||||
i++;
|
||||
}
|
||||
standards.clear();
|
||||
}
|
||||
|
||||
std::vector<CalStandard::Virtual *> Calkit::getStandards() const
|
||||
|
|
@ -391,6 +490,14 @@ void Calkit::addStandard(CalStandard::Virtual *s)
|
|||
}
|
||||
}
|
||||
standards.push_back(s);
|
||||
updateSCPINames();
|
||||
}
|
||||
|
||||
void Calkit::removeStandard(CalStandard::Virtual *s)
|
||||
{
|
||||
standards.erase(std::remove(standards.begin(), standards.end(), s), standards.end());
|
||||
delete s;
|
||||
updateSCPINames();
|
||||
}
|
||||
|
||||
nlohmann::json Calkit::toJSON()
|
||||
|
|
@ -411,6 +518,7 @@ nlohmann::json Calkit::toJSON()
|
|||
void Calkit::fromJSON(nlohmann::json j)
|
||||
{
|
||||
clearStandards();
|
||||
filename = "";
|
||||
Savable::parseJSON(j, descr);
|
||||
for(auto js : j["standards"]) {
|
||||
if(!js.contains("type") || !js.contains("params")) {
|
||||
|
|
@ -426,6 +534,7 @@ void Calkit::fromJSON(nlohmann::json j)
|
|||
s->fromJSON(js["params"]);
|
||||
addStandard(s);
|
||||
}
|
||||
updateSCPINames();
|
||||
}
|
||||
|
||||
void Calkit::setIdealDefault()
|
||||
|
|
@ -437,4 +546,5 @@ void Calkit::setIdealDefault()
|
|||
addStandard(new CalStandard::Short("Ideal Short Standard", 50.0, 0, 0, 0, 0, 0, 0));
|
||||
addStandard(new CalStandard::Load("Ideal Load Standard", 50.0, 0, 0, 50.0, 0, 0));
|
||||
addStandard(new CalStandard::Through("Ideal Through Standard", 50.0, 0, 0));
|
||||
updateSCPINames();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,15 +19,8 @@ class Calkit : public Savable, public SCPINode
|
|||
friend class LibreCALDialog;
|
||||
public:
|
||||
Calkit();
|
||||
Calkit(const Calkit&) = default;
|
||||
Calkit& operator=(const Calkit& other)
|
||||
{
|
||||
this->manufacturer = other.manufacturer;
|
||||
this->serialnumber = other.serialnumber;
|
||||
this->description = other.description;
|
||||
this->standards = other.standards;
|
||||
return *this;
|
||||
}
|
||||
Calkit(const Calkit&) = delete;
|
||||
Calkit& operator= (const Calkit&) = delete;
|
||||
|
||||
class SOLT {
|
||||
public:
|
||||
|
|
@ -44,11 +37,12 @@ public:
|
|||
};
|
||||
|
||||
void toFile(QString filename);
|
||||
static Calkit fromFile(QString filename);
|
||||
bool fromFile(QString filename);
|
||||
void edit(std::function<void(void)> updateCal = nullptr);
|
||||
|
||||
std::vector<CalStandard::Virtual *> getStandards() const;
|
||||
void addStandard(CalStandard::Virtual* s);
|
||||
void removeStandard(CalStandard::Virtual* s);
|
||||
|
||||
virtual nlohmann::json toJSON() override;
|
||||
virtual void fromJSON(nlohmann::json j) override;
|
||||
|
|
@ -57,7 +51,10 @@ public:
|
|||
|
||||
private:
|
||||
void clearStandards();
|
||||
void updateSCPINames();
|
||||
QString manufacturer, serialnumber, description;
|
||||
QString filename;
|
||||
SCPINode scpi_std;
|
||||
std::vector<CalStandard::Virtual*> standards;
|
||||
|
||||
const std::vector<Savable::SettingDescription> descr = {{
|
||||
|
|
|
|||
|
|
@ -27,8 +27,7 @@ CalkitDialog::CalkitDialog(Calkit &c, QWidget *parent) :
|
|||
connect(ui->bDelete, &QPushButton::clicked, [=](){
|
||||
auto row = ui->list->currentRow();
|
||||
if(row >= 0) {
|
||||
delete kit.standards[row];
|
||||
kit.standards.erase(kit.standards.begin() + row);
|
||||
kit.removeStandard(kit.standards[row]);
|
||||
updateStandardList();
|
||||
}
|
||||
});
|
||||
|
|
@ -39,6 +38,7 @@ CalkitDialog::CalkitDialog(Calkit &c, QWidget *parent) :
|
|||
swap(kit.standards[row], kit.standards[row-1]);
|
||||
ui->list->setCurrentRow(row-1);
|
||||
updateStandardList();
|
||||
kit.updateSCPINames();
|
||||
}
|
||||
});
|
||||
|
||||
|
|
@ -48,6 +48,7 @@ CalkitDialog::CalkitDialog(Calkit &c, QWidget *parent) :
|
|||
swap(kit.standards[row], kit.standards[row+1]);
|
||||
ui->list->setCurrentRow(row+1);
|
||||
updateStandardList();
|
||||
kit.updateSCPINames();
|
||||
}
|
||||
});
|
||||
|
||||
|
|
@ -93,7 +94,7 @@ CalkitDialog::CalkitDialog(Calkit &c, QWidget *parent) :
|
|||
if(filename.length() > 0) {
|
||||
Preferences::getInstance().UISettings.Paths.calkit = QFileInfo(filename).path();
|
||||
try {
|
||||
kit = Calkit::fromFile(filename);
|
||||
kit.fromFile(filename);
|
||||
} catch (runtime_error &e) {
|
||||
InformationBox::ShowError("Error", "The calibration kit file could not be parsed (" + QString(e.what()) + ")");
|
||||
qWarning() << "Parsing of calibration kit failed while opening calibration file: " << e.what();
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ using namespace std;
|
|||
using namespace CalStandard;
|
||||
|
||||
Virtual::Virtual(QString name) :
|
||||
SCPINode(name),
|
||||
name(name),
|
||||
minFreq(std::numeric_limits<double>::lowest()),
|
||||
maxFreq(std::numeric_limits<double>::max())
|
||||
|
|
@ -60,7 +61,7 @@ QString Virtual::TypeToString(Virtual::Type type)
|
|||
Virtual::Type Virtual::TypeFromString(QString s)
|
||||
{
|
||||
for(int i=0;i<(int) Type::Last;i++) {
|
||||
if(TypeToString((Type) i) == s) {
|
||||
if(TypeToString((Type) i).compare(s, Qt::CaseInsensitive) == 0) {
|
||||
return (Type) i;
|
||||
}
|
||||
}
|
||||
|
|
@ -101,6 +102,11 @@ void Virtual::setName(const QString &value)
|
|||
name = value;
|
||||
}
|
||||
|
||||
void Virtual::setupSCPI()
|
||||
{
|
||||
addStringParameter("NAME", name);
|
||||
}
|
||||
|
||||
void OnePort::setMeasurement(const Touchstone &ts, int port)
|
||||
{
|
||||
if(!touchstone) {
|
||||
|
|
@ -142,10 +148,35 @@ void OnePort::fromJSON(nlohmann::json j)
|
|||
}
|
||||
}
|
||||
|
||||
void OnePort::setupSCPI()
|
||||
{
|
||||
add(new SCPICommand("FILE", [=](QStringList params) -> QString {
|
||||
if(params.size() < 1) {
|
||||
return SCPI::getResultName(SCPI::Result::Error);
|
||||
}
|
||||
try {
|
||||
auto ts = Touchstone::fromFile(params[0].toStdString());
|
||||
unsigned long long index = 0;
|
||||
if(params.size() == 2) {
|
||||
if(!SCPI::paramToULongLong(params, 1, index)) {
|
||||
return SCPI::getResultName(SCPI::Result::Error);
|
||||
}
|
||||
}
|
||||
setMeasurement(ts, index-1);
|
||||
return SCPI::getResultName(SCPI::Result::Empty);
|
||||
} catch(const std::exception& e) {
|
||||
// failed to load file
|
||||
return SCPI::getResultName(SCPI::Result::Error);
|
||||
}
|
||||
}, nullptr, false));
|
||||
Virtual::setupSCPI();
|
||||
}
|
||||
|
||||
Open::Open()
|
||||
{
|
||||
Z0 = 50.0;
|
||||
delay = loss = C0 = C1 = C2 = C3 = 0.0;
|
||||
setupSCPI();
|
||||
}
|
||||
|
||||
std::complex<double> Open::toS11(double freq)
|
||||
|
|
@ -263,10 +294,23 @@ void Open::fromJSON(nlohmann::json j)
|
|||
C3 = j.value("C3", 0.0);
|
||||
}
|
||||
|
||||
void Open::setupSCPI()
|
||||
{
|
||||
addDoubleParameter("Z0", Z0, true, true, [=](){clearMeasurement();});
|
||||
addDoubleParameter("DELAY", delay, true, true, [=](){clearMeasurement();});
|
||||
addDoubleParameter("LOSS", loss, true, true, [=](){clearMeasurement();});
|
||||
addDoubleParameter("C0", C0, true, true, [=](){clearMeasurement();});
|
||||
addDoubleParameter("C1", C1, true, true, [=](){clearMeasurement();});
|
||||
addDoubleParameter("C2", C2, true, true, [=](){clearMeasurement();});
|
||||
addDoubleParameter("C3", C3, true, true, [=](){clearMeasurement();});
|
||||
OnePort::setupSCPI();
|
||||
}
|
||||
|
||||
Short::Short()
|
||||
{
|
||||
Z0 = 50.0;
|
||||
delay = loss = L0 = L1 = L2 = L3 = 0.0;
|
||||
setupSCPI();
|
||||
}
|
||||
|
||||
std::complex<double> Short::toS11(double freq)
|
||||
|
|
@ -378,12 +422,25 @@ void Short::fromJSON(nlohmann::json j)
|
|||
L3 = j.value("L3", 0.0);
|
||||
}
|
||||
|
||||
void Short::setupSCPI()
|
||||
{
|
||||
addDoubleParameter("Z0", Z0, true, true, [=](){clearMeasurement();});
|
||||
addDoubleParameter("DELAY", delay, true, true, [=](){clearMeasurement();});
|
||||
addDoubleParameter("LOSS", loss, true, true, [=](){clearMeasurement();});
|
||||
addDoubleParameter("L0", L0, true, true, [=](){clearMeasurement();});
|
||||
addDoubleParameter("L1", L1, true, true, [=](){clearMeasurement();});
|
||||
addDoubleParameter("L2", L2, true, true, [=](){clearMeasurement();});
|
||||
addDoubleParameter("L3", L3, true, true, [=](){clearMeasurement();});
|
||||
OnePort::setupSCPI();
|
||||
}
|
||||
|
||||
Load::Load()
|
||||
{
|
||||
Z0 = 50.0;
|
||||
resistance = 50.0;
|
||||
delay = Cparallel = Lseries = 0;
|
||||
Cfirst = true;
|
||||
setupSCPI();
|
||||
}
|
||||
|
||||
std::complex<double> Load::toS11(double freq)
|
||||
|
|
@ -519,6 +576,18 @@ void Load::fromJSON(nlohmann::json j)
|
|||
Cfirst = j.value("Cfirst", true);
|
||||
}
|
||||
|
||||
void Load::setupSCPI()
|
||||
{
|
||||
addDoubleParameter("Z0", Z0, true, true, [=](){clearMeasurement();});
|
||||
addDoubleParameter("DELAY", delay, true, true, [=](){clearMeasurement();});
|
||||
addDoubleParameter("LOSS", loss, true, true, [=](){clearMeasurement();});
|
||||
addDoubleParameter("RESistance", resistance, true, true, [=](){clearMeasurement();});
|
||||
addDoubleParameter("CPARallel", Cparallel, true, true, [=](){clearMeasurement();});
|
||||
addDoubleParameter("LSERies", Lseries, true, true, [=](){clearMeasurement();});
|
||||
addBoolParameter("CFIRST", Cfirst, true, true, [=](){clearMeasurement();});
|
||||
OnePort::setupSCPI();
|
||||
}
|
||||
|
||||
void TwoPort::setMeasurement(const Touchstone &ts, int port1, int port2)
|
||||
{
|
||||
if(!touchstone) {
|
||||
|
|
@ -560,11 +629,37 @@ void TwoPort::fromJSON(nlohmann::json j)
|
|||
}
|
||||
}
|
||||
|
||||
void TwoPort::setupSCPI()
|
||||
{
|
||||
add(new SCPICommand("FILE", [=](QStringList params) -> QString {
|
||||
if(params.size() != 3) {
|
||||
return SCPI::getResultName(SCPI::Result::Error);
|
||||
}
|
||||
try {
|
||||
auto ts = Touchstone::fromFile(params[0].toStdString());
|
||||
unsigned long long index1, index2 = 0;
|
||||
if(!SCPI::paramToULongLong(params, 1, index1)) {
|
||||
return SCPI::getResultName(SCPI::Result::Error);
|
||||
}
|
||||
if(!SCPI::paramToULongLong(params, 2, index1)) {
|
||||
return SCPI::getResultName(SCPI::Result::Error);
|
||||
}
|
||||
setMeasurement(ts, index1-1, index2-1);
|
||||
return SCPI::getResultName(SCPI::Result::Empty);
|
||||
} catch(const std::exception& e) {
|
||||
// failed to load file
|
||||
return SCPI::getResultName(SCPI::Result::Error);
|
||||
}
|
||||
}, nullptr, false));
|
||||
Virtual::setupSCPI();
|
||||
}
|
||||
|
||||
Through::Through()
|
||||
{
|
||||
Z0 = 50.0;
|
||||
delay = 0.0;
|
||||
loss = 0.0;
|
||||
setupSCPI();
|
||||
}
|
||||
|
||||
Sparam Through::toSparam(double freq)
|
||||
|
|
@ -675,9 +770,18 @@ void Through::fromJSON(nlohmann::json j)
|
|||
loss = j.value("loss", 0.0);
|
||||
}
|
||||
|
||||
void Through::setupSCPI()
|
||||
{
|
||||
addDoubleParameter("Z0", Z0, true, true, [=](){clearMeasurement();});
|
||||
addDoubleParameter("DELAY", delay, true, true, [=](){clearMeasurement();});
|
||||
addDoubleParameter("LOSS", loss, true, true, [=](){clearMeasurement();});
|
||||
TwoPort::setupSCPI();
|
||||
}
|
||||
|
||||
Reflect::Reflect()
|
||||
{
|
||||
isShort = true;
|
||||
setupSCPI();
|
||||
}
|
||||
|
||||
std::complex<double> Reflect::toS11(double freq)
|
||||
|
|
@ -724,10 +828,17 @@ bool Reflect::getIsShort() const
|
|||
return isShort;
|
||||
}
|
||||
|
||||
void Reflect::setupSCPI()
|
||||
{
|
||||
addBoolParameter("SHORT", isShort, true, true, [=](){clearMeasurement();});
|
||||
OnePort::setupSCPI();
|
||||
}
|
||||
|
||||
Line::Line()
|
||||
{
|
||||
Z0 = 50.0;
|
||||
setDelay(0.0);
|
||||
setupSCPI();
|
||||
}
|
||||
|
||||
Sparam Line::toSparam(double freq)
|
||||
|
|
@ -800,3 +911,10 @@ void Line::setDelay(double delay)
|
|||
minFreq = 1.0 / delay * 20 / 360;
|
||||
maxFreq = 1.0 / delay * 160 / 360;
|
||||
}
|
||||
|
||||
void Line::setupSCPI()
|
||||
{
|
||||
addDoubleParameter("Z0", Z0, true, true, [=](){clearMeasurement();});
|
||||
addDoubleParameter("DELAY", delay, true, true, [=](){clearMeasurement();});
|
||||
TwoPort::setupSCPI();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
#include "savable.h"
|
||||
#include "touchstone.h"
|
||||
#include "Tools/parameters.h"
|
||||
#include "scpi.h"
|
||||
|
||||
#include <complex>
|
||||
#include <functional>
|
||||
|
|
@ -11,7 +12,7 @@
|
|||
namespace CalStandard
|
||||
{
|
||||
|
||||
class Virtual : public QObject, public Savable
|
||||
class Virtual : public QObject, public Savable, public SCPINode
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
|
|
@ -53,6 +54,7 @@ signals:
|
|||
void deleted();
|
||||
|
||||
protected:
|
||||
void setupSCPI();
|
||||
QString name;
|
||||
double minFreq;
|
||||
double maxFreq;
|
||||
|
|
@ -75,6 +77,7 @@ public:
|
|||
virtual void fromJSON(nlohmann::json j) override;
|
||||
|
||||
protected:
|
||||
void setupSCPI();
|
||||
Touchstone *touchstone;
|
||||
};
|
||||
|
||||
|
|
@ -85,7 +88,7 @@ class Open : public OnePort
|
|||
public:
|
||||
Open();
|
||||
Open(QString name, double Z0, double delay, double loss, double C0, double C1, double C2, double C3)
|
||||
: OnePort(name), Z0(Z0), delay(delay), loss(loss), C0(C0), C1(C1), C2(C2), C3(C3){}
|
||||
: OnePort(name), Z0(Z0), delay(delay), loss(loss), C0(C0), C1(C1), C2(C2), C3(C3){setupSCPI();}
|
||||
|
||||
virtual std::complex<double> toS11(double freq) override;
|
||||
virtual void edit(std::function<void(void)> finishedCallback = nullptr) override;
|
||||
|
|
@ -93,6 +96,7 @@ public:
|
|||
virtual nlohmann::json toJSON() override;
|
||||
virtual void fromJSON(nlohmann::json j) override;
|
||||
private:
|
||||
void setupSCPI();
|
||||
double Z0, delay, loss, C0, C1, C2, C3;
|
||||
};
|
||||
|
||||
|
|
@ -101,7 +105,7 @@ class Short : public OnePort
|
|||
public:
|
||||
Short();
|
||||
Short(QString name, double Z0, double delay, double loss, double L0, double L1, double L2, double L3)
|
||||
: OnePort(name), Z0(Z0), delay(delay), loss(loss), L0(L0), L1(L1), L2(L2), L3(L3){}
|
||||
: OnePort(name), Z0(Z0), delay(delay), loss(loss), L0(L0), L1(L1), L2(L2), L3(L3){setupSCPI();}
|
||||
|
||||
virtual std::complex<double> toS11(double freq) override;
|
||||
virtual void edit(std::function<void(void)> finishedCallback = nullptr) override;
|
||||
|
|
@ -109,6 +113,7 @@ public:
|
|||
virtual nlohmann::json toJSON() override;
|
||||
virtual void fromJSON(nlohmann::json j) override;
|
||||
private:
|
||||
void setupSCPI();
|
||||
double Z0, delay, loss, L0, L1, L2, L3;
|
||||
};
|
||||
|
||||
|
|
@ -117,7 +122,7 @@ class Load : public OnePort
|
|||
public:
|
||||
Load();
|
||||
Load(QString name, double Z0, double delay, double loss, double resistance, double Cparallel, double Lseries, bool Cfirst = true)
|
||||
: OnePort(name), Z0(Z0), delay(delay), loss(loss), resistance(resistance), Cparallel(Cparallel), Lseries(Lseries), Cfirst(Cfirst){}
|
||||
: OnePort(name), Z0(Z0), delay(delay), loss(loss), resistance(resistance), Cparallel(Cparallel), Lseries(Lseries), Cfirst(Cfirst){setupSCPI();}
|
||||
|
||||
virtual std::complex<double> toS11(double freq) override;
|
||||
virtual void edit(std::function<void(void)> finishedCallback = nullptr) override;
|
||||
|
|
@ -125,6 +130,7 @@ public:
|
|||
virtual nlohmann::json toJSON() override;
|
||||
virtual void fromJSON(nlohmann::json j) override;
|
||||
private:
|
||||
void setupSCPI();
|
||||
double Z0, delay, loss, resistance, Cparallel, Lseries;
|
||||
bool Cfirst;
|
||||
};
|
||||
|
|
@ -144,6 +150,7 @@ public:
|
|||
bool getIsShort() const;
|
||||
|
||||
private:
|
||||
void setupSCPI();
|
||||
bool isShort;
|
||||
};
|
||||
|
||||
|
|
@ -164,6 +171,7 @@ public:
|
|||
virtual void fromJSON(nlohmann::json j) override;
|
||||
|
||||
protected:
|
||||
void setupSCPI();
|
||||
Touchstone *touchstone;
|
||||
};
|
||||
|
||||
|
|
@ -172,7 +180,7 @@ class Through : public TwoPort
|
|||
public:
|
||||
Through();
|
||||
Through(QString name, double Z0, double delay, double loss)
|
||||
: TwoPort(name), Z0(Z0), delay(delay), loss(loss){}
|
||||
: TwoPort(name), Z0(Z0), delay(delay), loss(loss){setupSCPI();}
|
||||
|
||||
virtual Sparam toSparam(double freq) override;
|
||||
virtual void edit(std::function<void(void)> finishedCallback = nullptr) override;
|
||||
|
|
@ -180,6 +188,7 @@ public:
|
|||
virtual nlohmann::json toJSON() override;
|
||||
virtual void fromJSON(nlohmann::json j) override;
|
||||
private:
|
||||
void setupSCPI();
|
||||
double Z0, delay, loss;
|
||||
};
|
||||
|
||||
|
|
@ -188,7 +197,7 @@ class Line : public TwoPort
|
|||
public:
|
||||
Line();
|
||||
Line(QString name, double Z0, double delay)
|
||||
: TwoPort(name), Z0(Z0), delay(delay){}
|
||||
: TwoPort(name), Z0(Z0), delay(delay){setupSCPI();}
|
||||
|
||||
virtual Sparam toSparam(double freq) override;
|
||||
virtual void edit(std::function<void(void)> finishedCallback = nullptr) override;
|
||||
|
|
@ -197,6 +206,7 @@ public:
|
|||
virtual void fromJSON(nlohmann::json j) override;
|
||||
private:
|
||||
void setDelay(double delay);
|
||||
void setupSCPI();
|
||||
double Z0, delay;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -64,6 +64,9 @@ SpectrumAnalyzer::SpectrumAnalyzer(AppWindow *window, QString name)
|
|||
normalize.measure = nullptr;
|
||||
normalize.enable = nullptr;
|
||||
|
||||
lastFreq = 0.0;
|
||||
lastTime = 0.0;
|
||||
|
||||
configurationTimer.setSingleShot(true);
|
||||
connect(&configurationTimer, &QTimer::timeout, this, [=](){
|
||||
ConfigureDevice();
|
||||
|
|
@ -396,6 +399,7 @@ nlohmann::json SpectrumAnalyzer::toJSON()
|
|||
freq["stop"] = settings.freqStop;
|
||||
sweep["frequency"] = freq;
|
||||
sweep["single"] = singleSweep;
|
||||
sweep["averages"] = averages;
|
||||
nlohmann::json acq;
|
||||
acq["RBW"] = settings.RBW;
|
||||
acq["window"] = WindowToString((DeviceDriver::SASettings::Window) settings.window).toStdString();
|
||||
|
|
@ -502,6 +506,7 @@ void SpectrumAnalyzer::fromJSON(nlohmann::json j)
|
|||
EnableNormalization(correctSize);
|
||||
}
|
||||
SetSingleSweep(sweep.value("single", singleSweep));
|
||||
SetAveraging(sweep.value("averages", averages));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -584,6 +589,9 @@ void SpectrumAnalyzer::NewDatapoint(DeviceDriver::SAMeasurement m)
|
|||
qWarning() << "Got point" << m_avg.pointNum << "but last received point was" << lastPoint << "("<<(m_avg.pointNum-lastPoint-1)<<"missed points)";
|
||||
}
|
||||
lastPoint = m_avg.pointNum;
|
||||
|
||||
lastFreq = m_avg.frequency;
|
||||
lastTime = (double) m_avg.us / 1000000;
|
||||
}
|
||||
|
||||
void SpectrumAnalyzer::SettingsChanged()
|
||||
|
|
@ -1102,6 +1110,12 @@ void SpectrumAnalyzer::SetupSCPI()
|
|||
}, [=](QStringList) -> QString {
|
||||
return singleSweep ? SCPI::getResultName(SCPI::Result::True): SCPI::getResultName(SCPI::Result::False);
|
||||
}));
|
||||
scpi_acq->add(new SCPICommand("FREQuency", nullptr, [=](QStringList) -> QString {
|
||||
return QString::number(lastFreq);
|
||||
}));
|
||||
scpi_acq->add(new SCPICommand("TIME", nullptr, [=](QStringList) -> QString {
|
||||
return QString::number(lastTime);
|
||||
}));
|
||||
auto scpi_tg = new SCPINode("TRACKing");
|
||||
SCPINode::add(scpi_tg);
|
||||
scpi_tg->add(new SCPICommand("ENable", [=](QStringList params) -> QString {
|
||||
|
|
|
|||
|
|
@ -132,6 +132,10 @@ private:
|
|||
QList<QAction*> importActions;
|
||||
QList<QAction*> exportActions;
|
||||
|
||||
// meta data from the last received datapoint
|
||||
double lastFreq;
|
||||
double lastTime;
|
||||
|
||||
signals:
|
||||
void dataChanged();
|
||||
void startFreqChanged(double freq);
|
||||
|
|
|
|||
|
|
@ -127,6 +127,31 @@ Deembedding::Deembedding(TraceModel &tm)
|
|||
addOption(option);
|
||||
return SCPI::getResultName(SCPI::Result::Empty);
|
||||
}, nullptr));
|
||||
add(new SCPICommand("DELete", [=](QStringList params) -> QString {
|
||||
unsigned long long index;
|
||||
if(!SCPI::paramToULongLong(params, 0, index)) {
|
||||
return SCPI::getResultName(SCPI::Result::Error);
|
||||
}
|
||||
if(index < 1 || index > options.size()) {
|
||||
return SCPI::getResultName(SCPI::Result::Error);
|
||||
}
|
||||
removeOption(index-1);
|
||||
return SCPI::getResultName(SCPI::Result::Empty);
|
||||
}, nullptr));
|
||||
add(new SCPICommand("SWAP", [=](QStringList params) -> QString {
|
||||
unsigned long long index1, index2;
|
||||
if(!SCPI::paramToULongLong(params, 0, index1)) {
|
||||
return SCPI::getResultName(SCPI::Result::Error);
|
||||
}
|
||||
if(!SCPI::paramToULongLong(params, 1, index2)) {
|
||||
return SCPI::getResultName(SCPI::Result::Error);
|
||||
}
|
||||
if(index1 < 1 || index1 > options.size() || index2 < 1 || index2 > options.size()) {
|
||||
return SCPI::getResultName(SCPI::Result::Error);
|
||||
}
|
||||
swapOptions(index1-1, index2-1);
|
||||
return SCPI::getResultName(SCPI::Result::Empty);
|
||||
}, nullptr));
|
||||
add(new SCPICommand("CLEAR", [=](QStringList params) -> QString {
|
||||
Q_UNUSED(params);
|
||||
clear();
|
||||
|
|
@ -209,12 +234,12 @@ void Deembedding::addOption(DeembeddingOption *option)
|
|||
emit optionAdded();
|
||||
}
|
||||
|
||||
void Deembedding::swapOptions(unsigned int index)
|
||||
void Deembedding::swapOptions(unsigned int index1, unsigned int index2)
|
||||
{
|
||||
if(index + 1 >= options.size()) {
|
||||
if(index1 > options.size() || index2 > options.size() || index1 == index2) {
|
||||
return;
|
||||
}
|
||||
std::swap(options[index], options[index+1]);
|
||||
std::swap(options[index1], options[index2]);
|
||||
updateSCPINames();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ public:
|
|||
|
||||
void removeOption(unsigned int index);
|
||||
void addOption(DeembeddingOption* option);
|
||||
void swapOptions(unsigned int index);
|
||||
void swapOptions(unsigned int index1, unsigned int index2);
|
||||
void clear();
|
||||
|
||||
bool isMeasuring();
|
||||
|
|
|
|||
|
|
@ -44,12 +44,12 @@ DeembeddingDialog::DeembeddingDialog(Deembedding *d, QWidget *parent) :
|
|||
});
|
||||
connect(ui->bMoveUp, &QPushButton::clicked, [=](){
|
||||
auto index = ui->view->currentIndex();
|
||||
d->swapOptions(index.row() - 1);
|
||||
d->swapOptions(index.row() - 1, index.row());
|
||||
ui->view->setCurrentIndex(index.sibling(index.row() - 1, 0));
|
||||
});
|
||||
connect(ui->bMoveDown, &QPushButton::clicked, [=](){
|
||||
auto index = ui->view->currentIndex();
|
||||
d->swapOptions(index.row());
|
||||
d->swapOptions(index.row(), index.row() + 1);
|
||||
ui->view->setCurrentIndex(index.sibling(index.row() + 1, 0));
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -56,6 +56,17 @@ MatchingNetwork::MatchingNetwork()
|
|||
addComponent(index, c);
|
||||
return SCPI::getResultName(SCPI::Result::Empty);
|
||||
}, nullptr));
|
||||
add(new SCPICommand("DELete", [=](QStringList params) -> QString {
|
||||
unsigned long long index;
|
||||
if(!SCPI::paramToULongLong(params, 0, index)) {
|
||||
return SCPI::getResultName(SCPI::Result::Error);
|
||||
}
|
||||
if(index < 1 || index > network.size()) {
|
||||
return SCPI::getResultName(SCPI::Result::Error);
|
||||
}
|
||||
removeComponent(index-1);
|
||||
return SCPI::getResultName(SCPI::Result::Empty);
|
||||
}, nullptr));
|
||||
add(new SCPICommand("TYPE", nullptr, [=](QStringList params) -> QString {
|
||||
unsigned long long index = 0;
|
||||
if(!SCPI::paramToULongLong(params, 0, index)) {
|
||||
|
|
@ -267,6 +278,7 @@ void MatchingNetwork::fromJSON(nlohmann::json j)
|
|||
}
|
||||
addNetwork = j.value("addNetwork", true);
|
||||
matching.clear();
|
||||
updateSCPINames();
|
||||
}
|
||||
|
||||
void MatchingNetwork::clearNetwork()
|
||||
|
|
@ -643,7 +655,7 @@ MatchingComponent::MatchingComponent(Type type)
|
|||
// failed to load file
|
||||
return SCPI::getResultName(SCPI::Result::Error);
|
||||
}
|
||||
}, nullptr));
|
||||
}, nullptr, false));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
|
@ -787,6 +799,7 @@ void MatchingComponent::updateTouchstoneLabel()
|
|||
return;
|
||||
}
|
||||
QFont font = touchstoneLabel->font();
|
||||
touchstoneLabel->setStyleSheet("color: black");
|
||||
font.setPointSize(10);
|
||||
touchstoneLabel->setFont(font);
|
||||
if(touchstone->points() == 0) {
|
||||
|
|
|
|||
|
|
@ -69,6 +69,10 @@ VNA::VNA(AppWindow *window, QString name)
|
|||
calWaitFirst = false;
|
||||
calDialog = nullptr;
|
||||
|
||||
lastFreq = 0.0;
|
||||
lastPower = 0.0;
|
||||
lastTime = 0.0;
|
||||
|
||||
changingSettings = false;
|
||||
settings.sweepType = SweepType::Frequency;
|
||||
settings.zerospan = false;
|
||||
|
|
@ -880,6 +884,7 @@ nlohmann::json VNA::toJSON()
|
|||
sweep["power"] = power;
|
||||
sweep["points"] = settings.npoints;
|
||||
sweep["IFBW"] = settings.bandwidth;
|
||||
sweep["averages"] = averages;
|
||||
j["sweep"] = sweep;
|
||||
|
||||
j["traces"] = traceModel.toJSON();
|
||||
|
|
@ -917,6 +922,7 @@ void VNA::fromJSON(nlohmann::json j)
|
|||
// restore sweep settings, keep current value as default in case of missing entry
|
||||
SetPoints(sweep.value("points", settings.npoints));
|
||||
SetIFBandwidth(sweep.value("IFBW", settings.bandwidth));
|
||||
SetAveraging(sweep.value("averages", averages));
|
||||
if(sweep.contains("frequency")) {
|
||||
auto freq = sweep["frequency"];
|
||||
SetStartFreq(freq.value("start", settings.Freq.start));
|
||||
|
|
@ -1015,6 +1021,10 @@ void VNA::NewDatapoint(DeviceDriver::VNAMeasurement m)
|
|||
}
|
||||
}
|
||||
|
||||
lastFreq = m_avg.frequency;
|
||||
lastPower = m_avg.dBm;
|
||||
lastTime = (double) m_avg.us / 1000000;
|
||||
|
||||
window->addStreamingData(m_avg, AppWindow::VNADataType::Raw, settings.zerospan);
|
||||
|
||||
if(average.settled()) {
|
||||
|
|
@ -1246,6 +1256,7 @@ void VNA::SetLogSweep(bool log)
|
|||
{
|
||||
if(settings.Freq.logSweep != log) {
|
||||
settings.Freq.logSweep = log;
|
||||
ConstrainAndUpdateFrequencies();
|
||||
emit logSweepChanged(log);
|
||||
SettingsChanged();
|
||||
}
|
||||
|
|
@ -1592,6 +1603,15 @@ void VNA::SetupSCPI()
|
|||
}, [=](QStringList) -> QString {
|
||||
return singleSweep ? SCPI::getResultName(SCPI::Result::True) : SCPI::getResultName(SCPI::Result::False);
|
||||
}));
|
||||
scpi_acq->add(new SCPICommand("FREQuency", nullptr, [=](QStringList) -> QString {
|
||||
return QString::number(lastFreq);
|
||||
}));
|
||||
scpi_acq->add(new SCPICommand("POWer", nullptr, [=](QStringList) -> QString {
|
||||
return QString::number(lastPower);
|
||||
}));
|
||||
scpi_acq->add(new SCPICommand("TIME", nullptr, [=](QStringList) -> QString {
|
||||
return QString::number(lastTime);
|
||||
}));
|
||||
auto scpi_stim = new SCPINode("STIMulus");
|
||||
SCPINode::add(scpi_stim);
|
||||
scpi_stim->add(new SCPICommand("LVL", [=](QStringList params) -> QString {
|
||||
|
|
@ -1627,6 +1647,12 @@ void VNA::SetupSCPI()
|
|||
|
||||
void VNA::ConstrainAndUpdateFrequencies()
|
||||
{
|
||||
if(settings.sweepType == SweepType::Frequency && settings.Freq.logSweep) {
|
||||
if(settings.Freq.start <= 0) {
|
||||
// start frequency must be positive, force it to 1 Hz
|
||||
settings.Freq.start = 1.0;
|
||||
}
|
||||
}
|
||||
if(settings.Freq.stop > DeviceDriver::getInfo(window->getDevice()).Limits.VNA.maxFreq) {
|
||||
settings.Freq.stop = DeviceDriver::getInfo(window->getDevice()).Limits.VNA.maxFreq;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -201,6 +201,10 @@ private:
|
|||
// Statistics for detecting missing points and sweep time
|
||||
QDateTime lastStart;
|
||||
int lastPoint;
|
||||
// meta data from the last received datapoint
|
||||
double lastFreq;
|
||||
double lastPower;
|
||||
double lastTime;
|
||||
|
||||
signals:
|
||||
void deviceInitialized();
|
||||
|
|
|
|||
|
|
@ -297,7 +297,7 @@ bool SCPINode::addDoubleParameter(QString name, double ¶m, bool gettable, bo
|
|||
return SCPI::getResultName(SCPI::Result::Error);
|
||||
}
|
||||
} : (std::function<QString(QStringList)>) nullptr;
|
||||
auto query = gettable ? [=](QStringList params) -> QString {
|
||||
auto query = gettable ? [¶m](QStringList params) -> QString {
|
||||
Q_UNUSED(params)
|
||||
return QString::number(param);
|
||||
} : (std::function<QString(QStringList)>) nullptr;
|
||||
|
|
@ -344,6 +344,26 @@ bool SCPINode::addBoolParameter(QString name, bool ¶m, bool gettable, bool s
|
|||
return add(new SCPICommand(name, cmd, query));
|
||||
}
|
||||
|
||||
bool SCPINode::addStringParameter(QString name, QString ¶m, bool gettable, bool settable, std::function<void ()> setCallback)
|
||||
{
|
||||
auto cmd = settable ? [¶m, setCallback](QStringList params) -> QString {
|
||||
if(params.size() == 1) {
|
||||
param = params[0];
|
||||
if(setCallback) {
|
||||
setCallback();
|
||||
}
|
||||
return SCPI::getResultName(SCPI::Result::Empty);
|
||||
} else {
|
||||
return SCPI::getResultName(SCPI::Result::Error);
|
||||
}
|
||||
} : (std::function<QString(QStringList)>) nullptr;
|
||||
auto query = gettable ? [=](QStringList params) -> QString {
|
||||
Q_UNUSED(params)
|
||||
return param;
|
||||
} : (std::function<QString(QStringList)>) nullptr;
|
||||
return add(new SCPICommand(name, cmd, query));
|
||||
}
|
||||
|
||||
bool SCPINode::changeName(QString newname)
|
||||
{
|
||||
if(newname == name) {
|
||||
|
|
@ -548,16 +568,43 @@ QString SCPINode::parse(QString cmd, SCPINode* &lastNode)
|
|||
return SCPI::getResultName(SCPI::Result::Error);
|
||||
} else {
|
||||
// no more levels, search for command
|
||||
auto params = cmd.split(" ");
|
||||
auto cmd = params.front();
|
||||
QStringList params;
|
||||
params.append("");
|
||||
bool inQuotes = false;
|
||||
for(unsigned int i=0;i<cmd.length();i++) {
|
||||
if(cmd[i] == '\\') {
|
||||
// escape character, ignore
|
||||
continue;
|
||||
}
|
||||
// check if we are starting/stopping quotes
|
||||
if(cmd[i] == '"' || cmd[i] == '\'') {
|
||||
// check whether quotes are escaped
|
||||
if(i == 0 || cmd[i-1] != '\\') {
|
||||
inQuotes = !inQuotes;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if(inQuotes) {
|
||||
params.back().append(cmd[i]);
|
||||
} else {
|
||||
// not in quotes, handle splitting by space
|
||||
if(cmd[i] == ' ') {
|
||||
if(params.back().length() > 0)
|
||||
params.append("");
|
||||
} else {
|
||||
params.back().append(cmd[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
// remove command name
|
||||
params.pop_front();
|
||||
bool isQuery = false;
|
||||
if (cmd[cmd.size()-1]=='?') {
|
||||
if (cmdName[cmdName.size()-1]=='?') {
|
||||
isQuery = true;
|
||||
cmd.chop(1);
|
||||
cmdName.chop(1);
|
||||
}
|
||||
for(auto c : commands) {
|
||||
if(SCPI::match(c->leafName(), cmd.toUpper())) {
|
||||
if(SCPI::match(c->leafName(), cmdName.toUpper())) {
|
||||
// save current node in case of non-root for the next command
|
||||
lastNode = this;
|
||||
if(c->convertToUppercase()) {
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@ public:
|
|||
bool addDoubleParameter(QString name, double ¶m, bool gettable = true, bool settable = true, std::function<void(void)> setCallback = nullptr);
|
||||
bool addUnsignedIntParameter(QString name, unsigned int ¶m, bool gettable = true, bool settable = true, std::function<void(void)> setCallback = nullptr);
|
||||
bool addBoolParameter(QString name, bool ¶m, bool gettable = true, bool settable = true, std::function<void(void)> setCallback = nullptr);
|
||||
bool addStringParameter(QString name, QString ¶m, bool gettable = true, bool settable = true, std::function<void(void)> setCallback = nullptr);
|
||||
|
||||
bool changeName(QString newname);
|
||||
QString leafName() {return name.split(":").back();}
|
||||
|
|
|
|||
Loading…
Reference in a new issue