From 9fdfc67f65e70bceb9b1ed99fe6b1927c5a01606 Mon Sep 17 00:00:00 2001 From: Uladzimir Karpenka Date: Mon, 8 Jun 2026 10:59:14 +0300 Subject: [PATCH] Phase 5 (batch 27): move Run=0 teardown (StopRunning) into the controller Extract the graceful Run=0 teardown from BtnStartStopClick's STOP branch into TRadioController.StopRunning: UpdateState/SetRunAndFreq(False) at zero drive, clear FRunning/FTransmitting, SetTXRun(False), reset RX telemetry, emit Changed(rfTransmitting) + rfRunning. The network stays Connected so the UI wrapper can persist state before Disconnect. New OnControllerState(rfRunning) render handles the START/STOP button, BtnMOX.Enabled and sleep inhibit; the context-specific offline status text stays with the caller. FormClose reuses StopRunning (same teardown). Co-Authored-By: Claude Opus 4.8 --- MainForm.pas | 48 ++++++++++++++++++++++----------------------- RadioController.pas | 20 +++++++++++++++++++ 2 files changed, 44 insertions(+), 24 deletions(-) diff --git a/MainForm.pas b/MainForm.pas index 91acc2a..5f0d4cf 100644 --- a/MainForm.pas +++ b/MainForm.pas @@ -1306,6 +1306,24 @@ begin end; // (DUC-очередь сбрасывает SetMOX) rfTuning: StyleButton(BtnTUN, FController.FTuning); + rfRunning: + // Run-состояние: кнопка START/STOP, доступность MOX, запрет сна. + // Текст offline-статуса контекстно-зависим (Disconnected / Connection + // lost / …) — его ставит вызывающий, не общий рендер. + if FController.FRunning then + begin + InhibitSleep; + BtnStartStop.Caption := 'STOP'; + StyleButton(BtnStartStop, True); + BtnMOX.Enabled := True; + end + else + begin + UninhibitSleep; + BtnStartStop.Caption := 'START'; + StyleButton(BtnStartStop, False); + BtnMOX.Enabled := False; + end; rfADCOverload: if FSpecView <> nil then begin @@ -1450,15 +1468,7 @@ begin // Останавливаем трансивер как при нажатии STOP if FController.FNetwork.Connected then begin - if FController.FRunning then - begin - FController.FNetwork.UpdateState(XvtrTranslate(FController.FCenterFreq), XvtrTranslate(ActiveTXFreqHz), 0, False, True, True); - FController.FNetwork.SetRunAndFreq(False, XvtrTranslate(FController.FCenterFreq), XvtrTranslate(FController.FCenterFreq), 0); - FController.FRunning := False; - UninhibitSleep; - FController.FTransmitting := False; - if FController.FWDSPReady then FController.FDSPEngine.SetTXRun(False); - end; + FController.StopRunning; FController.FNetwork.Disconnect; end; CloseAction := caFree; @@ -3643,18 +3653,9 @@ begin if FController.FNetwork.Connected then begin // --- STOP --- - if FController.FRunning then - begin - FController.FNetwork.UpdateState(XvtrTranslate(FController.FCenterFreq), XvtrTranslate(ActiveTXFreqHz), 0, False, True, True); - FController.FNetwork.SetRunAndFreq(False, XvtrTranslate(FController.FCenterFreq), XvtrTranslate(FController.FCenterFreq), 0); - FController.FRunning := False; - UninhibitSleep; - FController.FTransmitting := False; - if FController.FWDSPReady then FController.FDSPEngine.SetTXRun(False); - StyleButton(BtnMOX, False); - end; - FController.FRXPacketCount := 0; - FController.FActiveDDC := 0; + // Движок (graceful Run=0, сброс TX/телеметрии) + рендер run-кнопки/MOX/sleep + // — в контроллере (StopRunning + OnControllerState rfRunning/rfTransmitting). + FController.StopRunning; // Сохраняем текущую частоту/настройки чтобы следующий START восстановил их if FController.FDevConnected then begin @@ -3672,10 +3673,9 @@ begin FSpecView.DrawSpectrum; PbSpectrum.Invalidate; FController.FNetwork.Disconnect; - BtnStartStop.Caption := 'START'; - StyleButton(BtnStartStop, False); + // Run-кнопка/MOX уже перерисованы StopRunning (rfRunning); здесь только + // контекстный offline-статус. SetRadioOfflineStatus('Disconnected', True); - BtnMOX.Enabled := False; Exit; end; diff --git a/RadioController.pas b/RadioController.pas index a17713b..f8d9eb3 100644 --- a/RadioController.pas +++ b/RadioController.pas @@ -372,6 +372,7 @@ type // Жизненный цикл движка / устройства procedure StartStop; procedure SetRun(On_: Boolean); + procedure StopRunning; // Run=0: graceful-стоп RX-потока + сброс TX/телеметрии procedure ConnectDevice(const Dev: THPSDRDevice); procedure Discover; @@ -1824,6 +1825,25 @@ begin SetRun(not FRunning); end; procedure TRadioController.SetRun(On_: Boolean); begin FRunning := On_; Changed(rfRunning); { TODO wiring: логика BtnStartStopClick } end; +procedure TRadioController.StopRunning; +// Graceful-останов RX-потока (Run=0) + сброс TX и RX-телеметрии. Сеть остаётся +// Connected — Disconnect отдельно (UI-обёртка делает это после persistence). +// Рендер run-кнопки/sleep — UI через OnControllerState(rfRunning); MOX — rfTransmitting. +begin + if FRunning then + begin + FNetwork.UpdateState(XvtrTranslate(FCenterFreq), XvtrTranslate(ActiveTXFreqHz), 0, False, True, True); + FNetwork.SetRunAndFreq(False, XvtrTranslate(FCenterFreq), XvtrTranslate(FCenterFreq), 0); + FRunning := False; + FTransmitting := False; + if FWDSPReady then FDSPEngine.SetTXRun(False); + Changed(rfTransmitting); // MOX-кнопка off + end; + FRXPacketCount := 0; + FActiveDDC := 0; + Changed(rfRunning); // безусловный сброс run-кнопки/MOX.Enabled/sleep (как старый хвост STOP) +end; + procedure TRadioController.ConnectDevice(const Dev: THPSDRDevice); begin { TODO wiring: DoConnectDevice } Changed(rfDevice); end;