mirror of
https://github.com/jankae/LibreVNA.git
synced 2025-12-06 07:12:10 +01:00
Compare commits
No commits in common. "master" and "v1.6.4" have entirely different histories.
21
.github/workflows/Build.yml
vendored
21
.github/workflows/Build.yml
vendored
|
|
@ -17,7 +17,7 @@ jobs:
|
|||
- name: Install dependencies
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y libusb-1.0-0-dev qt6-tools-dev qt6-base-dev libqt6svg6-dev libgl-dev
|
||||
sudo apt-get install -y libusb-1.0-0-dev qt6-tools-dev qt6-base-dev
|
||||
qtchooser -install qt6 $(which qmake6)
|
||||
|
||||
- name: Get build timestamp
|
||||
|
|
@ -57,7 +57,7 @@ jobs:
|
|||
- name: Install dependencies
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y libusb-1.0-0-dev qt6-tools-dev qt6-base-dev libqt6svg6-dev
|
||||
sudo apt-get install -y libusb-1.0-0-dev qt6-tools-dev qt6-base-dev
|
||||
|
||||
- name: Get build timestamp
|
||||
id: id_date
|
||||
|
|
@ -88,22 +88,22 @@ jobs:
|
|||
path: Software/PC_Application/LibreVNA-GUI/LibreVNA-GUI
|
||||
|
||||
PC_Application_Windows:
|
||||
runs-on: windows-2022
|
||||
runs-on: windows-2019
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: msys2/setup-msys2@v2
|
||||
|
||||
- name: Install Qt
|
||||
uses: jurplel/install-qt-action@v4
|
||||
uses: jurplel/install-qt-action@v3
|
||||
with:
|
||||
version: '6.2.4'
|
||||
arch: 'win64_mingw'
|
||||
version: '6.2.0'
|
||||
arch: 'win64_mingw81'
|
||||
|
||||
- name: Download libusb
|
||||
run: |
|
||||
curl -o libusb.7z -L https://github.com/libusb/libusb/releases/download/v1.0.25/libusb-1.0.25.7z
|
||||
7z x libusb.7z -r -olibusb
|
||||
Xcopy /E /I /Y libusb\include %QT_ROOT_DIR%\include
|
||||
Xcopy /E /I /Y libusb\include ..\Qt\6.2.0\mingw81_64\include
|
||||
Xcopy /E /I /Y libusb\MinGW64\static\libusb-1.0.a Software\PC_Application\LibreVNA-GUI
|
||||
shell: cmd
|
||||
|
||||
|
|
@ -134,9 +134,10 @@ jobs:
|
|||
cd Software/PC_Application/LibreVNA-GUI/release
|
||||
del *.o *.cpp
|
||||
windeployqt.exe .
|
||||
copy %QT_ROOT_DIR%\bin\libwinpthread-1.dll .
|
||||
copy %QT_ROOT_DIR%\bin\libgcc_s_seh-1.dll .
|
||||
copy %QT_ROOT_DIR%\bin\Qt6OpenGL.dll .
|
||||
copy ..\..\..\..\..\Qt\6.2.0\mingw81_64\bin\libwinpthread-1.dll .
|
||||
copy ..\..\..\..\..\Qt\6.2.0\mingw81_64\bin\libgcc_s_seh-1.dll .
|
||||
copy "..\..\..\..\..\Qt\6.2.0\mingw81_64\bin\libstdc++-6.dll" .
|
||||
copy ..\..\..\..\..\Qt\6.2.0\mingw81_64\bin\Qt6OpenGL.dll .
|
||||
shell: cmd
|
||||
|
||||
- name: Upload
|
||||
|
|
|
|||
2
.github/workflows/HIL_Tests.yml
vendored
2
.github/workflows/HIL_Tests.yml
vendored
|
|
@ -19,7 +19,7 @@ jobs:
|
|||
- name: Install dependencies
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y libusb-1.0-0-dev qt6-tools-dev qt6-base-dev qt6-svg-dev
|
||||
sudo apt-get install -y libusb-1.0-0-dev qt6-tools-dev qt6-base-dev
|
||||
|
||||
- name: Build application
|
||||
run: |
|
||||
|
|
|
|||
21
.github/workflows/Release_tag_stable.yml
vendored
21
.github/workflows/Release_tag_stable.yml
vendored
|
|
@ -17,7 +17,7 @@ jobs:
|
|||
- name: Install dependencies
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y libusb-1.0-0-dev qt6-tools-dev qt6-base-dev libqt6svg6-dev libgl-dev zip
|
||||
sudo apt-get install -y libusb-1.0-0-dev qt6-tools-dev qt6-base-dev zip
|
||||
qtchooser -install qt6 $(which qmake6)
|
||||
|
||||
- name: Get app version
|
||||
|
|
@ -72,7 +72,7 @@ jobs:
|
|||
- name: Install dependencies
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y libusb-1.0-0-dev qt6-tools-dev qt6-base-dev qt6-svg-dev
|
||||
sudo apt-get install -y libusb-1.0-0-dev qt6-tools-dev qt6-base-dev
|
||||
|
||||
- name: Get app version
|
||||
id: id_version
|
||||
|
|
@ -104,22 +104,22 @@ jobs:
|
|||
|
||||
PC_Application_Windows:
|
||||
needs: PC_Application_Ubuntu
|
||||
runs-on: windows-2022
|
||||
runs-on: windows-2019
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: msys2/setup-msys2@v2
|
||||
|
||||
- name: Install Qt
|
||||
uses: jurplel/install-qt-action@v4
|
||||
uses: jurplel/install-qt-action@v3
|
||||
with:
|
||||
version: '6.2.4'
|
||||
arch: 'win64_mingw'
|
||||
version: '6.2.0'
|
||||
arch: 'win64_mingw81'
|
||||
|
||||
- name: Download libusb
|
||||
run: |
|
||||
curl -o libusb.7z -L https://github.com/libusb/libusb/releases/download/v1.0.25/libusb-1.0.25.7z
|
||||
7z x libusb.7z -r -olibusb
|
||||
Xcopy /E /I /Y libusb\include %QT_ROOT_DIR%\include
|
||||
Xcopy /E /I /Y libusb\include ..\Qt\6.2.0\mingw81_64\include
|
||||
Xcopy /E /I /Y libusb\MinGW64\static\libusb-1.0.a Software\PC_Application\LibreVNA-GUI
|
||||
shell: cmd
|
||||
|
||||
|
|
@ -145,9 +145,10 @@ jobs:
|
|||
cd Software/PC_Application/LibreVNA-GUI/release
|
||||
del *.o *.cpp
|
||||
windeployqt.exe .
|
||||
copy %QT_ROOT_DIR%\bin\libwinpthread-1.dll .
|
||||
copy %QT_ROOT_DIR%\bin\libgcc_s_seh-1.dll .
|
||||
copy %QT_ROOT_DIR%\bin\Qt6OpenGL.dll .
|
||||
copy ..\..\..\..\..\Qt\6.2.0\mingw81_64\bin\libwinpthread-1.dll .
|
||||
copy ..\..\..\..\..\Qt\6.2.0\mingw81_64\bin\libgcc_s_seh-1.dll .
|
||||
copy "..\..\..\..\..\Qt\6.2.0\mingw81_64\bin\libstdc++-6.dll" .
|
||||
copy ..\..\..\..\..\Qt\6.2.0\mingw81_64\bin\Qt6OpenGL.dll .
|
||||
shell: cmd
|
||||
|
||||
- name: Zip app
|
||||
|
|
|
|||
2
.github/workflows/Test.yml
vendored
2
.github/workflows/Test.yml
vendored
|
|
@ -17,7 +17,7 @@ jobs:
|
|||
- name: Install dependencies
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y libusb-1.0-0-dev qt6-tools-dev qt6-base-dev libqt6svg6-dev libgl-dev
|
||||
sudo apt-get install -y libusb-1.0-0-dev qt6-tools-dev qt6-base-dev
|
||||
qtchooser -install qt6 $(which qmake6)
|
||||
|
||||
- name: Build Tests
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -123,7 +123,6 @@
|
|||
\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}
|
||||
|
|
@ -463,21 +462,6 @@ 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}
|
||||
|
|
@ -617,9 +601,6 @@ 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}
|
||||
|
|
@ -628,10 +609,7 @@ 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}SLIDINGLOAD\\
|
||||
\hspace{1cm}REFLECT\\
|
||||
\hspace{1cm}LINE\\}
|
||||
\hspace{1cm}ISOLATION\\}
|
||||
|
||||
\subsubsection{VNA:CALibration:PORT}
|
||||
\event{Sets the port for the specified measurement}{VNA:CALibration:PORT}{<measurement number> <port number>}
|
||||
|
|
@ -659,23 +637,6 @@ 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:
|
||||
|
|
@ -687,343 +648,6 @@ 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.
|
||||
|
||||
|
|
@ -1136,16 +760,6 @@ 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}
|
||||
|
|
|
|||
Binary file not shown.
|
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 37 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 27 KiB |
Binary file not shown.
|
|
@ -1410,14 +1410,14 @@ When connected to a compound device and in VNA mode, there is no phase informati
|
|||
\end{important}
|
||||
|
||||
\subsection{Creating a compound device}
|
||||
Compound devices must be configured in the preferences:\linebreak\menu[,]{Window,Preferences,Device Drivers,LibreVNA/Compound}
|
||||
Compound devices must be configured in the preferences: \menu[,]{Window,Preferences,Compound Devices}
|
||||
\screenshot{1.0}{CompoundDeviceList.png}
|
||||
Create and remove compound devices with the buttons on the right. Edit an existing compound device by double-clicking it:
|
||||
\screenshot{1.0}{CompoundDeviceEdit.png}
|
||||
Required steps when creating a compound device:
|
||||
\begin{enumerate}
|
||||
\item Assign a name to the new compound device
|
||||
\item Select the synchronization method between devices. At the moment, only GUI synchronization is supported but future hardware versions might support faster synchronization via dedicated trigger ports
|
||||
\item Select the synchronization method between devices. At the moment, only USB synchronization is supported but future hardware versions might support faster synchronization via dedicated trigger ports
|
||||
\item Drag-and-drop a LibreVNA symbol into the configuration area for every physical device in the compound device
|
||||
\begin{itemize}
|
||||
\item At least two physical devices must be used
|
||||
|
|
|
|||
|
|
@ -13075,7 +13075,7 @@
|
|||
(hide yes)
|
||||
)
|
||||
)
|
||||
(property "MPN" "LM3370SD-3021"
|
||||
(property "MPN" "LM3370SD-4221"
|
||||
(at 101.6 190.5 0)
|
||||
(effects
|
||||
(font
|
||||
|
|
@ -13970,7 +13970,7 @@
|
|||
(hide yes)
|
||||
)
|
||||
)
|
||||
(property "MPN" "LM3370SD-3021"
|
||||
(property "MPN" "LM3370SD-4221"
|
||||
(at 101.6 231.14 0)
|
||||
(effects
|
||||
(font
|
||||
|
|
@ -16667,7 +16667,7 @@
|
|||
(hide yes)
|
||||
)
|
||||
)
|
||||
(property "MPN" "LM3370SD-3021"
|
||||
(property "MPN" "LM3370SD-4221"
|
||||
(at 208.28 180.34 0)
|
||||
(effects
|
||||
(font
|
||||
|
|
|
|||
|
|
@ -1,5 +1,3 @@
|
|||
# LibreVNA
|
||||
|
||||
  
|
||||
|
||||

|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@
|
|||
#include "caldevice.h"
|
||||
#include "usbdevice.h"
|
||||
#include "CustomWidgets/informationbox.h"
|
||||
#include "preferences.h"
|
||||
|
||||
#include <set>
|
||||
|
||||
|
|
@ -235,14 +234,6 @@ void LibreCALDialog::updateCalibrationStartStatus()
|
|||
canStart = validatePortSelection(true);
|
||||
}
|
||||
|
||||
if(canStart) {
|
||||
if(!Preferences::getInstance().Acquisition.allowUseOfUnstableLibreCALTemp && !device->stabilized()) {
|
||||
canStart = false;
|
||||
ui->lCalibrationStatus->setText("LibreCAL temperature unstable");
|
||||
ui->lCalibrationStatus->setStyleSheet("QLabel { color : red; }");
|
||||
}
|
||||
}
|
||||
|
||||
ui->start->setEnabled(canStart);
|
||||
if(canStart) {
|
||||
ui->lCalibrationStatus->setText("Ready to start");
|
||||
|
|
@ -268,7 +259,6 @@ void LibreCALDialog::updateDeviceStatus()
|
|||
ui->lDeviceStatus->setText("Heating up, please wait with calibration");
|
||||
ui->lDeviceStatus->setStyleSheet("QLabel { color : orange; }");
|
||||
}
|
||||
updateCalibrationStartStatus();
|
||||
}
|
||||
|
||||
void LibreCALDialog::determineAutoPorts()
|
||||
|
|
@ -430,7 +420,6 @@ void LibreCALDialog::stopSweep()
|
|||
void LibreCALDialog::startCalibration()
|
||||
{
|
||||
disableUI();
|
||||
busy = true;
|
||||
|
||||
ui->progressCal->setValue(0);
|
||||
ui->lCalibrationStatus->setText("Creating calibration kit from coefficients...");
|
||||
|
|
@ -603,7 +592,6 @@ void LibreCALDialog::startCalibration()
|
|||
disconnect(cal, &Calibration::measurementsUpdated, this, nullptr);
|
||||
setTerminationOnAllUsedPorts(CalDevice::Standard(CalDevice::Standard::Type::None));
|
||||
enableUI();
|
||||
busy = false;
|
||||
break;
|
||||
}
|
||||
setTerminationOnAllUsedPorts(CalDevice::Standard(CalDevice::Standard::Type::None));
|
||||
|
|
@ -621,7 +609,6 @@ void LibreCALDialog::startCalibration()
|
|||
connect(cal, &Calibration::measurementsAborted, this, [=](){
|
||||
setTerminationOnAllUsedPorts(CalDevice::Standard(CalDevice::Standard::Type::None));
|
||||
enableUI();
|
||||
busy = false;
|
||||
ui->lCalibrationStatus->setText("Ready to start");
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@
|
|||
#include "Util/util.h"
|
||||
#include "LibreCAL/librecaldialog.h"
|
||||
#include "preferences.h"
|
||||
#include "Traces/sparamtraceselectordialog.h"
|
||||
|
||||
#include "Tools/Eigen/Dense"
|
||||
|
||||
|
|
@ -302,9 +301,7 @@ QString Calibration::TypeToString(Calibration::Type type)
|
|||
{
|
||||
switch(type) {
|
||||
case Type::None: return "None";
|
||||
case Type::OSL: return "OSL";
|
||||
case Type::SOLT: return "SOLT";
|
||||
case Type::SOLTwithoutRxMatch: return "SOLTwithoutRxMatch";
|
||||
case Type::ThroughNormalization: return "ThroughNormalization";
|
||||
case Type::TRL: return "TRL";
|
||||
case Type::Last: return "Invalid";
|
||||
|
|
@ -410,7 +407,7 @@ void Calibration::correctTraces(std::map<QString, Trace *> traceSet)
|
|||
}
|
||||
}
|
||||
|
||||
void Calibration::edit(TraceModel *traceModel)
|
||||
void Calibration::edit()
|
||||
{
|
||||
auto d = new QDialog();
|
||||
d->setAttribute(Qt::WA_DeleteOnClose);
|
||||
|
|
@ -512,10 +509,6 @@ void Calibration::edit(TraceModel *traceModel)
|
|||
ui->bDelete->setEnabled(ui->table->currentRow() >= 0);
|
||||
ui->bMoveUp->setEnabled(ui->table->currentRow() >= 1);
|
||||
ui->bMoveDown->setEnabled(ui->table->currentRow() >= 0 && ui->table->currentRow() < ui->table->rowCount() - 1);
|
||||
auto selected = ui->table->selectionModel()->selectedRows();
|
||||
ui->measure->setEnabled(selected.size() > 0);
|
||||
ui->selectMeasurement->setEnabled(traceModel && selected.size() == 1);
|
||||
ui->clearMeasurement->setEnabled(selected.size() > 0);
|
||||
};
|
||||
|
||||
auto updateMeasurementTable = [=](){
|
||||
|
|
@ -533,9 +526,8 @@ void Calibration::edit(TraceModel *traceModel)
|
|||
ui->table->setCellWidget(i, 1, measurements[i]->createStandardWidget());
|
||||
ui->table->setCellWidget(i, 2, measurements[i]->createSettingsWidget());
|
||||
ui->table->setItem(i, 3, measurements[i]->getStatisticsItem());
|
||||
ui->table->setItem(i, 4, new QTableWidgetItem(measurements[i]->getTimestamp().toLocalTime().toString()));
|
||||
ui->table->setItem(i, 4, new QTableWidgetItem(measurements[i]->getTimestamp().toString()));
|
||||
}
|
||||
ui->table->setEditTriggers(QAbstractItemView::NoEditTriggers);
|
||||
ui->table->selectRow(row);
|
||||
updateTableEditButtons();
|
||||
};
|
||||
|
|
@ -626,40 +618,6 @@ void Calibration::edit(TraceModel *traceModel)
|
|||
emit startMeasurements(m);
|
||||
});
|
||||
|
||||
// double clicking on a row also starts the measurement
|
||||
connect(ui->table, &QTableWidget::doubleClicked, this, [=](){
|
||||
emit ui->measure->clicked();
|
||||
});
|
||||
|
||||
connect(ui->selectMeasurement, &QPushButton::clicked, [=](){
|
||||
auto selected = ui->table->selectionModel()->selectedRows();
|
||||
if(selected.size() != 1) {
|
||||
InformationBox::ShowError("Unable to select measurement", "Exactly one measurement must be selected");
|
||||
return;
|
||||
}
|
||||
// figure out which S parameters we need
|
||||
auto meas = measurements[selected[0].row()];
|
||||
auto ports = meas->getPorts();
|
||||
if(ports.size() == 0) {
|
||||
InformationBox::ShowError("Unable to select measurement", "Selecting measurements for this type of calibration measurement is not supported");
|
||||
return;
|
||||
}
|
||||
auto selector = new SParamTraceSelectorDialog(*traceModel, ports);
|
||||
connect(selector, &SParamTraceSelectorDialog::tracesSelected, d, [=](std::vector<DeviceDriver::VNAMeasurement> traceMeasurements){
|
||||
clearMeasurements({meas});
|
||||
for(const auto &tm : traceMeasurements) {
|
||||
addMeasurements({meas}, tm);
|
||||
}
|
||||
updateMeasurementTable();
|
||||
updateCalibrationList();
|
||||
});
|
||||
selector->show();
|
||||
});
|
||||
if(!traceModel) {
|
||||
// can not select a measurement if no trace model is supplied
|
||||
ui->selectMeasurement->setEnabled(false);
|
||||
}
|
||||
|
||||
connect(this, &Calibration::measurementsUpdated, d, [=](){
|
||||
updateMeasurementTable();
|
||||
updateCalibrationList();
|
||||
|
|
@ -706,7 +664,7 @@ void Calibration::edit(TraceModel *traceModel)
|
|||
});
|
||||
});
|
||||
|
||||
QObject::connect(ui->table, &QTableWidget::itemSelectionChanged, updateTableEditButtons);
|
||||
QObject::connect(ui->table, &QTableWidget::currentCellChanged, updateTableEditButtons);
|
||||
|
||||
auto addMenu = new QMenu();
|
||||
for(auto t : CalibrationMeasurement::Base::availableTypes()) {
|
||||
|
|
@ -750,19 +708,19 @@ Calibration::Point Calibration::createInitializedPoint(double f) {
|
|||
point.frequency = f;
|
||||
// resize vectors
|
||||
point.D.resize(caltype.usedPorts.size(), 0.0);
|
||||
point.R.resize(caltype.usedPorts.size(), 1.0);
|
||||
point.R.resize(caltype.usedPorts.size(), 0.0);
|
||||
point.S.resize(caltype.usedPorts.size(), 0.0);
|
||||
|
||||
point.L.resize(caltype.usedPorts.size());
|
||||
point.T.resize(caltype.usedPorts.size());
|
||||
point.I.resize(caltype.usedPorts.size());
|
||||
fill(point.L.begin(), point.L.end(), vector<complex<double>>(caltype.usedPorts.size(), 0.0));
|
||||
fill(point.T.begin(), point.T.end(), vector<complex<double>>(caltype.usedPorts.size(), 1.0));
|
||||
fill(point.T.begin(), point.T.end(), vector<complex<double>>(caltype.usedPorts.size(), 0.0));
|
||||
fill(point.I.begin(), point.I.end(), vector<complex<double>>(caltype.usedPorts.size(), 0.0));
|
||||
return point;
|
||||
}
|
||||
|
||||
Calibration::Point Calibration::computeOSL(double f)
|
||||
Calibration::Point Calibration::computeSOLT(double f)
|
||||
{
|
||||
Point point = createInitializedPoint(f);
|
||||
|
||||
|
|
@ -804,13 +762,6 @@ Calibration::Point Calibration::computeOSL(double f)
|
|||
auto delta = (l_c * l_m * (o_m - s_m) + o_c * o_m * (s_m - l_m) + s_c * s_m * (l_m - o_m)) / denom;
|
||||
point.R[i] = point.D[i] * point.S[i] - delta;
|
||||
}
|
||||
return point;
|
||||
}
|
||||
|
||||
Calibration::Point Calibration::computeSOLT(double f)
|
||||
{
|
||||
Point point = computeOSL(f);
|
||||
|
||||
// calculate forward match and transmission
|
||||
for(unsigned int i=0;i<caltype.usedPorts.size();i++) {
|
||||
for(unsigned int j=0;j<caltype.usedPorts.size();j++) {
|
||||
|
|
@ -850,17 +801,6 @@ Calibration::Point Calibration::computeSOLT(double f)
|
|||
return point;
|
||||
}
|
||||
|
||||
Calibration::Point Calibration::computeSOLTwithoutRxMatch(double f) {
|
||||
// This is very similar to SOLT but it assumes that receiver matching at the VNA is perfect.
|
||||
// It can be used if the through calibration standard is very lossy which would result in
|
||||
// very noisy values for the receiver match
|
||||
auto p = computeSOLT(f);
|
||||
for(auto &l : p.L) {
|
||||
fill(l.begin(), l.end(), 0.0);
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
Calibration::Point Calibration::computeThroughNormalization(double f)
|
||||
{
|
||||
Point point = createInitializedPoint(f);
|
||||
|
|
@ -1338,117 +1278,6 @@ bool Calibration::validForDevice(QString serial) const
|
|||
}
|
||||
}
|
||||
|
||||
bool Calibration::hasDirectivity(unsigned int port)
|
||||
{
|
||||
unsigned int index = std::find(caltype.usedPorts.begin(), caltype.usedPorts.end(), port) - caltype.usedPorts.begin();
|
||||
if(points.size() == 0 || index >= caltype.usedPorts.size()) {
|
||||
// no calibration or it does not contain this port
|
||||
return false;
|
||||
}
|
||||
auto def = std::complex<double>(0.0, 0.0);
|
||||
for(const auto &p : points) {
|
||||
if(p.D[index] != def) {
|
||||
// at least one point does not match the default value -> we have a valid calibration for this
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// all points still at default value
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Calibration::hasReflectionTracking(unsigned int port)
|
||||
{
|
||||
unsigned int index = std::find(caltype.usedPorts.begin(), caltype.usedPorts.end(), port) - caltype.usedPorts.begin();
|
||||
if(points.size() == 0 || index >= caltype.usedPorts.size()) {
|
||||
// no calibration or it does not contain this port
|
||||
return false;
|
||||
}
|
||||
auto def = std::complex<double>(1.0, 0.0);
|
||||
for(const auto &p : points) {
|
||||
if(p.R[index] != def) {
|
||||
// at least one point does not match the default value -> we have a valid calibration for this
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// all points still at default value
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Calibration::hasSourceMatch(unsigned int port)
|
||||
{
|
||||
unsigned int index = std::find(caltype.usedPorts.begin(), caltype.usedPorts.end(), port) - caltype.usedPorts.begin();
|
||||
if(points.size() == 0 || index >= caltype.usedPorts.size()) {
|
||||
// no calibration or it does not contain this port
|
||||
return false;
|
||||
}
|
||||
auto def = std::complex<double>(0.0, 0.0);
|
||||
for(const auto &p : points) {
|
||||
if(p.S[index] != def) {
|
||||
// at least one point does not match the default value -> we have a valid calibration for this
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// all points still at default value
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Calibration::hasReceiverMatch(unsigned int sourcePort, unsigned int receivePort)
|
||||
{
|
||||
unsigned int indexSrc = std::find(caltype.usedPorts.begin(), caltype.usedPorts.end(), sourcePort) - caltype.usedPorts.begin();
|
||||
unsigned int indexRcv = std::find(caltype.usedPorts.begin(), caltype.usedPorts.end(), receivePort) - caltype.usedPorts.begin();
|
||||
if(points.size() == 0 || indexSrc >= caltype.usedPorts.size() || indexRcv >= caltype.usedPorts.size()) {
|
||||
// no calibration or it does not contain this port
|
||||
return false;
|
||||
}
|
||||
auto def = std::complex<double>(0.0, 0.0);
|
||||
for(const auto &p : points) {
|
||||
if(p.L[indexSrc][indexRcv] != def) {
|
||||
// at least one point does not match the default value -> we have a valid calibration for this
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// all points still at default value
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Calibration::hasTransmissionTracking(unsigned int sourcePort, unsigned int receivePort)
|
||||
{
|
||||
unsigned int indexSrc = std::find(caltype.usedPorts.begin(), caltype.usedPorts.end(), sourcePort) - caltype.usedPorts.begin();
|
||||
unsigned int indexRcv = std::find(caltype.usedPorts.begin(), caltype.usedPorts.end(), receivePort) - caltype.usedPorts.begin();
|
||||
if(points.size() == 0 || indexSrc >= caltype.usedPorts.size() || indexRcv >= caltype.usedPorts.size()) {
|
||||
// no calibration or it does not contain this port
|
||||
return false;
|
||||
}
|
||||
auto def = std::complex<double>(1.0, 0.0);
|
||||
for(const auto &p : points) {
|
||||
if(p.T[indexSrc][indexRcv] != def) {
|
||||
// at least one point does not match the default value -> we have a valid calibration for this
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// all points still at default value
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Calibration::hasIsolation(unsigned int sourcePort, unsigned int receivePort)
|
||||
{
|
||||
unsigned int indexSrc = std::find(caltype.usedPorts.begin(), caltype.usedPorts.end(), sourcePort) - caltype.usedPorts.begin();
|
||||
unsigned int indexRcv = std::find(caltype.usedPorts.begin(), caltype.usedPorts.end(), receivePort) - caltype.usedPorts.begin();
|
||||
if(points.size() == 0 || indexSrc >= caltype.usedPorts.size() || indexRcv >= caltype.usedPorts.size()) {
|
||||
// no calibration or it does not contain this port
|
||||
return false;
|
||||
}
|
||||
auto def = std::complex<double>(0.0, 0.0);
|
||||
for(const auto &p : points) {
|
||||
if(p.I[indexSrc][indexRcv] != def) {
|
||||
// at least one point does not match the default value -> we have a valid calibration for this
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// all points still at default value
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Calibration::hasUnsavedChanges() const
|
||||
{
|
||||
return unsavedChanges;
|
||||
|
|
@ -1658,12 +1487,11 @@ bool Calibration::toFile(QString filename)
|
|||
{
|
||||
if(filename.isEmpty()) {
|
||||
QString fn = descriptiveCalName();
|
||||
filename = QFileDialog::getSaveFileName(nullptr, "Save calibration data", Preferences::getInstance().UISettings.Paths.cal + "/" + fn, "Calibration files (*.cal)", nullptr, Preferences::QFileDialogOptions());
|
||||
filename = QFileDialog::getSaveFileName(nullptr, "Save calibration data", fn, "Calibration files (*.cal)", nullptr, Preferences::QFileDialogOptions());
|
||||
if(filename.isEmpty()) {
|
||||
// aborted selection
|
||||
return false;
|
||||
}
|
||||
Preferences::getInstance().UISettings.Paths.cal = QFileInfo(filename).path();
|
||||
}
|
||||
|
||||
if(filename.toLower().endsWith(".cal")) {
|
||||
|
|
@ -1683,12 +1511,11 @@ bool Calibration::toFile(QString filename)
|
|||
bool Calibration::fromFile(QString filename)
|
||||
{
|
||||
if(filename.isEmpty()) {
|
||||
filename = QFileDialog::getOpenFileName(nullptr, "Load calibration data", Preferences::getInstance().UISettings.Paths.cal, "Calibration files (*.cal)", nullptr, Preferences::QFileDialogOptions());
|
||||
filename = QFileDialog::getOpenFileName(nullptr, "Load calibration data", "", "Calibration files (*.cal)", nullptr, Preferences::QFileDialogOptions());
|
||||
if(filename.isEmpty()) {
|
||||
// aborted selection
|
||||
return false;
|
||||
}
|
||||
Preferences::getInstance().UISettings.Paths.cal = QFileInfo(filename).path();
|
||||
}
|
||||
|
||||
// force correct file ending
|
||||
|
|
@ -1708,8 +1535,10 @@ bool Calibration::fromFile(QString filename)
|
|||
}
|
||||
calkit_file.append(".calkit");
|
||||
qDebug() << "Associated calibration kit expected in" << calkit_file;
|
||||
if(!kit.fromFile(calkit_file)) {
|
||||
qDebug() << "Parsing of calibration kit failed while opening calibration file (ignore for calibration format >= 3)";
|
||||
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)";
|
||||
}
|
||||
|
||||
ifstream file;
|
||||
|
|
@ -1775,7 +1604,7 @@ std::vector<Calibration::Type> Calibration::getTypes()
|
|||
return types;
|
||||
}
|
||||
|
||||
bool Calibration::canCompute(Calibration::CalType type, double *startFreq, double *stopFreq, int *points, bool *isLog)
|
||||
bool Calibration::canCompute(Calibration::CalType type, double *startFreq, double *stopFreq, int *points)
|
||||
{
|
||||
using RequiredMeasurements = struct {
|
||||
CalibrationMeasurement::Base::Type type;
|
||||
|
|
@ -1786,15 +1615,6 @@ bool Calibration::canCompute(Calibration::CalType type, double *startFreq, doubl
|
|||
case Type::None:
|
||||
return true; // Always possible to reset the calibration
|
||||
case Type::SOLT:
|
||||
case Type::SOLTwithoutRxMatch:
|
||||
// through measurements between all ports
|
||||
for(unsigned int i=1;i<=type.usedPorts.size();i++) {
|
||||
for(unsigned int j=i+1;j<=type.usedPorts.size();j++) {
|
||||
required.push_back({.type = CalibrationMeasurement::Base::Type::Through, .port1 = i, .port2 = j});
|
||||
}
|
||||
}
|
||||
[[fallthrough]];
|
||||
case Type::OSL:
|
||||
// SOL measurements for every port
|
||||
for(auto p : type.usedPorts) {
|
||||
required.push_back({.type = CalibrationMeasurement::Base::Type::Short, .port1 = p, .port2 = 0});
|
||||
|
|
@ -1807,6 +1627,12 @@ bool Calibration::canCompute(Calibration::CalType type, double *startFreq, doubl
|
|||
required.push_back({.type = CalibrationMeasurement::Base::Type::Load, .port1 = p, .port2 = 0});
|
||||
}
|
||||
}
|
||||
// through measurements between all ports
|
||||
for(unsigned int i=1;i<=type.usedPorts.size();i++) {
|
||||
for(unsigned int j=i+1;j<=type.usedPorts.size();j++) {
|
||||
required.push_back({.type = CalibrationMeasurement::Base::Type::Through, .port1 = i, .port2 = j});
|
||||
}
|
||||
}
|
||||
break;
|
||||
case Type::ThroughNormalization:
|
||||
// through measurements between all ports
|
||||
|
|
@ -1848,7 +1674,7 @@ bool Calibration::canCompute(Calibration::CalType type, double *startFreq, doubl
|
|||
foundMeasurements.push_back(meas);
|
||||
}
|
||||
}
|
||||
return hasFrequencyOverlap(foundMeasurements, startFreq, stopFreq, points, isLog);
|
||||
return hasFrequencyOverlap(foundMeasurements, startFreq, stopFreq, points);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
@ -1862,25 +1688,17 @@ bool Calibration::compute(Calibration::CalType type)
|
|||
}
|
||||
double start, stop;
|
||||
int numPoints;
|
||||
bool isLog;
|
||||
if(!canCompute(type, &start, &stop, &numPoints, &isLog)) {
|
||||
if(!canCompute(type, &start, &stop, &numPoints)) {
|
||||
return false;
|
||||
}
|
||||
caltype = type;
|
||||
try {
|
||||
points.clear();
|
||||
for(int i=0;i<numPoints;i++) {
|
||||
double f;
|
||||
if(!isLog) {
|
||||
f = start + (stop - start) * i / (numPoints - 1);
|
||||
} else {
|
||||
f = start * pow(10.0, i * log10(stop / start) / (numPoints - 1));
|
||||
}
|
||||
double f = start + (stop - start) * i / (numPoints - 1);
|
||||
Point p;
|
||||
switch(type.type) {
|
||||
case Type::OSL: p = computeOSL(f); break;
|
||||
case Type::SOLT: p = computeSOLT(f); break;
|
||||
case Type::SOLTwithoutRxMatch: p = computeSOLTwithoutRxMatch(f); break;
|
||||
case Type::ThroughNormalization: p = computeThroughNormalization(f); break;
|
||||
case Type::TRL: p = computeTRL(f); break;
|
||||
case Type::None:
|
||||
|
|
@ -1908,9 +1726,7 @@ void Calibration::reset()
|
|||
int Calibration::minimumPorts(Calibration::Type type)
|
||||
{
|
||||
switch(type) {
|
||||
case Type::OSL: return 1;
|
||||
case Type::SOLT: return 1;
|
||||
case Type::SOLTwithoutRxMatch: return 2;
|
||||
case Type::ThroughNormalization: return 2;
|
||||
case Type::TRL: return 2;
|
||||
case Type::None:
|
||||
|
|
@ -1975,12 +1791,12 @@ void Calibration::createDefaultMeasurements(Calibration::DefaultMeasurements dm)
|
|||
{
|
||||
lock_guard<recursive_mutex> guard(access);
|
||||
auto createSOL = [=](int port) {
|
||||
auto open = new CalibrationMeasurement::Open(this);
|
||||
open->setPort(port);
|
||||
measurements.push_back(open);
|
||||
auto _short = new CalibrationMeasurement::Short(this);
|
||||
_short->setPort(port);
|
||||
measurements.push_back(_short);
|
||||
auto open = new CalibrationMeasurement::Open(this);
|
||||
open->setPort(port);
|
||||
measurements.push_back(open);
|
||||
auto load = new CalibrationMeasurement::Load(this);
|
||||
load->setPort(port);
|
||||
measurements.push_back(load);
|
||||
|
|
@ -2034,13 +1850,11 @@ void Calibration::deleteMeasurements()
|
|||
measurements.clear();
|
||||
}
|
||||
|
||||
bool Calibration::hasFrequencyOverlap(std::vector<CalibrationMeasurement::Base *> m, double *startFreq, double *stopFreq, int *points, bool *isLog)
|
||||
bool Calibration::hasFrequencyOverlap(std::vector<CalibrationMeasurement::Base *> m, double *startFreq, double *stopFreq, int *points)
|
||||
{
|
||||
double minResolution = std::numeric_limits<double>::max();
|
||||
double minFreq = 0;
|
||||
double maxFreq = std::numeric_limits<double>::max();
|
||||
unsigned int logCount = 0;
|
||||
unsigned int linCount = 0;
|
||||
for(auto meas : m) {
|
||||
if(meas->numPoints() < 2) {
|
||||
return false;
|
||||
|
|
@ -2055,38 +1869,6 @@ bool Calibration::hasFrequencyOverlap(std::vector<CalibrationMeasurement::Base *
|
|||
if(resolution < minResolution) {
|
||||
minResolution = resolution;
|
||||
}
|
||||
// check whether the frequency points are more linear or more logarithmic
|
||||
double minDiff = std::numeric_limits<double>::max();
|
||||
double maxDiff = 0;
|
||||
double minRatio = std::numeric_limits<double>::max();
|
||||
double maxRatio = 0;
|
||||
for(unsigned int i=1;i<meas->numPoints();i++) {
|
||||
double f_prev = meas->getPointFreq(i-1);
|
||||
double f_next = meas->getPointFreq(i);
|
||||
double diff = f_next - f_prev;
|
||||
double ratio = f_next / f_prev;
|
||||
if(diff < minDiff) {
|
||||
minDiff = diff;
|
||||
}
|
||||
if(diff > maxDiff) {
|
||||
maxDiff = diff;
|
||||
}
|
||||
if(ratio < minRatio) {
|
||||
minRatio = ratio;
|
||||
}
|
||||
if(ratio > maxRatio) {
|
||||
maxRatio = ratio;
|
||||
}
|
||||
}
|
||||
double diffVariationNormalized = (maxDiff - minDiff) / maxDiff;
|
||||
double ratioVariationNormalized = (maxRatio - minRatio) / maxRatio;
|
||||
if(abs(diffVariationNormalized) < abs(ratioVariationNormalized)) {
|
||||
// more linear
|
||||
linCount++;
|
||||
} else {
|
||||
// more logarithmic
|
||||
logCount++;
|
||||
}
|
||||
}
|
||||
if(startFreq) {
|
||||
*startFreq = minFreq;
|
||||
|
|
@ -2097,9 +1879,6 @@ bool Calibration::hasFrequencyOverlap(std::vector<CalibrationMeasurement::Base *
|
|||
if(points) {
|
||||
*points = (maxFreq - minFreq) / minResolution + 1;
|
||||
}
|
||||
if(isLog) {
|
||||
*isLog = logCount > linCount;
|
||||
}
|
||||
if(maxFreq > minFreq) {
|
||||
return true;
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -14,15 +14,12 @@ class Calibration : public QObject, public Savable, public SCPINode
|
|||
Q_OBJECT
|
||||
|
||||
friend class LibreCALDialog;
|
||||
friend class CalibrationTests;
|
||||
public:
|
||||
Calibration();
|
||||
|
||||
enum class Type {
|
||||
None,
|
||||
OSL,
|
||||
SOLT,
|
||||
SOLTwithoutRxMatch,
|
||||
ThroughNormalization,
|
||||
TRL,
|
||||
Last,
|
||||
|
|
@ -47,7 +44,7 @@ public:
|
|||
void correctTraces(std::map<QString, Trace*> traceSet);
|
||||
|
||||
// Starts the calibration edit dialog, allowing the user to make/delete measurements
|
||||
void edit(TraceModel *traceModel = nullptr);
|
||||
void edit();
|
||||
|
||||
Calkit& getKit();
|
||||
|
||||
|
|
@ -65,7 +62,7 @@ public:
|
|||
static std::vector<Type> getTypes();
|
||||
// Checks whether all measurements for a specific calibration are available.
|
||||
// If pointer to the frequency/points variables are given, the start/stop frequency and number of points the calibration will have after the calculation is stored there
|
||||
bool canCompute(CalType type, double *startFreq = nullptr, double *stopFreq = nullptr, int *points = nullptr, bool *isLog = nullptr);
|
||||
bool canCompute(CalType type, double *startFreq = nullptr, double *stopFreq = nullptr, int *points = nullptr);
|
||||
// Resets the calibration (deletes all measurements and calculated coefficients)
|
||||
void reset();
|
||||
// Returns the minimum number of ports for a given calibration type.
|
||||
|
|
@ -101,14 +98,6 @@ public:
|
|||
QString getValidDevice() const;
|
||||
bool validForDevice(QString serial) const;
|
||||
|
||||
// query whether error terms coefficients are available. Port count starts at 1
|
||||
bool hasDirectivity(unsigned int port);
|
||||
bool hasReflectionTracking(unsigned int port);
|
||||
bool hasSourceMatch(unsigned int port);
|
||||
bool hasReceiverMatch(unsigned int sourcePort, unsigned int receivePort);
|
||||
bool hasTransmissionTracking(unsigned int sourcePort, unsigned int receivePort);
|
||||
bool hasIsolation(unsigned int sourcePort, unsigned int receivePort);
|
||||
|
||||
public slots:
|
||||
// Call once all datapoints of the current span have been added
|
||||
void measurementsComplete();
|
||||
|
|
@ -141,7 +130,7 @@ private:
|
|||
void createDefaultMeasurements(DefaultMeasurements dm);
|
||||
void deleteMeasurements();
|
||||
|
||||
static bool hasFrequencyOverlap(std::vector<CalibrationMeasurement::Base*> m, double *startFreq = nullptr, double *stopFreq = nullptr, int *points = nullptr, bool *isLog = nullptr);
|
||||
bool hasFrequencyOverlap(std::vector<CalibrationMeasurement::Base*> m, double *startFreq = nullptr, double *stopFreq = nullptr, int *points = nullptr);
|
||||
// returns all measurements that match the paramaters
|
||||
std::vector<CalibrationMeasurement::Base*> findMeasurements(CalibrationMeasurement::Base::Type type, int port1 = 0, int port2 = 0);
|
||||
// returns the first measurement in the list that matches the parameters
|
||||
|
|
@ -162,9 +151,7 @@ private:
|
|||
std::vector<Point> points;
|
||||
|
||||
Point createInitializedPoint(double f);
|
||||
Point computeOSL(double f);
|
||||
Point computeSOLT(double f);
|
||||
Point computeSOLTwithoutRxMatch(double f);
|
||||
Point computeThroughNormalization(double f);
|
||||
Point computeTRL(double f);
|
||||
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@
|
|||
<item>
|
||||
<widget class="QTableWidget" name="table">
|
||||
<property name="selectionBehavior">
|
||||
<enum>QAbstractItemView::SelectionBehavior::SelectRows</enum>
|
||||
<enum>QAbstractItemView::SelectRows</enum>
|
||||
</property>
|
||||
<attribute name="horizontalHeaderStretchLastSection">
|
||||
<bool>true</bool>
|
||||
|
|
@ -148,14 +148,6 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="selectMeasurement">
|
||||
<property name="text">
|
||||
<string>Select
|
||||
Measurement</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="clearMeasurement">
|
||||
<property name="text">
|
||||
|
|
@ -193,7 +185,7 @@ Kit</string>
|
|||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Orientation::Vertical</enum>
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
|
|
@ -295,7 +287,7 @@ Kit</string>
|
|||
<item>
|
||||
<spacer name="verticalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Orientation::Vertical</enum>
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
|
|
|
|||
|
|
@ -627,10 +627,6 @@ void CalibrationMeasurement::Isolation::addPoint(const DeviceDriver::VNAMeasurem
|
|||
QString name = meas.first;
|
||||
unsigned int rcv = name.mid(1, 1).toInt() - 1;
|
||||
unsigned int src = name.mid(2, 1).toInt() - 1;
|
||||
if(rcv > 8 || src > 8) {
|
||||
// skip
|
||||
continue;
|
||||
}
|
||||
if(rcv >= p.S.size()) {
|
||||
p.S.resize(rcv + 1);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,7 +41,6 @@ public:
|
|||
virtual double maxUsableFreq() = 0;
|
||||
virtual double minFreq() = 0;
|
||||
virtual double maxFreq() = 0;
|
||||
virtual double getPointFreq(unsigned int p) = 0;
|
||||
virtual unsigned int numPoints() = 0;
|
||||
virtual bool readyForMeasurement() {return false;}
|
||||
virtual bool readyForCalculation() {return false;}
|
||||
|
|
@ -61,8 +60,6 @@ public:
|
|||
virtual nlohmann::json toJSON() override;
|
||||
virtual void fromJSON(nlohmann::json j) override;
|
||||
|
||||
virtual std::vector<unsigned int> getPorts() = 0;
|
||||
|
||||
static bool canMeasureSimultaneously(std::set<Base *> measurements);
|
||||
QDateTime getTimestamp() const;
|
||||
|
||||
|
|
@ -91,7 +88,6 @@ public:
|
|||
virtual double maxUsableFreq() override;
|
||||
virtual double minFreq() override {return points.size() > 0 ? points.front().frequency : std::numeric_limits<double>::max();}
|
||||
virtual double maxFreq() override {return points.size() > 0 ? points.back().frequency : 0;}
|
||||
virtual double getPointFreq(unsigned int p) override { return p < points.size() ? points[p].frequency : 0;}
|
||||
virtual unsigned int numPoints() override {return points.size();}
|
||||
virtual bool readyForMeasurement() override {return standard != nullptr;}
|
||||
virtual bool readyForCalculation() override {return standard && points.size() > 0;}
|
||||
|
|
@ -104,8 +100,6 @@ public:
|
|||
virtual nlohmann::json toJSON() override;
|
||||
virtual void fromJSON(nlohmann::json j) override;
|
||||
|
||||
virtual std::vector<unsigned int> getPorts() override {return {port};}
|
||||
|
||||
class Point {
|
||||
public:
|
||||
double frequency;
|
||||
|
|
@ -213,7 +207,6 @@ public:
|
|||
virtual double maxUsableFreq() override;
|
||||
virtual double minFreq() override {return points.size() > 0 ? points.front().frequency : std::numeric_limits<double>::max();}
|
||||
virtual double maxFreq() override {return points.size() > 0 ? points.back().frequency : 0;}
|
||||
virtual double getPointFreq(unsigned int p) override { return p < points.size() ? points[p].frequency : 0;}
|
||||
virtual unsigned int numPoints() override {return points.size();}
|
||||
virtual bool readyForMeasurement() override {return standard != nullptr;}
|
||||
virtual bool readyForCalculation() override {return standard && points.size() > 0;}
|
||||
|
|
@ -226,8 +219,6 @@ public:
|
|||
virtual nlohmann::json toJSON() override;
|
||||
virtual void fromJSON(nlohmann::json j) override;
|
||||
|
||||
virtual std::vector<unsigned int> getPorts() override {return {port1, port2};}
|
||||
|
||||
class Point {
|
||||
public:
|
||||
double frequency;
|
||||
|
|
@ -290,7 +281,6 @@ public:
|
|||
virtual double maxUsableFreq() override {return maxFreq();}
|
||||
virtual double minFreq() override {return points.size() > 0 ? points.front().frequency : std::numeric_limits<double>::max();}
|
||||
virtual double maxFreq() override {return points.size() > 0 ? points.back().frequency : 0;}
|
||||
virtual double getPointFreq(unsigned int p) override { return p < points.size() ? points[p].frequency : 0;}
|
||||
virtual unsigned int numPoints() override;
|
||||
virtual bool readyForMeasurement() override {return true;}
|
||||
virtual bool readyForCalculation() override {return points.size() > 0;}
|
||||
|
|
@ -304,8 +294,6 @@ public:
|
|||
virtual nlohmann::json toJSON() override;
|
||||
virtual void fromJSON(nlohmann::json j) override;
|
||||
|
||||
virtual std::vector<unsigned int> getPorts() override {return {};}
|
||||
|
||||
class Point {
|
||||
public:
|
||||
double frequency;
|
||||
|
|
|
|||
|
|
@ -1,314 +0,0 @@
|
|||
#include "calibrationviewdialog.h"
|
||||
#include "ui_calibrationviewdialog.h"
|
||||
|
||||
#include <QGraphicsSimpleTextItem>
|
||||
#include <QVector2D>
|
||||
|
||||
const QColor CalibrationViewDialog::colorNoCal = Qt::darkRed;
|
||||
const QColor CalibrationViewDialog::colorHasCal = Qt::darkGreen;
|
||||
|
||||
CalibrationViewDialog::CalibrationViewDialog(Calibration *cal, unsigned int ports, QWidget *parent)
|
||||
: QDialog(parent)
|
||||
, ui(new Ui::CalibrationViewDialog)
|
||||
, cal(cal)
|
||||
, ports(ports)
|
||||
{
|
||||
setAttribute(Qt::WA_DeleteOnClose);
|
||||
ui->setupUi(this);
|
||||
ui->port->setMaximum(ports);
|
||||
scene = new QGraphicsScene();
|
||||
populateScene();
|
||||
ui->view->setScene(scene);
|
||||
|
||||
connect(ui->port, &QSpinBox::valueChanged, this, &CalibrationViewDialog::populateScene);
|
||||
}
|
||||
|
||||
CalibrationViewDialog::~CalibrationViewDialog()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void CalibrationViewDialog::populateScene()
|
||||
{
|
||||
scene->clear();
|
||||
auto colorF = QApplication::palette().text().color();
|
||||
auto colorB = QApplication::palette().base().color();
|
||||
auto pen = QPen(colorF);
|
||||
|
||||
auto drawDot = [this](float x, float y, float size, QPen pen = QPen(), QBrush brush = QBrush()) {
|
||||
scene->addEllipse(x - size/2, y - size/2, size, size, pen, brush);
|
||||
};
|
||||
|
||||
auto drawText = [this](float x, float y, QString s, QColor color, auto alignH = Qt::AlignCenter, auto alignV = Qt::AlignCenter, float rotation = 0.0f) {
|
||||
auto text = scene->addText(s);
|
||||
text->setRotation(rotation);
|
||||
switch(alignH) {
|
||||
default:
|
||||
case Qt::AlignLeft: break;
|
||||
case Qt::AlignCenter:
|
||||
case Qt::AlignHCenter: x -= text->boundingRect().bottomRight().x()/2; break;
|
||||
case Qt::AlignRight: x -= text->boundingRect().bottomRight().x(); break;
|
||||
}
|
||||
switch(alignV) {
|
||||
default:
|
||||
case Qt::AlignTop: break;
|
||||
case Qt::AlignCenter:
|
||||
case Qt::AlignVCenter: y -= text->boundingRect().bottomRight().y()/2; break;
|
||||
case Qt::AlignBottom: y -= text->boundingRect().bottomRight().y(); break;
|
||||
}
|
||||
text->setPos(QPointF(x, y));
|
||||
text->setDefaultTextColor(color);
|
||||
};
|
||||
|
||||
auto drawPath = [this, drawText](QList<QPointF> vertices, QColor color, QString label = QString(), bool arrow = false) {
|
||||
// draw lines
|
||||
for(unsigned int i=1;i<vertices.size();i++) {
|
||||
|
||||
scene->addLine(QLineF(vertices[i-1], vertices[i]), color);
|
||||
if(i == vertices.size() / 2) {
|
||||
// this is the middle segment, add label and arrow if required
|
||||
auto midPoint = (vertices[i-1]+vertices[i])/2;
|
||||
QVector2D direction = QVector2D(vertices[i] - vertices[i-1]);
|
||||
direction.normalize();
|
||||
auto ortho = QVector2D(-direction.y(), direction.x());
|
||||
if(arrow) {
|
||||
auto poly = QPolygonF({
|
||||
QPointF(midPoint + direction.toPointF()*arrowLength/2),
|
||||
QPointF(midPoint - direction.toPointF()*arrowLength/2 + ortho.toPointF()*arrowWidth/2),
|
||||
QPointF(midPoint - direction.toPointF()*arrowLength/2 - ortho.toPointF()*arrowWidth/2)
|
||||
});
|
||||
scene->addPolygon(poly, color, color);
|
||||
}
|
||||
if(!label.isEmpty()) {
|
||||
auto pos = midPoint;
|
||||
if(label.startsWith("_")) {
|
||||
label.remove(0, 1);
|
||||
pos -= ortho.toPointF() * labelDistance;
|
||||
} else {
|
||||
pos += ortho.toPointF() * labelDistance;
|
||||
}
|
||||
auto alignH = abs(direction.x()) > abs(direction.y()) ? Qt::AlignCenter : Qt::AlignLeft;
|
||||
auto alignV = abs(direction.y()) > abs(direction.x()) ? Qt::AlignCenter : Qt::AlignTop;
|
||||
drawText(pos.x(), pos.y(), label, color, alignH, alignV);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
auto DUTwidth = 2 * ports * pathSpacing;
|
||||
auto DUTstartX = ports * pathSpacing + 2*boxSpacing;
|
||||
|
||||
// set the overall scene size
|
||||
scene->setSceneRect(0, 0, marginLeft + DUTstartX + DUTwidth + marginRight, marginTop + ports * portHeight + marginBottom);
|
||||
|
||||
// create the DUT
|
||||
// rectangle
|
||||
scene->addRect(marginLeft + DUTstartX, marginTop, DUTwidth, ports * portHeight, pen);
|
||||
drawText(marginLeft + DUTstartX + DUTwidth/2, marginTop, "DUT", colorF, Qt::AlignCenter, Qt::AlignTop);
|
||||
// ports
|
||||
for(unsigned int i=1;i<=ports;i++) {
|
||||
// input marker
|
||||
drawDot(marginLeft + DUTstartX, marginTop + i*portHeight - portHeight/2 + portForwardYOffset, portSize, colorF, colorB);
|
||||
// output marker
|
||||
drawDot(marginLeft + DUTstartX, marginTop + i*portHeight - portHeight/2 + portReverseYOffset, portSize, colorF, colorB);
|
||||
}
|
||||
// the reflection path
|
||||
drawPath({
|
||||
QPointF(marginLeft + DUTstartX + portSize/2, marginTop + ui->port->value()*portHeight - portHeight/2 + portForwardYOffset),
|
||||
QPointF(marginLeft + DUTstartX + pathSpacing, marginTop + ui->port->value()*portHeight - portHeight/2 + portForwardYOffset),
|
||||
QPointF(marginLeft + DUTstartX + pathSpacing, marginTop + ui->port->value()*portHeight - portHeight/2 + portReverseYOffset),
|
||||
QPointF(marginLeft + DUTstartX + portSize/2, marginTop + ui->port->value()*portHeight - portHeight/2 + portReverseYOffset),
|
||||
}, colorF, "_S"+QString::number(ui->port->value())+QString::number(ui->port->value()), true);
|
||||
// the forward transmission paths
|
||||
float xstart = marginLeft + DUTstartX + pathSpacing;
|
||||
for(unsigned int i=1;i<=ports;i++) {
|
||||
if((int) i == ui->port->value()) {
|
||||
// skip, this is the reflection path
|
||||
continue;
|
||||
}
|
||||
drawDot(xstart, marginTop + ui->port->value()*portHeight - portHeight/2 + portForwardYOffset, junctionSize, colorF, colorF);
|
||||
drawPath({
|
||||
QPointF(xstart, marginTop + ui->port->value()*portHeight - portHeight/2 + portForwardYOffset),
|
||||
QPointF(xstart + pathSpacing, marginTop + ui->port->value()*portHeight - portHeight/2 + portForwardYOffset),
|
||||
QPointF(xstart + pathSpacing, marginTop + i*portHeight - portHeight/2 + portReverseYOffset),
|
||||
QPointF(marginLeft + DUTstartX + portSize/2, marginTop + i*portHeight - portHeight/2 + portReverseYOffset),
|
||||
}, colorF, QString((int) i > ui->port->value() ? "_" : "") + "S"+QString::number(i)+QString::number(ui->port->value()), true);
|
||||
xstart += pathSpacing;
|
||||
}
|
||||
// the reverse transmission paths
|
||||
bool first = true;
|
||||
for(unsigned int i=1;i<=ports;i++) {
|
||||
if((int) i == ui->port->value()) {
|
||||
// skip, this is the reflection path
|
||||
continue;
|
||||
}
|
||||
if(first) {
|
||||
first = false;
|
||||
drawDot(marginLeft + DUTstartX + pathSpacing, marginTop + ui->port->value()*portHeight - portHeight/2 + portReverseYOffset, junctionSize, colorF, colorF);
|
||||
drawPath({
|
||||
QPointF(marginLeft + DUTstartX + pathSpacing, marginTop + ui->port->value()*portHeight - portHeight/2 + portReverseYOffset),
|
||||
QPointF(xstart, marginTop + ui->port->value()*portHeight - portHeight/2 + portReverseYOffset),
|
||||
}, colorF, "", false);
|
||||
} else {
|
||||
drawDot(xstart, marginTop + ui->port->value()*portHeight - portHeight/2 + portReverseYOffset, junctionSize, colorF, colorF);
|
||||
}
|
||||
drawPath({
|
||||
QPointF(marginLeft + DUTstartX + portSize/2, marginTop + i*portHeight - portHeight/2 + portForwardYOffset),
|
||||
QPointF(xstart + pathSpacing, marginTop + i*portHeight - portHeight/2 + portForwardYOffset),
|
||||
QPointF(xstart + pathSpacing, marginTop + ui->port->value()*portHeight - portHeight/2 + portReverseYOffset),
|
||||
QPointF(xstart, marginTop + ui->port->value()*portHeight - portHeight/2 + portReverseYOffset),
|
||||
}, colorF, QString((int) i > ui->port->value() ? "" : "_") + "S"+QString::number(ui->port->value())+QString::number(i), true);
|
||||
xstart += pathSpacing;
|
||||
}
|
||||
|
||||
// isolation, transmission and receiver match paths
|
||||
xstart = marginLeft;
|
||||
for(unsigned int i=1;i<=ports;i++) {
|
||||
if((int) i == ui->port->value()) {
|
||||
// skip, this is the reflection path
|
||||
continue;
|
||||
}
|
||||
// isolation
|
||||
drawDot(xstart, marginTop + ui->port->value()*portHeight - portHeight/2 + portForwardYOffset, junctionSize, colorF, colorF);
|
||||
drawPath({
|
||||
QPointF(xstart, marginTop + ui->port->value()*portHeight - portHeight/2 + portForwardYOffset),
|
||||
QPointF(xstart + pathSpacing, marginTop + ui->port->value()*portHeight - portHeight/2 + portForwardYOffset),
|
||||
}, colorF);
|
||||
drawPath({
|
||||
QPointF(xstart + pathSpacing, marginTop + ui->port->value()*portHeight - portHeight/2 + portForwardYOffset),
|
||||
QPointF(xstart + pathSpacing, marginTop + i*portHeight - portHeight/2 + portReverseYOffset),
|
||||
}, cal->hasIsolation(ui->port->value(), i) ? colorHasCal : colorNoCal, QString((int) i > ui->port->value() ? "_" : "") + "I"+QString::number(i)+QString::number(ui->port->value()), true);
|
||||
drawPath({
|
||||
QPointF(xstart + pathSpacing, marginTop + i*portHeight - portHeight/2 + portReverseYOffset),
|
||||
QPointF(marginLeft, marginTop + i*portHeight - portHeight/2 + portReverseYOffset),
|
||||
}, colorF);
|
||||
xstart += pathSpacing;
|
||||
// transmission
|
||||
drawDot(xstart, marginTop + i*portHeight - portHeight/2 + portReverseYOffset, junctionSize, colorF, colorF);
|
||||
drawPath({
|
||||
QPointF(marginLeft + DUTstartX - portSize / 2, marginTop + i*portHeight - portHeight/2 + portReverseYOffset),
|
||||
QPointF(marginLeft + DUTstartX - pathSpacing, marginTop + i*portHeight - portHeight/2 + portReverseYOffset),
|
||||
}, colorF);
|
||||
drawPath({
|
||||
QPointF(marginLeft + DUTstartX - pathSpacing, marginTop + i*portHeight - portHeight/2 + portReverseYOffset),
|
||||
QPointF(xstart, marginTop + i*portHeight - portHeight/2 + portReverseYOffset),
|
||||
}, cal->hasTransmissionTracking(ui->port->value(), i) ? colorHasCal : colorNoCal, "_T"+QString::number(i)+QString::number(ui->port->value()), true);
|
||||
// Reveicer match
|
||||
drawDot(marginLeft + DUTstartX - pathSpacing, marginTop + i*portHeight - portHeight/2 + portReverseYOffset, junctionSize, colorF, colorF);
|
||||
drawPath({
|
||||
QPointF(marginLeft + DUTstartX - pathSpacing, marginTop + i*portHeight - portHeight/2 + portReverseYOffset),
|
||||
QPointF(marginLeft + DUTstartX - pathSpacing, marginTop + i*portHeight - portHeight/2 + portForwardYOffset),
|
||||
QPointF(marginLeft + DUTstartX - portSize/2, marginTop + i*portHeight - portHeight/2 + portForwardYOffset),
|
||||
}, cal->hasReceiverMatch(ui->port->value(), i) ? colorHasCal : colorNoCal, "L"+QString::number(i)+QString::number(ui->port->value()), true);
|
||||
}
|
||||
|
||||
// reflection error box
|
||||
drawDot(xstart, marginTop + ui->port->value()*portHeight - portHeight/2 + portForwardYOffset, junctionSize, colorF, colorF);
|
||||
drawDot(xstart + pathSpacing, marginTop + ui->port->value()*portHeight - portHeight/2 + portForwardYOffset, junctionSize, colorF, colorF);
|
||||
drawDot(xstart + pathSpacing, marginTop + ui->port->value()*portHeight - portHeight/2 + portReverseYOffset, junctionSize, colorF, colorF);
|
||||
drawDot(xstart + pathSpacing + boxSpacing, marginTop + ui->port->value()*portHeight - portHeight/2 + portForwardYOffset, junctionSize, colorF, colorF);
|
||||
drawDot(xstart + pathSpacing + boxSpacing, marginTop + ui->port->value()*portHeight - portHeight/2 + portReverseYOffset, junctionSize, colorF, colorF);
|
||||
// unity paths
|
||||
drawPath({
|
||||
QPointF(xstart, marginTop + ui->port->value()*portHeight - portHeight/2 + portForwardYOffset),
|
||||
QPointF(xstart + pathSpacing, marginTop + ui->port->value()*portHeight - portHeight/2 + portForwardYOffset),
|
||||
QPointF(xstart + pathSpacing + boxSpacing, marginTop + ui->port->value()*portHeight - portHeight/2 + portForwardYOffset),
|
||||
QPointF(marginLeft + DUTstartX - portSize/2, marginTop + ui->port->value()*portHeight - portHeight/2 + portForwardYOffset),
|
||||
}, colorF, "", true);
|
||||
drawPath({
|
||||
QPointF(marginLeft + DUTstartX - portSize/2, marginTop + ui->port->value()*portHeight - portHeight/2 + portReverseYOffset),
|
||||
QPointF(xstart + pathSpacing + boxSpacing, marginTop + ui->port->value()*portHeight - portHeight/2 + portReverseYOffset),
|
||||
}, colorF);
|
||||
drawPath({
|
||||
QPointF(marginLeft + portSize/2, marginTop + ui->port->value()*portHeight - portHeight/2 + portReverseYOffset),
|
||||
QPointF(xstart + pathSpacing, marginTop + ui->port->value()*portHeight - portHeight/2 + portReverseYOffset),
|
||||
}, colorF);
|
||||
|
||||
// directivity
|
||||
drawPath({
|
||||
QPointF(xstart + pathSpacing, marginTop + ui->port->value()*portHeight - portHeight/2 + portForwardYOffset),
|
||||
QPointF(xstart + pathSpacing, marginTop + ui->port->value()*portHeight - portHeight/2 + portReverseYOffset),
|
||||
}, cal->hasDirectivity(ui->port->value()) ? colorHasCal : colorNoCal, "_D"+QString::number(ui->port->value()), true);
|
||||
|
||||
// reflection tracking
|
||||
drawPath({
|
||||
QPointF(xstart + pathSpacing + boxSpacing, marginTop + ui->port->value()*portHeight - portHeight/2 + portReverseYOffset),
|
||||
QPointF(xstart + pathSpacing, marginTop + ui->port->value()*portHeight - portHeight/2 + portReverseYOffset),
|
||||
}, cal->hasReflectionTracking(ui->port->value()) ? colorHasCal : colorNoCal, "_R"+QString::number(ui->port->value()), true);
|
||||
|
||||
// source match
|
||||
drawPath({
|
||||
QPointF(xstart + pathSpacing + boxSpacing, marginTop + ui->port->value()*portHeight - portHeight/2 + portReverseYOffset),
|
||||
QPointF(xstart + pathSpacing + boxSpacing, marginTop + ui->port->value()*portHeight - portHeight/2 + portForwardYOffset),
|
||||
}, cal->hasSourceMatch(ui->port->value()) ? colorHasCal : colorNoCal, "S"+QString::number(ui->port->value()), true);
|
||||
|
||||
// create the VNA ports
|
||||
for(unsigned int i=1;i<=ports;i++) {
|
||||
// stimulus port
|
||||
if(i == (unsigned int) ui->port->value()) {
|
||||
drawDot(marginLeft, marginTop + i*portHeight - portHeight/2 + portForwardYOffset, portSize, colorF, colorB);
|
||||
drawText(marginLeft - portSize/2, marginTop + i*portHeight - portHeight/2 + portForwardYOffset, "a"+QString::number(i), colorF, Qt::AlignRight, Qt::AlignCenter);
|
||||
}
|
||||
// output marker
|
||||
drawDot(marginLeft, marginTop + i*portHeight - portHeight/2 + portReverseYOffset, portSize, colorF, colorB);
|
||||
drawText(marginLeft - portSize/2, marginTop + i*portHeight - portHeight/2 + portReverseYOffset, "b"+QString::number(i), colorF, Qt::AlignRight, Qt::AlignCenter);
|
||||
}
|
||||
|
||||
// Fill the measurement correction table
|
||||
ui->table->clear();
|
||||
ui->table->setRowCount(ports*ports);
|
||||
ui->table->setColumnCount(2);
|
||||
ui->table->setHorizontalHeaderLabels({"Parameter", "Calibration Status"});
|
||||
for(unsigned int i=1;i<=ports;i++) {
|
||||
for(unsigned int j=1;j<=ports;j++) {
|
||||
auto row = (i-1)*ports+j-1;
|
||||
// add parameter
|
||||
ui->table->setItem(row, 0, new QTableWidgetItem("S"+QString::number(j)+QString::number(i)));
|
||||
// check the calibration status
|
||||
QString status = "Uncalibrated";
|
||||
if(i == j) {
|
||||
// check reflection parameters
|
||||
if(cal->hasSourceMatch(i) && cal->hasDirectivity(i) && cal->hasReflectionTracking(i)) {
|
||||
// we are calibrated
|
||||
status = "Calibrated";
|
||||
// check if we have enhanced responses
|
||||
QList<int> enhanced;
|
||||
for(unsigned int k=1;k<=ports;k++) {
|
||||
if(k==i) {
|
||||
continue;
|
||||
}
|
||||
if(cal->hasReceiverMatch(i, k)) {
|
||||
enhanced.append(k);
|
||||
}
|
||||
}
|
||||
if(enhanced.size() == 1) {
|
||||
status += " with enhanced response from port "+QString::number(enhanced[0]);
|
||||
} else if(enhanced.size() > 1) {
|
||||
status += " with enhanced response from ports ";
|
||||
for(unsigned int k=0;k<enhanced.size();k++) {
|
||||
if(k == enhanced.size() - 1) {
|
||||
status += " and "+QString::number(enhanced[k]);
|
||||
} else if(k > 0) {
|
||||
status += ", ";
|
||||
}
|
||||
status += QString::number(enhanced[k]);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// check transmission calibration
|
||||
if(cal->hasTransmissionTracking(i, j)) {
|
||||
// we are calibrated
|
||||
status = "Calibrated";
|
||||
// check if we have isolation terms
|
||||
if(cal->hasIsolation(i, j)) {
|
||||
status += " with isolation measurement";
|
||||
}
|
||||
}
|
||||
}
|
||||
// add calibration status
|
||||
ui->table->setItem(row, 1, new QTableWidgetItem(status));
|
||||
}
|
||||
}
|
||||
ui->table->resizeColumnsToContents();
|
||||
}
|
||||
|
|
@ -1,51 +0,0 @@
|
|||
#ifndef CALIBRATIONVIEWDIALOG_H
|
||||
#define CALIBRATIONVIEWDIALOG_H
|
||||
|
||||
#include <QDialog>
|
||||
|
||||
#include "calibration.h"
|
||||
#include <QGraphicsScene>
|
||||
|
||||
namespace Ui {
|
||||
class CalibrationViewDialog;
|
||||
}
|
||||
|
||||
class CalibrationViewDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit CalibrationViewDialog(Calibration *cal, unsigned int ports, QWidget *parent = nullptr);
|
||||
~CalibrationViewDialog();
|
||||
|
||||
private slots:
|
||||
void populateScene();
|
||||
private:
|
||||
static constexpr int marginTop = 10;
|
||||
static constexpr int marginBottom = 10;
|
||||
static constexpr int marginLeft = 30;
|
||||
static constexpr int marginRight = 10;
|
||||
|
||||
static constexpr int portHeight = 170;
|
||||
static constexpr int portForwardYOffset = -50;
|
||||
static constexpr int portReverseYOffset = 50;
|
||||
static constexpr int boxSpacing = portReverseYOffset - portForwardYOffset;
|
||||
|
||||
static constexpr int portSize = 10;
|
||||
static constexpr int arrowLength = 15;
|
||||
static constexpr int arrowWidth = 10;
|
||||
static constexpr int junctionSize = 6;
|
||||
static constexpr int labelDistance = 6;
|
||||
|
||||
static constexpr int pathSpacing = 40;
|
||||
|
||||
static const QColor colorNoCal;
|
||||
static const QColor colorHasCal;
|
||||
|
||||
Ui::CalibrationViewDialog *ui;
|
||||
Calibration *cal;
|
||||
unsigned int ports;
|
||||
QGraphicsScene *scene;
|
||||
};
|
||||
|
||||
#endif // CALIBRATIONVIEWDIALOG_H
|
||||
|
|
@ -1,144 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>CalibrationViewDialog</class>
|
||||
<widget class="QDialog" name="CalibrationViewDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>1106</width>
|
||||
<height>665</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Calibration Error Term Model</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<item>
|
||||
<widget class="QSplitter" name="splitter">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
</property>
|
||||
<widget class="QWidget" name="">
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>View error term model when stimulus is at port</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSpinBox" name="port">
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>8</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string><html><head/><body><p><span style='color: darkgreen;'>Green</span> error terms have been calculated from calibration measurements.</p><p><span style='color: darkred;'>Red</span> error terms are at their default values (either 1 or 0).</p></body></html></string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGraphicsView" name="view">
|
||||
<property name="dragMode">
|
||||
<enum>QGraphicsView::DragMode::ScrollHandDrag</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string><html><head/><body><p>D: Directivity, R: Reflection tracking, S: Source match, L: Receiver match, T: Transmission tracking, I: Isolation</p></body></html></string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string>Which measurements are being corrected?</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QTableWidget" name="table">
|
||||
<property name="editTriggers">
|
||||
<set>QAbstractItemView::EditTrigger::NoEditTriggers</set>
|
||||
</property>
|
||||
<property name="selectionMode">
|
||||
<enum>QAbstractItemView::SelectionMode::NoSelection</enum>
|
||||
</property>
|
||||
<attribute name="horizontalHeaderStretchLastSection">
|
||||
<bool>true</bool>
|
||||
</attribute>
|
||||
<attribute name="verticalHeaderVisible">
|
||||
<bool>false</bool>
|
||||
</attribute>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::StandardButton::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>CalibrationViewDialog</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>374</x>
|
||||
<y>509</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>374</x>
|
||||
<y>265</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
||||
|
|
@ -16,47 +16,13 @@ using json = nlohmann::json;
|
|||
using namespace std;
|
||||
|
||||
Calkit::Calkit()
|
||||
: SCPINode("KIT"), scpi_std("STAndard")
|
||||
: SCPINode("KIT")
|
||||
{
|
||||
// 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
|
||||
|
|
@ -64,65 +30,19 @@ Calkit::Calkit()
|
|||
}
|
||||
toFile(params[0]);
|
||||
return SCPI::getResultName(SCPI::Result::Empty);
|
||||
}, nullptr, false));
|
||||
}, nullptr));
|
||||
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);
|
||||
}
|
||||
if(this->fromFile(params[0])) {
|
||||
try {
|
||||
*this = fromFile(params[0]);
|
||||
return SCPI::getResultName(SCPI::Result::True);
|
||||
} else {
|
||||
} catch (runtime_error &e) {
|
||||
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)
|
||||
|
|
@ -137,7 +57,6 @@ void Calkit::toFile(QString filename)
|
|||
file.open(filename.toStdString());
|
||||
file << setw(4) << toJSON() << endl;
|
||||
file.close();
|
||||
this->filename = filename;
|
||||
}
|
||||
|
||||
static QString readLine(ifstream &file) {
|
||||
|
|
@ -146,29 +65,27 @@ static QString readLine(ifstream &file) {
|
|||
return QString::fromStdString(line).simplified();
|
||||
}
|
||||
|
||||
bool Calkit::fromFile(QString filename)
|
||||
Calkit Calkit::fromFile(QString filename)
|
||||
{
|
||||
qDebug() << "Opening calkit from file" << filename;
|
||||
qDebug() << "Opening calkit to file" << filename;
|
||||
|
||||
auto c = Calkit();
|
||||
ifstream file;
|
||||
file.open(filename.toStdString());
|
||||
if(!file.is_open()) {
|
||||
qWarning() << "Unable to open file: " << filename;
|
||||
return false;
|
||||
throw runtime_error("Unable to open file");
|
||||
}
|
||||
|
||||
json j;
|
||||
try {
|
||||
file >> j;
|
||||
} catch (exception &e) {
|
||||
qWarning() << "JSON parsing error: " << QString(e.what());
|
||||
return false;
|
||||
throw runtime_error("JSON parsing error: " + string(e.what()));
|
||||
}
|
||||
clearStandards();
|
||||
this->filename = "";
|
||||
c.clearStandards();
|
||||
if(j.contains("standards")) {
|
||||
qDebug() << "new JSON format detected";
|
||||
fromJSON(j);
|
||||
c.fromJSON(j);
|
||||
} else {
|
||||
// older format is used
|
||||
struct {
|
||||
|
|
@ -216,7 +133,7 @@ bool Calkit::fromFile(QString filename)
|
|||
if(j.contains("SOLT")) {
|
||||
qDebug() << "old JSON format detected";
|
||||
// calkit file uses json format, parse
|
||||
Savable::parseJSON(j, descr);
|
||||
Savable::parseJSON(j, c.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},
|
||||
|
|
@ -369,7 +286,7 @@ bool Calkit::fromFile(QString filename)
|
|||
ts.fromFile(SOLT.open_m.file.toStdString());
|
||||
open_m->setMeasurement(ts, SOLT.open_m.Sparam);
|
||||
}
|
||||
addStandard(open_m);
|
||||
c.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) {
|
||||
|
|
@ -377,7 +294,7 @@ bool Calkit::fromFile(QString filename)
|
|||
ts.fromFile(SOLT.open_f.file.toStdString());
|
||||
open_m->setMeasurement(ts, SOLT.open_f.Sparam);
|
||||
}
|
||||
addStandard(open_f);
|
||||
c.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);
|
||||
|
|
@ -386,7 +303,7 @@ bool Calkit::fromFile(QString filename)
|
|||
ts.fromFile(SOLT.short_m.file.toStdString());
|
||||
short_m->setMeasurement(ts, SOLT.short_m.Sparam);
|
||||
}
|
||||
addStandard(short_m);
|
||||
c.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) {
|
||||
|
|
@ -394,7 +311,7 @@ bool Calkit::fromFile(QString filename)
|
|||
ts.fromFile(SOLT.short_f.file.toStdString());
|
||||
short_m->setMeasurement(ts, SOLT.short_f.Sparam);
|
||||
}
|
||||
addStandard(short_f);
|
||||
c.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);
|
||||
|
|
@ -403,7 +320,7 @@ bool Calkit::fromFile(QString filename)
|
|||
ts.fromFile(SOLT.load_m.file.toStdString());
|
||||
load_m->setMeasurement(ts, SOLT.load_m.Sparam);
|
||||
}
|
||||
addStandard(load_m);
|
||||
c.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) {
|
||||
|
|
@ -411,7 +328,7 @@ bool Calkit::fromFile(QString filename)
|
|||
ts.fromFile(SOLT.load_f.file.toStdString());
|
||||
load_m->setMeasurement(ts, SOLT.load_f.Sparam);
|
||||
}
|
||||
addStandard(load_f);
|
||||
c.addStandard(load_f);
|
||||
}
|
||||
|
||||
auto through = new CalStandard::Through("Default standard", SOLT.Through.Z0, SOLT.Through.delay, SOLT.Through.loss);
|
||||
|
|
@ -420,7 +337,7 @@ bool Calkit::fromFile(QString filename)
|
|||
ts.fromFile(SOLT.Through.file.toStdString());
|
||||
through->setMeasurement(ts, SOLT.Through.Sparam1, SOLT.Through.Sparam2);
|
||||
}
|
||||
addStandard(through);
|
||||
c.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"
|
||||
|
|
@ -428,10 +345,8 @@ bool Calkit::fromFile(QString filename)
|
|||
}
|
||||
|
||||
file.close();
|
||||
this->filename = filename;
|
||||
updateSCPINames();
|
||||
|
||||
return true;
|
||||
return c;
|
||||
}
|
||||
|
||||
void Calkit::edit(std::function<void (void)> updateCal)
|
||||
|
|
@ -449,24 +364,10 @@ void Calkit::edit(std::function<void (void)> updateCal)
|
|||
|
||||
void Calkit::clearStandards()
|
||||
{
|
||||
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++;
|
||||
for(auto s : standards) {
|
||||
delete s;
|
||||
}
|
||||
standards.clear();
|
||||
}
|
||||
|
||||
std::vector<CalStandard::Virtual *> Calkit::getStandards() const
|
||||
|
|
@ -490,14 +391,6 @@ 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()
|
||||
|
|
@ -518,7 +411,6 @@ 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")) {
|
||||
|
|
@ -534,7 +426,6 @@ void Calkit::fromJSON(nlohmann::json j)
|
|||
s->fromJSON(js["params"]);
|
||||
addStandard(s);
|
||||
}
|
||||
updateSCPINames();
|
||||
}
|
||||
|
||||
void Calkit::setIdealDefault()
|
||||
|
|
@ -546,5 +437,4 @@ 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,8 +19,15 @@ class Calkit : public Savable, public SCPINode
|
|||
friend class LibreCALDialog;
|
||||
public:
|
||||
Calkit();
|
||||
Calkit(const Calkit&) = delete;
|
||||
Calkit& operator= (const Calkit&) = delete;
|
||||
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;
|
||||
}
|
||||
|
||||
class SOLT {
|
||||
public:
|
||||
|
|
@ -37,12 +44,11 @@ public:
|
|||
};
|
||||
|
||||
void toFile(QString filename);
|
||||
bool fromFile(QString filename);
|
||||
static Calkit 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;
|
||||
|
|
@ -51,10 +57,7 @@ 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,7 +27,8 @@ CalkitDialog::CalkitDialog(Calkit &c, QWidget *parent) :
|
|||
connect(ui->bDelete, &QPushButton::clicked, [=](){
|
||||
auto row = ui->list->currentRow();
|
||||
if(row >= 0) {
|
||||
kit.removeStandard(kit.standards[row]);
|
||||
delete kit.standards[row];
|
||||
kit.standards.erase(kit.standards.begin() + row);
|
||||
updateStandardList();
|
||||
}
|
||||
});
|
||||
|
|
@ -38,7 +39,6 @@ CalkitDialog::CalkitDialog(Calkit &c, QWidget *parent) :
|
|||
swap(kit.standards[row], kit.standards[row-1]);
|
||||
ui->list->setCurrentRow(row-1);
|
||||
updateStandardList();
|
||||
kit.updateSCPINames();
|
||||
}
|
||||
});
|
||||
|
||||
|
|
@ -48,7 +48,6 @@ CalkitDialog::CalkitDialog(Calkit &c, QWidget *parent) :
|
|||
swap(kit.standards[row], kit.standards[row+1]);
|
||||
ui->list->setCurrentRow(row+1);
|
||||
updateStandardList();
|
||||
kit.updateSCPINames();
|
||||
}
|
||||
});
|
||||
|
||||
|
|
@ -90,11 +89,10 @@ CalkitDialog::CalkitDialog(Calkit &c, QWidget *parent) :
|
|||
accept();
|
||||
});
|
||||
connect(ui->buttonBox->button(QDialogButtonBox::Open), &QPushButton::clicked, [=](){
|
||||
auto filename = QFileDialog::getOpenFileName(this, "Open calibration kit coefficients", Preferences::getInstance().UISettings.Paths.calkit, "Calibration kit files (*.calkit)", nullptr, Preferences::QFileDialogOptions());
|
||||
auto filename = QFileDialog::getOpenFileName(this, "Open calibration kit coefficients", "", "Calibration kit files (*.calkit)", nullptr, Preferences::QFileDialogOptions());
|
||||
if(filename.length() > 0) {
|
||||
Preferences::getInstance().UISettings.Paths.calkit = QFileInfo(filename).path();
|
||||
try {
|
||||
kit.fromFile(filename);
|
||||
kit = Calkit::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();
|
||||
|
|
@ -105,9 +103,8 @@ CalkitDialog::CalkitDialog(Calkit &c, QWidget *parent) :
|
|||
});
|
||||
|
||||
connect(ui->buttonBox->button(QDialogButtonBox::Save), &QPushButton::clicked, [=](){
|
||||
auto filename = QFileDialog::getSaveFileName(this, "Save calibration kit coefficients", Preferences::getInstance().UISettings.Paths.calkit, "Calibration kit files (*.calkit)", nullptr, Preferences::QFileDialogOptions());
|
||||
auto filename = QFileDialog::getSaveFileName(this, "Save calibration kit coefficients", "", "Calibration kit files (*.calkit)", nullptr, Preferences::QFileDialogOptions());
|
||||
if(filename.length() > 0) {
|
||||
Preferences::getInstance().UISettings.Paths.calkit = QFileInfo(filename).path();
|
||||
parseEntries();
|
||||
kit.toFile(filename);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,7 +12,6 @@ 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())
|
||||
|
|
@ -61,7 +60,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).compare(s, Qt::CaseInsensitive) == 0) {
|
||||
if(TypeToString((Type) i) == s) {
|
||||
return (Type) i;
|
||||
}
|
||||
}
|
||||
|
|
@ -102,11 +101,6 @@ void Virtual::setName(const QString &value)
|
|||
name = value;
|
||||
}
|
||||
|
||||
void Virtual::setupSCPI()
|
||||
{
|
||||
addStringParameter("NAME", name);
|
||||
}
|
||||
|
||||
void OnePort::setMeasurement(const Touchstone &ts, int port)
|
||||
{
|
||||
if(!touchstone) {
|
||||
|
|
@ -148,35 +142,10 @@ 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)
|
||||
|
|
@ -294,23 +263,10 @@ 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)
|
||||
|
|
@ -422,25 +378,12 @@ 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)
|
||||
|
|
@ -576,18 +519,6 @@ 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) {
|
||||
|
|
@ -629,37 +560,11 @@ 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)
|
||||
|
|
@ -770,18 +675,9 @@ 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)
|
||||
|
|
@ -828,17 +724,10 @@ 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)
|
||||
|
|
@ -911,10 +800,3 @@ 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,7 +4,6 @@
|
|||
#include "savable.h"
|
||||
#include "touchstone.h"
|
||||
#include "Tools/parameters.h"
|
||||
#include "scpi.h"
|
||||
|
||||
#include <complex>
|
||||
#include <functional>
|
||||
|
|
@ -12,7 +11,7 @@
|
|||
namespace CalStandard
|
||||
{
|
||||
|
||||
class Virtual : public QObject, public Savable, public SCPINode
|
||||
class Virtual : public QObject, public Savable
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
|
|
@ -54,7 +53,6 @@ signals:
|
|||
void deleted();
|
||||
|
||||
protected:
|
||||
void setupSCPI();
|
||||
QString name;
|
||||
double minFreq;
|
||||
double maxFreq;
|
||||
|
|
@ -77,7 +75,6 @@ public:
|
|||
virtual void fromJSON(nlohmann::json j) override;
|
||||
|
||||
protected:
|
||||
void setupSCPI();
|
||||
Touchstone *touchstone;
|
||||
};
|
||||
|
||||
|
|
@ -88,7 +85,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){setupSCPI();}
|
||||
: OnePort(name), Z0(Z0), delay(delay), loss(loss), C0(C0), C1(C1), C2(C2), C3(C3){}
|
||||
|
||||
virtual std::complex<double> toS11(double freq) override;
|
||||
virtual void edit(std::function<void(void)> finishedCallback = nullptr) override;
|
||||
|
|
@ -96,7 +93,6 @@ public:
|
|||
virtual nlohmann::json toJSON() override;
|
||||
virtual void fromJSON(nlohmann::json j) override;
|
||||
private:
|
||||
void setupSCPI();
|
||||
double Z0, delay, loss, C0, C1, C2, C3;
|
||||
};
|
||||
|
||||
|
|
@ -105,7 +101,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){setupSCPI();}
|
||||
: OnePort(name), Z0(Z0), delay(delay), loss(loss), L0(L0), L1(L1), L2(L2), L3(L3){}
|
||||
|
||||
virtual std::complex<double> toS11(double freq) override;
|
||||
virtual void edit(std::function<void(void)> finishedCallback = nullptr) override;
|
||||
|
|
@ -113,7 +109,6 @@ public:
|
|||
virtual nlohmann::json toJSON() override;
|
||||
virtual void fromJSON(nlohmann::json j) override;
|
||||
private:
|
||||
void setupSCPI();
|
||||
double Z0, delay, loss, L0, L1, L2, L3;
|
||||
};
|
||||
|
||||
|
|
@ -122,7 +117,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){setupSCPI();}
|
||||
: OnePort(name), Z0(Z0), delay(delay), loss(loss), resistance(resistance), Cparallel(Cparallel), Lseries(Lseries), Cfirst(Cfirst){}
|
||||
|
||||
virtual std::complex<double> toS11(double freq) override;
|
||||
virtual void edit(std::function<void(void)> finishedCallback = nullptr) override;
|
||||
|
|
@ -130,7 +125,6 @@ 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;
|
||||
};
|
||||
|
|
@ -150,7 +144,6 @@ public:
|
|||
bool getIsShort() const;
|
||||
|
||||
private:
|
||||
void setupSCPI();
|
||||
bool isShort;
|
||||
};
|
||||
|
||||
|
|
@ -171,7 +164,6 @@ public:
|
|||
virtual void fromJSON(nlohmann::json j) override;
|
||||
|
||||
protected:
|
||||
void setupSCPI();
|
||||
Touchstone *touchstone;
|
||||
};
|
||||
|
||||
|
|
@ -180,7 +172,7 @@ class Through : public TwoPort
|
|||
public:
|
||||
Through();
|
||||
Through(QString name, double Z0, double delay, double loss)
|
||||
: TwoPort(name), Z0(Z0), delay(delay), loss(loss){setupSCPI();}
|
||||
: TwoPort(name), Z0(Z0), delay(delay), loss(loss){}
|
||||
|
||||
virtual Sparam toSparam(double freq) override;
|
||||
virtual void edit(std::function<void(void)> finishedCallback = nullptr) override;
|
||||
|
|
@ -188,7 +180,6 @@ public:
|
|||
virtual nlohmann::json toJSON() override;
|
||||
virtual void fromJSON(nlohmann::json j) override;
|
||||
private:
|
||||
void setupSCPI();
|
||||
double Z0, delay, loss;
|
||||
};
|
||||
|
||||
|
|
@ -197,7 +188,7 @@ class Line : public TwoPort
|
|||
public:
|
||||
Line();
|
||||
Line(QString name, double Z0, double delay)
|
||||
: TwoPort(name), Z0(Z0), delay(delay){setupSCPI();}
|
||||
: TwoPort(name), Z0(Z0), delay(delay){}
|
||||
|
||||
virtual Sparam toSparam(double freq) override;
|
||||
virtual void edit(std::function<void(void)> finishedCallback = nullptr) override;
|
||||
|
|
@ -206,7 +197,6 @@ public:
|
|||
virtual void fromJSON(nlohmann::json j) override;
|
||||
private:
|
||||
void setDelay(double delay);
|
||||
void setupSCPI();
|
||||
double Z0, delay;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ ManualCalibrationDialog::ManualCalibrationDialog(const TraceModel &model, Calibr
|
|||
ui(new Ui::ManualCalibrationDialog)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
auto traceSelector = new SparamTraceSelector(model, cal->getCaltype().usedPorts, true);
|
||||
auto traceSelector = new SparamTraceSelector(model, cal->getCaltype().usedPorts);
|
||||
ui->verticalLayout->insertWidget(1, traceSelector, 1.0);
|
||||
ui->buttonBox->setEnabled(false);
|
||||
connect(traceSelector, &SparamTraceSelector::selectionValid, ui->buttonBox, &QDialogButtonBox::setEnabled);
|
||||
|
|
|
|||
|
|
@ -64,9 +64,8 @@ void CSVImport::selectTrace(unsigned int index)
|
|||
|
||||
void CSVImport::on_browse_clicked()
|
||||
{
|
||||
auto filename = QFileDialog::getOpenFileName(nullptr, "Open measurement file", Preferences::getInstance().UISettings.Paths.data, "CSV files (*.csv)", nullptr, Preferences::QFileDialogOptions());
|
||||
auto filename = QFileDialog::getOpenFileName(nullptr, "Open measurement file", "", "CSV files (*.csv)", nullptr, Preferences::QFileDialogOptions());
|
||||
if (filename.length() > 0) {
|
||||
Preferences::getInstance().UISettings.Paths.data = QFileInfo(filename).path();
|
||||
ui->file->setText(filename);
|
||||
evaluateFile();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@ bool SIUnitEdit::eventFilter(QObject *, QEvent *event)
|
|||
clearFocus();
|
||||
return true;
|
||||
}
|
||||
if(key == Qt::Key_Return || key == Qt::Key_Enter) {
|
||||
if(key == Qt::Key_Return) {
|
||||
// use new value without prefix
|
||||
parseNewValue(1.0);
|
||||
continueEditing();
|
||||
|
|
|
|||
|
|
@ -112,9 +112,8 @@ void TouchstoneImport::setFile(QString filename)
|
|||
|
||||
void TouchstoneImport::on_browse_clicked()
|
||||
{
|
||||
auto filename = QFileDialog::getOpenFileName(nullptr, "Open measurement file", Preferences::getInstance().UISettings.Paths.data, "Touchstone files (*.s1p *.s2p *.s3p *.s4p)", nullptr, Preferences::QFileDialogOptions());
|
||||
auto filename = QFileDialog::getOpenFileName(nullptr, "Open measurement file", "", "Touchstone files (*.s1p *.s2p *.s3p *.s4p)", nullptr, Preferences::QFileDialogOptions());
|
||||
if (filename.length() > 0) {
|
||||
Preferences::getInstance().UISettings.Paths.data = QFileInfo(filename).path();
|
||||
ui->file->setText(filename);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,16 +0,0 @@
|
|||
#include "harogicb60.h"
|
||||
|
||||
HarogicB60::HarogicB60()
|
||||
{
|
||||
validUSBIDs.clear();
|
||||
validUSBIDs.append({0x367F, 0x0200, "B60"});
|
||||
|
||||
for(auto &s : specificSettings) {
|
||||
s.name.replace("LibreVNAUSBDriver", "HarogicB60Driver");
|
||||
}
|
||||
}
|
||||
|
||||
QString HarogicB60::getDriverName()
|
||||
{
|
||||
return "Harogic B60";
|
||||
}
|
||||
|
|
@ -1,19 +0,0 @@
|
|||
#ifndef HAROGICB60_H
|
||||
#define HAROGICB60_H
|
||||
|
||||
#include "../LibreVNA/librevnausbdriver.h"
|
||||
|
||||
class HarogicB60 : public LibreVNAUSBDriver
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
HarogicB60();
|
||||
|
||||
/**
|
||||
* @brief Returns the driver name. It must be unique across all implemented drivers and is used to identify the driver
|
||||
* @return driver name
|
||||
*/
|
||||
virtual QString getDriverName() override;
|
||||
};
|
||||
|
||||
#endif // HAROGICB60_H
|
||||
|
|
@ -44,12 +44,11 @@ AmplitudeCalDialog::AmplitudeCalDialog(LibreVNADriver *dev, QWidget *parent) :
|
|||
connect(ui->saveFile, &QPushButton::clicked, [=](){
|
||||
auto fileEnding = pointType() == Protocol::PacketType::SourceCalPoint ? ".srccal" : ".recvcal";
|
||||
auto fileFilter = QString("Amplitude calibration files (*")+fileEnding+")";
|
||||
auto filename = QFileDialog::getSaveFileName(nullptr, "Save calibration data", Preferences::getInstance().UISettings.Paths.vnacaldata, fileFilter, nullptr, Preferences::QFileDialogOptions());
|
||||
auto filename = QFileDialog::getSaveFileName(nullptr, "Save calibration data", "", fileFilter, nullptr, Preferences::QFileDialogOptions());
|
||||
if(filename.isEmpty()) {
|
||||
// aborted selection
|
||||
return;
|
||||
}
|
||||
Preferences::getInstance().UISettings.Paths.vnacaldata = QFileInfo(filename).path();
|
||||
if(!filename.endsWith(fileEnding)) {
|
||||
filename.append(fileEnding);
|
||||
}
|
||||
|
|
@ -71,12 +70,11 @@ AmplitudeCalDialog::AmplitudeCalDialog(LibreVNADriver *dev, QWidget *parent) :
|
|||
connect(ui->loadFile, &QPushButton::clicked, [=](){
|
||||
auto fileEnding = pointType() == Protocol::PacketType::SourceCalPoint ? ".srccal" : ".recvcal";
|
||||
auto fileFilter = QString("Amplitude calibration files (*")+fileEnding+")";
|
||||
auto filename = QFileDialog::getOpenFileName(nullptr, "Save calibration data", Preferences::getInstance().UISettings.Paths.vnacaldata, fileFilter, nullptr, Preferences::QFileDialogOptions());
|
||||
auto filename = QFileDialog::getOpenFileName(nullptr, "Save calibration data", "", fileFilter, nullptr, Preferences::QFileDialogOptions());
|
||||
if(filename.isEmpty()) {
|
||||
// aborted selection
|
||||
return;
|
||||
}
|
||||
Preferences::getInstance().UISettings.Paths.vnacaldata = QFileInfo(filename).path();
|
||||
ifstream file;
|
||||
file.open(filename.toStdString());
|
||||
if(!file.is_open()) {
|
||||
|
|
|
|||
|
|
@ -1,9 +1,6 @@
|
|||
#include "deviceconfigurationdialogv1.h"
|
||||
#include "ui_deviceconfigurationdialogv1.h"
|
||||
|
||||
#include <QPushButton>
|
||||
#include "CustomWidgets/informationbox.h"
|
||||
|
||||
DeviceConfigurationDialogV1::DeviceConfigurationDialogV1(LibreVNADriver &dev, QWidget *parent) :
|
||||
QDialog(parent),
|
||||
ui(new Ui::DeviceConfigurationDialogV1),
|
||||
|
|
@ -59,10 +56,6 @@ DeviceConfigurationDialogV1::DeviceConfigurationDialogV1(LibreVNADriver &dev, QW
|
|||
connect(ui->buttonBox, &QDialogButtonBox::rejected, this, [=](){
|
||||
reject();
|
||||
});
|
||||
connect(ui->buttonBox->button(QDialogButtonBox::RestoreDefaults), &QPushButton::clicked, this, [=](){
|
||||
resetDevice();
|
||||
this->dev.sendWithoutPayload(Protocol::PacketType::RequestDeviceConfiguration);
|
||||
});
|
||||
}
|
||||
|
||||
DeviceConfigurationDialogV1::~DeviceConfigurationDialogV1()
|
||||
|
|
@ -91,12 +84,3 @@ void DeviceConfigurationDialogV1::updateDevice()
|
|||
p.deviceConfig.V1.PLLSettlingDelay = ui->PLLSettlingDelay->value();
|
||||
dev.SendPacket(p);
|
||||
}
|
||||
|
||||
void DeviceConfigurationDialogV1::resetDevice()
|
||||
{
|
||||
dev.sendWithoutPayload(Protocol::PacketType::ResetDeviceConfiguration, [=](LibreVNADriver::TransmissionResult res){
|
||||
if(res != LibreVNADriver::TransmissionResult::Ack) {
|
||||
InformationBox::ShowError("Error", "Failed to reset device configuration");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,7 +20,6 @@ public:
|
|||
private:
|
||||
void updateGUI(const Protocol::DeviceConfig &c);
|
||||
void updateDevice();
|
||||
void resetDevice();
|
||||
|
||||
Ui::DeviceConfigurationDialogV1 *ui;
|
||||
LibreVNADriver &dev;
|
||||
|
|
|
|||
|
|
@ -164,7 +164,7 @@
|
|||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::StandardButton::Cancel|QDialogButtonBox::StandardButton::Ok|QDialogButtonBox::StandardButton::RestoreDefaults</set>
|
||||
<set>QDialogButtonBox::StandardButton::Cancel|QDialogButtonBox::StandardButton::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
|
|
|||
|
|
@ -1,72 +0,0 @@
|
|||
#include "deviceconfigurationdialogvd0.h"
|
||||
#include "ui_deviceconfigurationdialogvd0.h"
|
||||
|
||||
DeviceConfigurationDialogVD0::DeviceConfigurationDialogVD0(LibreVNADriver &dev, QWidget *parent) :
|
||||
QDialog(parent),
|
||||
ui(new Ui::DeviceConfigurationDialogVD0),
|
||||
dev(dev)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
setAttribute(Qt::WA_DeleteOnClose);
|
||||
|
||||
emit dev.acquireControl();
|
||||
|
||||
auto updateIF = [=]() {
|
||||
auto ADCrate = ui->ADCRate->value();
|
||||
ui->IF->setValue(ADCrate * ui->ADCphaseInc->value() / 65536);
|
||||
};
|
||||
|
||||
connect(ui->ADCRate, &SIUnitEdit::valueChanged, this, updateIF);
|
||||
connect(ui->ADCphaseInc, qOverload<int>(&QSpinBox::valueChanged), this, updateIF);
|
||||
|
||||
ui->ADCRate->setUnit("Hz");
|
||||
ui->ADCRate->setPrefixes(" kM");
|
||||
ui->ADCRate->setPrecision(5);
|
||||
ui->IF->setUnit("Hz");
|
||||
ui->IF->setPrefixes(" kM");
|
||||
ui->IF->setPrecision(5);
|
||||
|
||||
ui->ADCRate->setValue(1496000);
|
||||
ui->ADCphaseInc->setValue(10240);
|
||||
|
||||
updateIF();
|
||||
|
||||
connect(&dev, &LibreVNADriver::receivedPacket, this, [=](const Protocol::PacketInfo &p) {
|
||||
if(p.type == Protocol::PacketType::DeviceConfiguration) {
|
||||
updateGUI(p.deviceConfig);
|
||||
}
|
||||
});
|
||||
|
||||
dev.sendWithoutPayload(Protocol::PacketType::RequestDeviceConfiguration);
|
||||
|
||||
connect(ui->buttonBox, &QDialogButtonBox::accepted, this, [=](){
|
||||
updateDevice();
|
||||
accept();
|
||||
});
|
||||
connect(ui->buttonBox, &QDialogButtonBox::rejected, this, [=](){
|
||||
reject();
|
||||
});
|
||||
}
|
||||
|
||||
DeviceConfigurationDialogVD0::~DeviceConfigurationDialogVD0()
|
||||
{
|
||||
dev.releaseControl();
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void DeviceConfigurationDialogVD0::updateGUI(const Protocol::DeviceConfig &c)
|
||||
{
|
||||
ui->ADCRate->setValue(c.VD0.ADCrate);
|
||||
ui->ADCphaseInc->setValue(c.VD0.DFTphaseInc);
|
||||
ui->PLLSettlingDelay->setValue(c.VD0.PLLSettlingDelay);
|
||||
}
|
||||
|
||||
void DeviceConfigurationDialogVD0::updateDevice()
|
||||
{
|
||||
Protocol::PacketInfo p;
|
||||
p.type = Protocol::PacketType::DeviceConfiguration;
|
||||
p.deviceConfig.VD0.ADCrate = ui->ADCRate->value();
|
||||
p.deviceConfig.VD0.DFTphaseInc = ui->ADCphaseInc->value();
|
||||
p.deviceConfig.VD0.PLLSettlingDelay = ui->PLLSettlingDelay->value();
|
||||
dev.SendPacket(p);
|
||||
}
|
||||
|
|
@ -1,28 +0,0 @@
|
|||
#ifndef DEVICECONFIGURATIONDIALOGVD0_H
|
||||
#define DEVICECONFIGURATIONDIALOGVD0_H
|
||||
|
||||
#include <QDialog>
|
||||
|
||||
#include "librevnadriver.h"
|
||||
|
||||
namespace Ui {
|
||||
class DeviceConfigurationDialogVD0;
|
||||
}
|
||||
|
||||
class DeviceConfigurationDialogVD0 : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit DeviceConfigurationDialogVD0(LibreVNADriver &dev, QWidget *parent = nullptr);
|
||||
~DeviceConfigurationDialogVD0();
|
||||
|
||||
private:
|
||||
void updateGUI(const Protocol::DeviceConfig &c);
|
||||
void updateDevice();
|
||||
|
||||
Ui::DeviceConfigurationDialogVD0 *ui;
|
||||
LibreVNADriver &dev;
|
||||
};
|
||||
|
||||
#endif // DEVICECONFIGURATIONDIALOGVD0_H
|
||||
|
|
@ -1,138 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>DeviceConfigurationDialogVD0</class>
|
||||
<widget class="QDialog" name="DeviceConfigurationDialogVD0">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>421</width>
|
||||
<height>314</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Device Configuration</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>This dialog contains advanced system settings. It is recommended to leave them at default values unless you know what you are doing.</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_15">
|
||||
<property name="title">
|
||||
<string>IF and ADC frequencies</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_5">
|
||||
<item>
|
||||
<layout class="QFormLayout" name="formLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_31">
|
||||
<property name="text">
|
||||
<string>ADC sample rate:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="SIUnitEdit" name="ADCRate">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_32">
|
||||
<property name="text">
|
||||
<string>DFT Phase increment:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QSpinBox" name="ADCphaseInc">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Phase increment per ADC sample. Together with the ADC sample rate this determines the frequency of the second IF</p></body></html></string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>65535</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>10240</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_33">
|
||||
<property name="text">
|
||||
<string>IF:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="SIUnitEdit" name="IF">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox">
|
||||
<property name="title">
|
||||
<string>Other settings</string>
|
||||
</property>
|
||||
<layout class="QFormLayout" name="formLayout_2">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>PLL settling delay [us]:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QSpinBox" name="PLLSettlingDelay">
|
||||
<property name="minimum">
|
||||
<number>10</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>255</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>60</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::StandardButton::Cancel|QDialogButtonBox::StandardButton::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>SIUnitEdit</class>
|
||||
<extends>QLineEdit</extends>
|
||||
<header>CustomWidgets/siunitedit.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
|
|
@ -29,12 +29,11 @@ DevicePacketLogView::DevicePacketLogView(QWidget *parent) :
|
|||
updateTree();
|
||||
});
|
||||
connect(ui->buttonBox->button(QDialogButtonBox::Save), &QPushButton::clicked, [=](){
|
||||
QString filename = QFileDialog::getSaveFileName(nullptr, "Save LibreVNA log data", Preferences::getInstance().UISettings.Paths.packetlog, "LibreVNA log files (*.vnalog)", nullptr, Preferences::QFileDialogOptions());
|
||||
QString filename = QFileDialog::getSaveFileName(nullptr, "Load LibreVNA log data", "", "LibreVNA log files (*.vnalog)", nullptr, Preferences::QFileDialogOptions());
|
||||
if(filename.isEmpty()) {
|
||||
// aborted selection
|
||||
return;
|
||||
}
|
||||
Preferences::getInstance().UISettings.Paths.packetlog = QFileInfo(filename).path();
|
||||
if(!filename.endsWith(".vnalog")) {
|
||||
filename.append(".vnalog");
|
||||
}
|
||||
|
|
@ -44,12 +43,11 @@ DevicePacketLogView::DevicePacketLogView(QWidget *parent) :
|
|||
file.close();
|
||||
});
|
||||
connect(ui->buttonBox->button(QDialogButtonBox::Open), &QPushButton::clicked, [=](){
|
||||
QString filename = QFileDialog::getOpenFileName(nullptr, "Load LibreVNA log data", Preferences::getInstance().UISettings.Paths.packetlog, "LibreVNA log files (*.vnalog)", nullptr, Preferences::QFileDialogOptions());
|
||||
QString filename = QFileDialog::getOpenFileName(nullptr, "Load LibreVNA log data", "", "LibreVNA log files (*.vnalog)", nullptr, Preferences::QFileDialogOptions());
|
||||
if(filename.isEmpty()) {
|
||||
// aborted selection
|
||||
return;
|
||||
}
|
||||
Preferences::getInstance().UISettings.Paths.packetlog = QFileInfo(filename).path();
|
||||
ifstream file;
|
||||
file.open(filename.toStdString());
|
||||
if(!file.is_open()) {
|
||||
|
|
@ -219,21 +217,6 @@ void DevicePacketLogView::addEntry(const DevicePacketLog::LogEntry &e)
|
|||
addInteger(VFE, "MCU temperature", sFE.temp_MCU);
|
||||
addDouble(VFE, "eCal temperature", (double) sFE.temp_eCal / 100.0);
|
||||
addDouble(VFE, "eCal heater power", (double) sFE.power_heater / 1000.0);
|
||||
|
||||
auto sD0 = e.p->status.VD0;
|
||||
auto VD0 = new QTreeWidgetItem();
|
||||
VD0->setData(2, Qt::DisplayRole, "VD0");
|
||||
item->addChild(VD0);
|
||||
addBool(VD0, "External reference available", sD0.extRefAvailable);
|
||||
addBool(VD0, "External reference in use", sD0.extRefInUse);
|
||||
addBool(VD0, "FPGA configured", sD0.FPGA_configured);
|
||||
addBool(VD0, "Source locked", sD0.source_locked);
|
||||
addBool(VD0, "LO locked", sD0.LO_locked);
|
||||
addBool(VD0, "ADC overload", sD0.ADC_overload);
|
||||
addBool(VD0, "Unlevel", sD0.unlevel);
|
||||
addInteger(VD0, "MCU temperature", sD0.temp_MCU);
|
||||
addInteger(VD0, "Supply voltage", sD0.supply_voltage);
|
||||
addInteger(VD0, "Supply current", sD0.supply_current);
|
||||
}
|
||||
break;
|
||||
case Protocol::PacketType::DeviceInfo: {
|
||||
|
|
@ -326,32 +309,6 @@ void DevicePacketLogView::addEntry(const DevicePacketLog::LogEntry &e)
|
|||
addEnum(VFE, "Reference gain", s.VFE.RefGain, {"1 V/V", "10 V/V", "20 V/V", "30 V/V", "40 V/V", "60 V/V", "80 V/V", "120 V/V", "157 V/V", "0.25 V/V"});
|
||||
addEnum(VFE, "eCal state", s.VFE.eCal_state, {"Port", "Open", "Short", "Load"});
|
||||
addDouble(VFE, "eCal target temperature", (double) s.VFE.eCal_target / 100.0);
|
||||
|
||||
auto VD0 = new QTreeWidgetItem();
|
||||
VD0->setData(2, Qt::DisplayRole, "VD0");
|
||||
item->addChild(VD0);
|
||||
addBool(VD0, "High Source chip enable", s.VD0.SourceHighCE);
|
||||
addInteger(VD0, "High Source power", s.VD0.SourceHighPower);
|
||||
addEnum(VD0, "High Source lowpass", s.VD0.SourceHighLowpass, {"947 MHz", "1880 MHz", "3550 MHz", "None"});
|
||||
addDouble(VD0, "High Source frequency", s.VD0.SourceHighFrequency);
|
||||
addBool(VD0, "Low Source enable", s.VD0.SourceLowEN);
|
||||
addEnum(VD0, "Low Source power", s.VD0.SourceLowPower, {"2 mA", "4 mA", "6 mA", "8 mA"});
|
||||
addDouble(VD0, "Low Source frequency", s.VD0.SourceLowFrequency);
|
||||
addDouble(VD0, "Attenuator", s.VD0.attenuator * 0.25);
|
||||
addEnum(VD0, "Source band selection", s.VD0.SourceHighband, {"Low Source", "High Source"});
|
||||
addEnum(VD0, "Port switch", s.VD0.PortSwitch, {"Port 1", "Port 2"});
|
||||
addBool(VD0, "High LO chip enable", s.VD0.LOHighCE);
|
||||
addDouble(VD0, "High LO frequency", s.VD0.LOHighFrequency);
|
||||
addInteger(VD0, "High LO power", s.VD0.LOHighPower);
|
||||
addBool(VD0, "Low LO enable", s.VD0.LOLowEN);
|
||||
addEnum(VD0, "Low LO power", s.VD0.LOLowPower, {"2 mA", "4 mA", "6 mA", "8 mA"});
|
||||
addDouble(VD0, "Low LO frequency", s.VD0.LOLowFrequency);
|
||||
addEnum(VD0, "LO band selection", s.VD0.LOHighband, {"Low Source", "High Source"});
|
||||
addBool(VD0, "Port 1 receiver enable", s.VD0.Port1EN);
|
||||
addBool(VD0, "Port 2 receiver enable", s.VD0.Port2EN);
|
||||
addBool(VD0, "Reference receiver enable", s.VD0.RefEN);
|
||||
addInteger(VD0, "Samples", s.VD0.Samples);
|
||||
addEnum(VD0, "Window type", s.VD0.WindowType, {"None", "Kaiser", "Hann", "Flattop"});
|
||||
}
|
||||
break;
|
||||
case Protocol::PacketType::ManualStatus: {
|
||||
|
|
@ -405,24 +362,6 @@ void DevicePacketLogView::addEntry(const DevicePacketLog::LogEntry &e)
|
|||
addBool(VFE, "LO locked", s.VFE.LO_locked);
|
||||
addDouble(VFE, "eCal temperature", (double) s.VFE.temp_eCal / 100.0);
|
||||
addDouble(VFE, "eCal heater power", (double) s.VFE.power_heater / 1000.0);
|
||||
|
||||
auto VD0 = new QTreeWidgetItem();
|
||||
VD0->setData(2, Qt::DisplayRole, "VD0");
|
||||
item->addChild(VD0);
|
||||
addInteger(VD0, "ADC port 1 minimum", s.VD0.port1min);
|
||||
addInteger(VD0, "ADC port 1 maximum", s.VD0.port1max);
|
||||
addInteger(VD0, "ADC port 2 minimum", s.VD0.port2min);
|
||||
addInteger(VD0, "ADC port 2 maximum", s.VD0.port2max);
|
||||
addInteger(VD0, "ADC reference minimum", s.VD0.refmin);
|
||||
addInteger(VD0, "ADC reference maximum", s.VD0.refmax);
|
||||
addDouble(VD0, "Port 1 real", s.VD0.port1real);
|
||||
addDouble(VD0, "Port 1 imaginary", s.VD0.port1imag);
|
||||
addDouble(VD0, "Port 2 real", s.VD0.port2real);
|
||||
addDouble(VD0, "Port 2 imaginary", s.VD0.port2imag);
|
||||
addDouble(VD0, "Reference real", s.VD0.refreal);
|
||||
addDouble(VD0, "Reference imaginary", s.VD0.refimag);
|
||||
addBool(VD0, "Source locked", s.VD0.source_locked);
|
||||
addBool(VD0, "LO1 locked", s.VD0.LO_locked);
|
||||
}
|
||||
break;
|
||||
case Protocol::PacketType::SpectrumAnalyzerSettings: {
|
||||
|
|
@ -512,7 +451,6 @@ void DevicePacketLogView::addEntry(const DevicePacketLog::LogEntry &e)
|
|||
addDouble(V1, "1.IF", s1.IF1, "Hz");
|
||||
addInteger(V1, "ADC prescaler", s1.ADCprescaler);
|
||||
addInteger(V1, "DFT phase increment", s1.DFTphaseInc);
|
||||
addInteger(V1, "PLL settling delay", s1.PLLSettlingDelay);
|
||||
|
||||
auto sFF = e.p->deviceConfig.VFF;
|
||||
auto VFF = new QTreeWidgetItem();
|
||||
|
|
@ -533,14 +471,6 @@ void DevicePacketLogView::addEntry(const DevicePacketLog::LogEntry &e)
|
|||
addBool(VFE, "PGA autogain", sFE.autogain);
|
||||
addInteger(VFE, "Port gain", sFE.portGain);
|
||||
addInteger(VFE, "Reference gain", sFE.refGain);
|
||||
|
||||
auto sD0 = e.p->deviceConfig.VD0;
|
||||
auto VD0 = new QTreeWidgetItem();
|
||||
VD0->setData(2, Qt::DisplayRole, "VD0");
|
||||
item->addChild(VD0);
|
||||
addInteger(VD0, "ADC rate", sD0.ADCrate);
|
||||
addInteger(VD0, "DFT phase increment", sD0.DFTphaseInc);
|
||||
addInteger(VD0, "PLL settling delay", sD0.PLLSettlingDelay);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
|
|
|||
|
|
@ -52,9 +52,8 @@ bool FirmwareUpdateDialog::FirmwareUpdate(LibreVNADriver *dev, QString file)
|
|||
void FirmwareUpdateDialog::on_bFile_clicked()
|
||||
{
|
||||
ui->bStart->setEnabled(false);
|
||||
auto filename = QFileDialog::getOpenFileName(nullptr, "Open firmware file", Preferences::getInstance().UISettings.Paths.firmware, "Firmware file (*.vnafw)", nullptr, Preferences::QFileDialogOptions());
|
||||
auto filename = QFileDialog::getOpenFileName(nullptr, "Open firmware file", "", "Firmware file (*.vnafw)", nullptr, Preferences::QFileDialogOptions());
|
||||
if (filename.length() > 0) {
|
||||
Preferences::getInstance().UISettings.Paths.firmware = QFileInfo(filename).path();
|
||||
ui->lFile->setText(filename);
|
||||
reloadFile();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,12 +3,9 @@
|
|||
#include "manualcontroldialogV1.h"
|
||||
#include "manualcontroldialogvff.h"
|
||||
#include "manualcontroldialogvfe.h"
|
||||
#include "manualcontroldialogVE0.h"
|
||||
#include "manualcontroldialogVD0.h"
|
||||
#include "deviceconfigurationdialogv1.h"
|
||||
#include "deviceconfigurationdialogvff.h"
|
||||
#include "deviceconfigurationdialogvfe.h"
|
||||
#include "deviceconfigurationdialogvd0.h"
|
||||
#include "firmwareupdatedialog.h"
|
||||
#include "frequencycaldialog.h"
|
||||
#include "sourcecaldialog.h"
|
||||
|
|
@ -130,12 +127,6 @@ LibreVNADriver::LibreVNADriver()
|
|||
case 1:
|
||||
manualControlDialog = new ManualControlDialogV1(*this);
|
||||
break;
|
||||
case 0xD0:
|
||||
manualControlDialog = new ManualControlDialogVD0(*this);
|
||||
break;
|
||||
case 0xE0:
|
||||
manualControlDialog = new ManualControlDialogVE0(*this);
|
||||
break;
|
||||
case 0xFE:
|
||||
manualControlDialog = new ManualControlDialogVFE(*this);
|
||||
break;
|
||||
|
|
@ -162,9 +153,6 @@ LibreVNADriver::LibreVNADriver()
|
|||
case 1:
|
||||
d = new DeviceConfigurationDialogV1(*this);
|
||||
break;
|
||||
case 0xD0:
|
||||
d = new DeviceConfigurationDialogVD0(*this);
|
||||
break;
|
||||
case 0xFE:
|
||||
d = new DeviceConfigurationDialogVFE(*this);
|
||||
break;
|
||||
|
|
@ -210,26 +198,9 @@ LibreVNADriver::LibreVNADriver()
|
|||
});
|
||||
specificActions.push_back(freqcal);
|
||||
|
||||
auto internalAlignment = new QAction("Run Internal Alignment");
|
||||
connect(internalAlignment, &QAction::triggered, this, [=](){
|
||||
emit acquireControl();
|
||||
Protocol::PacketInfo p;
|
||||
p.type = Protocol::PacketType::PerformAction;
|
||||
p.performAction.action = Protocol::Action::InternalAlignment;
|
||||
SendPacket(p, [=](TransmissionResult res){
|
||||
if(res == TransmissionResult::Ack) {
|
||||
InformationBox::ShowMessage("Success", "Internal alignment completed");
|
||||
} else {
|
||||
InformationBox::ShowError("Error", "Running internal alignment failed");
|
||||
}
|
||||
emit releaseControl();
|
||||
}, 5000);
|
||||
});
|
||||
specificActions.push_back(internalAlignment);
|
||||
|
||||
auto sep2 = new QAction();
|
||||
sep2->setSeparator(true);
|
||||
specificActions.push_back(sep2);
|
||||
sep = new QAction();
|
||||
sep->setSeparator(true);
|
||||
specificActions.push_back(sep);
|
||||
|
||||
auto log = new QAction("View Packet Log");
|
||||
connect(log, &QAction::triggered, this, [=](){
|
||||
|
|
@ -238,14 +209,6 @@ LibreVNADriver::LibreVNADriver()
|
|||
});
|
||||
specificActions.push_back(log);
|
||||
|
||||
// set available actions for each hardware version
|
||||
availableActions[0x01] = {manual, config, update, sep, srccal, recvcal, freqcal, sep2, log};
|
||||
availableActions[0xD0] = {manual, config, update, sep, srccal, recvcal, freqcal, sep2, log};
|
||||
availableActions[0xE0] = {manual, update, sep, srccal, recvcal, freqcal, internalAlignment, sep2, log};
|
||||
availableActions[0xFD] = {manual, update, sep, srccal, recvcal, freqcal, sep2, log};
|
||||
availableActions[0xFE] = {manual, config, update, sep, srccal, recvcal, freqcal, sep2, log};
|
||||
availableActions[0xFF] = {manual, config, update, sep, srccal, recvcal, freqcal, sep2, log};
|
||||
|
||||
// Create driver specific commands
|
||||
specificSCPIcommands.push_back(new SCPICommand("DEVice:INFo:TEMPeratures", nullptr, [=](QStringList) -> QString {
|
||||
if(!connected) {
|
||||
|
|
@ -314,17 +277,6 @@ std::set<DeviceDriver::Flag> LibreVNADriver::getFlags()
|
|||
ret.insert(Flag::Overload);
|
||||
}
|
||||
break;
|
||||
case 0xD0:
|
||||
if(!lastStatus.VD0.source_locked || !lastStatus.VD0.LO_locked) {
|
||||
ret.insert(Flag::Unlocked);
|
||||
}
|
||||
if(lastStatus.VD0.unlevel) {
|
||||
ret.insert(Flag::Unlevel);
|
||||
}
|
||||
if(lastStatus.VD0.ADC_overload) {
|
||||
ret.insert(Flag::Overload);
|
||||
}
|
||||
break;
|
||||
case 0xFE:
|
||||
if(!lastStatus.VFE.source_locked || !lastStatus.VFE.LO_locked) {
|
||||
ret.insert(Flag::Unlocked);
|
||||
|
|
@ -370,19 +322,6 @@ QString LibreVNADriver::getStatus()
|
|||
}
|
||||
}
|
||||
break;
|
||||
case 0xD0:
|
||||
ret.append(" Temps MCU: "+QString::number(lastStatus.VD0.temp_MCU)+"°C");
|
||||
ret.append(" Supply: "+Unit::ToString((float) lastStatus.VD0.supply_voltage / 1000.0, "V", "m ", 3) + " " + Unit::ToString((float) lastStatus.VD0.supply_current / 1000.0, "A", "m ", 3));
|
||||
ret.append(" Reference:");
|
||||
if(lastStatus.VD0.extRefInUse) {
|
||||
ret.append("External");
|
||||
} else {
|
||||
ret.append("Internal");
|
||||
if(lastStatus.VD0.extRefAvailable) {
|
||||
ret.append(" (External available)");
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 0xFE:
|
||||
ret.append(" MCU Temp: "+QString::number(lastStatus.VFE.temp_MCU)+"°C");
|
||||
ret.append(" eCal Temp: "+QString::number(lastStatus.VFE.temp_eCal / 100.0)+"°C");
|
||||
|
|
@ -766,8 +705,6 @@ void LibreVNADriver::handleReceivedPacket(const Protocol::PacketInfo &packet)
|
|||
info.Limits.SA.maxdBm = (double) packet.info.limits_cdbm_max / 100;
|
||||
|
||||
limits_maxAmplitudePoints = packet.info.limits_maxAmplitudePoints;
|
||||
|
||||
updateActionVisibility(hardwareVersion);
|
||||
emit InfoUpdated();
|
||||
}
|
||||
break;
|
||||
|
|
@ -832,35 +769,12 @@ QString LibreVNADriver::hardwareVersionToString(uint8_t version)
|
|||
{
|
||||
switch(version) {
|
||||
case 0x01: return "1";
|
||||
case 0xD0: return "HAR0";
|
||||
case 0xE0: return "SAP1";
|
||||
case 0xFE: return "P2";
|
||||
case 0xFF: return "PT";
|
||||
default: return "Unknown";
|
||||
}
|
||||
}
|
||||
|
||||
void LibreVNADriver::updateActionVisibility(uint8_t hardwareVersion)
|
||||
{
|
||||
// only show actions for the correct hardware version
|
||||
if(availableActions.contains(hardwareVersion)) {
|
||||
// hide all actions
|
||||
for(auto a : specificActions) {
|
||||
a->setVisible(false);
|
||||
}
|
||||
// show the relevant actions
|
||||
for(auto a : availableActions[hardwareVersion]) {
|
||||
a->setVisible(true);
|
||||
}
|
||||
} else {
|
||||
// the hardware version is unknown. This should not happen but just in case
|
||||
// we set all actions to visible
|
||||
for(auto a : specificActions) {
|
||||
a->setVisible(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int LibreVNADriver::getProtocolVersion() const
|
||||
{
|
||||
return protocolVersion;
|
||||
|
|
@ -875,8 +789,6 @@ QString LibreVNADriver::getFirmwareMagicString()
|
|||
{
|
||||
switch(hardwareVersion) {
|
||||
case 0x01: return "VNA!";
|
||||
case 0xD0: return "VHP1";
|
||||
case 0xE0: return "VNS1";
|
||||
case 0xFE: return "VNP2";
|
||||
case 0xFF: return "VNPT";
|
||||
default: return "XXXX";
|
||||
|
|
|
|||
|
|
@ -197,7 +197,6 @@ protected slots:
|
|||
void handleReceivedPacket(const Protocol::PacketInfo& packet);
|
||||
protected:
|
||||
QString hardwareVersionToString(uint8_t version);
|
||||
void updateActionVisibility(uint8_t hardwareVersion);
|
||||
|
||||
bool connected;
|
||||
unsigned int protocolVersion;
|
||||
|
|
@ -229,9 +228,6 @@ protected:
|
|||
bool VNASuppressInvalidPeaks;
|
||||
bool VNAAdjustPowerLevel;
|
||||
|
||||
// available actions per hardware version
|
||||
QMap<uint8_t, QList<QAction*>> availableActions;
|
||||
|
||||
QDialog *manualControlDialog;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -8,6 +8,16 @@
|
|||
|
||||
using namespace std;
|
||||
|
||||
using USBID = struct {
|
||||
int VID;
|
||||
int PID;
|
||||
};
|
||||
static constexpr USBID IDs[] = {
|
||||
{0x0483, 0x564e},
|
||||
{0x0483, 0x4121},
|
||||
{0x1209, 0x4121},
|
||||
};
|
||||
|
||||
LibreVNAUSBDriver::LibreVNAUSBDriver()
|
||||
: LibreVNADriver()
|
||||
{
|
||||
|
|
@ -20,10 +30,6 @@ LibreVNAUSBDriver::LibreVNAUSBDriver()
|
|||
lastTimestamp = QDateTime::currentDateTime();
|
||||
byteCnt = 0;
|
||||
|
||||
validUSBIDs.append({0x0483, 0x564e, "VNA"});
|
||||
validUSBIDs.append({0x0483, 0x4121, "VNA"});
|
||||
validUSBIDs.append({0x1209, 0x4121, "VNA"});
|
||||
|
||||
specificSettings.push_back(Savable::SettingDescription(&captureRawReceiverValues, "LibreVNAUSBDriver.captureRawReceiverValues", false));
|
||||
specificSettings.push_back(Savable::SettingDescription(&harmonicMixing, "LibreVNAUSBDriver.harmonicMixing", false));
|
||||
specificSettings.push_back(Savable::SettingDescription(&SASignalID, "LibreVNAUSBDriver.signalID", true));
|
||||
|
|
@ -303,15 +309,15 @@ void LibreVNAUSBDriver::SearchDevices(std::function<bool (libusb_device_handle *
|
|||
continue;
|
||||
}
|
||||
|
||||
int IDindex = -1;
|
||||
for(int i=0;i<validUSBIDs.size();i++) {
|
||||
if(desc.idVendor == validUSBIDs[i].VID && desc.idProduct == validUSBIDs[i].PID) {
|
||||
IDindex = i;
|
||||
bool correctID = false;
|
||||
int numIDs = sizeof(IDs)/sizeof(IDs[0]);
|
||||
for(int i=0;i<numIDs;i++) {
|
||||
if(desc.idVendor == IDs[i].VID && desc.idProduct == IDs[i].PID) {
|
||||
correctID = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(IDindex == -1) {
|
||||
// invalid VID/PID
|
||||
if(!correctID) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
@ -342,7 +348,7 @@ void LibreVNAUSBDriver::SearchDevices(std::function<bool (libusb_device_handle *
|
|||
if (ret > 0) {
|
||||
/* managed to read the product string */
|
||||
QString product(c_product);
|
||||
if (product == validUSBIDs[IDindex].deviceName) {
|
||||
if (product == "VNA") {
|
||||
// this is a match
|
||||
if(!foundCallback(handle, QString(c_serial))) {
|
||||
// abort search
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@ private:
|
|||
void USBHandleThread();
|
||||
// foundCallback is called for every device that is found. If it returns true the search continues, otherwise it is aborted.
|
||||
// When the search is aborted the last found device is still opened
|
||||
void SearchDevices(std::function<bool(libusb_device_handle *handle, QString getSerial)> foundCallback, libusb_context *context, bool ignoreOpenError);
|
||||
static void SearchDevices(std::function<bool(libusb_device_handle *handle, QString getSerial)> foundCallback, libusb_context *context, bool ignoreOpenError);
|
||||
|
||||
libusb_device_handle *m_handle;
|
||||
libusb_context *m_context;
|
||||
|
|
@ -82,13 +82,6 @@ private:
|
|||
QDateTime lastTimestamp;
|
||||
unsigned long byteCnt;
|
||||
|
||||
using USBID = struct {
|
||||
int VID;
|
||||
int PID;
|
||||
QString deviceName;
|
||||
};
|
||||
protected:
|
||||
QList<USBID> validUSBIDs;
|
||||
};
|
||||
|
||||
#endif // LIBREVNAUSBDRIVER_H
|
||||
|
|
|
|||
|
|
@ -1,812 +0,0 @@
|
|||
#include "manualcontroldialogVD0.h"
|
||||
|
||||
#include "ui_manualcontroldialogVD0.h"
|
||||
#include "Util/util.h"
|
||||
|
||||
#include <QComboBox>
|
||||
#include <QDebug>
|
||||
#include <QButtonGroup>
|
||||
#include <complex>
|
||||
|
||||
|
||||
using namespace std;
|
||||
|
||||
ManualControlDialogVD0::ManualControlDialogVD0(LibreVNADriver &dev, QWidget *parent) :
|
||||
QDialog(parent),
|
||||
ui(new Ui::ManualControlDialogVD0),
|
||||
dev(dev)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
setAttribute(Qt::WA_DeleteOnClose);
|
||||
|
||||
emit dev.acquireControl();
|
||||
|
||||
ui->SourceLowFrequency->setUnit("Hz");
|
||||
ui->SourceLowFrequency->setPrefixes(" kM");
|
||||
ui->SourceLowFrequency->setPrecision(6);
|
||||
ui->SourceLowFrequency->setValueQuiet(1000000);
|
||||
|
||||
ui->SourceHighFrequency->setUnit("Hz");
|
||||
ui->SourceHighFrequency->setPrefixes(" kMG");
|
||||
ui->SourceHighFrequency->setPrecision(6);
|
||||
ui->SourceHighFrequency->setValueQuiet(1000000000);
|
||||
|
||||
ui->IFHigh->setUnit("Hz");
|
||||
ui->IFHigh->setPrefixes(" kM");
|
||||
ui->IFHigh->setPrecision(6);
|
||||
|
||||
ui->IFLow->setUnit("Hz");
|
||||
ui->IFLow->setPrefixes(" kM");
|
||||
ui->IFLow->setPrecision(6);
|
||||
|
||||
ui->LOHighFrequency->setUnit("Hz");
|
||||
ui->LOHighFrequency->setPrefixes(" kMG");
|
||||
ui->LOHighFrequency->setPrecision(6);
|
||||
|
||||
ui->LOLowFrequency->setUnit("Hz");
|
||||
ui->LOLowFrequency->setPrefixes(" kM");
|
||||
ui->LOLowFrequency->setPrecision(6);
|
||||
|
||||
auto UpdateLOHigh = [=]() {
|
||||
double sourceFreq;
|
||||
if (ui->SwitchLowband->isChecked()) {
|
||||
sourceFreq = ui->SourceLowFrequency->value();
|
||||
} else {
|
||||
sourceFreq = ui->SourceHighFrequency->value();
|
||||
}
|
||||
if (ui->LOHighFreqType->currentIndex() == 0) {
|
||||
// fixed IF mode
|
||||
ui->LOHighFrequency->setValueQuiet(sourceFreq + ui->IFHigh->value());
|
||||
} else {
|
||||
// Manual Frequency mode
|
||||
ui->IFHigh->setValueQuiet(ui->LOHighFrequency->value() - sourceFreq);
|
||||
}
|
||||
};
|
||||
auto UpdateLOLow = [=]() {
|
||||
double sourceFreq;
|
||||
if (ui->SwitchLowband->isChecked()) {
|
||||
sourceFreq = ui->SourceLowFrequency->value();
|
||||
} else {
|
||||
sourceFreq = ui->SourceHighFrequency->value();
|
||||
}
|
||||
if (ui->LOLowFreqType->currentIndex() == 0) {
|
||||
// fixed IF mode
|
||||
ui->LOLowFrequency->setValueQuiet(sourceFreq + ui->IFLow->value());
|
||||
} else {
|
||||
// Manual Frequency mode
|
||||
ui->IFLow->setValueQuiet(ui->LOLowFrequency->value() - sourceFreq);
|
||||
}
|
||||
};
|
||||
|
||||
connect(ui->IFHigh, &SIUnitEdit::valueChanged, [=](double) {
|
||||
UpdateLOHigh();
|
||||
});
|
||||
connect(ui->LOHighFrequency, &SIUnitEdit::valueChanged, [=](double) {
|
||||
UpdateLOHigh();
|
||||
});
|
||||
connect(ui->IFLow, &SIUnitEdit::valueChanged, [=](double) {
|
||||
UpdateLOLow();
|
||||
});
|
||||
connect(ui->LOLowFrequency, &SIUnitEdit::valueChanged, [=](double) {
|
||||
UpdateLOLow();
|
||||
});
|
||||
connect(ui->SourceSwitchGroup, qOverload<int, bool>(&QButtonGroup::idToggled), [=](int, bool) {
|
||||
UpdateLOHigh();
|
||||
UpdateLOLow();
|
||||
});
|
||||
connect(ui->SourceLowFrequency, &SIUnitEdit::valueChanged, [=](double) {
|
||||
UpdateLOHigh();
|
||||
UpdateLOLow();
|
||||
});
|
||||
connect(ui->SourceHighFrequency, &SIUnitEdit::valueChanged, [=](double) {
|
||||
UpdateLOHigh();
|
||||
UpdateLOLow();
|
||||
});
|
||||
|
||||
ui->IFHigh->setValue(233750);
|
||||
ui->IFLow->setValue(233750);
|
||||
|
||||
// LO high/low mode switch connections
|
||||
connect(ui->LOHighFreqType, qOverload<int>(&QComboBox::activated), this, [=](int index) {
|
||||
switch(index) {
|
||||
case 0:
|
||||
ui->LOHighFrequency->setEnabled(false);
|
||||
ui->IFHigh->setEnabled(true);
|
||||
break;
|
||||
case 1:
|
||||
ui->LOHighFrequency->setEnabled(true);
|
||||
ui->IFHigh->setEnabled(false);
|
||||
break;
|
||||
}
|
||||
});
|
||||
connect(ui->LOLowFreqType, qOverload<int>(&QComboBox::activated), this, [=](int index) {
|
||||
switch(index) {
|
||||
case 0:
|
||||
ui->LOLowFrequency->setEnabled(false);
|
||||
ui->IFLow->setEnabled(true);
|
||||
break;
|
||||
case 1:
|
||||
ui->LOLowFrequency->setEnabled(true);
|
||||
ui->IFLow->setEnabled(false);
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
// Readonly widgets
|
||||
auto MakeReadOnly = [](QWidget* w) {
|
||||
w->setAttribute(Qt::WA_TransparentForMouseEvents);
|
||||
w->setFocusPolicy(Qt::NoFocus);
|
||||
};
|
||||
MakeReadOnly(ui->SourceLocked);
|
||||
MakeReadOnly(ui->LOLocked);
|
||||
MakeReadOnly(ui->port1min);
|
||||
MakeReadOnly(ui->port1max);
|
||||
MakeReadOnly(ui->port1mag);
|
||||
MakeReadOnly(ui->port1phase);
|
||||
MakeReadOnly(ui->port1referenced);
|
||||
MakeReadOnly(ui->port2min);
|
||||
MakeReadOnly(ui->port2max);
|
||||
MakeReadOnly(ui->port2mag);
|
||||
MakeReadOnly(ui->port2phase);
|
||||
MakeReadOnly(ui->port2referenced);
|
||||
MakeReadOnly(ui->refmin);
|
||||
MakeReadOnly(ui->refmax);
|
||||
MakeReadOnly(ui->refmag);
|
||||
MakeReadOnly(ui->refphase);
|
||||
|
||||
connect(&dev, &LibreVNADriver::receivedPacket, this, [=](const Protocol::PacketInfo &p){
|
||||
if(p.type == Protocol::PacketType::ManualStatus) {
|
||||
NewStatus(p.manualStatus);
|
||||
}
|
||||
}, Qt::QueuedConnection);
|
||||
|
||||
connect(ui->SourceCE, &QCheckBox::toggled, this, [=](bool) { UpdateDevice(); });
|
||||
connect(ui->LOHighCE, &QCheckBox::toggled, this, [=](bool) { UpdateDevice(); });
|
||||
connect(ui->SourceLowEnable, &QCheckBox::toggled, this, [=](bool) { UpdateDevice(); });
|
||||
connect(ui->LOLowEnable, &QCheckBox::toggled, this, [=](bool) { UpdateDevice(); });
|
||||
connect(ui->Port1Enable, &QCheckBox::toggled, this, [=](bool) { UpdateDevice(); });
|
||||
connect(ui->Port2Enable, &QCheckBox::toggled, this, [=](bool) { UpdateDevice(); });
|
||||
connect(ui->RefEnable, &QCheckBox::toggled, this, [=](bool) { UpdateDevice(); });
|
||||
|
||||
connect(ui->SourceLowpass, qOverload<int>(&QComboBox::activated), this, [=](int) { UpdateDevice(); });
|
||||
connect(ui->SourceLowPower, qOverload<int>(&QComboBox::activated), this, [=](int) { UpdateDevice(); });
|
||||
connect(ui->LOLowPower, qOverload<int>(&QComboBox::activated), this, [=](int) { UpdateDevice(); });
|
||||
connect(ui->cbWindow, qOverload<int>(&QComboBox::activated), this, [=](int) { UpdateDevice(); });
|
||||
|
||||
connect(ui->SourceHighFrequency, &SIUnitEdit::valueChanged, this, [=](double) { UpdateDevice(); });
|
||||
connect(ui->SourceLowFrequency, &SIUnitEdit::valueChanged, this, [=](double) { UpdateDevice(); });
|
||||
connect(ui->LOHighFrequency, &SIUnitEdit::valueChanged, this, [=](double) { UpdateDevice(); });
|
||||
connect(ui->IFHigh, &SIUnitEdit::valueChanged, this, [=](double) { UpdateDevice(); });
|
||||
connect(ui->LOLowFrequency, &SIUnitEdit::valueChanged, this, [=](double) { UpdateDevice(); });
|
||||
connect(ui->IFLow, &SIUnitEdit::valueChanged, this, [=](double) { UpdateDevice(); });
|
||||
|
||||
connect(ui->PortSwitchGroup, qOverload<int, bool>(&QButtonGroup::idToggled), this, [=](int, bool) { UpdateDevice(); });
|
||||
connect(ui->SourceSwitchGroup, qOverload<int, bool>(&QButtonGroup::idToggled), this, [=](int, bool) { UpdateDevice(); });
|
||||
connect(ui->LOSwitchGroup, qOverload<int, bool>(&QButtonGroup::idToggled), this, [=](int, bool) { UpdateDevice(); });
|
||||
|
||||
connect(ui->Attenuator, qOverload<double>(&QDoubleSpinBox::valueChanged), this, [=](double) { UpdateDevice(); });
|
||||
connect(ui->SourceHighPower, qOverload<int>(&QSpinBox::valueChanged), this, [=](int) { UpdateDevice(); });
|
||||
connect(ui->Samples, qOverload<int>(&QSpinBox::valueChanged), this, [=](double) { UpdateDevice(); });
|
||||
|
||||
|
||||
// Create the SCPI commands
|
||||
|
||||
auto addBooleanManualSetting = [=](QString cmd, void(ManualControlDialogVD0::*set)(bool), bool(ManualControlDialogVD0::*get)(void)) {
|
||||
commands.push_back(new SCPICommand(cmd, [=](QStringList params) -> QString {
|
||||
bool enable;
|
||||
if(!SCPI::paramToBool(params, 0, enable)) {
|
||||
return SCPI::getResultName(SCPI::Result::Error);
|
||||
}
|
||||
auto set_fn = std::bind(set, this, std::placeholders::_1);
|
||||
set_fn(enable);
|
||||
return SCPI::getResultName(SCPI::Result::Empty);
|
||||
}, [=](QStringList) -> QString {
|
||||
auto get_fn = std::bind(get, this);
|
||||
return get_fn() ? SCPI::getResultName(SCPI::Result::True) : SCPI::getResultName(SCPI::Result::False);
|
||||
}));
|
||||
};
|
||||
|
||||
auto addDoubleManualSetting = [=](QString cmd, void(ManualControlDialogVD0::*set)(double), double(ManualControlDialogVD0::*get)(void)) {
|
||||
commands.push_back(new SCPICommand(cmd, [=](QStringList params) -> QString {
|
||||
double value;
|
||||
if(!SCPI::paramToDouble(params, 0, value)) {
|
||||
return SCPI::getResultName(SCPI::Result::Error);
|
||||
}
|
||||
auto set_fn = std::bind(set, this, std::placeholders::_1);
|
||||
set_fn(value);
|
||||
return SCPI::getResultName(SCPI::Result::Empty);
|
||||
}, [=](QStringList) -> QString {
|
||||
auto get_fn = std::bind(get, this);
|
||||
return QString::number(get_fn());
|
||||
}));
|
||||
};
|
||||
auto addIntegerManualSetting = [=](QString cmd, void(ManualControlDialogVD0::*set)(int), int(ManualControlDialogVD0::*get)(void)) {
|
||||
commands.push_back(new SCPICommand(cmd, [=](QStringList params) -> QString {
|
||||
double value;
|
||||
if(!SCPI::paramToDouble(params, 0, value)) {
|
||||
return SCPI::getResultName(SCPI::Result::Error);
|
||||
}
|
||||
auto set_fn = std::bind(set, this, std::placeholders::_1);
|
||||
set_fn(value);
|
||||
return SCPI::getResultName(SCPI::Result::Empty);
|
||||
}, [=](QStringList) -> QString {
|
||||
auto get_fn = std::bind(get, this);
|
||||
return QString::number(get_fn());
|
||||
}));
|
||||
};
|
||||
auto addIntegerManualSettingWithReturnValue = [=](QString cmd, bool(ManualControlDialogVD0::*set)(int), int(ManualControlDialogVD0::*get)(void)) {
|
||||
commands.push_back(new SCPICommand(cmd, [=](QStringList params) -> QString {
|
||||
double value;
|
||||
if(!SCPI::paramToDouble(params, 0, value)) {
|
||||
return SCPI::getResultName(SCPI::Result::Error);
|
||||
}
|
||||
auto set_fn = std::bind(set, this, std::placeholders::_1);
|
||||
if(set_fn(value)) {
|
||||
return SCPI::getResultName(SCPI::Result::Empty);
|
||||
} else {
|
||||
return SCPI::getResultName(SCPI::Result::Error);
|
||||
}
|
||||
}, [=](QStringList) -> QString {
|
||||
auto get_fn = std::bind(get, this);
|
||||
return QString::number(get_fn());
|
||||
}));
|
||||
};
|
||||
auto addIntegerManualQuery = [=](QString cmd, int(ManualControlDialogVD0::*get)(void)) {
|
||||
commands.push_back(new SCPICommand(cmd, nullptr, [=](QStringList) -> QString {
|
||||
auto get_fn = std::bind(get, this);
|
||||
return QString::number(get_fn());
|
||||
}));
|
||||
};
|
||||
auto addDoubleManualQuery = [=](QString cmd, double(ManualControlDialogVD0::*get)(void)) {
|
||||
commands.push_back(new SCPICommand(cmd, nullptr, [=](QStringList) -> QString {
|
||||
auto get_fn = std::bind(get, this);
|
||||
return QString::number(get_fn());
|
||||
}));
|
||||
};
|
||||
auto addBooleanManualQuery = [=](QString cmd, bool(ManualControlDialogVD0::*get)(void)) {
|
||||
commands.push_back(new SCPICommand(cmd, nullptr, [=](QStringList) -> QString {
|
||||
auto get_fn = std::bind(get, this);
|
||||
return get_fn() ? SCPI::getResultName(SCPI::Result::True) : SCPI::getResultName(SCPI::Result::False);
|
||||
}));
|
||||
};
|
||||
auto addComplexManualQuery = [=](QString cmd, std::complex<double>(ManualControlDialogVD0::*get)(void)) {
|
||||
commands.push_back(new SCPICommand(cmd, nullptr, [=](QStringList) -> QString {
|
||||
auto get_fn = std::bind(get, this);
|
||||
auto res = get_fn();
|
||||
return QString::number(res.real())+","+QString::number(res.imag());
|
||||
}));
|
||||
};
|
||||
|
||||
addBooleanManualSetting("MANual:HSRC_CE", &ManualControlDialogVD0::setHighSourceChipEnable, &ManualControlDialogVD0::getHighSourceChipEnable);
|
||||
addBooleanManualQuery("MANual:HSRC_LOCKed", &ManualControlDialogVD0::getHighSourceLocked);
|
||||
addIntegerManualSettingWithReturnValue("MANual:HSRC_PWR", &ManualControlDialogVD0::setHighSourcePower, &ManualControlDialogVD0::getHighSourcePower);
|
||||
addDoubleManualSetting("MANual:HSRC_FREQ", &ManualControlDialogVD0::setHighSourceFrequency, &ManualControlDialogVD0::getHighSourceFrequency);
|
||||
commands.push_back(new SCPICommand("MANual:HSRC_LPF", [=](QStringList params) -> QString {
|
||||
long value;
|
||||
if(!SCPI::paramToLong(params, 0, value)) {
|
||||
return SCPI::getResultName(SCPI::Result::Error);
|
||||
}
|
||||
switch(value) {
|
||||
case 947:
|
||||
setHighSourceLPF(ManualControlDialogVD0::LPF::M947);
|
||||
break;
|
||||
case 1880:
|
||||
setHighSourceLPF(ManualControlDialogVD0::LPF::M1880);
|
||||
break;
|
||||
case 3500:
|
||||
setHighSourceLPF(ManualControlDialogVD0::LPF::M3500);
|
||||
break;
|
||||
case 0:
|
||||
setHighSourceLPF(ManualControlDialogVD0::LPF::None);
|
||||
break;
|
||||
default:
|
||||
return SCPI::getResultName(SCPI::Result::Error);
|
||||
}
|
||||
return SCPI::getResultName(SCPI::Result::Empty);
|
||||
}, [=](QStringList) -> QString {
|
||||
auto lpf = getHighSourceLPF();
|
||||
switch(lpf) {
|
||||
case ManualControlDialogVD0::LPF::M947: return "947";
|
||||
case ManualControlDialogVD0::LPF::M1880: return "1880";
|
||||
case ManualControlDialogVD0::LPF::M3500: return "3500";
|
||||
case ManualControlDialogVD0::LPF::None: return "0";
|
||||
default: return SCPI::getResultName(SCPI::Result::Error);
|
||||
}
|
||||
}));
|
||||
addBooleanManualSetting("MANual:LSRC_EN", &ManualControlDialogVD0::setLowSourceEnable, &ManualControlDialogVD0::getLowSourceEnable);
|
||||
addIntegerManualSettingWithReturnValue("MANual:LSRC_PWR", &ManualControlDialogVD0::setLowSourcePower, &ManualControlDialogVD0::getLowSourcePower);
|
||||
addDoubleManualSetting("MANual:LSRC_FREQ", &ManualControlDialogVD0::setLowSourceFrequency, &ManualControlDialogVD0::getLowSourceFrequency);
|
||||
addBooleanManualSetting("MANual:BAND_SW", &ManualControlDialogVD0::setHighband, &ManualControlDialogVD0::getHighband);
|
||||
addDoubleManualSetting("MANual:ATTenuator", &ManualControlDialogVD0::setAttenuator, &ManualControlDialogVD0::getAttenuator);
|
||||
addIntegerManualSettingWithReturnValue("MANual:PORT_SW", &ManualControlDialogVD0::setPortSwitch, &ManualControlDialogVD0::getPortSwitch);
|
||||
addBooleanManualSetting("MANual:LOHigh_CE", &ManualControlDialogVD0::setLOHighChipEnable, &ManualControlDialogVD0::getLOHighChipEnable);
|
||||
addBooleanManualQuery("MANual:LOHigh_LOCKed", &ManualControlDialogVD0::getLOHighLocked);
|
||||
addDoubleManualSetting("MANual:LOHigh_FREQ", &ManualControlDialogVD0::setLOHighFrequency, &ManualControlDialogVD0::getLOHighFrequency);
|
||||
addDoubleManualSetting("MANual:IFHigh_FREQ", &ManualControlDialogVD0::setIFHighFrequency, &ManualControlDialogVD0::getIFHighFrequency);
|
||||
addBooleanManualSetting("MANual:LOLow_EN", &ManualControlDialogVD0::setLOLowEnable, &ManualControlDialogVD0::getLOLowEnable);
|
||||
addDoubleManualSetting("MANual:LOLow_FREQ", &ManualControlDialogVD0::setLOLowFrequency, &ManualControlDialogVD0::getLOLowFrequency);
|
||||
addDoubleManualSetting("MANual:IFLow_FREQ", &ManualControlDialogVD0::setIFLowFrequency, &ManualControlDialogVD0::getIFLowFrequency);
|
||||
addBooleanManualSetting("MANual:PORT1_EN", &ManualControlDialogVD0::setPort1Enable, &ManualControlDialogVD0::getPort1Enable);
|
||||
addBooleanManualSetting("MANual:PORT2_EN", &ManualControlDialogVD0::setPort2Enable, &ManualControlDialogVD0::getPort2Enable);
|
||||
addBooleanManualSetting("MANual:REF_EN", &ManualControlDialogVD0::setRefEnable, &ManualControlDialogVD0::getRefEnable);
|
||||
addIntegerManualSetting("MANual:SAMPLES", &ManualControlDialogVD0::setNumSamples, &ManualControlDialogVD0::getNumSamples);
|
||||
commands.push_back(new SCPICommand("MANual:WINdow", [=](QStringList params) -> QString {
|
||||
if(params.size() < 1) {
|
||||
return SCPI::getResultName(SCPI::Result::Error);
|
||||
}
|
||||
if (params[0] == "NONE") {
|
||||
setWindow(ManualControlDialogVD0::Window::None);
|
||||
} else if(params[0] == "KAISER") {
|
||||
setWindow(ManualControlDialogVD0::Window::Kaiser);
|
||||
} else if(params[0] == "HANN") {
|
||||
setWindow(ManualControlDialogVD0::Window::Hann);
|
||||
} else if(params[0] == "FLATTOP") {
|
||||
setWindow(ManualControlDialogVD0::Window::FlatTop);
|
||||
} else {
|
||||
return "INVALID WINDOW";
|
||||
}
|
||||
return SCPI::getResultName(SCPI::Result::Empty);
|
||||
}, [=](QStringList) -> QString {
|
||||
switch((ManualControlDialogVD0::Window) getWindow()) {
|
||||
case ManualControlDialogVD0::Window::None: return "NONE";
|
||||
case ManualControlDialogVD0::Window::Kaiser: return "KAISER";
|
||||
case ManualControlDialogVD0::Window::Hann: return "HANN";
|
||||
case ManualControlDialogVD0::Window::FlatTop: return "FLATTOP";
|
||||
default: return SCPI::getResultName(SCPI::Result::Error);
|
||||
}
|
||||
}));
|
||||
addIntegerManualQuery("MANual:PORT1_MIN", &ManualControlDialogVD0::getPort1MinADC);
|
||||
addIntegerManualQuery("MANual:PORT1_MAX", &ManualControlDialogVD0::getPort1MaxADC);
|
||||
addDoubleManualQuery("MANual:PORT1_MAG", &ManualControlDialogVD0::getPort1Magnitude);
|
||||
addDoubleManualQuery("MANual:PORT1_PHAse", &ManualControlDialogVD0::getPort1Phase);
|
||||
addComplexManualQuery("MANual:PORT1_REFerenced", &ManualControlDialogVD0::getPort1Referenced);
|
||||
|
||||
addIntegerManualQuery("MANual:PORT2_MIN", &ManualControlDialogVD0::getPort2MinADC);
|
||||
addIntegerManualQuery("MANual:PORT2_MAX", &ManualControlDialogVD0::getPort2MaxADC);
|
||||
addDoubleManualQuery("MANual:PORT2_MAG", &ManualControlDialogVD0::getPort2Magnitude);
|
||||
addDoubleManualQuery("MANual:PORT2_PHAse", &ManualControlDialogVD0::getPort2Phase);
|
||||
addComplexManualQuery("MANual:PORT2_REFerenced", &ManualControlDialogVD0::getPort2Referenced);
|
||||
|
||||
addIntegerManualQuery("MANual:REF_MIN", &ManualControlDialogVD0::getRefMinADC);
|
||||
addIntegerManualQuery("MANual:REF_MAX", &ManualControlDialogVD0::getRefMaxADC);
|
||||
addDoubleManualQuery("MANual:REF_MAG", &ManualControlDialogVD0::getRefMagnitude);
|
||||
addDoubleManualQuery("MANual:REF_PHAse", &ManualControlDialogVD0::getRefPhase);
|
||||
|
||||
for(auto c : commands) {
|
||||
emit dev.addSCPICommand(c);
|
||||
}
|
||||
|
||||
UpdateDevice();
|
||||
}
|
||||
|
||||
ManualControlDialogVD0::~ManualControlDialogVD0()
|
||||
{
|
||||
for(auto c : commands) {
|
||||
emit dev.removeSCPICommand(c);
|
||||
}
|
||||
emit dev.releaseControl();
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void ManualControlDialogVD0::setHighSourceChipEnable(bool enable)
|
||||
{
|
||||
ui->SourceCE->setChecked(enable);
|
||||
}
|
||||
|
||||
bool ManualControlDialogVD0::getHighSourceChipEnable()
|
||||
{
|
||||
return ui->SourceCE->isChecked();
|
||||
}
|
||||
|
||||
bool ManualControlDialogVD0::getHighSourceLocked()
|
||||
{
|
||||
return ui->SourceLocked->isChecked();
|
||||
}
|
||||
|
||||
bool ManualControlDialogVD0::setHighSourcePower(int dBm)
|
||||
{
|
||||
if(dBm < 0 || dBm > ui->SourceHighPower->maximum()) {
|
||||
return false;
|
||||
} else {
|
||||
ui->SourceHighPower->setValue(dBm);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
int ManualControlDialogVD0::getHighSourcePower()
|
||||
{
|
||||
return ui->SourceHighPower->value();
|
||||
}
|
||||
|
||||
void ManualControlDialogVD0::setHighSourceFrequency(double f)
|
||||
{
|
||||
ui->SourceHighFrequency->setValue(f);
|
||||
}
|
||||
|
||||
double ManualControlDialogVD0::getHighSourceFrequency()
|
||||
{
|
||||
return ui->SourceHighFrequency->value();
|
||||
}
|
||||
|
||||
void ManualControlDialogVD0::setHighSourceLPF(ManualControlDialogVD0::LPF lpf)
|
||||
{
|
||||
switch(lpf) {
|
||||
case LPF::M947:
|
||||
ui->SourceLowpass->setCurrentIndex(0);
|
||||
break;
|
||||
case LPF::M1880:
|
||||
ui->SourceLowpass->setCurrentIndex(1);
|
||||
break;
|
||||
case LPF::M3500:
|
||||
ui->SourceLowpass->setCurrentIndex(2);
|
||||
break;
|
||||
case LPF::None:
|
||||
ui->SourceLowpass->setCurrentIndex(3);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ManualControlDialogVD0::LPF ManualControlDialogVD0::getHighSourceLPF()
|
||||
{
|
||||
LPF lpfs[4] = {LPF::M947, LPF::M1880, LPF::M3500, LPF::None};
|
||||
return lpfs[ui->SourceLowpass->currentIndex()];
|
||||
}
|
||||
|
||||
void ManualControlDialogVD0::setLowSourceEnable(bool enable)
|
||||
{
|
||||
ui->SourceLowEnable->setChecked(enable);
|
||||
}
|
||||
|
||||
bool ManualControlDialogVD0::getLowSourceEnable()
|
||||
{
|
||||
return ui->SourceLowEnable->isChecked();
|
||||
}
|
||||
|
||||
bool ManualControlDialogVD0::setLowSourcePower(int mA)
|
||||
{
|
||||
switch(mA) {
|
||||
case 2:
|
||||
ui->SourceLowPower->setCurrentIndex(0);
|
||||
break;
|
||||
case 4:
|
||||
ui->SourceLowPower->setCurrentIndex(1);
|
||||
break;
|
||||
case 6:
|
||||
ui->SourceLowPower->setCurrentIndex(2);
|
||||
break;
|
||||
case 8:
|
||||
ui->SourceLowPower->setCurrentIndex(3);
|
||||
break;
|
||||
default:
|
||||
// invalid power setting
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
int ManualControlDialogVD0::getLowSourcePower()
|
||||
{
|
||||
int powers[4] = {2,4,6,8};
|
||||
return powers[ui->SourceLowPower->currentIndex()];
|
||||
}
|
||||
|
||||
void ManualControlDialogVD0::setLowSourceFrequency(double f)
|
||||
{
|
||||
ui->SourceLowFrequency->setValue(f);
|
||||
}
|
||||
|
||||
double ManualControlDialogVD0::getLowSourceFrequency()
|
||||
{
|
||||
return ui->SourceLowFrequency->value();
|
||||
}
|
||||
|
||||
void ManualControlDialogVD0::setHighband(bool high)
|
||||
{
|
||||
if(high) {
|
||||
ui->SwitchHighband->setChecked(true);
|
||||
} else {
|
||||
ui->SwitchLowband->setChecked(true);
|
||||
}
|
||||
}
|
||||
|
||||
bool ManualControlDialogVD0::getHighband()
|
||||
{
|
||||
return ui->SwitchHighband->isChecked();
|
||||
}
|
||||
|
||||
void ManualControlDialogVD0::setAttenuator(double att)
|
||||
{
|
||||
ui->Attenuator->setValue(att);
|
||||
}
|
||||
|
||||
double ManualControlDialogVD0::getAttenuator()
|
||||
{
|
||||
return ui->Attenuator->value();
|
||||
}
|
||||
|
||||
bool ManualControlDialogVD0::setPortSwitch(int port)
|
||||
{
|
||||
switch(port) {
|
||||
case 1:
|
||||
ui->Port1Switch->setChecked(true);
|
||||
break;
|
||||
case 2:
|
||||
ui->Port2Switch->setChecked(true);
|
||||
break;
|
||||
default:
|
||||
// invalid port
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
int ManualControlDialogVD0::getPortSwitch()
|
||||
{
|
||||
if(ui->Port1Switch->isChecked()) {
|
||||
return 1;
|
||||
} else {
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
||||
void ManualControlDialogVD0::setLOHighChipEnable(bool enable)
|
||||
{
|
||||
ui->LOHighCE->setChecked(enable);
|
||||
}
|
||||
|
||||
bool ManualControlDialogVD0::getLOHighChipEnable()
|
||||
{
|
||||
return ui->LOHighCE->isChecked();
|
||||
}
|
||||
|
||||
bool ManualControlDialogVD0::getLOHighLocked()
|
||||
{
|
||||
return ui->LOLocked->isChecked();
|
||||
}
|
||||
|
||||
void ManualControlDialogVD0::setLOHighFrequency(double f)
|
||||
{
|
||||
ui->LOHighFreqType->setCurrentIndex(1);
|
||||
ui->LOHighFrequency->setValue(f);
|
||||
}
|
||||
|
||||
double ManualControlDialogVD0::getLOHighFrequency()
|
||||
{
|
||||
return ui->LOHighFrequency->value();
|
||||
}
|
||||
|
||||
void ManualControlDialogVD0::setIFHighFrequency(double f)
|
||||
{
|
||||
ui->LOHighFreqType->setCurrentIndex(0);
|
||||
ui->IFHigh->setValue(f);
|
||||
}
|
||||
|
||||
double ManualControlDialogVD0::getIFHighFrequency()
|
||||
{
|
||||
return ui->IFHigh->value();
|
||||
}
|
||||
|
||||
void ManualControlDialogVD0::setLOLowEnable(bool enable)
|
||||
{
|
||||
ui->LOLowEnable->setChecked(enable);
|
||||
}
|
||||
|
||||
bool ManualControlDialogVD0::getLOLowEnable()
|
||||
{
|
||||
return ui->LOLowEnable->isChecked();
|
||||
}
|
||||
|
||||
void ManualControlDialogVD0::setLOLowFrequency(double f)
|
||||
{
|
||||
ui->LOLowFreqType->setCurrentIndex(1);
|
||||
ui->LOLowFrequency->setValue(f);
|
||||
}
|
||||
|
||||
double ManualControlDialogVD0::getLOLowFrequency()
|
||||
{
|
||||
return ui->LOLowFrequency->value();
|
||||
}
|
||||
|
||||
void ManualControlDialogVD0::setIFLowFrequency(double f)
|
||||
{
|
||||
ui->LOLowFreqType->setCurrentIndex(0);
|
||||
ui->IFLow->setValue(f);
|
||||
}
|
||||
|
||||
double ManualControlDialogVD0::getIFLowFrequency()
|
||||
{
|
||||
return ui->IFLow->value();
|
||||
}
|
||||
|
||||
void ManualControlDialogVD0::setPort1Enable(bool enable)
|
||||
{
|
||||
ui->Port1Enable->setChecked(enable);
|
||||
}
|
||||
|
||||
bool ManualControlDialogVD0::getPort1Enable()
|
||||
{
|
||||
return ui->Port1Enable->isChecked();
|
||||
}
|
||||
|
||||
void ManualControlDialogVD0::setPort2Enable(bool enable)
|
||||
{
|
||||
ui->Port2Enable->setChecked(enable);
|
||||
}
|
||||
|
||||
bool ManualControlDialogVD0::getPort2Enable()
|
||||
{
|
||||
return ui->Port2Enable->isChecked();
|
||||
}
|
||||
|
||||
void ManualControlDialogVD0::setRefEnable(bool enable)
|
||||
{
|
||||
ui->RefEnable->setChecked(enable);
|
||||
}
|
||||
|
||||
bool ManualControlDialogVD0::getRefEnable()
|
||||
{
|
||||
return ui->RefEnable->isChecked();
|
||||
}
|
||||
|
||||
void ManualControlDialogVD0::setNumSamples(int samples)
|
||||
{
|
||||
ui->Samples->setValue(samples);
|
||||
}
|
||||
|
||||
int ManualControlDialogVD0::getNumSamples()
|
||||
{
|
||||
return ui->Samples->value();
|
||||
}
|
||||
|
||||
void ManualControlDialogVD0::setWindow(ManualControlDialogVD0::Window w)
|
||||
{
|
||||
ui->cbWindow->setCurrentIndex((int) w);
|
||||
}
|
||||
|
||||
ManualControlDialogVD0::Window ManualControlDialogVD0::getWindow()
|
||||
{
|
||||
return (Window) ui->cbWindow->currentIndex();
|
||||
}
|
||||
|
||||
int ManualControlDialogVD0::getPort1MinADC()
|
||||
{
|
||||
return ui->port1min->text().toInt();
|
||||
}
|
||||
|
||||
int ManualControlDialogVD0::getPort1MaxADC()
|
||||
{
|
||||
return ui->port1max->text().toInt();
|
||||
}
|
||||
|
||||
double ManualControlDialogVD0::getPort1Magnitude()
|
||||
{
|
||||
return ui->port1mag->text().toDouble();
|
||||
}
|
||||
|
||||
double ManualControlDialogVD0::getPort1Phase()
|
||||
{
|
||||
return ui->port1phase->text().toDouble();
|
||||
}
|
||||
|
||||
std::complex<double> ManualControlDialogVD0::getPort1Referenced()
|
||||
{
|
||||
return port1referenced;
|
||||
}
|
||||
|
||||
int ManualControlDialogVD0::getPort2MinADC()
|
||||
{
|
||||
return ui->port2min->text().toInt();
|
||||
}
|
||||
|
||||
int ManualControlDialogVD0::getPort2MaxADC()
|
||||
{
|
||||
return ui->port2max->text().toInt();
|
||||
}
|
||||
|
||||
double ManualControlDialogVD0::getPort2Magnitude()
|
||||
{
|
||||
return ui->port2mag->text().toDouble();
|
||||
}
|
||||
|
||||
double ManualControlDialogVD0::getPort2Phase()
|
||||
{
|
||||
return ui->port2phase->text().toDouble();
|
||||
}
|
||||
|
||||
std::complex<double> ManualControlDialogVD0::getPort2Referenced()
|
||||
{
|
||||
return port2referenced;
|
||||
}
|
||||
|
||||
int ManualControlDialogVD0::getRefMinADC()
|
||||
{
|
||||
return ui->refmin->text().toInt();
|
||||
}
|
||||
|
||||
int ManualControlDialogVD0::getRefMaxADC()
|
||||
{
|
||||
return ui->refmax->text().toInt();
|
||||
}
|
||||
|
||||
double ManualControlDialogVD0::getRefMagnitude()
|
||||
{
|
||||
return ui->refmag->text().toDouble();
|
||||
}
|
||||
|
||||
double ManualControlDialogVD0::getRefPhase()
|
||||
{
|
||||
return ui->refphase->text().toDouble();
|
||||
}
|
||||
|
||||
void ManualControlDialogVD0::NewStatus(Protocol::ManualStatus status)
|
||||
{
|
||||
// ADC values
|
||||
ui->port1min->setText(QString::number(status.VD0.port1min));
|
||||
ui->port1max->setText(QString::number(status.VD0.port1max));
|
||||
auto port1 = complex<double>(status.VD0.port1real, status.VD0.port1imag);
|
||||
ui->port1mag->setText(QString::number(abs(port1)));
|
||||
ui->port1phase->setText(QString::number(arg(port1)*180/M_PI));
|
||||
|
||||
ui->port2min->setText(QString::number(status.VD0.port2min));
|
||||
ui->port2max->setText(QString::number(status.VD0.port2max));
|
||||
auto port2 = complex<double>(status.VD0.port2real, status.VD0.port2imag);
|
||||
ui->port2mag->setText(QString::number(abs(port2)));
|
||||
ui->port2phase->setText(QString::number(arg(port2)*180/M_PI));
|
||||
|
||||
ui->refmin->setText(QString::number(status.VD0.refmin));
|
||||
ui->refmax->setText(QString::number(status.VD0.refmax));
|
||||
auto ref = complex<double>(status.VD0.refreal, status.VD0.refimag);
|
||||
ui->refmag->setText(QString::number(abs(ref)));
|
||||
ui->refphase->setText(QString::number(arg(ref)*180/M_PI));
|
||||
|
||||
port1referenced = port1 / ref;
|
||||
port2referenced = port2 / ref;
|
||||
auto port1db = Util::SparamTodB(port1referenced);
|
||||
auto port2db = Util::SparamTodB(port2referenced);
|
||||
|
||||
ui->port1referenced->setText(QString::number(port1db, 'f', 1) + "db@" + QString::number(arg(port1referenced)*180/M_PI, 'f', 0) + "°");
|
||||
ui->port2referenced->setText(QString::number(port2db, 'f', 1) + "db@" + QString::number(arg(port2referenced)*180/M_PI, 'f', 0) + "°");
|
||||
|
||||
// PLL state
|
||||
ui->SourceLocked->setChecked(status.VD0.source_locked);
|
||||
ui->LOLocked->setChecked(status.VD0.LO_locked);
|
||||
}
|
||||
|
||||
void ManualControlDialogVD0::UpdateDevice()
|
||||
{
|
||||
Protocol::PacketInfo p;
|
||||
p.type = Protocol::PacketType::ManualControl;
|
||||
auto &m = p.manual.VD0;
|
||||
// Source highband
|
||||
m.SourceHighCE = ui->SourceCE->isChecked();
|
||||
m.SourceHighPower = ui->SourceHighPower->value();
|
||||
m.SourceHighFrequency = ui->SourceHighFrequency->value();
|
||||
m.SourceHighLowpass = ui->SourceLowpass->currentIndex();
|
||||
// Source lowband
|
||||
m.SourceLowEN = ui->SourceLowEnable->isChecked();
|
||||
m.SourceLowPower = ui->SourceLowPower->currentIndex();
|
||||
m.SourceLowFrequency = ui->SourceLowFrequency->value();
|
||||
// Source signal path
|
||||
m.SourceHighband = ui->SwitchHighband->isChecked();
|
||||
m.PortSwitch = ui->Port2Switch->isChecked();
|
||||
m.attenuator = -ui->Attenuator->value() / 0.25;
|
||||
// LO High
|
||||
m.LOHighCE = ui->LOHighCE->isChecked();
|
||||
m.LOHighFrequency = ui->LOHighFrequency->value();
|
||||
// LOLow
|
||||
m.LOLowEN = ui->LOLowEnable->isChecked();
|
||||
m.LOLowFrequency = ui->LOLowFrequency->value();
|
||||
m.LOLowPower = ui->LOLowPower->currentIndex();
|
||||
// LO signal path
|
||||
m.LOHighband = ui->LOSwitchHighband->isChecked();
|
||||
// Acquisition
|
||||
m.Port1EN = ui->Port1Enable->isChecked();
|
||||
m.Port2EN = ui->Port2Enable->isChecked();
|
||||
m.RefEN = ui->RefEnable->isChecked();
|
||||
m.Samples = ui->Samples->value();
|
||||
m.WindowType = ui->cbWindow->currentIndex();
|
||||
|
||||
qDebug() << "Updating manual control state";
|
||||
|
||||
dev.SendPacket(p);
|
||||
}
|
||||
|
|
@ -1,114 +0,0 @@
|
|||
#ifndef MANUALCONTROLDIALOGVD0_H
|
||||
#define MANUALCONTROLDIALOGVD0_H
|
||||
|
||||
#include "librevnadriver.h"
|
||||
|
||||
#include <QDialog>
|
||||
#include <complex>
|
||||
|
||||
namespace Ui {
|
||||
class ManualControlDialogVD0;
|
||||
}
|
||||
|
||||
class ManualControlDialogVD0 : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit ManualControlDialogVD0(LibreVNADriver &dev, QWidget *parent = nullptr);
|
||||
~ManualControlDialogVD0();
|
||||
|
||||
void setHighSourceChipEnable(bool enable);
|
||||
bool getHighSourceChipEnable();
|
||||
void setHighSourceRFEnable(bool enable);
|
||||
bool getHighSourceRFEnable();
|
||||
bool getHighSourceLocked();
|
||||
bool setHighSourcePower(int dBm);
|
||||
int getHighSourcePower();
|
||||
void setHighSourceFrequency(double f);
|
||||
double getHighSourceFrequency();
|
||||
|
||||
enum class LPF {
|
||||
M947,
|
||||
M1880,
|
||||
M3500,
|
||||
None,
|
||||
};
|
||||
|
||||
void setHighSourceLPF(LPF lpf);
|
||||
LPF getHighSourceLPF();
|
||||
void setLowSourceEnable(bool enable);
|
||||
bool getLowSourceEnable();
|
||||
bool setLowSourcePower(int mA);
|
||||
int getLowSourcePower();
|
||||
void setLowSourceFrequency(double f);
|
||||
double getLowSourceFrequency();
|
||||
void setHighband(bool high);
|
||||
bool getHighband();
|
||||
void setAttenuator(double att);
|
||||
double getAttenuator();
|
||||
bool setPortSwitch(int port);
|
||||
int getPortSwitch();
|
||||
void setLOHighChipEnable(bool enable);
|
||||
bool getLOHighChipEnable();
|
||||
bool getLOHighLocked();
|
||||
void setLOHighFrequency(double f);
|
||||
double getLOHighFrequency();
|
||||
void setIFHighFrequency(double f);
|
||||
double getIFHighFrequency();
|
||||
void setLOLowEnable(bool enable);
|
||||
bool getLOLowEnable();
|
||||
void setLOLowFrequency(double f);
|
||||
double getLOLowFrequency();
|
||||
void setIFLowFrequency(double f);
|
||||
double getIFLowFrequency();
|
||||
void setPort1Enable(bool enable);
|
||||
bool getPort1Enable();
|
||||
void setPort2Enable(bool enable);
|
||||
bool getPort2Enable();
|
||||
void setRefEnable(bool enable);
|
||||
bool getRefEnable();
|
||||
void setNumSamples(int samples);
|
||||
int getNumSamples();
|
||||
|
||||
enum class Window {
|
||||
None = 0,
|
||||
Kaiser = 1,
|
||||
Hann = 2,
|
||||
FlatTop = 3
|
||||
};
|
||||
|
||||
void setWindow(Window w);
|
||||
Window getWindow();
|
||||
|
||||
int getPort1MinADC();
|
||||
int getPort1MaxADC();
|
||||
double getPort1Magnitude();
|
||||
double getPort1Phase();
|
||||
std::complex<double> getPort1Referenced();
|
||||
|
||||
int getPort2MinADC();
|
||||
int getPort2MaxADC();
|
||||
double getPort2Magnitude();
|
||||
double getPort2Phase();
|
||||
std::complex<double> getPort2Referenced();
|
||||
|
||||
int getRefMinADC();
|
||||
int getRefMaxADC();
|
||||
double getRefMagnitude();
|
||||
double getRefPhase();
|
||||
|
||||
public slots:
|
||||
void NewStatus(Protocol::ManualStatus status);
|
||||
|
||||
private:
|
||||
void UpdateDevice();
|
||||
Ui::ManualControlDialogVD0 *ui;
|
||||
LibreVNADriver &dev;
|
||||
std::complex<double> port1referenced;
|
||||
std::complex<double> port2referenced;
|
||||
|
||||
std::vector<SCPICommand*> commands;
|
||||
};
|
||||
|
||||
#endif // MANUALCONTROLDIALOGVD0_H
|
||||
|
|
@ -1,812 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>ManualControlDialogVD0</class>
|
||||
<widget class="QDialog" name="ManualControlDialogVD0">
|
||||
<property name="windowModality">
|
||||
<enum>Qt::WindowModality::ApplicationModal</enum>
|
||||
</property>
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>857</width>
|
||||
<height>747</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Manual System Control</string>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_4">
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_15">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_10">
|
||||
<property name="title">
|
||||
<string>Signal Generation</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_14">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox">
|
||||
<property name="title">
|
||||
<string>Highband Source</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_10">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="SourceCE">
|
||||
<property name="text">
|
||||
<string>Chip Enable</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="SourceLocked">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Locked</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QFormLayout" name="formLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Power:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Frequency:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="SIUnitEdit" name="SourceHighFrequency"/>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>Lowpass:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QComboBox" name="SourceLowpass">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>947MHz</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>1880MHz</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>3500MHz</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>None</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QSpinBox" name="SourceHighPower">
|
||||
<property name="maximum">
|
||||
<number>63</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>63</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_7">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_2">
|
||||
<property name="title">
|
||||
<string>Lowband Source</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="SourceLowEnable">
|
||||
<property name="text">
|
||||
<string>Enable</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QFormLayout" name="formLayout_2">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string>Power:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QComboBox" name="SourceLowPower">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>2mA</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>4mA</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>6mA</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>8mA</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="text">
|
||||
<string>Frequency:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="SIUnitEdit" name="SourceLowFrequency"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_3">
|
||||
<property name="title">
|
||||
<string>Source Switch</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<item>
|
||||
<widget class="QRadioButton" name="SwitchLowband">
|
||||
<property name="text">
|
||||
<string>Lowband</string>
|
||||
</property>
|
||||
<attribute name="buttonGroup">
|
||||
<string notr="true">SourceSwitchGroup</string>
|
||||
</attribute>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="SwitchHighband">
|
||||
<property name="text">
|
||||
<string>Highband</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<attribute name="buttonGroup">
|
||||
<string notr="true">SourceSwitchGroup</string>
|
||||
</attribute>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_12">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_4">
|
||||
<property name="title">
|
||||
<string>Attenuator</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_4">
|
||||
<item>
|
||||
<widget class="QDoubleSpinBox" name="Attenuator">
|
||||
<property name="suffix">
|
||||
<string>db</string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<double>-31.750000000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>0.000000000000000</double>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<double>0.250000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_6">
|
||||
<property name="title">
|
||||
<string>Port Switch</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_5">
|
||||
<item>
|
||||
<widget class="QRadioButton" name="Port1Switch">
|
||||
<property name="text">
|
||||
<string>Port 1</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<attribute name="buttonGroup">
|
||||
<string notr="true">PortSwitchGroup</string>
|
||||
</attribute>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="Port2Switch">
|
||||
<property name="text">
|
||||
<string>Port 2</string>
|
||||
</property>
|
||||
<attribute name="buttonGroup">
|
||||
<string notr="true">PortSwitchGroup</string>
|
||||
</attribute>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_11">
|
||||
<property name="title">
|
||||
<string>Signal Analysis</string>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout" stretch="1,1">
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_13">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_7">
|
||||
<property name="title">
|
||||
<string>Highband LO</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_6">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="LOHighCE">
|
||||
<property name="text">
|
||||
<string>Chip Enable</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="LOLocked">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Locked</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QFormLayout" name="formLayout_3">
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_7">
|
||||
<property name="text">
|
||||
<string>Frequency:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="SIUnitEdit" name="LOHighFrequency">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_6">
|
||||
<property name="text">
|
||||
<string>IF:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="SIUnitEdit" name="IFHigh"/>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QComboBox" name="LOHighFreqType">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>IF</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Absolute</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_8">
|
||||
<property name="text">
|
||||
<string>Freq. Type:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_5">
|
||||
<property name="title">
|
||||
<string>Lowband LO</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_9">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="LOLowEnable">
|
||||
<property name="text">
|
||||
<string>Enable</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QFormLayout" name="formLayout_4">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_9">
|
||||
<property name="text">
|
||||
<string>Power:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QComboBox" name="LOLowPower">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>2mA</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>4mA</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>6mA</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>8mA</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_11">
|
||||
<property name="text">
|
||||
<string>Freq. Type:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QComboBox" name="LOLowFreqType">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>IF</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Absolute</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_10">
|
||||
<property name="text">
|
||||
<string>Frequency:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="SIUnitEdit" name="LOLowFrequency"/>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label_16">
|
||||
<property name="text">
|
||||
<string>IF:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="SIUnitEdit" name="IFLow"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_20">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_9">
|
||||
<property name="title">
|
||||
<string>Aquisition</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_8">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="Port1Enable">
|
||||
<property name="text">
|
||||
<string>Port 1 Enable</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="Port2Enable">
|
||||
<property name="text">
|
||||
<string>Port 2 Enable</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="RefEnable">
|
||||
<property name="text">
|
||||
<string>Reference Enable</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QFormLayout" name="formLayout_5">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_12">
|
||||
<property name="text">
|
||||
<string>Samples:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QSpinBox" name="Samples">
|
||||
<property name="minimum">
|
||||
<number>16</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>131072</number>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<number>16</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>131072</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_15">
|
||||
<property name="text">
|
||||
<string>Window:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QComboBox" name="cbWindow">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>None</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Kaiser</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Hann</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Flat Top</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_8">
|
||||
<property name="title">
|
||||
<string>LO Switch</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_11">
|
||||
<item>
|
||||
<widget class="QRadioButton" name="LOSwitchLowband">
|
||||
<property name="text">
|
||||
<string>Lowband</string>
|
||||
</property>
|
||||
<attribute name="buttonGroup">
|
||||
<string notr="true">LOSwitchGroup</string>
|
||||
</attribute>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="LOSwitchHighband">
|
||||
<property name="text">
|
||||
<string>Highband</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<attribute name="buttonGroup">
|
||||
<string notr="true">LOSwitchGroup</string>
|
||||
</attribute>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Orientation::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_12">
|
||||
<property name="title">
|
||||
<string>Measurements</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_16">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_16">
|
||||
<property name="title">
|
||||
<string>Port 1</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_19">
|
||||
<item>
|
||||
<layout class="QFormLayout" name="formLayout_9">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_25">
|
||||
<property name="text">
|
||||
<string>ADC min:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLineEdit" name="port1min"/>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_26">
|
||||
<property name="text">
|
||||
<string>ADC max:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLineEdit" name="port1max"/>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_27">
|
||||
<property name="text">
|
||||
<string>Magnitude:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QLineEdit" name="port1mag"/>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label_28">
|
||||
<property name="text">
|
||||
<string>Phase:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QLineEdit" name="port1phase"/>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="label_13">
|
||||
<property name="text">
|
||||
<string>Referenced:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QLineEdit" name="port1referenced"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_14">
|
||||
<property name="title">
|
||||
<string>Port 2</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_17">
|
||||
<item>
|
||||
<layout class="QFormLayout" name="formLayout_7">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_17">
|
||||
<property name="text">
|
||||
<string>ADC min:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLineEdit" name="port2min"/>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_18">
|
||||
<property name="text">
|
||||
<string>ADC max:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLineEdit" name="port2max"/>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_19">
|
||||
<property name="text">
|
||||
<string>Magnitude:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QLineEdit" name="port2mag"/>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label_20">
|
||||
<property name="text">
|
||||
<string>Phase:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QLineEdit" name="port2phase"/>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="label_14">
|
||||
<property name="text">
|
||||
<string>Referenced:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QLineEdit" name="port2referenced"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_15">
|
||||
<property name="title">
|
||||
<string>Reference</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_18">
|
||||
<item>
|
||||
<layout class="QFormLayout" name="formLayout_8">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_21">
|
||||
<property name="text">
|
||||
<string>ADC min:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLineEdit" name="refmin"/>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_22">
|
||||
<property name="text">
|
||||
<string>ADC max:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLineEdit" name="refmax"/>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_23">
|
||||
<property name="text">
|
||||
<string>Magnitude:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QLineEdit" name="refmag"/>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label_24">
|
||||
<property name="text">
|
||||
<string>Phase:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QLineEdit" name="refphase"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>SIUnitEdit</class>
|
||||
<extends>QLineEdit</extends>
|
||||
<header>CustomWidgets/siunitedit.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections/>
|
||||
<buttongroups>
|
||||
<buttongroup name="PortSwitchGroup"/>
|
||||
<buttongroup name="SourceSwitchGroup"/>
|
||||
<buttongroup name="LOSwitchGroup"/>
|
||||
</buttongroups>
|
||||
</ui>
|
||||
|
|
@ -1,179 +0,0 @@
|
|||
#include "manualcontroldialogVE0.h"
|
||||
|
||||
#include "ui_manualcontroldialogVE0.h"
|
||||
#include "Util/util.h"
|
||||
|
||||
#include <QComboBox>
|
||||
#include <QDebug>
|
||||
#include <QButtonGroup>
|
||||
#include <complex>
|
||||
|
||||
|
||||
using namespace std;
|
||||
|
||||
ManualControlDialogVE0::ManualControlDialogVE0(LibreVNADriver &dev, QWidget *parent) :
|
||||
QDialog(parent),
|
||||
ui(new Ui::ManualControlDialogVE0),
|
||||
dev(dev)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
setAttribute(Qt::WA_DeleteOnClose);
|
||||
|
||||
emit dev.acquireControl();
|
||||
|
||||
ui->src1Freq->setUnit("Hz");
|
||||
ui->src1Freq->setPrefixes(" kMG");
|
||||
ui->src1Freq->setPrecision(6);
|
||||
ui->src1Freq->setValueQuiet(100000000);
|
||||
|
||||
ui->src2Freq->setUnit("Hz");
|
||||
ui->src2Freq->setPrefixes(" kMG");
|
||||
ui->src2Freq->setPrecision(6);
|
||||
ui->src2Freq->setValueQuiet(100000000);
|
||||
|
||||
ui->LO1Freq->setUnit("Hz");
|
||||
ui->LO1Freq->setPrefixes(" kMG");
|
||||
ui->LO1Freq->setPrecision(6);
|
||||
ui->LO1Freq->setValueQuiet(100000000);
|
||||
|
||||
ui->LO2Freq->setUnit("Hz");
|
||||
ui->LO2Freq->setPrefixes(" kMG");
|
||||
ui->LO2Freq->setPrecision(6);
|
||||
ui->LO2Freq->setValueQuiet(100000000);
|
||||
|
||||
// Readonly widgets
|
||||
auto MakeReadOnly = [](QWidget* w) {
|
||||
w->setAttribute(Qt::WA_TransparentForMouseEvents);
|
||||
w->setFocusPolicy(Qt::NoFocus);
|
||||
};
|
||||
MakeReadOnly(ui->port1min);
|
||||
MakeReadOnly(ui->port1max);
|
||||
MakeReadOnly(ui->port1mag);
|
||||
MakeReadOnly(ui->port1phase);
|
||||
MakeReadOnly(ui->port1referenced);
|
||||
MakeReadOnly(ui->port2min);
|
||||
MakeReadOnly(ui->port2max);
|
||||
MakeReadOnly(ui->port2mag);
|
||||
MakeReadOnly(ui->port2phase);
|
||||
MakeReadOnly(ui->port2referenced);
|
||||
MakeReadOnly(ui->refmin);
|
||||
MakeReadOnly(ui->refmax);
|
||||
MakeReadOnly(ui->refmag);
|
||||
MakeReadOnly(ui->refphase);
|
||||
|
||||
connect(&dev, &LibreVNADriver::receivedPacket, this, [=](const Protocol::PacketInfo &p){
|
||||
if(p.type == Protocol::PacketType::ManualStatus) {
|
||||
NewStatus(p.manualStatus);
|
||||
}
|
||||
}, Qt::QueuedConnection);
|
||||
|
||||
connect(ui->src1CE, &QCheckBox::toggled, [=](bool) { UpdateDevice(); });
|
||||
connect(ui->src2CE, &QCheckBox::toggled, [=](bool) { UpdateDevice(); });
|
||||
connect(ui->LO1CE, &QCheckBox::toggled, [=](bool) { UpdateDevice(); });
|
||||
connect(ui->LO2CE, &QCheckBox::toggled, [=](bool) { UpdateDevice(); });
|
||||
connect(ui->srcAmp, &QCheckBox::toggled, [=](bool) { UpdateDevice(); });
|
||||
connect(ui->LO1CE, &QCheckBox::toggled, [=](bool) { UpdateDevice(); });
|
||||
|
||||
connect(ui->srcSel, qOverload<int>(&QComboBox::activated), [=](int) { UpdateDevice(); });
|
||||
connect(ui->portSel, qOverload<int>(&QComboBox::activated), [=](int) { UpdateDevice(); });
|
||||
connect(ui->LOSel, qOverload<int>(&QComboBox::activated), [=](int) { UpdateDevice(); });
|
||||
connect(ui->P1Path, qOverload<int>(&QComboBox::activated), [=](int) { UpdateDevice(); });
|
||||
connect(ui->P1Amp, qOverload<int>(&QComboBox::activated), [=](int) { UpdateDevice(); });
|
||||
connect(ui->P2Path, qOverload<int>(&QComboBox::activated), [=](int) { UpdateDevice(); });
|
||||
connect(ui->P2Amp, qOverload<int>(&QComboBox::activated), [=](int) { UpdateDevice(); });
|
||||
connect(ui->RefAmp, qOverload<int>(&QComboBox::activated), [=](int) { UpdateDevice(); });
|
||||
connect(ui->Window, qOverload<int>(&QComboBox::activated), [=](int) { UpdateDevice(); });
|
||||
|
||||
connect(ui->src1Freq, &SIUnitEdit::valueChanged, [=](double) { UpdateDevice(); });
|
||||
connect(ui->src2Freq, &SIUnitEdit::valueChanged, [=](double) { UpdateDevice(); });
|
||||
connect(ui->LO1Freq, &SIUnitEdit::valueChanged, [=](double) { UpdateDevice(); });
|
||||
connect(ui->LO2Freq, &SIUnitEdit::valueChanged, [=](double) { UpdateDevice(); });
|
||||
|
||||
connect(ui->src1Pwr, qOverload<int>(&QSpinBox::valueChanged), [=](double) { UpdateDevice(); });
|
||||
connect(ui->src2Pwr, qOverload<int>(&QSpinBox::valueChanged), [=](double) { UpdateDevice(); });
|
||||
connect(ui->LO1Pwr, qOverload<int>(&QSpinBox::valueChanged), [=](double) { UpdateDevice(); });
|
||||
connect(ui->LO2Pwr, qOverload<int>(&QSpinBox::valueChanged), [=](double) { UpdateDevice(); });
|
||||
connect(ui->Samples, qOverload<int>(&QSpinBox::valueChanged), [=](double) { UpdateDevice(); });
|
||||
|
||||
UpdateDevice();
|
||||
}
|
||||
|
||||
ManualControlDialogVE0::~ManualControlDialogVE0()
|
||||
{
|
||||
emit dev.releaseControl();
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void ManualControlDialogVE0::NewStatus(Protocol::ManualStatus status)
|
||||
{
|
||||
// ADC values
|
||||
auto &s = status.VE0;
|
||||
ui->port1min->setText(QString::number(s.port1min));
|
||||
ui->port1max->setText(QString::number(s.port1max));
|
||||
auto port1 = complex<double>(s.port1real, s.port1imag);
|
||||
ui->port1mag->setText(QString::number(abs(port1)));
|
||||
ui->port1phase->setText(QString::number(arg(port1)*180/M_PI));
|
||||
|
||||
ui->port2min->setText(QString::number(s.port2min));
|
||||
ui->port2max->setText(QString::number(s.port2max));
|
||||
auto port2 = complex<double>(s.port2real, s.port2imag);
|
||||
ui->port2mag->setText(QString::number(abs(port2)));
|
||||
ui->port2phase->setText(QString::number(arg(port2)*180/M_PI));
|
||||
|
||||
ui->refmin->setText(QString::number(s.refmin));
|
||||
ui->refmax->setText(QString::number(s.refmax));
|
||||
auto ref = complex<double>(s.refreal, s.refimag);
|
||||
ui->refmag->setText(QString::number(abs(ref)));
|
||||
ui->refphase->setText(QString::number(arg(ref)*180/M_PI));
|
||||
|
||||
port1referenced = port1 / ref;
|
||||
port2referenced = port2 / ref;
|
||||
auto port1db = Util::SparamTodB(port1referenced);
|
||||
auto port2db = Util::SparamTodB(port2referenced);
|
||||
|
||||
ui->port1referenced->setText(QString::number(port1db, 'f', 2) + "db@" + QString::number(arg(port1referenced)*180/M_PI, 'f', 2) + "°");
|
||||
ui->port2referenced->setText(QString::number(port2db, 'f', 2) + "db@" + QString::number(arg(port2referenced)*180/M_PI, 'f', 2) + "°");
|
||||
}
|
||||
|
||||
void ManualControlDialogVE0::UpdateDevice()
|
||||
{
|
||||
Protocol::PacketInfo p;
|
||||
p.type = Protocol::PacketType::ManualControl;
|
||||
auto &m = p.manual.VE0;
|
||||
// Source
|
||||
m.src1Freq = ui->src1Freq->value();
|
||||
m.src2Freq = ui->src2Freq->value();
|
||||
m.src1Pwr = ui->src1Pwr->value();
|
||||
m.src2Pwr = ui->src2Pwr->value();
|
||||
m.src1CE = ui->src1CE->isChecked();
|
||||
m.src2CE = ui->src2CE->isChecked();
|
||||
m.srcSel = ui->srcSel->currentIndex();
|
||||
m.portSel = ui->portSel->currentIndex();
|
||||
m.srcAmp = ui->srcAmp->isChecked();
|
||||
// LO
|
||||
m.LO1Freq = ui->LO1Freq->value();
|
||||
m.LO2Freq = ui->LO2Freq->value();
|
||||
m.LO1Pwr = ui->LO1Pwr->value();
|
||||
m.LO2Pwr = ui->LO2Pwr->value();
|
||||
m.LO1CE = ui->LO1CE->isChecked();
|
||||
m.LO2CE = ui->LO2CE->isChecked();
|
||||
m.LOSel = ui->LOSel->currentIndex();
|
||||
// Port 1
|
||||
m.P1PathSel = ui->P1Path->currentIndex();
|
||||
m.P1AmpOn = ui->P1Amp->currentIndex() == 1 ? 1 : 0;
|
||||
m.P1AmpBypass = ui->P1Amp->currentIndex() == 2 ? 1 : 0;
|
||||
// Port 2
|
||||
m.P2PathSel = ui->P2Path->currentIndex();
|
||||
m.P2AmpOn = ui->P2Amp->currentIndex() == 1 ? 1 : 0;
|
||||
m.P2AmpBypass = ui->P2Amp->currentIndex() == 2 ? 1 : 0;
|
||||
// Reference
|
||||
m.RefAmpOn = ui->RefAmp->currentIndex() == 1 ? 1 : 0;
|
||||
m.RefAmpBypass = ui->RefAmp->currentIndex() == 2 ? 1 : 0;
|
||||
// Acquisition
|
||||
m.Samples = ui->Samples->value();
|
||||
m.WindowType = ui->Window->currentIndex();
|
||||
|
||||
qDebug() << "Updating manual control state";
|
||||
|
||||
dev.SendPacket(p);
|
||||
}
|
||||
|
|
@ -1,34 +0,0 @@
|
|||
#ifndef MANUALCONTROLDIALOGVE0_H
|
||||
#define MANUALCONTROLDIALOGVE0_H
|
||||
|
||||
#include "librevnadriver.h"
|
||||
|
||||
#include <QDialog>
|
||||
#include <complex>
|
||||
|
||||
namespace Ui {
|
||||
class ManualControlDialogVE0;
|
||||
}
|
||||
|
||||
class ManualControlDialogVE0 : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit ManualControlDialogVE0(LibreVNADriver &dev, QWidget *parent = nullptr);
|
||||
~ManualControlDialogVE0();
|
||||
|
||||
public slots:
|
||||
void NewStatus(Protocol::ManualStatus status);
|
||||
|
||||
private:
|
||||
void UpdateDevice();
|
||||
Ui::ManualControlDialogVE0 *ui;
|
||||
LibreVNADriver &dev;
|
||||
std::complex<double> port1referenced;
|
||||
std::complex<double> port2referenced;
|
||||
|
||||
std::vector<SCPICommand*> commands;
|
||||
};
|
||||
|
||||
#endif // MANUALCONTROLDIALOGVE0_H
|
||||
|
|
@ -1,797 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>ManualControlDialogVE0</class>
|
||||
<widget class="QDialog" name="ManualControlDialogVE0">
|
||||
<property name="windowModality">
|
||||
<enum>Qt::WindowModality::ApplicationModal</enum>
|
||||
</property>
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>777</width>
|
||||
<height>717</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Manual System Control</string>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_4">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_10">
|
||||
<property name="title">
|
||||
<string>Signal Generation</string>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_3">
|
||||
<property name="title">
|
||||
<string>Source</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox">
|
||||
<property name="title">
|
||||
<string>PLL1</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_10">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="src1CE">
|
||||
<property name="text">
|
||||
<string>Chip Enable</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QFormLayout" name="formLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Power:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Frequency:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="SIUnitEdit" name="src1Freq"/>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QSpinBox" name="src1Pwr">
|
||||
<property name="maximum">
|
||||
<number>18</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>18</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_2">
|
||||
<property name="title">
|
||||
<string>PLL2</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_13">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="src2CE">
|
||||
<property name="text">
|
||||
<string>Chip Enable</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QFormLayout" name="formLayout_2">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>Power:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string>Frequency:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="SIUnitEdit" name="src2Freq"/>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QSpinBox" name="src2Pwr">
|
||||
<property name="maximum">
|
||||
<number>18</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>18</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QFormLayout" name="formLayout_10">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="text">
|
||||
<string>PLL selection:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QComboBox" name="srcSel">
|
||||
<property name="currentIndex">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>None</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>PLL1</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>PLL2</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_16">
|
||||
<property name="text">
|
||||
<string>Amplifier:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QCheckBox" name="srcAmp">
|
||||
<property name="text">
|
||||
<string>Enable</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_10">
|
||||
<property name="text">
|
||||
<string>Port selection:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QComboBox" name="portSel">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>None</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Port 1</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Port 2</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Orientation::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_4">
|
||||
<property name="title">
|
||||
<string>LO</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_5">
|
||||
<property name="title">
|
||||
<string>PLL1</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_11">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="LO1CE">
|
||||
<property name="text">
|
||||
<string>Chip Enable</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QFormLayout" name="formLayout_11">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_29">
|
||||
<property name="text">
|
||||
<string>Power:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_30">
|
||||
<property name="text">
|
||||
<string>Frequency:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="SIUnitEdit" name="LO1Freq"/>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QSpinBox" name="LO1Pwr">
|
||||
<property name="maximum">
|
||||
<number>63</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>18</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_6">
|
||||
<property name="title">
|
||||
<string>PLL2</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_14">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="LO2CE">
|
||||
<property name="text">
|
||||
<string>Chip Enable</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QFormLayout" name="formLayout_12">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_31">
|
||||
<property name="text">
|
||||
<string>Power:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_32">
|
||||
<property name="text">
|
||||
<string>Frequency:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="SIUnitEdit" name="LO2Freq"/>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QSpinBox" name="LO2Pwr">
|
||||
<property name="maximum">
|
||||
<number>18</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>18</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QFormLayout" name="formLayout_13">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_33">
|
||||
<property name="text">
|
||||
<string>PLL selection:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QComboBox" name="LOSel">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>PLL1</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>PLL2</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Orientation::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_11">
|
||||
<property name="title">
|
||||
<string>Signal Analysis</string>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_6">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_7">
|
||||
<property name="title">
|
||||
<string>Port 1</string>
|
||||
</property>
|
||||
<layout class="QFormLayout" name="formLayout_3">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_6">
|
||||
<property name="text">
|
||||
<string>Path:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QComboBox" name="P1Path">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Reflection</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Transmission</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_7">
|
||||
<property name="text">
|
||||
<string>Amplifier:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QComboBox" name="P1Amp">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Off</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>On</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Bypass</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_8">
|
||||
<property name="title">
|
||||
<string>Port 2</string>
|
||||
</property>
|
||||
<layout class="QFormLayout" name="formLayout_4">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_8">
|
||||
<property name="text">
|
||||
<string>Path:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QComboBox" name="P2Path">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Reflection</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Transmission</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_9">
|
||||
<property name="text">
|
||||
<string>Amplifier:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QComboBox" name="P2Amp">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Off</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>On</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Bypass</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_8">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_9">
|
||||
<property name="title">
|
||||
<string>Reference</string>
|
||||
</property>
|
||||
<layout class="QFormLayout" name="formLayout_5">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_11">
|
||||
<property name="text">
|
||||
<string>Amplifier:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QComboBox" name="RefAmp">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Off</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>On</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Bypass</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_13">
|
||||
<property name="title">
|
||||
<string>Acquisition</string>
|
||||
</property>
|
||||
<layout class="QFormLayout" name="formLayout_6">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_12">
|
||||
<property name="text">
|
||||
<string>Samples:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QSpinBox" name="Samples">
|
||||
<property name="minimum">
|
||||
<number>8</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>131072</number>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<number>8</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>131072</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_15">
|
||||
<property name="text">
|
||||
<string>Window:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QComboBox" name="Window">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>None</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Kaiser</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Hann</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Flat Top</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_12">
|
||||
<property name="title">
|
||||
<string>Measurements</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_16">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_16">
|
||||
<property name="title">
|
||||
<string>Port 1</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_19">
|
||||
<item>
|
||||
<layout class="QFormLayout" name="formLayout_9">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_25">
|
||||
<property name="text">
|
||||
<string>ADC min:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLineEdit" name="port1min"/>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_26">
|
||||
<property name="text">
|
||||
<string>ADC max:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLineEdit" name="port1max"/>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_27">
|
||||
<property name="text">
|
||||
<string>Magnitude:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QLineEdit" name="port1mag"/>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label_28">
|
||||
<property name="text">
|
||||
<string>Phase:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QLineEdit" name="port1phase"/>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="label_13">
|
||||
<property name="text">
|
||||
<string>Referenced:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QLineEdit" name="port1referenced"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_14">
|
||||
<property name="title">
|
||||
<string>Port 2</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_17">
|
||||
<item>
|
||||
<layout class="QFormLayout" name="formLayout_7">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_17">
|
||||
<property name="text">
|
||||
<string>ADC min:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLineEdit" name="port2min"/>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_18">
|
||||
<property name="text">
|
||||
<string>ADC max:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLineEdit" name="port2max"/>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_19">
|
||||
<property name="text">
|
||||
<string>Magnitude:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QLineEdit" name="port2mag"/>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label_20">
|
||||
<property name="text">
|
||||
<string>Phase:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QLineEdit" name="port2phase"/>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="label_14">
|
||||
<property name="text">
|
||||
<string>Referenced:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QLineEdit" name="port2referenced"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_15">
|
||||
<property name="title">
|
||||
<string>Reference</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_18">
|
||||
<item>
|
||||
<layout class="QFormLayout" name="formLayout_8">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_21">
|
||||
<property name="text">
|
||||
<string>ADC min:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLineEdit" name="refmin"/>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_22">
|
||||
<property name="text">
|
||||
<string>ADC max:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLineEdit" name="refmax"/>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_23">
|
||||
<property name="text">
|
||||
<string>Magnitude:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QLineEdit" name="refmag"/>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label_24">
|
||||
<property name="text">
|
||||
<string>Phase:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QLineEdit" name="refphase"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>SIUnitEdit</class>
|
||||
<extends>QLineEdit</extends>
|
||||
<header>CustomWidgets/siunitedit.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections/>
|
||||
<buttongroups>
|
||||
<buttongroup name="PortSwitchGroup"/>
|
||||
<buttongroup name="SourceSwitchGroup"/>
|
||||
</buttongroups>
|
||||
</ui>
|
||||
|
|
@ -5,7 +5,6 @@
|
|||
#include "LibreVNA/Compound/compounddriver.h"
|
||||
#include "SSA3000X/ssa3000xdriver.h"
|
||||
#include "SNA5000A/sna5000adriver.h"
|
||||
#include "Harogic/harogicb60.h"
|
||||
|
||||
DeviceDriver *DeviceDriver::activeDriver = nullptr;
|
||||
|
||||
|
|
@ -26,7 +25,6 @@ std::vector<DeviceDriver *> DeviceDriver::getDrivers()
|
|||
ret.push_back(new CompoundDriver);
|
||||
ret.push_back(new SSA3000XDriver);
|
||||
ret.push_back(new SNA5000ADriver);
|
||||
ret.push_back(new HarogicB60);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -68,9 +68,8 @@ void DeviceLog::clear()
|
|||
|
||||
void DeviceLog::on_bToFile_clicked()
|
||||
{
|
||||
auto filename = QFileDialog::getSaveFileName(this, "Select file for device log", Preferences::getInstance().UISettings.Paths.packetlog, "", nullptr, Preferences::QFileDialogOptions());
|
||||
auto filename = QFileDialog::getSaveFileName(this, "Select file for device log", "", "", nullptr, Preferences::QFileDialogOptions());
|
||||
if(filename.length() > 0) {
|
||||
Preferences::getInstance().UISettings.Paths.packetlog = QFileInfo(filename).path();
|
||||
// create file
|
||||
ofstream file;
|
||||
file.open(filename.toStdString());
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@ HEADERS += \
|
|||
Calibration/LibreCAL/usbdevice.h \
|
||||
Calibration/calibration.h \
|
||||
Calibration/calibrationmeasurement.h \
|
||||
Calibration/calibrationviewdialog.h \
|
||||
Calibration/calkit.h \
|
||||
Calibration/calkitdialog.h \
|
||||
Calibration/calstandard.h \
|
||||
|
|
@ -20,13 +19,11 @@ HEADERS += \
|
|||
CustomWidgets/toggleswitch.h \
|
||||
CustomWidgets/touchstoneimport.h \
|
||||
CustomWidgets/tracesetselector.h \
|
||||
Device/Harogic/harogicb60.h \
|
||||
Device/LibreVNA/Compound/compounddevice.h \
|
||||
Device/LibreVNA/Compound/compounddeviceeditdialog.h \
|
||||
Device/LibreVNA/Compound/compounddriver.h \
|
||||
Device/LibreVNA/amplitudecaldialog.h \
|
||||
Device/LibreVNA/deviceconfigurationdialogv1.h \
|
||||
Device/LibreVNA/deviceconfigurationdialogvd0.h \
|
||||
Device/LibreVNA/deviceconfigurationdialogvfe.h \
|
||||
Device/LibreVNA/deviceconfigurationdialogvff.h \
|
||||
Device/LibreVNA/devicepacketlog.h \
|
||||
|
|
@ -37,8 +34,6 @@ HEADERS += \
|
|||
Device/LibreVNA/librevnatcpdriver.h \
|
||||
Device/LibreVNA/librevnausbdriver.h \
|
||||
Device/LibreVNA/manualcontroldialogV1.h \
|
||||
Device/LibreVNA/manualcontroldialogVD0.h \
|
||||
Device/LibreVNA/manualcontroldialogVE0.h \
|
||||
Device/LibreVNA/manualcontroldialogvfe.h \
|
||||
Device/LibreVNA/manualcontroldialogvff.h \
|
||||
Device/LibreVNA/receivercaldialog.h \
|
||||
|
|
@ -119,7 +114,6 @@ HEADERS += \
|
|||
Traces/eyediagramplot.h \
|
||||
Traces/fftcomplex.h \
|
||||
Traces/sparamtraceselector.h \
|
||||
Traces/sparamtraceselectordialog.h \
|
||||
Traces/trace.h \
|
||||
Traces/traceaxis.h \
|
||||
Traces/tracecsvexport.h \
|
||||
|
|
@ -165,7 +159,6 @@ HEADERS += \
|
|||
preferences.h \
|
||||
savable.h \
|
||||
scpi.h \
|
||||
screenshot.h \
|
||||
streamingserver.h \
|
||||
tcpserver.h \
|
||||
touchstone.h \
|
||||
|
|
@ -178,7 +171,6 @@ SOURCES += \
|
|||
Calibration/LibreCAL/usbdevice.cpp \
|
||||
Calibration/calibration.cpp \
|
||||
Calibration/calibrationmeasurement.cpp \
|
||||
Calibration/calibrationviewdialog.cpp \
|
||||
Calibration/calkit.cpp \
|
||||
Calibration/calkitdialog.cpp \
|
||||
Calibration/calstandard.cpp \
|
||||
|
|
@ -192,13 +184,11 @@ SOURCES += \
|
|||
CustomWidgets/toggleswitch.cpp \
|
||||
CustomWidgets/touchstoneimport.cpp \
|
||||
CustomWidgets/tracesetselector.cpp \
|
||||
Device/Harogic/harogicb60.cpp \
|
||||
Device/LibreVNA/Compound/compounddevice.cpp \
|
||||
Device/LibreVNA/Compound/compounddeviceeditdialog.cpp \
|
||||
Device/LibreVNA/Compound/compounddriver.cpp \
|
||||
Device/LibreVNA/amplitudecaldialog.cpp \
|
||||
Device/LibreVNA/deviceconfigurationdialogv1.cpp \
|
||||
Device/LibreVNA/deviceconfigurationdialogvd0.cpp \
|
||||
Device/LibreVNA/deviceconfigurationdialogvfe.cpp \
|
||||
Device/LibreVNA/deviceconfigurationdialogvff.cpp \
|
||||
Device/LibreVNA/devicepacketlog.cpp \
|
||||
|
|
@ -209,8 +199,6 @@ SOURCES += \
|
|||
Device/LibreVNA/librevnatcpdriver.cpp \
|
||||
Device/LibreVNA/librevnausbdriver.cpp \
|
||||
Device/LibreVNA/manualcontroldialogV1.cpp \
|
||||
Device/LibreVNA/manualcontroldialogVD0.cpp \
|
||||
Device/LibreVNA/manualcontroldialogVE0.cpp \
|
||||
Device/LibreVNA/manualcontroldialogvfe.cpp \
|
||||
Device/LibreVNA/manualcontroldialogvff.cpp \
|
||||
Device/LibreVNA/receivercaldialog.cpp \
|
||||
|
|
@ -279,7 +267,6 @@ SOURCES += \
|
|||
Traces/eyediagramplot.cpp \
|
||||
Traces/fftcomplex.cpp \
|
||||
Traces/sparamtraceselector.cpp \
|
||||
Traces/sparamtraceselectordialog.cpp \
|
||||
Traces/trace.cpp \
|
||||
Traces/traceaxis.cpp \
|
||||
Traces/tracecsvexport.cpp \
|
||||
|
|
@ -323,7 +310,6 @@ SOURCES += \
|
|||
preferences.cpp \
|
||||
savable.cpp \
|
||||
scpi.cpp \
|
||||
screenshot.cpp \
|
||||
streamingserver.cpp \
|
||||
tcpserver.cpp \
|
||||
touchstone.cpp \
|
||||
|
|
@ -342,7 +328,7 @@ mac{
|
|||
PKGCONFIG += libusb-1.0
|
||||
}
|
||||
|
||||
QT += widgets network svg
|
||||
QT += widgets network
|
||||
|
||||
FORMS += \
|
||||
Calibration/CalStandardLineEditDialog.ui \
|
||||
|
|
@ -354,7 +340,6 @@ FORMS += \
|
|||
Calibration/LibreCAL/factoryUpdateDialog.ui \
|
||||
Calibration/LibreCAL/librecaldialog.ui \
|
||||
Calibration/calibrationdialogui.ui \
|
||||
Calibration/calibrationviewdialog.ui \
|
||||
Calibration/calkitdialog.ui \
|
||||
Calibration/manualcalibrationdialog.ui \
|
||||
CustomWidgets/csvimport.ui \
|
||||
|
|
@ -367,7 +352,6 @@ FORMS += \
|
|||
Device/LibreVNA/amplitudecaldialog.ui \
|
||||
Device/LibreVNA/automaticamplitudedialog.ui \
|
||||
Device/LibreVNA/deviceconfigurationdialogv1.ui \
|
||||
Device/LibreVNA/deviceconfigurationdialogvd0.ui \
|
||||
Device/LibreVNA/deviceconfigurationdialogvfe.ui \
|
||||
Device/LibreVNA/deviceconfigurationdialogvff.ui \
|
||||
Device/LibreVNA/devicepacketlogview.ui \
|
||||
|
|
@ -375,8 +359,6 @@ FORMS += \
|
|||
Device/LibreVNA/frequencycaldialog.ui \
|
||||
Device/LibreVNA/librevnadriversettingswidget.ui \
|
||||
Device/LibreVNA/manualcontroldialogV1.ui \
|
||||
Device/LibreVNA/manualcontroldialogVD0.ui \
|
||||
Device/LibreVNA/manualcontroldialogVE0.ui \
|
||||
Device/LibreVNA/manualcontroldialogvfe.ui \
|
||||
Device/LibreVNA/manualcontroldialogvff.ui \
|
||||
Device/devicelog.ui \
|
||||
|
|
@ -401,7 +383,6 @@ FORMS += \
|
|||
Traces/eyediagrameditdialog.ui \
|
||||
Traces/smithchartdialog.ui \
|
||||
Traces/polarchartdialog.ui \
|
||||
Traces/sparamtraceselectordialog.ui \
|
||||
Traces/tracecsvexport.ui \
|
||||
Traces/traceeditdialog.ui \
|
||||
Traces/traceimportdialog.ui \
|
||||
|
|
|
|||
|
|
@ -64,9 +64,6 @@ 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();
|
||||
|
|
@ -115,7 +112,7 @@ SpectrumAnalyzer::SpectrumAnalyzer(AppWindow *window, QString name)
|
|||
|
||||
auto eStart = new SIUnitEdit("Hz", " kMG", 6);
|
||||
// calculate width required with expected string length
|
||||
auto width = QFontMetrics(eStart->font()).horizontalAdvance("10.00000 MHz") + 15;
|
||||
auto width = QFontMetrics(eStart->font()).horizontalAdvance("3.00000GHz") + 15;
|
||||
eStart->setFixedWidth(width);
|
||||
eStart->setToolTip("Start frequency");
|
||||
connect(eStart, &SIUnitEdit::valueChanged, this, &SpectrumAnalyzer::SetStartFreq);
|
||||
|
|
@ -399,7 +396,6 @@ 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();
|
||||
|
|
@ -506,7 +502,6 @@ void SpectrumAnalyzer::fromJSON(nlohmann::json j)
|
|||
EnableNormalization(correctSize);
|
||||
}
|
||||
SetSingleSweep(sweep.value("single", singleSweep));
|
||||
SetAveraging(sweep.value("averages", averages));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -589,9 +584,6 @@ 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()
|
||||
|
|
@ -922,7 +914,7 @@ void SpectrumAnalyzer::ConfigureDevice()
|
|||
average.reset(DeviceDriver::SApoints());
|
||||
UpdateAverageCount();
|
||||
traceModel.clearLiveData();
|
||||
traceModel.setSpan(settings.freqStart, settings.freqStop);
|
||||
emit traceModel.SpanChanged(settings.freqStart, settings.freqStop);
|
||||
} else {
|
||||
if(window->getDevice()) {
|
||||
changingSettings = true;
|
||||
|
|
@ -1110,12 +1102,6 @@ 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,10 +132,6 @@ 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);
|
||||
|
|
|
|||
|
|
@ -130,7 +130,6 @@ QString Marker::formatToString(Marker::Format f)
|
|||
case Format::Inductance: return "Inductance";
|
||||
case Format::QualityFactor: return "Quality Factor";
|
||||
case Format::GroupDelay: return "Group Delay";
|
||||
case Format::NumberOfPeaks: return "Number of peaks";
|
||||
case Format::TOI: return "Third order intercept";
|
||||
case Format::AvgTone: return "Average Tone Level";
|
||||
case Format::AvgModulationProduct: return "Average Modulation Product Level";
|
||||
|
|
@ -195,6 +194,8 @@ std::vector<Marker::Format> Marker::applicableFormats()
|
|||
case Type::Delta:
|
||||
case Type::Maximum:
|
||||
case Type::Minimum:
|
||||
case Type::PeakTable:
|
||||
case Type::NegativePeakTable:
|
||||
if(Trace::isSAParameter(parentTrace->liveParameter())) {
|
||||
ret.push_back(Format::dBm);
|
||||
ret.push_back(Format::dBuV);
|
||||
|
|
@ -217,10 +218,6 @@ std::vector<Marker::Format> Marker::applicableFormats()
|
|||
}
|
||||
}
|
||||
break;
|
||||
case Type::PeakTable:
|
||||
case Type::NegativePeakTable:
|
||||
ret.push_back(Format::NumberOfPeaks);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
@ -231,6 +228,8 @@ std::vector<Marker::Format> Marker::applicableFormats()
|
|||
case Type::Delta:
|
||||
case Type::Maximum:
|
||||
case Type::Minimum:
|
||||
case Type::PeakTable:
|
||||
case Type::NegativePeakTable:
|
||||
if(Trace::isSAParameter(parentTrace->liveParameter())) {
|
||||
ret.push_back(Format::dBm);
|
||||
ret.push_back(Format::dBuV);
|
||||
|
|
@ -254,10 +253,6 @@ std::vector<Marker::Format> Marker::applicableFormats()
|
|||
}
|
||||
}
|
||||
break;
|
||||
case Type::PeakTable:
|
||||
case Type::NegativePeakTable:
|
||||
ret.push_back(Format::NumberOfPeaks);
|
||||
break;
|
||||
case Type::Bandpass:
|
||||
ret.push_back(Format::CenterBandwidth);
|
||||
ret.push_back(Format::InsertionLoss);
|
||||
|
|
@ -456,11 +451,7 @@ QString Marker::readableData(Format f)
|
|||
switch(type) {
|
||||
case Type::PeakTable:
|
||||
case Type::NegativePeakTable:
|
||||
switch(f) {
|
||||
case Format::NumberOfPeaks: return "Found " + QString::number(helperMarkers.size()) + " peak" + (helperMarkers.size() == 1 ? "" : "s");
|
||||
default: return "Invalid";
|
||||
}
|
||||
break;
|
||||
return "Found " + QString::number(helperMarkers.size()) + " peaks";
|
||||
case Type::Delta: {
|
||||
if(!delta) {
|
||||
return "Invalid delta marker";
|
||||
|
|
@ -597,7 +588,6 @@ QString Marker::readableData(Format f)
|
|||
case Format::maxDeltaPos:
|
||||
return "max. Δ+:"+Unit::ToString(maxDeltaPos, "dB", " ", 4);
|
||||
break;
|
||||
case Format::NumberOfPeaks:
|
||||
case Format::Last:
|
||||
return "Invalid";
|
||||
}
|
||||
|
|
@ -793,13 +783,6 @@ void Marker::setPosition(double pos)
|
|||
emit positionChanged(position);
|
||||
}
|
||||
|
||||
void Marker::setToMiddleOfTrace()
|
||||
{
|
||||
if(parentTrace) {
|
||||
setPosition((parentTrace->minX() + parentTrace->maxX()) / 2);
|
||||
}
|
||||
}
|
||||
|
||||
void Marker::parentTraceDeleted(Trace *t)
|
||||
{
|
||||
if(t == parentTrace) {
|
||||
|
|
@ -909,6 +892,10 @@ void Marker::deltaDeleted()
|
|||
|
||||
void Marker::updateContextmenu()
|
||||
{
|
||||
if(parent) {
|
||||
// do nothing, using contextmenu from parent anyway
|
||||
return;
|
||||
}
|
||||
// check if the contextmenu or one of its submenus is currently open
|
||||
auto *activeWidget = QApplication::activePopupWidget();
|
||||
while (activeWidget) {
|
||||
|
|
@ -923,8 +910,6 @@ void Marker::updateContextmenu()
|
|||
contextmenu.clear();
|
||||
contextmenu.addSection("Marker");
|
||||
|
||||
if(!parent) {
|
||||
// type can only be changed for top level markers
|
||||
auto typemenu = contextmenu.addMenu("Type");
|
||||
auto typegroup = new QActionGroup(&contextmenu);
|
||||
for(auto t : getSupportedTypes()) {
|
||||
|
|
@ -939,7 +924,6 @@ void Marker::updateContextmenu()
|
|||
typegroup->addAction(setTypeAction);
|
||||
typemenu->addAction(setTypeAction);
|
||||
}
|
||||
}
|
||||
|
||||
auto table = contextmenu.addMenu("Data Format in Table");
|
||||
auto tablegroup = new QActionGroup(&contextmenu);
|
||||
|
|
@ -981,8 +965,6 @@ void Marker::updateContextmenu()
|
|||
}
|
||||
}
|
||||
|
||||
if(!parent) {
|
||||
// grouping and deleting is only possible for top level markers
|
||||
contextmenu.addSeparator();
|
||||
|
||||
bool needsSeparator = false;
|
||||
|
|
@ -1026,7 +1008,6 @@ void Marker::updateContextmenu()
|
|||
connect(deleteAction, &QAction::triggered, this, &Marker::deleteLater);
|
||||
contextmenu.addAction(deleteAction);
|
||||
}
|
||||
}
|
||||
|
||||
void Marker::traceTypeChanged()
|
||||
{
|
||||
|
|
@ -1250,7 +1231,6 @@ void Marker::setType(Marker::Type t)
|
|||
helper->suffix = h.suffix;
|
||||
helper->assignTrace(parentTrace);
|
||||
helper->setType(h.type);
|
||||
helper->setVisible(visible);
|
||||
helperMarkers.push_back(helper);
|
||||
}
|
||||
if(type == Type::Flatness) {
|
||||
|
|
@ -1487,35 +1467,6 @@ void Marker::setNumber(int value)
|
|||
}
|
||||
}
|
||||
|
||||
QWidget *Marker::getTraceEditor(QAbstractItemDelegate *delegate)
|
||||
{
|
||||
auto c = new QComboBox;
|
||||
for(auto t : model->getModel().getTraces()) {
|
||||
c->addItem(t->name());
|
||||
if(parentTrace == t) {
|
||||
// select this item
|
||||
c->setCurrentIndex(c->count() - 1);
|
||||
}
|
||||
}
|
||||
connect(c, qOverload<int>(&QComboBox::currentIndexChanged), [=](int) {
|
||||
emit delegate->commitData(c);
|
||||
});
|
||||
return c;
|
||||
}
|
||||
|
||||
void Marker::updateTraceFromEditor(QWidget *w)
|
||||
{
|
||||
QComboBox *c = (QComboBox*) w;
|
||||
for(auto t : model->getModel().getTraces()) {
|
||||
if(c->currentText() == t->name()) {
|
||||
if(parentTrace != t) {
|
||||
assignTrace(t);
|
||||
}
|
||||
}
|
||||
}
|
||||
update();
|
||||
}
|
||||
|
||||
QWidget *Marker::getTypeEditor(QAbstractItemDelegate *delegate)
|
||||
{
|
||||
auto c = new QComboBox;
|
||||
|
|
@ -1820,8 +1771,12 @@ void Marker::setVisible(bool visible)
|
|||
}
|
||||
|
||||
QMenu *Marker::getContextMenu() {
|
||||
if(parent) {
|
||||
return parent->getContextMenu();
|
||||
} else {
|
||||
return &contextmenu;
|
||||
}
|
||||
}
|
||||
|
||||
void Marker::update()
|
||||
{
|
||||
|
|
@ -1845,29 +1800,20 @@ void Marker::update()
|
|||
break;
|
||||
case Type::PeakTable:
|
||||
case Type::NegativePeakTable: {
|
||||
deleteHelperMarkers();
|
||||
auto peaks = parentTrace->findPeakFrequencies(100, peakThreshold, 3.0, xmin, xmax, type == Type::NegativePeakTable);
|
||||
for(unsigned int i=0;i<peaks.size();i++) {
|
||||
if(helperMarkers.size() <= i) {
|
||||
// needs to create a new helper marker
|
||||
char suffix = 'a';
|
||||
for(auto p : peaks) {
|
||||
auto helper = new Marker(model, number, this);
|
||||
helper->suffix = QChar('a' + i);
|
||||
helper->suffix = suffix;
|
||||
helper->assignTrace(parentTrace);
|
||||
helper->setPosition(p);
|
||||
helper->formatTable = formatTable;
|
||||
helper->formatGraph = formatGraph;
|
||||
helper->updateContextmenu();
|
||||
helper->setVisible(visible);
|
||||
suffix++;
|
||||
helperMarkers.push_back(helper);
|
||||
}
|
||||
// update the position of the helper marker
|
||||
helperMarkers[i]->setPosition(peaks[i]);
|
||||
}
|
||||
if(helperMarkers.size() > peaks.size()) {
|
||||
// need to remove some helper markers
|
||||
emit beginRemoveHelperMarkers(this);
|
||||
for(unsigned int i = peaks.size(); i< helperMarkers.size();i++) {
|
||||
delete helperMarkers[i];
|
||||
}
|
||||
helperMarkers.resize(peaks.size());
|
||||
emit endRemoveHelperMarkers(this);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case Type::Lowpass:
|
||||
|
|
|
|||
|
|
@ -35,8 +35,6 @@ public:
|
|||
Inductance,
|
||||
QualityFactor,
|
||||
GroupDelay,
|
||||
// Peak table
|
||||
NumberOfPeaks,
|
||||
// Noise marker parameters
|
||||
Noise,
|
||||
PhaseNoise,
|
||||
|
|
@ -111,10 +109,8 @@ public:
|
|||
Last,
|
||||
};
|
||||
Type getType() const;
|
||||
QWidget *getTraceEditor(QAbstractItemDelegate *delegate = nullptr);
|
||||
void updateTraceFromEditor(QWidget *w);
|
||||
QWidget *getTypeEditor(QAbstractItemDelegate *delegate = nullptr);
|
||||
void updateTypeFromEditor(QWidget *w);
|
||||
void updateTypeFromEditor(QWidget *c);
|
||||
SIUnitEdit* getSettingsEditor();
|
||||
QWidget *getRestrictEditor();
|
||||
void adjustSettings(double value);
|
||||
|
|
@ -149,7 +145,6 @@ public:
|
|||
|
||||
public slots:
|
||||
void setPosition(double freq);
|
||||
void setToMiddleOfTrace();
|
||||
void updateContextmenu();
|
||||
signals:
|
||||
void positionChanged(double pos);
|
||||
|
|
|
|||
|
|
@ -77,8 +77,8 @@ Marker *MarkerModel::createDefaultMarker()
|
|||
}
|
||||
} while (used);
|
||||
auto marker = new Marker(this, number);
|
||||
marker->setPosition(2150000000);
|
||||
marker->assignTrace(model.trace(0));
|
||||
marker->setToMiddleOfTrace();
|
||||
return marker;
|
||||
}
|
||||
|
||||
|
|
@ -132,11 +132,11 @@ void MarkerModel::markerDataChanged(Marker *m)
|
|||
// only update the other columns, do not override editor data
|
||||
emit dataChanged(index(row, ColIndexData), index(row, ColIndexData));
|
||||
} else {
|
||||
emit dataChanged(index(row, ColIndexSettings), index(row, ColIndexData));
|
||||
emit dataChanged(index(row, ColIndexNumber), index(row, ColIndexData));
|
||||
// also update any potential helper markers
|
||||
for(unsigned int i=0;i<m->getHelperMarkers().size();i++) {
|
||||
auto modelIndex = createIndex(i, 0, m);
|
||||
emit dataChanged(index(i, ColIndexSettings, modelIndex), index(i, ColIndexData, modelIndex));
|
||||
emit dataChanged(index(i, ColIndexNumber, modelIndex), index(i, ColIndexData, modelIndex));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -436,17 +436,41 @@ QSize MarkerTraceDelegate::sizeHint(const QStyleOptionViewItem &, const QModelIn
|
|||
|
||||
QWidget *MarkerTraceDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &, const QModelIndex &index) const
|
||||
{
|
||||
auto marker = static_cast<const MarkerModel*>(index.model())->markerFromIndex(index);
|
||||
auto editor = marker->getTraceEditor(const_cast<MarkerTraceDelegate*>(this));
|
||||
editor->setMaximumHeight(rowHeight);
|
||||
editor->setParent(parent);
|
||||
return editor;
|
||||
auto model = (MarkerModel*) index.model();
|
||||
auto c = new QComboBox(parent);
|
||||
c->setMaximumHeight(rowHeight);
|
||||
connect(c, qOverload<int>(&QComboBox::currentIndexChanged), [c](int) {
|
||||
c->clearFocus();
|
||||
});
|
||||
auto traces = model->getModel().getTraces();
|
||||
for(auto t : traces) {
|
||||
MarkerWidgetTraceInfo info;
|
||||
info.trace = t;
|
||||
c->addItem(t->name(), QVariant::fromValue(info));
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
void MarkerTraceDelegate::setModelData(QWidget *editor, QAbstractItemModel *, const QModelIndex &index) const
|
||||
void MarkerTraceDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
|
||||
{
|
||||
auto marker = static_cast<const MarkerModel*>(index.model())->markerFromIndex(index);
|
||||
marker->updateTraceFromEditor(editor);
|
||||
auto c = (QComboBox*) editor;
|
||||
MarkerWidgetTraceInfo markerInfo;
|
||||
markerInfo.trace = marker->trace();
|
||||
for(int i=0;i<c->count();i++) {
|
||||
auto info = qvariant_cast<MarkerWidgetTraceInfo>(c->itemData(i));
|
||||
if(info == markerInfo) {
|
||||
c->setCurrentIndex(i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MarkerTraceDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
|
||||
{
|
||||
auto markerModel = (MarkerModel*) model;
|
||||
auto c = (QComboBox*) editor;
|
||||
markerModel->setData(index, c->itemData(c->currentIndex()));
|
||||
}
|
||||
|
||||
QSize MarkerSettingsDelegate::sizeHint(const QStyleOptionViewItem &, const QModelIndex &) const
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ class MarkerTraceDelegate : public QStyledItemDelegate
|
|||
Q_OBJECT
|
||||
QSize sizeHint ( const QStyleOptionViewItem & option, const QModelIndex & index ) const override;
|
||||
QWidget *createEditor(QWidget * parent, const QStyleOptionViewItem & option, const QModelIndex & index) const override;
|
||||
void setEditorData(QWidget * editor, const QModelIndex & index) const override;
|
||||
void setModelData(QWidget * editor, QAbstractItemModel * model, const QModelIndex & index) const override;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -15,7 +15,6 @@ Math::Expression::Expression()
|
|||
{
|
||||
parser = new ParserX(pckCOMMON | pckUNIT | pckCOMPLEX);
|
||||
parser->DefineVar("x", Variable(&x));
|
||||
dataType = DataType::Invalid;
|
||||
expressionChanged();
|
||||
}
|
||||
|
||||
|
|
@ -38,8 +37,10 @@ void Math::Expression::edit()
|
|||
{
|
||||
auto d = new QDialog();
|
||||
auto ui = new Ui::ExpressionDialog;
|
||||
d->setAttribute(Qt::WA_DeleteOnClose);
|
||||
ui->setupUi(d);
|
||||
connect(d, &QDialog::finished, [=](){
|
||||
delete ui;
|
||||
});
|
||||
ui->expEdit->setText(exp);
|
||||
connect(ui->buttonBox, &QDialogButtonBox::accepted, [=](){
|
||||
exp = ui->expEdit->text();
|
||||
|
|
@ -92,7 +93,7 @@ void Math::Expression::inputSamplesChanged(unsigned int begin, unsigned int end)
|
|||
data.resize(in.size());
|
||||
// sanity check input values
|
||||
if(end > 0 && end > in.size()) {
|
||||
end = in.size();
|
||||
end = in.size() - 1;
|
||||
}
|
||||
if(end <= begin) {
|
||||
dataMutex.unlock();
|
||||
|
|
@ -118,14 +119,6 @@ void Math::Expression::inputSamplesChanged(unsigned int begin, unsigned int end)
|
|||
emit outputSamplesChanged(begin, end);
|
||||
}
|
||||
|
||||
void Math::Expression::inputTypeChanged(DataType type)
|
||||
{
|
||||
// call base class slot
|
||||
TraceMath::inputTypeChanged(type);
|
||||
// we need to evaluate the expression again to create the correct variables
|
||||
expressionChanged();
|
||||
}
|
||||
|
||||
void Math::Expression::expressionChanged()
|
||||
{
|
||||
if(exp.isEmpty()) {
|
||||
|
|
|
|||
|
|
@ -24,7 +24,6 @@ public:
|
|||
|
||||
public slots:
|
||||
void inputSamplesChanged(unsigned int begin, unsigned int end) override;
|
||||
virtual void inputTypeChanged(DataType type) override;
|
||||
|
||||
private slots:
|
||||
void expressionChanged();
|
||||
|
|
|
|||
|
|
@ -130,7 +130,7 @@ public slots:
|
|||
// some values of the input data have changed, begin/end determine which sample(s) has changed
|
||||
virtual void inputSamplesChanged(unsigned int begin, unsigned int end){Q_UNUSED(begin) Q_UNUSED(end)}
|
||||
|
||||
virtual void inputTypeChanged(DataType type);
|
||||
void inputTypeChanged(DataType type);
|
||||
|
||||
signals:
|
||||
// emit this whenever a sample changed (alternatively, if all samples are about to change, emit outputDataChanged after they have changed)
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@
|
|||
#include "fftcomplex.h"
|
||||
#include "preferences.h"
|
||||
#include "appwindow.h"
|
||||
#include "screenshot.h"
|
||||
|
||||
#include <random>
|
||||
#include <thread>
|
||||
|
|
@ -404,7 +403,16 @@ void EyeDiagramPlot::updateContextMenu()
|
|||
auto image = new QAction("Save image...", contextmenu);
|
||||
contextmenu->addAction(image);
|
||||
connect(image, &QAction::triggered, this, [=]() {
|
||||
SaveScreenshot(this);
|
||||
auto filename = QFileDialog::getSaveFileName(nullptr, "Save plot image", "", "PNG image files (*.png)", nullptr, Preferences::QFileDialogOptions());
|
||||
if(filename.isEmpty()) {
|
||||
// aborted selection
|
||||
return;
|
||||
}
|
||||
if(filename.endsWith(".png")) {
|
||||
filename.chop(4);
|
||||
}
|
||||
filename += ".png";
|
||||
grab().save(filename);
|
||||
});
|
||||
|
||||
contextmenu->addSection("Traces");
|
||||
|
|
|
|||
|
|
@ -13,8 +13,7 @@ SparamTraceSelector::SparamTraceSelector(const TraceModel &model, std::vector<un
|
|||
: model(model),
|
||||
empty_allowed(empty_allowed),
|
||||
used_ports(used_ports),
|
||||
editablePorts(editablePorts),
|
||||
valid(false)
|
||||
editablePorts(editablePorts)
|
||||
{
|
||||
createGUI();
|
||||
setInitialChoices();
|
||||
|
|
@ -141,7 +140,6 @@ void SparamTraceSelector::traceSelectionChanged(QComboBox *cb)
|
|||
|
||||
} else if(cb->currentIndex() == 0 && points > 0) {
|
||||
if(!empty_allowed) {
|
||||
valid = false;
|
||||
emit selectionValid(false);
|
||||
}
|
||||
// Check if all trace selections are set for none
|
||||
|
|
@ -163,8 +161,7 @@ void SparamTraceSelector::traceSelectionChanged(QComboBox *cb)
|
|||
}
|
||||
if(empty_allowed) {
|
||||
// always valid as soon as at least one trace is selected
|
||||
valid = points > 0;
|
||||
emit selectionValid(valid);
|
||||
emit selectionValid(points > 0);
|
||||
} else {
|
||||
// actually need to check
|
||||
valid = true;
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ public:
|
|||
SparamTraceSelector(const TraceModel &model, std::vector<unsigned int> used_ports, bool empty_allowed = false, unsigned int editablePorts = 0);
|
||||
SparamTraceSelector(const TraceModel &model, std::set<unsigned int> used_ports, bool empty_allowed = false, unsigned int editablePorts = 0);
|
||||
|
||||
bool isValid() {return valid;}
|
||||
bool isValid();
|
||||
|
||||
std::map<QString, Trace*> getTraces();
|
||||
unsigned int getPoints() { return points;}
|
||||
|
|
|
|||
|
|
@ -1,36 +0,0 @@
|
|||
#include "sparamtraceselectordialog.h"
|
||||
#include "ui_sparamtraceselectordialog.h"
|
||||
|
||||
#include "sparamtraceselector.h"
|
||||
#include <QPushButton>
|
||||
|
||||
SParamTraceSelectorDialog::SParamTraceSelectorDialog(const TraceModel &model, std::vector<unsigned int> used_ports, bool empty_allowed)
|
||||
: QDialog(nullptr)
|
||||
, ui(new Ui::SParamTraceSelectorDialog)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
setAttribute(Qt::WA_DeleteOnClose);
|
||||
|
||||
auto selector = new SparamTraceSelector(model, used_ports, empty_allowed);
|
||||
ui->verticalLayout->replaceWidget(ui->placeholder, selector);
|
||||
|
||||
auto okButton = ui->buttonBox->button(QDialogButtonBox::StandardButton::Ok);
|
||||
connect(selector, &SparamTraceSelector::selectionValid, okButton, &QPushButton::setEnabled);
|
||||
okButton->setEnabled(selector->isValid());
|
||||
|
||||
connect(okButton, &QPushButton::clicked, [=](){
|
||||
auto traces = selector->getTraces();
|
||||
if(traces.size() == 0) {
|
||||
// should not happen
|
||||
reject();
|
||||
}
|
||||
emit tracesSelected(Trace::assembleDatapoints(traces));
|
||||
accept();
|
||||
});
|
||||
connect(ui->buttonBox, &QDialogButtonBox::rejected, this, &SParamTraceSelectorDialog::reject);
|
||||
}
|
||||
|
||||
SParamTraceSelectorDialog::~SParamTraceSelectorDialog()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
|
@ -1,27 +0,0 @@
|
|||
#ifndef SPARAMTRACESELECTORDIALOG_H
|
||||
#define SPARAMTRACESELECTORDIALOG_H
|
||||
|
||||
#include <QDialog>
|
||||
|
||||
#include "tracemodel.h"
|
||||
|
||||
namespace Ui {
|
||||
class SParamTraceSelectorDialog;
|
||||
}
|
||||
|
||||
class SParamTraceSelectorDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit SParamTraceSelectorDialog(const TraceModel &model, std::vector<unsigned int> used_ports, bool empty_allowed = false);
|
||||
~SParamTraceSelectorDialog();
|
||||
|
||||
signals:
|
||||
void tracesSelected(std::vector<DeviceDriver::VNAMeasurement> traceMeasurements);
|
||||
|
||||
private:
|
||||
Ui::SParamTraceSelectorDialog *ui;
|
||||
};
|
||||
|
||||
#endif // SPARAMTRACESELECTORDIALOG_H
|
||||
|
|
@ -1,34 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>SParamTraceSelectorDialog</class>
|
||||
<widget class="QDialog" name="SParamTraceSelectorDialog">
|
||||
<property name="windowModality">
|
||||
<enum>Qt::WindowModality::ApplicationModal</enum>
|
||||
</property>
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>494</width>
|
||||
<height>222</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>S-Paramter Trace Selector Dialog</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QWidget" name="placeholder" native="true"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::StandardButton::Cancel|QDialogButtonBox::StandardButton::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
|
|
@ -318,10 +318,6 @@ void Trace::fillFromDatapoints(std::map<QString, Trace *> traceSet, const std::v
|
|||
{
|
||||
// remove all previous points
|
||||
for(auto m : traceSet) {
|
||||
if(!m.second) {
|
||||
// no trace, skip
|
||||
continue;
|
||||
}
|
||||
if(!deembedded) {
|
||||
m.second->clear();
|
||||
} else {
|
||||
|
|
@ -336,10 +332,6 @@ void Trace::fillFromDatapoints(std::map<QString, Trace *> traceSet, const std::v
|
|||
td.y = m.second;
|
||||
QString measurement = m.first;
|
||||
if(traceSet.count(measurement)) {
|
||||
if(!traceSet[measurement]) {
|
||||
// no trace, skip
|
||||
continue;
|
||||
}
|
||||
if(!deembedded) {
|
||||
traceSet[measurement]->addData(td, DataType::Frequency);
|
||||
} else {
|
||||
|
|
@ -1073,24 +1065,16 @@ std::vector<DeviceDriver::VNAMeasurement> Trace::assembleDatapoints(std::map<QSt
|
|||
vector<DeviceDriver::VNAMeasurement> ret;
|
||||
|
||||
// Sanity check traces
|
||||
unsigned int samples = 0;
|
||||
auto impedance = 0;
|
||||
unsigned int samples = traceSet.begin()->second->size();
|
||||
auto impedance = traceSet.begin()->second->getReferenceImpedance();
|
||||
vector<double> freqs;
|
||||
for(auto m : traceSet) {
|
||||
const Trace *t = m.second;
|
||||
if(!t) {
|
||||
// trace not valid, skip
|
||||
continue;
|
||||
}
|
||||
if(samples == 0) {
|
||||
samples = t->size();
|
||||
} else if(t->size() != samples) {
|
||||
if(t->size() != samples) {
|
||||
qWarning() << "Selected traces do not have the same size";
|
||||
return ret;
|
||||
}
|
||||
if(impedance == 0) {
|
||||
impedance = t->getReferenceImpedance();
|
||||
} else if(t->getReferenceImpedance() != impedance) {
|
||||
if(t->getReferenceImpedance() != impedance) {
|
||||
qWarning() << "Selected traces do not have the same reference impedance";
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -1114,22 +1098,13 @@ std::vector<DeviceDriver::VNAMeasurement> Trace::assembleDatapoints(std::map<QSt
|
|||
}
|
||||
}
|
||||
|
||||
if(samples == 0 || freqs.size() == 0) {
|
||||
qWarning() << "Empty trace set";
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Checks passed, assemble datapoints
|
||||
for(unsigned int i=0;i<samples;i++) {
|
||||
DeviceDriver::VNAMeasurement d;
|
||||
for(auto m : traceSet) {
|
||||
QString measurement = m.first;
|
||||
const Trace *t = m.second;
|
||||
if(t) {
|
||||
d.measurements[measurement] = t->sample(i).y;
|
||||
} else {
|
||||
d.measurements[measurement] = 0.0;
|
||||
}
|
||||
}
|
||||
d.pointNum = i;
|
||||
d.frequency = freqs[i];
|
||||
|
|
|
|||
|
|
@ -72,12 +72,11 @@ void TraceCSVExport::on_buttonBox_accepted()
|
|||
return;
|
||||
}
|
||||
|
||||
auto filename = QFileDialog::getSaveFileName(nullptr, "Save calibration data", Preferences::getInstance().UISettings.Paths.data, "CSV files (*.csv)", nullptr, Preferences::QFileDialogOptions());
|
||||
auto filename = QFileDialog::getSaveFileName(nullptr, "Save calibration data", "", "CSV files (*.csv)", nullptr, Preferences::QFileDialogOptions());
|
||||
if(filename.isEmpty()) {
|
||||
// aborted selection
|
||||
return;
|
||||
}
|
||||
Preferences::getInstance().UISettings.Paths.data = QFileInfo(filename).path();
|
||||
if(!filename.endsWith(".csv")) {
|
||||
filename.append(".csv");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,8 +9,6 @@ using namespace std;
|
|||
TraceModel::TraceModel(QObject *parent)
|
||||
: QAbstractTableModel(parent)
|
||||
{
|
||||
spanFmin = 0.0;
|
||||
spanFmax = 6000000000.0;
|
||||
traces.clear();
|
||||
source = DataSource::Unknown;
|
||||
lastSweepPosition = 0.0;
|
||||
|
|
@ -370,13 +368,6 @@ double TraceModel::getSweepPosition() const
|
|||
}
|
||||
}
|
||||
|
||||
void TraceModel::setSpan(double fmin, double fmax)
|
||||
{
|
||||
spanFmin = fmin;
|
||||
spanFmax = fmax;
|
||||
emit SpanChanged(fmin, fmax);
|
||||
}
|
||||
|
||||
MarkerModel *TraceModel::getMarkerModel() const
|
||||
{
|
||||
return markerModel;
|
||||
|
|
|
|||
|
|
@ -62,10 +62,6 @@ public:
|
|||
|
||||
double getSweepPosition() const;
|
||||
|
||||
void setSpan(double fmin, double fmax);
|
||||
double getSpanStart() {return spanFmin;}
|
||||
double getSpanStop() {return spanFmax;}
|
||||
|
||||
signals:
|
||||
void SpanChanged(double fmin, double fmax);
|
||||
void traceAdded(Trace *t);
|
||||
|
|
@ -84,8 +80,6 @@ private:
|
|||
QDateTime lastReceivedData;
|
||||
std::vector<Trace*> traces;
|
||||
MarkerModel *markerModel;
|
||||
|
||||
double spanFmin, spanFmax;
|
||||
};
|
||||
|
||||
#endif // TRACEMODEL_H
|
||||
|
|
|
|||
|
|
@ -42,7 +42,8 @@ TracePlot::TracePlot(TraceModel &model, QWidget *parent)
|
|||
lastUpdate = QTime::currentTime();
|
||||
replotTimer.setSingleShot(true);
|
||||
connect(&replotTimer, &QTimer::timeout, this, qOverload<>(&TracePlot::update));
|
||||
TracePlot::updateSpan(model.getSpanStart(), model.getSpanStop());
|
||||
sweep_fmin = std::numeric_limits<double>::lowest();
|
||||
sweep_fmax = std::numeric_limits<double>::max();
|
||||
xSweep = std::numeric_limits<double>::quiet_NaN();
|
||||
// get notified when the span changes
|
||||
connect(&model, &TraceModel::SpanChanged, this, qOverload<double, double>(&TracePlot::updateSpan));
|
||||
|
|
@ -550,10 +551,6 @@ Marker *TracePlot::markerAtPosition(QPoint p, bool onlyMovable)
|
|||
}
|
||||
auto markers = t.first->getMarkers();
|
||||
for(Marker* m : markers) {
|
||||
if(!m->isVisible()) {
|
||||
// can not interact with invisible markers, pretend that there is nothing here
|
||||
continue;
|
||||
}
|
||||
if(!m->isMovable() && onlyMovable) {
|
||||
continue;
|
||||
}
|
||||
|
|
@ -562,16 +559,19 @@ Marker *TracePlot::markerAtPosition(QPoint p, bool onlyMovable)
|
|||
// invalid, skip
|
||||
continue;
|
||||
}
|
||||
if(!positionWithinGraphArea(markerPoint) && !Preferences::getInstance().Marker.clipToYAxis) {
|
||||
// this marker is currently not visible on the graph, do not accept it as a valid choice
|
||||
continue;
|
||||
}
|
||||
auto diff = markerPoint - p;
|
||||
unsigned int distance = diff.x() * diff.x() + diff.y() * diff.y();
|
||||
if(distance < closestDistance) {
|
||||
closestDistance = distance;
|
||||
if(m->getParent()) {
|
||||
closestMarker = m->getParent();
|
||||
if(closestMarker->getType() == Marker::Type::Flatness) {
|
||||
closestMarker = m;
|
||||
}
|
||||
} else {
|
||||
closestMarker = m;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if(closestDistance <= 400) {
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@
|
|||
#include "Marker/marker.h"
|
||||
#include "Util/util.h"
|
||||
#include "preferences.h"
|
||||
#include "screenshot.h"
|
||||
|
||||
#include <QFileDialog>
|
||||
|
||||
|
|
@ -130,7 +129,7 @@ bool TracePolar::positionWithinGraphArea(const QPoint &p)
|
|||
|
||||
QPoint TracePolar::dataToPixel(std::complex<double> d)
|
||||
{
|
||||
return transform.map(QPoint(round(d.real() * polarCoordMax * (1.0 / edgeReflection)), round(-d.imag() * polarCoordMax * (1.0 / edgeReflection))));
|
||||
return transform.map(QPoint(d.real() * polarCoordMax * (1.0 / edgeReflection), -d.imag() * polarCoordMax * (1.0 / edgeReflection)));
|
||||
}
|
||||
|
||||
QPoint TracePolar:: dataToPixel(Trace::Data d)
|
||||
|
|
@ -165,22 +164,13 @@ std::complex<double> TracePolar::pixelToData(QPoint p)
|
|||
QPoint TracePolar::markerToPixel(Marker *m)
|
||||
{
|
||||
QPoint ret = QPoint();
|
||||
// if(!m->isTimeDomain()) {
|
||||
if(m->getPosition() >= sweep_fmin && m->getPosition() <= sweep_fmax) {
|
||||
auto d = m->getData();
|
||||
d = dataAddOffset(d);
|
||||
if(abs(d) > edgeReflection && limitToEdge) {
|
||||
// marker position is outside of the graph
|
||||
auto &pref = Preferences::getInstance();
|
||||
if(pref.Marker.clipToYAxis) {
|
||||
// we still want to show the marker but at the edge of the graph
|
||||
d /= (abs(d) / edgeReflection);
|
||||
} else {
|
||||
// we do not show the marker
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
ret = dataToPixel(d);
|
||||
}
|
||||
// }
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -197,10 +187,6 @@ double TracePolar::nearestTracePoint(Trace *t, QPoint pixel, double *distance)
|
|||
continue;
|
||||
}
|
||||
data = dataAddOffset(data);
|
||||
if(limitToEdge && abs(data.y) > edgeReflection) {
|
||||
// this trace point is outside of the visible range, clip to circle
|
||||
data.y /= (abs(data.y) / edgeReflection);
|
||||
}
|
||||
auto plotPoint = dataToPixel(data);
|
||||
if (plotPoint.isNull()) {
|
||||
// destination point outside of currently displayed range
|
||||
|
|
@ -267,7 +253,16 @@ void TracePolar::updateContextMenu()
|
|||
auto image = new QAction("Save image...", contextmenu);
|
||||
contextmenu->addAction(image);
|
||||
connect(image, &QAction::triggered, [=]() {
|
||||
SaveScreenshot(this);
|
||||
auto filename = QFileDialog::getSaveFileName(nullptr, "Save plot image", "", "PNG image files (*.png)", nullptr, Preferences::QFileDialogOptions());
|
||||
if(filename.isEmpty()) {
|
||||
// aborted selection
|
||||
return;
|
||||
}
|
||||
if(filename.endsWith(".png")) {
|
||||
filename.chop(4);
|
||||
}
|
||||
filename += ".png";
|
||||
grab().save(filename);
|
||||
});
|
||||
|
||||
auto createMarker = contextmenu->addAction("Add marker here");
|
||||
|
|
|
|||
|
|
@ -367,16 +367,14 @@ void TraceSmithChart::draw(QPainter &p) {
|
|||
// marker not in trace range
|
||||
continue;
|
||||
}
|
||||
auto point = markerToPixel(m);
|
||||
if(point.isNull()) {
|
||||
// marker point is invalid
|
||||
auto coords = m->getData();
|
||||
coords = dataAddOffset(coords);
|
||||
|
||||
if (limitToEdge && abs(coords) > edgeReflection) {
|
||||
// outside of visible area
|
||||
continue;
|
||||
}
|
||||
|
||||
// if (limitToEdge && abs(pixelToData(point)) > edgeReflection) {
|
||||
// // outside of visible area
|
||||
// continue;
|
||||
// }
|
||||
auto point = dataToPixel(coords);
|
||||
auto symbol = m->getSymbol();
|
||||
p.drawPixmap(point.x() - symbol.width()/2, point.y() - symbol.height(), symbol);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,42 +18,22 @@ TraceTouchstoneExport::TraceTouchstoneExport(TraceModel &model, QWidget *parent)
|
|||
ui->selector->setPartialSelectionAllowed(true);
|
||||
connect(ui->selector, qOverload<>(&TraceSetSelector::selectionChanged), this, &TraceTouchstoneExport::selectionChanged);
|
||||
connect(ui->sbPorts, &QSpinBox::valueChanged, this, &TraceTouchstoneExport::setPortNum);
|
||||
// restore the last used settings
|
||||
auto& pref = Preferences::getInstance();
|
||||
auto ports = pref.UISettings.TouchstoneExport.ports;
|
||||
setPortNum(ports);
|
||||
ui->cFormat->setCurrentIndex(pref.UISettings.TouchstoneExport.formatIndex);
|
||||
ui->cUnit->setCurrentIndex(pref.UISettings.TouchstoneExport.unitIndex);
|
||||
|
||||
// attempt to set the traces that were exported last
|
||||
QStringList traces = pref.UISettings.TouchstoneExport.exportedTraceNames.split(",");
|
||||
if(traces.size() == ports * ports) {
|
||||
// got the correct number of traces
|
||||
for(unsigned int i=0;i<traces.size();i++) {
|
||||
// figure out how many ports the user most likely needs
|
||||
unsigned int p;
|
||||
for(p=4;p>=1;p--) {
|
||||
// do we have a trace name which could indicate such a number of ports?
|
||||
for(unsigned int i=1;i<=p;i++) {
|
||||
auto n1 = "S"+QString::number(p)+QString::number(i);
|
||||
auto n2 = "S"+QString::number(i)+QString::number(p);
|
||||
for(auto t : model.getTraces()) {
|
||||
if(t->name() == traces[i]) {
|
||||
setTrace(i / ports + 1, i % ports + 1, t);
|
||||
break;
|
||||
if(t->name().contains(n1) || t->name().contains(n2)) {
|
||||
goto traceFound;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// unsigned int p;
|
||||
// for(p=4;p>=1;p--) {
|
||||
// // do we have a trace name which could indicate such a number of ports?
|
||||
// for(unsigned int i=1;i<=p;i++) {
|
||||
// auto n1 = "S"+QString::number(p)+QString::number(i);
|
||||
// auto n2 = "S"+QString::number(i)+QString::number(p);
|
||||
// for(auto t : model.getTraces()) {
|
||||
// if(t->name().contains(n1) || t->name().contains(n2)) {
|
||||
// goto traceFound;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// traceFound:
|
||||
// setPortNum(p);
|
||||
traceFound:
|
||||
setPortNum(p);
|
||||
}
|
||||
|
||||
TraceTouchstoneExport::~TraceTouchstoneExport()
|
||||
|
|
@ -61,7 +41,7 @@ TraceTouchstoneExport::~TraceTouchstoneExport()
|
|||
delete ui;
|
||||
}
|
||||
|
||||
bool TraceTouchstoneExport::setTrace(int portTo, int portFrom, Trace *t)
|
||||
bool TraceTouchstoneExport::setTrace(int portFrom, int portTo, Trace *t)
|
||||
{
|
||||
return ui->selector->setTrace(portTo, portFrom, t);
|
||||
}
|
||||
|
|
@ -86,7 +66,7 @@ bool TraceTouchstoneExport::setPortNum(unsigned int ports)
|
|||
for(auto t : traces) {
|
||||
if(t->name().contains(name)) {
|
||||
// this could be the correct trace
|
||||
setTrace(i, j, t);
|
||||
setTrace(j, i, t);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -97,18 +77,17 @@ bool TraceTouchstoneExport::setPortNum(unsigned int ports)
|
|||
|
||||
void TraceTouchstoneExport::on_buttonBox_accepted()
|
||||
{
|
||||
unsigned int ports = ui->sbPorts->value();
|
||||
auto ports = ui->sbPorts->value();
|
||||
QString extension = ".s"+QString::number(ports)+"p";
|
||||
auto filename = QFileDialog::getSaveFileName(this, "Select file for exporting traces", Preferences::getInstance().UISettings.Paths.data, "Touchstone files (*"+extension+")", nullptr, Preferences::QFileDialogOptions());
|
||||
auto filename = QFileDialog::getSaveFileName(this, "Select file for exporting traces", "", "Touchstone files (*"+extension+")", nullptr, Preferences::QFileDialogOptions());
|
||||
if(filename.length() > 0) {
|
||||
Preferences::getInstance().UISettings.Paths.data = QFileInfo(filename).path();
|
||||
auto t = Touchstone(ports);
|
||||
t.setReferenceImpedance(ui->selector->getReferenceImpedance());
|
||||
// add trace points to touchstone
|
||||
for(unsigned int s=0;s<ui->selector->getPoints();s++) {
|
||||
Touchstone::Datapoint tData;
|
||||
for(unsigned int i=1;i<=ports;i++) {
|
||||
for(unsigned int j=1;j<=ports;j++) {
|
||||
for(int i=1;i<=ports;i++) {
|
||||
for(int j=1;j<=ports;j++) {
|
||||
auto t = ui->selector->getTrace(i, j);
|
||||
if(!t) {
|
||||
// missing trace, set to 0
|
||||
|
|
@ -138,25 +117,6 @@ void TraceTouchstoneExport::on_buttonBox_accepted()
|
|||
}
|
||||
|
||||
t.toFile(filename, unit, format);
|
||||
|
||||
// update preferences for next call
|
||||
auto& pref = Preferences::getInstance();
|
||||
pref.UISettings.TouchstoneExport.ports = ui->sbPorts->value();
|
||||
pref.UISettings.TouchstoneExport.formatIndex = ui->cFormat->currentIndex();
|
||||
pref.UISettings.TouchstoneExport.unitIndex = ui->cUnit->currentIndex();
|
||||
QString traceNames = "";
|
||||
for(unsigned int i=0;i<ports*ports;i++) {
|
||||
auto t = ui->selector->getTrace(i / ports + 1, i % ports + 1);
|
||||
if(t) {
|
||||
traceNames += t->name();
|
||||
}
|
||||
if(i != (ports*ports-1)) {
|
||||
// add separator for all but the last trace name
|
||||
traceNames += ",";
|
||||
}
|
||||
}
|
||||
pref.UISettings.TouchstoneExport.exportedTraceNames = traceNames;
|
||||
|
||||
delete this;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ class TraceTouchstoneExport : public QDialog
|
|||
public:
|
||||
explicit TraceTouchstoneExport(TraceModel &model, QWidget *parent = nullptr);
|
||||
~TraceTouchstoneExport();
|
||||
bool setTrace(int portTo, int portFrom, Trace *t);
|
||||
bool setTrace(int portFrom, int portTo, Trace *t);
|
||||
bool setPortNum(unsigned int ports);
|
||||
|
||||
private slots:
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@
|
|||
#include "waterfallaxisdialog.h"
|
||||
#include "appwindow.h"
|
||||
#include "tracexyplot.h"
|
||||
#include "screenshot.h"
|
||||
|
||||
#include <QFileDialog>
|
||||
#include <QPainter>
|
||||
|
|
@ -214,7 +213,16 @@ void TraceWaterfall::updateContextMenu()
|
|||
auto image = new QAction("Save image...", contextmenu);
|
||||
contextmenu->addAction(image);
|
||||
connect(image, &QAction::triggered, [=]() {
|
||||
SaveScreenshot(this);
|
||||
auto filename = QFileDialog::getSaveFileName(nullptr, "Save plot image", "", "PNG image files (*.png)", nullptr, Preferences::QFileDialogOptions());
|
||||
if(filename.isEmpty()) {
|
||||
// aborted selection
|
||||
return;
|
||||
}
|
||||
if(filename.endsWith(".png")) {
|
||||
filename.chop(4);
|
||||
}
|
||||
filename += ".png";
|
||||
grab().save(filename);
|
||||
});
|
||||
|
||||
contextmenu->addSection("Traces");
|
||||
|
|
|
|||
|
|
@ -222,9 +222,8 @@ void TraceWidget::importDialog()
|
|||
}
|
||||
supported.chop(1);
|
||||
supported += ")";
|
||||
auto filename = QFileDialog::getOpenFileName(nullptr, "Open measurement file", Preferences::getInstance().UISettings.Paths.data, supported, nullptr, Preferences::QFileDialogOptions());
|
||||
auto filename = QFileDialog::getOpenFileName(nullptr, "Open measurement file", "", supported, nullptr, Preferences::QFileDialogOptions());
|
||||
if (!filename.isEmpty()) {
|
||||
Preferences::getInstance().UISettings.Paths.data = QFileInfo(filename).path();
|
||||
importFile(filename);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@
|
|||
#include "preferences.h"
|
||||
#include "appwindow.h"
|
||||
#include "ui_XYPlotConstantLineEditDialog.h"
|
||||
#include "screenshot.h"
|
||||
|
||||
#include <QGridLayout>
|
||||
#include <cmath>
|
||||
|
|
@ -30,7 +29,8 @@ TraceXYPlot::TraceXYPlot(TraceModel &model, QWidget *parent)
|
|||
// Setup default axis
|
||||
setYAxis(0, YAxis::Type::Magnitude, false, false, YAxis::getDefaultLimitMin(YAxis::Type::Magnitude), YAxis::getDefaultLimitMax(YAxis::Type::Magnitude), 14, true);
|
||||
setYAxis(1, YAxis::Type::Phase, false, false, YAxis::getDefaultLimitMin(YAxis::Type::Phase), YAxis::getDefaultLimitMax(YAxis::Type::Phase), 12, true);
|
||||
|
||||
// enable autoscaling and set for full span (no information about actual span available yet)
|
||||
updateSpan(0, 6000000000);
|
||||
setXAxis(XAxis::Type::Frequency, XAxisMode::UseSpan, false, 0, 6000000000, 10, true);
|
||||
initializeTraceInfo();
|
||||
}
|
||||
|
|
@ -350,7 +350,16 @@ void TraceXYPlot::updateContextMenu()
|
|||
auto image = new QAction("Save image...", contextmenu);
|
||||
contextmenu->addAction(image);
|
||||
connect(image, &QAction::triggered, [=]() {
|
||||
SaveScreenshot(this);
|
||||
auto filename = QFileDialog::getSaveFileName(nullptr, "Save plot image", "", "PNG image files (*.png)", nullptr, Preferences::QFileDialogOptions());
|
||||
if(filename.isEmpty()) {
|
||||
// aborted selection
|
||||
return;
|
||||
}
|
||||
if(filename.endsWith(".png")) {
|
||||
filename.chop(4);
|
||||
}
|
||||
filename += ".png";
|
||||
grab().save(filename);
|
||||
});
|
||||
|
||||
auto createMarker = contextmenu->addAction("Add marker here");
|
||||
|
|
@ -452,8 +461,8 @@ void TraceXYPlot::draw(QPainter &p)
|
|||
plotAreaWidth -= yAxisDisabledSpace;
|
||||
}
|
||||
|
||||
auto plotRect = QRect(plotAreaLeft, plotAreaTop, plotAreaWidth + 1, plotAreaBottom-plotAreaTop + 1);
|
||||
p.drawRect(QRect(plotAreaLeft, plotAreaTop, plotAreaWidth, plotAreaBottom-plotAreaTop));
|
||||
auto plotRect = QRect(plotAreaLeft, plotAreaTop, plotAreaWidth + 1, plotAreaBottom-plotAreaTop);
|
||||
p.drawRect(plotRect);
|
||||
|
||||
// draw axis types
|
||||
auto font = p.font();
|
||||
|
|
@ -490,7 +499,7 @@ void TraceXYPlot::draw(QPainter &p)
|
|||
|
||||
int lastTickLabelEnd = std::numeric_limits<int>::max();
|
||||
for(unsigned int j = 0; j < yAxis[i].getTicks().size(); j++) {
|
||||
auto yCoord = yAxis[i].transform(yAxis[i].getTicks()[j], plotAreaBottom, plotAreaTop);
|
||||
auto yCoord = yAxis[i].transform(yAxis[i].getTicks()[j], w.height() - xAxisSpace, plotAreaTop);
|
||||
p.setPen(QPen(pref.Graphs.Color.axis, 1));
|
||||
// draw tickmark on axis
|
||||
auto tickStart = i == 0 ? plotAreaLeft : plotAreaLeft + plotAreaWidth;
|
||||
|
|
@ -630,6 +639,15 @@ void TraceXYPlot::draw(QPainter &p)
|
|||
p.drawLine(p1, p2);
|
||||
}
|
||||
|
||||
if(pref.Marker.clipToYAxis) {
|
||||
// clip Y coordinate of markers to visible area (always show markers, even when out of range)
|
||||
if(point.y() < plotRect.top()) {
|
||||
point.ry() = plotRect.top();
|
||||
} else if(point.y() > plotRect.bottom()) {
|
||||
point.ry() = plotRect.bottom();
|
||||
}
|
||||
}
|
||||
|
||||
if(!plotRect.contains(point)) {
|
||||
// out of screen
|
||||
continue;
|
||||
|
|
@ -1107,8 +1125,8 @@ QPointF TraceXYPlot::traceToCoordinate(Trace *t, unsigned int sample, YAxis &yax
|
|||
QPoint TraceXYPlot::plotValueToPixel(QPointF plotValue, int Yaxis)
|
||||
{
|
||||
QPoint p;
|
||||
p.setX(round(xAxis.transform(plotValue.x(), plotAreaLeft, plotAreaLeft + plotAreaWidth)));
|
||||
p.setY(round(yAxis[Yaxis].transform(plotValue.y(), plotAreaBottom, plotAreaTop)));
|
||||
p.setX(xAxis.transform(plotValue.x(), plotAreaLeft, plotAreaLeft + plotAreaWidth));
|
||||
p.setY(yAxis[Yaxis].transform(plotValue.y(), plotAreaBottom, plotAreaTop));
|
||||
return p;
|
||||
}
|
||||
|
||||
|
|
@ -1147,14 +1165,6 @@ QPoint TraceXYPlot::markerToPixel(Marker *m)
|
|||
} else {
|
||||
markerPoint = traceToCoordinate(t, t->index(xPosition), yAxis[0]);
|
||||
}
|
||||
auto &pref = Preferences::getInstance();
|
||||
if(pref.Marker.clipToYAxis) {
|
||||
if(markerPoint.y() > yAxis[0].getRangeMax()) {
|
||||
markerPoint.setY(yAxis[0].getRangeMax());
|
||||
} else if(markerPoint.y() < yAxis[0].getRangeMin()) {
|
||||
markerPoint.setY(yAxis[0].getRangeMin());
|
||||
}
|
||||
}
|
||||
return plotValueToPixel(markerPoint, 0);
|
||||
}
|
||||
|
||||
|
|
@ -1174,8 +1184,6 @@ double TraceXYPlot::nearestTracePoint(Trace *t, QPoint pixel, double *distance)
|
|||
continue;
|
||||
}
|
||||
auto plotPoint = plotValueToPixel(point, 0);
|
||||
// constrain to the visible Y axis range
|
||||
Util::constrain(plotPoint.ry(), plotAreaTop, plotAreaBottom);
|
||||
QPointF diff = plotPoint - pixel;
|
||||
auto distance = diff.x() * diff.x() + diff.y() * diff.y();
|
||||
if(distance < closestDistance) {
|
||||
|
|
|
|||
|
|
@ -116,7 +116,7 @@ XYplotAxisDialog::XYplotAxisDialog(TraceXYPlot *plot) :
|
|||
setupYAxisConnetions(ui->Y1type, ui->Y1linear, ui->Y1log, ui->Y1auto, ui->Y1min, ui->Y1max, ui->Y1Divs, ui->Y1autoDivs);
|
||||
setupYAxisConnetions(ui->Y2type, ui->Y2linear, ui->Y2log, ui->Y2auto, ui->Y2min, ui->Y2max, ui->Y2Divs, ui->Y2autoDivs);
|
||||
|
||||
auto updateXenableState = [](QRadioButton *linear, QRadioButton *log, QCheckBox *CBauto, SIUnitEdit *min, SIUnitEdit *max, QSpinBox *divs, QCheckBox *autoDivs, QComboBox *autoMode) {
|
||||
auto updateXenableState = [](QRadioButton *linear, QRadioButton *log, QCheckBox *CBauto, SIUnitEdit *min, SIUnitEdit *max, QSpinBox *divs, QCheckBox *autoDivs) {
|
||||
log->setEnabled(true);
|
||||
linear->setEnabled(true);
|
||||
CBauto->setEnabled(true);
|
||||
|
|
@ -126,7 +126,6 @@ XYplotAxisDialog::XYplotAxisDialog(TraceXYPlot *plot) :
|
|||
max->setEnabled(false);
|
||||
divs->setEnabled(false);
|
||||
autoDivs->setEnabled(false);
|
||||
autoMode->setEnabled(true);
|
||||
} else {
|
||||
min->setEnabled(true);
|
||||
max->setEnabled(true);
|
||||
|
|
@ -137,15 +136,14 @@ XYplotAxisDialog::XYplotAxisDialog(TraceXYPlot *plot) :
|
|||
autoDivs->setEnabled(true);
|
||||
divs->setEnabled(!autoDivs->isChecked());
|
||||
}
|
||||
autoMode->setEnabled(false);
|
||||
}
|
||||
};
|
||||
|
||||
connect(ui->Xauto, &QCheckBox::toggled, [this, updateXenableState](bool) {
|
||||
updateXenableState(ui->Xlinear, ui->Xlog, ui->Xauto, ui->Xmin, ui->Xmax, ui->XDivs, ui->XautoDivs, ui->Xautomode);
|
||||
updateXenableState(ui->Xlinear, ui->Xlog, ui->Xauto, ui->Xmin, ui->Xmax, ui->XDivs, ui->XautoDivs);
|
||||
});
|
||||
connect(ui->XautoDivs, &QCheckBox::toggled, [this, updateXenableState](bool) {
|
||||
updateXenableState(ui->Xlinear, ui->Xlog, ui->Xauto, ui->Xmin, ui->Xmax, ui->XDivs, ui->XautoDivs, ui->Xautomode);
|
||||
updateXenableState(ui->Xlinear, ui->Xlog, ui->Xauto, ui->Xmin, ui->Xmax, ui->XDivs, ui->XautoDivs);
|
||||
});
|
||||
|
||||
ui->XType->setCurrentIndex((int) plot->xAxis.getType());
|
||||
|
|
@ -161,7 +159,7 @@ XYplotAxisDialog::XYplotAxisDialog(TraceXYPlot *plot) :
|
|||
XAxisTypeChanged((int) plot->xAxis.getType());
|
||||
connect(ui->XType, qOverload<int>(&QComboBox::currentIndexChanged), this, &XYplotAxisDialog::XAxisTypeChanged);
|
||||
connect(ui->Xlog, &QCheckBox::toggled, [=](bool){
|
||||
updateXenableState(ui->Xlinear, ui->Xlog, ui->Xauto, ui->Xmin, ui->Xmax, ui->XDivs, ui->XautoDivs, ui->Xautomode);
|
||||
updateXenableState(ui->Xlinear, ui->Xlog, ui->Xauto, ui->Xmin, ui->Xmax, ui->XDivs, ui->XautoDivs);
|
||||
});
|
||||
|
||||
// Fill initial values
|
||||
|
|
@ -244,12 +242,11 @@ XYplotAxisDialog::XYplotAxisDialog(TraceXYPlot *plot) :
|
|||
removeLine(index);
|
||||
});
|
||||
connect(ui->exportLines, &QPushButton::clicked, this, [=](){
|
||||
QString filename = QFileDialog::getSaveFileName(nullptr, "Save limit lines", Preferences::getInstance().UISettings.Paths.limitLines, "Limit files (*.limits)", nullptr, Preferences::QFileDialogOptions());
|
||||
QString filename = QFileDialog::getSaveFileName(nullptr, "Save limit lines", "", "Limit files (*.limits)", nullptr, Preferences::QFileDialogOptions());
|
||||
if(filename.isEmpty()) {
|
||||
// aborted selection
|
||||
return;
|
||||
}
|
||||
Preferences::getInstance().UISettings.Paths.limitLines = QFileInfo(filename).path();
|
||||
if(!filename.endsWith(".limits")) {
|
||||
filename.append(".limits");
|
||||
}
|
||||
|
|
@ -268,7 +265,7 @@ XYplotAxisDialog::XYplotAxisDialog(TraceXYPlot *plot) :
|
|||
|
||||
});
|
||||
connect(ui->importLines, &QPushButton::clicked, [=](){
|
||||
QString filename = QFileDialog::getOpenFileName(nullptr, "Load limit lines", Preferences::getInstance().UISettings.Paths.limitLines, "Limit files (*.limits)", nullptr, Preferences::QFileDialogOptions());
|
||||
QString filename = QFileDialog::getOpenFileName(nullptr, "Load limit lines", "", "Limit files (*.limits)", nullptr, Preferences::QFileDialogOptions());
|
||||
ifstream file;
|
||||
file.open(filename.toStdString());
|
||||
if(!file.is_open()) {
|
||||
|
|
|
|||
|
|
@ -127,31 +127,6 @@ 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();
|
||||
|
|
@ -234,12 +209,12 @@ void Deembedding::addOption(DeembeddingOption *option)
|
|||
emit optionAdded();
|
||||
}
|
||||
|
||||
void Deembedding::swapOptions(unsigned int index1, unsigned int index2)
|
||||
void Deembedding::swapOptions(unsigned int index)
|
||||
{
|
||||
if(index1 > options.size() || index2 > options.size() || index1 == index2) {
|
||||
if(index + 1 >= options.size()) {
|
||||
return;
|
||||
}
|
||||
std::swap(options[index1], options[index2]);
|
||||
std::swap(options[index], options[index+1]);
|
||||
updateSCPINames();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ public:
|
|||
|
||||
void removeOption(unsigned int index);
|
||||
void addOption(DeembeddingOption* option);
|
||||
void swapOptions(unsigned int index1, unsigned int index2);
|
||||
void swapOptions(unsigned int index);
|
||||
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, index.row());
|
||||
d->swapOptions(index.row() - 1);
|
||||
ui->view->setCurrentIndex(index.sibling(index.row() - 1, 0));
|
||||
});
|
||||
connect(ui->bMoveDown, &QPushButton::clicked, [=](){
|
||||
auto index = ui->view->currentIndex();
|
||||
d->swapOptions(index.row(), index.row() + 1);
|
||||
d->swapOptions(index.row());
|
||||
ui->view->setCurrentIndex(index.sibling(index.row() + 1, 0));
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -56,17 +56,6 @@ 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)) {
|
||||
|
|
@ -278,7 +267,6 @@ void MatchingNetwork::fromJSON(nlohmann::json j)
|
|||
}
|
||||
addNetwork = j.value("addNetwork", true);
|
||||
matching.clear();
|
||||
updateSCPINames();
|
||||
}
|
||||
|
||||
void MatchingNetwork::clearNetwork()
|
||||
|
|
@ -655,7 +643,7 @@ MatchingComponent::MatchingComponent(Type type)
|
|||
// failed to load file
|
||||
return SCPI::getResultName(SCPI::Result::Error);
|
||||
}
|
||||
}, nullptr, false));
|
||||
}, nullptr));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
|
@ -779,9 +767,8 @@ void MatchingComponent::mouseDoubleClickEvent(QMouseEvent *e)
|
|||
Q_UNUSED(e);
|
||||
if(type == Type::DefinedThrough || type == Type::DefinedShunt) {
|
||||
// select new touchstone file
|
||||
auto filename = QFileDialog::getOpenFileName(nullptr, "Open measurement file", Preferences::getInstance().UISettings.Paths.data, "Touchstone files (*.s2p)", nullptr, Preferences::QFileDialogOptions());
|
||||
auto filename = QFileDialog::getOpenFileName(nullptr, "Open measurement file", "", "Touchstone files (*.s2p)", nullptr, Preferences::QFileDialogOptions());
|
||||
if (!filename.isEmpty()) {
|
||||
Preferences::getInstance().UISettings.Paths.data = QFileInfo(filename).path();
|
||||
try {
|
||||
*touchstone = Touchstone::fromFile(filename.toStdString());
|
||||
} catch(const std::exception& e) {
|
||||
|
|
@ -799,7 +786,6 @@ void MatchingComponent::updateTouchstoneLabel()
|
|||
return;
|
||||
}
|
||||
QFont font = touchstoneLabel->font();
|
||||
touchstoneLabel->setStyleSheet("color: black");
|
||||
font.setPointSize(10);
|
||||
touchstoneLabel->setFont(font);
|
||||
if(touchstone->points() == 0) {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
#include "vna.h"
|
||||
#include "vna.h"
|
||||
|
||||
#include "unit.h"
|
||||
#include "CustomWidgets/toggleswitch.h"
|
||||
|
|
@ -18,7 +18,6 @@
|
|||
#include "CustomWidgets/informationbox.h"
|
||||
#include "Deembedding/manualdeembeddingdialog.h"
|
||||
#include "Calibration/manualcalibrationdialog.h"
|
||||
#include "Calibration/calibrationviewdialog.h"
|
||||
#include "Calibration/LibreCAL/librecaldialog.h"
|
||||
#include "Util/util.h"
|
||||
#include "Tools/parameters.h"
|
||||
|
|
@ -69,10 +68,6 @@ 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;
|
||||
|
|
@ -114,7 +109,7 @@ VNA::VNA(AppWindow *window, QString name)
|
|||
|
||||
auto calData = calMenu->addAction("Calibration Measurements");
|
||||
connect(calData, &QAction::triggered, [=](){
|
||||
cal.edit(&traceModel);
|
||||
cal.edit();
|
||||
});
|
||||
|
||||
auto calEditKit = calMenu->addAction("Edit Calibration Kit");
|
||||
|
|
@ -134,16 +129,6 @@ VNA::VNA(AppWindow *window, QString name)
|
|||
|
||||
calMenu->addSeparator();
|
||||
|
||||
auto calViewTerms = calMenu->addAction("View error term model");
|
||||
connect(calViewTerms, &QAction::triggered, [=](){
|
||||
auto dialog = new CalibrationViewDialog(&cal, DeviceDriver::getInfo(window->getDevice()).Limits.VNA.ports);
|
||||
if(AppWindow::showGUI()) {
|
||||
dialog->show();
|
||||
}
|
||||
});
|
||||
|
||||
calMenu->addSeparator();
|
||||
|
||||
auto calImportTerms = calMenu->addAction("Import error terms as traces");
|
||||
calImportTerms->setEnabled(false);
|
||||
connect(calImportTerms, &QAction::triggered, [=](){
|
||||
|
|
@ -329,7 +314,7 @@ VNA::VNA(AppWindow *window, QString name)
|
|||
|
||||
auto eStart = new SIUnitEdit("Hz", " kMG", 6);
|
||||
// calculate width required with expected string length
|
||||
auto width = QFontMetrics(eStart->font()).horizontalAdvance("10.00000 MHz") + 15;
|
||||
auto width = QFontMetrics(eStart->font()).horizontalAdvance("3.00000GHz") + 15;
|
||||
eStart->setFixedWidth(width);
|
||||
eStart->setToolTip("Start frequency");
|
||||
connect(eStart, &SIUnitEdit::valueChanged, this, &VNA::SetStartFreq);
|
||||
|
|
@ -884,7 +869,6 @@ 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();
|
||||
|
|
@ -922,7 +906,6 @@ 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));
|
||||
|
|
@ -1021,10 +1004,6 @@ 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()) {
|
||||
|
|
@ -1256,7 +1235,6 @@ void VNA::SetLogSweep(bool log)
|
|||
{
|
||||
if(settings.Freq.logSweep != log) {
|
||||
settings.Freq.logSweep = log;
|
||||
ConstrainAndUpdateFrequencies();
|
||||
emit logSweepChanged(log);
|
||||
SettingsChanged();
|
||||
}
|
||||
|
|
@ -1386,7 +1364,7 @@ void VNA::ApplyCalibration(Calibration::CalType type)
|
|||
// Not all required traces available
|
||||
InformationBox::ShowMessageBlocking("Missing calibration measurements", "Not all calibration measurements for this type of calibration have been taken. The calibration can be enabled after the missing measurements have been acquired.");
|
||||
DisableCalibration();
|
||||
cal.edit(&traceModel);
|
||||
cal.edit();
|
||||
} else {
|
||||
// Not all required traces available
|
||||
InformationBox::ShowMessageBlocking("Missing calibration measurements", "Not all calibration measurements for this type of calibration have been taken. Please switch to frequency sweep to take these measurements.");
|
||||
|
|
@ -1603,15 +1581,6 @@ 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 {
|
||||
|
|
@ -1647,12 +1616,6 @@ 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;
|
||||
}
|
||||
|
|
@ -1987,7 +1950,7 @@ void VNA::ConfigureDevice(bool resetTraces, std::function<void(bool)> cb)
|
|||
double start = settings.sweepType == SweepType::Frequency ? settings.Freq.start : settings.Power.start;
|
||||
double stop = settings.sweepType == SweepType::Frequency ? settings.Freq.stop : settings.Power.stop;
|
||||
int npoints = settings.npoints;
|
||||
traceModel.setSpan(start, stop);
|
||||
emit traceModel.SpanChanged(start, stop);
|
||||
if (settings.segments > 1) {
|
||||
// more than one segment, adjust start/stop
|
||||
npoints = ceil((double) settings.npoints / settings.segments);
|
||||
|
|
|
|||
|
|
@ -201,10 +201,6 @@ 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();
|
||||
|
|
|
|||
|
|
@ -229,21 +229,19 @@ void AppWindow::SetupMenu()
|
|||
connect(ui->actionDisconnect, &QAction::triggered, this, &AppWindow::DisconnectDevice);
|
||||
connect(ui->actionQuit, &QAction::triggered, this, &AppWindow::close);
|
||||
connect(ui->actionSave_setup, &QAction::triggered, [=](){
|
||||
auto filename = QFileDialog::getSaveFileName(nullptr, "Save setup data", Preferences::getInstance().UISettings.Paths.setup, "Setup files (*.setup)", nullptr, Preferences::QFileDialogOptions());
|
||||
auto filename = QFileDialog::getSaveFileName(nullptr, "Save setup data", "", "Setup files (*.setup)", nullptr, Preferences::QFileDialogOptions());
|
||||
if(filename.isEmpty()) {
|
||||
// aborted selection
|
||||
return;
|
||||
}
|
||||
Preferences::getInstance().UISettings.Paths.setup = QFileInfo(filename).path();
|
||||
SaveSetup(filename);
|
||||
});
|
||||
connect(ui->actionLoad_setup, &QAction::triggered, [=](){
|
||||
auto filename = QFileDialog::getOpenFileName(nullptr, "Load setup data", Preferences::getInstance().UISettings.Paths.setup, "Setup files (*.setup)", nullptr, Preferences::QFileDialogOptions());
|
||||
auto filename = QFileDialog::getOpenFileName(nullptr, "Load setup data", "", "Setup files (*.setup)", nullptr, Preferences::QFileDialogOptions());
|
||||
if(filename.isEmpty()) {
|
||||
// aborted selection
|
||||
return;
|
||||
}
|
||||
Preferences::getInstance().UISettings.Paths.setup = QFileInfo(filename).path();
|
||||
LoadSetup(filename);
|
||||
});
|
||||
connect(ui->actionSave_image, &QAction::triggered, [=](){
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@
|
|||
#include "CustomWidgets/informationbox.h"
|
||||
|
||||
#include "ui_main.h"
|
||||
#include "screenshot.h"
|
||||
|
||||
#include <QPushButton>
|
||||
#include <QSettings>
|
||||
|
|
@ -142,7 +141,16 @@ Mode::Type Mode::TypeFromName(QString s)
|
|||
|
||||
void Mode::saveSreenshot()
|
||||
{
|
||||
SaveScreenshot(central);
|
||||
auto filename = QFileDialog::getSaveFileName(nullptr, "Save plot image", "", "PNG image files (*.png)", nullptr, Preferences::QFileDialogOptions());
|
||||
if(filename.isEmpty()) {
|
||||
// aborted selection
|
||||
return;
|
||||
}
|
||||
if(filename.endsWith(".png")) {
|
||||
filename.chop(4);
|
||||
}
|
||||
filename += ".png";
|
||||
central->grab().save(filename);
|
||||
}
|
||||
|
||||
void Mode::finalize(QWidget *centralWidget)
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@ PreferencesDialog::PreferencesDialog(Preferences *pref, QWidget *parent) :
|
|||
ui->StartupStack->setCurrentWidget(ui->StartupPageSetupFile);
|
||||
});
|
||||
connect(ui->StartupBrowse, &QPushButton::clicked, [=](){
|
||||
ui->StartupSetupFile->setText(QFileDialog::getOpenFileName(nullptr, "Select startup setup file", Preferences::getInstance().UISettings.Paths.setup, "Setup files (*.setup)", nullptr, Preferences::QFileDialogOptions()));
|
||||
ui->StartupSetupFile->setText(QFileDialog::getOpenFileName(nullptr, "Select startup setup file", "", "Setup files (*.setup)", nullptr, Preferences::QFileDialogOptions()));
|
||||
});
|
||||
ui->StartupSweepStart->setUnit("Hz");
|
||||
ui->StartupSweepStart->setPrefixes(" kMG");
|
||||
|
|
@ -162,7 +162,7 @@ PreferencesDialog::PreferencesDialog(Preferences *pref, QWidget *parent) :
|
|||
if(!w) {
|
||||
continue;
|
||||
}
|
||||
w->setObjectName(driver->getDriverName().replace(" ", ""));
|
||||
w->setObjectName(driver->getDriverName());
|
||||
ui->pageWidget->addWidget(w);
|
||||
auto driverItem = new QTreeWidgetItem();
|
||||
driverItem->setText(0, driver->getDriverName());
|
||||
|
|
@ -203,9 +203,8 @@ PreferencesDialog::PreferencesDialog(Preferences *pref, QWidget *parent) :
|
|||
emit p->updated();
|
||||
});
|
||||
connect(ui->buttonBox->button(QDialogButtonBox::Save), &QPushButton::clicked, [=](){
|
||||
auto filename = QFileDialog::getSaveFileName(this, "Save preferences", Preferences::getInstance().UISettings.Paths.pref, "LibreVNA preferences files (*.vnapref)", nullptr, Preferences::QFileDialogOptions());
|
||||
auto filename = QFileDialog::getSaveFileName(this, "Save preferences", "", "LibreVNA preferences files (*.vnapref)", nullptr, Preferences::QFileDialogOptions());
|
||||
if(filename.length() > 0) {
|
||||
Preferences::getInstance().UISettings.Paths.pref = QFileInfo(filename).path();
|
||||
if(!filename.toLower().endsWith(".vnapref")) {
|
||||
filename.append(".vnapref");
|
||||
}
|
||||
|
|
@ -217,9 +216,8 @@ PreferencesDialog::PreferencesDialog(Preferences *pref, QWidget *parent) :
|
|||
}
|
||||
});
|
||||
connect(ui->buttonBox->button(QDialogButtonBox::Open), &QPushButton::clicked, [=](){
|
||||
auto filename = QFileDialog::getOpenFileName(this, "Load preferences", Preferences::getInstance().UISettings.Paths.pref, "LibreVNA preferences files (*.vnapref)", nullptr, Preferences::QFileDialogOptions());
|
||||
auto filename = QFileDialog::getOpenFileName(this, "Load preferences", "", "LibreVNA preferences files (*.vnapref)", nullptr, Preferences::QFileDialogOptions());
|
||||
if(filename.length() > 0) {
|
||||
Preferences::getInstance().UISettings.Paths.pref = QFileInfo(filename).path();
|
||||
ifstream file;
|
||||
file.open(filename.toStdString());
|
||||
nlohmann::json j;
|
||||
|
|
@ -276,7 +274,6 @@ void PreferencesDialog::setInitialGUIState()
|
|||
|
||||
ui->AcquisitionAlwaysExciteBoth->setChecked(p->Acquisition.alwaysExciteAllPorts);
|
||||
ui->AcquisitionAllowSegmentedSweep->setChecked(p->Acquisition.allowSegmentedSweep);
|
||||
ui->AcquisitionAllowCalStartWithUnstableLibreCALTemperature->setChecked(p->Acquisition.allowUseOfUnstableLibreCALTemp);
|
||||
ui->AcquisitionAveragingMode->setCurrentIndex(p->Acquisition.useMedianAveraging ? 1 : 0);
|
||||
ui->AcquisitionFullSpanBehavior->setCurrentIndex(p->Acquisition.fullSpanManual ? 1 : 0);
|
||||
ui->AcquisitionFullSpanStart->setValue(p->Acquisition.fullSpanStart);
|
||||
|
|
@ -399,7 +396,6 @@ void PreferencesDialog::updateFromGUI()
|
|||
|
||||
p->Acquisition.alwaysExciteAllPorts = ui->AcquisitionAlwaysExciteBoth->isChecked();
|
||||
p->Acquisition.allowSegmentedSweep = ui->AcquisitionAllowSegmentedSweep->isChecked();
|
||||
p->Acquisition.allowUseOfUnstableLibreCALTemp = ui->AcquisitionAllowCalStartWithUnstableLibreCALTemperature->isChecked();
|
||||
p->Acquisition.useMedianAveraging = ui->AcquisitionAveragingMode->currentIndex() == 1;
|
||||
p->Acquisition.fullSpanManual = ui->AcquisitionFullSpanBehavior->currentIndex() == 1;
|
||||
p->Acquisition.fullSpanStart = ui->AcquisitionFullSpanStart->value();
|
||||
|
|
|
|||
|
|
@ -103,11 +103,8 @@ public:
|
|||
} SA;
|
||||
} Startup;
|
||||
struct {
|
||||
// VNA settings
|
||||
bool alwaysExciteAllPorts;
|
||||
bool allowSegmentedSweep;
|
||||
bool allowUseOfUnstableLibreCALTemp;
|
||||
|
||||
bool useMedianAveraging;
|
||||
|
||||
// Full span settings
|
||||
|
|
@ -210,27 +207,6 @@ public:
|
|||
bool saveTraceData;
|
||||
bool useNativeDialogs;
|
||||
} Debug;
|
||||
struct {
|
||||
struct {
|
||||
unsigned int ports;
|
||||
unsigned int formatIndex;
|
||||
unsigned int unitIndex;
|
||||
QString exportedTraceNames;
|
||||
} TouchstoneExport;
|
||||
struct {
|
||||
QString setup;
|
||||
QString cal;
|
||||
QString calkit;
|
||||
QString data;
|
||||
QString image;
|
||||
QString vnacaldata;
|
||||
QString packetlog;
|
||||
QString limitLines;
|
||||
QString pref;
|
||||
QString firmware;
|
||||
} Paths;
|
||||
qsizetype saveImageFilterIndex;
|
||||
} UISettings;
|
||||
|
||||
bool TCPoverride; // in case of manual port specification via command line
|
||||
|
||||
|
|
@ -281,7 +257,6 @@ private:
|
|||
{&Startup.SA.averaging, "Startup.SA.averaging", 1},
|
||||
{&Acquisition.alwaysExciteAllPorts, "Acquisition.alwaysExciteBothPorts", true},
|
||||
{&Acquisition.allowSegmentedSweep, "Acquisition.allowSegmentedSweep", true},
|
||||
{&Acquisition.allowUseOfUnstableLibreCALTemp, "Acquisition.allowUseOfUnstableLibreCALTemp", true},
|
||||
{&Acquisition.useMedianAveraging, "Acquisition.useMedianAveraging", false},
|
||||
{&Acquisition.fullSpanManual, "Acquisition.fullSpanManual", false},
|
||||
{&Acquisition.fullSpanStart, "Acquisition.fullSpanStart", 0.0},
|
||||
|
|
@ -399,22 +374,6 @@ private:
|
|||
{&Debug.USBlogSizeLimit, "Debug.USBlogSizeLimit", 10000000.0},
|
||||
{&Debug.saveTraceData, "Debug.saveTraceData", false},
|
||||
{&Debug.useNativeDialogs, "Debug.useNativeDialogs", true},
|
||||
|
||||
{&UISettings.TouchstoneExport.ports, "UISettings.TouchstoneExport.ports", 2},
|
||||
{&UISettings.TouchstoneExport.formatIndex, "UISettings.TouchstoneExport.formatIndex", 2},
|
||||
{&UISettings.TouchstoneExport.unitIndex, "UISettings.TouchstoneExport.unitIndex", 3},
|
||||
{&UISettings.TouchstoneExport.exportedTraceNames, "UISettings.TouchstoneExport.exportedTraceNames", ""},
|
||||
{&UISettings.Paths.setup, "UISettings.Paths.setup", ""},
|
||||
{&UISettings.Paths.cal, "UISettings.Paths.cal", ""},
|
||||
{&UISettings.Paths.calkit, "UISettings.Paths.calkit", ""},
|
||||
{&UISettings.Paths.data, "UISettings.Paths.data", ""},
|
||||
{&UISettings.Paths.image, "UISettings.Paths.image", ""},
|
||||
{&UISettings.Paths.vnacaldata, "UISettings.Paths.vnacaldata", ""},
|
||||
{&UISettings.Paths.packetlog, "UISettings.Paths.packetlog", ""},
|
||||
{&UISettings.Paths.limitLines, "UISettings.Paths.limitLines", ""},
|
||||
{&UISettings.Paths.pref, "UISettings.Paths.pref", ""},
|
||||
{&UISettings.Paths.firmware, "UISettings.Paths.firmware", ""},
|
||||
{&UISettings.saveImageFilterIndex, "UISettings.saveImageFilterIndex", 0},
|
||||
}};
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -98,7 +98,7 @@
|
|||
</size>
|
||||
</property>
|
||||
<property name="currentIndex">
|
||||
<number>1</number>
|
||||
<number>2</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="Startup">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_4">
|
||||
|
|
@ -112,8 +112,8 @@
|
|||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>683</width>
|
||||
<height>902</height>
|
||||
<width>522</width>
|
||||
<height>945</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_13">
|
||||
|
|
@ -713,8 +713,8 @@
|
|||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>697</width>
|
||||
<height>564</height>
|
||||
<width>564</width>
|
||||
<height>477</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_21">
|
||||
|
|
@ -741,22 +741,6 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_17">
|
||||
<property name="title">
|
||||
<string>Electronic Calibration</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_25">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="AcquisitionAllowCalStartWithUnstableLibreCALTemperature">
|
||||
<property name="text">
|
||||
<string>Allow calibration to start before the LibreCAL temperature has stabilized</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
|
|
@ -971,7 +955,7 @@
|
|||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>683</width>
|
||||
<height>1182</height>
|
||||
<height>1217</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_22">
|
||||
|
|
@ -1536,8 +1520,8 @@
|
|||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>486</width>
|
||||
<height>608</height>
|
||||
<width>602</width>
|
||||
<height>628</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_7">
|
||||
|
|
@ -1896,8 +1880,8 @@
|
|||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>144</width>
|
||||
<height>124</height>
|
||||
<width>168</width>
|
||||
<height>127</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_12">
|
||||
|
|
@ -2179,8 +2163,8 @@
|
|||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>697</width>
|
||||
<height>564</height>
|
||||
<width>258</width>
|
||||
<height>241</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_19">
|
||||
|
|
|
|||
|
|
@ -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 ? [¶m](QStringList params) -> QString {
|
||||
auto query = gettable ? [=](QStringList params) -> QString {
|
||||
Q_UNUSED(params)
|
||||
return QString::number(param);
|
||||
} : (std::function<QString(QStringList)>) nullptr;
|
||||
|
|
@ -344,26 +344,6 @@ 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) {
|
||||
|
|
@ -568,43 +548,16 @@ QString SCPINode::parse(QString cmd, SCPINode* &lastNode)
|
|||
return SCPI::getResultName(SCPI::Result::Error);
|
||||
} else {
|
||||
// no more levels, search for command
|
||||
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
|
||||
auto params = cmd.split(" ");
|
||||
auto cmd = params.front();
|
||||
params.pop_front();
|
||||
bool isQuery = false;
|
||||
if (cmdName[cmdName.size()-1]=='?') {
|
||||
if (cmd[cmd.size()-1]=='?') {
|
||||
isQuery = true;
|
||||
cmdName.chop(1);
|
||||
cmd.chop(1);
|
||||
}
|
||||
for(auto c : commands) {
|
||||
if(SCPI::match(c->leafName(), cmdName.toUpper())) {
|
||||
if(SCPI::match(c->leafName(), cmd.toUpper())) {
|
||||
// save current node in case of non-root for the next command
|
||||
lastNode = this;
|
||||
if(c->convertToUppercase()) {
|
||||
|
|
|
|||
|
|
@ -44,7 +44,6 @@ 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();}
|
||||
|
|
|
|||
|
|
@ -1,65 +0,0 @@
|
|||
#include "screenshot.h"
|
||||
|
||||
#include "preferences.h"
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QPainter>
|
||||
#include <QSvgGenerator>
|
||||
|
||||
void SaveScreenshot(QWidget *widget)
|
||||
{
|
||||
Q_ASSERT(widget != nullptr);
|
||||
|
||||
const QStringList extensions = QStringList() << "png" << "svg";
|
||||
QStringList filters;
|
||||
|
||||
for (const QString& ext: extensions) {
|
||||
filters << QString("%1 image files (*.%2)").arg(ext.toUpper(), ext);
|
||||
}
|
||||
|
||||
auto& settings = Preferences::getInstance().UISettings;
|
||||
const QString filterString = filters.join(";;");
|
||||
qsizetype filterIndex = qBound(0, settings.saveImageFilterIndex, filters.size() - 1);
|
||||
QString selectedFilter = filters[filterIndex];
|
||||
|
||||
auto filename = QFileDialog::getSaveFileName(nullptr, "Save plot image", settings.Paths.image, filterString, &selectedFilter, Preferences::QFileDialogOptions());
|
||||
if(filename.isEmpty()) {
|
||||
// aborted selection
|
||||
return;
|
||||
}
|
||||
|
||||
filterIndex = filters.indexOf(selectedFilter);
|
||||
const QString& extension = extensions[filterIndex];
|
||||
if(!filename.endsWith(extension)) {
|
||||
filename += '.' + extension;
|
||||
}
|
||||
|
||||
settings.Paths.image = QFileInfo(filename).path();
|
||||
settings.saveImageFilterIndex = filterIndex;
|
||||
|
||||
switch (filterIndex)
|
||||
{
|
||||
case 0: // PNG
|
||||
widget->grab().save(filename);
|
||||
break;
|
||||
|
||||
case 1: // SVG
|
||||
{
|
||||
QSvgGenerator generator;
|
||||
generator.setFileName(filename);
|
||||
generator.setViewBox(QRect(QPoint(), widget->size()));
|
||||
generator.setTitle(QCoreApplication::applicationName());
|
||||
generator.setDescription(QString("Created by %1 %2").arg(QCoreApplication::applicationName(), QCoreApplication::applicationVersion()));
|
||||
|
||||
QPainter painter;
|
||||
painter.begin(&generator);
|
||||
widget->render(&painter);
|
||||
painter.end();
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
Q_ASSERT(false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
#ifndef SCREENSHOT_H
|
||||
#define SCREENSHOT_H
|
||||
|
||||
class QWidget;
|
||||
|
||||
void SaveScreenshot(QWidget *widget);
|
||||
|
||||
#endif // SCREENSHOT_H
|
||||
|
|
@ -68,10 +68,6 @@ QString Unit::ToString(double value, QString unit, QString prefixes, int precisi
|
|||
}
|
||||
ss << value;
|
||||
sValue.append(QString::fromStdString(ss.str()));
|
||||
if(!unit.isEmpty() && !unit.startsWith(' ')) {
|
||||
// add space between number and unit
|
||||
sValue.append(' ');
|
||||
}
|
||||
sValue.append(prefixes[prefixIndex]);
|
||||
}
|
||||
sValue.append(unit);
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
QT += testlib widgets network svg
|
||||
QT += testlib widgets network
|
||||
|
||||
CONFIG += qt console warn_on depend_includepath testcase
|
||||
CONFIG -= app_bundle
|
||||
|
|
@ -12,7 +12,6 @@ SOURCES += \
|
|||
../LibreVNA-GUI/Calibration/LibreCAL/usbdevice.cpp \
|
||||
../LibreVNA-GUI/Calibration/calibration.cpp \
|
||||
../LibreVNA-GUI/Calibration/calibrationmeasurement.cpp \
|
||||
../LibreVNA-GUI/Calibration/calibrationviewdialog.cpp \
|
||||
../LibreVNA-GUI/Calibration/calkit.cpp \
|
||||
../LibreVNA-GUI/Calibration/calkitdialog.cpp \
|
||||
../LibreVNA-GUI/Calibration/calstandard.cpp \
|
||||
|
|
@ -26,10 +25,8 @@ SOURCES += \
|
|||
../LibreVNA-GUI/CustomWidgets/toggleswitch.cpp \
|
||||
../LibreVNA-GUI/CustomWidgets/touchstoneimport.cpp \
|
||||
../LibreVNA-GUI/CustomWidgets/tracesetselector.cpp \
|
||||
../LibreVNA-GUI/Device/Harogic/harogicb60.cpp \
|
||||
../LibreVNA-GUI/Device/LibreVNA/amplitudecaldialog.cpp \
|
||||
../LibreVNA-GUI/Device/LibreVNA/deviceconfigurationdialogv1.cpp \
|
||||
../LibreVNA-GUI/Device/LibreVNA/deviceconfigurationdialogvd0.cpp \
|
||||
../LibreVNA-GUI/Device/LibreVNA/deviceconfigurationdialogvfe.cpp \
|
||||
../LibreVNA-GUI/Device/LibreVNA/deviceconfigurationdialogvff.cpp \
|
||||
../LibreVNA-GUI/Device/LibreVNA/firmwareupdatedialog.cpp \
|
||||
|
|
@ -38,8 +35,6 @@ SOURCES += \
|
|||
../LibreVNA-GUI/Device/LibreVNA/librevnatcpdriver.cpp \
|
||||
../LibreVNA-GUI/Device/LibreVNA/librevnausbdriver.cpp \
|
||||
../LibreVNA-GUI/Device/LibreVNA/manualcontroldialogV1.cpp \
|
||||
../LibreVNA-GUI/Device/LibreVNA/manualcontroldialogVD0.cpp \
|
||||
../LibreVNA-GUI/Device/LibreVNA/manualcontroldialogVE0.cpp \
|
||||
../LibreVNA-GUI/Device/LibreVNA/manualcontroldialogvfe.cpp \
|
||||
../LibreVNA-GUI/Device/LibreVNA/manualcontroldialogvff.cpp \
|
||||
../LibreVNA-GUI/Device/LibreVNA/receivercaldialog.cpp \
|
||||
|
|
@ -113,7 +108,6 @@ SOURCES += \
|
|||
../LibreVNA-GUI/Traces/eyediagramplot.cpp \
|
||||
../LibreVNA-GUI/Traces/fftcomplex.cpp \
|
||||
../LibreVNA-GUI/Traces/sparamtraceselector.cpp \
|
||||
../LibreVNA-GUI/Traces/sparamtraceselectordialog.cpp \
|
||||
../LibreVNA-GUI/Traces/trace.cpp \
|
||||
../LibreVNA-GUI/Traces/traceaxis.cpp \
|
||||
../LibreVNA-GUI/Traces/tracecsvexport.cpp \
|
||||
|
|
@ -156,12 +150,10 @@ SOURCES += \
|
|||
../LibreVNA-GUI/preferences.cpp \
|
||||
../LibreVNA-GUI/savable.cpp \
|
||||
../LibreVNA-GUI/scpi.cpp \
|
||||
../LibreVNA-GUI/screenshot.cpp \
|
||||
../LibreVNA-GUI/tcpserver.cpp \
|
||||
../LibreVNA-GUI/streamingserver.cpp \
|
||||
../LibreVNA-GUI/touchstone.cpp \
|
||||
../LibreVNA-GUI/unit.cpp \
|
||||
calibrationtests.cpp \
|
||||
ffttests.cpp \
|
||||
impedancerenormalizationtests.cpp \
|
||||
main.cpp \
|
||||
|
|
@ -206,7 +198,6 @@ HEADERS += \
|
|||
../LibreVNA-GUI/Calibration/LibreCAL/usbdevice.h \
|
||||
../LibreVNA-GUI/Calibration/calibration.h \
|
||||
../LibreVNA-GUI/Calibration/calibrationmeasurement.h \
|
||||
../LibreVNA-GUI/Calibration/calibrationviewdialog.h \
|
||||
../LibreVNA-GUI/Calibration/calkit.h \
|
||||
../LibreVNA-GUI/Calibration/calkitdialog.h \
|
||||
../LibreVNA-GUI/Calibration/calstandard.h \
|
||||
|
|
@ -220,10 +211,8 @@ HEADERS += \
|
|||
../LibreVNA-GUI/CustomWidgets/toggleswitch.h \
|
||||
../LibreVNA-GUI/CustomWidgets/touchstoneimport.h \
|
||||
../LibreVNA-GUI/CustomWidgets/tracesetselector.h \
|
||||
../LibreVNA-GUI/Device/Harogic/harogicb60.h \
|
||||
../LibreVNA-GUI/Device/LibreVNA/amplitudecaldialog.h \
|
||||
../LibreVNA-GUI/Device/LibreVNA/deviceconfigurationdialogv1.h \
|
||||
../LibreVNA-GUI/Device/LibreVNA/deviceconfigurationdialogvd0.h \
|
||||
../LibreVNA-GUI/Device/LibreVNA/deviceconfigurationdialogvfe.h \
|
||||
../LibreVNA-GUI/Device/LibreVNA/deviceconfigurationdialogvff.h \
|
||||
../LibreVNA-GUI/Device/LibreVNA/firmwareupdatedialog.h \
|
||||
|
|
@ -232,8 +221,6 @@ HEADERS += \
|
|||
../LibreVNA-GUI/Device/LibreVNA/librevnatcpdriver.h \
|
||||
../LibreVNA-GUI/Device/LibreVNA/librevnausbdriver.h \
|
||||
../LibreVNA-GUI/Device/LibreVNA/manualcontroldialogV1.h \
|
||||
../LibreVNA-GUI/Device/LibreVNA/manualcontroldialogVD0.h \
|
||||
../LibreVNA-GUI/Device/LibreVNA/manualcontroldialogVE0.h \
|
||||
../LibreVNA-GUI/Device/LibreVNA/manualcontroldialogvfe.h \
|
||||
../LibreVNA-GUI/Device/LibreVNA/manualcontroldialogvff.h \
|
||||
../LibreVNA-GUI/Device/LibreVNA/receivercaldialog.h \
|
||||
|
|
@ -318,7 +305,6 @@ HEADERS += \
|
|||
../LibreVNA-GUI/Traces/eyediagramplot.h \
|
||||
../LibreVNA-GUI/Traces/fftcomplex.h \
|
||||
../LibreVNA-GUI/Traces/sparamtraceselector.h \
|
||||
../LibreVNA-GUI/Traces/sparamtraceselectordialog.h \
|
||||
../LibreVNA-GUI/Traces/trace.h \
|
||||
../LibreVNA-GUI/Traces/traceaxis.h \
|
||||
../LibreVNA-GUI/Traces/tracecsvexport.h \
|
||||
|
|
@ -362,12 +348,10 @@ HEADERS += \
|
|||
../LibreVNA-GUI/preferences.h \
|
||||
../LibreVNA-GUI/savable.h \
|
||||
../LibreVNA-GUI/scpi.h \
|
||||
../LibreVNA-GUI/screenshot.h \
|
||||
../LibreVNA-GUI/tcpserver.h \
|
||||
../LibreVNA-GUI/streamingserver.h \
|
||||
../LibreVNA-GUI/touchstone.h \
|
||||
../LibreVNA-GUI/unit.h \
|
||||
calibrationtests.h \
|
||||
ffttests.h \
|
||||
impedancerenormalizationtests.h \
|
||||
parametertests.h \
|
||||
|
|
@ -390,7 +374,6 @@ FORMS += \
|
|||
../LibreVNA-GUI/Calibration/LibreCAL/factoryUpdateDialog.ui \
|
||||
../LibreVNA-GUI/Calibration/LibreCAL/librecaldialog.ui \
|
||||
../LibreVNA-GUI/Calibration/calibrationdialogui.ui \
|
||||
../LibreVNA-GUI/Calibration/calibrationviewdialog.ui \
|
||||
../LibreVNA-GUI/Calibration/calkitdialog.ui \
|
||||
../LibreVNA-GUI/Calibration/manualcalibrationdialog.ui \
|
||||
../LibreVNA-GUI/CustomWidgets/csvimport.ui \
|
||||
|
|
@ -402,7 +385,6 @@ FORMS += \
|
|||
../LibreVNA-GUI/Device/LibreVNA/amplitudecaldialog.ui \
|
||||
../LibreVNA-GUI/Device/LibreVNA/automaticamplitudedialog.ui \
|
||||
../LibreVNA-GUI/Device/LibreVNA/deviceconfigurationdialogv1.ui \
|
||||
../LibreVNA-GUI/Device/LibreVNA/deviceconfigurationdialogvd0.ui \
|
||||
../LibreVNA-GUI/Device/LibreVNA/deviceconfigurationdialogvfe.ui \
|
||||
../LibreVNA-GUI/Device/LibreVNA/deviceconfigurationdialogvff.ui \
|
||||
../LibreVNA-GUI/Device/LibreVNA/firmwareupdatedialog.ui \
|
||||
|
|
@ -410,8 +392,6 @@ FORMS += \
|
|||
../LibreVNA-GUI/Device/LibreVNA/librevnadriversettingswidget.ui \
|
||||
../LibreVNA-GUI/Device/LibreVNA/manualcontroldialogV1.ui \
|
||||
../LibreVNA-GUI/Device/LibreVNA/Compound/compounddeviceeditdialog.ui \
|
||||
../LibreVNA-GUI/Device/LibreVNA/manualcontroldialogVD0.ui \
|
||||
../LibreVNA-GUI/Device/LibreVNA/manualcontroldialogVE0.ui \
|
||||
../LibreVNA-GUI/Device/LibreVNA/manualcontroldialogvfe.ui \
|
||||
../LibreVNA-GUI/Device/LibreVNA/manualcontroldialogvff.ui \
|
||||
../LibreVNA-GUI/Device/devicelog.ui \
|
||||
|
|
@ -437,7 +417,6 @@ FORMS += \
|
|||
../LibreVNA-GUI/Traces/eyediagrameditdialog.ui \
|
||||
../LibreVNA-GUI/Traces/polarchartdialog.ui \
|
||||
../LibreVNA-GUI/Traces/smithchartdialog.ui \
|
||||
../LibreVNA-GUI/Traces/sparamtraceselectordialog.ui \
|
||||
../LibreVNA-GUI/Traces/tracecsvexport.ui \
|
||||
../LibreVNA-GUI/Traces/traceeditdialog.ui \
|
||||
../LibreVNA-GUI/Traces/traceimportdialog.ui \
|
||||
|
|
|
|||
|
|
@ -1,136 +0,0 @@
|
|||
#include "calibrationtests.h"
|
||||
|
||||
#include "calibration.h"
|
||||
|
||||
CalibrationTests::CalibrationTests() {}
|
||||
|
||||
void CalibrationTests::LinearDetection()
|
||||
{
|
||||
// create some measurements
|
||||
std::vector<CalibrationMeasurement::Base*> m;
|
||||
double startFreq = 100000;
|
||||
double stopFreq = 6000000000;
|
||||
int points = 1001;
|
||||
Calibration cal;
|
||||
cal.getKit().setIdealDefault();
|
||||
auto open = new CalibrationMeasurement::Open(&cal);
|
||||
open->setPort(1);
|
||||
m.push_back(open);
|
||||
auto _short = new CalibrationMeasurement::Short(&cal);
|
||||
_short->setPort(1);
|
||||
m.push_back(_short);
|
||||
auto load = new CalibrationMeasurement::Load(&cal);
|
||||
load->setPort(1);
|
||||
m.push_back(load);
|
||||
|
||||
for(int i=0;i<points;i++) {
|
||||
double f = startFreq + (stopFreq - startFreq) * i / (points-1);
|
||||
DeviceDriver::VNAMeasurement meas;
|
||||
meas.frequency = f;
|
||||
meas.measurements["S11"] = 0.0;
|
||||
m[0]->addPoint(meas);
|
||||
m[1]->addPoint(meas);
|
||||
m[2]->addPoint(meas);
|
||||
}
|
||||
|
||||
// verify correct detection
|
||||
double detectedStart;
|
||||
double detectedStop;
|
||||
int detectedPoints;
|
||||
bool detectedLog;
|
||||
Calibration::hasFrequencyOverlap(m, &detectedStart, &detectedStop, &detectedPoints, &detectedLog);
|
||||
|
||||
QVERIFY(qFuzzyCompare(detectedStart, startFreq));
|
||||
QVERIFY(qFuzzyCompare(detectedStop, stopFreq));
|
||||
QVERIFY(detectedPoints == points);
|
||||
QVERIFY(detectedLog == false);
|
||||
}
|
||||
|
||||
void CalibrationTests::LogDetection()
|
||||
{
|
||||
// create some measurements
|
||||
std::vector<CalibrationMeasurement::Base*> m;
|
||||
double startFreq = 100000;
|
||||
double stopFreq = 6000000000;
|
||||
int points = 1001;
|
||||
Calibration cal;
|
||||
cal.getKit().setIdealDefault();
|
||||
auto open = new CalibrationMeasurement::Open(&cal);
|
||||
open->setPort(1);
|
||||
m.push_back(open);
|
||||
auto _short = new CalibrationMeasurement::Short(&cal);
|
||||
_short->setPort(1);
|
||||
m.push_back(_short);
|
||||
auto load = new CalibrationMeasurement::Load(&cal);
|
||||
load->setPort(1);
|
||||
m.push_back(load);
|
||||
|
||||
for(int i=0;i<points;i++) {
|
||||
double f = startFreq * pow(10.0, i * log10(stopFreq / startFreq) / (points - 1));
|
||||
DeviceDriver::VNAMeasurement meas;
|
||||
meas.frequency = f;
|
||||
meas.measurements["S11"] = 0.0;
|
||||
m[0]->addPoint(meas);
|
||||
m[1]->addPoint(meas);
|
||||
m[2]->addPoint(meas);
|
||||
}
|
||||
|
||||
// verify correct detection
|
||||
double detectedStart;
|
||||
double detectedStop;
|
||||
int detectedPoints;
|
||||
bool detectedLog;
|
||||
Calibration::hasFrequencyOverlap(m, &detectedStart, &detectedStop, &detectedPoints, &detectedLog);
|
||||
|
||||
QVERIFY(qFuzzyCompare(detectedStart, startFreq));
|
||||
QVERIFY(qFuzzyCompare(detectedStop, stopFreq));
|
||||
QVERIFY(detectedPoints == points);
|
||||
QVERIFY(detectedLog == true);
|
||||
}
|
||||
|
||||
void CalibrationTests::MixedDetection()
|
||||
{
|
||||
// create some measurements
|
||||
std::vector<CalibrationMeasurement::Base*> m;
|
||||
double startFreq = 100000;
|
||||
double stopFreq = 6000000000;
|
||||
int points = 1001;
|
||||
Calibration cal;
|
||||
cal.getKit().setIdealDefault();
|
||||
auto open = new CalibrationMeasurement::Open(&cal);
|
||||
open->setPort(1);
|
||||
m.push_back(open);
|
||||
auto _short = new CalibrationMeasurement::Short(&cal);
|
||||
_short->setPort(1);
|
||||
m.push_back(_short);
|
||||
auto load = new CalibrationMeasurement::Load(&cal);
|
||||
load->setPort(1);
|
||||
m.push_back(load);
|
||||
|
||||
for(int i=0;i<points;i++) {
|
||||
// one linear measurement, two log measurement
|
||||
double flin = startFreq + (stopFreq - startFreq) * i / (points-1);
|
||||
double flog = startFreq * pow(10.0, i * log10(stopFreq / startFreq) / (points - 1));
|
||||
DeviceDriver::VNAMeasurement measlin;
|
||||
measlin.frequency = flin;
|
||||
measlin.measurements["S11"] = 0.0;
|
||||
DeviceDriver::VNAMeasurement measlog;
|
||||
measlog.frequency = flog;
|
||||
measlog.measurements["S11"] = 0.0;
|
||||
m[0]->addPoint(measlin);
|
||||
m[1]->addPoint(measlog);
|
||||
m[2]->addPoint(measlog);
|
||||
}
|
||||
|
||||
// verify correct detection
|
||||
double detectedStart;
|
||||
double detectedStop;
|
||||
int detectedPoints;
|
||||
bool detectedLog;
|
||||
Calibration::hasFrequencyOverlap(m, &detectedStart, &detectedStop, &detectedPoints, &detectedLog);
|
||||
|
||||
QVERIFY(qFuzzyCompare(detectedStart, startFreq));
|
||||
QVERIFY(qFuzzyCompare(detectedStop, stopFreq));
|
||||
QVERIFY(detectedPoints == points);
|
||||
QVERIFY(detectedLog == true);
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue