diff --git a/MainForm.pas b/MainForm.pas index 9857dc4..6a2dc38 100644 --- a/MainForm.pas +++ b/MainForm.pas @@ -8520,64 +8520,23 @@ begin end; procedure TMainForm.OnTXSettingsChange(const T: TTXSettings); -// Любая правка в Settings→Transmit летит сюда: обновляем FController.FTXSettings, -// перешиваем WDSP TX-цепь и (если поменялись mic-биты) перепосылаем DUC Specific. -var - OldMicByte, NewMicByte: Byte; - OldAtt, OldTUNLevel, OldTUNFreq: Integer; - GridChanged: Boolean; +// Любая правка в Settings→Transmit летит сюда. Применение записи (WDSP, DUC +// Specific, живой TUN, профиль, персист) — в контроллере: SetTXSettings, та же +// дверь, что у CAT и web. Форме остаётся рендер. +// Notify=False — иначе rfTXProfile перезагрузил бы вкладку Transmit прямо под +// руками у того, кто её сейчас правит. +var GridChanged: Boolean; begin - OldMicByte := FController.BuildMicLineSelectByte; - OldAtt := FController.FTXSettings.AttOnTX; - OldTUNLevel := FController.FTXSettings.TUNLevel; - OldTUNFreq := FController.FTXSettings.TUNFreq; GridChanged := (FController.FTXSpecRefLevel <> T.TXSpecRefLevel) or (FController.FTXSpecRange <> T.TXSpecRange) or (FController.FTXSpecGridStep <> T.TXSpecGridStep); - FController.FTXSettings := T; - NewMicByte := FController.BuildMicLineSelectByte; - // TX-grid в момент правки — обновляем рабочие поля и (если на передаче) пушим в FSpecView - FController.FTXSpecRefLevel := FController.FTXSettings.TXSpecRefLevel; - FController.FTXSpecRange := FController.FTXSettings.TXSpecRange; - if FController.FTXSettings.TXSpecGridStep > 0 then - FController.FTXSpecGridStep := FController.FTXSettings.TXSpecGridStep; + FController.SetTXSettings(T, False); if GridChanged and FController.FTransmitting then ApplySpecViewGridFromState; - FController.ApplyTXSettingsToDSP; // Low/High из вкладки Transmit — та же полоска фильтра на спектре: кромки // берём уже пересчитанными движком (знак боковой) и на передаче перерисовываем. PushFilterEdgesToView; if FController.FTransmitting then FSpectrumDirty := True; - if (OldMicByte <> NewMicByte) or (OldAtt <> FController.FTXSettings.AttOnTX) then - FController.SendDUCSpecificFromSettings; - // TUN-параметры live: если идёт tune — обновить тон/drive, иначе просто запомнить. - if FController.FTuning then - begin - if (OldTUNFreq <> FController.FTXSettings.TUNFreq) and FController.FWDSPReady then - FController.FDSPEngine.SetTXTone(True, FController.FTXSettings.TUNFreq, 1.0); - if OldTUNLevel <> FController.FTXSettings.TUNLevel then - begin - FController.FDriveLevel := CalcDriveByte; - if FController.FWDSPReady then - FController.FDSPEngine.SetDriveLevel(FController.FTXSettings.TUNLevel / 100.0); - if FController.FNetwork.Connected and FController.FNetwork.Running then - begin - FController.FNetwork.UpdateState(XvtrTranslate(FController.FCenterFreq), FController.TXTuneFreqHz, FController.FDriveLevel, - FController.FTransmitting, True, True, FController.FTuning, FController.FTwoTone); - FController.FNetwork.SendFullHP; - end; - end; - end; - // Правка «звуковых» полей — это правка активного профиля: отдельной кнопки - // «сохранить» нет, профиль ведётся за живым состоянием (см. TTXProfile). - FController.StoreActiveTXProfile; - // Сохраняем сразу — настройки per-device, попадают в hpsdr_settings.json - if FController.FDevConnected then - begin - FController.FSettings.SaveTX(FController.FDevMAC, FController.FTXSettings); - FController.FSettings.SaveTXProfiles(FController.FDevMAC, FController.FTXProfiles); - FController.FSettings.Save; - end; end; procedure TMainForm.OnCWSettingsChange(const C: TCWSettings); diff --git a/RadioController.pas b/RadioController.pas index 8513296..aa84084 100644 --- a/RadioController.pas +++ b/RadioController.pas @@ -691,6 +691,11 @@ type function TXProfileCount: Integer; function TXProfileName(Idx: Integer): string; function ActiveTXProfile: Integer; + // Единая дверь для правки TX-настроек снаружи (вкладка Transmit, CAT, web): + // применяет запись к движку/железу, дописывает активный профиль и персистит. + // Notify=False — вызывающий сам отрисует изменения (так делает MainForm, + // иначе rfTXProfile перезагрузил бы форму настроек прямо под руками). + procedure SetTXSettings(const T: TTXSettings; Notify: Boolean = True); // Auto=True — переключение сделала автоматика привязок; ручной выбор // (дропдаун, список настроек) дополнительно ЗАПОМИНАЕТСЯ за текущей парой // «источник + модуляция» (BindTXProfileToCurrentMode). @@ -787,6 +792,9 @@ type // Громкость / mute / drive / аттенюатор procedure SetVolume(V: Integer); procedure VolumeBy(Delta: Integer); + // Громкость self-monitor'а на передаче отдельно от RX-громкости: слайдер + // правит её только когда MonitoringTX, а CAT (ZZTM) — в любой момент. + procedure SetTXMonVolume(V: Integer); // True — сейчас звучит self-monitor даунлинка на передаче (TX + DUP + RX MUTE // off). В этом контексте SetVolume/слайдер правят FTxMonVolume, иначе FVolume. function MonitoringTX: Boolean; @@ -4683,6 +4691,14 @@ end; procedure TRadioController.VolumeBy(Delta: Integer); begin SetVolume(ActiveVolume + Delta); end; +procedure TRadioController.SetTXMonVolume(V: Integer); +// Адресно правит громкость self-monitor'а. Слайдер добирается до неё только на +// передаче (SetVolume через ActiveVolume), CAT-клиенту такой контекст не нужен. +begin + FTxMonVolume := EnsureRange(V, 0, 100); + if MonitoringTX then ApplyActiveVolume; +end; + procedure TRadioController.SetMute(On_: Boolean); begin FMuted := On_; @@ -5531,6 +5547,59 @@ begin FSettings.Save; end; +procedure TRadioController.SetTXSettings(const T: TTXSettings; Notify: Boolean); +// Одна дверь для правки TX-настроек — по образцу SetCWSettings. Клиенту +// (вкладка Transmit, CAT, web) достаточно отдать запись целиком: применение к +// WDSP, перепосыл DUC Specific при смене mic-битов/ATT, живое обновление TUN, +// запись в активный профиль и персист — здесь. +var + OldMicByte: Byte; + OldAtt, OldTUNLevel, OldTUNFreq: Integer; +begin + OldMicByte := BuildMicLineSelectByte; + OldAtt := FTXSettings.AttOnTX; + OldTUNLevel := FTXSettings.TUNLevel; + OldTUNFreq := FTXSettings.TUNFreq; + FTXSettings := T; + // TX-сетка спектра — рабочие поля рендера; их перерисовку заказывает вызывающий. + FTXSpecRefLevel := FTXSettings.TXSpecRefLevel; + FTXSpecRange := FTXSettings.TXSpecRange; + if FTXSettings.TXSpecGridStep > 0 then FTXSpecGridStep := FTXSettings.TXSpecGridStep; + ApplyTXSettingsToDSP; + // Маршрутизация микрофона и ATT on TX живут в железе (DUC Specific), WDSP тут + // ни при чём — пакет перепосылаем только когда байты реально поменялись. + if (BuildMicLineSelectByte <> OldMicByte) or (OldAtt <> FTXSettings.AttOnTX) then + SendDUCSpecificFromSettings; + // TUN-параметры live: идёт настройка — обновить тон/уровень, иначе просто запомнить. + if FTuning then + begin + if (OldTUNFreq <> FTXSettings.TUNFreq) and FWDSPReady then + FDSPEngine.SetTXTone(True, FTXSettings.TUNFreq, 1.0); + if OldTUNLevel <> FTXSettings.TUNLevel then + begin + FDriveLevel := CalcDriveByte; + if FWDSPReady then + FDSPEngine.SetDriveLevel(EnsureRange(FTXSettings.TUNLevel, 0, 100) / 100.0); + if FNetwork.Connected and FNetwork.Running then + begin + FNetwork.UpdateState(XvtrTranslate(FCenterFreq), TXTuneFreqHz, FDriveLevel, + FTransmitting, True, True, FTuning, FTwoTone); + FNetwork.SendFullHP; + end; + end; + end; + // Правка «звуковых» полей — это правка активного профиля: отдельной кнопки + // «сохранить» нет, профиль ведётся за живым состоянием (см. TTXProfile). + StoreActiveTXProfile; + if FDevConnected and Assigned(FSettings) then + begin + FSettings.SaveTX(FDevMAC, FTXSettings); + FSettings.SaveTXProfiles(FDevMAC, FTXProfiles); + FSettings.Save; + end; + if Notify then Changed(rfTXProfile); +end; + procedure TRadioController.StoreActiveTXProfile(Persist: Boolean = False); // Живое состояние → активный профиль. Зовётся на каждой правке TX-настроек и // на смене drive; Persist=False не трогает диск (drive ездит слайдером).