Linux and Icom IC-7300

Since Linux is my primary operating system I use on my desktop and laptop, I have only done the necessary actions for Linux to get the Icom IC-7300 properly connected. Please don't ask me how to do this on a Windows computer, I really wouldn't know. The first action is to create a serial device, after that the internal clock of the IC-7300 will be synchronized with the system clock of the computer.

Create a serial device

The most important thing is that Linux recognizes the IC-7300 as a serial device based on the USB vendor and product id's. The serial number of the IC-7300 is also taken into account so that this solution can also work when more than one IC-7300 is connected to the computer. In the example below, 12345678 in the ATTRS{serial} is the serial number of the IC-7300. If you have more than one IC-7300 you can give a serial number or other identification to the SYMLINK, for example ic7300a. This symlink will point to the serial port on which this IC-7300 is available for all kinds of applications, in my case the serial port will be known as /dev/ic7300.

Copy the line below into the file: /etc/udev/rules.d/99-icom_ic7300.rules, the exact file name is not so relevant in this example as long as it ends with .rules. If you have more than one IC-7300 then you can put several of these lines in that single file, each with its own serial number and SYMLINK.

SUBSYSTEM=="tty", ATTRS{idVendor}=="10c4", ATTRS{idProduct}=="ea60", ATTRS{serial}=="IC-7300 12345678", SYMLINK+="ic7300" RUN+="/usr/bin/Set_IC7300_time.py"

Time synchronization

As you can see the line for the udev rules ends with a RUN+ statement. This is the script that is executed after the IC-7300 is connected to the computer, or when the computer and IC-7300 are turned on. The script below should, in my example, be copied to the /usr/bin/Set_IC7300_time.py file. This elegant but simple time synchronization script was written by Kevin KB9RLW and I only adapted the baudrate, gmtoffset and serialport to my situation. The original script can be found at the github repository of Kevin.

The offset I choose depends on whether or not daylight saving time applies, I want the clock on my IC-7300 to be on UTC. Maybe I will adapt this script so that the conversion to UTC will be automatic regardless of whether or not daylight saving time applies. This script will only work for one IC-7300 if more than one IC-7300 is connected, although the script can easily be adapted to this.

#! /usr/bin/python3
#
# IC-7300 time sync by Kevin Loughin, KB9RLW. June 2019
# Ver. 1.0
# This script will set the Icom 7300 internal clock based on your computer
# clock.  Provided your computer clock is synced to network time, this
# should insure your radio's clock is within a fraction of a second of
# standard time.
#
# Below are three variables you need to change to match your location and
# radio.  If your computer clock is not set to Universal time, set the 
# offset value.
# Also the serial port name for your IC-7300 on your computer. Change to 
# match your setup. i.e. COM3 or similar for windows.
#
baudrate = 115200  #change to match your radio
gmtoffset = -2  #change to a negative or positive offset from GMT if you
#               want to use local time.  i.e. -5 for EST
serialport = "/dev/ic7300"  # Serial port of your radios serial interface.

# Defining the command to set the radios time in hex bytes.
preamble = ["0xFE", "0xFE", "0x94", "0xE0", "0x1A", "0x05", "0x00", "0x95"]
postamble = "0xfd"

#Import libraries we'll need to use
import time
import serial
import struct

# Here we get the computers current time in hours and minutes.
# Add in the offset, if any, and roll over if we exceed 23 or go below 0
# hours.  Finally appending hex byte formated time data to the command string.
t = time.localtime()
hours = time.strftime("%H")
hours = int(hours) + gmtoffset
if hours < 0:
    hours = 23 + hours
if hours > 23:
    hours = 23 - hours
hours = str(hours)

if (len(hours) < 2):
    hours = "0" + str(hours)
hours = "0x" + hours
preamble.append(hours)

minutes = (int(time.strftime("%M")) + 1)
minutes = str(minutes)
if (len(minutes) < 2):
    minutes = "0" + minutes
minutes = "0x" + minutes
preamble.append(minutes)
preamble.append('0xFD')

# Now I get the current computer time in seconds.  Needed to set the time only
# at the top of the minute.
seconds = int(time.strftime("%S"))

# Now we wait for the top of the minute.
lastsec = 1
while(seconds != 0):
   t = time.localtime()
   seconds = int(time.strftime("%S"))
   if(seconds != lastsec):
        lastsec = seconds
   time.sleep(.01)

# Now that we've reached the top of the minute, set the radios time!
ser = serial.Serial(serialport, baudrate)

count = 0
while(count < 11):
    senddata = int(bytes(preamble[count], 'UTF-8'), 16)
    ser.write(struct.pack('>B', senddata))
    count = count +1

ser.close()
# All done.  The radio is now in sync with the computer clock.