diff --git a/MainForm.pas b/MainForm.pas index ec59aa2..f8130f5 100644 --- a/MainForm.pas +++ b/MainForm.pas @@ -3361,29 +3361,14 @@ end; procedure TMainForm.DoStopAndDisconnect; // STOP-teardown, общий для десктоп-STOP и web-disconnect. Движок (graceful Run=0, -// сброс TX/телеметрии) + рендер run-кнопки/MOX/sleep — в контроллере (StopRunning -// + OnControllerState). Здесь: persistence + сеть Disconnect + offline-статус. +// сброс TX/телеметрии) + персист настроек + Disconnect — в контроллере +// (StopAndDisconnect); рендер run-кнопки/MOX/sleep — через rfRunning. Здесь — +// только очистка спектра и контекстный offline-статус. begin - FController.StopRunning; - // Сохраняем текущую частоту/настройки чтобы следующий START восстановил их - if FController.FDevConnected then - begin - SaveCurrentBand; - FController.SaveGlobalSettings; - FController.FSettings.SaveAlex(FController.FDevMAC, FController.FAlexSettings); - // XVTR LastFreq → актуальная видимая частота в момент остановки - if (FController.FCurrentXvtr >= 0) and (FController.FCurrentXvtr < CFG_XVTR_COUNT) then - FController.FXvtrSettings.Entries[FController.FCurrentXvtr].LastFreq := FController.FVfoA; - FController.FSettings.SaveXvtr(FController.FDevMAC, FController.FXvtrSettings); - end; - FController.FSettings.SaveStartupPreview(FController.FVfoA, FController.FVfoB, FController.FSampleRate); - FController.FSettings.Save; + FController.StopAndDisconnect; FSpecView.ResetSpectrumBuf; FSpecView.DrawSpectrum; PbSpectrum.Invalidate; - FController.FNetwork.Disconnect; - // Run-кнопка/MOX уже перерисованы StopRunning (rfRunning); здесь только - // контекстный offline-статус. SetRadioOfflineStatus('Disconnected', True); end; @@ -3454,42 +3439,24 @@ procedure TMainForm.DoConnectDevice(const Dev: THPSDRDevice); begin BtnStartStop.Enabled := True; - // Connect + загрузка per-device настроек в контроллер; рендер ВСЕХ device- - // виджетов идёт через OnControllerState(rfDevice) внутри ConnectDevice. - if not FController.ConnectDevice(Dev) then + // Connect + load-by-MAC + перестройка диапазона/XVTR/активного VFO + go-live — + // вся оркестрация в контроллере (ConnectAndRun); рендер device/band/run- + // виджетов идёт через события (rfDevice/rfBandRestore/rfXvtr/rfActiveVfo/ + // rfRunning). Здесь — только UI-extras (статус-строки/AGCTop/resize). + if not FController.ConnectAndRun(Dev, FSpectrumWidth) then begin ShowMessage('Failed to connect to ' + Dev.IPAddress + IfThen(FController.FNetwork.LastError <> '', ': ' + FController.FNetwork.LastError, '')); Exit; end; - // Перестройка диапазона/VFO — обёртки с UI-extras (финальная перестройка через - // ApplyVfoA; XVTR — wideband-view+web). Состояние уже загружено ConnectDevice. - RestoreBand(FController.FCurrentBand); - - // Восстанавливаем XVTR-режим, если он был активен при выходе. - // FController.FCurrentBand уже загружен (HF-диапазон, на который пользователь зашёл - // до XVTR), его FController.FBandCache не пострадает — ActivateXvtrBand только - // выставит FController.FVfoA на XVTR-частоту и FController.FCurrentXvtr. - if (FController.FLoadedGlobal.LastXvtr >= 0) and (FController.FLoadedGlobal.LastXvtr < CFG_XVTR_COUNT) - and FController.FXvtrSettings.Entries[FController.FLoadedGlobal.LastXvtr].Enabled then - ActivateXvtrBand(FController.FLoadedGlobal.LastXvtr); - - // Активный VFO загружен из настроек (выше), но подсветку рисовали в FormCreate - // (тогда FActiveVfo ещё = 0 → A), а RestoreBand/ActivateXvtrBand перестраивают - // только VFO A. Приводим приёмник И подсветку к фактически активному VFO, - // иначе движок работает по B, а UI показывает активным A. - if FController.FActiveVfo = 1 then - FController.SetActiveVfo(1) // перестройка RX на VFO B + рендер (rfActiveVfo) - else + // Активный VFO=A: подсветку (рисовалась в FormCreate при FActiveVfo=0) освежаем + // здесь — для B это сделал SetActiveVfo(1) внутри ConnectAndRun. + if FController.FActiveVfo <> 1 then UpdateVfoDisplay; SetStatusText(1, 'IP: ' + FController.FNetwork.Device.IPAddress); SetStatusText(0, 'Board: ' + BoardTypeName(FController.FNetwork.Device.BoardType)); - - // «Go-live» Run=1 (General/DDC/DUC + DSP restore) — в контроллере; рендер - // run-кнопки/MOX/sleep идёт через OnControllerState(rfRunning). - FController.StartRunning(FSpectrumWidth); FSpecView.AGCTop := FController.FAGCTop; SetStatusText(6, 'SEQ OK'); SetStatusText(2, 'Running'); diff --git a/RadioController.pas b/RadioController.pas index 05cff8e..6631cdd 100644 --- a/RadioController.pas +++ b/RadioController.pas @@ -444,6 +444,8 @@ type procedure StartRunning(SpectrumWidth: Integer); // Run=1 bring-up: General/DDC/DUC + DSP restore procedure StopRunning; // Run=0: graceful-стоп RX-потока + сброс TX/телеметрии function ConnectDevice(const Dev: THPSDRDevice): Boolean; // Connect + load-by-MAC; рендер через rfDevice + function ConnectAndRun(const Dev: THPSDRDevice; SpectrumWidth: Integer): Boolean; // ConnectDevice + band/xvtr/vfo restore + go-live + procedure StopAndDisconnect; // graceful Run=0 + персист настроек + Disconnect (headless) procedure Discover; // ---- События наружу ---- @@ -2389,6 +2391,59 @@ begin Changed(rfDevice); // UI: полная синхронизация device-виджетов из состояния end; +function TRadioController.ConnectAndRun(const Dev: THPSDRDevice; + SpectrumWidth: Integer): Boolean; +// Headless-оркестрация подключения: Connect+load-by-MAC (ConnectDevice) → +// перестройка диапазона/XVTR/активного VFO → go-live (StartRunning). Рендер всех +// device/band/run-виджетов идёт через события (rfDevice/rfBandRestore/rfXvtr/ +// rfActiveVfo/rfRunning). UI-обёртка добавляет лишь статус-строки/AGCTop/resize. +// Возвращает False, если Connect не удался (тогда bring-up не делается). +begin + Result := ConnectDevice(Dev); + if not Result then Exit; + + // Перестройка диапазона — команда несёт финальную перестройку по активному VFO. + RestoreBand(FCurrentBand); + + // Восстанавливаем XVTR-режим, если он был активен при выходе. FCurrentBand уже + // загружен (HF-диапазон до XVTR) — ActivateXvtr только выставит FVfoA/FCurrentXvtr. + if (FLoadedGlobal.LastXvtr >= 0) and (FLoadedGlobal.LastXvtr < CFG_XVTR_COUNT) + and FXvtrSettings.Entries[FLoadedGlobal.LastXvtr].Enabled then + ActivateXvtr(FLoadedGlobal.LastXvtr); + + // Активный VFO загружен из настроек; RestoreBand/ActivateXvtr строят только + // VFO A. Если активен B — перестраиваем приёмник И подсветку на него. Для + // активного A подсветку освежает UI-обёртка (чистый рендер). + if FActiveVfo = 1 then + SetActiveVfo(1); + + // Go-live Run=1 (General/DDC/DUC + DSP restore); рендер — через rfRunning. + StartRunning(SpectrumWidth); +end; + +procedure TRadioController.StopAndDisconnect; +// Headless STOP+teardown: graceful Run=0 (StopRunning) + персист настроек +// устройства/диапазона/глобала + разрыв сети. Персист идёт ДО Disconnect (saves +// читают живое состояние). Рендер run-кнопки/MOX/sleep — через StopRunning→ +// rfRunning; UI-обёртка добавляет очистку спектра и offline-статус. +begin + StopRunning; + // Сохраняем текущую частоту/настройки чтобы следующий START восстановил их. + if FDevConnected then + begin + SaveCurrentBand; + SaveGlobalSettings; + FSettings.SaveAlex(FDevMAC, FAlexSettings); + // XVTR LastFreq → актуальная видимая частота в момент остановки. + if (FCurrentXvtr >= 0) and (FCurrentXvtr < CFG_XVTR_COUNT) then + FXvtrSettings.Entries[FCurrentXvtr].LastFreq := FVfoA; + FSettings.SaveXvtr(FDevMAC, FXvtrSettings); + end; + FSettings.SaveStartupPreview(FVfoA, FVfoB, FSampleRate); + FSettings.Save; + FNetwork.Disconnect; +end; + // --------------------------------------------------------------------------- // Discovery — поиск устройств в фоновом потоке. Найденные приходят через // FNetwork.OnDeviceFound (=OnDeviceFound) и копятся в FDeviceStore.Discovered;