diff --git a/calib_envelope.npy b/calib_envelope.npy index abc000b..31401e5 100644 Binary files a/calib_envelope.npy and b/calib_envelope.npy differ 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