From 00860e51541cccce6c257222223ab1964a5aefd1 Mon Sep 17 00:00:00 2001 From: Vladimir Date: Wed, 12 Aug 2026 23:46:05 +0300 Subject: [PATCH] =?UTF-8?q?fix(slice-cat):=20=D0=BF=D0=B5=D1=80=D0=B5?= =?UTF-8?q?=D1=81=D1=82=D1=80=D0=BE=D0=B9=D0=BA=D0=B0=20=D1=81=D0=BB=D0=B0?= =?UTF-8?q?=D0=B9=D1=81=D0=B0=20=D0=B2=D0=BD=D1=83=D1=82=D1=80=D0=B8=20?= =?UTF-8?q?=D0=BF=D0=BE=D0=BB=D0=BE=D1=81=D1=8B=20=D0=B7=D0=B0=D1=85=D0=B2?= =?UTF-8?q?=D0=B0=D1=82=D0=B0=20=D0=BE=D0=B1=D0=BD=D0=BE=D0=B2=D0=BB=D1=8F?= =?UTF-8?q?=D0=B5=D1=82=20=D1=84=D0=BB=D0=B0=D0=B3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit TuneSliceInBand в быстрой ветке (цель уже внутри захваченной полосы) звал только SetSliceTarget и не слал ни одного Changed. Позицию флага UI держит сам (TickFlags -> LayoutFlags читает живой TargetHz), а частота и кромки фильтра живут в собственных полях оверлея и заливаются только из PushSliceFlagState. Итог: флаг уезжал на новую частоту, показывая старые цифры и старую полосу фильтра. Дальний QSY выглядел исправным лишь потому, что там двигалось окно DDC и приходил rfPanFreq с PushAllSliceFlagStates. Новое поле rfSliceFreq (+ FSliceFreqId как полезная нагрузка) и хелпер SliceFreqChanged: шлётся из быстрой ветки и из ветки пана 0 (rfCenterFreq флаги не перезаливает). MainForm обновляет только тронутый слайс. Тракт передачи не менялся: ActiveTXFreqHz и так берёт TargetHz слайса- источника, а SetSliceTarget сразу пушит сетевое состояние (DUC). Co-Authored-By: Claude Opus 5 --- MainForm.pas | 11 +++++++++++ RadioController.pas | 23 ++++++++++++++++++++++- 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/MainForm.pas b/MainForm.pas index 6bc5b07..8bd1538 100644 --- a/MainForm.pas +++ b/MainForm.pas @@ -1822,6 +1822,17 @@ begin end; end; + rfSliceFreq: + begin + // Слайс перестроен по своему CAT-порту в пределах захваченной полосы: + // окно DDC не двигалось (rfPanFreq не придёт), но цифры и полоса + // фильтра во флаге — его собственные поля, их надо перезалить. + PushFlagStateAllPans(FController.FSliceFreqId); + LayoutFlagsAllPans; + for i := 0 to MAX_PANS - 1 do + if FPans[i] <> nil then MarkPanDirty(FPans[i]); + end; + rfPanFreq: begin // Центр доп. пана переехал не из UI (CAT слайса перестроил его за diff --git a/RadioController.pas b/RadioController.pas index 27fd9b9..26e2419 100644 --- a/RadioController.pas +++ b/RadioController.pas @@ -87,7 +87,8 @@ type rfBeaconLock, // QO-100 beacon lock: статус/коррекция rfDevice, // подключённое устройство сменилось rfDeviceList, // список discovered устройств обновился - rfPanFreq // центр доп. пана уехал (ретюн DDC извне) + rfPanFreq, // центр доп. пана уехал (ретюн DDC извне) + rfSliceFreq // слайс перестроен извне (CAT); Id — FSliceFreqId ); TRadioStateEvent = procedure(Sender: TObject; Field: TRadioField) of object; @@ -366,6 +367,9 @@ type FTwoTone: Boolean; // 2TON активен FSplitTxB: Boolean; FTxSliceId: Integer; // 0 = главный VFO (A/B split); >0 = слайс-источник TX + // Id слайса, перестроенного извне (CAT): полезная нагрузка rfSliceFreq — + // Changed несёт только поле, а обработчику нужен конкретный флаг. + FSliceFreqId: Integer; // Auto TX слайса (индекс = СЛОТ слайса, не Id): PTT по CAT-порту слайса сам // назначает его TX-источником. Флаг живёт на слоте, а не на слайсе, потому // что настройка привязана к букве (B..G) и переживает удаление слайса. @@ -884,6 +888,9 @@ type // вне захваченной полосы пана — двигаем окно DDC. False = отказ (другой // диапазон либо окно не подвинуть, не оглушив главный приёмник). function TuneSliceInBand(Id: Integer; TargetHz: Double): Boolean; + // Уведомление UI «частота слайса пришла извне»: перезалить флаг (цифры + + // кромки фильтра), позиция флага и так живая. + procedure SliceFreqChanged(Id: Integer); // ---- Панадаптеры на аппаратных DDC (этап 3.1; UI/движок — 3.2/3.3) ---- // Создаёт пан PanId (1..MAX_PANS-1) на своём DDC: FreqHz = центр в ВИДИМЫХ @@ -1948,6 +1955,17 @@ begin Result := BandEdges(FCurrentBand, IsPluto, LoHz, HiHz); end; +procedure TRadioController.SliceFreqChanged(Id: Integer); +// Слайс перестроен НЕ из UI (CAT-порт слайса). Позицию флага UI держит сам +// (TickFlags → LayoutFlags читает живой TargetHz), а вот ЧАСТОТА и кромки +// фильтра во флаге живут в его собственных полях и обновляются только +// PushSliceFlagState. Без этого уведомления флаг уезжал на новую частоту, +// показывая старые цифры и старую полосу фильтра. +begin + FSliceFreqId := Id; + Changed(rfSliceFreq); +end; + function TRadioController.TuneSliceInBand(Id: Integer; TargetHz: Double): Boolean; // Свобода внешней программы: она двигает слайс куда угодно ВНУТРИ включённого // диапазона (2 м на трансвертере: 144.174 при окне на 145.5 — можно), но сменить @@ -1971,6 +1989,7 @@ begin if SliceFitsCapture(TargetHz, PanId) then begin SetSliceTarget(Id, TargetHz); + SliceFreqChanged(Id); Exit(True); end; @@ -1982,6 +2001,7 @@ begin SetPanDDCFreq(PanId, NewCenter); SetSliceTarget(Id, TargetHz); Changed(rfPanFreq); // UI: шапка/зум-бар/флаги пана под новый центр + // (несёт и перезалив флагов — SliceFreqChanged лишний) Result := True; end else @@ -1995,6 +2015,7 @@ begin NewCenter := (TargetHz + ActiveVfoHz) / 2; SetCenter(NewCenter); // несёт Changed(rfCenterFreq) + сдвиги слайсов SetSliceTarget(Id, TargetHz); + SliceFreqChanged(Id); // rfCenterFreq флаги не перезаливает — нужен свой Result := True; end; end;