2020-06-13 08:22:30 +00:00
|
|
|
# NanoVNASaver
|
2020-06-25 17:52:30 +00:00
|
|
|
#
|
2020-06-13 08:22:30 +00:00
|
|
|
# A python program to view and export Touchstone data from a NanoVNA
|
2020-06-25 17:52:30 +00:00
|
|
|
# Copyright (C) 2019, 2020 Rune B. Broberg
|
2021-06-30 05:21:14 +00:00
|
|
|
# Copyright (C) 2020,2021 NanoVNA-Saver Authors
|
2019-08-29 13:10:35 +00:00
|
|
|
#
|
|
|
|
# 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/>.
|
2019-11-20 15:56:09 +00:00
|
|
|
import logging
|
2023-03-22 14:56:59 +00:00
|
|
|
from dataclasses import dataclass, replace
|
2020-07-27 14:28:50 +00:00
|
|
|
from enum import Enum
|
2020-07-24 19:14:48 +00:00
|
|
|
from math import log
|
2020-07-27 14:28:50 +00:00
|
|
|
from threading import Lock
|
2023-03-22 14:56:59 +00:00
|
|
|
from typing import Iterator, NamedTuple
|
2019-10-07 19:24:18 +00:00
|
|
|
|
2019-09-16 13:47:37 +00:00
|
|
|
logger = logging.getLogger(__name__)
|
2019-08-28 22:56:54 +00:00
|
|
|
|
|
|
|
|
2020-07-27 14:28:50 +00:00
|
|
|
class SweepMode(Enum):
|
|
|
|
SINGLE = 0
|
|
|
|
CONTINOUS = 1
|
|
|
|
AVERAGE = 2
|
|
|
|
|
|
|
|
|
2023-03-22 14:56:59 +00:00
|
|
|
class Properties(NamedTuple):
|
|
|
|
name: str = ""
|
|
|
|
mode: "SweepMode" = SweepMode.SINGLE
|
|
|
|
averages: tuple[int, int] = (3, 0)
|
|
|
|
logarithmic: bool = False
|
2020-07-27 14:28:50 +00:00
|
|
|
|
|
|
|
|
2023-03-22 14:56:59 +00:00
|
|
|
@dataclass
|
2022-05-27 07:03:37 +00:00
|
|
|
class Sweep:
|
2023-03-22 14:56:59 +00:00
|
|
|
start: int = 3600000
|
|
|
|
end: int = 30000000
|
|
|
|
points: int = 101
|
|
|
|
segments: int = 1
|
|
|
|
properties: "Properties" = Properties()
|
|
|
|
|
|
|
|
def __post_init__(self):
|
2020-07-27 14:28:50 +00:00
|
|
|
self.lock = Lock()
|
2020-07-09 10:46:26 +00:00
|
|
|
self.check()
|
2020-07-27 14:28:50 +00:00
|
|
|
logger.debug("%s", self)
|
2020-07-09 10:46:26 +00:00
|
|
|
|
2023-03-08 08:40:39 +00:00
|
|
|
def copy(self) -> "Sweep":
|
2023-03-22 14:56:59 +00:00
|
|
|
return replace(self)
|
2020-07-28 08:30:59 +00:00
|
|
|
|
2020-07-27 14:28:50 +00:00
|
|
|
@property
|
|
|
|
def span(self) -> int:
|
|
|
|
return self.end - self.start
|
|
|
|
|
|
|
|
@property
|
|
|
|
def stepsize(self) -> int:
|
2022-05-27 07:03:37 +00:00
|
|
|
return round(self.span / (self.points * self.segments - 1))
|
2020-07-27 14:28:50 +00:00
|
|
|
|
2020-07-09 10:46:26 +00:00
|
|
|
def check(self):
|
2022-03-17 16:54:52 +00:00
|
|
|
if (
|
2023-03-08 08:40:39 +00:00
|
|
|
self.segments <= 0
|
|
|
|
or self.points <= 0
|
2023-03-14 18:22:46 +00:00
|
|
|
or self.start < 0
|
2023-03-08 08:40:39 +00:00
|
|
|
or self.end <= 0
|
|
|
|
or self.stepsize < 1
|
2022-03-17 16:54:52 +00:00
|
|
|
):
|
2020-07-09 10:46:26 +00:00
|
|
|
raise ValueError(f"Illegal sweep settings: {self}")
|
2020-07-27 17:57:39 +00:00
|
|
|
|
2020-07-25 19:34:49 +00:00
|
|
|
def _exp_factor(self, index: int) -> float:
|
2020-07-24 19:14:48 +00:00
|
|
|
return 1 - log(self.segments + 1 - index) / log(self.segments + 1)
|
2020-07-09 10:46:26 +00:00
|
|
|
|
2023-03-22 14:56:59 +00:00
|
|
|
def get_index_range(self, index: int) -> tuple[int, int]:
|
2020-07-27 14:28:50 +00:00
|
|
|
if not self.properties.logarithmic:
|
|
|
|
start = self.start + index * self.points * self.stepsize
|
|
|
|
end = start + (self.points - 1) * self.stepsize
|
2020-07-24 19:14:48 +00:00
|
|
|
else:
|
2020-07-25 19:34:49 +00:00
|
|
|
start = round(self.start + self.span * self._exp_factor(index))
|
|
|
|
end = round(self.start + self.span * self._exp_factor(index + 1))
|
2020-07-24 19:14:48 +00:00
|
|
|
logger.debug("get_index_range(%s) -> (%s, %s)", index, start, end)
|
2022-05-27 07:03:37 +00:00
|
|
|
return start, end
|
2020-07-09 10:46:26 +00:00
|
|
|
|
2020-07-10 09:10:40 +00:00
|
|
|
def get_frequencies(self) -> Iterator[int]:
|
2020-07-24 19:14:48 +00:00
|
|
|
for i in range(self.segments):
|
|
|
|
start, stop = self.get_index_range(i)
|
|
|
|
step = (stop - start) / self.points
|
|
|
|
freq = start
|
|
|
|
for _ in range(self.points):
|
|
|
|
yield round(freq)
|
|
|
|
freq += step
|