feat: IC-7300MKII, and two Icom addresses that were plain wrong
Adds the IC-7300MKII at CI-V 0xB6. Doing so exposed a drift between the two hand-kept copies of the model table: the settings offered the IC-7700 at 0x88 and the IC-7800 at 0x80, which are the IC-7100's and the IC-7410's factory addresses. Picking either set an address the rig never answers on — the symptom is a radio that simply stays silent — and the backend then named it as the other model. Corrected to 0x74 and 0x6A, and the four models the backend already knew (IC-7100, IC-7410, IC-7600, IC-7851) are now offered too instead of forcing a manual address. A test reads the model list out of the .tsx and asserts civ.ModelName agrees, so the next model added on one side alone fails the build rather than someone's radio.
This commit is contained in:
@@ -3,11 +3,13 @@
|
||||
"version": "0.21.9",
|
||||
"date": "2026-07-28",
|
||||
"en": [
|
||||
"The Icom model list gains the IC-7300MKII (CI-V B6), plus the IC-7100, IC-7410, IC-7600 and IC-7851. The IC-7700 and IC-7800 were listed at the IC-7100's and IC-7410's addresses, so picking them set an address the rig never answers on.",
|
||||
"Icom over the LAN: the frequency no longer stays frozen after another program (WSJT-X through OmniRig, the Remote Utility) takes the CI-V session. The rig kept answering pings while sending nothing, so OpsLog showed the last known frequency until it was restarted; it now reconnects on its own.",
|
||||
"The offline FCC (ULS) database now answers while you type a US callsign, filling state, county and a 6-character grid. It was only applied when the QSO was saved, so without a QRZ.com or HamQTH account you saw nothing but the country and a coarse grid. Online lookups still win — ULS only fills what is blank.",
|
||||
"CQ and ITU zones you correct by hand in your profile stay corrected. They are derived from cty.dat, which gives the zones of the whole entity — in a country spanning several, the automatic value is wrong and it came back at every restart. They now only fill in when empty, and recompute when the callsign or grid changes."
|
||||
],
|
||||
"fr": [
|
||||
"La liste des modèles Icom gagne l'IC-7300MKII (CI-V B6), ainsi que les IC-7100, IC-7410, IC-7600 et IC-7851. Les IC-7700 et IC-7800 y figuraient avec les adresses des IC-7100 et IC-7410 : les choisir réglait une adresse sur laquelle la radio ne répond jamais.",
|
||||
"Icom via le réseau : la fréquence ne reste plus figée après qu'un autre programme (WSJT-X via OmniRig, la Remote Utility) a pris la session CI-V. La radio continuait de répondre aux pings sans rien émettre, si bien qu'OpsLog affichait la dernière fréquence connue jusqu'à son redémarrage ; il se reconnecte désormais tout seul.",
|
||||
"La base FCC (ULS) hors ligne répond désormais pendant la saisie d'un indicatif américain, en remplissant l'état, le comté et un locator 6 caractères. Elle n'était appliquée qu'à l'enregistrement du QSO : sans compte QRZ.com ou HamQTH, vous ne voyiez que le pays et un locator approximatif. Les recherches en ligne restent prioritaires — l'ULS ne comble que ce qui est vide.",
|
||||
"Les zones CQ et ITU corrigées à la main dans votre profil restent corrigées. Elles proviennent de cty.dat, qui donne les zones de l'entité entière — dans un pays qui en couvre plusieurs, la valeur automatique est fausse et revenait à chaque redémarrage. Elles ne se remplissent désormais que si le champ est vide, et se recalculent quand l'indicatif ou le locator change."
|
||||
|
||||
@@ -1006,12 +1006,20 @@ function FlexBandAntennasPanel({ bands }: { bands: string[] }) {
|
||||
// model sets icom_addr so the backend identifies it (civ.ModelName) and the UI
|
||||
// adapts (e.g. the attenuator steps differ by model). Keep in lockstep with
|
||||
// civ.ModelName in internal/cat/civ/civ.go. `addr` is decimal.
|
||||
// The IC-7700 and IC-7800 were listed at 0x88 and 0x80 — which are the IC-7100's
|
||||
// and the IC-7410's. Picking one of them set an address the rig never answers on,
|
||||
// and the backend then named it as the other model.
|
||||
const ICOM_MODELS: { name: string; addr: number }[] = [
|
||||
{ name: 'IC-705', addr: 0xA4 },
|
||||
{ name: 'IC-7100', addr: 0x88 },
|
||||
{ name: 'IC-7300', addr: 0x94 },
|
||||
{ name: 'IC-7300MKII', addr: 0xB6 },
|
||||
{ name: 'IC-7410', addr: 0x80 },
|
||||
{ name: 'IC-7600', addr: 0x7A },
|
||||
{ name: 'IC-7610', addr: 0x98 },
|
||||
{ name: 'IC-7700', addr: 0x88 },
|
||||
{ name: 'IC-7800', addr: 0x80 },
|
||||
{ name: 'IC-7700', addr: 0x74 },
|
||||
{ name: 'IC-7800', addr: 0x6A },
|
||||
{ name: 'IC-7851', addr: 0x8E },
|
||||
{ name: 'IC-9100', addr: 0x7C },
|
||||
{ name: 'IC-9700', addr: 0xA2 },
|
||||
];
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"os"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"testing"
|
||||
|
||||
"hamlog/internal/cat/civ"
|
||||
)
|
||||
|
||||
// The Icom model picker in the settings and civ.ModelName are two hand-kept
|
||||
// copies of the same table, and they had drifted: the UI offered the IC-7700 at
|
||||
// 0x88 and the IC-7800 at 0x80, which are the IC-7100's and the IC-7410's
|
||||
// factory addresses. Picking either set an address the rig never answers on —
|
||||
// the symptom is a rig that simply never replies — and the backend then named it
|
||||
// as the other model.
|
||||
//
|
||||
// The list is read out of the .tsx itself, so a model added on one side alone
|
||||
// fails here rather than on someone's radio.
|
||||
func TestIcomModelAddressesMatch(t *testing.T) {
|
||||
src, err := os.ReadFile("frontend/src/components/SettingsModal.tsx")
|
||||
if err != nil {
|
||||
t.Skipf("frontend source not available: %v", err)
|
||||
}
|
||||
re := regexp.MustCompile(`\{ name: '(IC-[A-Za-z0-9-]+)', addr: 0x([0-9A-Fa-f]{2}) \}`)
|
||||
ms := re.FindAllStringSubmatch(string(src), -1)
|
||||
if len(ms) < 5 {
|
||||
t.Fatalf("only %d models found — the parse is wrong, not the data", len(ms))
|
||||
}
|
||||
for _, m := range ms {
|
||||
name := m[1]
|
||||
addr, err := strconv.ParseUint(m[2], 16, 8)
|
||||
if err != nil {
|
||||
t.Fatalf("bad address %q for %s", m[2], name)
|
||||
}
|
||||
if got := civ.ModelName(byte(addr)); got != name {
|
||||
t.Errorf("settings offer %s at 0x%02X, but civ.ModelName(0x%02X) = %q",
|
||||
name, addr, addr, got)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -344,6 +344,8 @@ func ModelName(addr byte) string {
|
||||
return "IC-9700"
|
||||
case 0xA4:
|
||||
return "IC-705"
|
||||
case 0xB6:
|
||||
return "IC-7300MKII"
|
||||
}
|
||||
return fmt.Sprintf("Icom (0x%02X)", addr)
|
||||
}
|
||||
|
||||
@@ -152,6 +152,7 @@ func TestModelNameAddresses(t *testing.T) {
|
||||
0x98: "IC-7610",
|
||||
0xA2: "IC-9700",
|
||||
0xA4: "IC-705",
|
||||
0xB6: "IC-7300MKII",
|
||||
} {
|
||||
if got := ModelName(addr); got != want {
|
||||
t.Errorf("ModelName(0x%02X) = %q, want %q", addr, got, want)
|
||||
|
||||
Reference in New Issue
Block a user