Compare commits

...

11 Commits

Author SHA1 Message Date
Rob French 40c053ae9f More changes trying to get bi-directional frequency changes to work. The problem is that I can't control/predict where the H/W frequency will be relative to the VFO frequency. 2020-10-27 12:45:14 -05:00
Rob French bb5a0579b9 Did anything actually change? 2020-09-29 11:56:09 -05:00
Rob French b3887bc68d Simplified, solved the tuning step problem, but now tuning is backwards again (if I disable Swap I/Q), or just wrong (if I enable Swap I/Q). 2020-09-29 11:48:12 -05:00
Rob French 623956731c Committing since I'm about to make a large change. Everything is awesome, except that if a large step size is selected on the rig, then the Gqrx can never successfully set the rig freq. 2020-09-29 10:38:56 -05:00
Rob French 769e1ca274 Added a simple GUI. Made it so you can toggle on/off "Rig-to-GQRX" and "GQRX-to-Rig". Some of the cases aren't quite right, however. Need to separate out the LNB frequency, and make LNB frequency ALWAYS get updated based on the rig frequency, regardless of whether the the rig frequency is being used to set the GQRX frequency. 2020-09-25 22:57:41 -05:00
Rob French df4b6e419c Update 'README.md'
Format tweaks.
2020-09-22 15:25:03 +00:00
Rob French f41716f89b Updated README.md
Updated to incorporate new options added in the kc4upr branch, and to describe the added behavior.
2020-09-22 15:16:34 +00:00
Rob French 27aa7edcc0 Updated to make the frequency read out correctly (positive numbers). Notes:
- Rig-to-GQRX seems to work.
- GQRX-to-Rig seems to work.
- Frequency scale increases left to right.
- Frequency scale uses positive numbers.
So, seems to be functioning, but needs more extensive testing.
2020-09-21 23:07:17 -05:00
Rob French 4948c79d84 Seems to be a successful attempt at allowing both:
(a) rig to control GQRX
(b) GQRX to control rig
There's a 0.5 second hang time whenever a given input is made, to prevent
dueling inputs.
The key thing appears to be, whenever GQRX sets the frequency, I need to
tell the rig, but then also, tell GQRX again, so that it centers up the frequency.
Other thing to note is that the frequencies are all negative. I wonder if that
is actually necessary.
2020-09-20 23:30:40 -05:00
Rob French 44a0db9894 Saving off what I've created. It doesn't work well, yet. 2020-09-12 22:42:46 -05:00
Rob French cea01b2ac5 Added additional command-line arguments, to allow use with a remote rigctld and/or Gqrx instance. 2020-05-11 03:36:02 +00:00
2 changed files with 230 additions and 22 deletions

View File

@ -1,24 +1,34 @@
# Gqrx Panadapter
# Gqrx Panadapter (uBITX panadapter version)
A [Gqrx](http://gqrx.dk/) to [Hamlib](http://www.hamlib.org) interface that
keeps the frequency displayed in Gqrx synchronized with the frequency settings
on your radio.
Authors
- Original version: Alexander Fasching, OE5TKM
- uBITX version: Rob French, KC4UPR
The IF output of the radio should be connected to a SDR, which is then received by Gqrx.
This script continuously reads the frequency of the radio from ```rigctld```
and sets the LNB setting Gqrx.
A [Gqrx](http://gqrx.dk/) to [Hamlib](http://www.hamlib.org) interface that keeps
the frequency displayed in Gqrx synchronized with the frequency settings on your
radio. This version allows for bidirectional control: if the frequency is changed
on the radio, then it will be updated in Gqrx, and if a new frequency is selected
in Gqrx, then the radio will be tuned to that frequency.
The IF output of the radio should be connected to a SDR, which is then received by
Gqrx. This script continuously reads the frequency of the radio from ```rigctld```
and sets the LNB and frequency settings in Gqrx. In addition, if a new frequency
is selected in Gqrx by clicking on the waterfall, then the script will command a
new frequency to ```rigctld``` to update the radio's frequency.
## Usage
```
gqrx-panadapter.py [-h] [-g P] [-r P] [-i T] [-f F]
gqrx-panadapter.py [-h] [-ga A] [-gp P] [-ra A] [-rp P] [-i T] [-f F]
optional arguments:
-h, --help show this help message and exit
-g P, --gqrx-port P remote control port configured in Gqrx
-r P, --rigctld-port P listening port of rigctld
-i T, --interval T update interval in milliseconds
-f F, --ifreq F intermediate frequency in MHz
-h, --help show this help message and exit
-ga A, --gqrx-address A address that Gqrx is listening on
-gp P, --gqrx-port P remote control port configured in Gqrx
-ra A, --rigctld-address A address that rigctld is listening on
-rp P, --rigctld-port P listening port of rigctld
-i T, --interval T update interval in milliseconds
-f F, --ifreq F intermediate frequency in MHz
```
Make sure you configure [remote control](http://gqrx.dk/doc/remote-control) in Gqrx.

View File

@ -23,11 +23,138 @@ import argparse
import socket
import time
import Tkinter
from Tkinter import *
DEBUG=True
delay_secs = 0.05 # 50 msec delay
timeout = 0.0
usb_if_offset = 0 #-3000 # 0 #-2250
lsb_if_offset = 0 #3000 # -1000 #0
rs = 0
gs = 0
#class TmpSettings:
# def __init__(self):
# self.RIG_TO_GQRX = IntVar(1)
# self.GQRX_TO_RIG = IntVar(1)
def freq_to_string(freq):
freq_str = str(freq).rjust(9)
return freq_str[0:3] + "." + freq_str[3:6] + "." + freq_str[6:9]
#MHz = int(freq/1000000)
#kHz = int(freq/1000)-(MHz*1000)
#Hz = freq - ((MHz*1000000)+(kHz*1000))
#return str(MHz) + "." + str(kHz) + "." + str(Hz)
class MainWindow:
def __init__(self, root, rig_name="uBITX"):
self.__root = root
self.__root.title("Gqrx Panadapter - " + rig_name)
self.rig_to_gqrx = IntVar()
self.gqrx_to_rig = IntVar()
self.rig_freq = StringVar()
self.gqrx_freq = StringVar()
self.rig_mode = StringVar()
self.__rig_frame = Frame(self.__root, relief=GROOVE, bd=3)
self.__rig_frame.grid(row=0, column=0)
self.__rig_freq_lbl = Label(self.__rig_frame, text="Rig Freq: ")
self.__rig_freq_lbl.grid(row=0, column=0, padx=5)
self.__rig_freq_val = Label(self.__rig_frame, textvariable=self.rig_freq)
self.__rig_freq_val.grid(row=0, column=1, padx=5)
self.__rig_mode_lbl = Label(self.__rig_frame, text="Mode: ")
self.__rig_mode_lbl.grid(row=0, column=2, padx=5)
self.__rig_mode_val = Label(self.__rig_frame, textvariable=self.rig_mode)
self.__rig_mode_val.grid(row=0, column=3, padx=5)
self.__r2g_ctrl = Checkbutton(self.__rig_frame, text="Rig-to-Gqrx", variable=self.rig_to_gqrx)
self.__r2g_ctrl.grid(row=0, column=4, padx=5)
self.rig_to_gqrx.set(1)
self.__gqrx_frame = Frame(self.__root, relief=GROOVE, bd=3)
self.__gqrx_frame.grid(row=0, column=1)
self.__gqrx_freq_lbl = Label(self.__gqrx_frame, text="Gqrx Freq: ")
self.__gqrx_freq_lbl.grid(row=0, column=0, padx=5)
self.__gqrx_freq_val = Label(self.__gqrx_frame, textvariable=self.gqrx_freq)
self.__gqrx_freq_val.grid(row=0, column=1, padx=5)
self.__g2r_ctrl = Checkbutton(self.__gqrx_frame, text="Gqrx-to-Rig", variable=self.gqrx_to_rig)
self.__g2r_ctrl.grid(row=0, column=2, padx=5)
self.gqrx_to_rig.set(1)
#self.__hw_freq = Entry(self.__gqrx_frame, text=H
def calc_lnb_lo(freq, ifreq, isusb=True):
if DEBUG:
print('Freq: ' + str(freq))
print('IF Freq: ' + str(ifreq))
if isusb:
if DEBUG:
print('USB IF: ' + str(ifreq + usb_if_offset))
#return - freq - (ifreq - usb_if_offset)
#return freq + usb_if_offset - (ifreq + (129600*2)) # need to make this configurable; would be great to get it from Gqrx
return freq - (ifreq + 129600*2 + usb_if_offset)
else:
if DEBUG:
print('LSB IF: ' + str(ifreq + lsb_if_offset))
#return - freq - (ifreq + lsb_if_offset)
#return freq + lsb_if_offset - (ifreq + (129600*2)) # need to make this configurable; would be great to get it from Gqrx
return freq - (ifreq + 129600*2 + lsb_if_offset)
def get_rig_freq(rs):
rs.send(b'm\n')
is_usb = True if rs.recv(1024).splitlines()[0] == "USB" else False
rs.send(b'f\n')
return (int(rs.recv(1024)), is_usb)
def set_rig_freq(rs, freq):
if DEBUG:
print('Set Rig freq: {}'.format(freq).encode())
rs.send(b'F ' + str(freq) + '\n')
rs.recv(1024)
def get_gqrx_freq(gs):
gs.send(b'f\n')
return int(gs.recv(1024)) #* -1
def set_gqrx_freq(gs, freq):
if DEBUG:
print('Set GQRX Freq: {}'.format(freq).encode())
gs.send('F {}'.format(freq).encode())
gs.recv(1024)
def set_gqrx_lnb_lo(gs, freq, ifreq, isusb):
lnb = calc_lnb_lo(freq, ifreq, isusb)
if DEBUG:
print('Set LNB Freq: {}'.format(lnb).encode())
gs.send('LNB_LO {}'.format(lnb).encode())
gs.recv(1024)
def reset_gqrx(gs, ifreq):
set_gqrx_lnb_lo(gs, 0, 0, True)
set_gqrx_freq(gs, 28800000)
set_gqrx_freq(gs, ifreq)
def main():
parser = argparse.ArgumentParser()
parser.add_argument('-g', '--gqrx-port', type=int, default=7356,
parser.add_argument('-ga', '--gqrx-address', type=str, default='localhost',
metavar='A', help='address that Gqrx is listening on')
parser.add_argument('-gp', '--gqrx-port', type=int, default=7356,
metavar='P', help='remote control port configured in Gqrx')
parser.add_argument('-r', '--rigctld-port', type=int, default=4532,
parser.add_argument('-ra', '--rigctld-address', type=str, default='localhost',
metavar='A', help='address that rigctld is listening on')
parser.add_argument('-rp', '--rigctld-port', type=int, default=4532,
metavar='P', help='listening port of rigctld')
parser.add_argument('-i', '--interval', type=int, default=1000,
metavar='T', help='update interval in milliseconds')
@ -38,29 +165,100 @@ def main():
try:
rs = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
rs.connect(('127.0.0.1', args.rigctld_port))
rs.connect((args.rigctld_address, args.rigctld_port))
except Exception as e:
print('Connection to rigctld failed:', e, file=sys.stderr)
return 1
try:
gs = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
gs.connect(('127.0.0.1', args.gqrx_port))
gs.connect((args.gqrx_address, args.gqrx_port))
except Exception as e:
print('Connection to Gqrx failed:', e, file=sys.stderr)
return 1
try:
if_freq = int(args.ifreq * 1e6)
#reset_gqrx(gs, if_freq)
old_is_usb = False
old_rig_freq = -1 # force initial update
old_gqrx_freq = -1 # force initial update
(rig_freq, is_usb) = get_rig_freq(rs)
gqrx_freq = get_gqrx_freq(gs)
tk = Tk()
window = MainWindow(tk)
while True:
rs.send(b'f\n')
allow_rig_to_gqrx = window.rig_to_gqrx.get()
allow_gqrx_to_rig = window.gqrx_to_rig.get()
rigfreq = int(rs.recv(1024))
lnbfreq = rigfreq - int(args.ifreq * 1e6)
(rig_freq, is_usb) = get_rig_freq(rs)
gqrx_freq = get_gqrx_freq(gs)
gs.send('LNB_LO {}'.format(lnbfreq).encode())
gs.recv(1024)
#-----------------------------------------------------------------
# Update the GUI, if the freqs/modes have changed.
#-----------------------------------------------------------------
if rig_freq != old_rig_freq or is_usb != old_is_usb:
window.rig_freq.set(freq_to_string(rig_freq))
if is_usb:
window.rig_mode.set("USB")
else:
window.rig_mode.set("LSB")
if gqrx_freq != old_gqrx_freq:
window.gqrx_freq.set(freq_to_string(gqrx_freq))
#-----------------------------------------------------------------
# Update the Rig and/or Gqrx, as applicable
#-----------------------------------------------------------------
# Regardless of anything else, if the rig freq changes, the
# LNB LO frequency must be updated (even if allow_rig_to_gqrx is
# false).
if rig_freq != old_rig_freq or is_usb != old_is_usb:
#if abs(rig_freq - old_rig_freq) > 500000:
# reset_gqrx(gs, if_freq)
if DEBUG:
print("\nRig freq changed -- update LNB LO\n")
set_gqrx_lnb_lo(gs, rig_freq, if_freq, is_usb)
set_gqrx_freq(gs, gqrx_freq)
#time.sleep(delay_secs)
if allow_rig_to_gqrx and (rig_freq != old_rig_freq or is_usb != old_is_usb):
if DEBUG:
print("\nRig freq to Gqrx freq\n")
set_gqrx_lnb_lo(gs, rig_freq, if_freq, is_usb)
set_gqrx_freq(gs, rig_freq)
#time.sleep(delay_secs)
elif allow_gqrx_to_rig and gqrx_freq != old_gqrx_freq:
if DEBUG:
print("\nGqrx freq to Rig freq\n")
# First set the rig frequency,then wait to ensure it takes.
set_rig_freq(rs, gqrx_freq)
#time.sleep(delay_secs)
# Now grab the rig frequency and use it to re-set the Gqrx
# frequency. This is due to the fact that tuning steps on
# the rig may prevent the actual Gqrx frequency from being
# set, so Gqrx will use whatever the rig accepted.
(rig_freq, is_usb) = get_rig_freq(rs)
set_gqrx_lnb_lo(gs, rig_freq, if_freq, is_usb)
set_gqrx_freq(gs, rig_freq)
#time.sleep(delay_secs)
tk.update_idletasks()
tk.update()
time.sleep(args.interval / 1000.0)
old_is_usb = is_usb
old_rig_freq = rig_freq
old_gqrx_freq = gqrx_freq
except KeyboardInterrupt:
pass
except Exception as e: