Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7e8a0846f7 | ||
|
|
fb888a2e08 | ||
|
|
78a1ca3d60 |
@@ -1,3 +1,24 @@
|
|||||||
|
Quisk Version 4.2.40 November 2024
|
||||||
|
===================================
|
||||||
|
Python 3.13 eliminated the telnetlib module, so I wrote a replacement. I fixed a bug in window sizing.
|
||||||
|
If you use the Dx Cluster feature, please report any problems. Dx Cluster used to use the telnetlib module
|
||||||
|
but is now new code.
|
||||||
|
|
||||||
|
I updated the install to Python 3.13. Please report any problems with Python 3.13.
|
||||||
|
|
||||||
|
Quisk Version 4.2.39 October 2024
|
||||||
|
==================================
|
||||||
|
I added an optional Hardware method PollGuiControl(self). If you define this in your Hardware file,
|
||||||
|
the GUI thread will call it frequently. It can be used to set PTT from your hardware.
|
||||||
|
|
||||||
|
I am trying to work around a wxPython quirk that causes mouse wheel tuning to fail. Please test.
|
||||||
|
|
||||||
|
Quisk Version 4.2.38 September 2024
|
||||||
|
====================================
|
||||||
|
This is a bugfix release. I fixed a bug in the Hamlib serial port when using a physical TTY instead
|
||||||
|
of a pseudo-tty. The Hamlib ZZFA command now changes the receive frequency instead of the transmit
|
||||||
|
frequency. I fixed some window sizing issues.
|
||||||
|
|
||||||
Quisk Version 4.2.37 August 2024
|
Quisk Version 4.2.37 August 2024
|
||||||
=================================
|
=================================
|
||||||
Quisk now has a new option "Fixed tune offset" on the Config/radio/Options screen. This is meant for
|
Quisk now has a new option "Fixed tune offset" on the Config/radio/Options screen. This is meant for
|
||||||
|
|||||||
+1
-1
@@ -1,2 +1,2 @@
|
|||||||
#Quisk version 4.2.37
|
#Quisk version 4.2.40
|
||||||
from .quisk import main
|
from .quisk import main
|
||||||
|
|||||||
+87
-39
@@ -1,9 +1,9 @@
|
|||||||
from __future__ import absolute_import
|
|
||||||
# This code was contributed by Christof, DJ4CM. Many Thanks!!
|
# This code was contributed by Christof, DJ4CM. Many Thanks!!
|
||||||
|
# Modified November 2024 by N2ADR to remove deprecated telnetlib module.
|
||||||
|
|
||||||
import threading
|
import threading
|
||||||
|
import socket
|
||||||
import time
|
import time
|
||||||
import telnetlib
|
|
||||||
import quisk_conf_defaults as conf
|
import quisk_conf_defaults as conf
|
||||||
|
|
||||||
class DxEntry:
|
class DxEntry:
|
||||||
@@ -81,61 +81,109 @@ class DxEntry:
|
|||||||
|
|
||||||
class DxCluster(threading.Thread):
|
class DxCluster(threading.Thread):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.do_init = 1
|
self.error = 'Starting'
|
||||||
|
self.dxSpots = []
|
||||||
threading.Thread.__init__(self)
|
threading.Thread.__init__(self)
|
||||||
self.doQuit = threading.Event()
|
self.doQuit = threading.Event()
|
||||||
self.dxSpots = []
|
|
||||||
self.doQuit.clear()
|
self.doQuit.clear()
|
||||||
|
self.dxLock = threading.Lock()
|
||||||
|
self.addr = conf.dxClHost + ':' + str(conf.dxClPort)
|
||||||
|
self.msg_no_spots = "No DX Cluster data from " + self.addr
|
||||||
|
self.msg_one_spot = '1 DX spot received from ' + self.addr
|
||||||
|
self.msg_spots = ' DX spots received from ' + self.addr
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
self.telnetInit()
|
|
||||||
self.telnetConnect()
|
self.telnetConnect()
|
||||||
|
if self.error:
|
||||||
|
self.sock.close()
|
||||||
|
return
|
||||||
while not self.doQuit.isSet():
|
while not self.doQuit.isSet():
|
||||||
try:
|
try:
|
||||||
self.telnetRead()
|
by = self.sock.recv(1024)
|
||||||
|
except TimeoutError:
|
||||||
|
continue
|
||||||
except:
|
except:
|
||||||
self.tn.close()
|
by = b''
|
||||||
time.sleep(20)
|
if by:
|
||||||
|
with self.dxLock:
|
||||||
|
self.bytes += by
|
||||||
|
else:
|
||||||
|
self.sock.close()
|
||||||
|
self.error = "Restarting " + self.addr
|
||||||
|
time.sleep(2)
|
||||||
if not self.doQuit.isSet():
|
if not self.doQuit.isSet():
|
||||||
self.telnetConnect()
|
self.telnetConnect()
|
||||||
self.tn.close()
|
if self.error:
|
||||||
|
self.sock.close()
|
||||||
def setListener (self, listener):
|
return
|
||||||
self.listener = listener
|
self.sock.close()
|
||||||
|
|
||||||
def telnetInit(self):
|
|
||||||
self.tn = telnetlib.Telnet()
|
|
||||||
|
|
||||||
def telnetConnect(self):
|
def telnetConnect(self):
|
||||||
|
self.bytes = bytearray(0)
|
||||||
|
self.error = 'Starting'
|
||||||
|
self.sock = socket.socket()
|
||||||
|
self.sock.settimeout(20)
|
||||||
|
try:
|
||||||
|
self.sock.connect( (conf.dxClHost, conf.dxClPort) )
|
||||||
|
except:
|
||||||
|
self.error = "Failed to connect to " + self.addr
|
||||||
|
return
|
||||||
|
self.sock.settimeout(1)
|
||||||
for i in range(10):
|
for i in range(10):
|
||||||
try:
|
try:
|
||||||
self.tn.open(conf.dxClHost, conf.dxClPort, 10)
|
self.bytes += self.sock.recv(1024)
|
||||||
self.tn.read_until(b"login:", 10)
|
|
||||||
self.tn.write(conf.user_call_sign.encode('utf-8', errors='ignore') + b"\n") # user_call_sign may be Unicode
|
|
||||||
break
|
|
||||||
except:
|
except:
|
||||||
time.sleep(0.5)
|
pass
|
||||||
|
if b"login:" in self.bytes:
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
self.error = 'No "login:" prompt from ' + self.addr
|
||||||
|
return
|
||||||
|
self.sock.sendall(conf.user_call_sign.encode('utf-8', errors='ignore') + b"\r\n")
|
||||||
if conf.dxClPassword:
|
if conf.dxClPassword:
|
||||||
self.tn.read_until(b"Password: ")
|
for i in range(10):
|
||||||
self.tn.write(conf.dxClPassword.encode('utf-8', errors='ignore') + b"\n")
|
try:
|
||||||
|
self.bytes += self.sock.recv(1024)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
if b"Password:" in self.bytes:
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
self.error = 'No "Password:" prompt from ' + self.addr
|
||||||
|
return
|
||||||
|
self.sock.sendall(conf.dxClPassword.encode('utf-8', errors='ignore') + b"\r\n")
|
||||||
|
self.error = ''
|
||||||
|
self.bytes = bytearray(0)
|
||||||
|
|
||||||
def telnetRead(self):
|
def Poll(self):
|
||||||
message = self.tn.read_until(b'\n', 60).decode(encoding='utf-8', errors='replace')
|
with self.dxLock:
|
||||||
if self.doQuit.isSet() == False:
|
index = self.bytes.find(b"\n")
|
||||||
dxEntry = DxEntry();
|
if index >= 0:
|
||||||
if dxEntry.parseMessage(message):
|
message = self.bytes[0:index + 1]
|
||||||
for i, listElement in enumerate(self.dxSpots):
|
self.bytes = self.bytes[index + 1:]
|
||||||
if (listElement.equal(dxEntry)):
|
else:
|
||||||
listElement.join (dxEntry)
|
return
|
||||||
return
|
message = message.decode(encoding='utf-8', errors='replace')
|
||||||
if listElement.isExpired():
|
dxEntry = DxEntry()
|
||||||
del (self.dxSpots[i])
|
if dxEntry.parseMessage(message):
|
||||||
self.dxSpots.append(dxEntry)
|
for i, listElement in enumerate(self.dxSpots):
|
||||||
if self.listener:
|
if (listElement.equal(dxEntry)):
|
||||||
self.listener()
|
listElement.join (dxEntry)
|
||||||
|
return True
|
||||||
def getHost(self):
|
if listElement.isExpired():
|
||||||
return self.tn.host + ':' + str(self.tn.port)
|
del (self.dxSpots[i])
|
||||||
|
self.dxSpots.append(dxEntry)
|
||||||
|
return True
|
||||||
|
|
||||||
def stop(self):
|
def stop(self):
|
||||||
self.doQuit.set()
|
self.doQuit.set()
|
||||||
|
|
||||||
|
def dxStatus(self):
|
||||||
|
if self.error:
|
||||||
|
return self.error
|
||||||
|
nSpots = len(self.dxSpots)
|
||||||
|
if nSpots == 0:
|
||||||
|
return self.msg_no_spots
|
||||||
|
elif nSpots == 1:
|
||||||
|
return self.msg_one_spot
|
||||||
|
return str(nSpots) + self.msg_spots
|
||||||
|
|||||||
@@ -402,6 +402,8 @@ class Hardware(BaseHardware):
|
|||||||
if do_tx:
|
if do_tx:
|
||||||
try:
|
try:
|
||||||
self.rx_udp_socket.send(s)
|
self.rx_udp_socket.send(s)
|
||||||
|
if DEBUG:
|
||||||
|
self.PrintStatus(' Send', self.want_udp_status)
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
def SetVNA(self, key_down=None, vna_start=None, vna_stop=None, vna_count=None, do_tx=False):
|
def SetVNA(self, key_down=None, vna_start=None, vna_stop=None, vna_count=None, do_tx=False):
|
||||||
|
|||||||
@@ -91,6 +91,8 @@ class Hardware(BaseHardware):
|
|||||||
conf.si570_direct_control = False
|
conf.si570_direct_control = False
|
||||||
conf.si570_xtal_freq = 114285000
|
conf.si570_xtal_freq = 114285000
|
||||||
conf.repeater_delay = 0.25
|
conf.repeater_delay = 0.25
|
||||||
|
self.ptt_count = 200
|
||||||
|
self.ptt_on = 0
|
||||||
BaseHardware.__init__(self, app, conf)
|
BaseHardware.__init__(self, app, conf)
|
||||||
QS.set_sparams(multus_cw_samples=1)
|
QS.set_sparams(multus_cw_samples=1)
|
||||||
self.use_softrock = True
|
self.use_softrock = True
|
||||||
@@ -104,6 +106,13 @@ class Hardware(BaseHardware):
|
|||||||
self.usb_dev.ctrl_transfer(OUT, address, self.si570_i2c_address + 0x700, 0, message)
|
self.usb_dev.ctrl_transfer(OUT, address, self.si570_i2c_address + 0x700, 0, message)
|
||||||
if DEBUG:
|
if DEBUG:
|
||||||
print ("USB send to 0x%X" % address, message)
|
print ("USB send to 0x%X" % address, message)
|
||||||
|
def TransferIn(self, address, length):
|
||||||
|
if self.usb_dev:
|
||||||
|
recv = self.usb_dev.ctrl_transfer(IN, address, self.si570_i2c_address + 0x700, 0, length)
|
||||||
|
if DEBUG:
|
||||||
|
print ("USB receive from 0x%X" % address, recv)
|
||||||
|
return recv
|
||||||
|
return None
|
||||||
def open(self):
|
def open(self):
|
||||||
text = BaseHardware.open(self)
|
text = BaseHardware.open(self)
|
||||||
self.InitKeyer()
|
self.InitKeyer()
|
||||||
@@ -120,8 +129,20 @@ class Hardware(BaseHardware):
|
|||||||
print ("Mode is not CW")
|
print ("Mode is not CW")
|
||||||
self.TransferOut(0x70, cw_mode)
|
self.TransferOut(0x70, cw_mode)
|
||||||
return ret
|
return ret
|
||||||
def PollCwKey(self): # Called frequently by Quisk to check the CW key status
|
def PollCwKey(self): # Called frequently from the sound thread to check the CW key status
|
||||||
return # Quisk is always in Rx
|
return # Quisk is always in Rx
|
||||||
|
def PollGuiControl(self): # Called frequently from the GUI thread
|
||||||
|
self.ptt_count -= 1
|
||||||
|
if self.ptt_count <= 0:
|
||||||
|
self.ptt_count = 200
|
||||||
|
reply = self.TransferIn(0xA5, 1)
|
||||||
|
if DEBUG:
|
||||||
|
print ("PollGuiControl got", reply)
|
||||||
|
if reply:
|
||||||
|
ptt = reply[0] # This is 255 for error
|
||||||
|
if ptt in (0, 1) and ptt != self.ptt_on:
|
||||||
|
self.ptt_on = ptt
|
||||||
|
self.application.pttButton.SetValue(ptt, True)
|
||||||
def InitKeyer(self):
|
def InitKeyer(self):
|
||||||
# Initialize the keyer parameters
|
# Initialize the keyer parameters
|
||||||
conf = self.conf
|
conf = self.conf
|
||||||
|
|||||||
@@ -334,6 +334,7 @@ class HamlibHandlerSerial:
|
|||||||
self.public_name = public_name # the public name for the serial port
|
self.public_name = public_name # the public name for the serial port
|
||||||
self.tune_step = 1000
|
self.tune_step = 1000
|
||||||
if sys.platform == 'win32' or public_name.startswith("/dev/"):
|
if sys.platform == 'win32' or public_name.startswith("/dev/"):
|
||||||
|
self.port_is_mod_serial = True # self.port is from the serial module
|
||||||
try:
|
try:
|
||||||
import serial
|
import serial
|
||||||
except:
|
except:
|
||||||
@@ -346,6 +347,7 @@ class HamlibHandlerSerial:
|
|||||||
print ("The serial port %s could not be opened." % public_name)
|
print ("The serial port %s could not be opened." % public_name)
|
||||||
else:
|
else:
|
||||||
import tty
|
import tty
|
||||||
|
self.port_is_mod_serial = False # self.port is a file descriptor
|
||||||
if os.path.lexists(public_name):
|
if os.path.lexists(public_name):
|
||||||
try:
|
try:
|
||||||
os.remove(public_name)
|
os.remove(public_name)
|
||||||
@@ -369,7 +371,7 @@ class HamlibHandlerSerial:
|
|||||||
def open(self):
|
def open(self):
|
||||||
return
|
return
|
||||||
def close(self):
|
def close(self):
|
||||||
if sys.platform == 'win32':
|
if self.port_is_mod_serial:
|
||||||
if self.port:
|
if self.port:
|
||||||
self.port.close()
|
self.port.close()
|
||||||
self.port = None
|
self.port = None
|
||||||
@@ -382,7 +384,7 @@ class HamlibHandlerSerial:
|
|||||||
def Read(self):
|
def Read(self):
|
||||||
if self.port is None:
|
if self.port is None:
|
||||||
return
|
return
|
||||||
if sys.platform == 'win32':
|
if self.port_is_mod_serial:
|
||||||
text = self.port.read(99)
|
text = self.port.read(99)
|
||||||
if not isinstance(text, Q3StringTypes):
|
if not isinstance(text, Q3StringTypes):
|
||||||
text = text.decode('utf-8')
|
text = text.decode('utf-8')
|
||||||
@@ -433,22 +435,14 @@ class HamlibHandlerSerial:
|
|||||||
return
|
return
|
||||||
if isinstance(data, Q3StringTypes):
|
if isinstance(data, Q3StringTypes):
|
||||||
data = data.encode('utf-8', errors='ignore')
|
data = data.encode('utf-8', errors='ignore')
|
||||||
if sys.platform == 'win32':
|
if self.port_is_mod_serial:
|
||||||
self.port.write(data)
|
self.port.write(data)
|
||||||
else:
|
else:
|
||||||
r, w, x = select.select((), (self.port,), (), 0)
|
r, w, x = select.select((), (self.port,), (), 0)
|
||||||
if w:
|
if w:
|
||||||
os.write(self.port, data)
|
os.write(self.port, data)
|
||||||
def set_frequency(self, freq):
|
def set_frequency(self, freq): # This changes the Rx frequency
|
||||||
tune = freq - self.app.VFO
|
self.app.ChangeRxTxFrequency(freq, None)
|
||||||
d = self.app.sample_rate * 45 // 100
|
|
||||||
if -d <= tune <= d: # Frequency is on-screen
|
|
||||||
vfo = self.app.VFO
|
|
||||||
else: # Change the VFO
|
|
||||||
vfo = (freq // 5000) * 5000 - 5000
|
|
||||||
tune = freq - vfo
|
|
||||||
self.app.BandFromFreq(freq)
|
|
||||||
self.app.ChangeHwFrequency(tune, vfo, 'FreqEntry')
|
|
||||||
if HAMLIB_DEBUG: print("New Freq rx,tx", self.app.txFreq + self.app.VFO, self.app.rxFreq + self.app.VFO)
|
if HAMLIB_DEBUG: print("New Freq rx,tx", self.app.txFreq + self.app.VFO, self.app.rxFreq + self.app.VFO)
|
||||||
def ZZAC(self, cmd, data, length): # Set or read tune steps
|
def ZZAC(self, cmd, data, length): # Set or read tune steps
|
||||||
if length == 0:
|
if length == 0:
|
||||||
@@ -1440,12 +1434,8 @@ class ConfigStatus(wx.ScrolledCanvas):
|
|||||||
self.MakeRow2("Sample interrupts", self.interrupts, cfile)
|
self.MakeRow2("Sample interrupts", self.interrupts, cfile)
|
||||||
self.MakeRow2("Microphone or DGT level dB", level, qfile)
|
self.MakeRow2("Microphone or DGT level dB", level, qfile)
|
||||||
self.MakeRow2("FFT number of points", self.fft_size, err_msg)
|
self.MakeRow2("FFT number of points", self.fft_size, err_msg)
|
||||||
if conf.dxClHost: # connection to dx cluster
|
if application.dxCluster:
|
||||||
nSpots = len(application.dxCluster.dxSpots)
|
msg = application.dxCluster.dxStatus()
|
||||||
if nSpots > 0:
|
|
||||||
msg = str(nSpots) + ' DX spot' + ('' if nSpots==1 else 's') + ' received from ' + application.dxCluster.getHost()
|
|
||||||
else:
|
|
||||||
msg = "No DX Cluster data from %s" % conf.dxClHost
|
|
||||||
self.MakeRow2("FFT number of errors", self.fft_error, msg)
|
self.MakeRow2("FFT number of errors", self.fft_error, msg)
|
||||||
else:
|
else:
|
||||||
self.MakeRow2("FFT number of errors", self.fft_error)
|
self.MakeRow2("FFT number of errors", self.fft_error)
|
||||||
@@ -2129,7 +2119,7 @@ class GraphScreen(wx.Window):
|
|||||||
"""For mouse clicks in our display, translate to our screen coordinates."""
|
"""For mouse clicks in our display, translate to our screen coordinates."""
|
||||||
mouse_x, mouse_y = event.GetPosition()
|
mouse_x, mouse_y = event.GetPosition()
|
||||||
win = event.GetEventObject()
|
win = event.GetEventObject()
|
||||||
if win is not self:
|
if win and win is not self:
|
||||||
x, y = win.GetPosition().Get()
|
x, y = win.GetPosition().Get()
|
||||||
mouse_x += x
|
mouse_x += x
|
||||||
mouse_y += y
|
mouse_y += y
|
||||||
@@ -2643,7 +2633,7 @@ class WaterfallScreen(wx.SplitterWindow):
|
|||||||
self.y_zero = conf.waterfall_y_zero
|
self.y_zero = conf.waterfall_y_zero
|
||||||
self.zoom_control = 0
|
self.zoom_control = 0
|
||||||
wx.SplitterWindow.__init__(self, frame)
|
wx.SplitterWindow.__init__(self, frame)
|
||||||
self.SetSizeHints(width, -1, width)
|
self.SetSizeHints(width, -1)
|
||||||
self.SetSashGravity(0.50)
|
self.SetSashGravity(0.50)
|
||||||
self.SetMinimumPaneSize(1)
|
self.SetMinimumPaneSize(1)
|
||||||
self.SetSize((width, conf.waterfall_graph_size + 100)) # be able to set sash size
|
self.SetSize((width, conf.waterfall_graph_size + 100)) # be able to set sash size
|
||||||
@@ -2997,7 +2987,7 @@ class MultiReceiverScreen(wx.SplitterWindow):
|
|||||||
self.rx_zero = self.graph
|
self.rx_zero = self.graph
|
||||||
self.Initialize(self.rx_zero)
|
self.Initialize(self.rx_zero)
|
||||||
self.waterfall.Hide()
|
self.waterfall.Hide()
|
||||||
self.SetSizeHints(self.width, -1, self.width)
|
self.SetSizeHints(self.width, -1)
|
||||||
# Calculate control width
|
# Calculate control width
|
||||||
rx_btn = QuiskPushbutton(self, None, "Rx 8....", style=wx.BU_EXACTFIT)
|
rx_btn = QuiskPushbutton(self, None, "Rx 8....", style=wx.BU_EXACTFIT)
|
||||||
self.rx_btn_width, self.rx_btn_height = rx_btn.GetSize().Get()
|
self.rx_btn_width, self.rx_btn_height = rx_btn.GetSize().Get()
|
||||||
@@ -3530,6 +3520,7 @@ class App(wx.App):
|
|||||||
if not os.path.isdir(self.QuiskFilesDir):
|
if not os.path.isdir(self.QuiskFilesDir):
|
||||||
self.QuiskFilesDir = DefaultConfigDir
|
self.QuiskFilesDir = DefaultConfigDir
|
||||||
self.std_out_err = StdOutput(self)
|
self.std_out_err = StdOutput(self)
|
||||||
|
self.std_out_err.Logfile("WxPython " + wx.version())
|
||||||
QS.set_params(quisk_is_vna=0) # We are not the VNA program
|
QS.set_params(quisk_is_vna=0) # We are not the VNA program
|
||||||
# Read in configuration from the selected radio
|
# Read in configuration from the selected radio
|
||||||
self.BandPlan = []
|
self.BandPlan = []
|
||||||
@@ -3620,6 +3611,7 @@ class App(wx.App):
|
|||||||
setattr(conf, 'widgets_file_name', '')
|
setattr(conf, 'widgets_file_name', '')
|
||||||
Hardware = self.Hardware
|
Hardware = self.Hardware
|
||||||
self.use_fast_heart_beat = hasattr(Hardware, "FastHeartBeat")
|
self.use_fast_heart_beat = hasattr(Hardware, "FastHeartBeat")
|
||||||
|
self.poll_gui_control = hasattr(Hardware, "PollGuiControl")
|
||||||
# Initialization - may be over-written by persistent state
|
# Initialization - may be over-written by persistent state
|
||||||
self.local_conf.Initialize()
|
self.local_conf.Initialize()
|
||||||
self.clip_time0 = 0 # timer to display a CLIP message on ADC overflow
|
self.clip_time0 = 0 # timer to display a CLIP message on ADC overflow
|
||||||
@@ -3830,9 +3822,10 @@ class App(wx.App):
|
|||||||
self.std_out_err.Show(False)
|
self.std_out_err.Show(False)
|
||||||
else:
|
else:
|
||||||
self.std_out_err.Show(True)
|
self.std_out_err.Show(True)
|
||||||
wClient, hClient = frame.GetClientSize()
|
wClient, hClient = self.main_frame.GetClientSize()
|
||||||
#w, h = frame.GetSize().Get()
|
wFrame, hFrame = self.main_frame.GetSize()
|
||||||
#print ('Main frame: size', w, h, 'client', wClient, hClient)
|
main_border_w = wFrame - wClient
|
||||||
|
#print ('Main frame: size', wFrame, hFrame, 'client', wClient, hClient, 'border', main_border_w)
|
||||||
# Find the data width from a list of preferred sizes; it is the width of returned graph data.
|
# Find the data width from a list of preferred sizes; it is the width of returned graph data.
|
||||||
# The graph_width is the width of data_width that is displayed.
|
# The graph_width is the width of data_width that is displayed.
|
||||||
# The total width of the graph is graph_width + self.graph_borders
|
# The total width of the graph is graph_width + self.graph_borders
|
||||||
@@ -3963,14 +3956,14 @@ class App(wx.App):
|
|||||||
frame.SetSizer(vertBox)
|
frame.SetSizer(vertBox)
|
||||||
# Add the screens
|
# Add the screens
|
||||||
vertBox.Add(self.config_screen, 1, wx.EXPAND)
|
vertBox.Add(self.config_screen, 1, wx.EXPAND)
|
||||||
vertBox.Add(self.multi_rx_screen, 1)
|
vertBox.Add(self.multi_rx_screen, 1, wx.EXPAND)
|
||||||
vertBox.Add(self.scope, 1)
|
vertBox.Add(self.scope, 1, wx.EXPAND)
|
||||||
vertBox.Add(self.bandscope_screen, 1)
|
vertBox.Add(self.bandscope_screen, 1, wx.EXPAND)
|
||||||
vertBox.Add(self.filter_screen, 1)
|
vertBox.Add(self.filter_screen, 1, wx.EXPAND)
|
||||||
if self.rate_audio_fft:
|
if self.rate_audio_fft:
|
||||||
vertBox.Add(self.audio_fft_screen, 1)
|
vertBox.Add(self.audio_fft_screen, 1, wx.EXPAND)
|
||||||
vertBox.Add(self.help_screen, 1)
|
vertBox.Add(self.help_screen, 1, wx.EXPAND)
|
||||||
vertBox.Add(self.station_screen)
|
vertBox.Add(self.station_screen, 0, wx.EXPAND)
|
||||||
# Add the spacer
|
# Add the spacer
|
||||||
vertBox.Add(Spacer(frame), 0, wx.EXPAND)
|
vertBox.Add(Spacer(frame), 0, wx.EXPAND)
|
||||||
# Add the sizer for the controls
|
# Add the sizer for the controls
|
||||||
@@ -3983,13 +3976,16 @@ class App(wx.App):
|
|||||||
vertBox.AddSpacer(5) # Thanks to Christof, DJ4CM
|
vertBox.AddSpacer(5) # Thanks to Christof, DJ4CM
|
||||||
# End of vertical box.
|
# End of vertical box.
|
||||||
self.MakeButtons(frame, gbs)
|
self.MakeButtons(frame, gbs)
|
||||||
minw = width = self.graph.width
|
|
||||||
maxw = maxh = -1
|
|
||||||
minh = 100
|
|
||||||
if conf.window_width > 0:
|
if conf.window_width > 0:
|
||||||
minw = width = maxw = conf.window_width
|
minw = maxw = conf.window_width
|
||||||
|
else:
|
||||||
|
minw = self.graph.width + main_border_w
|
||||||
|
maxw = -1
|
||||||
if conf.window_height > 0:
|
if conf.window_height > 0:
|
||||||
minh = maxh = self.height = conf.window_height
|
minh = maxh = self.height = conf.window_height
|
||||||
|
else:
|
||||||
|
minh = 100
|
||||||
|
maxh = -1
|
||||||
self.main_frame.SetSizeHints(minw, minh, maxw, maxh)
|
self.main_frame.SetSizeHints(minw, minh, maxw, maxh)
|
||||||
self.main_frame.SetClientSize(wx.Size(width, self.height))
|
self.main_frame.SetClientSize(wx.Size(width, self.height))
|
||||||
if hasattr(Hardware, 'pre_open'): # pre_open() is called before open()
|
if hasattr(Hardware, 'pre_open'): # pre_open() is called before open()
|
||||||
@@ -4031,7 +4027,6 @@ class App(wx.App):
|
|||||||
if conf.dxClHost:
|
if conf.dxClHost:
|
||||||
# create DX Cluster and register listener for change notification
|
# create DX Cluster and register listener for change notification
|
||||||
self.dxCluster = dxcluster.DxCluster()
|
self.dxCluster = dxcluster.DxCluster()
|
||||||
self.dxCluster.setListener(self.OnDxClChange)
|
|
||||||
self.dxCluster.start()
|
self.dxCluster.start()
|
||||||
# Create shortcut keys for buttons
|
# Create shortcut keys for buttons
|
||||||
if conf.button_layout == 'Large screen':
|
if conf.button_layout == 'Large screen':
|
||||||
@@ -4382,8 +4377,6 @@ class App(wx.App):
|
|||||||
conf.tx_ip, conf.tx_audio_port,
|
conf.tx_ip, conf.tx_audio_port,
|
||||||
conf.mic_sample_rate, conf.mic_channel_I, conf.mic_channel_Q,
|
conf.mic_sample_rate, conf.mic_channel_I, conf.mic_channel_Q,
|
||||||
0.7, conf.mic_playback_rate)
|
0.7, conf.mic_playback_rate)
|
||||||
def OnDxClChange(self):
|
|
||||||
self.station_screen.Refresh()
|
|
||||||
def OnIdle(self, event):
|
def OnIdle(self, event):
|
||||||
if self.screen:
|
if self.screen:
|
||||||
self.screen.OnIdle(event)
|
self.screen.OnIdle(event)
|
||||||
@@ -6458,6 +6451,8 @@ class App(wx.App):
|
|||||||
self.hamlib_com2_handler.Process()
|
self.hamlib_com2_handler.Process()
|
||||||
if self.use_fast_heart_beat:
|
if self.use_fast_heart_beat:
|
||||||
Hardware.FastHeartBeat()
|
Hardware.FastHeartBeat()
|
||||||
|
if self.poll_gui_control:
|
||||||
|
Hardware.PollGuiControl()
|
||||||
if conf.do_repeater_offset:
|
if conf.do_repeater_offset:
|
||||||
hold = QS.tx_hold_state(-1)
|
hold = QS.tx_hold_state(-1)
|
||||||
if hold == 2: # Tx is being held for an FM repeater TX frequency shift
|
if hold == 2: # Tx is being held for an FM repeater TX frequency shift
|
||||||
@@ -6638,6 +6633,9 @@ class App(wx.App):
|
|||||||
self.ChangeDisplayFrequency(tune - vfo, vfo)
|
self.ChangeDisplayFrequency(tune - vfo, vfo)
|
||||||
self.FldigiPoll()
|
self.FldigiPoll()
|
||||||
self.HamlibPoll()
|
self.HamlibPoll()
|
||||||
|
if self.dxCluster:
|
||||||
|
if self.dxCluster.Poll():
|
||||||
|
self.station_screen.Refresh()
|
||||||
if self.timer - self.slowheart_time0 > 0.5:
|
if self.timer - self.slowheart_time0 > 0.5:
|
||||||
self.slowheart_time0 = self.timer
|
self.slowheart_time0 = self.timer
|
||||||
if self.w_phase:
|
if self.w_phase:
|
||||||
|
|||||||
+2
-1
@@ -29,9 +29,10 @@ class Hardware(BaseHardware):
|
|||||||
# self.hamlib_rigctld_port = 4532 # Standard rigctld control port
|
# self.hamlib_rigctld_port = 4532 # Standard rigctld control port
|
||||||
# self.hamlib_poll_seconds = 0.2 # Time interval to poll for changes
|
# self.hamlib_poll_seconds = 0.2 # Time interval to poll for changes
|
||||||
def open(self):
|
def open(self):
|
||||||
|
# Thanks to Peter, DC6AR, Rig ID changed from 229 to 2045.
|
||||||
ret = BaseHardware.open(self)
|
ret = BaseHardware.open(self)
|
||||||
if not self.hamlib_connected: # rigctld is not started. Try to start it.
|
if not self.hamlib_connected: # rigctld is not started. Try to start it.
|
||||||
os.system("rigctld -m 229 -r /dev/ttyUSB0 -s 4800 & ") # Check the baud rate menu setting
|
os.system("rigctld -m 2045 -r /dev/ttyUSB0 -s 4800 & ") # Check the baud rate menu setting
|
||||||
# If this fails, start rigctld by hand.
|
# If this fails, start rigctld by hand.
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
|||||||
@@ -120,6 +120,8 @@ class Hardware:
|
|||||||
self.application.bandscope_clock = clock
|
self.application.bandscope_clock = clock
|
||||||
#def PollCwKey(self): # Optional. Called frequently by the sound thread to check the CW key status.
|
#def PollCwKey(self): # Optional. Called frequently by the sound thread to check the CW key status.
|
||||||
# pass # Do not define if not needed.
|
# pass # Do not define if not needed.
|
||||||
|
#def PollGuiControl(self): # Optional. Called frequently by the GUI thread to change GUI settings (PTT etc.)
|
||||||
|
# pass # Do not define if not needed.
|
||||||
def StartSamples(self): # Quisk calls this from the sound thread to start sending samples.
|
def StartSamples(self): # Quisk calls this from the sound thread to start sending samples.
|
||||||
# If you return a string, it replaces the string returned from hardware open()
|
# If you return a string, it replaces the string returned from hardware open()
|
||||||
pass
|
pass
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import os
|
|||||||
# You must define the version here. A title string including
|
# You must define the version here. A title string including
|
||||||
# the version will be written to __init__.py and read by quisk.py.
|
# the version will be written to __init__.py and read by quisk.py.
|
||||||
|
|
||||||
Version = '4.2.37'
|
Version = '4.2.40'
|
||||||
|
|
||||||
fp = open("__init__.py", "w") # write title string
|
fp = open("__init__.py", "w") # write title string
|
||||||
fp.write("#Quisk version %s\n" % Version)
|
fp.write("#Quisk version %s\n" % Version)
|
||||||
|
|||||||
Reference in New Issue
Block a user