Files
ewsdr/FMRepeater.pas
ew8bakandClaude Sonnet 4.6 1175e42516 Add channel memory: CH button, dropdown, editor form, smart CTCSS/RPT auto-clear
- New ChannelStore.pas: TChannel record + JSON persistence (channels.json)
- New ChannelsForm.pas: full channel editor (list + fields, pre-fills from current radio state)
- CH button in RX block: left-click opens dropdown, right-click opens editor
- Active channel: button highlights with channel name, deactivates on VFO move
- ApplyChannel: auto-switches XVTR/HF band based on channel frequency; saves old
  band state before switching to prevent cache corruption
- SaveCurrentBand: skip save when VFO > 61 MHz (prevents HF cache corruption
  from VHF channel application without XVTR)
- DeactivateXvtr: save full XVTR state (was only saving LastFreq)
- CTCSS/RPT from channel marked as auto: cleared automatically when tuning away
  from channel frequency; survives band switches via FXvtrSettings auto-flags
- TXvtrEntry: add LastCTCSSAutoActive, LastFMRptAutoActive fields

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-27 15:39:37 +03:00

80 lines
2.0 KiB
ObjectPascal

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
{ 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.