From a4a923a64919e718250f54883e83d74eb6918a6f Mon Sep 17 00:00:00 2001 From: t52ta6ek <24543390+t52ta6ek@users.noreply.github.com> Date: Wed, 5 Jul 2023 10:18:51 +0200 Subject: [PATCH] Jncradiovna3g - support Sysjoint-Tek / CHELEGANCE JNCRadio VNA 3G (#652) * Added support for Sysjoint-Tek / CHELEGANCE JNCRadio VNA 3G Device reported as JNCRadio and Custom points added under Manage tab. * Minor change to correct spelling or error msg. --- AUTHORS.rst | 1 + src/NanoVNASaver/Hardware/Hardware.py | 3 ++ src/NanoVNASaver/Hardware/JNCRadio_VNA_3G.py | 57 ++++++++++++++++++++ src/NanoVNASaver/Hardware/VNA.py | 9 ++++ src/NanoVNASaver/Windows/DeviceSettings.py | 37 +++++++++++++ 5 files changed, 107 insertions(+) create mode 100644 src/NanoVNASaver/Hardware/JNCRadio_VNA_3G.py diff --git a/AUTHORS.rst b/AUTHORS.rst index 4d7cde1..6540d56 100644 --- a/AUTHORS.rst +++ b/AUTHORS.rst @@ -39,4 +39,5 @@ Contributors * Rune B. Broberg * Sascha Silbe * sysjoint-tek <63992872+sysjoint-tek@users.noreply.github.com> +* Thomas de Lellis <24543390+t52ta6ek@users.noreply.github.com> * zstadler diff --git a/src/NanoVNASaver/Hardware/Hardware.py b/src/NanoVNASaver/Hardware/Hardware.py index b63f5f3..327e849 100644 --- a/src/NanoVNASaver/Hardware/Hardware.py +++ b/src/NanoVNASaver/Hardware/Hardware.py @@ -30,6 +30,7 @@ from NanoVNASaver.Hardware.AVNA import AVNA from NanoVNASaver.Hardware.NanoVNA import NanoVNA from NanoVNASaver.Hardware.NanoVNA_F import NanoVNA_F from NanoVNASaver.Hardware.NanoVNA_F_V2 import NanoVNA_F_V2 +from NanoVNASaver.Hardware.JNCRadio_VNA_3G import JNCRadio_VNA_3G from NanoVNASaver.Hardware.NanoVNA_H import NanoVNA_H from NanoVNASaver.Hardware.NanoVNA_H4 import NanoVNA_H4 from NanoVNASaver.Hardware.NanoVNA_V2 import NanoVNA_V2 @@ -55,6 +56,7 @@ NAME2DEVICE = { "H4": NanoVNA_H4, "H": NanoVNA_H, "F_V2": NanoVNA_F_V2, + "JNCRadio": JNCRadio_VNA_3G, "F": NanoVNA_F, "NanoVNA": NanoVNA, "tinySA": TinySA, @@ -150,6 +152,7 @@ def get_comment(iface: Interface) -> str: ("NanoVNA-H 4", "H4"), ("NanoVNA-H", "H"), ("NanoVNA-F_V2", "F_V2"), + ("JNCRadio_VNA_3G", "JNCRadio"), ("NanoVNA-F", "F"), ("NanoVNA", "NanoVNA"), ("tinySA4", "tinySA_Ultra"), diff --git a/src/NanoVNASaver/Hardware/JNCRadio_VNA_3G.py b/src/NanoVNASaver/Hardware/JNCRadio_VNA_3G.py new file mode 100644 index 0000000..18a9d50 --- /dev/null +++ b/src/NanoVNASaver/Hardware/JNCRadio_VNA_3G.py @@ -0,0 +1,57 @@ +# NanoVNASaver +# +# A python program to view and export Touchstone data from a NanoVNA +# Copyright (C) 2019, 2020 Rune B. Broberg +# Copyright (C) 2020,2021 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 . +import logging + +import serial +from PyQt6.QtGui import QImage, QPixmap + +from NanoVNASaver.Hardware.NanoVNA import NanoVNA +from NanoVNASaver.Hardware.Serial import Interface + +logger = logging.getLogger(__name__) + + +class JNCRadio_VNA_3G(NanoVNA): + name = "JNCRadio_VNA_3G" + screenwidth = 800 + screenheight = 480 + valid_datapoints = (101, 201, 301, 401, 501) + sweep_points_max = 501 + + def __init__(self, iface: Interface): + super().__init__(iface) + self.sweep_max_freq_Hz = 3e9 + + def getScreenshot(self) -> QPixmap: + logger.debug("Capturing screenshot...") + if not self.connected(): + return QPixmap() + try: + rgba_array = self._capture_data() + image = QImage( + rgba_array, + self.screenwidth, + self.screenheight, + QImage.Format.Format_RGB16, + ) + logger.debug("Captured screenshot") + return QPixmap(image) + except serial.SerialException as exc: + logger.exception("Exception while capturing screenshot: %s", exc) + return QPixmap() diff --git a/src/NanoVNASaver/Hardware/VNA.py b/src/NanoVNASaver/Hardware/VNA.py index 361efca..7006cf3 100644 --- a/src/NanoVNASaver/Hardware/VNA.py +++ b/src/NanoVNASaver/Hardware/VNA.py @@ -55,6 +55,9 @@ class VNA: name = "VNA" valid_datapoints = (101, 51, 11) wait = 0.05 + SN = "NOT SUPPORTED" + sweep_points_max = 101 + sweep_points_min = 11 def __init__(self, iface: Interface): self.serial = iface @@ -123,6 +126,9 @@ class VNA: logger.debug("result:\n%s", result) if "capture" in result: self.features.add("Screenshots") + if "sn:" in result: + self.features.add("SN") + self.SN = self.getSerialNumber() if "bandwidth" in result: self.features.add("Bandwidth") result = " ".join(list(self.exec_command("bandwidth"))) @@ -210,3 +216,6 @@ class VNA: def setTXPower(self, freq_range, power_desc): raise NotImplementedError() + + def getSerialNumber(self) -> str: + return " ".join(list(self.exec_command("sn"))) diff --git a/src/NanoVNASaver/Windows/DeviceSettings.py b/src/NanoVNASaver/Windows/DeviceSettings.py index 0a9673d..acffcad 100644 --- a/src/NanoVNASaver/Windows/DeviceSettings.py +++ b/src/NanoVNASaver/Windows/DeviceSettings.py @@ -18,6 +18,7 @@ # along with this program. If not, see . import logging +from PyQt6.QtGui import QIntValidator from PyQt6 import QtWidgets, QtCore, QtGui from NanoVNASaver.Windows.Defaults import make_scrollable @@ -27,6 +28,8 @@ logger = logging.getLogger(__name__) class DeviceSettingsWindow(QtWidgets.QWidget): + custom_points_checkBox = QtWidgets.QCheckBox + custom_points_Eidt = QtWidgets.QLineEdit def __init__(self, app: QtWidgets.QWidget): super().__init__() @@ -40,6 +43,7 @@ class DeviceSettingsWindow(QtWidgets.QWidget): "status": QtWidgets.QLabel("Not connected."), "firmware": QtWidgets.QLabel("Not connected."), "calibration": QtWidgets.QLabel("Not connected."), + "SN": QtWidgets.QLabel("Not connected."), } top_layout = QtWidgets.QHBoxLayout() @@ -55,6 +59,7 @@ class DeviceSettingsWindow(QtWidgets.QWidget): status_layout.addRow("Status:", self.label["status"]) status_layout.addRow("Firmware:", self.label["firmware"]) status_layout.addRow("Calibration:", self.label["calibration"]) + status_layout.addRow("SN:", self.label["SN"]) status_layout.addRow(QtWidgets.QLabel("Features:")) @@ -91,12 +96,20 @@ class DeviceSettingsWindow(QtWidgets.QWidget): self.datapoints.addItem(str(self.app.vna.datapoints)) self.datapoints.currentIndexChanged.connect(self.updateNrDatapoints) + self.custom_points_checkBox = QtWidgets.QCheckBox("Custom points") + self.custom_points_checkBox.stateChanged.connect(self.customPoint_check) + self.custom_points_Eidt = QtWidgets.QLineEdit("101") + self.custom_points_Eidt.setValidator(QIntValidator(self.app.vna.sweep_points_min,self.app.vna.sweep_points_max)) + self.custom_points_Eidt.textEdited.connect(self.updatecustomPoint) + self.custom_points_Eidt.setDisabled(True) + self.bandwidth = QtWidgets.QComboBox() self.bandwidth.addItem(str(self.app.vna.bandwidth)) self.bandwidth.currentIndexChanged.connect(self.updateBandwidth) form_layout = QtWidgets.QFormLayout() form_layout.addRow(QtWidgets.QLabel("Datapoints"), self.datapoints) + form_layout.addRow(self.custom_points_checkBox, self.custom_points_Eidt) form_layout.addRow(QtWidgets.QLabel("Bandwidth"), self.bandwidth) right_layout.addWidget(settings_box) settings_layout.addRow(form_layout) @@ -116,6 +129,7 @@ class DeviceSettingsWindow(QtWidgets.QWidget): self.label["status"].setText("Not connected.") self.label["firmware"].setText("Not connected.") self.label["calibration"].setText("Not connected.") + self.label["SN"].setText("Not connected.") self.featureList.clear() self.btnCaptureScreenshot.setDisabled(True) return @@ -128,6 +142,7 @@ class DeviceSettingsWindow(QtWidgets.QWidget): self.label["calibration"].setText("(Sweep running)") else: self.label["calibration"].setText(self.app.vna.getCalibration()) + self.label["SN"].setText(self.app.vna.SN) self.featureList.clear() features = self.app.vna.getFeatures() for item in features: @@ -182,3 +197,25 @@ class DeviceSettingsWindow(QtWidgets.QWidget): return logger.debug("Bandwidth: %s", self.bandwidth.itemText(i)) self.app.vna.set_bandwidth(int(self.bandwidth.itemText(i))) + + def customPoint_check(self, validate_data: bool): + self.datapoints.setDisabled(validate_data) + self.custom_points_Eidt.setDisabled(not(validate_data)) + + def updatecustomPoint(self,points_str: str): + if self.custom_points_checkBox.isChecked(): + #points_str = self.custom_points_Eidt.text() + if len(points_str) == 0: + return + points = int(points_str) + if points < self.app.vna.sweep_points_min: + return + if points > self.app.vna.sweep_points_max: + points = int(self.app.vna.sweep_points_max) + + if points != self.app.vna.datapoints: + logger.debug("DP: %s", points) + self.app.vna.datapoints = points + self.app.sweep.points = self.app.vna.datapoints + self.app.sweep_control.update_step_size() + self.custom_points_Eidt.setText(str(points))