From ece30f1cd5e23ac461023b9b8133e415aa0ecb54 Mon Sep 17 00:00:00 2001 From: Theodor Chikin Date: Wed, 18 Feb 2026 23:01:34 +0300 Subject: [PATCH] impoved tty parser binary mode: now it supports 32-bit values of intensity --- calib_envelope.npy | Bin 3164 -> 3164 bytes rfg_adc_plotter/io/sweep_reader.py | 71 +++++++++++++++-------------- rfg_adc_plotter/main.py | 5 +- 3 files changed, 41 insertions(+), 35 deletions(-) diff --git a/calib_envelope.npy b/calib_envelope.npy index abc000b6ba0143bb2284f1bb9f8df48da3b3e3db..31401e5c4a4201bbf8c98bb4c12e60148576cd18 100644 GIT binary patch literal 3164 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 diff --git a/rfg_adc_plotter/io/sweep_reader.py b/rfg_adc_plotter/io/sweep_reader.py index 674cd4b..705983c 100644 --- a/rfg_adc_plotter/io/sweep_reader.py +++ b/rfg_adc_plotter/io/sweep_reader.py @@ -40,9 +40,9 @@ class SweepReader(threading.Thread): self._n_valid_hist = deque() @staticmethod - def _u16_to_i16(v: int) -> int: - """Преобразование 16-bit слова в знаковое значение.""" - return v - 0x10000 if (v & 0x8000) else v + def _u32_to_i32(v: int) -> int: + """Преобразование 32-bit слова в знаковое значение.""" + return v - 0x1_0000_0000 if (v & 0x8000_0000) else v def _finalize_current(self, xs, ys, channels: Optional[set]): if not xs: @@ -211,10 +211,7 @@ class SweepReader(threading.Thread): ys: list[int] = [] cur_channel: Optional[int] = None cur_channels: set[int] = set() - waiting_channel = False - waiting_first_point = False - point_word: Optional[int] = None - value_word: Optional[int] = None + words = deque() buf = bytearray() while not self._stop.is_set(): @@ -232,47 +229,53 @@ class SweepReader(threading.Thread): i = 0 while i < usable: w = int(buf[i]) | (int(buf[i + 1]) << 8) + words.append(w) i += 2 - if waiting_channel: - cur_channel = int(w) - cur_channels.add(cur_channel) - waiting_channel = False - waiting_first_point = True - continue + # Бинарный протокол: + # старт свипа (актуальный): 0xFFFF, 0xFFFF, 0xFFFF, (ch<<8)|0x0A + # старт свипа (legacy): 0xFFFF, 0xFFFF, channel, 0x0A0A + # точка: step, value_hi, value_lo, 0x000A + while len(words) >= 4: + w0 = int(words[0]) + w1 = int(words[1]) + w2 = int(words[2]) + w3 = int(words[3]) - if w == 0xFFFF: + if w0 == 0xFFFF and w1 == 0xFFFF and w2 == 0xFFFF and (w3 & 0x00FF) == 0x000A: self._finalize_current(xs, ys, cur_channels) xs.clear() ys.clear() - cur_channel = None cur_channels.clear() - waiting_channel = True - waiting_first_point = False - point_word = None - value_word = None + cur_channel = (w3 >> 8) & 0x00FF + cur_channels.add(cur_channel) + for _ in range(4): + words.popleft() continue - if point_word is None: - if waiting_first_point and (w == 0x0A0A or w == 0x000A): - continue - point_word = int(w) - waiting_first_point = False + if w0 == 0xFFFF and w1 == 0xFFFF and w3 == 0x0A0A: + self._finalize_current(xs, ys, cur_channels) + xs.clear() + ys.clear() + cur_channels.clear() + cur_channel = w2 + cur_channels.add(cur_channel) + for _ in range(4): + words.popleft() continue - if value_word is None: - value_word = int(w) - continue - - is_point_end = (w == 0x000A) or ((w & 0x00FF) == 0x0A) or ((w >> 8) == 0x0A) - if is_point_end: + if w3 == 0x000A: if cur_channel is not None: cur_channels.add(cur_channel) - xs.append(point_word) - ys.append(self._u16_to_i16(value_word)) + xs.append(w0) + value_u32 = (w1 << 16) | w2 + ys.append(self._u32_to_i32(value_u32)) + for _ in range(4): + words.popleft() + continue - point_word = None - value_word = None + # Поток может начаться с середины пакета; сдвигаемся по слову до ресинхронизации. + words.popleft() del buf[:usable] if len(buf) > 1_000_000: diff --git a/rfg_adc_plotter/main.py b/rfg_adc_plotter/main.py index 85d4df7..ff1feb6 100755 --- a/rfg_adc_plotter/main.py +++ b/rfg_adc_plotter/main.py @@ -81,7 +81,10 @@ def build_parser() -> argparse.ArgumentParser: "--bin", dest="bin_mode", action="store_true", - help="Бинарный протокол: 16-bit поток, 0xFFFF+канал для старта свипа, точки point,value,'\\n'", + help=( + "Бинарный протокол: старт свипа 0xFFFF,0xFFFF,0xFFFF,(CH<<8)|0x0A; " + "точки step,uint32(hi16,lo16),0x000A" + ), ) return parser