mirror of
https://git.vladimir.cc/vladimir/ewsdr.git
synced 2026-08-25 17:27:32 +00:00
feature(calibration): офсет спектра/водопада на диапазон и на трансвертер
Вторая калибровочная таблица рядом с S-метром (паритет с Display Cal Offset в Thetis): у display-тракта своё окно/детектор, и его уровень расходится с показаниями стрелки на пару дБ, поэтому таблицы раздельные. - Settings: DispBandDB[12] / DispXvtrDB[8] (JSON cal_disp_band_i / cal_disp_xvtr_i, дефолт 0 — картинка не меняется до первой правки). - WDSPEngine: колбэк OnDispCal(PanId) — движок раз в кадр спрашивает офсет в UpdateSpectrum и прибавляет к пикселям (главный спектр/водопад в копирующем цикле, паны in-place при ненулевом офсете). На TX-дисплее не применяется. Так обошлись без хуков на каждое присваивание FCenterFreq. - RadioController: общий CalLookup(Hz, BandTbl, XvtrTbl) — на нём SMeterCalFor и DispCalFor(PanId): главный дисплей по FCenterFreq, пан по FPanFreqHz[p], т.е. кросс-банд паны получают свой офсет. Колбэк вешается в CreateEngines, поэтому работает и в GUI, и в ewsdrd; web-зеркало получает готовые кадры. - SettingsForm: группа «Spectrum / waterfall» с той же разбивкой (диапазоны + включённые трансвертеры активного железа) и кнопка «= S-meter» — копия таблицы стрелки как старт калибровки; общая раскладка сеток вынесена в LayoutCalOffsets. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
+28
-2
@@ -191,6 +191,11 @@ type
|
||||
// SliceId — логический id (из RadioController), не WDSP-канал.
|
||||
TOnSliceAudio = procedure(SliceId: Integer; const Left, Right: array of Single;
|
||||
Count: Integer) of object;
|
||||
// Калибровочный офсет спектра/водопада (дБ) для дисплея: PanId 0 = главный,
|
||||
// 1..MAX_PANS-1 = доп. панадаптер. Спрашивается раз в кадр из display-потока:
|
||||
// величина зависит от диапазона/трансвертера, о которых знает только
|
||||
// TRadioController (аналог SMeterCalFor для стрелки).
|
||||
TOnDispCalQuery = function(PanId: Integer): Double of object;
|
||||
// Пиксели спектра/водопада доп. пана — из display-потока (как FOnSpectrum/
|
||||
// FOnWaterfall главного). Внутри колбэка НЕ звать slice/pan API движка.
|
||||
TOnPanPixels = procedure(PanId: Integer; const Pixels: array of Single;
|
||||
@@ -331,6 +336,7 @@ type
|
||||
FOnDemodAudio:TOnAudioReady; // pre-volume/mute tap for digital decoders
|
||||
FOnSpectrum: TOnSpectrumReady;
|
||||
FOnWaterfall: TOnWaterfallReady;
|
||||
FOnDispCal: TOnDispCalQuery;
|
||||
FOnTXIQ: TOnTXIQReady;
|
||||
|
||||
// --- Мультислайсы ---
|
||||
@@ -756,6 +762,8 @@ type
|
||||
property OnSliceAudio: TOnSliceAudio read FOnSliceAudio write FOnSliceAudio;
|
||||
property OnSliceDemodAudio: TOnSliceAudio
|
||||
read FOnSliceDemodAudio write FOnSliceDemodAudio;
|
||||
// Офсет дисплея (дБ) на кадр — см. TOnDispCalQuery. nil = без коррекции.
|
||||
property OnDispCal: TOnDispCalQuery read FOnDispCal write FOnDispCal;
|
||||
property OnSpectrum: TOnSpectrumReady read FOnSpectrum write FOnSpectrum;
|
||||
property OnWaterfall: TOnWaterfallReady read FOnWaterfall write FOnWaterfall;
|
||||
// Пиксели доп. панов (display-поток). UI вешает при появлении панов (3.3).
|
||||
@@ -3810,18 +3818,24 @@ var
|
||||
Flag: Integer;
|
||||
i, N, p: Integer;
|
||||
DispID: Integer;
|
||||
Cal: Single;
|
||||
GotSpec, GotWf: Boolean;
|
||||
begin
|
||||
if not FInitialized or not FAnalyzerOpen then Exit;
|
||||
N := EnsureRange(FDisplayPixelCount, 1, SPECTRUM_PIXELS);
|
||||
DispID := FActiveDisplayID; // RX_DISP_ID или TX_DISP_ID, зависит от FTXActive
|
||||
|
||||
// Калибровка дисплея (дБ) — сдвиг всей трассы, спрашиваем раз в кадр.
|
||||
// На TX-дисплее коррекция входного тракта не при чём.
|
||||
if Assigned(FOnDispCal) and (DispID = RX_DISP_ID) then Cal := FOnDispCal(0)
|
||||
else Cal := 0;
|
||||
|
||||
Flag := 0;
|
||||
GetPixels(DispID, 0, @PixBuf[0], @Flag);
|
||||
if Flag <> 0 then
|
||||
begin
|
||||
for i := 0 to N - 1 do
|
||||
FSpectrumPixels[i] := PixBuf[i];
|
||||
FSpectrumPixels[i] := PixBuf[i] + Cal;
|
||||
if Assigned(FOnSpectrum) then
|
||||
FOnSpectrum(FSpectrumPixels, N);
|
||||
end;
|
||||
@@ -3831,7 +3845,7 @@ begin
|
||||
if Flag <> 0 then
|
||||
begin
|
||||
for i := 0 to N - 1 do
|
||||
FWaterfallPixels[i] := PixBuf[i];
|
||||
FWaterfallPixels[i] := PixBuf[i] + Cal;
|
||||
if Assigned(FOnWaterfall) then
|
||||
FOnWaterfall(FWaterfallPixels, N);
|
||||
end;
|
||||
@@ -3858,6 +3872,18 @@ begin
|
||||
finally
|
||||
FSliceLock.Leave;
|
||||
end;
|
||||
// Пан может стоять на своём диапазоне — офсет спрашиваем по его PanId.
|
||||
if GotSpec or GotWf then
|
||||
begin
|
||||
if Assigned(FOnDispCal) then Cal := FOnDispCal(p) else Cal := 0;
|
||||
if Cal <> 0 then
|
||||
begin
|
||||
if GotSpec then
|
||||
for i := 0 to N - 1 do PixBuf[i] := PixBuf[i] + Cal;
|
||||
if GotWf then
|
||||
for i := 0 to N - 1 do WfBuf[i] := WfBuf[i] + Cal;
|
||||
end;
|
||||
end;
|
||||
if GotSpec and Assigned(FOnPanSpectrum) then
|
||||
FOnPanSpectrum(p, PixBuf, N);
|
||||
if GotWf and Assigned(FOnPanWaterfall) then
|
||||
|
||||
Reference in New Issue
Block a user