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:
2026-07-21 11:16:34 +03:00
co-authored by Claude Opus 4.8
parent 797bfc2e7c
commit 366d4c9821
4 changed files with 244 additions and 61 deletions
+16
View File
@@ -345,6 +345,11 @@ type
// Pluto); таблицы не пересекаются, т.к. секция JSON ключуется по MAC.
SMeterBandDB: array[0..CFG_BAND_COUNT-1] of Double;
SMeterXvtrDB: array[0..CFG_XVTR_COUNT-1] of Double;
// Офсет спектра/водопада, дБ — та же разбивка. Отдельно от S-метра (как
// Display Cal Offset в Thetis): у display-тракта своё окно/детектор, и его
// уровень отличается от показаний стрелки на пару дБ.
DispBandDB: array[0..CFG_BAND_COUNT-1] of Double;
DispXvtrDB: array[0..CFG_XVTR_COUNT-1] of Double;
end;
TGlobalSettings = record
@@ -905,6 +910,13 @@ begin
for i := 0 to CFG_XVTR_COUNT-1 do
G.Cal.SMeterXvtrDB[i] :=
EnsureRange(JD(GObj,'cal_smeter_xvtr_'+IntToStr(i), SMLegacy), -30.0, 30.0);
// Спектр/водопад: своя таблица офсетов (дефолт 0 — как было).
for i := 0 to CFG_BAND_COUNT-1 do
G.Cal.DispBandDB[i] :=
EnsureRange(JD(GObj,'cal_disp_band_'+IntToStr(i), 0.0), -30.0, 30.0);
for i := 0 to CFG_XVTR_COUNT-1 do
G.Cal.DispXvtrDB[i] :=
EnsureRange(JD(GObj,'cal_disp_xvtr_'+IntToStr(i), 0.0), -30.0, 30.0);
for i := 0 to CFG_BAND_COUNT-1 do
begin
@@ -1025,6 +1037,10 @@ begin
JW(O,'cal_smeter_band_'+IntToStr(i),G.Cal.SMeterBandDB[i]);
for i := 0 to CFG_XVTR_COUNT-1 do
JW(O,'cal_smeter_xvtr_'+IntToStr(i),G.Cal.SMeterXvtrDB[i]);
for i := 0 to CFG_BAND_COUNT-1 do
JW(O,'cal_disp_band_'+IntToStr(i),G.Cal.DispBandDB[i]);
for i := 0 to CFG_XVTR_COUNT-1 do
JW(O,'cal_disp_xvtr_'+IntToStr(i),G.Cal.DispXvtrDB[i]);
end;
procedure TSettingsManager.SaveBand(const MAC: array of Byte; BandIdx: Integer;