Skip to content

DevSkoll/rfdtool

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

9 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

rfdtool

A Linux desktop GUI for configuring RFDesign RFD900-series radio modems running the SiK firmware. Feature parity target: the official Windows-only RFD Modem Tools.

Supports RFD900, RFD900+, RFD900u (8051-based, Intel HEX firmware) and RFD900x, RFD900ux, RFD900x2 (STM32-based, .bin firmware).

Developer: Skollme@skoll.dev Part of: sUAS Tools

screenshot placeholder

Features

  • Auto-detect connected radios across every USB serial port (FTDI / CP210x / CH340).
  • Side-by-side local + remote S-register editor with friendly labels, validated ranges, and tooltips.
  • Built-in profile presets ("MAVLink defaults", "Long range / low data rate", "Point-to-point max throughput") plus JSON profile import/export.
  • Firmware update for both 8051 and STM32 radios — Intel-HEX path uses the SiK bootloader native protocol, STM32 path wraps stm32flash.
  • Live RSSI / noise chart driven by either MAVLink RADIO_STATUS packets or ATI7 polling (radio-button toggle).
  • Raw AT terminal with command history, hex-byte sends, and timestamped log.
  • Startup environment checks that warn on ModemManager interference and missing dialout group membership.

Requirements

  • Linux (tested on Ubuntu 22.04 / 24.04; should work on any modern distro)
  • Python 3.10+
  • stm32flash for RFD900x / RFD900ux firmware updates (optional; required only for STM32 flashing)

Install (development)

git clone <this repo>
cd rfdtool
python3 -m venv .venv
.venv/bin/pip install -r requirements.txt
.venv/bin/pip install pyserial   # the `pyserial` import name; pulled in by requirements as well
sudo apt install stm32flash      # optional, for RFD900x/ux flashing

Run

.venv/bin/python rfdtool.py

Useful flags:

.venv/bin/python rfdtool.py --port /dev/ttyUSB0           # auto-connect on launch
.venv/bin/python rfdtool.py --port /dev/ttyUSB0 --baud 115200
.venv/bin/python rfdtool.py --no-mavlink                  # skip RADIO_STATUS parsing
.venv/bin/python rfdtool.py --skip-checks                 # skip the startup environment checks

Build a standalone binary

.venv/bin/pip install pyinstaller
.venv/bin/pyinstaller rfdtool.spec
# output in dist/rfdtool/

Tests

The protocol layer (AT command parsing, Intel HEX parsing, XMODEM-CRC, SiK bootloader protocol, MAVLink RADIO_STATUS extraction, STM32 flash subprocess wrapper) is covered by ~200 unit tests using a mock serial port — none of them touch real hardware.

.venv/bin/python -m pytest -v

Troubleshooting

"Permission denied: /dev/ttyUSB0"

Your user is not in the dialout group:

sudo usermod -aG dialout $USER
# log out and back in (or reboot) for the group change to take effect

rfdtool checks this at startup and warns if you're not a member.

ModemManager keeps grabbing the port

If you see brief AT-command activity on the port after plugging in the radio, or commands time out the first ~10 seconds after connect, ModemManager is probing the device. Two fixes:

# Aggressive: remove ModemManager entirely (you don't need it on a desktop
# unless you have a USB cellular modem):
sudo apt remove modemmanager

# Targeted: tell ModemManager to ignore FTDI / CP210x adapters via udev:
sudo tee /etc/udev/rules.d/99-rfdtool.rules <<'EOF'
ATTRS{idVendor}=="0403", ENV{ID_MM_DEVICE_IGNORE}="1"
ATTRS{idVendor}=="10c4", ENV{ID_MM_DEVICE_IGNORE}="1"
EOF
sudo udevadm control --reload-rules
sudo udevadm trigger

Radio is "stuck in data mode" — +++ doesn't get to command mode

Symptoms: connect succeeds (/dev/ttyUSB0 opens) but the parameter list never loads, and the log shows could not enter command mode. Causes and fixes:

  • Wrong baud. The radio remembers its serial speed across reboots. Try 115200, 38400, 9600 in turn from the Connection panel.
  • Active link saturating the UART. If a flight controller is streaming MAVLink at high rate into the same UART pair, the +++ escape can be defeated. Disconnect the autopilot (or hold its boot button to silence it) and reconnect.
  • Wrong cable wiring. Verify TX/RX are crossed; the breakout silk-screens are TX from the breakout's perspective.

Firmware update bricked the radio (no banner, no AT response)

Hold the BOOT pin (also labelled CTS/IO0 on some breakouts) to ground while powering the radio on. This forces the bootloader to come up regardless of firmware state. With the BOOT pin still held:

  • For 8051 radios (RFD900/+/u): re-run a known-good .ihx flash from the Firmware tab. The bootloader is always there even if the firmware image is corrupt.
  • For STM32 radios (RFD900x/ux): re-run stm32flash against a known-good .bin. The STM32 system memory bootloader is mask-ROM and cannot be bricked.

Release the BOOT pin after the flash completes.

stm32flash: command not found when flashing an RFD900x

sudo apt install stm32flash

The Firmware tab shows this hint automatically when you try to flash a .bin without stm32flash on PATH.

Multiple radios on one host

rfdtool lists every detected serial port and highlights likely radios (FTDI / CP210x / CH340 VID/PIDs in bold). Pick the one you want from the dropdown and connect. Future versions will support driving more than one radio simultaneously from a single window.

Project layout

rfdtool.py                 entry point
rfd/                       protocol + I/O (no Qt — fully unit-tested)
  registers.py             S-register definitions, ranges, tooltips
  protocol.py              AT command builders + ATI/ATI5/ATI7 parsers
  radio.py                 RadioCore (sync) + Radio (Qt wrapper, threaded)
  detector.py              port enumeration + radio fingerprinting
  ihx.py                   Intel HEX parser
  xmodem.py                XMODEM-CRC sender (sender-only)
  mavlink_parser.py        pymavlink RADIO_STATUS extractor
  uploader_8051.py         SiK 8051 bootloader driver
  uploader_stm32.py        stm32flash subprocess wrapper
  presets.py               built-in profiles + JSON I/O
ui/                        Qt UI layer (depends on rfd/, no reverse dep)
  main_window.py           QMainWindow assembling all tabs
  connection_panel.py      port/baud/connect/LED row
  settings_tab.py          local + remote S-register editor
  terminal_tab.py          raw AT console
  rssi_tab.py              live RSSI/noise chart
  firmware_tab.py          firmware update workflow
  system_checks.py         ModemManager / dialout startup checks
  theme.py                 forced light Fusion palette
tests/                     pytest suite for the protocol layer

License

MIT — see LICENSE.

About

Linux Qt6 GUI for configuring RFD900-series SiK radio modems (RFD900/+/u/x/ux/x2)

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages