Project

General

Profile

Actions

DevelopersAdd a Radio » History » Revision 10

« Previous | Revision 10/29 (diff) | Next »
Dan Smith, 12/10/2022 05:48 AM


How to add a new radio driver

You've got a radio that's not in Chirp, a little bit of software development experience, and you want to add that radio to Chirp. Here's what you'll need:

Setting up the development environment

If you want to develop in another operating system, you're on your own. This guide isn't going to cover it. Here's a guide for Windows: DevelopersWin32Environment.

Look over some existing code

Read source:chirp/drivers/template.py. The whole thing.

This serves as a starting point for understanding the structure of a driver for a radio that operates in "clone mode", which is by far the most common type of radio and CHIRP driver. If your radio will operate in "live mode", and especially if your radio uses the CAT protocol, you should probably start by reading source:chirp/drivers/kenwood_live.py.

Write the download/upload routines

Sniffing the protocol used by existing software

If you have other programming software for your radio, such as the software from the manufacturer, you can sniff the serial programming protocol with Portmon. Typically, radio programming software is written for Windows, and Portmon is a Windows utility.

For recent versions of Windows, you might try sniffing USB with USBPcap. The captured data is analysed with any recent version of Wireshark.

Start with a read.

  1. Click Read in the official software
  2. Watch the output of Portmon after you click Read
  3. Look for a line that sets the BAUD RATE. Sometimes there are a few of them.
  4. Look for a WRITE line with a few data bytes. This is probably the command to tell the radio to start sending data.
  5. Look for READ lines with lots of data bytes after them. This is probably the memory contents of the radio being downloaded
  6. You're a smart developer. You should be able to figure out the protocol from here!

You can also sniff a many Windows programs by running them in the Wine environment under Linux. Manufacturers' radio programming software is likely to run in this environment. See DevelopersUSB Sniffing in Linux.

h3. Using existing Chirp code

If the radio you're developing for doesn't have existing programming software, you won't be able to use the above reverse engineering technique. Most radio manufacturers use a common protocol across most of their radios. Because Chirp supports so many manufacturers, there's a chance an existing radio driver has a download routine that will work with your new radio. This is especially true with Yaesu radios (other than the FT-4/FT-65 family), which don't really even have a protocol. They just dump their memory. All you need to figure out is the baud rate and the memory size (and baud rate is usually 9600).

Choose a radio driver that you think might be similar. If you were going to add the VX9, you might start with the VX8 driver:

$ cd chirp/chirp
$ sed s/VX8/VX9/g vx8.py > vx9.py

Increase the _memsize variable significantly. The goal is to read more data than the radio sends.

Launch Chirp and start a download with your new radio driver. Did it work, sort of? Save the .img.

Now we're going to determine the _memsize. Open the .img in a hex editor:

$ hexdump -C VX9_oversize.img | less

Look towards the end of the file for the offset where the data becomes all zeros. This is your _memsize. The radio has stopped sending data, but Chirp was still "reading". Change _memsize in your driver so that Chirp reads the same number of bytes the radio is sending.

h2. Map the memory blob

To map the memory layout, you're going to make a small change on the radio, do a download, then look for differences. Do this over and over until you have the whole memory layout mapped.

Here's a little helper script I use for the comparisons:

hexdiff.sh:

#!/bin/sh

A=`mktemp`
B=`mktemp`

hexdump -C $1 > $A
hexdump -C $2 > $B
diff $A $B | less
rm $A $B
  1. Find the first channel
  2. Find the second channel
  3. The offset between the two is your memory channel struct size
  4. Find the last channel. Hopefully its offset is struct size * advertised number of channels away from the first channel!

You'll probably start off with something like this:

MEM_FORMAT = """
#seekto 0xb00;
struct {
  u32 freq;
  u8 unknown1;
  u8 unknown2;
  u8 unknown3;
  char name[8];
} memory[200];
"""

0xb00 is the location of the first memory channel.
200 is the number of channels the radio supports.
unknown1, unknown2, and unknown3 are for memory-specific settings (e.g., tone) that you haven't sussed out yet.

Write get_memory()

Write set_memory()

Add an image of your radio to the tree

Save it to tests/images/Vendor_Model.img

Run tests

Make sure all the tests pass before you submit:

$ tox

Submit code to github

Updated by Dan Smith about 2 years ago · 10 revisions