mirror of
https://git.vladimir.cc/vladimir/ewsdr.git
synced 2026-08-25 18:43:51 +00:00
feat(oc): OC Control — Open Collector выходы Penny/Alex (эталон Thetis)
Byte 1401 High Priority packet: per-band (HF 160m-6m) и per-slot (XVTR) RX/TX-маски на 7 пинов + TX pin action (MOX/TUNE/2TON и комбинации). Только openHPSDR — у Pluto/AD936x такого выхода нет, вкладка Settings скрывается на этом бэкенде. Настройки — вкладка "OC Control" в SettingsForm. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
+98
-5
@@ -169,6 +169,11 @@ type
|
|||||||
FAlexEnabled: Boolean;
|
FAlexEnabled: Boolean;
|
||||||
FAlexConfig: TAlexSettings; // per-band antenna + routing config
|
FAlexConfig: TAlexSettings; // per-band antenna + routing config
|
||||||
FStepAtten: Byte; // ADC0 step attenuator 0-31 dB
|
FStepAtten: Byte; // ADC0 step attenuator 0-31 dB
|
||||||
|
// ---- OC Control (Open Collector выходы Penny/Alex, byte 1401) ----
|
||||||
|
FOCConfig: TOCSettings;
|
||||||
|
FTuning: Boolean; // TUN активен (для TX pin action)
|
||||||
|
FTwoTone: Boolean; // 2TON активен (для TX pin action)
|
||||||
|
FXvtrSlot: Integer; // активный слот XVTR (0..7) или -1 = HF-группа
|
||||||
// ---- PureSignal ----
|
// ---- PureSignal ----
|
||||||
// FPSEnabled — фича вооружена (кнопка PS). FPSTXActive — активная PTT-фаза:
|
// FPSEnabled — фича вооружена (кнопка PS). FPSTXActive — активная PTT-фаза:
|
||||||
// RebuildDDCSpecific включает feedback-DDC0 (ADC0) + sync DDC1 (TX DAC),
|
// RebuildDDCSpecific включает feedback-DDC0 (ADC0) + sync DDC1 (TX DAC),
|
||||||
@@ -261,16 +266,21 @@ type
|
|||||||
procedure SetRunAndFreq(Run: Boolean; DDC0FreqHz, DUCFreqHz: Double;
|
procedure SetRunAndFreq(Run: Boolean; DDC0FreqHz, DUCFreqHz: Double;
|
||||||
DriveLevel: Byte = 100); override;
|
DriveLevel: Byte = 100); override;
|
||||||
procedure UpdateState(RXFreqHz, TXFreqHz: Double; DriveLevel: Byte;
|
procedure UpdateState(RXFreqHz, TXFreqHz: Double; DriveLevel: Byte;
|
||||||
Transmitting, PAEnabled, AlexEnabled: Boolean); override;
|
Transmitting, PAEnabled, AlexEnabled: Boolean;
|
||||||
|
Tuning: Boolean = False; TwoTone: Boolean = False); override;
|
||||||
procedure SetStepAtten(dB: Byte); override;
|
procedure SetStepAtten(dB: Byte); override;
|
||||||
procedure SetFreqCalPPM(P: Double); override;
|
procedure SetFreqCalPPM(P: Double); override;
|
||||||
// Частота с поправкой опорника — для частотного слова DDC/DUC.
|
// Частота с поправкой опорника — для частотного слова DDC/DUC.
|
||||||
function CalFreq(Hz: Double): Double;
|
function CalFreq(Hz: Double): Double;
|
||||||
procedure SetAlexConfig(const A: TAlexSettings); override;
|
procedure SetAlexConfig(const A: TAlexSettings); override;
|
||||||
|
// OC Control (Open Collector выходы) — конфиг применяется мгновенно.
|
||||||
|
procedure SetOCConfig(const O: TOCSettings); override;
|
||||||
// Включение/настройка XVTR-режима. Все параметры применяются мгновенно
|
// Включение/настройка XVTR-режима. Все параметры применяются мгновенно
|
||||||
// (отправляется HP-пакет). Когда AEnable=False, XVTR-bit гасится,
|
// (отправляется HP-пакет). Когда AEnable=False, XVTR-bit гасится,
|
||||||
// антенна и Alex routing возвращаются к per-band дефолту.
|
// антенна и Alex routing возвращаются к per-band дефолту. ASlot — активный
|
||||||
procedure SetXvtrMode(AEnable, ADisablePA: Boolean; ARxAnt: Byte); override;
|
// слот трансвертера (0..7), для per-slot OC-масок; -1 если не применимо.
|
||||||
|
procedure SetXvtrMode(AEnable, ADisablePA: Boolean; ARxAnt: Byte;
|
||||||
|
ASlot: Integer = -1); override;
|
||||||
procedure SendFullHP; override;
|
procedure SendFullHP; override;
|
||||||
// Отдельная отправка PTT: переключает реле (bit27) и drive ДО, потом PTT.
|
// Отдельная отправка PTT: переключает реле (bit27) и drive ДО, потом PTT.
|
||||||
// Не меняет FIsTransmitting — вызывать после UpdateState+SendFullHP.
|
// Не меняет FIsTransmitting — вызывать после UpdateState+SendFullHP.
|
||||||
@@ -750,6 +760,10 @@ begin
|
|||||||
FPAEnabled := True;
|
FPAEnabled := True;
|
||||||
FAlexEnabled := True;
|
FAlexEnabled := True;
|
||||||
TSettingsManager.DefaultAlex(FAlexConfig);
|
TSettingsManager.DefaultAlex(FAlexConfig);
|
||||||
|
TSettingsManager.DefaultOC(FOCConfig);
|
||||||
|
FTuning := False;
|
||||||
|
FTwoTone := False;
|
||||||
|
FXvtrSlot := -1;
|
||||||
FSendLock := TCriticalSection.Create;
|
FSendLock := TCriticalSection.Create;
|
||||||
FHPSendLock := TCriticalSection.Create;
|
FHPSendLock := TCriticalSection.Create;
|
||||||
FDUCIQLock := TCriticalSection.Create;
|
FDUCIQLock := TCriticalSection.Create;
|
||||||
@@ -1510,7 +1524,8 @@ begin
|
|||||||
if FConnected then SendFullHP;
|
if FConnected then SendFullHP;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure THPSDRNetwork.SetXvtrMode(AEnable, ADisablePA: Boolean; ARxAnt: Byte);
|
procedure THPSDRNetwork.SetXvtrMode(AEnable, ADisablePA: Boolean; ARxAnt: Byte;
|
||||||
|
ASlot: Integer);
|
||||||
begin
|
begin
|
||||||
FXvtrEnable := AEnable;
|
FXvtrEnable := AEnable;
|
||||||
FXvtrDisablePA := AEnable and ADisablePA;
|
FXvtrDisablePA := AEnable and ADisablePA;
|
||||||
@@ -1518,9 +1533,79 @@ begin
|
|||||||
FXvtrRxAntOverride := ARxAnt
|
FXvtrRxAntOverride := ARxAnt
|
||||||
else
|
else
|
||||||
FXvtrRxAntOverride := 0;
|
FXvtrRxAntOverride := 0;
|
||||||
|
if AEnable and (ASlot >= 0) then
|
||||||
|
FXvtrSlot := ASlot
|
||||||
|
else
|
||||||
|
FXvtrSlot := -1;
|
||||||
if FConnected then SendFullHP;
|
if FConnected then SendFullHP;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure THPSDRNetwork.SetOCConfig(const O: TOCSettings);
|
||||||
|
begin
|
||||||
|
FOCConfig := O;
|
||||||
|
if FConnected then SendFullHP;
|
||||||
|
end;
|
||||||
|
|
||||||
|
// Строит 8-битное слово OC (byte 1401 HP-пакета, биты 0..6 = пины 1..7).
|
||||||
|
// Портировано из Thetis (Penny.UpdateExtCtrl/adjustForTXAction), урезано:
|
||||||
|
// без PA-override и split-pins VFO A/B (см. project_oc_control память).
|
||||||
|
// RX: маска банда/слота как есть. TX: маска банда/слота, каждый включённый
|
||||||
|
// пин дополнительно гейтится своим TX pin action (MOX/TUNE/TWOTONE и их
|
||||||
|
// комбинации) — тот же tx-флаг остаётся True на всём протяжении TUN/2TON
|
||||||
|
// (см. TRadioController.SetTune/SetTwoTone), поэтому "чистый MOX" явно
|
||||||
|
// исключает Tuning/TwoTone.
|
||||||
|
function CalcOCBits(RXFreqHz, TXFreqHz: Double;
|
||||||
|
Transmitting, Tuning, TwoTone: Boolean;
|
||||||
|
XvtrSlot: Integer;
|
||||||
|
const OC: TOCSettings): Byte;
|
||||||
|
var
|
||||||
|
RxMask, TxMask: Byte;
|
||||||
|
Actions: TOCPinActions;
|
||||||
|
i: Integer;
|
||||||
|
Fire: Boolean;
|
||||||
|
Band: Integer;
|
||||||
|
begin
|
||||||
|
Result := 0;
|
||||||
|
if not OC.Enabled then Exit;
|
||||||
|
|
||||||
|
if (XvtrSlot >= 0) and (XvtrSlot < CFG_XVTR_COUNT) then
|
||||||
|
begin
|
||||||
|
RxMask := OC.RxMaskXvtr[XvtrSlot];
|
||||||
|
TxMask := OC.TxMaskXvtr[XvtrSlot];
|
||||||
|
Actions := OC.ActionXvtr;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
if Transmitting then Band := FreqToBandIndex(TXFreqHz)
|
||||||
|
else Band := FreqToBandIndex(RXFreqHz);
|
||||||
|
RxMask := OC.RxMaskHF[Band];
|
||||||
|
TxMask := OC.TxMaskHF[Band];
|
||||||
|
Actions := OC.ActionHF;
|
||||||
|
end;
|
||||||
|
|
||||||
|
if not Transmitting then
|
||||||
|
begin
|
||||||
|
Result := RxMask;
|
||||||
|
Exit;
|
||||||
|
end;
|
||||||
|
|
||||||
|
for i := 0 to OC_PIN_COUNT - 1 do
|
||||||
|
begin
|
||||||
|
if (TxMask and (1 shl i)) = 0 then Continue;
|
||||||
|
case Actions[i] of
|
||||||
|
OCA_MOX: Fire := (not Tuning) and (not TwoTone);
|
||||||
|
OCA_TUNE: Fire := Tuning;
|
||||||
|
OCA_TWOTONE: Fire := TwoTone;
|
||||||
|
OCA_MOX_TUNE: Fire := not TwoTone;
|
||||||
|
OCA_MOX_TWOTONE: Fire := not Tuning;
|
||||||
|
OCA_TUNE_TWOTONE: Fire := Tuning or TwoTone;
|
||||||
|
OCA_MOX_TUNE_TWOTONE: Fire := True;
|
||||||
|
else Fire := False;
|
||||||
|
end;
|
||||||
|
if Fire then Result := Result or (1 shl i);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
function THPSDRNetwork.DDCBaseIndex: Integer;
|
function THPSDRNetwork.DDCBaseIndex: Integer;
|
||||||
begin
|
begin
|
||||||
// Для ANGELIA/ORION/ORION2/SATURN DDC начинается с индекса 2 (DDC0/1 — PureSignal)
|
// Для ANGELIA/ORION/ORION2/SATURN DDC начинается с индекса 2 (DDC0/1 — PureSignal)
|
||||||
@@ -1690,7 +1775,8 @@ end;
|
|||||||
|
|
||||||
procedure THPSDRNetwork.UpdateState(RXFreqHz, TXFreqHz: Double;
|
procedure THPSDRNetwork.UpdateState(RXFreqHz, TXFreqHz: Double;
|
||||||
DriveLevel: Byte;
|
DriveLevel: Byte;
|
||||||
Transmitting, PAEnabled, AlexEnabled: Boolean);
|
Transmitting, PAEnabled, AlexEnabled: Boolean;
|
||||||
|
Tuning: Boolean; TwoTone: Boolean);
|
||||||
begin
|
begin
|
||||||
FCurrentRXFreq := RXFreqHz;
|
FCurrentRXFreq := RXFreqHz;
|
||||||
FCurrentTXFreq := TXFreqHz;
|
FCurrentTXFreq := TXFreqHz;
|
||||||
@@ -1698,6 +1784,8 @@ begin
|
|||||||
FIsTransmitting := Transmitting;
|
FIsTransmitting := Transmitting;
|
||||||
FPAEnabled := PAEnabled;
|
FPAEnabled := PAEnabled;
|
||||||
FAlexEnabled := AlexEnabled;
|
FAlexEnabled := AlexEnabled;
|
||||||
|
FTuning := Tuning;
|
||||||
|
FTwoTone := TwoTone;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function THPSDRNetwork.CalFreq(Hz: Double): Double;
|
function THPSDRNetwork.CalFreq(Hz: Double): Double;
|
||||||
@@ -1847,6 +1935,11 @@ begin
|
|||||||
if not FSpeakerAudioEnabled then
|
if not FSpeakerAudioEnabled then
|
||||||
Buf[1400] := Buf[1400] or $02;
|
Buf[1400] := Buf[1400] or $02;
|
||||||
|
|
||||||
|
// OC Control — Open Collector outputs (byte 1401)
|
||||||
|
if FOCConfig.Enabled then
|
||||||
|
Buf[1401] := CalcOCBits(FCurrentRXFreq, FCurrentTXFreq, FIsTransmitting,
|
||||||
|
FTuning, FTwoTone, FXvtrSlot, FOCConfig);
|
||||||
|
|
||||||
// Step attenuators ADC0/ADC1 (bytes 1443/1442)
|
// Step attenuators ADC0/ADC1 (bytes 1443/1442)
|
||||||
// 0 dB = 0, max 31 dB
|
// 0 dB = 0, max 31 dB
|
||||||
Buf[1443] := FStepAtten; // ADC0 attenuation
|
Buf[1443] := FStepAtten; // ADC0 attenuation
|
||||||
|
|||||||
+25
-6
@@ -591,6 +591,7 @@ type
|
|||||||
// восстанавливаются позже и должны встать на свои звуковухи.
|
// восстанавливаются позже и должны встать на свои звуковухи.
|
||||||
procedure ApplySliceSlotAudio;
|
procedure ApplySliceSlotAudio;
|
||||||
procedure OnAlexSettingsChange(const A: TAlexSettings);
|
procedure OnAlexSettingsChange(const A: TAlexSettings);
|
||||||
|
procedure OnOCSettingsChange(const O: TOCSettings);
|
||||||
procedure OnXvtrSettingsChange(const X: TXvtrSettings);
|
procedure OnXvtrSettingsChange(const X: TXvtrSettings);
|
||||||
procedure PushXvtrToWeb;
|
procedure PushXvtrToWeb;
|
||||||
procedure PushRatePresetsToWeb; // backend sample-rate пресеты → web
|
procedure PushRatePresetsToWeb; // backend sample-rate пресеты → web
|
||||||
@@ -1234,6 +1235,7 @@ begin
|
|||||||
// Дефолты TX, Alex и XVTR (на случай если устройство ещё не выбрано).
|
// Дефолты TX, Alex и XVTR (на случай если устройство ещё не выбрано).
|
||||||
TSettingsManager.DefaultTX(FController.FTXSettings);
|
TSettingsManager.DefaultTX(FController.FTXSettings);
|
||||||
TSettingsManager.DefaultAlex(FController.FAlexSettings);
|
TSettingsManager.DefaultAlex(FController.FAlexSettings);
|
||||||
|
TSettingsManager.DefaultOC(FController.FOCSettings);
|
||||||
TSettingsManager.DefaultXvtr(FController.FXvtrSettings);
|
TSettingsManager.DefaultXvtr(FController.FXvtrSettings);
|
||||||
FController.FCurrentXvtr := -1;
|
FController.FCurrentXvtr := -1;
|
||||||
|
|
||||||
@@ -4404,7 +4406,7 @@ begin
|
|||||||
if FController.FNetwork.Connected and FController.FNetwork.Running then
|
if FController.FNetwork.Connected and FController.FNetwork.Running then
|
||||||
begin
|
begin
|
||||||
FController.FNetwork.UpdateState(XvtrTranslate(FController.FCenterFreq), XvtrTranslateTX(ActiveTXFreqHz), FController.FDriveLevel,
|
FController.FNetwork.UpdateState(XvtrTranslate(FController.FCenterFreq), XvtrTranslateTX(ActiveTXFreqHz), FController.FDriveLevel,
|
||||||
FController.FTransmitting, True, True);
|
FController.FTransmitting, True, True, FController.FTuning, FController.FTwoTone);
|
||||||
FController.FNetwork.SendFullHP;
|
FController.FNetwork.SendFullHP;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
@@ -4426,7 +4428,7 @@ begin
|
|||||||
if FController.FNetwork.Connected and FController.FNetwork.Running then
|
if FController.FNetwork.Connected and FController.FNetwork.Running then
|
||||||
begin
|
begin
|
||||||
FController.FNetwork.UpdateState(XvtrTranslate(FController.FCenterFreq), XvtrTranslateTX(ActiveTXFreqHz), FController.FDriveLevel,
|
FController.FNetwork.UpdateState(XvtrTranslate(FController.FCenterFreq), XvtrTranslateTX(ActiveTXFreqHz), FController.FDriveLevel,
|
||||||
FController.FTransmitting, True, True);
|
FController.FTransmitting, True, True, FController.FTuning, FController.FTwoTone);
|
||||||
FController.FNetwork.SendFullHP;
|
FController.FNetwork.SendFullHP;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
@@ -4926,7 +4928,8 @@ begin
|
|||||||
if FController.FNetwork.Connected and FController.FNetwork.Running then
|
if FController.FNetwork.Connected and FController.FNetwork.Running then
|
||||||
begin
|
begin
|
||||||
FController.FNetwork.UpdateState(XvtrTranslate(FController.FCenterFreq),
|
FController.FNetwork.UpdateState(XvtrTranslate(FController.FCenterFreq),
|
||||||
XvtrTranslateTX(ActiveTXFreqHz), FController.FDriveLevel, FController.FTransmitting, True, True);
|
XvtrTranslateTX(ActiveTXFreqHz), FController.FDriveLevel, FController.FTransmitting, True, True,
|
||||||
|
FController.FTuning, FController.FTwoTone);
|
||||||
FController.FNetwork.SendFullHP;
|
FController.FNetwork.SendFullHP;
|
||||||
end;
|
end;
|
||||||
if FController.FCurrentXvtr < 0 then
|
if FController.FCurrentXvtr < 0 then
|
||||||
@@ -7608,7 +7611,7 @@ begin
|
|||||||
end;
|
end;
|
||||||
FController.FDriveLevel := CalcDriveByte;
|
FController.FDriveLevel := CalcDriveByte;
|
||||||
if FController.FNetwork.Connected and FController.FNetwork.Running then
|
if FController.FNetwork.Connected and FController.FNetwork.Running then
|
||||||
FController.FNetwork.UpdateState(XvtrTranslate(FController.FCenterFreq), XvtrTranslateTX(ActiveTXFreqHz), FController.FDriveLevel, FController.FTransmitting, True, True);
|
FController.FNetwork.UpdateState(XvtrTranslate(FController.FCenterFreq), XvtrTranslateTX(ActiveTXFreqHz), FController.FDriveLevel, FController.FTransmitting, True, True, FController.FTuning, FController.FTwoTone);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TMainForm.OnPlutoTxMaxAttChange(MaxAttDb: Double);
|
procedure TMainForm.OnPlutoTxMaxAttChange(MaxAttDb: Double);
|
||||||
@@ -7643,7 +7646,7 @@ begin
|
|||||||
end;
|
end;
|
||||||
FController.FDriveLevel := CalcDriveByte;
|
FController.FDriveLevel := CalcDriveByte;
|
||||||
if FController.FNetwork.Connected and FController.FNetwork.Running then
|
if FController.FNetwork.Connected and FController.FNetwork.Running then
|
||||||
FController.FNetwork.UpdateState(XvtrTranslate(FController.FCenterFreq), XvtrTranslateTX(ActiveTXFreqHz), FController.FDriveLevel, FController.FTransmitting, True, True);
|
FController.FNetwork.UpdateState(XvtrTranslate(FController.FCenterFreq), XvtrTranslateTX(ActiveTXFreqHz), FController.FDriveLevel, FController.FTransmitting, True, True, FController.FTuning, FController.FTwoTone);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TMainForm.OnTXSettingsChange(const T: TTXSettings);
|
procedure TMainForm.OnTXSettingsChange(const T: TTXSettings);
|
||||||
@@ -7686,7 +7689,7 @@ begin
|
|||||||
if FController.FNetwork.Connected and FController.FNetwork.Running then
|
if FController.FNetwork.Connected and FController.FNetwork.Running then
|
||||||
begin
|
begin
|
||||||
FController.FNetwork.UpdateState(XvtrTranslate(FController.FCenterFreq), XvtrTranslateTX(ActiveTXFreqHz), FController.FDriveLevel,
|
FController.FNetwork.UpdateState(XvtrTranslate(FController.FCenterFreq), XvtrTranslateTX(ActiveTXFreqHz), FController.FDriveLevel,
|
||||||
FController.FTransmitting, True, True);
|
FController.FTransmitting, True, True, FController.FTuning, FController.FTwoTone);
|
||||||
FController.FNetwork.SendFullHP;
|
FController.FNetwork.SendFullHP;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
@@ -7711,6 +7714,18 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TMainForm.OnOCSettingsChange(const O: TOCSettings);
|
||||||
|
begin
|
||||||
|
FController.FOCSettings := O;
|
||||||
|
if FController.FNetwork.Connected then
|
||||||
|
FController.FNetwork.SetOCConfig(O);
|
||||||
|
if FController.FDevConnected then
|
||||||
|
begin
|
||||||
|
FController.FSettings.SaveOC(FController.FDevMAC, O);
|
||||||
|
FController.FSettings.Save;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
// ===========================================================================
|
// ===========================================================================
|
||||||
// XVTR (Transverter) integration
|
// XVTR (Transverter) integration
|
||||||
// ===========================================================================
|
// ===========================================================================
|
||||||
@@ -8493,6 +8508,7 @@ begin
|
|||||||
SF.OnTXChange := OnTXSettingsChange;
|
SF.OnTXChange := OnTXSettingsChange;
|
||||||
SF.OnAlexChange := OnAlexSettingsChange;
|
SF.OnAlexChange := OnAlexSettingsChange;
|
||||||
SF.OnXvtrChange := OnXvtrSettingsChange;
|
SF.OnXvtrChange := OnXvtrSettingsChange;
|
||||||
|
SF.OnOCChange := OnOCSettingsChange;
|
||||||
SF.OnWfAGCNFChange := ApplyWfAGCNF;
|
SF.OnWfAGCNFChange := ApplyWfAGCNF;
|
||||||
SF.OnADCChange := ApplyADCSettings;
|
SF.OnADCChange := ApplyADCSettings;
|
||||||
SF.OnWebSettingsChange := ApplyWebSettings;
|
SF.OnWebSettingsChange := ApplyWebSettings;
|
||||||
@@ -8511,6 +8527,9 @@ begin
|
|||||||
SF.SetCalibrationBackend(FController.BackendCaps.Kind = bkPluto);
|
SF.SetCalibrationBackend(FController.BackendCaps.Kind = bkPluto);
|
||||||
SF.LoadAnt936x(FController.Ant936x, FController.FXvtrSettings);
|
SF.LoadAnt936x(FController.Ant936x, FController.FXvtrSettings);
|
||||||
SF.LoadXvtrSettings(FController.FXvtrSettings);
|
SF.LoadXvtrSettings(FController.FXvtrSettings);
|
||||||
|
SF.LoadOCSettings(FController.FOCSettings);
|
||||||
|
// Вкладка OC Control — только openHPSDR, у Pluto/AD936x нет такого выхода.
|
||||||
|
SF.SetOCBackend(FController.BackendCaps.Kind = bkPluto);
|
||||||
SF.LoadPASettings(FController.FPAMaxPower, FController.FPABandCal);
|
SF.LoadPASettings(FController.FPAMaxPower, FController.FPABandCal);
|
||||||
SF.LoadCalibration(FController.FCal);
|
SF.LoadCalibration(FController.FCal);
|
||||||
SF.LoadPlutoTxMaxAtt(FController.FPlutoTxMaxAttDb);
|
SF.LoadPlutoTxMaxAtt(FController.FPlutoTxMaxAttDb);
|
||||||
|
|||||||
+3
-2
@@ -170,7 +170,8 @@ type
|
|||||||
procedure SetRunAndFreq(Run: Boolean; DDC0FreqHz, DUCFreqHz: Double;
|
procedure SetRunAndFreq(Run: Boolean; DDC0FreqHz, DUCFreqHz: Double;
|
||||||
DriveLevel: Byte = 100); override;
|
DriveLevel: Byte = 100); override;
|
||||||
procedure UpdateState(RXFreqHz, TXFreqHz: Double; DriveLevel: Byte;
|
procedure UpdateState(RXFreqHz, TXFreqHz: Double; DriveLevel: Byte;
|
||||||
Transmitting, PAEnabled, AlexEnabled: Boolean); override;
|
Transmitting, PAEnabled, AlexEnabled: Boolean;
|
||||||
|
Tuning: Boolean = False; TwoTone: Boolean = False); override;
|
||||||
procedure SendFullHP; override;
|
procedure SendFullHP; override;
|
||||||
procedure SendPTT(Active: Boolean); override;
|
procedure SendPTT(Active: Boolean); override;
|
||||||
procedure SetAntPorts(RxPort, TxPort: Byte); override;
|
procedure SetAntPorts(RxPort, TxPort: Byte); override;
|
||||||
@@ -1065,7 +1066,7 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TPlutoBackend.UpdateState(RXFreqHz, TXFreqHz: Double; DriveLevel: Byte;
|
procedure TPlutoBackend.UpdateState(RXFreqHz, TXFreqHz: Double; DriveLevel: Byte;
|
||||||
Transmitting, PAEnabled, AlexEnabled: Boolean);
|
Transmitting, PAEnabled, AlexEnabled: Boolean; Tuning: Boolean; TwoTone: Boolean);
|
||||||
begin
|
begin
|
||||||
FRXFreq := RXFreqHz;
|
FRXFreq := RXFreqHz;
|
||||||
FTXFreq := TXFreqHz;
|
FTXFreq := TXFreqHz;
|
||||||
|
|||||||
+13
-3
@@ -158,7 +158,8 @@ type
|
|||||||
procedure SetRunAndFreq(Run: Boolean; DDC0FreqHz, DUCFreqHz: Double;
|
procedure SetRunAndFreq(Run: Boolean; DDC0FreqHz, DUCFreqHz: Double;
|
||||||
DriveLevel: Byte = 100); virtual; abstract;
|
DriveLevel: Byte = 100); virtual; abstract;
|
||||||
procedure UpdateState(RXFreqHz, TXFreqHz: Double; DriveLevel: Byte;
|
procedure UpdateState(RXFreqHz, TXFreqHz: Double; DriveLevel: Byte;
|
||||||
Transmitting, PAEnabled, AlexEnabled: Boolean); virtual; abstract;
|
Transmitting, PAEnabled, AlexEnabled: Boolean;
|
||||||
|
Tuning: Boolean = False; TwoTone: Boolean = False); virtual; abstract;
|
||||||
procedure SendFullHP; virtual; abstract;
|
procedure SendFullHP; virtual; abstract;
|
||||||
procedure SendPTT(Active: Boolean); virtual; abstract;
|
procedure SendPTT(Active: Boolean); virtual; abstract;
|
||||||
|
|
||||||
@@ -189,7 +190,11 @@ type
|
|||||||
// (мощность там через DriveLevel/DUC). Db < 0.
|
// (мощность там через DriveLevel/DUC). Db < 0.
|
||||||
procedure SetTxAtten(Db: Double); virtual;
|
procedure SetTxAtten(Db: Double); virtual;
|
||||||
procedure SetAlexConfig(const A: TAlexSettings); virtual;
|
procedure SetAlexConfig(const A: TAlexSettings); virtual;
|
||||||
procedure SetXvtrMode(AEnable, ADisablePA: Boolean; ARxAnt: Byte); virtual;
|
// OC Control (Open Collector выходы Penny/Alex) — no-op по умолчанию
|
||||||
|
// (Pluto/AD936x не имеет такого выхода).
|
||||||
|
procedure SetOCConfig(const O: TOCSettings); virtual;
|
||||||
|
procedure SetXvtrMode(AEnable, ADisablePA: Boolean; ARxAnt: Byte;
|
||||||
|
ASlot: Integer = -1); virtual;
|
||||||
procedure SendDDCAudio(const LeftRight: array of SmallInt); virtual;
|
procedure SendDDCAudio(const LeftRight: array of SmallInt); virtual;
|
||||||
procedure SendSpeakerAudio(const Left, Right: array of Single; Count: Integer); virtual;
|
procedure SendSpeakerAudio(const Left, Right: array of Single; Count: Integer); virtual;
|
||||||
procedure SetSpeakerAudio(AEnabled: Boolean); virtual;
|
procedure SetSpeakerAudio(AEnabled: Boolean); virtual;
|
||||||
@@ -284,7 +289,12 @@ procedure TRadioBackend.SetAlexConfig(const A: TAlexSettings);
|
|||||||
begin
|
begin
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TRadioBackend.SetXvtrMode(AEnable, ADisablePA: Boolean; ARxAnt: Byte);
|
procedure TRadioBackend.SetXvtrMode(AEnable, ADisablePA: Boolean; ARxAnt: Byte;
|
||||||
|
ASlot: Integer);
|
||||||
|
begin
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TRadioBackend.SetOCConfig(const O: TOCSettings);
|
||||||
begin
|
begin
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|||||||
+12
-7
@@ -407,6 +407,7 @@ type
|
|||||||
// ---- Конфиги / устройство (per-MAC) ----
|
// ---- Конфиги / устройство (per-MAC) ----
|
||||||
FTXSettings: TTXSettings;
|
FTXSettings: TTXSettings;
|
||||||
FAlexSettings: TAlexSettings;
|
FAlexSettings: TAlexSettings;
|
||||||
|
FOCSettings: TOCSettings; // OC Control (Open Collector, openHPSDR-only)
|
||||||
// Антенные разъёмы AD936x (Pluto/LibreSDR) на диапазон/трансвертер.
|
// Антенные разъёмы AD936x (Pluto/LibreSDR) на диапазон/трансвертер.
|
||||||
FAnt936x: TAD936xAnt;
|
FAnt936x: TAD936xAnt;
|
||||||
FXvtrSettings: TXvtrSettings;
|
FXvtrSettings: TXvtrSettings;
|
||||||
@@ -1187,7 +1188,7 @@ begin
|
|||||||
if Assigned(FNetwork) and FNetwork.Connected and FNetwork.Running then
|
if Assigned(FNetwork) and FNetwork.Connected and FNetwork.Running then
|
||||||
begin
|
begin
|
||||||
FNetwork.UpdateState(XvtrTranslate(FCenterFreq), XvtrTranslateTX(ActiveTXFreqHz),
|
FNetwork.UpdateState(XvtrTranslate(FCenterFreq), XvtrTranslateTX(ActiveTXFreqHz),
|
||||||
FDriveLevel, FTransmitting, True, True);
|
FDriveLevel, FTransmitting, True, True, FTuning, FTwoTone);
|
||||||
FNetwork.SendFullHP;
|
FNetwork.SendFullHP;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
@@ -4273,7 +4274,8 @@ begin
|
|||||||
En := False; DisablePA := False; RxAnt := 0;
|
En := False; DisablePA := False; RxAnt := 0;
|
||||||
end;
|
end;
|
||||||
if Assigned(FNetwork) and FNetwork.Connected then
|
if Assigned(FNetwork) and FNetwork.Connected then
|
||||||
FNetwork.SetXvtrMode(En, DisablePA, RxAnt);
|
if En then FNetwork.SetXvtrMode(En, DisablePA, RxAnt, FCurrentXvtr)
|
||||||
|
else FNetwork.SetXvtrMode(En, DisablePA, RxAnt, -1);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TRadioController.ActivateXvtr(Idx: Integer);
|
procedure TRadioController.ActivateXvtr(Idx: Integer);
|
||||||
@@ -4903,7 +4905,7 @@ begin
|
|||||||
begin
|
begin
|
||||||
FNetwork.ClearDUCIQQueue;
|
FNetwork.ClearDUCIQQueue;
|
||||||
FNetwork.UpdateState(XvtrTranslate(FCenterFreq), XvtrTranslateTX(ActiveTXFreqHz),
|
FNetwork.UpdateState(XvtrTranslate(FCenterFreq), XvtrTranslateTX(ActiveTXFreqHz),
|
||||||
FDriveLevel, True, True, True);
|
FDriveLevel, True, True, True, FTuning, FTwoTone);
|
||||||
FNetwork.SendFullHP; // 1й пакет: Alex bit27=1 (T/R relay), drive — без PTT
|
FNetwork.SendFullHP; // 1й пакет: Alex bit27=1 (T/R relay), drive — без PTT
|
||||||
FNetwork.SendPTT(True); // 2й пакет: PTT=1 после переключения реле
|
FNetwork.SendPTT(True); // 2й пакет: PTT=1 после переключения реле
|
||||||
// PureSignal: перевести feedback-DDC0/1 в TX-конфигурацию (частоты = TX,
|
// PureSignal: перевести feedback-DDC0/1 в TX-конфигурацию (частоты = TX,
|
||||||
@@ -4982,7 +4984,7 @@ begin
|
|||||||
// PureSignal: вернуть DDC0/1 в RX-конфигурацию (убрать feedback-DDC).
|
// PureSignal: вернуть DDC0/1 в RX-конфигурацию (убрать feedback-DDC).
|
||||||
FNetwork.SetPureSignalTX(False);
|
FNetwork.SetPureSignalTX(False);
|
||||||
FNetwork.UpdateState(XvtrTranslate(FCenterFreq), XvtrTranslateTX(ActiveTXFreqHz),
|
FNetwork.UpdateState(XvtrTranslate(FCenterFreq), XvtrTranslateTX(ActiveTXFreqHz),
|
||||||
FDriveLevel, False, True, True);
|
FDriveLevel, False, True, True, FTuning, FTwoTone);
|
||||||
FNetwork.ClearDUCIQQueue;
|
FNetwork.ClearDUCIQQueue;
|
||||||
FNetwork.SendFullHP; // 2й пакет: Alex bit27=0 (T/R relay RX)
|
FNetwork.SendFullHP; // 2й пакет: Alex bit27=0 (T/R relay RX)
|
||||||
end;
|
end;
|
||||||
@@ -5023,7 +5025,7 @@ begin
|
|||||||
if Assigned(FNetwork) and FNetwork.Connected and FNetwork.Running then
|
if Assigned(FNetwork) and FNetwork.Connected and FNetwork.Running then
|
||||||
begin
|
begin
|
||||||
FNetwork.UpdateState(XvtrTranslate(FCenterFreq), XvtrTranslateTX(ActiveTXFreqHz),
|
FNetwork.UpdateState(XvtrTranslate(FCenterFreq), XvtrTranslateTX(ActiveTXFreqHz),
|
||||||
FDriveLevel, FTransmitting, True, True);
|
FDriveLevel, FTransmitting, True, True, FTuning, FTwoTone);
|
||||||
FNetwork.SendFullHP;
|
FNetwork.SendFullHP;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
@@ -5506,7 +5508,7 @@ begin
|
|||||||
// Сначала отправляем Run=1 — эмулятор/железо создают ddc_specific_thread
|
// Сначала отправляем Run=1 — эмулятор/железо создают ddc_specific_thread
|
||||||
// (порт 1025) и rx_thread (порт 1035+) только после получения HP Run=1.
|
// (порт 1025) и rx_thread (порт 1035+) только после получения HP Run=1.
|
||||||
// DDC Specific и DUC Specific отправляем ПОСЛЕ, иначе порты ещё не открыты.
|
// DDC Specific и DUC Specific отправляем ПОСЛЕ, иначе порты ещё не открыты.
|
||||||
FNetwork.UpdateState(XvtrTranslate(FCenterFreq), XvtrTranslateTX(ActiveTXFreqHz), FDriveLevel, False, True, True);
|
FNetwork.UpdateState(XvtrTranslate(FCenterFreq), XvtrTranslateTX(ActiveTXFreqHz), FDriveLevel, False, True, True, FTuning, FTwoTone);
|
||||||
FNetwork.SetRunAndFreq(True, XvtrTranslate(FCenterFreq), XvtrTranslate(FCenterFreq), FDriveLevel);
|
FNetwork.SetRunAndFreq(True, XvtrTranslate(FCenterFreq), XvtrTranslate(FCenterFreq), FDriveLevel);
|
||||||
FRunning := True;
|
FRunning := True;
|
||||||
FRXStartTime := GetTickCount64;
|
FRXStartTime := GetTickCount64;
|
||||||
@@ -5557,7 +5559,7 @@ begin
|
|||||||
// (3.3 UI пересоздаст по персисту при следующем старте).
|
// (3.3 UI пересоздаст по персисту при следующем старте).
|
||||||
for p := 1 to MAX_PANS - 1 do
|
for p := 1 to MAX_PANS - 1 do
|
||||||
RemovePanDDC(p);
|
RemovePanDDC(p);
|
||||||
FNetwork.UpdateState(XvtrTranslate(FCenterFreq), XvtrTranslateTX(ActiveTXFreqHz), 0, False, True, True);
|
FNetwork.UpdateState(XvtrTranslate(FCenterFreq), XvtrTranslateTX(ActiveTXFreqHz), 0, False, True, True, FTuning, FTwoTone);
|
||||||
FNetwork.SetRunAndFreq(False, XvtrTranslate(FCenterFreq), XvtrTranslate(FCenterFreq), 0);
|
FNetwork.SetRunAndFreq(False, XvtrTranslate(FCenterFreq), XvtrTranslate(FCenterFreq), 0);
|
||||||
FRunning := False;
|
FRunning := False;
|
||||||
FTransmitting := False;
|
FTransmitting := False;
|
||||||
@@ -5744,6 +5746,8 @@ begin
|
|||||||
FSettings.LoadAlex(FDevMAC, FAlexSettings);
|
FSettings.LoadAlex(FDevMAC, FAlexSettings);
|
||||||
FSettings.LoadAnt936x(FDevMAC, FAnt936x);
|
FSettings.LoadAnt936x(FDevMAC, FAnt936x);
|
||||||
FNetwork.SetAlexConfig(FAlexSettings);
|
FNetwork.SetAlexConfig(FAlexSettings);
|
||||||
|
FSettings.LoadOC(FDevMAC, FOCSettings);
|
||||||
|
FNetwork.SetOCConfig(FOCSettings); // no-op на Pluto (base-класс)
|
||||||
FSettings.LoadXvtr(FDevMAC, FXvtrSettings);
|
FSettings.LoadXvtr(FDevMAC, FXvtrSettings);
|
||||||
FCurrentXvtr := -1;
|
FCurrentXvtr := -1;
|
||||||
ApplyXvtrToNetwork;
|
ApplyXvtrToNetwork;
|
||||||
@@ -5914,6 +5918,7 @@ begin
|
|||||||
SaveGlobalSettings;
|
SaveGlobalSettings;
|
||||||
FSettings.SaveAlex(FDevMAC, FAlexSettings);
|
FSettings.SaveAlex(FDevMAC, FAlexSettings);
|
||||||
FSettings.SaveAnt936x(FDevMAC, FAnt936x);
|
FSettings.SaveAnt936x(FDevMAC, FAnt936x);
|
||||||
|
FSettings.SaveOC(FDevMAC, FOCSettings);
|
||||||
// XVTR LastFreq → актуальная видимая частота в момент остановки.
|
// XVTR LastFreq → актуальная видимая частота в момент остановки.
|
||||||
if (FCurrentXvtr >= 0) and (FCurrentXvtr < CFG_XVTR_COUNT) then
|
if (FCurrentXvtr >= 0) and (FCurrentXvtr < CFG_XVTR_COUNT) then
|
||||||
FXvtrSettings.Entries[FCurrentXvtr].LastFreq := FVfoA;
|
FXvtrSettings.Entries[FCurrentXvtr].LastFreq := FVfoA;
|
||||||
|
|||||||
+108
@@ -13,6 +13,16 @@ const
|
|||||||
SETTINGS_FILE = 'hpsdr_settings.json';
|
SETTINGS_FILE = 'hpsdr_settings.json';
|
||||||
CFG_BAND_COUNT = 12;
|
CFG_BAND_COUNT = 12;
|
||||||
CFG_XVTR_COUNT = 8; // количество XVTR-слотов (трансверторов)
|
CFG_XVTR_COUNT = 8; // количество XVTR-слотов (трансверторов)
|
||||||
|
OC_PIN_COUNT = 7; // количество Open Collector выходов (Penny/Alex)
|
||||||
|
// TX pin action (byte-константы, как TXPinActions в Thetis Penny.cs):
|
||||||
|
// при каком состоянии передачи пин активен.
|
||||||
|
OCA_MOX = 0; // только обычный TX (не TUNE, не 2TON)
|
||||||
|
OCA_TUNE = 1; // только TUNE
|
||||||
|
OCA_TWOTONE = 2; // только 2TON
|
||||||
|
OCA_MOX_TUNE = 3; // TX или TUNE
|
||||||
|
OCA_MOX_TWOTONE = 4; // TX или 2TON
|
||||||
|
OCA_TUNE_TWOTONE = 5; // TUNE или 2TON
|
||||||
|
OCA_MOX_TUNE_TWOTONE = 6; // любое из трёх (дефолт)
|
||||||
CFG_MODE_MIN = RadioModes.MODE_MIN;
|
CFG_MODE_MIN = RadioModes.MODE_MIN;
|
||||||
CFG_MODE_MAX = RadioModes.MODE_MAX;
|
CFG_MODE_MAX = RadioModes.MODE_MAX;
|
||||||
CFG_PANS_MAX = 4; // потолок панадаптеров (пан 0 + доп.) — = WDSPEngine.MAX_PANS
|
CFG_PANS_MAX = 4; // потолок панадаптеров (пан 0 + доп.) — = WDSPEngine.MAX_PANS
|
||||||
@@ -341,6 +351,26 @@ type
|
|||||||
EnableXvtrHf: Boolean; // режим XVTR HF
|
EnableXvtrHf: Boolean; // режим XVTR HF
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
// OC Control (Open Collector выходы Penny/Alex, byte 1401 HP packet).
|
||||||
|
// Только openHPSDR — у AD936x (Pluto/LibreSDR) такого выхода нет.
|
||||||
|
// Хранятся в JSON-секции "oc" под MAC. Портировано из Thetis
|
||||||
|
// (Console/setup.cs UpdateOCBits + Console/HPSDR/Penny.cs), объём сокращён:
|
||||||
|
// без PA-override/hot-switching внешнего PA (в EWSDR нет такой концепции
|
||||||
|
// на панели) и без split-pins VFO A/B (у EWSDR мультислайсы).
|
||||||
|
// HF-группа — 11 диапазонов (0=160m..10=6m, как в TAlexSettings).
|
||||||
|
// VHF-группа — 8 слотов XVTR (аналог Thetis VHF0-13, но по нашим слотам).
|
||||||
|
TOCPinActions = array[0..OC_PIN_COUNT-1] of Byte; // OCA_* на пин
|
||||||
|
|
||||||
|
TOCSettings = record
|
||||||
|
Enabled: Boolean;
|
||||||
|
RxMaskHF: array[0..CFG_BAND_COUNT-1] of Byte; // 7-бит маска, биты 0..6 = пины 1..7
|
||||||
|
TxMaskHF: array[0..CFG_BAND_COUNT-1] of Byte;
|
||||||
|
ActionHF: TOCPinActions; // для HF TX-маски
|
||||||
|
RxMaskXvtr: array[0..CFG_XVTR_COUNT-1] of Byte;
|
||||||
|
TxMaskXvtr: array[0..CFG_XVTR_COUNT-1] of Byte;
|
||||||
|
ActionXvtr: TOCPinActions; // для XVTR TX-маски
|
||||||
|
end;
|
||||||
|
|
||||||
// Калибровки (вкладка Calibration): детектор мощности/КСВ Alex-моста,
|
// Калибровки (вкладка Calibration): детектор мощности/КСВ Alex-моста,
|
||||||
// напряжение/ток питания, S-метр. Модель детектора задаёт константы моста
|
// напряжение/ток питания, S-метр. Модель детектора задаёт константы моста
|
||||||
// (Vref/bridge_volt/ADC-offset, как в Thetis computeAlexFwdPower).
|
// (Vref/bridge_volt/ADC-offset, как в Thetis computeAlexFwdPower).
|
||||||
@@ -526,6 +556,10 @@ type
|
|||||||
class procedure DefaultAlex(out A: TAlexSettings);
|
class procedure DefaultAlex(out A: TAlexSettings);
|
||||||
function LoadAlex(const MAC: array of Byte; out A: TAlexSettings): Boolean;
|
function LoadAlex(const MAC: array of Byte; out A: TAlexSettings): Boolean;
|
||||||
procedure SaveAlex(const MAC: array of Byte; const A: TAlexSettings);
|
procedure SaveAlex(const MAC: array of Byte; const A: TAlexSettings);
|
||||||
|
// OC Control settings per-device (JSON-секция "oc" под MAC).
|
||||||
|
class procedure DefaultOC(out O: TOCSettings);
|
||||||
|
function LoadOC(const MAC: array of Byte; out O: TOCSettings): Boolean;
|
||||||
|
procedure SaveOC(const MAC: array of Byte; const O: TOCSettings);
|
||||||
// XVTR (Transverter) settings per-device (JSON-секция "xvtr" под MAC).
|
// XVTR (Transverter) settings per-device (JSON-секция "xvtr" под MAC).
|
||||||
class procedure DefaultXvtr(out X: TXvtrSettings);
|
class procedure DefaultXvtr(out X: TXvtrSettings);
|
||||||
function LoadXvtr(const MAC: array of Byte; out X: TXvtrSettings): Boolean;
|
function LoadXvtr(const MAC: array of Byte; out X: TXvtrSettings): Boolean;
|
||||||
@@ -1567,6 +1601,80 @@ begin
|
|||||||
A.EnableXvtrHf := JB(O, 'enable_xvtr_hf', False);
|
A.EnableXvtrHf := JB(O, 'enable_xvtr_hf', False);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
class procedure TSettingsManager.DefaultOC(out O: TOCSettings);
|
||||||
|
var i: Integer;
|
||||||
|
begin
|
||||||
|
FillChar(O, SizeOf(O), 0);
|
||||||
|
O.Enabled := False;
|
||||||
|
for i := 0 to CFG_BAND_COUNT - 1 do
|
||||||
|
begin
|
||||||
|
O.RxMaskHF[i] := 0;
|
||||||
|
O.TxMaskHF[i] := 0;
|
||||||
|
end;
|
||||||
|
for i := 0 to CFG_XVTR_COUNT - 1 do
|
||||||
|
begin
|
||||||
|
O.RxMaskXvtr[i] := 0;
|
||||||
|
O.TxMaskXvtr[i] := 0;
|
||||||
|
end;
|
||||||
|
for i := 0 to OC_PIN_COUNT - 1 do
|
||||||
|
begin
|
||||||
|
O.ActionHF[i] := OCA_MOX_TUNE_TWOTONE;
|
||||||
|
O.ActionXvtr[i] := OCA_MOX_TUNE_TWOTONE;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TSettingsManager.LoadOC(const MAC: array of Byte;
|
||||||
|
out O: TOCSettings): Boolean;
|
||||||
|
var MacStr: string; DevObj, Obj: TJSONObject; i: Integer;
|
||||||
|
begin
|
||||||
|
DefaultOC(O);
|
||||||
|
MacStr := MacToStr(MAC);
|
||||||
|
Result := FRoot.Find(MacStr) <> nil;
|
||||||
|
if not Result then Exit;
|
||||||
|
DevObj := GetDevObj(MacStr);
|
||||||
|
if DevObj.Find('oc') = nil then begin Result := False; Exit; end;
|
||||||
|
Obj := EnsureObj(DevObj, 'oc');
|
||||||
|
O.Enabled := JB(Obj, 'enabled', False);
|
||||||
|
for i := 0 to CFG_BAND_COUNT - 1 do
|
||||||
|
begin
|
||||||
|
O.RxMaskHF[i] := EnsureRange(JI(Obj, 'rx_hf_' + IntToStr(i), 0), 0, 127);
|
||||||
|
O.TxMaskHF[i] := EnsureRange(JI(Obj, 'tx_hf_' + IntToStr(i), 0), 0, 127);
|
||||||
|
end;
|
||||||
|
for i := 0 to CFG_XVTR_COUNT - 1 do
|
||||||
|
begin
|
||||||
|
O.RxMaskXvtr[i] := EnsureRange(JI(Obj, 'rx_xvtr_' + IntToStr(i), 0), 0, 127);
|
||||||
|
O.TxMaskXvtr[i] := EnsureRange(JI(Obj, 'tx_xvtr_' + IntToStr(i), 0), 0, 127);
|
||||||
|
end;
|
||||||
|
for i := 0 to OC_PIN_COUNT - 1 do
|
||||||
|
begin
|
||||||
|
O.ActionHF[i] := EnsureRange(JI(Obj, 'action_hf_' + IntToStr(i), OCA_MOX_TUNE_TWOTONE), 0, 6);
|
||||||
|
O.ActionXvtr[i] := EnsureRange(JI(Obj, 'action_xvtr_' + IntToStr(i), OCA_MOX_TUNE_TWOTONE), 0, 6);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TSettingsManager.SaveOC(const MAC: array of Byte;
|
||||||
|
const O: TOCSettings);
|
||||||
|
var Obj: TJSONObject; i: Integer;
|
||||||
|
begin
|
||||||
|
Obj := EnsureObj(GetDevObj(MacToStr(MAC)), 'oc');
|
||||||
|
JW(Obj, 'enabled', O.Enabled);
|
||||||
|
for i := 0 to CFG_BAND_COUNT - 1 do
|
||||||
|
begin
|
||||||
|
JW(Obj, 'rx_hf_' + IntToStr(i), Integer(O.RxMaskHF[i]));
|
||||||
|
JW(Obj, 'tx_hf_' + IntToStr(i), Integer(O.TxMaskHF[i]));
|
||||||
|
end;
|
||||||
|
for i := 0 to CFG_XVTR_COUNT - 1 do
|
||||||
|
begin
|
||||||
|
JW(Obj, 'rx_xvtr_' + IntToStr(i), Integer(O.RxMaskXvtr[i]));
|
||||||
|
JW(Obj, 'tx_xvtr_' + IntToStr(i), Integer(O.TxMaskXvtr[i]));
|
||||||
|
end;
|
||||||
|
for i := 0 to OC_PIN_COUNT - 1 do
|
||||||
|
begin
|
||||||
|
JW(Obj, 'action_hf_' + IntToStr(i), Integer(O.ActionHF[i]));
|
||||||
|
JW(Obj, 'action_xvtr_' + IntToStr(i), Integer(O.ActionXvtr[i]));
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
class procedure TSettingsManager.DefaultAnt936x(out A: TAD936xAnt);
|
class procedure TSettingsManager.DefaultAnt936x(out A: TAD936xAnt);
|
||||||
var i: Integer;
|
var i: Integer;
|
||||||
begin
|
begin
|
||||||
|
|||||||
+285
-1
@@ -85,6 +85,7 @@ type
|
|||||||
const InDev: array of string) of object;
|
const InDev: array of string) of object;
|
||||||
TOnAlexChange = procedure(const A: TAlexSettings) of object;
|
TOnAlexChange = procedure(const A: TAlexSettings) of object;
|
||||||
TOnXvtrChange = procedure(const X: TXvtrSettings) of object;
|
TOnXvtrChange = procedure(const X: TXvtrSettings) of object;
|
||||||
|
TOnOCChange = procedure(const O: TOCSettings) of object;
|
||||||
|
|
||||||
{ TSettingsForm }
|
{ TSettingsForm }
|
||||||
TSettingsForm = class(TForm)
|
TSettingsForm = class(TForm)
|
||||||
@@ -320,6 +321,26 @@ type
|
|||||||
FXvtrConfig: TXvtrSettings;
|
FXvtrConfig: TXvtrSettings;
|
||||||
FOnXvtrChange: TOnXvtrChange;
|
FOnXvtrChange: TOnXvtrChange;
|
||||||
|
|
||||||
|
// ---- OC Control tab (Open Collector выходы Penny/Alex, openHPSDR-only) ----
|
||||||
|
FPageOC: TScrollBox;
|
||||||
|
FNavOC: TFlatButton;
|
||||||
|
FOCSubtitle: TLabel;
|
||||||
|
FOCEnabled: TFlatCheckBox;
|
||||||
|
// HF-группа: 11 диапазонов (0=160m..10=6m) × 7 пинов, RX/TX-маски
|
||||||
|
FOCHFRx: array[0..10, 0..OC_PIN_COUNT-1] of TFlatCheckBox;
|
||||||
|
FOCHFTx: array[0..10, 0..OC_PIN_COUNT-1] of TFlatCheckBox;
|
||||||
|
FOCHFAction: array[0..OC_PIN_COUNT-1] of TFlatComboBox;
|
||||||
|
FOCHFGrp: TPanel;
|
||||||
|
FOCHFActGrp: TPanel;
|
||||||
|
// VHF-группа = 8 слотов XVTR × 7 пинов, RX/TX-маски
|
||||||
|
FOCXvtrRx: array[0..CFG_XVTR_COUNT-1, 0..OC_PIN_COUNT-1] of TFlatCheckBox;
|
||||||
|
FOCXvtrTx: array[0..CFG_XVTR_COUNT-1, 0..OC_PIN_COUNT-1] of TFlatCheckBox;
|
||||||
|
FOCXvtrAction: array[0..OC_PIN_COUNT-1] of TFlatComboBox;
|
||||||
|
FOCXvtrGrp: TPanel;
|
||||||
|
FOCXvtrActGrp: TPanel;
|
||||||
|
FOCConfig: TOCSettings;
|
||||||
|
FOnOCChange: TOnOCChange;
|
||||||
|
|
||||||
// ---- QO-100 tab (редактирует зарезервированный слот QO100_SLOT) ----
|
// ---- QO-100 tab (редактирует зарезервированный слот QO100_SLOT) ----
|
||||||
FPageQO: TScrollBox;
|
FPageQO: TScrollBox;
|
||||||
FNavQO: TFlatButton;
|
FNavQO: TFlatButton;
|
||||||
@@ -431,6 +452,10 @@ type
|
|||||||
procedure FireXvtrChange;
|
procedure FireXvtrChange;
|
||||||
procedure OnXvtrAnyChange(Sender: TObject);
|
procedure OnXvtrAnyChange(Sender: TObject);
|
||||||
procedure UpdateXvtrRowEnabled(Idx: Integer);
|
procedure UpdateXvtrRowEnabled(Idx: Integer);
|
||||||
|
procedure BuildOCTab;
|
||||||
|
procedure CollectOCFromUI;
|
||||||
|
procedure FireOCChange;
|
||||||
|
procedure OnOCAnyChange(Sender: TObject);
|
||||||
procedure CollectTXFromUI;
|
procedure CollectTXFromUI;
|
||||||
procedure FireTXChange;
|
procedure FireTXChange;
|
||||||
procedure OnTXAnyChange(Sender: TObject);
|
procedure OnTXAnyChange(Sender: TObject);
|
||||||
@@ -547,6 +572,9 @@ type
|
|||||||
procedure LoadTXSettings(const T: TTXSettings; BoardType: Integer = 0);
|
procedure LoadTXSettings(const T: TTXSettings; BoardType: Integer = 0);
|
||||||
procedure LoadAlexSettings(const A: TAlexSettings; BoardType: Integer);
|
procedure LoadAlexSettings(const A: TAlexSettings; BoardType: Integer);
|
||||||
procedure LoadXvtrSettings(const X: TXvtrSettings);
|
procedure LoadXvtrSettings(const X: TXvtrSettings);
|
||||||
|
procedure LoadOCSettings(const O: TOCSettings);
|
||||||
|
// Вкладка OC Control — только openHPSDR (у Pluto/AD936x нет такого выхода).
|
||||||
|
procedure SetOCBackend(IsPluto: Boolean);
|
||||||
procedure LoadWfAGCNF(AGC, NF: Boolean);
|
procedure LoadWfAGCNF(AGC, NF: Boolean);
|
||||||
procedure LoadWfRender(Palette: Integer; Gamma: Double;
|
procedure LoadWfRender(Palette: Integer; Gamma: Double;
|
||||||
ResLimit, SpeedDiv: Integer);
|
ResLimit, SpeedDiv: Integer);
|
||||||
@@ -559,6 +587,7 @@ type
|
|||||||
property OnSliceCATChange: TOnSliceCATChange read FOnSliceCATChange write FOnSliceCATChange;
|
property OnSliceCATChange: TOnSliceCATChange read FOnSliceCATChange write FOnSliceCATChange;
|
||||||
property OnAlexChange: TOnAlexChange read FOnAlexChange write FOnAlexChange;
|
property OnAlexChange: TOnAlexChange read FOnAlexChange write FOnAlexChange;
|
||||||
property OnXvtrChange: TOnXvtrChange read FOnXvtrChange write FOnXvtrChange;
|
property OnXvtrChange: TOnXvtrChange read FOnXvtrChange write FOnXvtrChange;
|
||||||
|
property OnOCChange: TOnOCChange read FOnOCChange write FOnOCChange;
|
||||||
property OnPAChange: TOnPASettingsChange read FOnPAChange write FOnPAChange;
|
property OnPAChange: TOnPASettingsChange read FOnPAChange write FOnPAChange;
|
||||||
property OnPlutoTxChange: TOnPlutoTxChange read FOnPlutoTxChange write FOnPlutoTxChange;
|
property OnPlutoTxChange: TOnPlutoTxChange read FOnPlutoTxChange write FOnPlutoTxChange;
|
||||||
property OnAnt936xChange: TOnAnt936xChange read FOnAnt936xChange write FOnAnt936xChange;
|
property OnAnt936xChange: TOnAnt936xChange read FOnAnt936xChange write FOnAnt936xChange;
|
||||||
@@ -643,6 +672,10 @@ const
|
|||||||
PA_BAND_NAMES: array[0..10] of string =
|
PA_BAND_NAMES: array[0..10] of string =
|
||||||
('160m','80m','60m','40m','30m','20m','17m','15m','12m','10m','6m');
|
('160m','80m','60m','40m','30m','20m','17m','15m','12m','10m','6m');
|
||||||
|
|
||||||
|
// TX pin action (OC Control) — имена в UI, значения = OCA_* из Settings.pas.
|
||||||
|
OC_ACTION_NAMES: array[0..6] of string = (
|
||||||
|
'MOX', 'TUNE', '2TON', 'MOX+TUNE', 'MOX+2TON', 'TUNE+2TON', 'MOX+TUNE+2TON');
|
||||||
|
|
||||||
// Раскладка вкладки Calibration — общая для построения (BuildCalibrationTab)
|
// Раскладка вкладки Calibration — общая для построения (BuildCalibrationTab)
|
||||||
// и перекладки под активное железо (RelayoutCalTab).
|
// и перекладки под активное железо (RelayoutCalTab).
|
||||||
CAL_MARGIN = 22;
|
CAL_MARGIN = 22;
|
||||||
@@ -818,7 +851,8 @@ begin
|
|||||||
FNavSlices := MakeNavButton('Slices', 398);
|
FNavSlices := MakeNavButton('Slices', 398);
|
||||||
FNavAlex := MakeNavButton('Antenna / Alex', 434);
|
FNavAlex := MakeNavButton('Antenna / Alex', 434);
|
||||||
FNavXvtr := MakeNavButton('Transverter', 470);
|
FNavXvtr := MakeNavButton('Transverter', 470);
|
||||||
FNavQO := MakeNavButton('QO-100', 506);
|
FNavOC := MakeNavButton('OC Control', 506);
|
||||||
|
FNavQO := MakeNavButton('QO-100', 542);
|
||||||
|
|
||||||
FContentPanel := TPanel.Create(Self);
|
FContentPanel := TPanel.Create(Self);
|
||||||
FContentPanel.Parent := Self;
|
FContentPanel.Parent := Self;
|
||||||
@@ -838,11 +872,13 @@ begin
|
|||||||
FPageSlices := MakeScrollPage;
|
FPageSlices := MakeScrollPage;
|
||||||
FPageAlex := MakeScrollPage;
|
FPageAlex := MakeScrollPage;
|
||||||
FPageXvtr := MakeScrollPage;
|
FPageXvtr := MakeScrollPage;
|
||||||
|
FPageOC := MakeScrollPage;
|
||||||
FPageQO := MakeScrollPage;
|
FPageQO := MakeScrollPage;
|
||||||
FAlexBoardType := 0;
|
FAlexBoardType := 0;
|
||||||
TSettingsManager.DefaultAlex(FAlexConfig);
|
TSettingsManager.DefaultAlex(FAlexConfig);
|
||||||
TSettingsManager.DefaultXvtr(FXvtrConfig);
|
TSettingsManager.DefaultXvtr(FXvtrConfig);
|
||||||
TSettingsManager.DefaultCalibration(FCalConfig);
|
TSettingsManager.DefaultCalibration(FCalConfig);
|
||||||
|
TSettingsManager.DefaultOC(FOCConfig);
|
||||||
|
|
||||||
BuildAudioTab;
|
BuildAudioTab;
|
||||||
BuildDisplayTab;
|
BuildDisplayTab;
|
||||||
@@ -855,6 +891,7 @@ begin
|
|||||||
BuildSlicesTab;
|
BuildSlicesTab;
|
||||||
BuildAlexTab;
|
BuildAlexTab;
|
||||||
BuildXvtrTab;
|
BuildXvtrTab;
|
||||||
|
BuildOCTab;
|
||||||
BuildQOTab;
|
BuildQOTab;
|
||||||
|
|
||||||
FBtnClose := TFlatButton.Create(Self);
|
FBtnClose := TFlatButton.Create(Self);
|
||||||
@@ -889,6 +926,7 @@ begin
|
|||||||
else if Sender = FNavSlices then SelectPage(FPageSlices, FNavSlices)
|
else if Sender = FNavSlices then SelectPage(FPageSlices, FNavSlices)
|
||||||
else if Sender = FNavAlex then SelectPage(FPageAlex, FNavAlex)
|
else if Sender = FNavAlex then SelectPage(FPageAlex, FNavAlex)
|
||||||
else if Sender = FNavXvtr then SelectPage(FPageXvtr, FNavXvtr)
|
else if Sender = FNavXvtr then SelectPage(FPageXvtr, FNavXvtr)
|
||||||
|
else if Sender = FNavOC then SelectPage(FPageOC, FNavOC)
|
||||||
else if Sender = FNavQO then SelectPage(FPageQO, FNavQO);
|
else if Sender = FNavQO then SelectPage(FPageQO, FNavQO);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@@ -906,6 +944,7 @@ begin
|
|||||||
FPageSlices.Visible := APage = FPageSlices;
|
FPageSlices.Visible := APage = FPageSlices;
|
||||||
FPageAlex.Visible := APage = FPageAlex;
|
FPageAlex.Visible := APage = FPageAlex;
|
||||||
FPageXvtr.Visible := APage = FPageXvtr;
|
FPageXvtr.Visible := APage = FPageXvtr;
|
||||||
|
FPageOC.Visible := APage = FPageOC;
|
||||||
FPageQO.Visible := APage = FPageQO;
|
FPageQO.Visible := APage = FPageQO;
|
||||||
|
|
||||||
FNavAudio.Active := ANav = FNavAudio;
|
FNavAudio.Active := ANav = FNavAudio;
|
||||||
@@ -920,6 +959,7 @@ begin
|
|||||||
FNavSlices.Active := ANav = FNavSlices;
|
FNavSlices.Active := ANav = FNavSlices;
|
||||||
FNavAlex.Active := ANav = FNavAlex;
|
FNavAlex.Active := ANav = FNavAlex;
|
||||||
FNavXvtr.Active := ANav = FNavXvtr;
|
FNavXvtr.Active := ANav = FNavXvtr;
|
||||||
|
FNavOC.Active := ANav = FNavOC;
|
||||||
FNavQO.Active := ANav = FNavQO;
|
FNavQO.Active := ANav = FNavQO;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@@ -4658,6 +4698,250 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
// ===========================================================================
|
||||||
|
// OC Control tab (Open Collector выходы Penny/Alex, byte 1401 HP-пакета).
|
||||||
|
// Портировано из Thetis (Console/setup.cs UpdateOCBits + Console/HPSDR/
|
||||||
|
// Penny.cs), объём сокращён — см. память project_oc_control: без PA-override/
|
||||||
|
// hot-switching внешнего PA и без split-pins VFO A/B. Только openHPSDR —
|
||||||
|
// вкладка целиком прячется на Pluto/AD936x (SetOCBackend).
|
||||||
|
// HF-группа = 11 диапазонов (как Alex/PA), VHF-группа = 8 слотов XVTR.
|
||||||
|
// ===========================================================================
|
||||||
|
|
||||||
|
procedure TSettingsForm.BuildOCTab;
|
||||||
|
const
|
||||||
|
MARGIN = 22;
|
||||||
|
PAD = 12;
|
||||||
|
HDR1_H = 22;
|
||||||
|
HDR2_H = 20;
|
||||||
|
ROW_H = 24;
|
||||||
|
PIN_W = 24;
|
||||||
|
BAND_X = PAD;
|
||||||
|
RX0_X = PAD + 50;
|
||||||
|
TX0_X = RX0_X + OC_PIN_COUNT * PIN_W + 20;
|
||||||
|
GRP_W = TX0_X + OC_PIN_COUNT * PIN_W + PAD;
|
||||||
|
DATA_Y0 = GRP_TITLE_H + HDR1_H + HDR2_H + 4;
|
||||||
|
HF_GRP_H = GRP_TITLE_H + HDR1_H + HDR2_H + 11 * ROW_H + PAD;
|
||||||
|
XVTR_GRP_H = GRP_TITLE_H + HDR1_H + HDR2_H + CFG_XVTR_COUNT * ROW_H + PAD;
|
||||||
|
ACT_ROW_H = 30;
|
||||||
|
ACT_GRP_W = 260;
|
||||||
|
ACT_GRP_H = GRP_TITLE_H + PAD + OC_PIN_COUNT * ACT_ROW_H;
|
||||||
|
|
||||||
|
HF_BAND_NAMES: array[0..10] of string =
|
||||||
|
('160m','80m','60m','40m','30m','20m','17m','15m','12m','10m','6m');
|
||||||
|
|
||||||
|
var
|
||||||
|
Grp, ActGrp: TPanel;
|
||||||
|
b, p: Integer;
|
||||||
|
Y: Integer;
|
||||||
|
Cmb: TFlatComboBox;
|
||||||
|
|
||||||
|
function MkChk(AParent: TWinControl; AX, AY: Integer): TFlatCheckBox;
|
||||||
|
begin
|
||||||
|
Result := TFlatCheckBox.Create(Self);
|
||||||
|
Result.Parent := AParent;
|
||||||
|
Result.Caption := '';
|
||||||
|
Result.SetBounds(AX, AY, PIN_W, 20);
|
||||||
|
Result.Font.Color := CLR_TEXT;
|
||||||
|
Result.Font.Name := UI_FONT;
|
||||||
|
Result.Font.Size := 9;
|
||||||
|
Result.OnChange := OnOCAnyChange;
|
||||||
|
end;
|
||||||
|
|
||||||
|
begin
|
||||||
|
FLoading := True;
|
||||||
|
try
|
||||||
|
with TLabel.Create(Self) do
|
||||||
|
begin
|
||||||
|
Parent := FPageOC;
|
||||||
|
Caption := 'OC Control';
|
||||||
|
SetBounds(MARGIN, 18, 500, 28);
|
||||||
|
Font.Name := UI_FONT; Font.Size := 16;
|
||||||
|
Font.Style := [fsBold]; Font.Color := CLR_TEXT;
|
||||||
|
end;
|
||||||
|
FOCSubtitle := TLabel.Create(Self);
|
||||||
|
FOCSubtitle.Parent := FPageOC;
|
||||||
|
FOCSubtitle.Caption :=
|
||||||
|
'Open Collector outputs (Penny/Alex board), per-band and per-transverter. openHPSDR only.';
|
||||||
|
FOCSubtitle.SetBounds(MARGIN, 48, 680, 20);
|
||||||
|
FOCSubtitle.Font.Name := UI_FONT;
|
||||||
|
FOCSubtitle.Font.Size := 9;
|
||||||
|
FOCSubtitle.Font.Color := CLR_TEXTDIM;
|
||||||
|
|
||||||
|
FOCEnabled := TFlatCheckBox.Create(Self);
|
||||||
|
FOCEnabled.Parent := FPageOC;
|
||||||
|
FOCEnabled.Caption := 'Enable OC Control';
|
||||||
|
FOCEnabled.SetBounds(MARGIN, 76, 220, 22);
|
||||||
|
FOCEnabled.Font.Color := CLR_TEXT;
|
||||||
|
FOCEnabled.Font.Name := UI_FONT;
|
||||||
|
FOCEnabled.Font.Size := 9;
|
||||||
|
FOCEnabled.OnChange := OnOCAnyChange;
|
||||||
|
|
||||||
|
// ---- HF band grid ----
|
||||||
|
Grp := MakeGroupPanel(FPageOC, 'HF Bands', MARGIN, 106, GRP_W, HF_GRP_H);
|
||||||
|
FOCHFGrp := Grp;
|
||||||
|
MakeLbl(Grp, 'Band', BAND_X, GRP_TITLE_H + 2, 44);
|
||||||
|
MakeLbl(Grp, 'RX pins', RX0_X, GRP_TITLE_H + 2, OC_PIN_COUNT * PIN_W);
|
||||||
|
MakeLbl(Grp, 'TX pins', TX0_X, GRP_TITLE_H + 2, OC_PIN_COUNT * PIN_W);
|
||||||
|
for p := 0 to OC_PIN_COUNT - 1 do
|
||||||
|
begin
|
||||||
|
MakeLbl(Grp, IntToStr(p + 1), RX0_X + p * PIN_W + 5, GRP_TITLE_H + HDR1_H + 2, PIN_W);
|
||||||
|
MakeLbl(Grp, IntToStr(p + 1), TX0_X + p * PIN_W + 5, GRP_TITLE_H + HDR1_H + 2, PIN_W);
|
||||||
|
end;
|
||||||
|
for b := 0 to 10 do
|
||||||
|
begin
|
||||||
|
Y := DATA_Y0 + b * ROW_H;
|
||||||
|
MakeLbl(Grp, HF_BAND_NAMES[b], BAND_X, Y + 2, 44);
|
||||||
|
for p := 0 to OC_PIN_COUNT - 1 do
|
||||||
|
begin
|
||||||
|
FOCHFRx[b, p] := MkChk(Grp, RX0_X + p * PIN_W, Y);
|
||||||
|
FOCHFTx[b, p] := MkChk(Grp, TX0_X + p * PIN_W, Y);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
// ---- HF TX pin action ----
|
||||||
|
ActGrp := MakeGroupPanel(FPageOC, 'HF TX Pin Action',
|
||||||
|
MARGIN + GRP_W + 14, 106, ACT_GRP_W, ACT_GRP_H);
|
||||||
|
FOCHFActGrp := ActGrp;
|
||||||
|
for p := 0 to OC_PIN_COUNT - 1 do
|
||||||
|
begin
|
||||||
|
MakeLbl(ActGrp, 'Pin ' + IntToStr(p + 1), PAD, GRP_TITLE_H + PAD + p * ACT_ROW_H + 5, 44);
|
||||||
|
Cmb := MakeCombo(ActGrp, PAD + 50, GRP_TITLE_H + PAD + p * ACT_ROW_H, 190, OnOCAnyChange);
|
||||||
|
for b := 0 to 6 do Cmb.Items.Add(OC_ACTION_NAMES[b]);
|
||||||
|
Cmb.ItemIndex := OCA_MOX_TUNE_TWOTONE;
|
||||||
|
FOCHFAction[p] := Cmb;
|
||||||
|
end;
|
||||||
|
|
||||||
|
// ---- XVTR (VHF) slot grid ----
|
||||||
|
Grp := MakeGroupPanel(FPageOC, 'Transverter Slots', MARGIN, 106 + HF_GRP_H + 14,
|
||||||
|
GRP_W, XVTR_GRP_H);
|
||||||
|
FOCXvtrGrp := Grp;
|
||||||
|
MakeLbl(Grp, 'Slot', BAND_X, GRP_TITLE_H + 2, 44);
|
||||||
|
MakeLbl(Grp, 'RX pins', RX0_X, GRP_TITLE_H + 2, OC_PIN_COUNT * PIN_W);
|
||||||
|
MakeLbl(Grp, 'TX pins', TX0_X, GRP_TITLE_H + 2, OC_PIN_COUNT * PIN_W);
|
||||||
|
for p := 0 to OC_PIN_COUNT - 1 do
|
||||||
|
begin
|
||||||
|
MakeLbl(Grp, IntToStr(p + 1), RX0_X + p * PIN_W + 5, GRP_TITLE_H + HDR1_H + 2, PIN_W);
|
||||||
|
MakeLbl(Grp, IntToStr(p + 1), TX0_X + p * PIN_W + 5, GRP_TITLE_H + HDR1_H + 2, PIN_W);
|
||||||
|
end;
|
||||||
|
for b := 0 to CFG_XVTR_COUNT - 1 do
|
||||||
|
begin
|
||||||
|
Y := DATA_Y0 + b * ROW_H;
|
||||||
|
MakeLbl(Grp, 'XVTR' + IntToStr(b + 1), BAND_X, Y + 2, 48);
|
||||||
|
for p := 0 to OC_PIN_COUNT - 1 do
|
||||||
|
begin
|
||||||
|
FOCXvtrRx[b, p] := MkChk(Grp, RX0_X + p * PIN_W, Y);
|
||||||
|
FOCXvtrTx[b, p] := MkChk(Grp, TX0_X + p * PIN_W, Y);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
// ---- XVTR TX pin action ----
|
||||||
|
ActGrp := MakeGroupPanel(FPageOC, 'Transverter TX Pin Action',
|
||||||
|
MARGIN + GRP_W + 14, 106 + HF_GRP_H + 14, ACT_GRP_W, ACT_GRP_H);
|
||||||
|
FOCXvtrActGrp := ActGrp;
|
||||||
|
for p := 0 to OC_PIN_COUNT - 1 do
|
||||||
|
begin
|
||||||
|
MakeLbl(ActGrp, 'Pin ' + IntToStr(p + 1), PAD, GRP_TITLE_H + PAD + p * ACT_ROW_H + 5, 44);
|
||||||
|
Cmb := MakeCombo(ActGrp, PAD + 50, GRP_TITLE_H + PAD + p * ACT_ROW_H, 190, OnOCAnyChange);
|
||||||
|
for b := 0 to 6 do Cmb.Items.Add(OC_ACTION_NAMES[b]);
|
||||||
|
Cmb.ItemIndex := OCA_MOX_TUNE_TWOTONE;
|
||||||
|
FOCXvtrAction[p] := Cmb;
|
||||||
|
end;
|
||||||
|
finally
|
||||||
|
FLoading := False;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TSettingsForm.CollectOCFromUI;
|
||||||
|
var b, p: Integer; Mask: Byte;
|
||||||
|
begin
|
||||||
|
FOCConfig.Enabled := (FOCEnabled <> nil) and FOCEnabled.Checked;
|
||||||
|
for b := 0 to 10 do
|
||||||
|
begin
|
||||||
|
Mask := 0;
|
||||||
|
for p := 0 to OC_PIN_COUNT - 1 do
|
||||||
|
if (FOCHFRx[b, p] <> nil) and FOCHFRx[b, p].Checked then Mask := Mask or (1 shl p);
|
||||||
|
FOCConfig.RxMaskHF[b] := Mask;
|
||||||
|
Mask := 0;
|
||||||
|
for p := 0 to OC_PIN_COUNT - 1 do
|
||||||
|
if (FOCHFTx[b, p] <> nil) and FOCHFTx[b, p].Checked then Mask := Mask or (1 shl p);
|
||||||
|
FOCConfig.TxMaskHF[b] := Mask;
|
||||||
|
end;
|
||||||
|
for b := 0 to CFG_XVTR_COUNT - 1 do
|
||||||
|
begin
|
||||||
|
Mask := 0;
|
||||||
|
for p := 0 to OC_PIN_COUNT - 1 do
|
||||||
|
if (FOCXvtrRx[b, p] <> nil) and FOCXvtrRx[b, p].Checked then Mask := Mask or (1 shl p);
|
||||||
|
FOCConfig.RxMaskXvtr[b] := Mask;
|
||||||
|
Mask := 0;
|
||||||
|
for p := 0 to OC_PIN_COUNT - 1 do
|
||||||
|
if (FOCXvtrTx[b, p] <> nil) and FOCXvtrTx[b, p].Checked then Mask := Mask or (1 shl p);
|
||||||
|
FOCConfig.TxMaskXvtr[b] := Mask;
|
||||||
|
end;
|
||||||
|
for p := 0 to OC_PIN_COUNT - 1 do
|
||||||
|
begin
|
||||||
|
if (FOCHFAction[p] <> nil) and (FOCHFAction[p].ItemIndex >= 0) then
|
||||||
|
FOCConfig.ActionHF[p] := Byte(FOCHFAction[p].ItemIndex);
|
||||||
|
if (FOCXvtrAction[p] <> nil) and (FOCXvtrAction[p].ItemIndex >= 0) then
|
||||||
|
FOCConfig.ActionXvtr[p] := Byte(FOCXvtrAction[p].ItemIndex);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TSettingsForm.FireOCChange;
|
||||||
|
begin
|
||||||
|
if FLoading then Exit;
|
||||||
|
CollectOCFromUI;
|
||||||
|
if Assigned(FOnOCChange) then
|
||||||
|
FOnOCChange(FOCConfig);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TSettingsForm.OnOCAnyChange(Sender: TObject);
|
||||||
|
begin
|
||||||
|
FireOCChange;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TSettingsForm.LoadOCSettings(const O: TOCSettings);
|
||||||
|
var b, p: Integer;
|
||||||
|
begin
|
||||||
|
FLoading := True;
|
||||||
|
try
|
||||||
|
FOCConfig := O;
|
||||||
|
if FOCEnabled <> nil then FOCEnabled.Checked := O.Enabled;
|
||||||
|
for b := 0 to 10 do
|
||||||
|
for p := 0 to OC_PIN_COUNT - 1 do
|
||||||
|
begin
|
||||||
|
if FOCHFRx[b, p] <> nil then
|
||||||
|
FOCHFRx[b, p].Checked := (O.RxMaskHF[b] and (1 shl p)) <> 0;
|
||||||
|
if FOCHFTx[b, p] <> nil then
|
||||||
|
FOCHFTx[b, p].Checked := (O.TxMaskHF[b] and (1 shl p)) <> 0;
|
||||||
|
end;
|
||||||
|
for b := 0 to CFG_XVTR_COUNT - 1 do
|
||||||
|
for p := 0 to OC_PIN_COUNT - 1 do
|
||||||
|
begin
|
||||||
|
if FOCXvtrRx[b, p] <> nil then
|
||||||
|
FOCXvtrRx[b, p].Checked := (O.RxMaskXvtr[b] and (1 shl p)) <> 0;
|
||||||
|
if FOCXvtrTx[b, p] <> nil then
|
||||||
|
FOCXvtrTx[b, p].Checked := (O.TxMaskXvtr[b] and (1 shl p)) <> 0;
|
||||||
|
end;
|
||||||
|
for p := 0 to OC_PIN_COUNT - 1 do
|
||||||
|
begin
|
||||||
|
if FOCHFAction[p] <> nil then FOCHFAction[p].ItemIndex := EnsureRange(O.ActionHF[p], 0, 6);
|
||||||
|
if FOCXvtrAction[p] <> nil then FOCXvtrAction[p].ItemIndex := EnsureRange(O.ActionXvtr[p], 0, 6);
|
||||||
|
end;
|
||||||
|
finally
|
||||||
|
FLoading := False;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TSettingsForm.SetOCBackend(IsPluto: Boolean);
|
||||||
|
// У Pluto/AD936x нет Open Collector выхода — вкладка целиком скрывается,
|
||||||
|
// а не показывает пустое содержимое (в отличие от Antenna, где Pluto имеет
|
||||||
|
// свою таблицу разъёмов).
|
||||||
|
begin
|
||||||
|
FNavOC.Visible := not IsPluto;
|
||||||
|
if IsPluto and (FPageOC.Visible) then
|
||||||
|
SelectPage(FPageAudio, FNavAudio);
|
||||||
|
end;
|
||||||
|
|
||||||
// ── QO-100 page ─────────────────────────────────────────────────────────────
|
// ── QO-100 page ─────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
procedure TSettingsForm.BuildQOTab;
|
procedure TSettingsForm.BuildQOTab;
|
||||||
|
|||||||
@@ -17,9 +17,9 @@
|
|||||||
<UseVersionInfo Value="True"/>
|
<UseVersionInfo Value="True"/>
|
||||||
<AutoIncrementBuild Value="True"/>
|
<AutoIncrementBuild Value="True"/>
|
||||||
<MinorVersionNr Value="9"/>
|
<MinorVersionNr Value="9"/>
|
||||||
<BuildNr Value="286"/>
|
<BuildNr Value="287"/>
|
||||||
</VersionInfo>
|
</VersionInfo>
|
||||||
<MacroValues Count="119">
|
<MacroValues Count="120">
|
||||||
<Macro1 Name="LCLWidgetType" Value="qt6"/>
|
<Macro1 Name="LCLWidgetType" Value="qt6"/>
|
||||||
<Macro2 Name="LCLWidgetType" Value="qt6"/>
|
<Macro2 Name="LCLWidgetType" Value="qt6"/>
|
||||||
<Macro3 Name="LCLWidgetType" Value="qt6"/>
|
<Macro3 Name="LCLWidgetType" Value="qt6"/>
|
||||||
@@ -139,6 +139,7 @@
|
|||||||
<Macro117 Name="LCLWidgetType" Value="qt6"/>
|
<Macro117 Name="LCLWidgetType" Value="qt6"/>
|
||||||
<Macro118 Name="LCLWidgetType" Value="qt6"/>
|
<Macro118 Name="LCLWidgetType" Value="qt6"/>
|
||||||
<Macro119 Name="LCLWidgetType" Value="qt6"/>
|
<Macro119 Name="LCLWidgetType" Value="qt6"/>
|
||||||
|
<Macro120 Name="LCLWidgetType" Value="qt6"/>
|
||||||
</MacroValues>
|
</MacroValues>
|
||||||
<BuildModes>
|
<BuildModes>
|
||||||
<Item Name="Debug" Default="True"/>
|
<Item Name="Debug" Default="True"/>
|
||||||
|
|||||||
Reference in New Issue
Block a user