feat: QO-100 central beacon BPSK decoder (Milestone 1 — stable demod)

Декодер центрального маяка QO-100 (10489.750, AO-40 BPSK 400 бод): фронтенд
до мягких символов + констелляция, с устойчивым захватом несущей/символа.

Цепочка (BeaconDecoder.pas): NCO-снос смещения → boxcar-децим до 9600 →
RRC матч-фильтр → AGC-нормировка → Gardner timing → Costas BPSK с frequency
offload в пред-RRC NCO. squaring-FFT оставлена индикатором несущей (prom).

Ключевые решения по итогам эфирной отладки:
- invert=True для тракта QO-100 (LNB+трансвертер зеркалит спектр).
- Декодер развязан от beacon-lock (тот ретюнил железо, рвал IQ).
- AGC-нормировка петель: сигнал ~-60 dBFS замораживал Costas/Gardner.
- Frequency offload: накопл. снос Costas стекает в FResidInc (без потолка
  ±π/символ) → держит ошибку наведения (1пкс≈300Гц) + дрейф LNB.

Интеграция: тап IQ в WDSPEngine.PushIQItemToDSP; RadioController владеет
декодером, клик-наведение (ПКМ BEACON + ЛКМ/Shift+ЛКМ по спектру); узкий
фильтр-маркер в SpectrumView/GL; окно констелляции BeaconScopeForm; файловый
лог HOME/ewsdr_beacon.log для диагностики.

Milestone 2 (далее): FEC — Viterbi k=7 + RS(160,128) + интерливер + дескремблер.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-21 18:15:00 +03:00
co-authored by Claude Opus 4.8
parent 28adf9508a
commit c063d7a197
8 changed files with 1134 additions and 11 deletions
+12 -3
View File
@@ -668,8 +668,17 @@ procedure TSpectrumViewOpenGL.DrawBeaconMarkersGL(W, H: Integer);
DrawLine(x, 0, x, H, Col, 1, False);
end;
begin
Vline(FBeaconRefFreq, clLime); // где маяк ДОЛЖЕН быть
Vline(FBeaconTrkFreq, TColor($000AA5FF)); // отслеживаемый центроид (оранж)
if FBeaconMarkActive then
begin
Vline(FBeaconRefFreq, clLime); // где маяк ДОЛЖЕН быть
Vline(FBeaconTrkFreq, TColor($000AA5FF)); // отслеживаемый центроид (оранж)
end;
if FBeaconDecActive then
begin
Vline(FBeaconDecFreq - FBeaconDecHalf, TColor($0020D0FF)); // грань фильтра
Vline(FBeaconDecFreq + FBeaconDecHalf, TColor($0020D0FF));
Vline(FBeaconDecFreq, TColor($0020D0FF)); // центр наведения
end;
end;
procedure TSpectrumViewOpenGL.DrawADCOverlay(W, H: Integer);
@@ -797,7 +806,7 @@ begin
DrawAGCLines(W, H, DBmax, InvRange);
DrawSpectrumCurve(W, H, DBmax, InvRange);
DrawMarker(W, H);
if FBeaconMarkActive then DrawBeaconMarkersGL(W, H);
if FBeaconMarkActive or FBeaconDecActive then DrawBeaconMarkersGL(W, H);
DrawADCOverlay(W, H);
DrawCachedOverlays(W, H);