Skip to content

Adding a New Radio (Rig Profiles)

Overview

icom-lan uses TOML rig files to define radio capabilities, protocol type, CI-V commands, and hardware parameters. Adding a new radio means adding a new .toml file — no Python changes required for most radios.

Rig files live in rigs/. Reference files:

  • rigs/ic7610.toml — IC-7610 (dual receiver, LAN, CI-V, full feature set)
  • rigs/ic7300.toml — IC-7300 (single receiver, USB serial, CI-V)
  • rigs/ftx1.toml — Yaesu FTX-1 (Yaesu CAT protocol, dual RX)
  • rigs/x6100.toml — Xiegu X6100 (CI-V, IC-705 compatible subset, QRP)
  • rigs/tx500.toml — Lab599 TX-500 (Kenwood CAT protocol, QRP)

Quick Start

# 1. Copy the closest reference rig file
cp rigs/ic7610.toml rigs/ic9700.toml   # for Icom CI-V
cp rigs/tx500.toml rigs/ts890s.toml    # for Kenwood CAT
cp rigs/ftx1.toml rigs/ft710.toml      # for Yaesu CAT

# 2. Edit [radio] and [protocol] sections
# 3. Update [capabilities] to match your radio
# 4. Update [commands] (CI-V radios) or leave empty (Kenwood/Yaesu CAT)
# 5. Add [controls], [meters], [[rules]] as needed
# 6. Run the loader tests
uv run pytest tests/test_rig_loader.py tests/test_rig_multi_vendor.py -v

Supported Protocols

Protocol Type string Examples Description
Icom CI-V "civ" IC-7610, IC-7300, Xiegu X6100/X6200 Binary CI-V frames
Kenwood CAT "kenwood_cat" Lab599 TX-500, Kenwood TS-890S Text "CMD params;"
Yaesu CAT "yaesu_cat" Yaesu FTX-1, FT-710 Yaesu text protocol
[protocol]
type = "civ"  # or "kenwood_cat" or "yaesu_cat"

For CI-V radios, [radio].civ_addr is required. For Kenwood/Yaesu, omit it.

TOML Schema Reference

The sections below provide complete field documentation.

Section-by-Section Walkthrough

[radio] — Model Identity

[radio]
id = "icom_ic9700"        # unique snake_case ID
model = "IC-9700"         # human-readable, used in UI and logs
civ_addr = 0xA2           # CI-V address (required for civ, omit for others)
receiver_count = 2        # 1 or 2 independent receivers
has_lan = true            # Ethernet port built-in?
has_wifi = false          # WiFi built-in?
default_baud = 115200     # optional: default serial baud rate

id must be globally unique. Convention: <vendor>_<model_lower> (e.g. icom_ic7300, yaesu_ftx1, lab599_tx500).

[protocol] — Communication Protocol

[protocol]
type = "civ"       # "civ" | "kenwood_cat" | "yaesu_cat"
address = 0xA2     # optional: override civ_addr for protocol
baud = 115200      # optional: protocol-specific baud rate

Omit this section entirely for CI-V radios — defaults to type = "civ".

[capabilities] — Feature Flags

[capabilities]
features = [
    "audio",      # RX/TX audio streaming
    "scope",      # spectrum scope
    "dual_rx",    # dual independent receivers
    "meters",     # S-meter, SWR, ALC, etc.
    "tx",         # transmit capability
    "attenuator", # ATT control
    "preamp",     # preamplifier
    # ... see _schema.md for full list
]

The capability list controls Web UI guards — features not listed are hidden.

[controls] — UI Control Styles (new)

Defines how controls render in the UI. Each sub-table corresponds to a capability:

[controls.attenuator]
style = "stepped"          # IC-7610: 16 discrete steps with stepper UI

[controls.nb]
style = "toggle_and_level" # IC-7610: separate ON/OFF + level slider

Styles: - toggle — ON/OFF (IC-7300 ATT, X6100 ATT) - stepped — Discrete steps with [−][dropdown][+] (IC-7610 ATT) - selector — Dropdown/selector (FTX-1 ATT: 4 named levels) - toggle_and_level — Separate toggle + slider (IC-7610 NB/NR) - level_is_toggle — 0=OFF, >0=level (FTX-1 NB/NR)

[meters] — Calibration Tables (new)

Non-linear raw→actual calibration for meters. The frontend interpolates between points:

[meters.s_meter]
redline_raw = 130   # where the red zone starts

[[meters.s_meter.calibration]]
raw = 0
actual = -54.0
label = "S0"

[[meters.s_meter.calibration]]
raw = 130
actual = 0.0
label = "S9"

[[rules]] — Constraint Rules (new)

Defines how capabilities interact (mutual exclusion, dependencies):

[[rules]]
kind = "mutex"
fields = ["attenuator", "preamp"]

[[rules]]
kind = "disables"
when_active = "digisel"
disables = ["preamp"]
reason = "DIGI-SEL overrides preamp"

Rule kinds: mutex, disables, requires, value_limit.

[vfo] — VFO Scheme

Four schemes supported:

Scheme Receivers VFOs Example
main_sub 2 2 IC-7610
ab 1 2 IC-7300, X6100, TX-500
ab_shared 2 1 FTX-1
single 1 1 Simple QRP rigs
[vfo]
scheme = "main_sub"
main_select = [0xD0]
sub_select = [0xD1]
swap = [0xB0]
equal = [0xB1]

[commands] — Wire Bytes

Required for CI-V radios. Optional (may be empty) for Kenwood/Yaesu CAT:

[commands]
get_freq = [0x03]
set_freq = [0x05]
get_af_level = [0x14, 0x01]
# ... full list in ic7610.toml

[commands.overrides]
# Model-specific differences

For Kenwood/Yaesu radios, commands are handled by the protocol adapter, not CI-V bytes.

Other Sections

See the full schema for: [attenuator], [preamp], [agc], [spectrum], [[freq_ranges.ranges]], [cmd29], [antenna], [apf], [notch], [ssb_tx_bw], [break_in], [rit], [cw], [nb], [power].

Testing Your Rig File

# Basic load + validation
uv run python -c "
from pathlib import Path
from icom_lan.rig_loader import load_rig
cfg = load_rig(Path('rigs/ic9700.toml'))
print(cfg.model, cfg.protocol_type, cfg.receiver_count)
print('capabilities:', cfg.capabilities)
print('controls:', cfg.controls)
print('rules:', cfg.rules)
"

# Full test suite
uv run pytest tests/ -x -q

# Multi-vendor specific tests
uv run pytest tests/test_rig_multi_vendor.py -v

Common Mistakes

Mistake Error message
Missing [capabilities].features features must not be empty
Unknown capability unknown capability 'xyz'. Known: [...]
Invalid VFO scheme scheme must be one of {'ab', 'main_sub', 'ab_shared', 'single'}
Invalid protocol type type must be one of {'civ', 'kenwood_cat', 'yaesu_cat'}
Invalid control style style must be one of {'toggle', 'stepped', ...}
Invalid rule kind kind must be one of {'mutex', 'disables', ...}
CI-V addr missing for CI-V radio Parser defaults to 0 — may cause runtime errors

See Also