fix: read the real SWR on the Yaesu, and show the ratio
A second measurement at a known mismatch settled both the index and the scale. At SWR 1.1: RM6=0. At SWR 1.5: RM6=52, while RM4 kept tracking the power. 52/255 = 0.204, which is the reflection coefficient of a 1.5 SWR to three decimals. So the raw value is rho scaled to 255, and the ratio is (1+rho)/(1-rho) — physics, not a curve fitted through two points, which is why 2.0 and 3.0 fall out of it correctly without ever having been measured. The panel now shows that ratio, the number the operator reads on the rig, rather than a percentage of meter travel — and a dash while receiving, since a stale SWR from the last transmission reads as a live one. Both measurements are recorded in the code and in a test, so the mapping is evidence rather than a table borrowed from another model — which is exactly how it came to read 81 in the first place.
This commit is contained in:
@@ -55,7 +55,10 @@ type YaesuTXState struct {
|
||||
NR bool `json:"nr"`
|
||||
NRLevel int `json:"nr_level"` // 1-15
|
||||
Narrow bool `json:"narrow"` // NAR filter
|
||||
VOX bool `json:"vox"`
|
||||
// SWR is the RATIO (1.0, 1.5…), computed from the reflection coefficient —
|
||||
// what an operator reads on the rig, not a percentage of meter travel.
|
||||
SWR float64 `json:"swr"`
|
||||
VOX bool `json:"vox"`
|
||||
// CW-only controls. Read (and shown) only in CW, where MIC and VOX mean
|
||||
// nothing and these are what an operator reaches for.
|
||||
KeySpeed int `json:"key_speed"` // WPM
|
||||
@@ -157,12 +160,14 @@ func (y *Yaesu) readPanel(mode string, split bool, txHz int64) {
|
||||
if v, ok := y.askNum("RM4;", "RM4", 3); ok {
|
||||
y.panel.PowerMeter = scale255(v)
|
||||
}
|
||||
// SWR: RM6 is the remaining candidate. It read 0 throughout, which is
|
||||
// CONSISTENT with the 1.1 match but does not prove the index — only a
|
||||
// deliberate mismatch would. Shown because a bar stuck at zero on a good
|
||||
// antenna is honest, where 81 was actively misleading.
|
||||
// SWR is RM6, and a second measurement at a KNOWN mismatch settled both the
|
||||
// index and the scale: 0 at SWR 1.1, then 52 at SWR 1.5. 52/255 = 0.204,
|
||||
// which is the reflection coefficient of a 1.5 SWR to three decimals — so
|
||||
// the raw value is rho scaled to 255, and the ratio follows from physics
|
||||
// rather than from a fitted curve.
|
||||
if v, ok := y.askNum("RM6;", "RM6", 3); ok {
|
||||
y.panel.SWRMeter = scale255(v)
|
||||
y.panel.SWR = swrFromReflection(v)
|
||||
}
|
||||
} else {
|
||||
// Zeroed rather than frozen: a stale SWR bar from the last transmission
|
||||
@@ -658,3 +663,27 @@ func (y *Yaesu) YaesuZeroIn() error {
|
||||
}
|
||||
return y.write("ZI;")
|
||||
}
|
||||
|
||||
// swrFromReflection turns the rig's SWR meter reading into the ratio itself.
|
||||
//
|
||||
// The raw value is the reflection coefficient scaled to 255 — established on an
|
||||
// FTDX10 by measuring at two known matches (0 at 1.1, 52 at 1.5; 52/255 = 0.204,
|
||||
// which is rho for a 1.5 SWR). So SWR = (1+rho)/(1-rho), physics rather than a
|
||||
// curve fitted to two points.
|
||||
//
|
||||
// Capped at 9.9: past that the number stops meaning anything to an operator, and
|
||||
// rho approaching 1 sends the ratio to infinity.
|
||||
func swrFromReflection(raw int) float64 {
|
||||
if raw <= 0 {
|
||||
return 1.0
|
||||
}
|
||||
rho := float64(raw) / 255.0
|
||||
if rho >= 0.98 {
|
||||
return 9.9
|
||||
}
|
||||
swr := (1 + rho) / (1 - rho)
|
||||
if swr > 9.9 {
|
||||
return 9.9
|
||||
}
|
||||
return swr
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user