Lab043: add hardware diagnostics and HackRF comparison tools

This commit is contained in:
LittleSam129
2026-08-21 17:33:57 +03:00
parent f0fa7e8a46
commit 42b0120eea
42 changed files with 8763 additions and 6 deletions

View File

@@ -650,6 +650,60 @@ def locate_calibration_tone_start(
raise RuntimeError("Начало двухтоновой калибровки не найдено по фиксированному порогу 10 дБ")
def locate_calibration_tone_start_spectral(
samples: np.ndarray,
sample_rate_hz: float,
block_samples: int = CALIBRATION_NFFT,
hop_samples: int = CALIBRATION_NFFT // 4,
required_consecutive_blocks: int = 3,
) -> int:
"""Найти начало по двум известным тонам с тем же порогом 10 дБ.
Резервный метод нужен, когда узкие тоны надёжны спектрально, но не дают
десятикратного роста полной широкополосной мощности. Дополнительно
применяется существующее ограничение геометрии тонов: ошибка такта не
должна превышать 1000 ppm.
"""
received = np.asarray(samples, dtype=np.complex128)
if received.ndim != 1 or len(received) < block_samples:
raise ValueError("Захват слишком короток для спектрального поиска калибровки")
if (
sample_rate_hz <= 0.0
or block_samples < 1024
or hop_samples <= 0
or required_consecutive_blocks <= 0
):
raise ValueError("Параметры спектрального поиска должны быть положительными")
window = np.hanning(block_samples)
frequencies = np.fft.fftshift(
np.fft.fftfreq(block_samples, d=1.0 / sample_rate_hz)
)
starts = np.arange(
0,
len(received) - block_samples + 1,
hop_samples,
dtype=np.int64,
)
active = np.zeros(len(starts), dtype=bool)
for index, start in enumerate(starts):
block = received[start : start + block_samples]
centered = block - np.mean(block)
spectrum = np.fft.fftshift(np.fft.fft(centered * window))
estimate = estimate_calibration_from_spectrum(
frequencies,
np.abs(spectrum) ** 2,
)
active[index] = bool(estimate.valid)
for index in range(len(active) - required_consecutive_blocks + 1):
if bool(np.all(active[index : index + required_consecutive_blocks])):
return int(starts[index])
raise RuntimeError(
"Начало двухтоновой калибровки не найдено спектрально: "
"два тона не прошли неизменный порог 10 дБ и проверку геометрии"
)
def split_calibration_and_bpsk(
samples: np.ndarray,
plan: PrbsTransmissionPlan,
@@ -659,7 +713,15 @@ def split_calibration_and_bpsk(
"""Выделить тоны и BPSK по одной временной шкале одного захвата."""
received = np.asarray(samples, dtype=np.complex128)
tone_start = locate_calibration_tone_start(received, actual_rx_sample_rate_hz)
try:
tone_start = locate_calibration_tone_start(received, actual_rx_sample_rate_hz)
tone_start_locator = "broadband_power_10db"
except RuntimeError:
tone_start = locate_calibration_tone_start_spectral(
received,
actual_rx_sample_rate_hz,
)
tone_start_locator = "two_tone_spectral_10db"
tone_duration_rx = round(
plan.calibration_sample_count / actual_tx_sample_rate_hz * actual_rx_sample_rate_hz
)
@@ -684,6 +746,7 @@ def split_calibration_and_bpsk(
received[bpsk_start:bpsk_end],
{
"tone_start_sample": int(tone_start),
"tone_start_locator": tone_start_locator,
"calibration_start_sample": int(calibration_start),
"calibration_end_sample": int(calibration_end),
"bpsk_nominal_start_sample": int(bpsk_nominal_start),