mirror of
https://git.vladimir.cc/vladimir/ewsdr.git
synced 2026-08-25 19:45:09 +00:00
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:
+49
-1
@@ -39,7 +39,7 @@ uses
|
||||
WinFirewall,
|
||||
BoardUtils, WisdomBuilder, UISync,
|
||||
FlatEdit, FMRepeater,
|
||||
ChannelStore, ChannelsForm,
|
||||
ChannelStore, ChannelsForm, BeaconScopeForm,
|
||||
PowerInhibit,
|
||||
DeviceStore,
|
||||
RadioBackend, PlutoBackend,
|
||||
@@ -135,6 +135,7 @@ type
|
||||
FSpecDragX0: Integer; // X при нажатии
|
||||
FSpecDragFreq: Double; // FCenterFreq при нажатии
|
||||
FBeaconArming: Boolean; // ждём клик по маяку (после включения BEACON)
|
||||
FBeaconDecArming: Boolean; // ждём клик: навести узкий фильтр декодера на маяк
|
||||
FSpectrumDirty: Boolean; // таймер должен перерисовать спектр/водопад
|
||||
// TX DUC-очередь (FDUCPending*) переехала в TRadioController (OnTXIQ).
|
||||
FSMeterPeak: Double; // верхняя граница светлой зоны
|
||||
@@ -287,6 +288,7 @@ type
|
||||
BtnChannels: TFlatButton;
|
||||
FChannelsDropDown: TFlatDropDown;
|
||||
FChannelsForm: TObject; // TChannelsForm (cast при использовании)
|
||||
FBeaconScopeForm: TBeaconScopeForm; // окно констелляции маяка (ПКМ по BEACON)
|
||||
|
||||
// ---- Right panel ----
|
||||
PanelRight: TPanel;
|
||||
@@ -384,6 +386,8 @@ type
|
||||
procedure BtnFilterClick(Sender: TObject);
|
||||
procedure BtnCTunClick(Sender: TObject);
|
||||
procedure BtnBeaconClick(Sender: TObject);
|
||||
procedure BtnBeaconMouseDown(Sender: TObject; Button: TMouseButton;
|
||||
Shift: TShiftState; X, Y: Integer);
|
||||
procedure UpdateBeaconButton;
|
||||
procedure BtnDUPClick(Sender: TObject);
|
||||
procedure ApplyDUP(Active: Boolean);
|
||||
@@ -795,6 +799,7 @@ begin
|
||||
FController.FTXSpecGridStep := 10.0;
|
||||
FSettingsForm := nil;
|
||||
FChannelsForm := nil;
|
||||
FBeaconScopeForm := nil;
|
||||
FillChar(FController.FDevMAC, SizeOf(FController.FDevMAC), 0);
|
||||
|
||||
// Инициализируем кэш диапазонов умолчаниями
|
||||
@@ -1752,6 +1757,7 @@ begin
|
||||
LeftPanelButtonWidth(LEFT_W, 3, 2),
|
||||
BTN_H, BtnBeaconClick);
|
||||
BtnBeacon.Visible := False;
|
||||
BtnBeacon.OnMouseDown := BtnBeaconMouseDown; // ПКМ → декодер + окно констелляции
|
||||
StyleButton(BtnBeacon, False);
|
||||
|
||||
MakeLbl(PanelRXBlock, 'VOL', 4, 50);
|
||||
@@ -3272,6 +3278,9 @@ function TMainForm.BeaconStatusText: string;
|
||||
// Компактный статус QO-100 beacon lock для поля 7 статус-бара (Pluto). Courier 8pt,
|
||||
// поле ~200px → держим ≤ ~24 символов.
|
||||
begin
|
||||
if FBeaconDecArming then Exit('DEC: click beacon');
|
||||
if FController.BeaconDecodeEnabled and (FController.BeaconDecodeFreqHz > 0) then
|
||||
Exit('DEC: shift-click=re-aim');
|
||||
if not FController.BeaconLockEnabled then Exit('BCN: off');
|
||||
if FBeaconArming then Exit('BCN: click beacon');
|
||||
case FController.BeaconState of
|
||||
@@ -3988,6 +3997,28 @@ begin
|
||||
UpdateBeaconButton;
|
||||
end;
|
||||
|
||||
procedure TMainForm.BtnBeaconMouseDown(Sender: TObject; Button: TMouseButton;
|
||||
Shift: TShiftState; X, Y: Integer);
|
||||
// ПКМ по BEACON: включает фронтенд-декодер маяка (BPSK 400 бод) и открывает окно
|
||||
// констелляции для диагностики демодуляции (Milestone 1 — до подключения FEC).
|
||||
begin
|
||||
if Button <> mbRight then Exit;
|
||||
FController.SetBeaconDecode(not FController.BeaconDecodeEnabled);
|
||||
if FController.BeaconDecodeEnabled then
|
||||
begin
|
||||
// «Вооружаем» наведение: следующий ЛКМ по спектру поставит узкий фильтр
|
||||
// декодера на маяк. Потом перенавести — Shift+ЛКМ по спектру.
|
||||
FBeaconDecArming := True;
|
||||
if FBeaconScopeForm = nil then
|
||||
FBeaconScopeForm := TBeaconScopeForm.CreateWith(Self, FController);
|
||||
FBeaconScopeForm.ApplyTheme(DarkTheme);
|
||||
FBeaconScopeForm.Show;
|
||||
end
|
||||
else
|
||||
FBeaconDecArming := False;
|
||||
UpdateBeaconButton;
|
||||
end;
|
||||
|
||||
procedure TMainForm.UpdateBeaconButton;
|
||||
// Beacon-маркеры + кнопка BEACON. Кнопка видима только на Pluto в трансвертере
|
||||
// (см. rfXvtr) — это ПРОСТО кнопка: подпись 'BEACON', подсветка = лок включён.
|
||||
@@ -3996,9 +4027,15 @@ procedure TMainForm.UpdateBeaconButton;
|
||||
begin
|
||||
// Маркеры на спектре: опорная частота (зелёная) + отслеживаемый центроид (оранж).
|
||||
if FSpecView <> nil then
|
||||
begin
|
||||
FSpecView.SetBeaconMarkers(FController.BeaconLockEnabled,
|
||||
FController.BeaconRefHz,
|
||||
FController.BeaconTrackedFreqHz);
|
||||
// Узкий фильтр-маркер декодера (±450 Гц ≈ полоса BPSK-маяка).
|
||||
FSpecView.SetBeaconDecMarker(
|
||||
FController.BeaconDecodeEnabled and (FController.BeaconDecodeFreqHz > 0),
|
||||
FController.BeaconDecodeFreqHz, 450.0);
|
||||
end;
|
||||
UpdateStatusField7; // моментальный апдейт статус-бара (не ждём MeterTimer)
|
||||
if BtnBeacon = nil then Exit;
|
||||
BtnBeacon.Caption := 'BEACON';
|
||||
@@ -4186,6 +4223,17 @@ begin
|
||||
|
||||
if Button = mbLeft then
|
||||
begin
|
||||
// Наведение узкого фильтра ДЕКОДЕРА на маяк: после ПКМ BEACON (вооружено)
|
||||
// либо Shift+ЛКМ в любой момент при включённом декодере. Не трогает VFO.
|
||||
if FController.BeaconDecodeEnabled and (PbSpectrum.Width > 0) and
|
||||
(FBeaconDecArming or (ssShift in Shift)) then
|
||||
begin
|
||||
FController.SetBeaconDecodeAtHz(
|
||||
PixelToFreq(X, PbSpectrum.Width, FController.FCenterFreq, FController.FSpanHz));
|
||||
FBeaconDecArming := False;
|
||||
UpdateBeaconButton;
|
||||
Exit;
|
||||
end;
|
||||
// Наведение beacon-lock: ЛКМ указывает на маяк (вместо перестройки VFO).
|
||||
if FBeaconArming and (PbSpectrum.Width > 0) then
|
||||
begin
|
||||
|
||||
Reference in New Issue
Block a user