Files
ewsdr/FMRepeater.pas
T
Uladzimir KarpenkaandClaude Opus 4.8 fd145b28f6 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>
2026-06-04 15:15:46 +03:00

90 lines
2.6 KiB
ObjectPascal
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
unit FMRepeater;
{ FM repeater offset helpers — constants, default offsets, auto-direction logic. }
{$mode objfpc}{$H+}
interface
const
RPT_NONE = 0;
RPT_MINUS = 1;
RPT_PLUS = 2;
RPT_2M_BEGIN = 144000000.0;
RPT_2M_END = 148000000.0;
RPT_70CM_BEGIN = 430000000.0;
RPT_70CM_END = 440000000.0;
RPT_DEFAULT_2M = 600000.0; // 0.600 MHz
RPT_DEFAULT_70CM = 7600000.0; // 7.600 MHz
// European 2m repeater input segment: auto-enable minus direction
RPT_AUTO_MINUS_LO = 145600000.0; // 145.600 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.
70 cm band → 7.600 MHz; everything else → 0.600 MHz. }
function RptDefaultOffsetHz(FreqHz: Double): Double;
{ Returns RPT_MINUS when FreqHz falls in the 2 m auto-minus segment,
RPT_NONE otherwise. }
function RptAutoDir(FreqHz: Double): Integer;
{ Formats OffsetHz as MHz with 3 decimal places, e.g. "0.600". }
function RptFormatOffset(OffsetHz: Double): string;
{ Parses a MHz string ("0.600", "7.6", "7,600") to Hz.
Returns 0 on parse error or out-of-range value. }
function RptParseOffset(const S: string): Double;
implementation
uses SysUtils;
function RptDefaultOffsetHz(FreqHz: Double): Double;
begin
if (FreqHz >= RPT_70CM_BEGIN) and (FreqHz <= RPT_70CM_END) then
Result := RPT_DEFAULT_70CM
else
Result := RPT_DEFAULT_2M;
end;
function RptAutoDir(FreqHz: Double): Integer;
begin
if (FreqHz >= RPT_AUTO_MINUS_LO) and (FreqHz <= RPT_AUTO_MINUS_HI) then
Result := RPT_MINUS
else
Result := RPT_NONE;
end;
function RptFormatOffset(OffsetHz: Double): string;
begin
Result := Format('%.3f', [OffsetHz / 1000000.0]);
end;
function RptParseOffset(const S: string): Double;
var
V: Double;
Code: Integer;
Norm: string;
begin
Norm := StringReplace(Trim(S), ',', '.', [rfReplaceAll]);
Val(Norm, V, Code);
if (Code = 0) and (V > 0.0) and (V <= 100.0) then
Result := V * 1000000.0
else
Result := 0.0;
end;
end.