From e5451b7843c399453923b8f29331e110728ec19d Mon Sep 17 00:00:00 2001 From: Vladimir Date: Tue, 14 Jul 2026 20:31:21 +0300 Subject: [PATCH] fix(dmr): prevent TX selection on receive slices --- RadioController.pas | 11 ++++++++++- VfoOverlay.pas | 22 +++++++++++++++++----- 2 files changed, 27 insertions(+), 6 deletions(-) diff --git a/RadioController.pas b/RadioController.pas index 562024f..d0e1753 100644 --- a/RadioController.pas +++ b/RadioController.pas @@ -1849,6 +1849,9 @@ begin FSlices[idx].DMR := TDMRSliceDecoder.Create(Self, Id); FSlices[idx].Mode := Mode; if Assigned(FDSPEngine) then FDSPEngine.SetSliceMode(Id, Mode); + // DMR is receive-only. If this slice used to be the TX source, hand TX back + // to the main receiver as soon as it enters DMR. + if (Mode = MODE_DMR) and (FTxSliceId = Id) then SetTxSlice(0); if (OldMode = MODE_DMR) and (Mode <> MODE_DMR) then FreeAndNil(FSlices[idx].DMR); end; @@ -2134,7 +2137,13 @@ var S: TCtrlSlice; begin if SliceId < 0 then SliceId := 0; // Слайс-источник должен существовать (0 = главный всегда валиден). - if (SliceId > 0) and not GetSlice(SliceId, S) then Exit; + if SliceId > 0 then + begin + if not GetSlice(SliceId, S) then Exit; + // EWSDR has no DMR transmitter/AMBE encoder. Do not accidentally use the + // analog WFM transmitter for a receive-only DMR slice. + if S.Mode = MODE_DMR then Exit; + end; if FTxSliceId = SliceId then Exit; FTxSliceId := SliceId; // Передающий тракт под режим нового источника (idle-канал, применится к PTT). diff --git a/VfoOverlay.pas b/VfoOverlay.pas index 85b9598..38b556c 100644 --- a/VfoOverlay.pas +++ b/VfoOverlay.pas @@ -141,6 +141,7 @@ type function GetFilterBWForMode(ModeIdx, FilterIdx: Integer): Integer; function GetFilterLblForMode(ModeIdx, FilterIdx: Integer): string; function GetFilterCountForMode(ModeIdx: Integer): Integer; + function TxSelectionAllowed: Boolean; function PanelContentH: Integer; function ComputeHeight: Integer; procedure SetPanel(P: TFlyPanel); @@ -423,6 +424,12 @@ begin end; end; +function TVfoOverlay.TxSelectionAllowed: Boolean; +begin + // Main A remains the normal TX source. Additional DMR slices are RX-only. + Result := FIsMain or (FMode <> 11); +end; + { ---- Lifecycle ---- } constructor TVfoOverlay.Create(AOwner: TComponent); @@ -1006,13 +1013,14 @@ begin C.Font.Name := 'Courier New'; C.Font.Size := 8; C.Font.Style := []; C.Font.Color := CLR_DIM; C.Brush.Style := bsClear; C.TextOut(X + 22, CurY + 1, BWStr); - // TX badge (правый край) — кликабельно: выбор TX-слайса. - // передача идёт → красный; слайс выбран для TX → янтарный; иначе → нейтральный. + // TX badge: a DMR slice is visibly disabled and has no hit target. R := Rect(W - PAD - 26, CurY, W - PAD, CurY + HDR_BADGE_H); - if FTx then DrawBadge(C, R, 'TX', CLR_TX_ON, clWhite) + if not TxSelectionAllowed then + DrawBadge(C, R, 'TX', CLR_CARD_BG, CLR_DIM) + else if FTx then DrawBadge(C, R, 'TX', CLR_TX_ON, clWhite) else if FTxSel then DrawBadge(C, R, 'TX', CLR_TX_SEL, CLR_BADGE_TXT) else DrawBadge(C, R, 'TX', CLR_BTN_NORM, CLR_DIM); - RegisterHit(R, HIT_TX); + if TxSelectionAllowed then RegisterHit(R, HIT_TX); // SPLIT (левее TX) — кликабельно; только у главного: split = TX на VFO B, // у слайса своего B-VFO нет (кросс-частотный TX делается TX-бейджем слайса). if FIsMain then @@ -1168,7 +1176,11 @@ begin if Assigned(FOnSquelchChange) then FOnSquelchChange(FSQLOn, FSQLLevel); Exit; end; HIT_SPLIT: begin if Assigned(FOnSplit) then FOnSplit(Self); Exit; end; - HIT_TX: begin if Assigned(FOnTxSelect) then FOnTxSelect(Self); Exit; end; + HIT_TX: begin + if TxSelectionAllowed and Assigned(FOnTxSelect) then + FOnTxSelect(Self); + Exit; + end; HIT_SLICE_SEL: begin if Assigned(FOnSliceSelect) then FOnSliceSelect(Self); Exit; end; HIT_CLOSE: begin if Assigned(FOnClose) then FOnClose(Self); Exit; end; HIT_AUD_UP: begin if FAudScroll > 0 then Dec(FAudScroll);