1 Commits
Author SHA1 Message Date
James C. Ahlstrom d8aee9284d Quisk version 4.2.47 2025-11-22 13:39:10 -05:00
11 changed files with 259 additions and 163 deletions
+12
View File
@@ -1,3 +1,15 @@
Quisk Version 4.2.47 November 2025
===================================
To improve the performance of Quisk with the Anan 10-E and other OpenHPSDR radios, I added
a new type of radio "OpenHPSDR". Use this type for the Anan 10-E and similar radios. It removes
all the protocol extensions added by the Hermes-Lite2 project. I removed the configuration
option "Hermes Lite2 protocol enable". This is now automatic.
I added buttons for antennas 0, 1, 2 and 3 for OpenHPSDR radios that support more antennas.
I added controls for the OpenHPSDR preamplifier and attenuator.
I do not have any Apache Labs radios, so I must depend on my users to report problems and solutions.
Quisk Version 4.2.46 October 2025
==================================
I fixed a bug in Hamlib rig 2 which happens with the new Pure Signal code. The Hamlib "f" command
+1 -1
View File
@@ -1,2 +1,2 @@
#Quisk version 4.2.46
#Quisk version 4.2.47
from .quisk import main
+7 -4
View File
@@ -88,6 +88,7 @@ class Configuration:
platform_ignore = 'win_'
self.sections = []
self.receiver_data = []
self.receiver_explain = []
self.StatePath = conf.settings_file_path
if not self.StatePath:
self.StatePath = os.path.join(app.QuiskFilesDir, "quisk_settings.json")
@@ -601,6 +602,7 @@ class Configuration:
# Receiver sections start with 16 #, "Receivers ", receiver name, explain
# self.receiver_data is a list of [receiver_name, receiver_data]
# receiver_data is a list of [data_name, text, fmt, help_text, values]
# self.receiver_explain is a list of the text in Receivers: the name, a comma and the explanation.
# Variable names start with ## variable_name variable_text, format
# The format is integer, number, text, boolean, integer choice, text choice, rfile
@@ -638,6 +640,7 @@ class Configuration:
continue
if line[0:27] == '################ Receivers ':
section = 'Receivers'
self.receiver_explain.append(line[27:].strip())
args = line[27:].split(',', 1)
rxname = args[0].strip()
section_data = []
@@ -2298,7 +2301,7 @@ class ControlMixin:
if self.radio_name == Settings[1]: # changed for current radio
if name in ('hot_key_ptt_toggle', 'hot_key_ptt_if_hidden', 'keyupDelay', 'cwTone', 'pulse_audio_verbose_output',
'start_cw_delay', 'start_ssb_delay', 'maximum_tx_secs', 'quisk_serial_cts', 'quisk_serial_dsr',
'hot_key_ptt1', 'hot_key_ptt2', 'midi_ptt_toggle', 'TxRxSilenceMsec', 'hermes_lite2_enable',
'hot_key_ptt1', 'hot_key_ptt2', 'midi_ptt_toggle', 'TxRxSilenceMsec',
'fixed_tune_offset'):
setattr(conf, name, x)
application.ImmediateChange(name)
@@ -2737,8 +2740,8 @@ class Radios(BaseWindow): # The "Radios" first-level page
self.NextRow()
rb = self.AddRadioButton(1, "Add a new radio with the general type", self.NewTop)
choices = []
for name, data in local_conf.receiver_data:
choices.append(name)
for explain in local_conf.receiver_explain:
choices.append(explain)
choices.sort()
self.add_type = self.AddComboCtrl(2, '', choices=choices, no_edit=True)
self.add_type.SetSelection(0)
@@ -2810,7 +2813,7 @@ class Radios(BaseWindow): # The "Radios" first-level page
if not name or self.DuplicateName(name):
return
self.add_name.SetValue('')
typ = self.add_type.GetValue().strip()
typ = self.add_type.GetValue().split(',')[0].strip()
if local_conf.AddRadio(name, typ):
self.NewRadioNames()
local_conf.settings_changed = True
+31
View File
@@ -0,0 +1,31 @@
# Please do not change this widgets module for Quisk. Instead copy
# it to your own quisk_widgets.py and make changes there.
#
# This module is used to add extra widgets to the QUISK screen.
import wx
class BottomWidgets: # Add extra widgets to the bottom of the screen
def __init__(self, app, hardware, conf, frame, gbs, vertBox):
self.config = conf
self.hardware = hardware
self.application = app
self.start_row = app.widget_row # The first available row
self.start_col = app.button_start_col # The start of the button columns
self.num_rows_added = 1
self.btnPreamp = app.QuiskCheckbutton(frame, self.OnBtnPreamp, text='Preamp')
gbs.Add(self.btnPreamp, (self.start_row, self.start_col), flag=wx.EXPAND)
init = app.hermes_atten_dB
self.sliderAtten = app.SliderBoxHH(frame, 'Atten %d dB', init, 0, 31, self.OnAtten, True)
self.sliderAtten.idName = "RfAtten"
app.midiControls["RfAtten"] = (self.sliderAtten, self.OnAtten)
hardware.ChangeAtten(init)
gbs.Add(self.sliderAtten, (self.start_row, self.start_col + 2), (1, 6), flag=wx.EXPAND)
def OnBtnPreamp(self, event):
self.hardware.ChangePreamp(self.btnPreamp.GetValue())
def OnAtten(self, event):
value = self.sliderAtten.GetValue()
self.hardware.ChangeAtten(value)
self.application.hermes_atten_dB = value
def UpdateText(self): # Called at intervals
pass
+23 -11
View File
@@ -48,6 +48,8 @@ class IOBoard:
def HeartBeat(self): # Called at 10 Hz for housekeeping tasks
if not QS.get_params('rx_udp_started'):
return
if self.hardware.hermes_board_id != 6:
return
if self.have_IO_Board is None:
resp = self.hardware.ReadI2C(0x7d, 0x41, 0) # Check for the N2ADR HL2 IO Board
if resp and resp[1] == 0xF1:
@@ -166,7 +168,10 @@ class Hardware(BaseHardware):
self.vna_count = 0
self.vna_started = False
self.repeater_freq = None # original repeater output frequency
self.antenna_labels = ('Ant 0', 'Ant 1') # labels for the antenna button
if conf.hardware_file_type == "Red Pitaya":
self.antenna_labels = ('Ant 0', 'Ant 1') # labels for the antenna button
else:
self.antenna_labels = ('Ant 0', 'Ant 1', 'Ant 2', 'Ant 3')
self.antenna_index = 0 # index of antenna in use
self.delay_config = True # Delay sending message to HL2 until after sound starts
self.TFRC_counter = 0 # Call for power etc. at intervals
@@ -529,7 +534,9 @@ class Hardware(BaseHardware):
def ChangeBandFilters(self):
if not hasattr(self.application, "multi_rx_screen"):
return # Needed for the VNA program
self.SetControlBit(0x00, 13, self.antenna_index)
self.SetControlBit(0x00, 13, self.antenna_index & 0x01)
self.SetControlBit(0x00, 14, self.antenna_index & 0x02)
self.SetControlBit(0x00, 15, self.antenna_index > 0)
highest = self.band
freq = self.conf.BandEdge.get(highest, (0, 0))[0]
for pane in self.application.multi_rx_screen.receiver_list:
@@ -606,12 +613,7 @@ class Hardware(BaseHardware):
return (48000, 384000)
## Hardware AGC is no longer supported in HL2 identifying as version >=40
def ChangeAGC(self, value):
if value:
self.pc2hermes[2] |= 0x10 # C0 index == 0, C3[4]: AGC enable
else:
self.pc2hermes[2] &= ~0x10
QS.pc_to_hermes(self.pc2hermes)
if DEBUG: print ("Change AGC to", value)
pass
## Simpler LNA setting for HL2 identifying as version >=40, see HL2 wiki for details
def ChangeLNA(self, value): # LNA for Rx
# value is -12 to +48
@@ -624,7 +626,7 @@ class Hardware(BaseHardware):
value = 51 - value
else:
value = ((value+12) & 0x3f) | 0x40
self.pc2hermes[4 * 10 + 3] = value # C0 index == 0x1010, C4[4:0] LNA 0-32 dB gain
self.pc2hermes[4 * 10 + 3] = value # C0 index == 0b1010, C4[4:0] LNA 0-32 dB gain
QS.pc_to_hermes(self.pc2hermes)
if DEBUG: print ("Change LNA to", value)
def ChangeTxLNA(self, value): # LNA for Tx
@@ -634,9 +636,17 @@ class Hardware(BaseHardware):
elif value > 48:
value = 48
value = ((value+12) & 0x3f) | 0x40 | 0x80
self.SetControlByte(0x0e, 3, value, False) # C0 index == 0x0e, C3
self.SetControlByte(0x0e, 3, value, False) # C0 index == 0b1110 == 0x0e, C3
QS.pc_to_hermes(self.pc2hermes)
if DEBUG: print ("Change Tx LNA to", value)
def ChangeAtten(self, value):
# value is 0 to 31
self.pc2hermes[4 * 10 + 3] = value & 0x1F # C0 index == 0b1010, C4[4:0] attenuator, 0 to 31 dB
self.SetControlBit(0b1010, 5, value) # enable attenuator
QS.pc_to_hermes(self.pc2hermes)
if DEBUG: print ("Change attenuator to", value)
def ChangePreamp(self, value):
self.SetControlBit(0b0000, 10, value) # enable preamp
def SetTxLevel(self):
try:
tx_level = self.conf.tx_level[self.band]
@@ -653,7 +663,7 @@ class Hardware(BaseHardware):
tx_level = 0
elif tx_level > 255:
tx_level = 255
self.pc2hermes[4 * 9] = tx_level # C0 index == 0x1001, C1[7:0] Tx level
self.pc2hermes[4 * 9] = tx_level # C0 index == 0b1001, C1[7:0] Tx level
QS.pc_to_hermes(self.pc2hermes)
if DEBUG: print("Change tx_level to", tx_level)
def MultiRxCount(self, count): # count == number of additional receivers besides the Tx/Rx receiver: 1, 2, 3
@@ -876,6 +886,8 @@ class Hardware(BaseHardware):
QS.set_hermeslite_writepointer(0)
return False
def WriteQueue(self, wait=False):
if self.hermes_board_id != 6:
return False
self._wait_queue()
# Send next write
self.old_writequeue = self.pc2hermeslitewritequeue[:]
+1 -2
View File
@@ -26,12 +26,11 @@ class Hardware(BaseHw):
return BaseHw.close(self)
def ChangeFilterFrequency(self, tx_freq):
if tx_freq and tx_freq > 0:
self.v2filter.SetTxFreq(tx_freq)
if self.GUI:
self.GUI.SetTxFreq(tx_freq)
self.GUI.freq_entry.ChangeValue("%.3f" % (tx_freq * 1E-6))
else:
self.anttuner.SetTxFreq(tx_freq)
self.v2filter.SetTxFreq(tx_freq)
def ChangeFrequency(self, tx_freq, vfo_freq, source='', band='', event=None):
self.ChangeFilterFrequency(tx_freq)
return BaseHw.ChangeFrequency(self, tx_freq, vfo_freq, source, band, event)
+80 -119
View File
@@ -1,9 +1,5 @@
# This file supports various hardware boxes at my shack
from __future__ import print_function
from __future__ import absolute_import
from __future__ import division
import sys, struct, math, socket, select, time, traceback, os
import wx, wx.lib.buttons
@@ -410,19 +406,16 @@ class AntennaTuner: # Control my homebrew antenna tuner and my KI8BV dipole
self.set_C = 0
self.set_HighZ = 0
self.antnum = 0 # Antenna number 0 or 1
self.dipole2 = None #AntennaControl(app, conf) # Control the KI8BV dipole
if False and conf.use_rx_udp == 10: # Hermes UDP protocol for Hermes-Lite2
path = 'TunerLCZ_HL2.txt'
else:
path = 'TunerLCZ.txt'
self.dipole2 = AntennaControl(app, conf) # Control the KI8BV dipole
path = 'TunerLCZ.txt'
if sys.platform == "win32":
path = 'C:/pub/' + path
self.path = 'C:/pub/' + path
else:
path = '/home/jim/pub/' + path
fp = open(path, "r")
self.path = '/home/jim/pub/' + path
fp = open(self.path, "r")
lines = fp.readlines()
fp.close()
self.TunerLCZ = [(0, 0, 0, 0), (999111000, 0, 0, 0)] # Add dummy first and last entry.
self.TunerLCZ = []
for line in lines:
freq, antL, antC, hilo = line.split()
freq = int(freq)
@@ -451,7 +444,12 @@ class AntennaTuner: # Control my homebrew antenna tuner and my KI8BV dipole
pass
def ChangeBand(self, band):
pass
def FindLCZ(self, tx_freq):
def SaveLCZ(self):
fp = open(self.path, 'w')
for tup in self.TunerLCZ:
fp.write("%12d %2d %2d %d\n" % tup)
fp.close()
def FindIndexTup(self, tx_freq):
i1 = 0
i2 = len(self.TunerLCZ) - 1
while 1: # binary partition
@@ -462,20 +460,14 @@ class AntennaTuner: # Control my homebrew antenna tuner and my KI8BV dipole
i2 = i
if i2 - i1 <= 1:
break
# The correct setting is between i1 and i2.
# The correct setting is between i1 and i2, or below i1 or above i2.
# Choose the index that is closest in frequency.
delta1 = tx_freq - self.TunerLCZ[i1][0]
delta2 = self.TunerLCZ[i2][0] - tx_freq
if i1 == 0: # below the first frequency
if abs(tx_freq - self.TunerLCZ[i1][0]) < abs(tx_freq - self.TunerLCZ[i2][0]):
index = i1
elif i2 == len(self.TunerLCZ) - 1: # above the last frequency
else:
index = i2
elif delta2 < delta1: # i2 is closer
index = i2
else: # i1 is closer
index = i1
if DEBUG: print ("AntennaTuner FindLCZ", tx_freq, i1, i2, len(self.TunerLCZ), self.TunerLCZ[index])
return self.TunerLCZ[index]
if DEBUG: print ("StatuinControlGUI FindIndexTup", tx_freq, i1, i2, len(self.TunerLCZ), index, self.TunerLCZ[index])
return index, self.TunerLCZ[index]
def SetTxFreq(self, tx_freq, no_tune=False):
#if DEBUG: print("AntennaTuner SetTxFreq", tx_freq)
self.tx_freq = tx_freq
@@ -496,7 +488,7 @@ class AntennaTuner: # Control my homebrew antenna tuner and my KI8BV dipole
if abs(self.tune_freq - tx_freq) < 5000: # ignore small changes
return
self.tune_freq = tx_freq
f, newL, newC, newH = self.FindLCZ(tx_freq)
index, (f, newL, newC, newH) = self.FindIndexTup(tx_freq)
if newH != self.set_HighZ or self.set_C != newC or self.set_L != newL:
self.set_HighZ = newH
self.set_C = newC
@@ -540,26 +532,7 @@ class StationControlGUI(wx.Frame): # Display a stand-alone control window for
self.conf = conf
self.data_saving = False
self.tx_freq = 0
if sys.platform == "win32":
self.filename = 'C:/pub/TunerLCZ.tmp'
else:
self.filename = '/home/jim/pub/TunerLCZ.tmp'
try:
fp = open(self.filename, "r")
except FileNotFoundError:
lines = ()
else:
lines = fp.readlines()
fp.close()
self.TunerLCZ = [(0, 0, 0, 0), (999111000, 0, 0, 0)] # Add dummy first and last entry.
for line in lines:
freq, antL, antC, hilo = line.split()
freq = int(freq)
antL = int(antL)
antC = int(antC)
hilo = int(hilo)
self.TunerLCZ.append((freq, antL, antC, hilo))
self.TunerLCZ.sort()
self.anttuner = self.hware.anttuner
self.SetBackgroundColour('light steel blue')
self.Bind(wx.EVT_CHAR_HOOK, self.OnKeyDown)
sizer = wx.GridBagSizer(hgap=5, vgap=3)
@@ -569,6 +542,7 @@ class StationControlGUI(wx.Frame): # Display a stand-alone control window for
self.bands = []
for band in ('160', '80', '60', '40', '30', '20', '17', '15', '12', '10'):
b = wx.lib.buttons.GenToggleButton(self, -1, band)
b.Enable(False)
b.SetUseFocusIndicator(False)
b.SetBezelWidth(4)
self.bands.append(b)
@@ -605,6 +579,7 @@ class StationControlGUI(wx.Frame): # Display a stand-alone control window for
szr = wx.BoxSizer(wx.HORIZONTAL)
szr.AddSpacer(20)
b = wx.lib.buttons.GenToggleButton(self, -1, "Key Down")
b.Enable(False)
b.SetFont(font)
b.SetUseFocusIndicator(False)
b.SetBezelWidth(4)
@@ -612,6 +587,7 @@ class StationControlGUI(wx.Frame): # Display a stand-alone control window for
szr.Add(b)
szr.AddSpacer(10)
b = wx.lib.buttons.GenToggleButton(self, -1, "FilterV2 Preamp")
b.Enable(False)
b.SetFont(font)
b.SetUseFocusIndicator(False)
b.SetBezelWidth(4)
@@ -623,16 +599,31 @@ class StationControlGUI(wx.Frame): # Display a stand-alone control window for
b.SetFont(font)
szr.Add(b, flag=wx.ALIGN_CENTER_VERTICAL)
szr.AddSpacer(10)
self.freq_entry = wx.TextCtrl(self, value='0000.000', style=wx.TE_PROCESS_ENTER)
self.freq_entry = wx.StaticText(self, -1, "0000.000")
#self.freq_entry = wx.TextCtrl(self, value='0000.000', style=wx.TE_PROCESS_ENTER)
self.freq_entry.SetFont(font)
self.Bind(wx.EVT_TEXT_ENTER, self.OnFreqEntry, self.freq_entry)
szr.Add(self.freq_entry)
#self.Bind(wx.EVT_TEXT_ENTER, self.OnFreqEntry, self.freq_entry)
szr.Add(self.freq_entry, flag=wx.ALIGN_CENTER_VERTICAL)
szr.AddSpacer(10)
b = wx.lib.buttons.GenButton(self, -1, "Search Freq")
b = wx.lib.buttons.GenButton(self, -1, "Freq-")
b.SetUseFocusIndicator(False)
b.SetBezelWidth(4)
b.SetFont(font)
self.Bind(wx.EVT_BUTTON, self.OnButtonSearch, b)
self.Bind(wx.EVT_BUTTON, self.OnButtonDown, b)
szr.Add(b)
szr.AddSpacer(10)
b = wx.lib.buttons.GenButton(self, -1, "Freq+")
b.SetUseFocusIndicator(False)
b.SetBezelWidth(4)
b.SetFont(font)
self.Bind(wx.EVT_BUTTON, self.OnButtonUp, b)
szr.Add(b)
szr.AddSpacer(10)
b = wx.lib.buttons.GenButton(self, -1, "Delete")
b.SetUseFocusIndicator(False)
b.SetBezelWidth(4)
b.SetFont(font)
self.Bind(wx.EVT_BUTTON, self.OnButtonDelete, b)
szr.Add(b)
sizer.Add(szr, pos=(row, 0), span=(1, 3))
if frame is None:
@@ -648,13 +639,13 @@ class StationControlGUI(wx.Frame): # Display a stand-alone control window for
self.Bind(wx.EVT_TIMER, self.HeartBeat)
self.timer.Start(100)
def SetTxFreq(self, tx_freq):
#print("StationControlGUI SetTxFreq", tx_freq)
tx_freq = ((tx_freq + 500) // 1000) * 1000
self.tx_freq = tx_freq
index, tup = self.FindIndexTup(tx_freq)
anttuner = self.anttuner
index, tup = anttuner.FindIndexTup(tx_freq)
self.sliderL.SetValue(tup[1])
self.sliderC.SetValue(tup[2])
self.btnHiLo.SetValue(tup[3])
anttuner = self.hware.anttuner
fff, anttuner.set_L, anttuner.set_C, anttuner.set_HighZ = tup
if tx_freq < 17000000:
anttuner.antnum = 0
@@ -663,31 +654,7 @@ class StationControlGUI(wx.Frame): # Display a stand-alone control window for
if anttuner.antnum == 1 and anttuner.dipole2:
anttuner.dipole2.SetTxFreq(tx_freq)
anttuner.WantData()
def FindIndexTup(self, tx_freq):
i1 = 0
i2 = len(self.TunerLCZ) - 1
while 1: # binary partition
i = (i1 + i2) // 2
if self.TunerLCZ[i][0] < tx_freq:
i1 = i
else:
i2 = i
if i2 - i1 <= 1:
break
# The correct setting is between i1 and i2.
# Choose the index that is closest in frequency.
delta1 = tx_freq - self.TunerLCZ[i1][0]
delta2 = self.TunerLCZ[i2][0] - tx_freq
if i1 == 0: # below the first frequency
index = i1
elif i2 == len(self.TunerLCZ) - 1: # above the last frequency
index = i2
elif delta2 < delta1: # i2 is closer
index = i2
else: # i1 is closer
index = i1
if DEBUG: print ("StatuinControlGUI FindLCZ", tx_freq, i1, i2, len(self.TunerLCZ), index, self.TunerLCZ[index])
return index, self.TunerLCZ[index]
self.freq_entry.SetLabel("%.3f" % (tx_freq * 1E-6))
def OnBtnClose(self, event):
self.hware.anttuner.close()
self.hware.controlbox.close()
@@ -731,16 +698,15 @@ class StationControlGUI(wx.Frame): # Display a stand-alone control window for
f = ((f + 500) // 1000) * 1000
if self.hware.v2filter:
self.hware.v2filter.SetTxFreq(f)
self.hware.anttuner.SetTxFreq(f, no_tune=True)
self.anttuner.SetTxFreq(f, no_tune=True)
self.freq_entry.ChangeValue("%.3f" % (f * 1E-6))
self.SetTxFreq(f)
def OnButtonHiLo(self, event):
anttuner = self.hware.anttuner
if self.btnHiLo.GetValue():
anttuner.set_HighZ = 1
self.anttuner.set_HighZ = 1
else:
anttuner.set_HighZ = 0
anttuner.WantData()
self.anttuner.set_HighZ = 0
self.anttuner.WantData()
def OnFreqEntry(self, event=None):
freq = self.freq_entry.GetValue()
freq = float(freq) * 1E6
@@ -752,11 +718,27 @@ class StationControlGUI(wx.Frame): # Display a stand-alone control window for
freq = int(freq + 0.1)
self.tx_freq = freq
self.SetTxFreq(self.tx_freq)
def OnButtonDown(self, event):
index, tup = self.anttuner.FindIndexTup(self.tx_freq)
index -= 1
if index >= 0:
self.SetTxFreq(self.anttuner.TunerLCZ[index][0])
def OnButtonUp(self, event):
index, tup = self.anttuner.FindIndexTup(self.tx_freq)
index += 1
if index < len(self.anttuner.TunerLCZ):
self.SetTxFreq(self.anttuner.TunerLCZ[index][0])
def OnButtonDelete(self, event):
index, tup = self.anttuner.FindIndexTup(self.tx_freq)
if self.tx_freq == self.anttuner.TunerLCZ[index][0]:
del self.anttuner.TunerLCZ[index]
if index > 0:
self.SetTxFreq(self.anttuner.TunerLCZ[index - 1][0])
elif len(self.anttuner.TunerLCZ) > 0:
self.SetTxFreq(self.anttuner.TunerLCZ[0][0])
else:
self.SetTxFreq(0)
def OnButtonSave(self, event):
freq = self.freq_entry.GetValue()
freq = float(freq) * 1E6
freq = int(freq + 0.1)
self.tx_freq = freq
L = self.sliderL.GetValue()
C = self.sliderC.GetValue()
if self.btnHiLo.GetValue():
@@ -764,22 +746,19 @@ class StationControlGUI(wx.Frame): # Display a stand-alone control window for
else:
hilo = 0
tup = (self.tx_freq, L, C, hilo)
index, t = self.FindIndexTup(self.tx_freq)
if self.tx_freq == self.TunerLCZ[index][0]:
self.TunerLCZ[index] = tup
index, t = self.anttuner.FindIndexTup(self.tx_freq)
if self.tx_freq == self.anttuner.TunerLCZ[index][0]:
self.anttuner.TunerLCZ[index] = tup
else:
self.TunerLCZ.append(tup)
self.TunerLCZ.sort()
fp = open(self.filename, 'w')
for tup in self.TunerLCZ[1:-1]: # Throw away dummy entries
fp.write("%12d %2d %2d %d\n" % tup)
fp.close()
self.anttuner.TunerLCZ.append(tup)
self.anttuner.TunerLCZ.sort()
self.anttuner.SaveLCZ()
def OnSliderL(self, event=None):
self.hware.anttuner.set_L = self.sliderL.GetValue()
self.hware.anttuner.WantData()
self.anttuner.set_L = self.sliderL.GetValue()
self.anttuner.WantData()
def OnSliderC(self, event=None):
self.hware.anttuner.set_C = self.sliderC.GetValue()
self.hware.anttuner.WantData()
self.anttuner.set_C = self.sliderC.GetValue()
self.anttuner.WantData()
def OnBtnV2Preamp(self, event):
if self.hware.v2filter:
self.hware.v2filter.SetPreamp(event.GetEventObject().GetValue())
@@ -1073,21 +1052,3 @@ class AT200PC: # Control an AT-200PC autotuner made by LDG
self.set_C += 1
elif text == 'C-':
self.set_C -= 1
class App(wx.App):
def OnInit(self):
if sys.path[0] != "'.'": # Make sure the current working directory is on path
sys.path.insert(0, '.')
import quisk_conf_defaults as conf
import quisk_hardware_model as hardware
self.bottom_widgets = None
hardware.anttuner = AntennaTuner(self, conf) # Control the antenna tuner
hardware.v2filter = FilterBoxV2(self, conf) # Control V2 filter box
hardware.controlbox = ControlBox(self, conf) # Control my Station Control Box
self.main_frame = frame = StationControlGUI (None, hardware, self, conf)
frame.Open()
frame.Show()
return True
if __name__ == '__main__':
App().MainLoop()
+1 -1
View File
@@ -18,7 +18,7 @@ from quisk_hardware_model import Hardware as BaseHardware
DEBUG = 1
# Define the name of the hardware and the items on the hardware screen (see quisk_conf_defaults.py):
################ Receivers PerseusSDR, The PerseusSDR interface to multiple hardware SDRs.
################ Receivers PerseusSDR, The PerseusSDR interface to multiple SDRs.
## hardware_file_name Hardware file path, rfile
# This is the file that contains the control logic for each radio.
#hardware_file_name = 'perseuspkg/quisk_hardware.py'
+3 -2
View File
@@ -3718,7 +3718,7 @@ class App(wx.App):
'wfallScaleZ', 'wfallGrScaleZ', 'graphScaleZ', 'split_rxtx_play', 'modeFilter',
'file_name_rec_audio', 'file_name_rec_samples', 'file_name_rec_mic', 'file_name_rec_tmp',
'file_name_play_audio', 'file_name_play_samples', 'file_name_play_cq',
'file_play_source', 'hermes_LNA_dB']
'file_play_source', 'hermes_LNA_dB', 'hermes_atten_dB']
def __init__(self):
global application
QS.AppStatus(1)
@@ -3939,6 +3939,7 @@ class App(wx.App):
self.serial_ptt_active = False
self.vox_ptt_active = False
self.hermes_LNA_dB = 20
self.hermes_atten_dB = 0
if hasattr(Hardware, "OnChangeRxTx"):
self.want_RxTx = True
else:
@@ -6798,7 +6799,7 @@ class App(wx.App):
if self.timer - self.heart_time0 > 0.10: # call hardware to perform background tasks:
self.heart_time0 = self.timer
Hardware.HeartBeat()
if conf.hermes_lite2_enable:
if conf.use_rx_udp == 10 and Hardware.hermes_board_id == 6:
self.tx_inhibit = QS.get_params('quisk_tx_inhibit')
else:
self.tx_inhibit = 0
+99 -22
View File
@@ -48,7 +48,7 @@ quisk_widgets = None
################ Receivers SoftRock USB, Devices controlled by USB that capture samples from a sound card, and (for Tx) play samples to a sound card
################ Receivers SoftRock USB, Sound card radios controlled by USB.
## hardware_file_name Hardware file path, rfile
# This is the file that contains the control logic for each radio.
#hardware_file_name = 'softrock/hardware_usb.py'
@@ -133,7 +133,7 @@ digital_tx_level = 100
################ Receivers SoftRock Fixed, Fixed frequency devices that capture samples from a sound card, and (for Tx) play samples to a sound card
################ Receivers SoftRock Fixed, Fixed frequency sound card radios.
## hardware_file_name Hardware file path, rfile
# This is the file that contains the control logic for each radio.
#hardware_file_name = 'quisk_hardware_fixed.py'
@@ -174,7 +174,7 @@ digital_tx_level = 100
################ Receivers HiQSDR, The original N2ADR hardware and the improved HiQSDR using UDP
################ Receivers HiQSDR, The original N2ADR and HiQSDR radios.
## hardware_file_name Hardware file path, rfile
# This is the file that contains the control logic for each radio.
#hardware_file_name = 'hiqsdr/quisk_hardware.py'
@@ -258,7 +258,7 @@ sndp_active = True
################ Receivers Hermes, The Hermes-Lite Project and possibly other hardware with the Hermes FPGA code.
################ Receivers Hermes, The Hermes-Lite project by Steve Haynal.
## hardware_file_name Hardware file path, rfile
# This is the file that contains the control logic for each radio.
#hardware_file_name = 'hermes/quisk_hardware.py'
@@ -275,7 +275,7 @@ sndp_active = True
# You can set these options:
## use_rx_udp Hardware type, integer choice
# This is the type of UDP hardware. Use 10 for the Hermes protocol.
# This is the type of UDP hardware. Use 10 for the Hermes Lite2 protocol.
#use_rx_udp = 10
## udp_rx_ip Hermes known IP, text
@@ -373,6 +373,7 @@ hermes_disable_sync = False
# be sure to write it down. To use this address you must set "Eeprom IP Usage".
# And you may want to set "Hermes known IP" too. Make sure the address does not conflict
# with your DHCP server.
# Power cycle the HL2 after changing this item.
Hware_Hl2_EepromIP = '192.168.1.6'
#Hware_Hl2_EepromIP = '192.168.1.241'
@@ -380,6 +381,7 @@ Hware_Hl2_EepromIP = '192.168.1.6'
# This is the way the EEPROM IP address is used at power on.
# "Ignore" means it is not used at all. "Set address" means DHCP is not used and the EEPROM IP address is used.
# "Use DHCP first" means the EEPROM IP address is only used if DHCP fails.
# Power cycle the HL2 after changing this item.
Hware_Hl2_EepromIPUse = 'Ignore'
#Hware_Hl2_EepromIPUse = 'Use DHCP first'
#Hware_Hl2_EepromIPUse = 'Set address'
@@ -390,6 +392,7 @@ Hware_Hl2_EepromIPUse = 'Ignore'
# at power on instead of the factory supplied MAC address 0:1c:c0:a2:13:dd. It is only used at power on,
# and it is only used if it is marked valid by setting "Eeprom MAC usage" to "Set address".
# If you have two HL2's, you must have a unique MAC address for each.
# Power cycle the HL2 after changing this item.
Hware_Hl2_EepromMAC = '0xA1 0x6B'
#Hware_Hl2_EepromMAC = '0x4C 0x33'
@@ -398,6 +401,7 @@ Hware_Hl2_EepromMAC = '0xA1 0x6B'
# the HL2 will use the last two MAC bytes from "Eeprom MAC address"; otherwise the default MAC is used.
# If you change this item, the bit is written to the HL2.
# The HL2 only uses these bits at power on.
# Power cycle the HL2 after changing this item.
Hware_Hl2_EepromMACUse = 'Ignore'
#Hware_Hl2_EepromMACUse = 'Set address'
@@ -474,13 +478,6 @@ hermes_iob_rxin = 'J10 available'
#hermes_iob_rxin = 'HL2 Rx to J9'
#hermes_iob_rxin = 'Use J9 and J10'
## hermes_lite2_enable Hermes Lite2 protocol, boolean
# This turns on some of the protocol extensions for the Hermes Lite2 that are not part
# of the official Hermes Protocol 1. Currently this only enables Tx Inhibit (CN8).
# Changes are immediate (no need to restart).
hermes_lite2_enable = True
#hermes_lite2_enable = False
# These are known power meter calibration tables. This table is not present in the JSON settings file.
power_meter_std_calibrations = {}
@@ -508,17 +505,17 @@ Hermes_BandDictEnTx = False
#Hermes_BandDictEnTx = True
################ Receivers Red Pitaya, The Red Pitaya Project by Pavel Demin. This uses the Hermes FPGA code.
################ Receivers Red Pitaya, The Red Pitaya project by Pavel Demin.
## hardware_file_name Hardware file path, rfile
# This is the file that contains the control logic for each radio.
#hardware_file_name = 'hermes/quisk_hardware.py'
## widgets_file_name Widget file path, rfile
# This optional file adds additional controls for the radio.
#widgets_file_name = ''
#widgets_file_name = 'hermes/hpsdr_widgets.py'
## use_rx_udp Hardware type, integer choice
# This is the type of UDP hardware. Use 10 for the Hermes protocol.
# This is the type of UDP hardware. Use 10 for the Red Pitaya using the OpenHPSDR protocol.
#use_rx_udp = 10
## rx_udp_ip IP change, text
@@ -586,7 +583,87 @@ Hermes_BandDictEnTx = False
#Hermes_BandDictEnTx = True
################ Receivers SoapySDR, The SoapySDR interface to multiple hardware SDRs.
################ Receivers OpenHPSDR, Radios using the HPSDR Protocol 1.
## hardware_file_name Hardware file path, rfile
# This is the file that contains the control logic for each radio.
#hardware_file_name = 'hermes/quisk_hardware.py'
## widgets_file_name Widget file path, rfile
# This optional file adds additional controls for the radio.
#widgets_file_name = 'hermes/hpsdr_widgets.py'
## use_rx_udp Hardware type, integer choice
# This is the type of UDP hardware. Use 10 for hardware using the OpenHPSDR protocol 1.
#use_rx_udp = 10
## rx_udp_ip IP change, text
# This item should be left blank. It is used to change the IP address of the hardware to a different
# IP once the hardware is found. Not all Hermes firmware supports changing the IP address.
#rx_udp_ip = ""
## rx_udp_port Hardware UDP port, integer
# This is the UDP port number of your hardware.
#rx_udp_port = 1024
## rx_udp_ip_netmask Network netmask, text
# This is the netmask for the network.
#rx_udp_ip_netmask = '255.255.255.0'
## tx_ip Transmit IP, text
# Leave this blank to use the same IP address as the receive hardware. Otherwise, enter "disable"
# to disable sending transmit I/Q samples, or enter the actual IP address. You must enter "disable"
# if you have multiple hardwares on the network, and only one should transmit. This item is normally blank.
tx_ip = ""
#tx_ip = "disable"
## tx_audio_port Tx audio UDP port, integer
# This is the UDP port for transmit audio I/Q samples. Enter zero to calculate this from the
# base hardware port. Otherwise enter the special custom port.
tx_audio_port = 0
## rx_udp_clock Clock frequency Hertz, integer
# This is the clock frequency of the hardware in Hertz.
#rx_udp_clock = 122880000
#rx_udp_clock = 76800000
#rx_udp_clock = 125000000
## tx_level Tx Level, dict
# This sets the transmit level 0 to 255 for each band.
# The config screen has a slider 0 to 100% so you can reduce the transmit power.
# The hardware only supports a limited adjustment range, so zero is still a small amount of power.
tx_level = {}
## digital_tx_level Digital Tx power %, integer
# Digital modes reduce power by the percentage on the config screen.
# This is the maximum value of the slider.
#digital_tx_level = 100
## hermes_code_version Hermes code version, integer
# There can be multiple Hermes devices on a network, but Quisk can only use one of these. If you have multiple
# hermes devices, you can use this to specify a unique device. Or use -1 to accept any board.
hermes_code_version = -1
## hermes_board_id Hermes board ID, integer
# There can be multiple Hermes devices on a network, but Quisk can only use one of these. If you have multiple
# hermes devices, you can use this to specify a unique device. Or use -1 to accept any board.
hermes_board_id = -1
## Hermes_BandDict Hermes Bus, dict
# The Hermes_BandDict sets the 7 bits on the J16 connector.
Hermes_BandDict = {
'160':0b0000001, '80':0b0000010, '60':0b0000100, '40':0b0001000, '30':0b0010000, '20':0b0100000, '15':0b1000000}
## Hermes_BandDictTx Tx IO Bus, dict
# The Hermes_BandDictTx sets the 7 bits on the J16 connector for Tx if enabled.
Hermes_BandDictTx = {'160':0, '80':0, '60':0, '40':0, '30':0, '20':0, '17':0, '15':0, '12':0, '10':0}
## Hermes_BandDictEnTx Enable Tx Filt, boolean
# Enable the separate Rx and Tx settings for the J16 connector.
Hermes_BandDictEnTx = False
#Hermes_BandDictEnTx = True
################ Receivers SoapySDR, The SoapySDR interface to multiple SDRs.
## hardware_file_name Hardware file path, rfile
# This is the file that contains the control logic for each radio.
#hardware_file_name = 'soapypkg/quisk_hardware.py'
@@ -602,7 +679,7 @@ Hermes_BandDictEnTx = False
# Further items are present in the radio dictionary with names soapy_*
################ Receivers SdrIQ, The SDR-IQ receiver by RfSpace
################ Receivers SdrIQ, The SDR-IQ receiver by RfSpace.
## hardware_file_name Hardware file path, rfile
# This is the file that contains the control logic for each radio.
hardware_file_name = 'quisk_hardware_sdriq.py'
@@ -633,7 +710,7 @@ sdriq_decimation = 1250
################ Receivers Odyssey, The Odyssey project using a UDP protocol similar to the HiQSDR
################ Receivers Odyssey, The Odyssey project.
## hardware_file_name Hardware file path, rfile
# This is the file that contains the control logic for each radio.
#hardware_file_name = 'hiqsdr/quisk_hardware.py'
@@ -744,7 +821,7 @@ sndp_active = True
#radio_sound_mic_boost = True
################ Receivers Odyssey2, The Odyssey-2 project using the HPSDR Hermes protocol
################ Receivers Odyssey2, The Odyssey-2 project.
## hardware_file_name Hardware file path, rfile
# This is the file that contains the control logic for each radio.
#hardware_file_name = 'hermes/quisk_hardware.py'
@@ -759,7 +836,7 @@ sndp_active = True
# You can set these options:
## use_rx_udp Hardware type, integer choice
# This is the type of UDP hardware. Use 10 for the Hermes protocol.
# This is the type of UDP hardware. Use 10 for the Odyssey-2.
#use_rx_udp = 10
## rx_udp_ip IP change, text
@@ -828,7 +905,7 @@ Hermes_BandDictEnTx = False
#Hermes_BandDictEnTx = True
################ Receivers Afedri, The Afedri SDR receiver with the Ethernet interface.
################ Receivers Afedri, The Afedri SDR receiver with Ethernet.
## hardware_file_name Hardware file path, rfile
# This is the file that contains the control logic for each radio.
#hardware_file_name = 'afedrinet/quisk_hardware.py'
@@ -860,7 +937,7 @@ Hermes_BandDictEnTx = False
#default_rf_gain = 11
################ Receivers Control Head, Use Quisk to control a remote radio. No real hardware is used here.
################ Receivers Control Head, Use Quisk to control a remote Quisk radio.
## hardware_file_name Hardware file path, rfile
# Quisk can be used as a control head to control a real radio located remotely.
# This file contains the control logic for remote radios of type Hermes, SoftRock or HiQSDR.
+1 -1
View File
@@ -7,7 +7,7 @@ import os
# You must define the version here. A title string including
# the version will be written to __init__.py and read by quisk.py.
Version = '4.2.46'
Version = '4.2.47'
fp = open("__init__.py", "w") # write title string
fp.write("#Quisk version %s\n" % Version)