diff --git a/frontend/src/components/TCIPanel.tsx b/frontend/src/components/TCIPanel.tsx index 103b191..03c8d4d 100644 --- a/frontend/src/components/TCIPanel.tsx +++ b/frontend/src/components/TCIPanel.tsx @@ -47,15 +47,16 @@ function widthLabel(w: number): string { return w >= 1000 ? `${(w / 1000).toFixed(1)}k` : String(w); } -// edgesFor turns a width into the pair TCI wants. Narrow filters are centred on -// the CW note: a 250 Hz filter from 100 to 350 would put the note outside its -// own passband. -function edgesFor(w: number, mode: string): { lo: number; hi: number } { - const cw = /CW/i.test(mode); - if (cw || w <= 1000) { - return { lo: Math.max(0, CW_PITCH - Math.round(w / 2)), hi: CW_PITCH + Math.round(w / 2) }; - } - return { lo: 100, hi: 100 + w }; +// edgesFor turns a width into the pair TCI wants: 0 to the width, and nothing +// clever. +// +// It centred narrow filters on the CW note first — 250 became 575-825 — on the +// reasoning that a CW filter should contain the note. That reasoning may even be +// right for a radio, but it is not what the button says, and a button that does +// not do what it says is worse than one that does something simple. 250 means +// 0-250. The two edges are editable underneath for anything else. +function edgesFor(w: number, _mode: string): { lo: number; hi: number } { + return { lo: 0, hi: w }; } // dBm → S units. TCI reports a real signal level rather than a meter position, @@ -311,6 +312,16 @@ export function TCIPanel({ onReportRST }: { onReportRST?: (rst: string) => void {t('tcip.filter')} {st.filter_lo}–{st.filter_hi} Hz +
+ call(() => SetTCIFilter(v, st.filter_hi))} /> +
+
+ call(() => SetTCIFilter(st.filter_lo, v))} /> +
{WIDTHS.map((w) => { const e = edgesFor(w, mode); diff --git a/internal/cat/tci_panel.go b/internal/cat/tci_panel.go index bbe8fca..e8fd39d 100644 --- a/internal/cat/tci_panel.go +++ b/internal/cat/tci_panel.go @@ -95,6 +95,14 @@ func (t *TCI) handlePanel(name string, get func(int) string, args string) bool { yes := func(s string) bool { return strings.EqualFold(strings.TrimSpace(s), "true") } p := &t.panel.st + // Mute and squelch are LOGGED as they change, because a report from a real + // radio says pressing MUTE lights the squelch and nothing here can explain + // it. What the radio actually announces after the command settles whether + // this is our reading or its doing, and no amount of reasoning will. + switch name { + case "mute", "sql_enable", "sql_level": + debugLog.Printf("TCI: %s:%s", name, args) + } switch name { case "protocol": p.Protocol = strings.TrimSpace(args)