IC-7610 USB Serial Backend Setup (macOS)¶
This guide shows how to control the IC-7610 via USB serial CI-V + USB audio devices instead of the default LAN backend.
Why Use the Serial Backend?¶
- No network required — direct USB connection
- Lower latency — no UDP/network overhead
- Simpler setup — no IP config, username, or password
- Field operation — works without WiFi/Ethernet
Hardware Requirements¶
- IC-7610 transceiver
- USB A-to-B cable (typically included with the radio)
- macOS computer (tested on Ventura+ arm64/Intel)
Radio Configuration¶
Critical Setup Step
On the IC-7610, navigate to Menu → Set → Connectors → CI-V → CI-V USB Port and set it to Link to [CI-V], NOT [REMOTE].
Link to [CI-V]— serial CI-V commands work (required for icom-lan serial backend)[REMOTE]— RS-BA1 mode, serial CI-V is blocked
This finding was confirmed with live hardware validation in issue #146.
Recommended Radio Settings¶
| Setting | Value | Why |
|---|---|---|
| CI-V USB Port | Link to [CI-V] |
✅ Required — enables serial CI-V |
| CI-V USB Baud Rate | 115200 |
Recommended for scope/waterfall |
| CI-V Address | 0x98 (default) |
Library auto-detects, but confirm if changed |
| USB Audio TX | Enabled | Allows browser/WSJT-X TX via USB audio |
| USB Audio RX | Enabled | Exports RX audio to computer |
Baud Rate
115200baud is recommended for scope/waterfall capability- Lower baud rates (19200, 9600) work for basic control (freq, mode, PTT) but scope/waterfall is disabled by a guardrail due to high packet rate
- CI-V baud rate IS significant on IC-7610 — it must match between radio and library
macOS Setup¶
1. Install icom-lan¶
# Core install — includes serial CI-V (pyserial), USB audio RX/TX,
# audio-device listing (sounddevice + numpy + opuslib).
pip install icom-lan
Note
Since v0.19 the audio-bridge stack (sounddevice, numpy, opuslib)
is part of the core install. The legacy [bridge] and [audio] extras
still resolve but are now no-op aliases.
2. Connect the Radio¶
- Power on the IC-7610
- Connect USB A-to-B cable from Mac to IC-7610 USB (B) port (rear panel, square connector)
- Wait ~5 seconds for macOS to enumerate the device
3. Find the Serial Device¶
The IC-7610 typically appears as /dev/cu.usbserial-XXXXXX where XXXXXX is the radio's serial number.
You can also use icom-lan discover --serial-only to find USB-connected radios automatically:
4. Find USB Audio Devices¶
Audio-device listing requires sounddevice, which ships with the core
install since v0.19 (pip install icom-lan).
Example output:
4 audio device(s):
[0] IC-7610 USB Audio (in=2, out=2)
[1] Built-in Microphone (in=2, out=0)
[2] Built-in Output (in=0, out=2)
[3] BlackHole 2ch (in=2, out=2)
The IC-7610 USB audio device is typically named IC-7610 USB Audio or similar.
Multi-Radio: Automatic USB Audio Resolution
When two or more Icom radios are connected via USB simultaneously (e.g. IC-7300 + IC-7610),
each exposes an identically named "USB Audio CODEC" device. Specifying --rx-device by name
is ambiguous in this situation.
The serial backend automatically resolves the correct audio device using USB topology matching (macOS only): it reads each device's USB hub location from IORegistry and matches the audio device that shares the same USB hub as the serial CI-V port. No manual index specification is required.
If topology resolution fails (e.g. on Linux), the driver falls back to selecting the
first matching USB Audio CODEC device by name, which may be incorrect for multi-radio setups.
In that case, specify explicit device indices with --rx-device and --tx-device.
5. Test the Connection¶
# Set environment variables
export ICOM_SERIAL_DEVICE=/dev/cu.usbserial-111120
export ICOM_SERIAL_BAUDRATE=115200
# Test basic control
icom-lan --backend serial status
icom-lan --backend serial freq
icom-lan --backend serial mode
Expected output:
6. Test Audio (Optional)¶
# Capture 10 seconds of RX audio to WAV
icom-lan --backend serial \
--rx-device "IC-7610 USB Audio" \
audio rx --out test_rx.wav --seconds 10
# Audio devices are auto-detected if not specified
Usage Examples¶
CLI¶
# Status check
icom-lan --backend serial status
# Set frequency
icom-lan --backend serial freq 7.074m
# Set mode
icom-lan --backend serial mode USB
# PTT on/off
icom-lan --backend serial ptt on
icom-lan --backend serial ptt off
# CW keying
icom-lan --backend serial cw "CQ CQ DE KN4KYD K"
# Attenuator (uses Command29 for IC-7610)
icom-lan --backend serial att 18
icom-lan --backend serial att 0
# Preamp
icom-lan --backend serial preamp 1
icom-lan --backend serial preamp 0
Python API¶
import asyncio
from icom_lan.backends.factory import create_radio
from icom_lan.backends.config import SerialBackendConfig
async def main():
config = SerialBackendConfig(
device="/dev/cu.usbserial-111120",
baudrate=115200,
radio_addr=0x98,
rx_device="IC-7610 USB Audio", # or None for auto-detect
tx_device="IC-7610 USB Audio", # or None for auto-detect
)
radio = create_radio(config)
async with radio:
# Control
freq = await radio.get_frequency()
print(f"Frequency: {freq/1e6:.3f} MHz")
await radio.set_frequency(14_074_000)
await radio.set_mode("USB")
# Meters
s = await radio.get_s_meter()
print(f"S-meter: {s}")
# Audio (if audio_capable)
from icom_lan.radio_protocol import AudioCapable
if isinstance(radio, AudioCapable):
def on_audio(packet):
print(f"RX audio: {len(packet.data)} bytes")
await radio.start_audio_rx_opus(on_audio)
await asyncio.sleep(10)
await radio.stop_audio_rx_opus()
asyncio.run(main())
Web UI with Serial Backend¶
# Start web UI on serial backend
icom-lan --backend serial \
--rx-device "IC-7610 USB Audio" \
--tx-device "IC-7610 USB Audio" \
web
# Then open http://localhost:8080
The web UI will show: - Frequency/mode control - Meters (S-meter, power, SWR during TX) - RX audio streaming to browser - TX audio from browser microphone (if USB audio TX is enabled)
rigctld with Serial Backend¶
# Start rigctld server on serial backend
icom-lan --backend serial serve
# Then configure WSJT-X:
# Radio: Hamlib NET rigctl
# Network Server: localhost:4532
Capability Differences: LAN vs Serial¶
| Feature | LAN Backend | Serial Backend |
|---|---|---|
| Control (freq/mode/PTT) | ✅ Full | ✅ Full |
| Meters (S/SWR/ALC) | ✅ Full | ✅ Full |
| Audio RX | ✅ Opus/PCM over UDP | ✅ USB audio device |
| Audio TX | ✅ Opus/PCM over UDP | ✅ USB audio device |
| Scope/Waterfall | ✅ Full (~225 pkt/s) | ⚠️ Requires ≥115200 baud* |
| Dual Receiver | ✅ Command29 | ✅ Command29 |
| Remote Access | ✅ Over LAN/VPN | ❌ USB only |
| Discovery | ✅ UDP broadcast | ✅ CI-V auto-probe |
* Scope guardrail: Serial backend enforces a minimum 115200 baud for scope/waterfall operations due to high CI-V packet rate. Lower baud rates risk command timeout/starvation. Override is possible via allow_low_baud_scope=True or ICOM_SERIAL_SCOPE_ALLOW_LOW_BAUD=1 (use with caution).
Troubleshooting¶
"No such file or directory: /dev/cu.usbserial-..."¶
Cause: USB cable not connected, or radio not powered on.
Fix:
1. Check USB cable connection (rear panel USB (B) port on IC-7610)
2. Power-cycle the radio
3. Wait 5-10 seconds after power-on
4. Run ls -l /dev/cu.usbserial-* again
"Permission denied: /dev/cu.usbserial-..."¶
Cause: User lacks permissions to access serial device.
Fix (macOS typically doesn't need this, but if it happens):
# Add your user to the dialout group (Linux)
sudo usermod -a -G dialout $USER
# Logout and login again
On macOS, if you see permissions issues, try:
# Check ownership
ls -l /dev/cu.usbserial-*
# Typically owned by root:wheel with mode 0666 (world read/write)
# If not, contact system admin or check USB security settings
"Audio device 'IC-7610 USB Audio' not found"¶
Cause: USB audio not exported by radio, or wrong device name.
Fix: 1. Verify USB audio is enabled in radio settings: - Menu → Set → Connectors → USB Audio → Enabled 2. List available devices:
3. Use exact device name from the list (case-sensitive) 4. If still not visible, disconnect/reconnect USB cable"Scope over serial requires baudrate >= 115200"¶
Symptom: CommandError when calling enable_scope() or capture_scope_frame() with baud rate < 115200.
Cause: Scope/waterfall CI-V traffic is high-rate (~225 packets/sec on LAN). Lower serial baud rates cannot sustain this rate without starving command responses.
Fix: 1. Recommended: Set CI-V USB Baud Rate to 115200 in radio settings 2. Override (use with caution):
or Library will log a warning about timeout risk."CI-V response timed out" on serial¶
Causes:
1. Wrong baud rate — radio and library must match
2. Wrong CI-V USB Port setting — must be Link to [CI-V], not [REMOTE]
3. Serial port busy — another app (wfview, hamlib, etc.) is using the serial device
Fix: 1. Check radio baud rate: Menu → Set → Connectors → CI-V → CI-V USB Baud Rate 2. Check CI-V USB Port setting (see "Critical Setup Step" above) 3. Close other apps using the serial port:
Wrong USB audio device selected with two radios connected¶
Symptom: Audio from the wrong radio when IC-7300 and IC-7610 are both connected via USB.
Cause: Two identical "USB Audio CODEC" devices appear in the system; name-based selection picks the first one regardless of which radio's serial port is in use.
Fix: On macOS, this is resolved automatically — the library reads USB hub topology via IORegistry and selects the audio device on the same USB hub as the serial CI-V port. Check the log for a line like:
If you see "topology resolution not supported" (Linux), specify device indices explicitly:
Use icom-lan --list-audio-devices to find the correct indices.
Audio TX not working¶
Cause: Radio USB Audio TX not enabled.
Fix:
1. Menu → Set → Connectors → USB Audio → USB Audio TX → Enabled
2. Check PTT is active before transmitting audio
3. Verify --tx-device matches the USB audio device name
Environment Variables¶
For convenience, set these in your shell profile:
# ~/.bashrc or ~/.zshrc
export ICOM_SERIAL_DEVICE=/dev/cu.usbserial-111120
export ICOM_SERIAL_BAUDRATE=115200
export ICOM_USB_RX_DEVICE="IC-7610 USB Audio"
export ICOM_USB_TX_DEVICE="IC-7610 USB Audio"
# Then simply:
icom-lan --backend serial status
Migration from LAN to Serial¶
If you're currently using the LAN backend and want to switch to serial:
-
No code changes needed — use
create_radio(config)factory with typed config:# Before (LAN) from icom_lan.backends.config import LanBackendConfig config = LanBackendConfig(host="192.168.1.100", ...) # After (Serial) from icom_lan.backends.config import SerialBackendConfig config = SerialBackendConfig(device="/dev/cu.usbserial-111120", ...) # Same factory call radio = create_radio(config) -
CLI: add
--backend serialflag: -
Capability check: scope/waterfall requires ≥115200 baud (see table above)
-
Audio device selection: LAN uses Opus/PCM over UDP, serial uses USB audio devices (explicit device names or auto-detect)
Next Steps¶
- Web UI + Serial: See Web UI Guide
- rigctld + Serial: See CLI Reference
- Python API: See API Reference
- Troubleshooting: See Troubleshooting Guide
Hardware validated: 2026-03-06, IC-7610 over USB on macOS (Darwin arm64), Python 3.11.14, pytest 9.0.2 (issue #146)