mirror of
https://git.vladimir.cc/vladimir/ewsdr.git
synced 2026-08-25 18:43:51 +00:00
feature(calibration): офсет S-метра на диапазон и на трансвертер, раздельно по железу
Вместо одного офсета на всё устройство — таблицы «на диапазон» и «на слот трансвертера»; состав таблиц задаёт активное железо. - Settings: SMeterOffsetDB -> SMeterBandDB[12] / SMeterXvtrDB[8] (JSON cal_smeter_band_i / cal_smeter_xvtr_i). Легаси-ключ cal_smeter_db становится дефолтом всех слотов — показания после обновления не меняются. Разделение Pluto/openHPSDR даёт сама секция JSON: она ключуется по MAC устройства (у Pluto — synthetic MAC из serial). - Офсет убран из WDSPEngine (FSMeterCalDB): движок не знает ни диапазонов, ни трансвертеров. Теперь TRadioController.SMeterCalFor(VisibleHz) — окно включённого XVTR-слота приоритетнее диапазона, индекс диапазона по плану железа (FreqToBandIdx с IsPluto); ReadSMeterDBm для главного S-метра (MainForm + ewsdrd) и SliceSMeter по TargetHz слайса — паны N на других диапазонах считаются по своему банду, а не по главному. - SettingsForm: таблицы на 12 слотов, подписи/видимость/раскладку ставит RelayoutCalTab; SetCalibrationBackend(IsPluto) вызывается рядом с SetAntennaBackend. У openHPSDR — HF-план, у Pluto — VHF/UHF-план и скрытые группы Power/SWR detector и Supply V/A (нет Alex-моста и его телеметрии). Слоты трансвертеров показываются только включённые, с их именами. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
+43
-6
@@ -623,6 +623,11 @@ type
|
||||
procedure SetSliceDSP(Id, NRMode, NBMode: Integer; SNBOn, ANFOn: Boolean);
|
||||
procedure SetSliceFMSquelch(Id: Integer; On_: Boolean; Level: Integer);
|
||||
function SliceSMeter(Id: Integer): Double; // dBm, из DSP-потока
|
||||
// S-метр главного приёмника, dBm, с калибровочным офсетом текущего
|
||||
// диапазона/трансвертера (движок отдаёт сырое значение).
|
||||
function ReadSMeterDBm: Double;
|
||||
// Офсет S-метра (дБ) для видимой частоты: слот трансвертера или диапазон.
|
||||
function SMeterCalFor(VisibleHz: Double): Double;
|
||||
procedure SetSliceDevice(Id, DevIndex: Integer; const DevName: string);
|
||||
function SliceCount: Integer;
|
||||
function GetSlice(Id: Integer; out S: TCtrlSlice): Boolean;
|
||||
@@ -685,7 +690,7 @@ type
|
||||
function PlutoTxAttForDrive: Double; // дБ<0 под текущий FDrivePercent
|
||||
procedure ApplyPlutoTxAtten; // ставит att по FTransmitting/FTuning
|
||||
procedure SetPlutoTxMaxAtt(Db: Double); // потолок на drive=100% (внешний усилитель)
|
||||
procedure SetCalibration(const C: TCalibration); // вкладка Calibration → FCal + офсет S-метра в DSP
|
||||
procedure SetCalibration(const C: TCalibration); // вкладка Calibration → FCal (офсеты S-метра — в SMeterCalFor)
|
||||
procedure ApplyWDSPDrive(Pct: Integer); // цифровой drive WDSP: Pluto=1.0 (мощность — атт), HPSDR=Pct/100
|
||||
|
||||
// Диапазоны / трансвертеры / спан
|
||||
@@ -971,7 +976,6 @@ begin
|
||||
FDSPEngine.OnSliceDemodAudio := OnSliceDemodAudioReady;
|
||||
FDSPEngine.OnDemodAudio := OnDemodAudioReady;
|
||||
FDSPEngine.SetDisplayResLimit(FDisplayPixels);
|
||||
FDSPEngine.SMeterCalDB := FCal.SMeterOffsetDB;
|
||||
|
||||
// QO-100 beacon lock: эталон частоты = декодер (см. ServiceBeaconLock).
|
||||
FBeaconRefHz := 10489750000.0; // центральный BPSK-маяк NB-транспондера (downlink)
|
||||
@@ -2039,9 +2043,42 @@ begin
|
||||
end;
|
||||
|
||||
function TRadioController.SliceSMeter(Id: Integer): Double;
|
||||
// Слайс может стоять на другом диапазоне (паны N кросс-банд), поэтому офсет
|
||||
// берём по ЕГО видимой частоте, а не по главному диапазону.
|
||||
var idx: Integer;
|
||||
begin
|
||||
if Assigned(FDSPEngine) then Result := FDSPEngine.GetSliceSMeter(Id)
|
||||
else Result := -130.0;
|
||||
Result := -130.0;
|
||||
if not Assigned(FDSPEngine) then Exit;
|
||||
Result := FDSPEngine.GetSliceSMeter(Id);
|
||||
idx := FindSliceIndex(Id);
|
||||
if idx >= 0 then Result := Result + SMeterCalFor(FSlices[idx].TargetHz);
|
||||
end;
|
||||
|
||||
function TRadioController.ReadSMeterDBm: Double;
|
||||
begin
|
||||
if not Assigned(FDSPEngine) then Exit(-130.0);
|
||||
Result := FDSPEngine.GetSMeterDBm + SMeterCalFor(ActiveVfoHz);
|
||||
end;
|
||||
|
||||
function TRadioController.SMeterCalFor(VisibleHz: Double): Double;
|
||||
// Трансвертер имеет приоритет над диапазоном: его окно частот — видимые
|
||||
// (не IF), и усиление тракта задаёт конвертер/LNB, а не КВ-вход трансивера.
|
||||
// Индекс диапазона — по плану активного железа (HF openHPSDR / VHF-UHF Pluto).
|
||||
var i, Bi: Integer;
|
||||
begin
|
||||
Result := 0.0;
|
||||
if (FCurrentXvtr >= 0) and (FCurrentXvtr < CFG_XVTR_COUNT)
|
||||
and FXvtrSettings.Entries[FCurrentXvtr].Enabled
|
||||
and (VisibleHz >= FXvtrSettings.Entries[FCurrentXvtr].FreqBegin)
|
||||
and (VisibleHz <= FXvtrSettings.Entries[FCurrentXvtr].FreqEnd) then
|
||||
Exit(FCal.SMeterXvtrDB[FCurrentXvtr]);
|
||||
for i := 0 to CFG_XVTR_COUNT-1 do
|
||||
if FXvtrSettings.Entries[i].Enabled
|
||||
and (VisibleHz >= FXvtrSettings.Entries[i].FreqBegin)
|
||||
and (VisibleHz <= FXvtrSettings.Entries[i].FreqEnd) then
|
||||
Exit(FCal.SMeterXvtrDB[i]);
|
||||
Bi := FreqToBandIdx(VisibleHz, IsPluto);
|
||||
if (Bi >= 0) and (Bi < CFG_BAND_COUNT) then Result := FCal.SMeterBandDB[Bi];
|
||||
end;
|
||||
|
||||
procedure TRadioController.SetSliceDevice(Id, DevIndex: Integer;
|
||||
@@ -3567,8 +3604,8 @@ begin
|
||||
// Санитизация: битый конфиг не должен дать деление на ноль/абсурдные ватты.
|
||||
FCal.PwrDetModel := EnsureRange(FCal.PwrDetModel, 0, 3);
|
||||
if FCal.AmpSensMVA <= 0 then FCal.AmpSensMVA := 120.0;
|
||||
if Assigned(FDSPEngine) then
|
||||
FDSPEngine.SMeterCalDB := FCal.SMeterOffsetDB;
|
||||
// Офсет S-метра берётся из FCal на каждом чтении (SMeterCalFor) — применять
|
||||
// отдельно нечего: он зависит от диапазона/трансвертера, а не от движка.
|
||||
SaveGlobalSettings; // персист (гейт по FDevConnected внутри)
|
||||
end;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user