Paint the band the way N1MM paints it
Behind the bandmap scale, the CW part of the band is one shade and the phone part another, with a third for a digital block. That is what N1MM's graphical bandmap does: ResizeBandPanels puts a CW, a Digi and an SSB panel behind the scale, sized from its CWBands, DigiBands and SSBBands tables. Anything past a band edge is shaded red, which is the only place the edges themselves show, and it only appears now that the slice can reach past an edge. The defaults are N1MM's: CW ends at 1840, 3600, 7125, 14150 and so on, and the digital pair is empty until somebody fills it in, exactly as N1MM ships. They are one worldwide set rather than one per ITU region, which is also N1MM's answer — the reason recorded for leaving this out, that the segments differ by region, was wrong about what N1MM holds. 60M and everything above 2M get no entry, because N1MM's own numbers there contradict themselves: its 1.25M CW top is below its phone start, and its 70CM CW top is above the band. Config ▸ Sub bands edits them, one row per band in kilohertz, with a Defaults button. Only the rows that differ are written to the settings file, so a plan nobody has touched leaves nothing behind. BandPlan is an object rather than a static table, so the stored changes layer over the defaults and the bandmap picks up a save without a restart. The numbers are a drawing aid, not a licence. Nothing stops a contact being logged either side of a boundary. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -62,6 +62,10 @@ public sealed record Settings
|
||||
|
||||
public int KeyerSpeed { get; init; } = 28;
|
||||
|
||||
/// Sub-band boundaries the operator has changed. Empty means the defaults
|
||||
/// in `BandPlan.Default`; an entry replaces one band's boundaries.
|
||||
public IReadOnlyList<StoredSubBand> SubBands { get; init; } = [];
|
||||
|
||||
/// The twelve function key messages, keyed F1 to F12.
|
||||
public IReadOnlyList<string> CwMessages { get; init; } = [];
|
||||
|
||||
@@ -91,6 +95,20 @@ public sealed record Settings
|
||||
}
|
||||
}
|
||||
|
||||
/// The defaults with the operator's changes applied over them.
|
||||
public BandPlan ToBandPlan()
|
||||
{
|
||||
BandPlan plan = BandPlan.Default;
|
||||
foreach (StoredSubBand stored in SubBands)
|
||||
{
|
||||
if (stored.ToSegments() is { } segments)
|
||||
{
|
||||
plan = plan.With(segments);
|
||||
}
|
||||
}
|
||||
return plan;
|
||||
}
|
||||
|
||||
public void Save(string path) =>
|
||||
File.WriteAllText(path, JsonSerializer.Serialize(this, Json));
|
||||
|
||||
@@ -112,6 +130,38 @@ public sealed record Settings
|
||||
};
|
||||
}
|
||||
|
||||
/// One band's sub-band boundaries as they are stored. Kilohertz, because that
|
||||
/// is what the operator types into the editor.
|
||||
public sealed record StoredSubBand
|
||||
{
|
||||
public string Band { get; init; } = "";
|
||||
|
||||
public double CwHigh { get; init; }
|
||||
|
||||
public double DigitalLow { get; init; }
|
||||
|
||||
public double DigitalHigh { get; init; }
|
||||
|
||||
/// Null when the band name is not one we know, or the CW boundary is
|
||||
/// missing: an entry that cannot be read leaves the default in place.
|
||||
public BandSegments? ToSegments() =>
|
||||
Bands.Named(Band) is { } band && CwHigh > 0
|
||||
? new BandSegments(
|
||||
band,
|
||||
Frequency.FromKilohertz(CwHigh),
|
||||
Frequency.FromKilohertz(DigitalLow),
|
||||
Frequency.FromKilohertz(DigitalHigh))
|
||||
: null;
|
||||
|
||||
public static StoredSubBand From(BandSegments segments) => new()
|
||||
{
|
||||
Band = segments.Band.Name,
|
||||
CwHigh = segments.CwHigh.Kilohertz,
|
||||
DigitalLow = segments.DigitalLow.Kilohertz,
|
||||
DigitalHigh = segments.DigitalHigh.Kilohertz,
|
||||
};
|
||||
}
|
||||
|
||||
/// One radio's `rigctld`.
|
||||
public sealed record StoredRadio
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user