{
  Copyright (C)
  2026 - Uladzimir Karpenka, EW8BAK

  This program is free software; you can redistribute it and/or
  modify it under the terms of the GNU General Public License
  as published by the Free Software Foundation; either version 2
  of the License, or (at your option) any later version.

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program; if not, write to the Free Software
  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
}

unit BoardUtils;

{$IFDEF FPC}
  {$MODE Delphi}
{$ENDIF}

interface

type
  // Один диапазон плана (имя кнопки + частота по умолчанию). Общий тип для
  // desktop/web UI — единый источник band-плана через TRadioController.BandPlan.
  TBandInfo = record
    Name:   string;
    FreqHz: Double;
  end;
  TBandPlanArray = array of TBandInfo;

function BoardTypeName(BoardType: Integer): string;
// Короткое человекочитаемое имя AD936x-платы по hw_model (Pluto / LibreSDR / прочие).
function PlutoModelName(const HwModel: string): string;
// Индекс диапазона по частоте. Pluto=True → VHF/UHF план, иначе HF (openHPSDR).
function FreqToBandIdx(Hz: Double; Pluto: Boolean = False): Integer;
// Короткое имя диапазона для кнопки (зависит от плана).
function BandName(Idx: Integer; Pluto: Boolean = False): string;
// Частота по умолчанию при входе в диапазон (если нет сохранённой/в диапазоне).
function BandDefaultFreq(Idx: Integer; Pluto: Boolean = False): Double;
// Границы диапазона по плану. False = слот пуст/индекс вне плана (Lo=Hi=0).
function BandEdges(Idx: Integer; Pluto: Boolean; out LoHz, HiHz: Double): Boolean;
// Полный band-план активного бэкенда (имена + дефолтные частоты).
function BuildBandPlan(Pluto: Boolean): TBandPlanArray;

implementation

uses SysUtils;

const
  // Максимум слотов среди всех планов (кнопки/кэши бэндов рассчитаны на это
  // число). VHF/UHF-план Pluto использует все 12; HF-план (openHPSDR) — только
  // 11, 12-й слот пустой (кнопка прячется, см. TMainForm.RelabelBands).
  BAND_COUNT = 12;

  // ---- HF/6m план (openHPSDR), 11 диапазонов + пустой 12-й слот ----
  HF_NAMES: array[0..BAND_COUNT-1] of string = (
    '160m','80m','60m','40m','30m','20m','17m','15m','12m','10m','6m','');
  HF_LO: array[0..BAND_COUNT-1] of Double = (
    1800000,  3500000,  5330000,  7000000,  10100000,
    14000000, 18068000, 21000000, 24890000, 28000000, 50000000, 0);
  HF_HI: array[0..BAND_COUNT-1] of Double = (
    2000000,  4000000,  5410000,  7300000,  10150000,
    14350000, 18168000, 21450000, 24990000, 29700000, 54000000, 0);
  HF_DEF: array[0..BAND_COUNT-1] of Double = (
    1840000,  3700000,  5357000,  7100000,  10120000,
    14200000, 18130000, 21300000, 24940000, 28400000, 50150000, 0);

  // ---- VHF/UHF/SHF план (Pluto / AD936x), 12 слотов ----
  // OIRT (65..74 МГц) — вещательный УКВ-диапазон, кнопка стоит перед FM.
  VU_NAMES: array[0..BAND_COUNT-1] of string = (
    '6m','4m','2m','1.25m','70cm','23cm','13cm','9cm','OIRT','FM','Air','ADS-B');
  VU_LO: array[0..BAND_COUNT-1] of Double = (
    50000000,   70000000,  144000000, 222000000, 430000000,
    1240000000, 2300000000, 3300000000, 65000000, 88000000, 118000000, 1087000000);
  VU_HI: array[0..BAND_COUNT-1] of Double = (
    54000000,   70500000,  148000000, 225000000, 440000000,
    1300000000, 2450000000, 3500000000, 74000000, 108000000, 137000000, 1093000000);
  VU_DEF: array[0..BAND_COUNT-1] of Double = (
    50150000,   70200000,  145000000, 223500000, 433500000,
    1296200000, 2320000000, 3400100000, 69000000, 100000000, 124000000, 1090000000);

function BoardTypeName(BoardType: Integer): string;
begin
  case BoardType of
    1:  Result := 'HERMES (ANAN-10/100)';
    2:  Result := 'HERMES-E (ANAN-10E/100B)';
    3:  Result := 'ANGELIA (ANAN-100D)';
    4:  Result := 'ORION (ANAN-200D)';
    5:  Result := 'ORION MkII (ANAN-7000/8000)';
    6:  Result := 'HERMES-LITE 2';
    10: Result := 'SATURN (G2)';
    else Result := Format('Unknown Board #%d', [BoardType]);
  end;
end;

function PlutoModelName(const HwModel: string): string;
var
  L: string;
begin
  // hw_model клонов AD936x обычно содержит маркер платы. Узнаём Pluto/LibreSDR,
  // иначе показываем сырой hw_model, а при его отсутствии — обобщённое имя.
  L := LowerCase(HwModel);
  if Pos('libre', L) > 0 then Result := 'LibreSDR'
  else if Pos('pluto', L) > 0 then Result := 'PlutoSDR'
  else if HwModel <> '' then Result := HwModel
  else Result := 'AD936x SDR';
end;

function BandEdges(Idx: Integer; Pluto: Boolean; out LoHz, HiHz: Double): Boolean;
begin
  LoHz := 0; HiHz := 0;
  Result := (Idx >= 0) and (Idx < BAND_COUNT);
  if not Result then Exit;
  if Pluto then begin LoHz := VU_LO[Idx]; HiHz := VU_HI[Idx]; end
  else           begin LoHz := HF_LO[Idx]; HiHz := HF_HI[Idx]; end;
  Result := HiHz > LoHz;   // пустой 12-й слот HF-плана
end;

function FreqToBandIdx(Hz: Double; Pluto: Boolean): Integer;
var
  i: Integer;
begin
  Result := -1;
  if Pluto then
  begin
    for i := 0 to BAND_COUNT - 1 do
      if (Hz >= VU_LO[i]) and (Hz <= VU_HI[i]) then Exit(i);
  end
  else
  begin
    for i := 0 to BAND_COUNT - 1 do
      if (Hz >= HF_LO[i]) and (Hz <= HF_HI[i]) then Exit(i);
  end;
end;

function BandName(Idx: Integer; Pluto: Boolean): string;
begin
  if (Idx < 0) or (Idx >= BAND_COUNT) then Exit('');
  if Pluto then Result := VU_NAMES[Idx] else Result := HF_NAMES[Idx];
end;

function BandDefaultFreq(Idx: Integer; Pluto: Boolean): Double;
begin
  if (Idx < 0) or (Idx >= BAND_COUNT) then Exit(0);
  if Pluto then Result := VU_DEF[Idx] else Result := HF_DEF[Idx];
end;

function BuildBandPlan(Pluto: Boolean): TBandPlanArray;
var i: Integer;
begin
  SetLength(Result, BAND_COUNT);
  for i := 0 to BAND_COUNT - 1 do
  begin
    if Pluto then
    begin
      Result[i].Name   := VU_NAMES[i];
      Result[i].FreqHz := VU_DEF[i];
    end
    else
    begin
      Result[i].Name   := HF_NAMES[i];
      Result[i].FreqHz := HF_DEF[i];
    end;
  end;
end;

end.
