feat(tci): the transmit meters, and no temperature invented
TX_POWER and TX_SWR are read-only commands the radio answers when asked, so they are asked for on each poll of a KEYED radio and not at all otherwise: a receiving station pays nothing for meters nobody is watching. Both appear next to the S-meter only while transmitting, because showing them the rest of the time would show the last thing that happened as if it were now. An SWR of 0 draws as '—' rather than as 1.0. A perfect match on an antenna nobody has measured is the one reading an operator should never be handed. There is no temperature. The protocol's command list has TX_POWER and TX_SWR and nothing thermal at all — so rather than leave the question hanging, it is written down where the next person will look for it. A temperature invented from something else, on a transmitter, is exactly the kind of number somebody would trust.
This commit is contained in:
@@ -23,6 +23,7 @@ type TCIState = {
|
||||
filter_lo: number; filter_hi: number;
|
||||
rit: boolean; rit_offset: number; xit: boolean; xit_offset: number; lock: boolean; split: boolean;
|
||||
smeter: number; modulations?: string[];
|
||||
tx_power_w: number; tx_swr: number;
|
||||
};
|
||||
|
||||
const ZERO: TCIState = {
|
||||
@@ -30,6 +31,7 @@ const ZERO: TCIState = {
|
||||
volume: 0, mute: false, squelch_on: false, squelch: 0,
|
||||
nb: false, nr: false, anf: false, apf: false, filter_lo: 0, filter_hi: 0,
|
||||
rit: false, rit_offset: 0, xit: false, xit_offset: 0, lock: false, split: false, smeter: 0,
|
||||
tx_power_w: 0, tx_swr: 0,
|
||||
};
|
||||
|
||||
// The widths worth a button, PER MODE — because 250 Hz is useless in SSB and
|
||||
@@ -265,9 +267,12 @@ export function TCIPanel({ onReportRST }: { onReportRST?: (rst: string) => void
|
||||
{off && <div className="text-xs text-muted-foreground px-1">{t('tcip.waiting')}</div>}
|
||||
{!!err && <div className="text-[11px] text-danger px-1">{err}</div>}
|
||||
|
||||
{/* Meters — one for now: TCI reports the receive level and does not
|
||||
publish a transmit power reading, so a PWR bar here would be an
|
||||
empty promise. */}
|
||||
{/* Meters. The S-meter while receiving, power and SWR while
|
||||
transmitting — the radio answers TX_POWER and TX_SWR only when it is
|
||||
keyed, so showing them the rest of the time would be showing the
|
||||
last thing that happened as if it were now.
|
||||
There is no temperature: the protocol has no such command, and a
|
||||
made-up figure on a transmitter is the kind somebody trusts. */}
|
||||
<Card icon={Activity} title={t('tcip.meters')}>
|
||||
<MeterBar label="S-METER" value={st.tx ? 0 : sBar(st.smeter)} lo={0} hi={100}
|
||||
accent="#16a34a" segColor={sSegColor}
|
||||
@@ -277,6 +282,18 @@ export function TCIPanel({ onReportRST }: { onReportRST?: (rst: string) => void
|
||||
onReportRST(sMeterRST(s.s, s.over, mode));
|
||||
}}
|
||||
title={t('tcip.sMeterHint')} />
|
||||
{st.tx && (
|
||||
<div className="grid grid-cols-1 sm:grid-cols-2 gap-2">
|
||||
<MeterBar label="PWR" value={st.tx_power_w} lo={0} hi={Math.max(10, Math.ceil(st.tx_power_w / 10) * 10)}
|
||||
accent="#0ea5e9" display={`${st.tx_power_w.toFixed(1)} W`} />
|
||||
{/* 0 is "not measured yet", and it must not draw as a perfect
|
||||
match: an SWR of 1.0 on an antenna nobody has measured is the
|
||||
one reading an operator should not be handed. */}
|
||||
<MeterBar label="SWR" value={st.tx_swr > 0 ? Math.min(100, (st.tx_swr - 1) * 50) : 0} lo={0} hi={100}
|
||||
accent="#f59e0b" display={st.tx_swr > 0 ? st.tx_swr.toFixed(1) : '—'}
|
||||
segColor={(f) => (f > 0.5 ? '#dc2626' : f > 0.25 ? '#f59e0b' : '#16a34a')} />
|
||||
</div>
|
||||
)}
|
||||
</Card>
|
||||
|
||||
{/* Transmit */}
|
||||
|
||||
Reference in New Issue
Block a user