mirror of
https://git.vladimir.cc/vladimir/ewsdr.git
synced 2026-08-25 18:43:51 +00:00
DUP (display duplex) + ATT on TX
- DUP: локальный режим отображения, при TX данные RX1, поверх рисуется TX-фильтр. Кнопка на левой панели рядом с CTUN. Аппаратной командой не является. Отдельный SetDisplaySourceTX в WDSPEngine, разделение TXMode (data) и TXOverlay (filter band) в SpectrumView. - ATT on TX: 0..31 dB, default 31 (Thetis-style). UI на вкладке Transmit в группе Microphone. Передаётся в DUC Specific bytes 57/58/59 (StepAtten0/1/2). Перепосылается при изменении.
This commit is contained in:
+67
-4
@@ -182,6 +182,9 @@ type
|
||||
FRunning: Boolean;
|
||||
FTransmitting: Boolean;
|
||||
FSplitTxB: Boolean;
|
||||
// DUP: при TX продолжаем показывать RX1-водопад/панораму, а TX-фильтр
|
||||
// и TX-линии рисуем поверх. Аппаратной командой не является.
|
||||
FDisplayDuplex: Boolean;
|
||||
FHWPTTActive: Boolean; // True = hardware PTT нажата
|
||||
FMuted: Boolean;
|
||||
FVolume: Integer;
|
||||
@@ -304,6 +307,7 @@ type
|
||||
PanelFilter: TPanel;
|
||||
BtnFilter: array[0..FILT_COUNT-1] of TFlatButton;
|
||||
BtnCTun: TFlatButton;
|
||||
BtnDUP: TFlatButton;
|
||||
|
||||
PanelRX: TPanel;
|
||||
BtnAGCMode: array[0..4] of TFlatButton; // FAST MED SLOW LONG OFF
|
||||
@@ -413,6 +417,8 @@ type
|
||||
procedure BtnModeClick(Sender: TObject);
|
||||
procedure BtnFilterClick(Sender: TObject);
|
||||
procedure BtnCTunClick(Sender: TObject);
|
||||
procedure BtnDUPClick(Sender: TObject);
|
||||
procedure ApplyDUP(Active: Boolean);
|
||||
procedure UpdateFilterButtons;
|
||||
procedure PbSpectrumMouseDown(Sender: TObject; Button: TMouseButton;
|
||||
Shift: TShiftState; X, Y: Integer);
|
||||
@@ -863,6 +869,7 @@ begin
|
||||
Result.AudioSampleRate := FAudioOut.SampleRate;
|
||||
Result.ShowSpectrum := FShowSpectrum;
|
||||
Result.ShowWaterfall := FShowWaterfall;
|
||||
Result.DisplayDuplex := FDisplayDuplex;
|
||||
Result.DisplayFPS := FDisplayFPS;
|
||||
Result.LightTheme := FLightTheme;
|
||||
// Audio device names
|
||||
@@ -987,6 +994,7 @@ begin
|
||||
FRunning := False;
|
||||
FTransmitting := False;
|
||||
FSplitTxB := False;
|
||||
FDisplayDuplex := False;
|
||||
FMuted := False;
|
||||
FVolume := 70;
|
||||
FCenterFreq := FVfoA;
|
||||
@@ -1541,11 +1549,16 @@ begin
|
||||
|
||||
Inc(Y, 76);
|
||||
|
||||
// CTUN button
|
||||
// CTUN / DUP buttons (display-related)
|
||||
BtnCTun := MakeBtn(PanelLeft, 'CTUN', 2, Y, LEFT_W div 3 - 2, BTN_H, BtnCTunClick);
|
||||
BtnCTun.Tag := 0;
|
||||
StyleButton(BtnCTun, FCTun);
|
||||
|
||||
BtnDUP := MakeBtn(PanelLeft, 'DUP',
|
||||
2 + (LEFT_W div 3) + 0, Y, LEFT_W div 3 - 2, BTN_H, BtnDUPClick);
|
||||
BtnDUP.Tag := 0;
|
||||
StyleButton(BtnDUP, FDisplayDuplex);
|
||||
|
||||
Inc(Y, BTN_H + 4);
|
||||
|
||||
// RX controls
|
||||
@@ -2215,6 +2228,7 @@ begin
|
||||
for i := 0 to FILT_COUNT-1 do StyleButton(BtnFilter[i], BtnFilter[i].Active);
|
||||
for i := 0 to 4 do StyleButton(BtnAGCMode[i],BtnAGCMode[i].Active);
|
||||
StyleButton(BtnCTun, BtnCTun.Active);
|
||||
StyleButton(BtnDUP, BtnDUP.Active);
|
||||
StyleButton(BtnNR, BtnNR.Active);
|
||||
StyleButton(BtnNB, BtnNB.Active);
|
||||
StyleButton(BtnSNB, BtnSNB.Active);
|
||||
@@ -2910,6 +2924,12 @@ begin
|
||||
DUCPkt.DUC0RateLo := Lo(RateKsps);
|
||||
DUCPkt.DUC0Bits := 24;
|
||||
DUCPkt.MicLineSelect := BuildMicLineSelectByte;
|
||||
// ATT on TX — RX-ADC step attenuator во время передачи (Thetis-style protection).
|
||||
// Дублируем значение во все три ADC-байта: на однопотоковых платах активен только
|
||||
// ADC0, на Saturn/Hermes Lite 2 — могут использоваться ADC1/ADC2.
|
||||
DUCPkt.StepAtten0 := Byte(EnsureRange(FTXSettings.AttOnTX, 0, 31));
|
||||
DUCPkt.StepAtten1 := DUCPkt.StepAtten0;
|
||||
DUCPkt.StepAtten2 := DUCPkt.StepAtten0;
|
||||
FNetwork.SendDUCSpecific(DUCPkt);
|
||||
end;
|
||||
|
||||
@@ -3352,6 +3372,8 @@ begin
|
||||
FSpecView.ResetWfAvgBuf;
|
||||
FShowSpectrum := G_Settings.ShowSpectrum;
|
||||
FShowWaterfall := G_Settings.ShowWaterfall;
|
||||
FDisplayDuplex := G_Settings.DisplayDuplex;
|
||||
if BtnDUP <> nil then StyleButton(BtnDUP, FDisplayDuplex);
|
||||
if G_Settings.DisplayFPS > 0 then
|
||||
ApplyFPS(G_Settings.DisplayFPS);
|
||||
// Настройки дисплея и сетки
|
||||
@@ -3866,6 +3888,35 @@ begin
|
||||
PbWaterfall.Invalidate;
|
||||
end;
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// DUP toggle (Thetis-style local display mode — без аппаратной команды)
|
||||
// ---------------------------------------------------------------------------
|
||||
procedure TMainForm.ApplyDUP(Active: Boolean);
|
||||
begin
|
||||
FDisplayDuplex := Active;
|
||||
StyleButton(BtnDUP, FDisplayDuplex);
|
||||
// Если сейчас идёт передача — переключаем источник пикселей и сбрасываем
|
||||
// буферы, чтобы старые TX/RX bin'ы не оставались на следующем кадре.
|
||||
if FTransmitting then
|
||||
begin
|
||||
if FWDSPReady then
|
||||
FDSPEngine.SetDisplaySourceTX(not FDisplayDuplex);
|
||||
FSpecView.TXMode := FTransmitting and not FDisplayDuplex;
|
||||
FSpecView.ResetSpectrumBuf;
|
||||
FSpecView.ResetWfAvgBuf;
|
||||
ApplySpecViewGridFromState;
|
||||
FSpecView.DrawSpectrum;
|
||||
FSpecView.DrawWaterfall;
|
||||
PbSpectrum.Invalidate;
|
||||
PbWaterfall.Invalidate;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TMainForm.BtnDUPClick(Sender: TObject);
|
||||
begin
|
||||
ApplyDUP(not FDisplayDuplex);
|
||||
end;
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Клик/драг по спектру/водопаду
|
||||
// ---------------------------------------------------------------------------
|
||||
@@ -4261,11 +4312,20 @@ begin
|
||||
FSpecView.TXFreq := ActiveTXFreqHz;
|
||||
if FSplitTxB then FSpecView.TXVfoIndex := 1
|
||||
else FSpecView.TXVfoIndex := FActiveVfo;
|
||||
FSpecView.TXMode := FTransmitting;
|
||||
// DUP: данные остаются от RX-анализатора (TXMode=False), но TX-полоса
|
||||
// фильтра рисуется поверх через TXOverlay. Без DUP при TX оба флага True.
|
||||
FSpecView.TXMode := FTransmitting and not FDisplayDuplex;
|
||||
FSpecView.TXOverlay := FTransmitting;
|
||||
// Перерисовываем сетку спектра под активный тракт (Thetis-style).
|
||||
ApplySpecViewGridFromState;
|
||||
if FWDSPReady then
|
||||
begin
|
||||
FDSPEngine.SetTXRun(FTransmitting);
|
||||
// SetTXRun переключает FActiveDisplayID на TX_DISP_ID; при DUP возвращаем
|
||||
// источник на RX, чтобы видеть приём во время передачи.
|
||||
if FTransmitting and FDisplayDuplex then
|
||||
FDSPEngine.SetDisplaySourceTX(False);
|
||||
end;
|
||||
if FNetwork.Connected and FNetwork.Running then
|
||||
begin
|
||||
FNetwork.UpdateState(FCenterFreq, ActiveTXFreqHz, FDriveLevel,
|
||||
@@ -5029,9 +5089,11 @@ procedure TMainForm.OnTXSettingsChange(const T: TTXSettings);
|
||||
// перешиваем WDSP TX-цепь и (если поменялись mic-биты) перепосылаем DUC Specific.
|
||||
var
|
||||
OldMicByte, NewMicByte: Byte;
|
||||
OldAtt: Integer;
|
||||
GridChanged: Boolean;
|
||||
begin
|
||||
OldMicByte := BuildMicLineSelectByte;
|
||||
OldAtt := FTXSettings.AttOnTX;
|
||||
GridChanged := (FTXSpecRefLevel <> T.TXSpecRefLevel)
|
||||
or (FTXSpecRange <> T.TXSpecRange)
|
||||
or (FTXSpecGridStep <> T.TXSpecGridStep);
|
||||
@@ -5045,7 +5107,7 @@ begin
|
||||
if GridChanged and FTransmitting then
|
||||
ApplySpecViewGridFromState;
|
||||
ApplyTXSettingsToDSP;
|
||||
if OldMicByte <> NewMicByte then
|
||||
if (OldMicByte <> NewMicByte) or (OldAtt <> FTXSettings.AttOnTX) then
|
||||
SendDUCSpecificFromSettings;
|
||||
// Сохраняем сразу — настройки per-device, попадают в hpsdr_settings.json
|
||||
if FDevConnected then
|
||||
@@ -5226,7 +5288,8 @@ end;
|
||||
|
||||
procedure TMainForm.ApplySpecViewGridFromState;
|
||||
begin
|
||||
if FTransmitting then
|
||||
// При DUP во время TX данные приходят от RX-анализатора → используем RX-сетку.
|
||||
if FTransmitting and not FDisplayDuplex then
|
||||
begin
|
||||
FSpecView.SpecRefLevel := FTXSpecRefLevel;
|
||||
FSpecView.SpecRange := FTXSpecRange;
|
||||
|
||||
Reference in New Issue
Block a user