kopia lustrzana https://github.com/NanoVNA-Saver/nanovna-saver
214 wiersze
8.0 KiB
Python
214 wiersze
8.0 KiB
Python
# NanoVNASaver
|
|
#
|
|
# A python program to view and export Touchstone data from a NanoVNA
|
|
# Copyright (C) 2019, 2020 Rune B. Broberg
|
|
# Copyright (C) 2020 NanoVNA-Saver Authors
|
|
#
|
|
# This program is free software: you can redistribute it and/or modify
|
|
# it under the terms of the GNU General Public License as published by
|
|
# the Free Software Foundation, either version 3 of the License, or
|
|
# (at your option) any later version.
|
|
#
|
|
# This program is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
# GNU General Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU General Public License
|
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
import logging
|
|
|
|
from PyQt5 import QtWidgets, QtCore
|
|
from PyQt5.QtCore import pyqtSignal
|
|
|
|
|
|
from NanoVNASaver.Formatting import (
|
|
format_frequency_sweep, format_frequency_short,
|
|
parse_frequency)
|
|
from NanoVNASaver.Inputs import FrequencyInputWidget
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
class SweepControl(QtWidgets.QGroupBox):
|
|
updated = pyqtSignal(object)
|
|
|
|
def __init__(self, app: QtWidgets.QWidget, title: str = "Sweep control"):
|
|
super().__init__()
|
|
self.app = app
|
|
self.setMaximumWidth(250)
|
|
self.setTitle(title)
|
|
control_layout = QtWidgets.QFormLayout(self)
|
|
|
|
line = QtWidgets.QFrame()
|
|
line.setFrameShape(QtWidgets.QFrame.VLine)
|
|
|
|
input_layout = QtWidgets.QHBoxLayout()
|
|
input_left_layout = QtWidgets.QFormLayout()
|
|
input_right_layout = QtWidgets.QFormLayout()
|
|
input_layout.addLayout(input_left_layout)
|
|
input_layout.addWidget(line)
|
|
input_layout.addLayout(input_right_layout)
|
|
control_layout.addRow(input_layout)
|
|
|
|
self.input_start = FrequencyInputWidget()
|
|
self.input_start.setMinimumWidth(60)
|
|
self.input_start.setAlignment(QtCore.Qt.AlignRight)
|
|
self.input_start.textEdited.connect(self.update_center_span)
|
|
self.input_start.textChanged.connect(self.update_step_size)
|
|
input_left_layout.addRow(QtWidgets.QLabel("Start"), self.input_start)
|
|
|
|
self.input_end = FrequencyInputWidget()
|
|
self.input_end.setAlignment(QtCore.Qt.AlignRight)
|
|
self.input_end.textEdited.connect(self.update_center_span)
|
|
self.input_end.textChanged.connect(self.update_step_size)
|
|
input_left_layout.addRow(QtWidgets.QLabel("Stop"), self.input_end)
|
|
|
|
self.input_center = FrequencyInputWidget()
|
|
self.input_center.setMinimumWidth(60)
|
|
self.input_center.setAlignment(QtCore.Qt.AlignRight)
|
|
self.input_center.textEdited.connect(self.update_start_end)
|
|
|
|
input_right_layout.addRow(QtWidgets.QLabel("Center"), self.input_center)
|
|
|
|
self.input_span = FrequencyInputWidget()
|
|
self.input_span.setAlignment(QtCore.Qt.AlignRight)
|
|
self.input_span.textEdited.connect(self.update_start_end)
|
|
|
|
input_right_layout.addRow(QtWidgets.QLabel("Span"), self.input_span)
|
|
|
|
self.input_segments = QtWidgets.QLineEdit(self.app.settings.value("Segments", "1"))
|
|
self.input_segments.setAlignment(QtCore.Qt.AlignRight)
|
|
self.input_segments.setFixedWidth(60)
|
|
self.input_segments.textEdited.connect(self.update_step_size)
|
|
|
|
self.label_step = QtWidgets.QLabel("Hz/step")
|
|
self.label_step.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter)
|
|
|
|
segment_layout = QtWidgets.QHBoxLayout()
|
|
segment_layout.addWidget(self.input_segments)
|
|
segment_layout.addWidget(self.label_step)
|
|
control_layout.addRow(QtWidgets.QLabel("Segments"), segment_layout)
|
|
|
|
btn_settings_window = QtWidgets.QPushButton("Sweep settings ...")
|
|
btn_settings_window.clicked.connect(
|
|
lambda: self.app.display_window("sweep_settings"))
|
|
|
|
control_layout.addRow(btn_settings_window)
|
|
|
|
self.progress_bar = QtWidgets.QProgressBar()
|
|
self.progress_bar.setMaximum(100)
|
|
self.progress_bar.setValue(0)
|
|
control_layout.addRow(self.progress_bar)
|
|
|
|
self.btn_start = QtWidgets.QPushButton("Sweep")
|
|
self.btn_start.clicked.connect(self.app.sweep_start)
|
|
self.btn_start.setShortcut(QtCore.Qt.Key_W | QtCore.Qt.CTRL)
|
|
self.btn_stop = QtWidgets.QPushButton("Stop")
|
|
self.btn_stop.clicked.connect(self.app.sweep_stop)
|
|
self.btn_stop.setShortcut(QtCore.Qt.Key_Escape)
|
|
self.btn_stop.setDisabled(True)
|
|
btn_layout = QtWidgets.QHBoxLayout()
|
|
btn_layout.addWidget(self.btn_start)
|
|
btn_layout.addWidget(self.btn_stop)
|
|
btn_layout.setContentsMargins(0, 0, 0, 0)
|
|
btn_layout_widget = QtWidgets.QWidget()
|
|
btn_layout_widget.setLayout(btn_layout)
|
|
control_layout.addRow(btn_layout_widget)
|
|
|
|
self.input_start.textEdited.emit(self.input_start.text())
|
|
self.input_start.textChanged.emit(self.input_start.text())
|
|
|
|
def get_start(self) -> int:
|
|
return parse_frequency(self.input_start.text())
|
|
|
|
def set_start(self, start: int):
|
|
self.input_start.setText(format_frequency_sweep(start))
|
|
self.input_start.textEdited.emit(self.input_start.text())
|
|
self.updated.emit(self)
|
|
|
|
def get_end(self) -> int:
|
|
return parse_frequency(self.input_end.text())
|
|
|
|
def set_end(self, end: int):
|
|
self.input_end.setText(format_frequency_sweep(end))
|
|
self.input_end.textEdited.emit(self.input_end.text())
|
|
self.updated.emit(self)
|
|
|
|
def get_center(self) -> int:
|
|
return parse_frequency(self.input_center.text())
|
|
|
|
def set_center(self, center: int):
|
|
self.input_center.setText(format_frequency_sweep(center))
|
|
self.input_center.textEdited.emit(self.input_center.text())
|
|
self.updated.emit(self)
|
|
|
|
def get_segments(self) -> int:
|
|
try:
|
|
result = int(self.input_segments.text())
|
|
except ValueError:
|
|
result = 1
|
|
return result
|
|
|
|
def set_segments(self, count: int):
|
|
self.input_segments.setText(str(count))
|
|
self.input_segments.textEdited.emit(self.input_segments.text())
|
|
self.updated.emit(self)
|
|
|
|
def get_span(self) -> int:
|
|
return parse_frequency(self.input_span.text())
|
|
|
|
def set_span(self, span: int):
|
|
self.input_span.setText(format_frequency_sweep(span))
|
|
self.input_span.textEdited.emit(self.input_span.text())
|
|
self.updated.emit(self)
|
|
|
|
def toggle_settings(self, disabled):
|
|
self.input_start.setDisabled(disabled)
|
|
self.input_end.setDisabled(disabled)
|
|
self.input_span.setDisabled(disabled)
|
|
self.input_center.setDisabled(disabled)
|
|
self.input_segments.setDisabled(disabled)
|
|
|
|
def update_center_span(self):
|
|
fstart = self.get_start()
|
|
fstop = self.get_end()
|
|
fspan = fstop - fstart
|
|
fcenter = round((fstart + fstop) / 2)
|
|
if fspan < 0 or fstart < 0 or fstop < 0:
|
|
return
|
|
self.input_span.setText(fspan)
|
|
self.input_center.setText(fcenter)
|
|
self.update_sweep()
|
|
|
|
def update_start_end(self):
|
|
fcenter = self.get_center()
|
|
fspan = self.get_span()
|
|
if fspan < 0 or fcenter < 0:
|
|
return
|
|
fstart = round(fcenter - fspan / 2)
|
|
fstop = round(fcenter + fspan / 2)
|
|
if fstart < 0 or fstop < 0:
|
|
return
|
|
self.input_start.setText(fstart)
|
|
self.input_end.setText(fstop)
|
|
self.update_sweep()
|
|
|
|
def update_step_size(self):
|
|
fspan = self.get_span()
|
|
if fspan < 0:
|
|
return
|
|
segments = self.get_segments()
|
|
if segments > 0:
|
|
fstep = fspan / (segments * self.app.vna.datapoints - 1)
|
|
self.label_step.setText(
|
|
f"{format_frequency_short(fstep)}/step")
|
|
self.update_sweep()
|
|
|
|
def update_sweep(self):
|
|
sweep = self.app.sweep
|
|
with sweep.lock:
|
|
sweep.start = self.get_start()
|
|
sweep.end = self.get_end()
|
|
sweep.segments = self.get_segments()
|