From 753b3fab9407b1c9f94e3db380a89e1b350bcb6c Mon Sep 17 00:00:00 2001 From: xros Date: Wed, 8 Jan 2025 12:16:29 +0800 Subject: [PATCH 01/15] add nanovna f v3 in hardware --- src/NanoVNASaver/Hardware/Hardware.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/NanoVNASaver/Hardware/Hardware.py b/src/NanoVNASaver/Hardware/Hardware.py index 4965f19f..0577411d 100644 --- a/src/NanoVNASaver/Hardware/Hardware.py +++ b/src/NanoVNASaver/Hardware/Hardware.py @@ -30,6 +30,7 @@ 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.NanoVNA_F_V3 import NanoVNA_F_V3 from NanoVNASaver.Hardware.NanoVNA_H import NanoVNA_H from NanoVNASaver.Hardware.NanoVNA_H4 import NanoVNA_H4 from NanoVNASaver.Hardware.NanoVNA_V2 import NanoVNA_V2 @@ -58,6 +59,7 @@ "H4": NanoVNA_H4, "H": NanoVNA_H, "F_V2": NanoVNA_F_V2, + "F_V3": NanoVNA_F_V3, "F": NanoVNA_F, "NanoVNA": NanoVNA, "tinySA": TinySA, @@ -138,14 +140,13 @@ def get_portinfos() -> list[str]: def get_VNA(iface: Interface) -> VNA: # serial_port.timeout = TIMEOUT + # debug1 return NAME2DEVICE[iface.comment](iface) - def get_comment(iface: Interface) -> str: logger.info("Finding correct VNA type...") with iface.lock: vna_version = detect_version(iface) - if vna_version == "v2": return "S-A-A-2" @@ -156,6 +157,7 @@ def get_comment(iface: Interface) -> str: ("NanoVNA-H 4", "H4"), ("NanoVNA-H", "H"), ("NanoVNA-F_V2", "F_V2"), + ("NanoVNA-F_V3", "F_V3"), ("NanoVNA-F", "F"), ("NanoVNA", "NanoVNA"), ("tinySA4", "tinySA_Ultra"), @@ -181,6 +183,7 @@ def detect_version(serial_port: serial.Serial) -> str: sleep(0.05) data = serial_port.read(128).decode("ascii") + if data.startswith("ch> "): return "v1" # -H versions From e39d4f44b0c65f1d494a0d4377771b0106e859f5 Mon Sep 17 00:00:00 2001 From: xros Date: Wed, 8 Jan 2025 12:20:29 +0800 Subject: [PATCH 02/15] fix SN number not showing in nanovna F v3 using nanovna-saver --- src/NanoVNASaver/Hardware/VNA.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/NanoVNASaver/Hardware/VNA.py b/src/NanoVNASaver/Hardware/VNA.py index 727a1cf4..36ca46df 100644 --- a/src/NanoVNASaver/Hardware/VNA.py +++ b/src/NanoVNASaver/Hardware/VNA.py @@ -56,6 +56,7 @@ class VNA: valid_datapoints = (101, 51, 11) wait = 0.05 SN = "NOT SUPPORTED" + sweep_points_max = 101 sweep_points_min = 11 @@ -126,9 +127,13 @@ def read_features(self): logger.debug("result:\n%s", result) if "capture" in result: self.features.add("Screenshots") - if "sn:" in result: + + #mod# + if "sn:" or "SN:" in result: self.features.add("SN") self.SN = self.getSerialNumber() + #end-mod# + if "bandwidth" in result: self.features.add("Bandwidth") result = " ".join(list(self.exec_command("bandwidth"))) @@ -220,4 +225,5 @@ def setTXPower(self, freq_range, power_desc): raise NotImplementedError() def getSerialNumber(self) -> str: - return " ".join(list(self.exec_command("sn"))) + # return " ".join(list(self.exec_command("sn"))) + return " ".join(list(self.exec_command("SN"))) From 2b4b6963063c7bd7702beab1bd96b4cd3f44c63f Mon Sep 17 00:00:00 2001 From: xros Date: Wed, 8 Jan 2025 12:32:31 +0800 Subject: [PATCH 03/15] add hardware settings for NanoVNA F V3 & set data valid points to 101, 11, 51, 201, 301, 501, 801 --- src/NanoVNASaver/Hardware/NanoVNA_F_V3.py | 58 +++++++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 src/NanoVNASaver/Hardware/NanoVNA_F_V3.py diff --git a/src/NanoVNASaver/Hardware/NanoVNA_F_V3.py b/src/NanoVNASaver/Hardware/NanoVNA_F_V3.py new file mode 100644 index 00000000..d1b86976 --- /dev/null +++ b/src/NanoVNASaver/Hardware/NanoVNA_F_V3.py @@ -0,0 +1,58 @@ +# 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 NanoVNA_F_V3(NanoVNA): + name = "NanoVNA-F_V3" + screenwidth = 800 + screenheight = 480 + valid_datapoints = (101, 11, 51, 201, 301, 501, 801) + sweep_points_min = 11 + sweep_points_max = 801 + + def __init__(self, iface: Interface): + super().__init__(iface) + self.sweep_max_freq_Hz = 6.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() From 6eb4ba508bf6c1753f5f4985dc6625c49106509f Mon Sep 17 00:00:00 2001 From: xros Date: Wed, 8 Jan 2025 13:03:56 +0800 Subject: [PATCH 04/15] fix showing serial number on different VNAs whether they use different uppercase SN commands or lowercase sn commands --- src/NanoVNASaver/Hardware/VNA.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/NanoVNASaver/Hardware/VNA.py b/src/NanoVNASaver/Hardware/VNA.py index 36ca46df..efb3bd84 100644 --- a/src/NanoVNASaver/Hardware/VNA.py +++ b/src/NanoVNASaver/Hardware/VNA.py @@ -225,5 +225,4 @@ def setTXPower(self, freq_range, power_desc): raise NotImplementedError() def getSerialNumber(self) -> str: - # return " ".join(list(self.exec_command("sn"))) - return " ".join(list(self.exec_command("SN"))) + return " ".join(list(self.exec_command("SN"))) if 'SN:' in " ".join(self.exec_command("help")).split() else " ".join(list(self.exec_command("sn"))) \ No newline at end of file From c210cdcb54988c05f7a679c872e00b6a77a8b641 Mon Sep 17 00:00:00 2001 From: xros Date: Wed, 8 Jan 2025 13:16:29 +0800 Subject: [PATCH 05/15] remove unused comments in codes --- src/NanoVNASaver/Hardware/VNA.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/NanoVNASaver/Hardware/VNA.py b/src/NanoVNASaver/Hardware/VNA.py index efb3bd84..ecffec5e 100644 --- a/src/NanoVNASaver/Hardware/VNA.py +++ b/src/NanoVNASaver/Hardware/VNA.py @@ -128,11 +128,9 @@ def read_features(self): if "capture" in result: self.features.add("Screenshots") - #mod# if "sn:" or "SN:" in result: self.features.add("SN") self.SN = self.getSerialNumber() - #end-mod# if "bandwidth" in result: self.features.add("Bandwidth") From db3b3a3072d2932e6751f1373686108a0720aad0 Mon Sep 17 00:00:00 2001 From: xros Date: Wed, 8 Jan 2025 13:19:41 +0800 Subject: [PATCH 06/15] remove unused comments in codes --- src/NanoVNASaver/Hardware/Hardware.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/NanoVNASaver/Hardware/Hardware.py b/src/NanoVNASaver/Hardware/Hardware.py index 0577411d..e15a5d1a 100644 --- a/src/NanoVNASaver/Hardware/Hardware.py +++ b/src/NanoVNASaver/Hardware/Hardware.py @@ -140,7 +140,6 @@ def get_portinfos() -> list[str]: def get_VNA(iface: Interface) -> VNA: # serial_port.timeout = TIMEOUT - # debug1 return NAME2DEVICE[iface.comment](iface) def get_comment(iface: Interface) -> str: From 2449d5cbafb1f0229b16e287d7d4320b05c82b70 Mon Sep 17 00:00:00 2001 From: xros Date: Wed, 8 Jan 2025 13:24:44 +0800 Subject: [PATCH 07/15] remove unused comments in codes --- src/NanoVNASaver/Hardware/VNA.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/NanoVNASaver/Hardware/VNA.py b/src/NanoVNASaver/Hardware/VNA.py index ecffec5e..64938bc5 100644 --- a/src/NanoVNASaver/Hardware/VNA.py +++ b/src/NanoVNASaver/Hardware/VNA.py @@ -56,7 +56,6 @@ class VNA: valid_datapoints = (101, 51, 11) wait = 0.05 SN = "NOT SUPPORTED" - sweep_points_max = 101 sweep_points_min = 11 @@ -223,4 +222,4 @@ def setTXPower(self, freq_range, power_desc): raise NotImplementedError() def getSerialNumber(self) -> str: - return " ".join(list(self.exec_command("SN"))) if 'SN:' in " ".join(self.exec_command("help")).split() else " ".join(list(self.exec_command("sn"))) \ No newline at end of file + return " ".join(list(self.exec_command("SN"))) if 'SN:' in " ".join(self.exec_command("help")).split() else " ".join(list(self.exec_command("sn"))) From 6d2b8db893c7b5cd9019189bb55e401393ee6abf Mon Sep 17 00:00:00 2001 From: xros Date: Wed, 15 Jan 2025 02:43:41 +0800 Subject: [PATCH 08/15] unlock datapoints upto 4095 and sweep points upto 65535 --- src/NanoVNASaver/Hardware/NanoVNA_F_V3.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/NanoVNASaver/Hardware/NanoVNA_F_V3.py b/src/NanoVNASaver/Hardware/NanoVNA_F_V3.py index d1b86976..523cd9e6 100644 --- a/src/NanoVNASaver/Hardware/NanoVNA_F_V3.py +++ b/src/NanoVNASaver/Hardware/NanoVNA_F_V3.py @@ -31,9 +31,9 @@ class NanoVNA_F_V3(NanoVNA): name = "NanoVNA-F_V3" screenwidth = 800 screenheight = 480 - valid_datapoints = (101, 11, 51, 201, 301, 501, 801) + valid_datapoints = (101, 11, 51, 201, 301, 401, 501, 601, 701, 801, 1023, 2047, 4095) sweep_points_min = 11 - sweep_points_max = 801 + sweep_points_max = 65535 def __init__(self, iface: Interface): super().__init__(iface) From e5d0bbc0bfbb2a2b3976522a54dfe2e65c924a59 Mon Sep 17 00:00:00 2001 From: xros Date: Wed, 15 Jan 2025 03:26:04 +0800 Subject: [PATCH 09/15] re-limit NanoVNA-F V3 datapoints upto 801 and re-code the SN command feature in new Class NanoVNA_F_V3 rather than modifying the VNA.py --- src/NanoVNASaver/Hardware/NanoVNA_F_V3.py | 14 ++++++++++++-- src/NanoVNASaver/Hardware/VNA.py | 4 ++-- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/src/NanoVNASaver/Hardware/NanoVNA_F_V3.py b/src/NanoVNASaver/Hardware/NanoVNA_F_V3.py index 523cd9e6..6f69382d 100644 --- a/src/NanoVNASaver/Hardware/NanoVNA_F_V3.py +++ b/src/NanoVNASaver/Hardware/NanoVNA_F_V3.py @@ -31,9 +31,9 @@ class NanoVNA_F_V3(NanoVNA): name = "NanoVNA-F_V3" screenwidth = 800 screenheight = 480 - valid_datapoints = (101, 11, 51, 201, 301, 401, 501, 601, 701, 801, 1023, 2047, 4095) + valid_datapoints = (101, 11, 51, 201, 301, 401, 501, 601, 701, 801) sweep_points_min = 11 - sweep_points_max = 65535 + sweep_points_max = 801 def __init__(self, iface: Interface): super().__init__(iface) @@ -56,3 +56,13 @@ def getScreenshot(self) -> QPixmap: except serial.SerialException as exc: logger.exception("Exception while capturing screenshot: %s", exc) return QPixmap() + + def read_features(self): + super().read_features() + result = " ".join(self.exec_command("help")).split() + if "sn:" or "SN:" in result: + self.features.add("SN") + self.SN = self.getSerialNumber() + + def getSerialNumber(self) -> str: + return " ".join(list(self.exec_command("SN"))) if 'SN:' in " ".join(self.exec_command("help")).split() else " ".join(list(self.exec_command("sn"))) diff --git a/src/NanoVNASaver/Hardware/VNA.py b/src/NanoVNASaver/Hardware/VNA.py index 64938bc5..12e1b6ee 100644 --- a/src/NanoVNASaver/Hardware/VNA.py +++ b/src/NanoVNASaver/Hardware/VNA.py @@ -127,7 +127,7 @@ def read_features(self): if "capture" in result: self.features.add("Screenshots") - if "sn:" or "SN:" in result: + if "sn:" in result: self.features.add("SN") self.SN = self.getSerialNumber() @@ -222,4 +222,4 @@ def setTXPower(self, freq_range, power_desc): raise NotImplementedError() def getSerialNumber(self) -> str: - return " ".join(list(self.exec_command("SN"))) if 'SN:' in " ".join(self.exec_command("help")).split() else " ".join(list(self.exec_command("sn"))) + return " ".join(list(self.exec_command("sn"))) From cb91380e82b854cbd3a719ed8b90b9545db201d2 Mon Sep 17 00:00:00 2001 From: xros Date: Wed, 15 Jan 2025 03:32:16 +0800 Subject: [PATCH 10/15] restore the VNA.py --- src/NanoVNASaver/Hardware/VNA.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/NanoVNASaver/Hardware/VNA.py b/src/NanoVNASaver/Hardware/VNA.py index 12e1b6ee..727a1cf4 100644 --- a/src/NanoVNASaver/Hardware/VNA.py +++ b/src/NanoVNASaver/Hardware/VNA.py @@ -126,11 +126,9 @@ def read_features(self): 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"))) From 964339beb0c590f6160a49dfb2ea99e9e554dddd Mon Sep 17 00:00:00 2001 From: xros Date: Wed, 15 Jan 2025 03:33:06 +0800 Subject: [PATCH 11/15] restore Hardware.py --- src/NanoVNASaver/Hardware/Hardware.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/NanoVNASaver/Hardware/Hardware.py b/src/NanoVNASaver/Hardware/Hardware.py index e15a5d1a..096ff57f 100644 --- a/src/NanoVNASaver/Hardware/Hardware.py +++ b/src/NanoVNASaver/Hardware/Hardware.py @@ -182,7 +182,6 @@ def detect_version(serial_port: serial.Serial) -> str: sleep(0.05) data = serial_port.read(128).decode("ascii") - if data.startswith("ch> "): return "v1" # -H versions From 2d394c6933108c4cc084222ae2e04755daa4c733 Mon Sep 17 00:00:00 2001 From: xros Date: Mon, 20 Jan 2025 04:14:40 +0800 Subject: [PATCH 12/15] add support for NanoVNA_F_V2 for reaching max datapoints up to 201 and 301 on different firmwares --- src/NanoVNASaver/Hardware/NanoVNA_F_V2.py | 40 ++++++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-) diff --git a/src/NanoVNASaver/Hardware/NanoVNA_F_V2.py b/src/NanoVNASaver/Hardware/NanoVNA_F_V2.py index 7765bda7..0ff330f9 100644 --- a/src/NanoVNASaver/Hardware/NanoVNA_F_V2.py +++ b/src/NanoVNASaver/Hardware/NanoVNA_F_V2.py @@ -23,6 +23,7 @@ from NanoVNASaver.Hardware.NanoVNA import NanoVNA from NanoVNASaver.Hardware.Serial import Interface +from NanoVNASaver.Version import Version logger = logging.getLogger(__name__) @@ -31,10 +32,25 @@ class NanoVNA_F_V2(NanoVNA): name = "NanoVNA-F_V2" screenwidth = 800 screenheight = 480 - + valid_datapoints = (101, 11, 51, 201, 301) + sweep_points_min = 11 + sweep_points_max = 301 + def __init__(self, iface: Interface): super().__init__(iface) self.sweep_max_freq_Hz = 3e9 + self.version = self.read_firmware_version() + # max datapoints reach up to 301 since version 0.5.0 + if self.version >= Version("0.5.0"): + pass + # max datapoints reach up to 201 since version 0.2.0 + elif self.version >= Version("0.2.0"): + self.valid_datapoints = (101, 11, 51, 201) + self.sweep_points_max = 201 + # max datapoints reach up to 101 before version 0.2.0 + else: + self.valid_datapoints = (101, 11, 51) + self.sweep_points_max = 101 def getScreenshot(self) -> QPixmap: logger.debug("Capturing screenshot...") @@ -53,3 +69,25 @@ def getScreenshot(self) -> QPixmap: except serial.SerialException as exc: logger.exception("Exception while capturing screenshot: %s", exc) return QPixmap() + + def read_firmware_version(self) -> "Version": + """For example, command version in NanoVNA_F_V2 and NanoVNA_F_V3 returns as this + 0.5.8 + """ + result = list(self.exec_command("version")) + logger.debug("firmware version result:\n%s", result[0]) + return Version(result[0]) + + def read_features(self): + super().read_features() + result = " ".join(self.exec_command("help")).split() + if "sn:" or "SN:" in result: + self.features.add("SN") + self.SN = self.getSerialNumber() + + def getSerialNumber(self) -> str: + return ( + " ".join(list(self.exec_command("SN"))) + if "SN:" in " ".join(self.exec_command("help")).split() + else " ".join(list(self.exec_command("sn"))) + ) From c8dd683bd78a61067d1b321ccc41a0c1482cdb51 Mon Sep 17 00:00:00 2001 From: xros Date: Mon, 20 Jan 2025 11:15:51 +0800 Subject: [PATCH 13/15] add option Hardware in Device Settings for some models with hardware revision such as TinySA and TinySA Ultra --- src/NanoVNASaver/Hardware/TinySA.py | 1 - src/NanoVNASaver/Hardware/VNA.py | 1 + src/NanoVNASaver/Windows/DeviceSettings.py | 6 ++++++ 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/NanoVNASaver/Hardware/TinySA.py b/src/NanoVNASaver/Hardware/TinySA.py index 6c58014a..5ceb48e3 100644 --- a/src/NanoVNASaver/Hardware/TinySA.py +++ b/src/NanoVNASaver/Hardware/TinySA.py @@ -133,7 +133,6 @@ class TinySA_Ultra(TinySA): # noqa: N801 screenwidth = 480 screenheight = 320 valid_datapoints = (450, 51, 101, 145, 290) - hardware_revision = None def __init__(self, iface: Interface): super().__init__(iface) diff --git a/src/NanoVNASaver/Hardware/VNA.py b/src/NanoVNASaver/Hardware/VNA.py index 727a1cf4..892c54f2 100644 --- a/src/NanoVNASaver/Hardware/VNA.py +++ b/src/NanoVNASaver/Hardware/VNA.py @@ -56,6 +56,7 @@ class VNA: valid_datapoints = (101, 51, 11) wait = 0.05 SN = "NOT SUPPORTED" + hardware_revision = "NOT SUPPORTED" sweep_points_max = 101 sweep_points_min = 11 diff --git a/src/NanoVNASaver/Windows/DeviceSettings.py b/src/NanoVNASaver/Windows/DeviceSettings.py index 4f297b57..c47a4f79 100644 --- a/src/NanoVNASaver/Windows/DeviceSettings.py +++ b/src/NanoVNASaver/Windows/DeviceSettings.py @@ -44,6 +44,7 @@ def __init__(self, app: QtWidgets.QWidget) -> None: # noqa: PLR0915 self.label = { "status": QtWidgets.QLabel("Not connected."), "firmware": QtWidgets.QLabel("Not connected."), + "hardware": QtWidgets.QLabel("Not connected."), "calibration": QtWidgets.QLabel("Not connected."), "SN": QtWidgets.QLabel("Not connected."), } @@ -60,6 +61,7 @@ def __init__(self, app: QtWidgets.QWidget) -> None: # noqa: PLR0915 status_layout.addRow("Status:", self.label["status"]) status_layout.addRow("Firmware:", self.label["firmware"]) + status_layout.addRow("Hardware:", self.label["hardware"]) status_layout.addRow("Calibration:", self.label["calibration"]) status_layout.addRow("SN:", self.label["SN"]) @@ -134,6 +136,7 @@ def updateFields(self): if not self.app.vna.connected(): self.label["status"].setText("Not connected.") self.label["firmware"].setText("Not connected.") + self.label["hardware"].setText("Not connected.") self.label["calibration"].setText("Not connected.") self.label["SN"].setText("Not connected.") self.featureList.clear() @@ -144,6 +147,9 @@ def updateFields(self): self.label["firmware"].setText( f"{self.app.vna.name} v{self.app.vna.version}" ) + self.label["hardware"].setText( + f"{self.app.vna.hardware_revision}" + ) if self.app.worker.state == SweepState.RUNNING: self.label["calibration"].setText("(Sweep running)") else: From 4838f0e31457ffde40bcdb6e34a969f11552bfec Mon Sep 17 00:00:00 2001 From: xros Date: Mon, 20 Jan 2025 14:33:41 +0800 Subject: [PATCH 14/15] add Live View for viewing monitor screen of NanoVNA and TinySA in real time --- src/NanoVNASaver/Windows/DeviceSettings.py | 17 +++++++++++++++-- src/NanoVNASaver/Windows/Screenshot.py | 20 ++++++++++++++++++++ 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/src/NanoVNASaver/Windows/DeviceSettings.py b/src/NanoVNASaver/Windows/DeviceSettings.py index c47a4f79..5041a1fb 100644 --- a/src/NanoVNASaver/Windows/DeviceSettings.py +++ b/src/NanoVNASaver/Windows/DeviceSettings.py @@ -23,7 +23,7 @@ from NanoVNASaver.SweepWorker import SweepState from NanoVNASaver.Windows.Defaults import make_scrollable -from NanoVNASaver.Windows.Screenshot import ScreenshotWindow +from NanoVNASaver.Windows.Screenshot import ScreenshotWindow, LiveViewWindow logger = logging.getLogger(__name__) @@ -92,7 +92,13 @@ def __init__(self, app: QtWidgets.QWidget) -> None: # noqa: PLR0915 self.btnCaptureScreenshot = QtWidgets.QPushButton("Screenshot") self.btnCaptureScreenshot.clicked.connect(self.captureScreenshot) control_layout.addWidget(self.btnCaptureScreenshot) - + + self.liveViewWindow = LiveViewWindow(self) + self.btnLiveView = QtWidgets.QPushButton("Live view") + self.btnLiveView.clicked.connect(self.liveView) + self.liveViewWindow.setAttribute(QtCore.Qt.WidgetAttribute.WA_DeleteOnClose) + control_layout.addWidget(self.btnLiveView) + left_layout.addWidget(status_box) left_layout.addLayout(control_layout) @@ -141,6 +147,7 @@ def updateFields(self): self.label["SN"].setText("Not connected.") self.featureList.clear() self.btnCaptureScreenshot.setDisabled(True) + self.btnLiveView.setDisabled(True) return self.label["status"].setText(f"Connected to {self.app.vna.name}.") @@ -161,6 +168,7 @@ def updateFields(self): self.featureList.addItem(item) self.btnCaptureScreenshot.setDisabled("Screenshots" not in features) + self.btnLiveView.setDisabled("Screenshots" not in features) if "Customizable data points" in features: self.datapoints.clear() @@ -200,6 +208,11 @@ def captureScreenshot(self) -> None: # TODO: Consider having a list of widgets that want to be # disabled when a sweep is running? + + def liveView(self) -> None: + if self.app.worker.state != SweepState.RUNNING: + self.liveViewWindow.start() + def updateNrDatapoints(self, i) -> None: if i < 0 or self.app.worker.state == SweepState.RUNNING: return diff --git a/src/NanoVNASaver/Windows/Screenshot.py b/src/NanoVNASaver/Windows/Screenshot.py index 6f526a5c..f94e90d2 100644 --- a/src/NanoVNASaver/Windows/Screenshot.py +++ b/src/NanoVNASaver/Windows/Screenshot.py @@ -19,6 +19,9 @@ import logging from PyQt6 import QtCore, QtGui, QtWidgets +from PyQt6.QtCore import QTimer,QDateTime +from NanoVNASaver.SweepWorker import SweepState +from PyQt6.QtCore import Qt logger = logging.getLogger(__name__) @@ -116,3 +119,20 @@ def setScale(self, scale): self.pix.size().height() * scale, ) self.resize(width, height) + +class LiveViewWindow(ScreenshotWindow): + def __init__(self, qtwidgets: QtWidgets.QTableWidget): + super().__init__() + self.setWindowTitle("Live View") + self.qtwidgets = qtwidgets + self.timer = QTimer(self) + self.timer.timeout.connect(self.update_screenshot) + + def start(self): + self.timer.start(500) # Update every 500ms + + def update_screenshot(self): + if self.qtwidgets.app.worker.state != SweepState.RUNNING: # Check if worker is not running + pixmap = self.qtwidgets.app.vna.getScreenshot() + self.qtwidgets.liveViewWindow.setScreenshot(pixmap) + self.qtwidgets.liveViewWindow.show() \ No newline at end of file From 9bdbb337dc8d5694f630e04cf9fff3d85140e745 Mon Sep 17 00:00:00 2001 From: xros Date: Mon, 20 Jan 2025 15:16:10 +0800 Subject: [PATCH 15/15] set interval fresh every 2000ms for not getting more time for receiving screen data via USB from nanovna and tinysa. performance improved a little. --- src/NanoVNASaver/Windows/Screenshot.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/NanoVNASaver/Windows/Screenshot.py b/src/NanoVNASaver/Windows/Screenshot.py index f94e90d2..ee8c5dad 100644 --- a/src/NanoVNASaver/Windows/Screenshot.py +++ b/src/NanoVNASaver/Windows/Screenshot.py @@ -129,7 +129,7 @@ def __init__(self, qtwidgets: QtWidgets.QTableWidget): self.timer.timeout.connect(self.update_screenshot) def start(self): - self.timer.start(500) # Update every 500ms + self.timer.start(2000) # Update every 2000ms (this will not burn the little chip too much on nanovna & tinysa) def update_screenshot(self): if self.qtwidgets.app.worker.state != SweepState.RUNNING: # Check if worker is not running