new mode --bin24

This commit is contained in:
awe
2026-08-17 14:06:49 +03:00
parent 2cf7543bbe
commit 428ba2a9e0
6 changed files with 392 additions and 14 deletions
+25 -14
View File
@@ -75,6 +75,7 @@ DEFAULT_MAIN_WINDOW_HEIGHT = 680
MIN_MAIN_WINDOW_WIDTH = 640
MIN_MAIN_WINDOW_HEIGHT = 420
TTY_CODE_SCALE_DENOM = 32767.0
TTY_CODE_SCALE_DENOM_24 = 8388607.0
TTY_RANGE_DEFAULT_V = 5.0
TTY_RANGE_MIN_V = 1e-6
TTY_RANGE_MAX_V = 1_000_000.0
@@ -640,13 +641,18 @@ def sanitize_tty_voltage_range(range_v: float, default: float = TTY_RANGE_DEFAUL
return float(np.clip(abs(value), TTY_RANGE_MIN_V, TTY_RANGE_MAX_V))
def convert_tty_i16_to_voltage(codes: np.ndarray, range_v: float) -> np.ndarray:
"""Convert signed tty int16 code array to clipped voltage values in ``[-range_v, +range_v]``."""
def convert_tty_i16_to_voltage(
codes: np.ndarray, range_v: float, *, denom: float = TTY_CODE_SCALE_DENOM
) -> np.ndarray:
"""Convert signed tty code array to clipped voltage values in ``[-range_v, +range_v]``.
``denom`` is the code full-scale magnitude (2^15-1 for int16, 2^23-1 for int24).
"""
code_arr = np.asarray(codes, dtype=np.float32).reshape(-1)
if code_arr.size <= 0:
return np.zeros((0,), dtype=np.float32)
range_abs_v = sanitize_tty_voltage_range(range_v)
scale_v = range_abs_v / float(TTY_CODE_SCALE_DENOM)
scale_v = range_abs_v / float(denom)
volt = code_arr * np.float32(scale_v)
return np.clip(volt, -range_abs_v, range_abs_v).astype(np.float32, copy=False)
@@ -656,9 +662,10 @@ def build_logdet_voltage_fft_input(
range_v: float,
*,
exp_input_limit: float = LOGDET_EXP_INPUT_LIMIT,
denom: float = TTY_CODE_SCALE_DENOM,
) -> Tuple[np.ndarray, np.ndarray]:
"""Convert 1a00 log-detector codes to raw volts and a real FFT input ``exp(V)``."""
volts = convert_tty_i16_to_voltage(codes, range_v)
volts = convert_tty_i16_to_voltage(codes, range_v, denom=denom)
if volts.size <= 0:
empty = np.zeros((0,), dtype=np.float32)
return empty, empty
@@ -889,15 +896,18 @@ def run_pyqtgraph(args) -> None:
peak_calibrate_mode = bool(getattr(args, "calibrate", False))
peak_search_enabled = bool(getattr(args, "peak_search", False))
bin_mode = bool(getattr(args, "bin_mode", False))
bin24_mode = bool(getattr(args, "bin24_mode", False))
tty_range_v = sanitize_tty_voltage_range(getattr(args, "tty_range_v", TTY_RANGE_DEFAULT_V))
tty_code_denom = TTY_CODE_SCALE_DENOM_24 if bin24_mode else TTY_CODE_SCALE_DENOM
complex_ascii_mode = bool(getattr(args, "parser_complex_ascii", False))
complex_sweep_mode = bool(
bin_mode
or bin24_mode
or complex_ascii_mode
or getattr(args, "parser_16_bit_x2", False)
or getattr(args, "parser_test", False)
)
bin_iq_power_mode = bool(bin_mode)
bin_iq_power_mode = bool(bin_mode or bin24_mode)
if not sys.platform.startswith("win"):
display_name = os.environ.get("DISPLAY") or os.environ.get("WAYLAND_DISPLAY")
if not display_name:
@@ -921,6 +931,7 @@ def run_pyqtgraph(args) -> None:
stop_event,
fancy=bool(args.fancy),
bin_mode=bin_mode,
bin24_mode=bin24_mode,
logscale=bool(args.logscale),
parser_16_bit_x2=bool(args.parser_16_bit_x2),
parser_test=bool(args.parser_test),
@@ -1904,8 +1915,8 @@ def run_pyqtgraph(args) -> None:
width = min(code_1_arr.size, code_2_arr.size)
if width <= 0:
return False
ch_1_v = convert_tty_i16_to_voltage(code_1_arr[:width], tty_range_v)
ch_2_v = convert_tty_i16_to_voltage(code_2_arr[:width], tty_range_v)
ch_1_v = convert_tty_i16_to_voltage(code_1_arr[:width], tty_range_v, denom=tty_code_denom)
ch_2_v = convert_tty_i16_to_voltage(code_2_arr[:width], tty_range_v, denom=tty_code_denom)
runtime.full_do1_tagged_raw_low = None
runtime.full_do1_tagged_raw_high = None
runtime.full_do1_tagged_aux_low = None
@@ -1936,10 +1947,10 @@ def run_pyqtgraph(args) -> None:
if width <= 0:
return False
low_ch_1_v = convert_tty_i16_to_voltage(low_code_1_arr[:width], tty_range_v)
low_ch_2_v = convert_tty_i16_to_voltage(low_code_2_arr[:width], tty_range_v)
high_ch_1_v = convert_tty_i16_to_voltage(high_code_1_arr[:width], tty_range_v)
high_ch_2_v = convert_tty_i16_to_voltage(high_code_2_arr[:width], tty_range_v)
low_ch_1_v = convert_tty_i16_to_voltage(low_code_1_arr[:width], tty_range_v, denom=tty_code_denom)
low_ch_2_v = convert_tty_i16_to_voltage(low_code_2_arr[:width], tty_range_v, denom=tty_code_denom)
high_ch_1_v = convert_tty_i16_to_voltage(high_code_1_arr[:width], tty_range_v, denom=tty_code_denom)
high_ch_2_v = convert_tty_i16_to_voltage(high_code_2_arr[:width], tty_range_v, denom=tty_code_denom)
low_ch_1_v_f64 = low_ch_1_v.astype(np.float64, copy=False)
low_ch_2_v_f64 = low_ch_2_v.astype(np.float64, copy=False)
@@ -1964,7 +1975,7 @@ def run_pyqtgraph(args) -> None:
code_arr = np.asarray(runtime.full_current_sweep_codes, dtype=np.float32).reshape(-1)
if code_arr.size <= 0:
return False
sweep_raw_v, fft_input = build_logdet_voltage_fft_input(code_arr, tty_range_v)
sweep_raw_v, fft_input = build_logdet_voltage_fft_input(code_arr, tty_range_v, denom=tty_code_denom)
runtime.full_do1_tagged_raw_low = None
runtime.full_do1_tagged_raw_high = None
runtime.full_do1_tagged_aux_low = None
@@ -3089,13 +3100,13 @@ def run_pyqtgraph(args) -> None:
calibrate_freqs({"F": base_freqs, "I": sec_ch1})["I"],
dtype=np.float32,
)
runtime.full_secondary_ch1 = convert_tty_i16_to_voltage(sec_ch1_calibrated, tty_range_v)
runtime.full_secondary_ch1 = convert_tty_i16_to_voltage(sec_ch1_calibrated, tty_range_v, denom=tty_code_denom)
if sec_ch2 is not None:
sec_ch2_calibrated = np.asarray(
calibrate_freqs({"F": base_freqs, "I": sec_ch2})["I"],
dtype=np.float32,
)
runtime.full_secondary_ch2 = convert_tty_i16_to_voltage(sec_ch2_calibrated, tty_range_v)
runtime.full_secondary_ch2 = convert_tty_i16_to_voltage(sec_ch2_calibrated, tty_range_v, denom=tty_code_denom)
if runtime.full_secondary_ch1 is not None and runtime.full_secondary_ch2 is not None:
w = min(runtime.full_secondary_ch1.size, runtime.full_secondary_ch2.size)
v1 = runtime.full_secondary_ch1[:w]