mirror of
https://git.vladimir.cc/vladimir/ewsdr.git
synced 2026-08-25 17:27:32 +00:00
Phase 3 (batch 6): route FM squelch + CTCSS through controller commands
The user plans to expose FM over web/CAT later, so FM controls get the same controller treatment now — future web/CAT FM commands plug straight into these. - Relocate CTCSS_COUNT/CTCSS_TONES from MainForm to FMRepeater (a shared FM unit MainForm already uses) so TRadioController can drive CTCSS on the DSP. CTCSS_NAMES stays in MainForm (UI dropdown labels). MODE_FM is already visible to the controller via WDSPEngine. - SetFMSquelch/SetFMSquelchLevel apply FM squelch (mode-gated) to the DSP; SetFMCTCSS/SetFMCTCSSTone clamp and apply CTCSS. All fire OnStateChanged. - OnControllerState restyles the SQ/CTCSS buttons, syncs the squelch slider + label, and the CTCSS tone dropdown. Handlers/SetFMCTCSSTone call the commands (manual CTCSS still clears the auto-active flag in the handler). FM repeater stays for the heavy batch — it needs XvtrTranslate/ ActiveTXFreqHz moved into the controller. ApplyFMSquelch remains for band/mode re-apply paths (RestoreBand, XVTR). Builds clean (cocoa). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
7d3570346f
commit
fd145b28f6
@@ -22,6 +22,16 @@ const
|
|||||||
RPT_AUTO_MINUS_LO = 145600000.0; // 145.600 MHz
|
RPT_AUTO_MINUS_LO = 145600000.0; // 145.600 MHz
|
||||||
RPT_AUTO_MINUS_HI = 145787500.0; // 145.7875 MHz
|
RPT_AUTO_MINUS_HI = 145787500.0; // 145.7875 MHz
|
||||||
|
|
||||||
|
// CTCSS tones (38 standard tones). Здесь (а не в MainForm), чтобы таблица
|
||||||
|
// была доступна TRadioController для FDSPEngine.SetTXCTCSS. Имена тонов
|
||||||
|
// (CTCSS_NAMES) остаются в MainForm — это UI-метки выпадающего списка.
|
||||||
|
CTCSS_COUNT = 38;
|
||||||
|
CTCSS_TONES: array[0..CTCSS_COUNT-1] of Double = (
|
||||||
|
67.0, 71.9, 74.4, 77.0, 79.7, 82.5, 85.4, 88.5, 91.5, 94.8,
|
||||||
|
97.4, 100.0, 103.5, 107.2, 110.9, 114.8, 118.8, 123.0, 127.3, 131.8,
|
||||||
|
136.5, 141.3, 146.2, 151.4, 156.7, 162.2, 167.9, 173.8, 179.9, 186.2,
|
||||||
|
192.8, 203.5, 210.7, 218.1, 225.7, 233.6, 241.8, 250.3);
|
||||||
|
|
||||||
{ Returns default offset (Hz) for the given visible frequency.
|
{ Returns default offset (Hz) for the given visible frequency.
|
||||||
70 cm band → 7.600 MHz; everything else → 0.600 MHz. }
|
70 cm band → 7.600 MHz; everything else → 0.600 MHz. }
|
||||||
function RptDefaultOffsetHz(FreqHz: Double): Double;
|
function RptDefaultOffsetHz(FreqHz: Double): Double;
|
||||||
|
|||||||
+27
-22
@@ -101,12 +101,7 @@ const
|
|||||||
FILT_FM_DEF = 0; // NFM
|
FILT_FM_DEF = 0; // NFM
|
||||||
|
|
||||||
// CTCSS tones (38 standard tones, no None — toggle via CTCSS button)
|
// CTCSS tones (38 standard tones, no None — toggle via CTCSS button)
|
||||||
CTCSS_COUNT = 38;
|
// CTCSS_COUNT и CTCSS_TONES перенесены в FMRepeater (нужны TRadioController).
|
||||||
CTCSS_TONES: array[0..37] of Double = (
|
|
||||||
67.0, 71.9, 74.4, 77.0, 79.7, 82.5, 85.4, 88.5, 91.5, 94.8,
|
|
||||||
97.4, 100.0, 103.5, 107.2, 110.9, 114.8, 118.8, 123.0, 127.3, 131.8,
|
|
||||||
136.5, 141.3, 146.2, 151.4, 156.7, 162.2, 167.9, 173.8, 179.9, 186.2,
|
|
||||||
192.8, 203.5, 210.7, 218.1, 225.7, 233.6, 241.8, 250.3);
|
|
||||||
CTCSS_NAMES: array[0..37] of string = (
|
CTCSS_NAMES: array[0..37] of string = (
|
||||||
'67.0', '71.9', '74.4', '77.0', '79.7', '82.5', '85.4', '88.5',
|
'67.0', '71.9', '74.4', '77.0', '79.7', '82.5', '85.4', '88.5',
|
||||||
'91.5', '94.8', '97.4', '100.0', '103.5', '107.2', '110.9', '114.8',
|
'91.5', '94.8', '97.4', '100.0', '103.5', '107.2', '110.9', '114.8',
|
||||||
@@ -1460,6 +1455,23 @@ begin
|
|||||||
if (FController.FMode = MODE_FM) and (FSpecView <> nil) then
|
if (FController.FMode = MODE_FM) and (FSpecView <> nil) then
|
||||||
FSpecView.FMGridStepHz := FM_STEP_HZ[FController.FFMStepIdx];
|
FSpecView.FMGridStepHz := FM_STEP_HZ[FController.FFMStepIdx];
|
||||||
end;
|
end;
|
||||||
|
rfFMSQ:
|
||||||
|
begin
|
||||||
|
StyleButton(BtnFMSQ, FController.FFMSQOn);
|
||||||
|
BtnFMSQ.Repaint;
|
||||||
|
end;
|
||||||
|
rfFMSQLevel:
|
||||||
|
begin
|
||||||
|
TrkFMSQ.Position := FController.FFMSQLevel;
|
||||||
|
if LblFMSQ <> nil then LblFMSQ.Caption := IntToStr(FController.FFMSQLevel);
|
||||||
|
end;
|
||||||
|
rfFMCTCSS:
|
||||||
|
begin
|
||||||
|
StyleButton(BtnFMCTCSS, FController.FFMCTCSSOn);
|
||||||
|
BtnFMCTCSS.Repaint;
|
||||||
|
end;
|
||||||
|
rfFMCTCSSTone:
|
||||||
|
if FCTCSSDropDown <> nil then FCTCSSDropDown.SetItemIndex(FController.FFMCTCSSToneIdx);
|
||||||
end;
|
end;
|
||||||
finally
|
finally
|
||||||
FSyncingFromController := False;
|
FSyncingFromController := False;
|
||||||
@@ -5288,18 +5300,15 @@ end;
|
|||||||
|
|
||||||
procedure TMainForm.BtnFMSQClick(Sender: TObject);
|
procedure TMainForm.BtnFMSQClick(Sender: TObject);
|
||||||
begin
|
begin
|
||||||
FController.FFMSQOn := not FController.FFMSQOn;
|
if FSyncingFromController then Exit;
|
||||||
StyleButton(BtnFMSQ, FController.FFMSQOn);
|
FController.SetFMSquelch(not FController.FFMSQOn); // DSP + OnControllerState
|
||||||
BtnFMSQ.Repaint;
|
|
||||||
ApplyFMSquelch;
|
|
||||||
SaveCurrentBand;
|
SaveCurrentBand;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TMainForm.TrkFMSQChange(Sender: TObject);
|
procedure TMainForm.TrkFMSQChange(Sender: TObject);
|
||||||
begin
|
begin
|
||||||
FController.FFMSQLevel := TrkFMSQ.Position;
|
if FSyncingFromController then Exit;
|
||||||
if LblFMSQ <> nil then LblFMSQ.Caption := IntToStr(FController.FFMSQLevel);
|
FController.SetFMSquelchLevel(TrkFMSQ.Position);
|
||||||
ApplyFMSquelch;
|
|
||||||
SaveCurrentBand;
|
SaveCurrentBand;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@@ -5658,20 +5667,16 @@ end;
|
|||||||
|
|
||||||
procedure TMainForm.SetFMCTCSSTone(Idx: Integer);
|
procedure TMainForm.SetFMCTCSSTone(Idx: Integer);
|
||||||
begin
|
begin
|
||||||
FController.FFMCTCSSToneIdx := Idx;
|
// Тонкая обёртка: команда применяет к DSP, OnControllerState(rfFMCTCSSTone)
|
||||||
if FCTCSSDropDown <> nil then FCTCSSDropDown.SetItemIndex(Idx);
|
// обновит выпадающий список. Сохранена для вызовов из restore/channel/XVTR.
|
||||||
if FController.FWDSPReady then
|
FController.SetFMCTCSSTone(Idx);
|
||||||
FController.FDSPEngine.SetTXCTCSS(FController.FFMCTCSSOn, CTCSS_TONES[Idx]);
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TMainForm.BtnFMCTCSSClick(Sender: TObject);
|
procedure TMainForm.BtnFMCTCSSClick(Sender: TObject);
|
||||||
begin
|
begin
|
||||||
FController.FFMCTCSSOn := not FController.FFMCTCSSOn;
|
if FSyncingFromController then Exit;
|
||||||
FController.FFMCTCSSAutoActive := False; // ручное действие снимает авто-флаг
|
FController.FFMCTCSSAutoActive := False; // ручное действие снимает авто-флаг
|
||||||
StyleButton(BtnFMCTCSS, FController.FFMCTCSSOn);
|
FController.SetFMCTCSS(not FController.FFMCTCSSOn);
|
||||||
BtnFMCTCSS.Repaint; // Flush visual state before WDSP call
|
|
||||||
if FController.FWDSPReady then
|
|
||||||
FController.FDSPEngine.SetTXCTCSS(FController.FFMCTCSSOn, CTCSS_TONES[FController.FFMCTCSSToneIdx]);
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TMainForm.BtnFMCTCSSToneClick(Sender: TObject);
|
procedure TMainForm.BtnFMCTCSSToneClick(Sender: TObject);
|
||||||
|
|||||||
+26
-5
@@ -50,7 +50,7 @@ uses
|
|||||||
Classes, SysUtils,
|
Classes, SysUtils,
|
||||||
HPSDRProtocol, HPSDRNetwork,
|
HPSDRProtocol, HPSDRNetwork,
|
||||||
WDSPEngine, AudioOutput, AudioInput,
|
WDSPEngine, AudioOutput, AudioInput,
|
||||||
Settings, ChannelStore;
|
Settings, ChannelStore, FMRepeater;
|
||||||
|
|
||||||
type
|
type
|
||||||
// Поле, которое изменилось — для гранулярных уведомлений наружу.
|
// Поле, которое изменилось — для гранулярных уведомлений наружу.
|
||||||
@@ -523,16 +523,37 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TRadioController.SetFMCTCSS(On_: Boolean);
|
procedure TRadioController.SetFMCTCSS(On_: Boolean);
|
||||||
begin FFMCTCSSOn := On_; Changed(rfFMCTCSS); { TODO wiring } end;
|
begin
|
||||||
|
FFMCTCSSOn := On_;
|
||||||
|
if FWDSPReady and Assigned(FDSPEngine) then
|
||||||
|
FDSPEngine.SetTXCTCSS(FFMCTCSSOn, CTCSS_TONES[FFMCTCSSToneIdx]);
|
||||||
|
Changed(rfFMCTCSS);
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TRadioController.SetFMCTCSSTone(Idx: Integer);
|
procedure TRadioController.SetFMCTCSSTone(Idx: Integer);
|
||||||
begin FFMCTCSSToneIdx := Idx; Changed(rfFMCTCSSTone); { TODO wiring } end;
|
begin
|
||||||
|
if Idx < 0 then Idx := 0 else if Idx > CTCSS_COUNT - 1 then Idx := CTCSS_COUNT - 1;
|
||||||
|
FFMCTCSSToneIdx := Idx;
|
||||||
|
if FWDSPReady and Assigned(FDSPEngine) then
|
||||||
|
FDSPEngine.SetTXCTCSS(FFMCTCSSOn, CTCSS_TONES[FFMCTCSSToneIdx]);
|
||||||
|
Changed(rfFMCTCSSTone);
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TRadioController.SetFMSquelch(On_: Boolean);
|
procedure TRadioController.SetFMSquelch(On_: Boolean);
|
||||||
begin FFMSQOn := On_; Changed(rfFMSQ); { TODO wiring } end;
|
begin
|
||||||
|
FFMSQOn := On_;
|
||||||
|
if FWDSPReady and Assigned(FDSPEngine) then
|
||||||
|
FDSPEngine.SetFMSquelch(FFMSQOn and (FMode = MODE_FM), FFMSQLevel);
|
||||||
|
Changed(rfFMSQ);
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TRadioController.SetFMSquelchLevel(V: Integer);
|
procedure TRadioController.SetFMSquelchLevel(V: Integer);
|
||||||
begin FFMSQLevel := V; Changed(rfFMSQLevel); { TODO wiring } end;
|
begin
|
||||||
|
FFMSQLevel := V;
|
||||||
|
if FWDSPReady and Assigned(FDSPEngine) then
|
||||||
|
FDSPEngine.SetFMSquelch(FFMSQOn and (FMode = MODE_FM), FFMSQLevel);
|
||||||
|
Changed(rfFMSQLevel);
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TRadioController.SetFMRpt(Dir: Integer);
|
procedure TRadioController.SetFMRpt(Dir: Integer);
|
||||||
begin FFMRptDir := Dir; Changed(rfFMRpt); { TODO wiring } end;
|
begin FFMRptDir := Dir; Changed(rfFMRpt); { TODO wiring } end;
|
||||||
|
|||||||
Reference in New Issue
Block a user