Initial hackrf_sweep skeleton

This commit is contained in:
Mike Walters 2016-07-30 06:23:25 +01:00
parent 6cf2694708
commit a3ce184f5e
5 changed files with 107 additions and 10 deletions

View File

@ -5,7 +5,7 @@ import sys, signal, time
from PyQt4 import QtCore, QtGui from PyQt4 import QtCore, QtGui
from qspectrumanalyzer.version import __version__ from qspectrumanalyzer.version import __version__
from qspectrumanalyzer.backend import RtlPowerThread, RtlPowerFftwThread from qspectrumanalyzer.backend import RtlPowerThread, RtlPowerFftwThread, HackRFSweepThread
from qspectrumanalyzer.data import DataStorage from qspectrumanalyzer.data import DataStorage
from qspectrumanalyzer.plot import SpectrumPlotWidget, WaterfallPlotWidget from qspectrumanalyzer.plot import SpectrumPlotWidget, WaterfallPlotWidget
from qspectrumanalyzer.utils import color_to_str, str_to_color from qspectrumanalyzer.utils import color_to_str, str_to_color
@ -186,6 +186,9 @@ class QSpectrumAnalyzerMainWindow(QtGui.QMainWindow, Ui_QSpectrumAnalyzerMainWin
backend = settings.value("backend", "rtl_power") backend = settings.value("backend", "rtl_power")
if backend == "rtl_power_fftw": if backend == "rtl_power_fftw":
self.rtl_power_thread = RtlPowerFftwThread(self.data_storage) self.rtl_power_thread = RtlPowerFftwThread(self.data_storage)
elif backend == "hackrf_sweep":
self.rtl_power_thread = HackRFSweepThread(self.data_storage)
print(self.rtl_power_thread)
else: else:
self.rtl_power_thread = RtlPowerThread(self.data_storage) self.rtl_power_thread = RtlPowerThread(self.data_storage)

View File

@ -267,3 +267,85 @@ class RtlPowerFftwThread(RtlPowerBaseThread):
pass pass
self.prev_line = line self.prev_line = line
class HackRFSweepThread(RtlPowerBaseThread):
"""Thread which runs hackrf_sweep process"""
def setup(self, start_freq, stop_freq, bin_size, interval=10.0, gain=-1,
ppm=0, crop=0, single_shot=False, device_index=0, sample_rate=2560000):
"""Setup hackrf_sweep params"""
crop = crop * 100
overlap = crop * 2
freq_range = stop_freq * 1e6 - start_freq * 1e6
min_overhang = sample_rate * overlap * 0.01
hops = math.ceil((freq_range - min_overhang) / (sample_rate - min_overhang))
overhang = (hops * sample_rate - freq_range) / (hops - 1) if hops > 1 else 0
bins = math.ceil(sample_rate / (bin_size * 1e3))
crop_freq = sample_rate * crop * 0.01
self.params = {
"start_freq": start_freq,
"stop_freq": stop_freq,
"freq_range": freq_range,
"device_index": device_index,
"sample_rate": sample_rate,
"bin_size": bin_size,
"bins": bins,
"interval": interval,
"hops": hops,
"time": interval / hops,
"gain": gain * 10,
"ppm": ppm,
"crop": crop,
"overlap": overlap,
"min_overhang": min_overhang,
"overhang": overhang,
"single_shot": single_shot
}
self.freqs = [self.get_hop_freq(hop) for hop in range(hops)]
self.freqs_crop = [(f[0] + crop_freq, f[1] - crop_freq) for f in self.freqs]
self.databuffer = {"timestamp": [], "x": [], "y": []}
self.databuffer_hop = {"timestamp": [], "x": [], "y": []}
self.hop = 0
self.prev_line = ""
print("hackrf_sweep params:")
pprint.pprint(self.params)
print()
def get_hop_freq(self, hop):
"""Get start and stop frequency for particular hop"""
start_freq = self.params["start_freq"] * 1e6 + (self.params["sample_rate"] - self.params["overhang"]) * hop
stop_freq = start_freq + self.params["sample_rate"] - (self.params["sample_rate"] / self.params["bins"])
return (start_freq, stop_freq)
def process_start(self):
"""Start hackrf_sweep process"""
if not self.process and self.params:
settings = QtCore.QSettings()
cmdline = [
settings.value("rtl_power_executable", "hackrf_sweep"),
]
self.process = subprocess.Popen(cmdline, stdout=subprocess.PIPE, stderr=subprocess.DEVNULL,
universal_newlines=False)
def parse_output(self, buf):
"""Parse one buf of output from hackrf_sweep"""
data = np.fromstring(buf, dtype='<f4')
print("Got buffer for {}MHz".format(data[0]))
def run(self):
"""hackrf_sweep thread main loop"""
self.process_start()
self.alive = True
self.rtlPowerStarted.emit()
while self.alive:
buf = self.process.stdout.read(4*(1+32))
if buf:
self.parse_output(buf)
self.process_stop()
self.alive = False
self.rtlPowerStopped.emit()

View File

@ -252,37 +252,37 @@
<context> <context>
<name>QSpectrumAnalyzerSettings</name> <name>QSpectrumAnalyzerSettings</name>
<message> <message>
<location filename="ui_qspectrumanalyzer_settings.py" line="112"/> <location filename="ui_qspectrumanalyzer_settings.py" line="114"/>
<source>rtl_power</source> <source>rtl_power</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="ui_qspectrumanalyzer_settings.py" line="113"/> <location filename="ui_qspectrumanalyzer_settings.py" line="115"/>
<source>...</source> <source>...</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="ui_qspectrumanalyzer_settings.py" line="110"/> <location filename="ui_qspectrumanalyzer_settings.py" line="111"/>
<source>rtl_power_fftw</source> <source>rtl_power_fftw</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="ui_qspectrumanalyzer_settings.py" line="108"/> <location filename="ui_qspectrumanalyzer_settings.py" line="109"/>
<source>&amp;Backend:</source> <source>&amp;Backend:</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="ui_qspectrumanalyzer_settings.py" line="111"/> <location filename="ui_qspectrumanalyzer_settings.py" line="113"/>
<source>E&amp;xecutable:</source> <source>E&amp;xecutable:</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="ui_qspectrumanalyzer_settings.py" line="114"/> <location filename="ui_qspectrumanalyzer_settings.py" line="116"/>
<source>&amp;Waterfall history size:</source> <source>&amp;Waterfall history size:</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="ui_qspectrumanalyzer_settings.py" line="116"/> <location filename="ui_qspectrumanalyzer_settings.py" line="118"/>
<source>Sa&amp;mple rate:</source> <source>Sa&amp;mple rate:</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
@ -292,15 +292,20 @@
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="ui_qspectrumanalyzer_settings.py" line="107"/> <location filename="ui_qspectrumanalyzer_settings.py" line="108"/>
<source>Settings - QSpectrumAnalyzer</source> <source>Settings - QSpectrumAnalyzer</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="ui_qspectrumanalyzer_settings.py" line="115"/> <location filename="ui_qspectrumanalyzer_settings.py" line="117"/>
<source>&amp;Device index:</source> <source>&amp;Device index:</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message>
<location filename="ui_qspectrumanalyzer_settings.py" line="112"/>
<source>hackrf_sweep</source>
<translation type="unfinished"></translation>
</message>
</context> </context>
<context> <context>
<name>QSpectrumAnalyzerSmooth</name> <name>QSpectrumAnalyzerSmooth</name>

View File

@ -38,6 +38,11 @@
<string>rtl_power_fftw</string> <string>rtl_power_fftw</string>
</property> </property>
</item> </item>
<item>
<property name="text">
<string>hackrf_sweep</string>
</property>
</item>
</widget> </widget>
</item> </item>
<item row="1" column="0"> <item row="1" column="0">

View File

@ -37,6 +37,7 @@ class Ui_QSpectrumAnalyzerSettings(object):
self.backendComboBox.setObjectName(_fromUtf8("backendComboBox")) self.backendComboBox.setObjectName(_fromUtf8("backendComboBox"))
self.backendComboBox.addItem(_fromUtf8("")) self.backendComboBox.addItem(_fromUtf8(""))
self.backendComboBox.addItem(_fromUtf8("")) self.backendComboBox.addItem(_fromUtf8(""))
self.backendComboBox.addItem(_fromUtf8(""))
self.formLayout.setWidget(0, QtGui.QFormLayout.FieldRole, self.backendComboBox) self.formLayout.setWidget(0, QtGui.QFormLayout.FieldRole, self.backendComboBox)
self.label = QtGui.QLabel(QSpectrumAnalyzerSettings) self.label = QtGui.QLabel(QSpectrumAnalyzerSettings)
self.label.setObjectName(_fromUtf8("label")) self.label.setObjectName(_fromUtf8("label"))
@ -108,6 +109,7 @@ class Ui_QSpectrumAnalyzerSettings(object):
self.label_3.setText(_translate("QSpectrumAnalyzerSettings", "&Backend:", None)) self.label_3.setText(_translate("QSpectrumAnalyzerSettings", "&Backend:", None))
self.backendComboBox.setItemText(0, _translate("QSpectrumAnalyzerSettings", "rtl_power", None)) self.backendComboBox.setItemText(0, _translate("QSpectrumAnalyzerSettings", "rtl_power", None))
self.backendComboBox.setItemText(1, _translate("QSpectrumAnalyzerSettings", "rtl_power_fftw", None)) self.backendComboBox.setItemText(1, _translate("QSpectrumAnalyzerSettings", "rtl_power_fftw", None))
self.backendComboBox.setItemText(2, _translate("QSpectrumAnalyzerSettings", "hackrf_sweep", None))
self.label.setText(_translate("QSpectrumAnalyzerSettings", "E&xecutable:", None)) self.label.setText(_translate("QSpectrumAnalyzerSettings", "E&xecutable:", None))
self.executableEdit.setText(_translate("QSpectrumAnalyzerSettings", "rtl_power", None)) self.executableEdit.setText(_translate("QSpectrumAnalyzerSettings", "rtl_power", None))
self.executableButton.setText(_translate("QSpectrumAnalyzerSettings", "...", None)) self.executableButton.setText(_translate("QSpectrumAnalyzerSettings", "...", None))