Hardware.py 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. # NanoVNASaver
  2. #
  3. # A python program to view and export Touchstone data from a NanoVNA
  4. # Copyright (C) 2019, 2020 Rune B. Broberg
  5. # Copyright (C) 2020 NanoVNA-Saver Authors
  6. #
  7. # This program is free software: you can redistribute it and/or modify
  8. # it under the terms of the GNU General Public License as published by
  9. # the Free Software Foundation, either version 3 of the License, or
  10. # (at your option) any later version.
  11. #
  12. # This program is distributed in the hope that it will be useful,
  13. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. # GNU General Public License for more details.
  16. #
  17. # You should have received a copy of the GNU General Public License
  18. # along with this program. If not, see <https://www.gnu.org/licenses/>.
  19. import logging
  20. import platform
  21. from collections import namedtuple
  22. from time import sleep
  23. from typing import List
  24. import serial
  25. from serial.tools import list_ports
  26. from .Serial import drain_serial, Interface
  27. logger = logging.getLogger(__name__)
  28. USBDevice = namedtuple("Device", "vid pid name")
  29. USBDEVICETYPES = (
  30. USBDevice(0x0483, 0x5740, "NanoVNA"),
  31. USBDevice(0x16c0, 0x0483, "AVNA"),
  32. USBDevice(0x04b4, 0x0008, "S-A-A-2"),
  33. )
  34. RETRIES = 3
  35. TIMEOUT = 0.2
  36. WAIT = 0.05
  37. # The USB Driver for NanoVNA V2 seems to deliver an
  38. # incompatible hardware info like:
  39. # 'PORTS\\VID_04B4&PID_0008\\DEMO'
  40. # This function will fix it.
  41. def _fix_v2_hwinfo(dev):
  42. if dev.hwid == r'PORTS\VID_04B4&PID_0008\DEMO':
  43. dev.vid, dev.pid = 0x04b4, 0x0008
  44. return dev
  45. # Get list of interfaces with VNAs connected
  46. def get_interfaces() -> List[Interface]:
  47. interfaces = []
  48. # serial like usb interfaces
  49. for d in list_ports.comports():
  50. if platform.system() == 'Windows' and d.vid is None:
  51. d = _fix_v2_hwinfo(d)
  52. for t in USBDEVICETYPES:
  53. if d.vid != t.vid or d.pid != t.pid:
  54. continue
  55. logger.debug("Found %s USB:(%04x:%04x) on port %s",
  56. t.name, d.vid, d.pid, d.device)
  57. iface = Interface('serial', t.name)
  58. iface.port = d.device
  59. interfaces.append(iface)
  60. return interfaces
  61. # def get_VNA(iface: Interface) -> 'VNA':
  62. # # serial_port.timeout = TIMEOUT
  63. # logger.info("Finding correct VNA type...")
  64. # with iface.lock:
  65. # vna_version = detect_version(iface)
  66. # if vna_version == 'v2':
  67. # logger.info("Type: NanoVNA-V2")
  68. # return NanoVNA_V2(iface)
  69. # logger.info("Finding firmware variant...")
  70. # info = get_info(iface)
  71. # if info.find("AVNA + Teensy") >= 0:
  72. # logger.info("Type: AVNA")
  73. # return AVNA(iface)
  74. # if info.find("NanoVNA-H 4") >= 0:
  75. # logger.info("Type: NanoVNA-H4")
  76. # vna = NanoVNA_H4(iface)
  77. # return vna
  78. # if info.find("NanoVNA-H") >= 0:
  79. # logger.info("Type: NanoVNA-H")
  80. # vna = NanoVNA_H(iface)
  81. # return vna
  82. # if info.find("NanoVNA-F_V2") >= 0:
  83. # logger.info("Type: NanoVNA-F_V2")
  84. # return NanoVNA_F_V2(iface)
  85. # if info.find("NanoVNA-F") >= 0:
  86. # logger.info("Type: NanoVNA-F")
  87. # return NanoVNA_F(iface)
  88. # if info.find("NanoVNA") >= 0:
  89. # logger.info("Type: Generic NanoVNA")
  90. # return NanoVNA(iface)
  91. # logger.warning("Did not recognize NanoVNA type from firmware.")
  92. # return NanoVNA(iface)
  93. # def detect_version(serial_port: serial.Serial) -> str:
  94. # data = ""
  95. # for i in range(RETRIES):
  96. # drain_serial(serial_port)
  97. # serial_port.write("\r".encode("ascii"))
  98. # sleep(0.05)
  99. # data = serial_port.read(128).decode("ascii")
  100. # if data.startswith("ch> "):
  101. # return "v1"
  102. # # -H versions
  103. # if data.startswith("\r\nch> "):
  104. # return "vh"
  105. # if data.startswith("2"):
  106. # return "v2"
  107. # logger.debug("Retry detection: %s", i + 1)
  108. # logger.error('No VNA detected. Hardware responded to CR with: %s', data)
  109. # return ""
  110. # def get_info(serial_port: serial.Serial) -> str:
  111. # for _ in range(RETRIES):
  112. # drain_serial(serial_port)
  113. # serial_port.write("info\r".encode("ascii"))
  114. # lines = []
  115. # retries = 0
  116. # while True:
  117. # line = serial_port.readline()
  118. # line = line.decode("ascii").strip()
  119. # if not line:
  120. # retries += 1
  121. # if retries > RETRIES:
  122. # return ""
  123. # sleep(WAIT)
  124. # continue
  125. # if line == "info": # suppress echo
  126. # continue
  127. # if line.startswith("ch>"):
  128. # logger.debug("Needed retries: %s", retries)
  129. # break
  130. # lines.append(line)
  131. # return "\n".join(lines)