-----
The Flex Radio 6400 is an amazing state of the art ham radio transceiver with so many modern bells and whistles than no normal human could ever get around to using them all. However, this can also put off many olde tyme hams that resist changes from the Golden Age of Radio. In an effort to ease this transition we had to create the Drifty Flex application. As helpful as this has been, there was still the common complaint that "Dammit, real radios have knobs!". So, to assist again with the transition to Flex Radio we launched a new project.
-----
One fantastic feature Flex provides is access to the rig API. This has allowed for many amazing third party programs to be developed and also allows any user to create their on applications. This is exactly what we did here. The Python script below monitors a FT232RL FTDI USB to RS232 Converter to detect pulses from the rotary dial phone. Those pulse are interpreted as numbers to build a frequency for the FlexRadio to tune to. After the frequency is "dial in" the Python program sends the API command to the rig to change to that frequency. The hardware and software are pretty straight forward.
-----
Hook it up like this:
Run the script and this is what you get this:
A convenient, satisfying, and familiar analog input for your modern radio.-----
#
# FlexRadio Dial Up Interface
# www.WhiskeyTangloHotel.Com
# June 2025#
#
# Use an old Rotary Dial phone to change frequency on your FlexRadio.
# Program runs under Window with Python3.
#
# Uses FT232RL FTDI Module [USB to TTL serial] with a 10K resistor.
#
# +5V from FTDI VCC pin
# |
# |
# [ 10kΩ ]
# |
# +-------------------+
# | |
# FTDI CTS pin Rotary Dial Switch
# (Normally closed,
# | opens during pulse)
# |
# GND <-------------+
# (FTDI GND pin) |
# |
# GND <----------------+
# (Rotary phone body ground or second switch terminal)
import serial
import time
import socket
import sys
import msvcrt
# >>>>> Rotary Pulse Detection Settings. Set to your COM port <<<<<
ser = serial.Serial('COM21', baudrate=9600, timeout=1)
prev_cts = ser.cts
pulse_count = 0
number = ""
last_pulse_time = None
last_activity_time = None
# >>>>> FlexRadio Control Settings <<<<<
DEBUG = "OFF" # Turn on to show vebose comments that could be helpful for debugging
IP_ADDRESS = "192.168.1.2" # <<< Replace with your FlexRadio IP address
PORT = 4992
MODE = "CW"
BANDWIDTH_HZ = 2800
SLICE_INDEX = 0 # 0 = Slice A
print("Ready: Dial in the frequency...")
def send_cmd(sock, cmd, sequence):
sock.send(cmd.encode())
sequence += 1
time.sleep(0.5)
response = sock.recv(4096).decode()
return response, sequence
try:
while True:
cts = ser.cts
current_time = time.time()
# Detect falling edge pulse from rotary dial
if prev_cts and not cts:
pulse_count += 1
last_pulse_time = current_time
last_activity_time = current_time
# Build freq number if input detected between 0.25 and 3 seconds
if pulse_count > 0 and last_pulse_time:
if 0.250 <= (current_time - last_pulse_time) <= 3:
digit = pulse_count if pulse_count != 10 else 0
number += str(digit)
print(f"Digit entered: {digit} | Frequency so far: {number}")
pulse_count = 0
last_pulse_time = None
# If >3 sec since last pulse, treat number as complete
if number and last_activity_time and (current_time - last_activity_time) > 3.0:
print(f"\nTuning to Frequency: {number}")
# Format number for FlexRadio
FrequencyString = number
try:
FREQUENCY_HZ = int(float(FrequencyString) / 1000 * 1_000_000)
if DEBUG == "ON":
print(f"Prepared settings:")
print(f" Frequency: {FREQUENCY_HZ / 1_000_000:.3f} MHz")
print(f" Mode: {MODE}")
print(f" Filter Bandwidth: {BANDWIDTH_HZ} Hz")
print(f" Slice: {SLICE_INDEX}")
except ValueError:
print("Invalid frequency input. Expected format like '14114.000'.")
number = ""
continue
# Send to FlexRadio automatically, no keyboard interaction
sock = None
client_handle = None
sequence = 1
try:
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.settimeout(5)
sock.connect((IP_ADDRESS, PORT))
if DEBUG == "ON":
print(f"\nConnected to FlexRadio at {IP_ADDRESS}:{PORT}")
response = sock.recv(4096).decode()
for line in response.splitlines():
if line.startswith("H"):
client_handle = line[1:]
if DEBUG == "ON":
print(f"Client handle assigned: {client_handle}")
if not client_handle and DEBUG == "ON":
print("Warning: No client handle received.")
except Exception as e:
print(f"Connection failed: {e}")
sock = None
if sock and client_handle:
resp, sequence = send_cmd(sock, f"C{sequence}|slice list\n", sequence)
if DEBUG == "ON":
print(f"Slice list response:\n{resp}")
freq_mhz = FREQUENCY_HZ / 1_000_000
send_cmd(sock, f"C{sequence}|slice tune {SLICE_INDEX} {freq_mhz:.6f}\n", sequence)
send_cmd(sock, f"C{sequence}|filter set {SLICE_INDEX} low=0 high={BANDWIDTH_HZ}\n", sequence)
send_cmd(sock, f"C{sequence}|transmit set slice={SLICE_INDEX}\n", sequence)
send_cmd(sock, f"C{sequence}|client disconnect {client_handle}\n", sequence)
sock.close()
print("Radio settings applied successfully!!!")
print(" ")
print(" ")
print("Ready to detect rotary dial pulses for frequency...")
# Reset for next number
number = ""
pulse_count = 0
last_pulse_time = None
last_activity_time = None
prev_cts = cts
time.sleep(0.01)
except KeyboardInterrupt:
print("\nBye for now...")
finally:
ser.close()
-----