Everything is basically in place for at least live text. For some reason spawning the flowgraph is broken.
This commit is contained in:
parent
3b533f6b35
commit
113c23b634
@ -183,7 +183,7 @@ if __name__ == '__main__':
|
||||
updates = [] #registry of plugin update functions
|
||||
|
||||
if options.raw is True:
|
||||
rawport = air_modes.modes_raw_server()
|
||||
rawport = air_modes.modes_raw_server(9988) #port
|
||||
outputs.append(rawport.output)
|
||||
outputs.append(printraw)
|
||||
updates.append(rawport.add_pending_conns)
|
||||
@ -194,7 +194,7 @@ if __name__ == '__main__':
|
||||
outputs.append(kmlgen.output)
|
||||
|
||||
if options.sbs1 is True:
|
||||
sbs1port = air_modes.modes_output_sbs1(my_position)
|
||||
sbs1port = air_modes.modes_output_sbs1(my_position, 30003)
|
||||
outputs.append(sbs1port.output)
|
||||
updates.append(sbs1port.add_pending_conns)
|
||||
|
||||
|
@ -25,9 +25,9 @@ from string import split, join
|
||||
from datetime import *
|
||||
|
||||
class modes_raw_server:
|
||||
def __init__(self):
|
||||
def __init__(self, port):
|
||||
self._s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
self._s.bind(('', 9988))
|
||||
self._s.bind(('', port))
|
||||
self._s.listen(1)
|
||||
self._s.setblocking(0) #nonblocking
|
||||
self._conns = [] #list of active connections
|
||||
|
@ -27,11 +27,11 @@ from datetime import *
|
||||
from modes_exceptions import *
|
||||
|
||||
class modes_output_sbs1(modes_parse.modes_parse):
|
||||
def __init__(self, mypos):
|
||||
def __init__(self, mypos, port):
|
||||
modes_parse.modes_parse.__init__(self, mypos)
|
||||
self._s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
self._s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
||||
self._s.bind(('', 30003))
|
||||
self._s.bind(('', port))
|
||||
self._s.listen(1)
|
||||
self._s.setblocking(0) #nonblocking
|
||||
self._conns = [] #list of active connections
|
||||
|
246
res/modes_rx.ui
246
res/modes_rx.ui
@ -7,7 +7,7 @@
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>800</width>
|
||||
<height>600</height>
|
||||
<height>618</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
@ -18,7 +18,7 @@
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>10</x>
|
||||
<y>220</y>
|
||||
<y>240</y>
|
||||
<width>91</width>
|
||||
<height>281</height>
|
||||
</rect>
|
||||
@ -30,7 +30,7 @@
|
||||
<x>10</x>
|
||||
<y>10</y>
|
||||
<width>221</width>
|
||||
<height>181</height>
|
||||
<height>191</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="title">
|
||||
@ -62,20 +62,7 @@
|
||||
<string>Source</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>10</x>
|
||||
<y>90</y>
|
||||
<width>66</width>
|
||||
<height>17</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Gain</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QComboBox" name="comboSource">
|
||||
<widget class="QComboBox" name="combo_source">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>90</x>
|
||||
@ -85,24 +72,11 @@
|
||||
</rect>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>10</x>
|
||||
<y>150</y>
|
||||
<width>66</width>
|
||||
<height>17</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Antenna</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>10</x>
|
||||
<y>120</y>
|
||||
<y>90</y>
|
||||
<width>66</width>
|
||||
<height>17</height>
|
||||
</rect>
|
||||
@ -121,54 +95,21 @@
|
||||
</rect>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QLineEdit" name="line_gain">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>90</x>
|
||||
<y>90</y>
|
||||
<width>71</width>
|
||||
<height>27</height>
|
||||
</rect>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QLineEdit" name="line_threshold">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>90</x>
|
||||
<y>120</y>
|
||||
<y>90</y>
|
||||
<width>71</width>
|
||||
<height>27</height>
|
||||
</rect>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QComboBox" name="combo_ant">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>90</x>
|
||||
<y>150</y>
|
||||
<width>121</width>
|
||||
<height>27</height>
|
||||
</rect>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QLabel" name="label_18">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>160</x>
|
||||
<y>90</y>
|
||||
<width>31</width>
|
||||
<height>17</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>dB</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QLabel" name="label_19">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>160</x>
|
||||
<y>120</y>
|
||||
<y>90</y>
|
||||
<width>31</width>
|
||||
<height>17</height>
|
||||
</rect>
|
||||
@ -190,13 +131,112 @@
|
||||
<string>Msps</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QStackedWidget" name="stack_source">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>120</y>
|
||||
<width>221</width>
|
||||
<height>71</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="currentIndex">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="page_rf">
|
||||
<widget class="QComboBox" name="combo_ant">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>90</x>
|
||||
<y>40</y>
|
||||
<width>121</width>
|
||||
<height>27</height>
|
||||
</rect>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QLineEdit" name="line_gain">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>90</x>
|
||||
<y>10</y>
|
||||
<width>71</width>
|
||||
<height>27</height>
|
||||
</rect>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>10</x>
|
||||
<y>10</y>
|
||||
<width>66</width>
|
||||
<height>17</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Gain</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>10</x>
|
||||
<y>40</y>
|
||||
<width>66</width>
|
||||
<height>17</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Antenna</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QLabel" name="label_18">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>160</x>
|
||||
<y>10</y>
|
||||
<width>31</width>
|
||||
<height>17</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>dB</string>
|
||||
</property>
|
||||
</widget>
|
||||
</widget>
|
||||
<widget class="QWidget" name="page_file">
|
||||
<widget class="QLineEdit" name="line_inputfile">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>90</x>
|
||||
<y>10</y>
|
||||
<width>113</width>
|
||||
<height>27</height>
|
||||
</rect>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QLabel" name="label_13">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>10</x>
|
||||
<y>10</y>
|
||||
<width>66</width>
|
||||
<height>17</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Filename</string>
|
||||
</property>
|
||||
</widget>
|
||||
</widget>
|
||||
</widget>
|
||||
</widget>
|
||||
<widget class="QGroupBox" name="group_output">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>260</x>
|
||||
<y>10</y>
|
||||
<width>341</width>
|
||||
<width>281</width>
|
||||
<height>151</height>
|
||||
</rect>
|
||||
</property>
|
||||
@ -365,7 +405,7 @@
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>100</x>
|
||||
<y>220</y>
|
||||
<y>240</y>
|
||||
<width>16</width>
|
||||
<height>281</height>
|
||||
</rect>
|
||||
@ -378,7 +418,7 @@
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>130</x>
|
||||
<y>200</y>
|
||||
<y>220</y>
|
||||
<width>651</width>
|
||||
<height>301</height>
|
||||
</rect>
|
||||
@ -692,7 +732,7 @@
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>10</x>
|
||||
<y>200</y>
|
||||
<y>220</y>
|
||||
<width>101</width>
|
||||
<height>17</height>
|
||||
</rect>
|
||||
@ -704,7 +744,7 @@
|
||||
<widget class="QPushButton" name="button_start">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>640</x>
|
||||
<x>670</x>
|
||||
<y>30</y>
|
||||
<width>98</width>
|
||||
<height>27</height>
|
||||
@ -718,7 +758,7 @@
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>10</x>
|
||||
<y>520</y>
|
||||
<y>540</y>
|
||||
<width>271</width>
|
||||
<height>22</height>
|
||||
</rect>
|
||||
@ -727,6 +767,68 @@
|
||||
<string>Show ADS-B-equipped aircraft only</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QGroupBox" name="groupBox">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>570</x>
|
||||
<y>90</y>
|
||||
<width>211</width>
|
||||
<height>111</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>RX position</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<widget class="QLabel" name="label_29">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>20</x>
|
||||
<y>60</y>
|
||||
<width>71</width>
|
||||
<height>20</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Longitude</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QLineEdit" name="line_my_lon">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>90</x>
|
||||
<y>60</y>
|
||||
<width>113</width>
|
||||
<height>27</height>
|
||||
</rect>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QLineEdit" name="line_my_lat">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>90</x>
|
||||
<y>30</y>
|
||||
<width>113</width>
|
||||
<height>27</height>
|
||||
</rect>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QLabel" name="label_28">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>30</x>
|
||||
<y>40</y>
|
||||
<width>61</width>
|
||||
<height>20</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Latitude</string>
|
||||
</property>
|
||||
</widget>
|
||||
</widget>
|
||||
</widget>
|
||||
<widget class="QMenuBar" name="menubar">
|
||||
<property name="geometry">
|
||||
|
188
res/testmain.py
188
res/testmain.py
@ -1,11 +1,12 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
import os, sys
|
||||
import os, sys, time, threading
|
||||
from PyQt4 import QtCore,QtGui
|
||||
|
||||
from test import Ui_MainWindow
|
||||
|
||||
from gnuradio import gr, gru, optfir, eng_notation, blks2
|
||||
import gnuradio.gr.gr_threading as _threading
|
||||
import air_modes
|
||||
from test import Ui_MainWindow
|
||||
import csv
|
||||
|
||||
class mainwindow(QtGui.QMainWindow):
|
||||
def __init__(self):
|
||||
@ -16,8 +17,8 @@ class mainwindow(QtGui.QMainWindow):
|
||||
|
||||
#set defaults
|
||||
#add file, RTL, UHD sources
|
||||
self.ui.comboSource.addItems(["UHD device", "RTL-SDR", "File"])
|
||||
self.ui.comboSource.setCurrentIndex(0)
|
||||
self.ui.combo_source.addItems(["UHD device", "RTL-SDR", "File"])
|
||||
self.ui.combo_source.setCurrentIndex(0)
|
||||
|
||||
#populate antenna, rate combo boxes based on source
|
||||
self.populate_source_options()
|
||||
@ -44,9 +45,17 @@ class mainwindow(QtGui.QMainWindow):
|
||||
#disable by default
|
||||
self.ui.check_adsbonly.setCheckState(QtCore.Qt.Unchecked)
|
||||
|
||||
self.queue = gr.msg_queue(10)
|
||||
self.runner = None
|
||||
self.fg = None
|
||||
self.outputs = []
|
||||
self.updates = []
|
||||
self.output_handler = None
|
||||
self.kmlgen = None #necessary bc we stop its thread in shutdown
|
||||
|
||||
#goes and gets valid antenna, sample rate options from the device and grays out appropriate things
|
||||
def populate_source_options(self):
|
||||
sourceid = self.ui.comboSource.currentText()
|
||||
sourceid = self.ui.combo_source.currentText()
|
||||
self.rates = []
|
||||
self.ratetext = []
|
||||
self.antennas = []
|
||||
@ -60,23 +69,27 @@ class mainwindow(QtGui.QMainWindow):
|
||||
self.src = None #deconstruct UHD source for now
|
||||
self.ui.combo_ant.setEnabled(True)
|
||||
self.ui.combo_rate.setEnabled(True)
|
||||
self.ui.stack_source.setCurrentIndex(0)
|
||||
except:
|
||||
self.rates = []
|
||||
self.antennas = []
|
||||
self.ui.combo_ant.setEnabled(False)
|
||||
self.ui.combo_rate.setEnabled(False)
|
||||
self.ui.stack_source.setCurrentIndex(0)
|
||||
|
||||
elif sourceid == "RTL-SDR":
|
||||
self.rates = [2.4e6]
|
||||
self.antennas = ["RX"]
|
||||
self.ui.combo_ant.setEnabled(False)
|
||||
self.ui.combo_rate.setEnabled(False)
|
||||
self.ui.stack_source.setCurrentIndex(0)
|
||||
|
||||
elif sourceid == "File":
|
||||
self.rates = [2e6, 4e6, 6e6, 8e6, 10e6]
|
||||
self.antennas = ["None"]
|
||||
self.ui.combo_ant.setEnabled(False)
|
||||
self.ui.combo_rate.setEnabled(True)
|
||||
self.ui.stack_source.setCurrentIndex(1)
|
||||
|
||||
self.ui.combo_rate.clear()
|
||||
self.ratetext = ["%.3f" % (rate / 1.e6) for rate in self.rates]
|
||||
@ -89,9 +102,168 @@ class mainwindow(QtGui.QMainWindow):
|
||||
if 4e6 in self.rates:
|
||||
self.ui.combo_rate.setCurrentIndex(self.rates.index(4e6))
|
||||
|
||||
def on_comboSource_currentIndexChanged(self, index):
|
||||
def on_combo_source_currentIndexChanged(self, index):
|
||||
self.populate_source_options()
|
||||
|
||||
def on_button_start_released(self):
|
||||
#if we're already running, kill it!
|
||||
if self.runner is not None:
|
||||
self.output_handler.done = True
|
||||
self.output_handler = None
|
||||
self.fg.stop()
|
||||
self.runner = None
|
||||
if self.kmlgen is not None:
|
||||
self.kmlgen.done = True
|
||||
#TODO FIXME KMLGEN NEEDS SELFDESTRUCT
|
||||
#self.kmlgen = None
|
||||
|
||||
self.ui.button_start.setText("Start")
|
||||
|
||||
else: #we aren't already running, let's get this party started
|
||||
options = {}
|
||||
options["source"] = self.ui.combo_source.currentText()
|
||||
options["rate"] = int(self.ui.combo_rate.currentIndex())
|
||||
options["antenna"] = self.ui.combo_ant.currentText()
|
||||
options["gain"] = float(self.ui.line_gain.text())
|
||||
options["threshold"] = float(self.ui.line_threshold.text())
|
||||
options["filename"] = str(self.ui.line_inputfile.text())
|
||||
|
||||
self.fg = adsb_rx_block(options, self.queue) #create top RX block
|
||||
self.runner = top_block_runner(self.fg) #spawn new thread to do RX
|
||||
|
||||
try:
|
||||
my_position = [float(self.ui.line_my_lat.text()), float(self.ui.line_my_lon.text())]
|
||||
except:
|
||||
my_position = None
|
||||
|
||||
self.outputs = []
|
||||
self.updates = []
|
||||
|
||||
#output options to populate outputs, updates
|
||||
if self.ui.check_kml.checkState():
|
||||
#we spawn a thread to run every 30 seconds (or whatever) to generate KML
|
||||
self.kmlgen = air_modes.modes_kml(self.ui.line_kmlfilename.text(), my_position) #create a KML generating thread
|
||||
self.outputs.append(self.kmlgen.output)
|
||||
|
||||
if self.ui.check_sbs1.checkState():
|
||||
sbs1port = int(self.ui.line_sbs1port.text())
|
||||
sbs1out = air_modes.modes_output_sbs1(my_position, sbs1port)
|
||||
self.outputs.append(sbs1out.output)
|
||||
self.updates.append(sbs1out.add_pending_conns)
|
||||
|
||||
if self.ui.check_fgfs.checkState():
|
||||
fghost = "127.0.0.1" #TODO FIXME
|
||||
fgport = self.ui.line_fgfsport.currentText()
|
||||
fgout = air_modes.modes_flightgear(my_position, fghost, int(fgport))
|
||||
self.outputs.append(fgout.output)
|
||||
|
||||
if self.ui.check_raw.checkState():
|
||||
rawport = air_modes.modes_raw_server(int(self.ui.line_raw.text()))
|
||||
self.outputs.append(rawport.output)
|
||||
self.updates.append(rawport.add_pending_conns)
|
||||
|
||||
#add output for live data box
|
||||
self.outputs.append(self.output_live_data)
|
||||
|
||||
#create output handler
|
||||
self.output_handler = output_handler(self.outputs, self.updates, self.queue)
|
||||
self.ui.button_start.setText("Stop") #modify button text
|
||||
|
||||
def output_live_data(self, msg):
|
||||
self.ui.text_livedata.append(msg)
|
||||
|
||||
|
||||
class output_handler(threading.Thread):
|
||||
def __init__(self, outputs, updates, queue):
|
||||
threading.Thread.__init__(self)
|
||||
self.setDaemon(1)
|
||||
self.outputs = outputs
|
||||
self.updates = updates
|
||||
self.queue = queue
|
||||
self.done = False
|
||||
self.start()
|
||||
|
||||
def run(self):
|
||||
while self.done is False:
|
||||
for update in self.updates:
|
||||
update()
|
||||
if not self.queue.empty_p():
|
||||
msg = self.queue.delete_head()
|
||||
for output in self.outputs:
|
||||
try:
|
||||
output(msg.to_string())
|
||||
except ADSBError:
|
||||
pass
|
||||
|
||||
time.sleep(0.3)
|
||||
|
||||
self.done = True
|
||||
|
||||
|
||||
class top_block_runner(_threading.Thread):
|
||||
def __init__(self, tb):
|
||||
_threading.Thread.__init__(self)
|
||||
self.setDaemon(1)
|
||||
self.tb = tb
|
||||
self.done = False
|
||||
self.start()
|
||||
|
||||
def run(self):
|
||||
self.tb.run()
|
||||
self.done = True
|
||||
|
||||
#Top block for ADSB receiver. If you define a standard interface you
|
||||
#can make this common code between the GUI app and the cmdline app
|
||||
class adsb_rx_block (gr.top_block):
|
||||
def __init__(self, options, queue):
|
||||
gr.top_block.__init__(self)
|
||||
|
||||
self.options = options
|
||||
rate = int(options["rate"])
|
||||
use_resampler = False
|
||||
|
||||
if options["source"] == "UHD device":
|
||||
from gnuradio import uhd
|
||||
self.u = uhd.single_usrp_source("", uhd.io_type_t.COMPLEX_FLOAT32, 1)
|
||||
time_spec = uhd.time_spec(0.0)
|
||||
self.u.set_time_now(time_spec)
|
||||
self.u.set_antenna(options["antenna"])
|
||||
self.u.set_samp_rate(rate)
|
||||
self.u.set_gain(options["gain"])
|
||||
|
||||
elif options["source"] == "RTL-SDR":
|
||||
import osmosdr
|
||||
self.u = osmosdr.source_c()
|
||||
self.u.set_sample_rate(2.4e6) #fixed for RTL dongles
|
||||
self.u.set_gain_mode(0) #manual gain mode
|
||||
self.u.set_gain(options["gain"])
|
||||
use_resampler = True
|
||||
|
||||
elif options["source"] == "File":
|
||||
self.u = gr.file_source(gr.sizeof_gr_complex, options["filename"])
|
||||
|
||||
self.demod = gr.complex_to_mag()
|
||||
self.avg = gr.moving_average_ff(100, 1.0/100, 400)
|
||||
|
||||
self.preamble = air_modes.modes_preamble(rate, options["threshold"])
|
||||
self.slicer = air_modes.modes_slicer(rate, queue)
|
||||
|
||||
if use_resampler:
|
||||
self.lpfiltcoeffs = gr.firdes.low_pass(1, 5*2.4e6, 1.2e6, 300e3)
|
||||
self.resample = blks2.rational_resampler_ccf(interpolation=5, decimation=3, taps=self.lpfiltcoeffs)
|
||||
self.connect(self.u, self.resample, self.demod)
|
||||
else:
|
||||
self.connect(self.u, self.demod)
|
||||
|
||||
self.connect(self.demod, self.avg)
|
||||
self.connect(self.demod, (self.preamble, 0))
|
||||
self.connect(self.avg, (self.preamble, 1))
|
||||
self.connect((self.preamble, 0), (self.slicer, 0))
|
||||
|
||||
def tune(self, freq):
|
||||
result = self.u.set_center_freq(freq, 0)
|
||||
return result
|
||||
|
||||
if __name__ == '__main__':
|
||||
app = QtGui.QApplication(sys.argv)
|
||||
window = mainwindow()
|
||||
|
Loading…
Reference in New Issue
Block a user