quisk-kc4upr/soapypkg/quisk_hardware.py

165 lines
6.4 KiB
Python
Executable File

# This is the hardware file to support radios accessed by the SoapySDR interface.
from __future__ import print_function
from __future__ import absolute_import
from __future__ import division
import socket, traceback, time, math
import _quisk as QS
try:
from soapypkg import soapy
except:
#traceback.print_exc()
soapy = None
from quisk_hardware_model import Hardware as BaseHardware
DEBUG = 0
class Hardware(BaseHardware):
def __init__(self, app, conf):
BaseHardware.__init__(self, app, conf)
self.vardecim_index = 0
self.fVFO = 0.0 # Careful, this is a float
def pre_open(self):
pass
def set_parameter(self, *args):
if soapy:
txt = soapy.set_parameter(*args)
if txt:
dlg = wx.MessageDialog(None, txt, 'SoapySDR Error', wx.OK|wx.ICON_ERROR)
dlg.ShowModal()
dlg.Destroy()
def open(self): # Called once to open the Hardware
if not soapy:
return "Soapy module not available"
radio_dict = self.application.local_conf.GetRadioDict()
device = radio_dict.get('soapy_device', '')
if radio_dict.get('soapy_enable_tx', '') == "Enable":
txt = soapy.open_device(device, 1, self.conf.data_poll_usec)
else:
txt = soapy.open_device(device, 3, self.conf.data_poll_usec) # Tx is disabled
for name in ('soapy_setAntenna_rx', 'soapy_setAntenna_tx'):
value = radio_dict.get(name, '') # string values
self.set_parameter(name, value, 0.0)
for name in ('soapy_setBandwidth_rx', 'soapy_setBandwidth_tx', 'soapy_setSampleRate_rx', 'soapy_setSampleRate_tx'):
value = radio_dict.get(name, '')
try:
value = float(value) * 1E3 # these are in KHz
except:
pass
else:
self.set_parameter(name, '', value)
if name == 'soapy_setSampleRate_tx':
value = int(value + 0.1)
QS.set_tx_audio(tx_sample_rate=value)
self.ChangeGain('_rx')
self.ChangeGain('_tx')
#for name in ('soapy_getSampleRate_rx', 'soapy_getSampleRate_tx', 'soapy_getBandwidth_rx', 'soapy_getBandwidth_tx'):
# print ('Get ***', name, soapy.get_parameter(name, 1))
return txt
def ChangeGain(self, rxtx): # rxtx is '_rx' or '_tx'
if not soapy:
return
radio_dict = self.application.local_conf.GetRadioDict()
gain_mode = radio_dict['soapy_gain_mode' + rxtx]
gain_values = radio_dict['soapy_gain_values' + rxtx]
if gain_mode == 'automatic':
self.set_parameter('soapy_setGainMode' + rxtx, 'true', 0.0)
elif gain_mode == 'total':
self.set_parameter('soapy_setGainMode' + rxtx, 'false', 0.0)
gain = gain_values.get('total', '0')
gain = float(gain)
self.set_parameter('soapy_setGain' + rxtx, '', gain)
elif gain_mode == 'detailed':
self.set_parameter('soapy_setGainMode' + rxtx, 'false', 0.0)
for name, dmin, dmax, dstep in radio_dict.get('soapy_listGainsValues' + rxtx, ()):
if name == 'total':
continue
gain = gain_values.get(name, '0')
gain = float(gain)
self.set_parameter('soapy_setGainElement' + rxtx, name, gain)
def close(self): # Called once to close the Hardware
if soapy:
soapy.close_device(1)
def ChangeFrequency(self, tune, vfo, source='', band='', event=None):
fVFO = float(vfo)
if self.fVFO != fVFO:
self.fVFO = fVFO
self.set_parameter('soapy_setFrequency_rx', '', fVFO)
self.set_parameter('soapy_setFrequency_tx', '', float(tune))
return tune, vfo
def ReturnFrequency(self):
# Return the current tuning and VFO frequency. If neither have changed,
# you can return (None, None). This is called at about 10 Hz by the main.
# return (tune, vfo) # return changed frequencies
return None, None # frequencies have not changed
def ReturnVfoFloat(self):
# Return the accurate VFO frequency as a floating point number.
# You can return None to indicate that the integer VFO frequency is valid.
return None
def OnBtnFDX(self, fdx): # fdx is 0 or 1
if soapy:
self.set_parameter('soapy_FDX', '', float(fdx))
def OnButtonPTT(self, event):
btn = event.GetEventObject()
if btn.GetValue():
QS.set_PTT(1)
QS.set_key_down(1)
else:
QS.set_PTT(0)
QS.set_key_down(0)
def OnSpot(self, level):
# level is -1 for Spot button Off; else the Spot level 0 to 1000.
pass
def ChangeMode(self, mode): # Change the tx/rx mode
# mode is a string: "USB", "AM", etc.
pass
def ChangeBand(self, band):
# band is a string: "60", "40", "WWV", etc.
try:
self.transverter_offset = self.conf.bandTransverterOffset[band]
except:
self.transverter_offset = 0
def HeartBeat(self): # Called at about 10 Hz by the main
pass
def ImmediateChange(self, name, value):
if name in ('soapy_gain_mode_rx', 'soapy_gain_mode_tx'):
self.ChangeGain(name[-3:])
elif name in ('soapy_setAntenna_rx', 'soapy_setAntenna_tx'):
self.set_parameter(name, value, 0.0) # string values
elif name in ('soapy_setBandwidth_rx', 'soapy_setBandwidth_tx', 'soapy_setSampleRate_rx', 'soapy_setSampleRate_tx'):
try:
value = float(value) * 1E3 # kHz values
except:
pass
else:
self.set_parameter(name, '', value)
if name == 'soapy_setSampleRate_tx':
value = int(value + 0.1)
QS.set_tx_audio(tx_sample_rate=value)
elif name == 'soapy_setSampleRate_rx':
value = int(value + 0.1)
self.application.OnBtnDecimation(rate=value)
self.set_parameter('soapy_setFrequency_rx', '', self.fVFO) # driver Lime requires reset of Rx freq on sample rate change
# The "VarDecim" methods are used to change the hardware decimation rate.
# If VarDecimGetChoices() returns any False value, no other methods are called.
def VarDecimGetChoices(self): # Not used to set sample rate
return ["None"]
def VarDecimGetLabel(self): # Return a text label for the decimation control.
return 'Rx rate: Use SoapySDR config'
def VarDecimGetIndex(self): # Return the index 0, 1, ... of the current decimation.
return 0
def VarDecimSet(self, index=None): # Called when the control is operated; if index==None, called on startup.
name = 'soapy_setSampleRate_rx'
radio_dict = self.application.local_conf.GetRadioDict()
rate = radio_dict.get(name, 48) # this is in KHz
try:
rate = float(rate) * 1E3
rate = int(rate + 0.1)
except:
rate = 48000
return rate
def VarDecimRange(self): # Return the lowest and highest sample rate.
return 48000, 192000