mirror of
https://git.vladimir.cc/vladimir/ewsdr.git
synced 2026-08-25 17:27:32 +00:00
feature(calibration): частотная калибровка опорника (ppm) + TO Error в слоте QO-100
Пункт 3 плана. Ручные подгонки остаются: ppm работает ПОД ними, а не вместо — уход тракта где-то больше, где-то меньше. - Settings: TCalibration.FreqCalPPM (JSON cal_freq_ppm, +-100 ppm, per-device). Смысл знака: «опора выше номинала на N ppm», положительное значение поднимает показываемые частоты. - RadioBackend: виртуальный SetFreqCalPPM. - HPSDRNetwork: CalFreq(Hz) = Hz / (1 + ppm) в частотном слове — все четыре точки (главный DDC, DDC панов, feedback-DDC PureSignal, DUC передачи). Тактовый генератор радио менять нечем, поэтому правим запрос. - PlutoBackend: штатный xo_correction в ad9361-phy (device-attr биндинги добавлены в IIOBindings). Номинал XO снимается при коннекте с округлением до 100 кГц, чтобы наша же коррекция с прошлой сессии не накапливалась; после записи LO переписываются, иначе правка ждала бы следующей перестройки. Одна цифра лечит RX и TX на всех диапазонах. - QO-100: TXvtrEntry.TxLOError (JSON tx_lo_error) + поле «TO Error (Hz)» на странице QO-100. Сам транспондер-offset держим стандартным (8089.5 МГц), уход тракта правим поправкой; ActiveTXFreqHz учитывает её, подсказка внизу страницы считает TX-частоту уже с ней. - UI-фиксы вкладки Calibration: длинные подсказки переведены на несколько строк (WordWrap — TLabel по умолчанию режется по краю группы), заголовки таблиц укорочены и не заезжают под кнопку «= S-meter»; RelayoutCalTab сбрасывает прокрутку страницы перед перекладкой (SetBounds в TScrollBox задаёт координаты относительно прокрученного клиента). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
+24
-4
@@ -156,6 +156,9 @@ type
|
||||
FMainDither: Boolean;
|
||||
FMainRandom: Boolean;
|
||||
|
||||
// Частотная калибровка опорника радио (ppm) — вносится в частотное слово
|
||||
// (тактовый генератор радио менять нечем, поэтому правим запрос).
|
||||
FFreqCalPPM: Double;
|
||||
// Текущее состояние для построения HP пакетов
|
||||
FCurrentRXFreq: Double;
|
||||
FCurrentTXFreq: Double;
|
||||
@@ -260,6 +263,9 @@ type
|
||||
procedure UpdateState(RXFreqHz, TXFreqHz: Double; DriveLevel: Byte;
|
||||
Transmitting, PAEnabled, AlexEnabled: Boolean); override;
|
||||
procedure SetStepAtten(dB: Byte); override;
|
||||
procedure SetFreqCalPPM(P: Double); override;
|
||||
// Частота с поправкой опорника — для частотного слова DDC/DUC.
|
||||
function CalFreq(Hz: Double): Double;
|
||||
procedure SetAlexConfig(const A: TAlexSettings); override;
|
||||
// Включение/настройка XVTR-режима. Все параметры применяются мгновенно
|
||||
// (отправляется HP-пакет). Когда AEnable=False, XVTR-bit гасится,
|
||||
@@ -736,6 +742,7 @@ begin
|
||||
FWBUpdateRateMS := 70;
|
||||
FWBFrameCount := 0;
|
||||
FWBSeqValid := False;
|
||||
FFreqCalPPM := 0.0;
|
||||
FCurrentRXFreq := 7100000;
|
||||
FCurrentTXFreq := 7100000;
|
||||
FCurrentDrive := 0;
|
||||
@@ -1693,6 +1700,19 @@ begin
|
||||
FAlexEnabled := AlexEnabled;
|
||||
end;
|
||||
|
||||
function THPSDRNetwork.CalFreq(Hz: Double): Double;
|
||||
// Опора радио выше номинала на FFreqCalPPM ⇒ DDC/DUC уходят вверх на столько
|
||||
// же. Компенсируем запрошенной частотой: просим ниже ровно на ppm.
|
||||
begin
|
||||
if FFreqCalPPM = 0 then Exit(Hz);
|
||||
Result := Hz / (1.0 + FFreqCalPPM * 1.0E-6);
|
||||
end;
|
||||
|
||||
procedure THPSDRNetwork.SetFreqCalPPM(P: Double);
|
||||
begin
|
||||
FFreqCalPPM := P;
|
||||
end;
|
||||
|
||||
procedure THPSDRNetwork.SetStepAtten(dB: Byte);
|
||||
begin
|
||||
if dB > 31 then dB := 31;
|
||||
@@ -1737,7 +1757,7 @@ begin
|
||||
DDCBase := DDCBaseIndex;
|
||||
|
||||
// DDC RX frequency (bytes 9 + DDC*4)
|
||||
Ph := FreqToPhaseWord(FCurrentRXFreq);
|
||||
Ph := FreqToPhaseWord(CalFreq(FCurrentRXFreq));
|
||||
Buf[9 + DDCBase*4] := (Ph shr 24) and $FF;
|
||||
Buf[10 + DDCBase*4] := (Ph shr 16) and $FF;
|
||||
Buf[11 + DDCBase*4] := (Ph shr 8) and $FF;
|
||||
@@ -1748,7 +1768,7 @@ begin
|
||||
for ddc := 0 to MAX_DDCS - 1 do
|
||||
if FPanDDCEnabled[ddc] then
|
||||
begin
|
||||
Ph := FreqToPhaseWord(FPanDDCFreqHz[ddc]);
|
||||
Ph := FreqToPhaseWord(CalFreq(FPanDDCFreqHz[ddc]));
|
||||
Buf[9 + ddc*4] := (Ph shr 24) and $FF;
|
||||
Buf[10 + ddc*4] := (Ph shr 16) and $FF;
|
||||
Buf[11 + ddc*4] := (Ph shr 8) and $FF;
|
||||
@@ -1759,7 +1779,7 @@ begin
|
||||
// DDCBase=2 ⇒ с частотным словом главного DDC (bytes 17..20) не пересекаемся.
|
||||
if FPSTXActive then
|
||||
begin
|
||||
Ph := FreqToPhaseWord(FCurrentTXFreq);
|
||||
Ph := FreqToPhaseWord(CalFreq(FCurrentTXFreq));
|
||||
Buf[9] := (Ph shr 24) and $FF;
|
||||
Buf[10] := (Ph shr 16) and $FF;
|
||||
Buf[11] := (Ph shr 8) and $FF;
|
||||
@@ -1771,7 +1791,7 @@ begin
|
||||
end;
|
||||
|
||||
// DUC TX frequency (bytes 329-332)
|
||||
Ph := FreqToPhaseWord(FCurrentTXFreq);
|
||||
Ph := FreqToPhaseWord(CalFreq(FCurrentTXFreq));
|
||||
Buf[329] := (Ph shr 24) and $FF;
|
||||
Buf[330] := (Ph shr 16) and $FF;
|
||||
Buf[331] := (Ph shr 8) and $FF;
|
||||
|
||||
Reference in New Issue
Block a user