Merge pull request #10 from xmikos/hackrf_sweep
Merge hackrf_sweep branch into master
This commit is contained in:
commit
7fa0985133
@ -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, SoapyPowerThread, RxPowerThread
|
from qspectrumanalyzer.backend import RtlPowerThread, RtlPowerFftwThread, SoapyPowerThread, RxPowerThread, 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
|
||||||
@ -57,6 +57,15 @@ class QSpectrumAnalyzerSettings(QtGui.QDialog, Ui_QSpectrumAnalyzerSettings):
|
|||||||
self.executableEdit.setText(text)
|
self.executableEdit.setText(text)
|
||||||
self.deviceEdit.setText("")
|
self.deviceEdit.setText("")
|
||||||
|
|
||||||
|
if text == "hackrf_sweep":
|
||||||
|
self.sampleRateSpinBox.setMinimum(20000000)
|
||||||
|
self.sampleRateSpinBox.setMaximum(20000000)
|
||||||
|
self.sampleRateSpinBox.setValue(20000000)
|
||||||
|
else:
|
||||||
|
self.sampleRateSpinBox.setMinimum(0)
|
||||||
|
self.sampleRateSpinBox.setMaximum(25000000)
|
||||||
|
self.sampleRateSpinBox.setValue(2560000)
|
||||||
|
|
||||||
def accept(self):
|
def accept(self):
|
||||||
"""Save settings when dialog is accepted"""
|
"""Save settings when dialog is accepted"""
|
||||||
settings = QtCore.QSettings()
|
settings = QtCore.QSettings()
|
||||||
@ -193,6 +202,29 @@ class QSpectrumAnalyzerMainWindow(QtGui.QMainWindow, Ui_QSpectrumAnalyzerMainWin
|
|||||||
self.power_thread = RxPowerThread(self.data_storage)
|
self.power_thread = RxPowerThread(self.data_storage)
|
||||||
elif backend == "rtl_power_fftw":
|
elif backend == "rtl_power_fftw":
|
||||||
self.power_thread = RtlPowerFftwThread(self.data_storage)
|
self.power_thread = RtlPowerFftwThread(self.data_storage)
|
||||||
|
elif backend == "hackrf_sweep":
|
||||||
|
self.gainSpinBox.setMinimum(0)
|
||||||
|
self.gainSpinBox.setMaximum(102)
|
||||||
|
self.gainSpinBox.setValue(40)
|
||||||
|
self.startFreqSpinBox.setMinimum(0)
|
||||||
|
self.startFreqSpinBox.setMaximum(7230)
|
||||||
|
self.startFreqSpinBox.setValue(0)
|
||||||
|
self.stopFreqSpinBox.setMinimum(0)
|
||||||
|
self.stopFreqSpinBox.setMaximum(7250)
|
||||||
|
self.stopFreqSpinBox.setValue(6000)
|
||||||
|
self.binSizeSpinBox.setMinimum(40)
|
||||||
|
self.binSizeSpinBox.setMaximum(5000)
|
||||||
|
self.binSizeSpinBox.setValue(1000)
|
||||||
|
self.intervalSpinBox.setMinimum(0)
|
||||||
|
self.intervalSpinBox.setMaximum(0)
|
||||||
|
self.intervalSpinBox.setValue(0)
|
||||||
|
self.ppmSpinBox.setMinimum(0)
|
||||||
|
self.ppmSpinBox.setMaximum(0)
|
||||||
|
self.ppmSpinBox.setValue(0)
|
||||||
|
self.cropSpinBox.setMinimum(0)
|
||||||
|
self.cropSpinBox.setMaximum(0)
|
||||||
|
self.cropSpinBox.setValue(0)
|
||||||
|
self.power_thread = HackRFSweepThread(self.data_storage)
|
||||||
else:
|
else:
|
||||||
self.power_thread = RtlPowerThread(self.data_storage)
|
self.power_thread = RtlPowerThread(self.data_storage)
|
||||||
|
|
||||||
|
@ -2,6 +2,7 @@ import subprocess, math, pprint, re
|
|||||||
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
from PyQt4 import QtCore
|
from PyQt4 import QtCore
|
||||||
|
import struct
|
||||||
|
|
||||||
|
|
||||||
class BasePowerThread(QtCore.QThread):
|
class BasePowerThread(QtCore.QThread):
|
||||||
@ -147,6 +148,8 @@ class RtlPowerThread(BasePowerThread):
|
|||||||
def setup(self, start_freq, stop_freq, bin_size, interval=10.0, gain=-1,
|
def setup(self, start_freq, stop_freq, bin_size, interval=10.0, gain=-1,
|
||||||
ppm=0, crop=0, single_shot=False, device=0, sample_rate=2560000):
|
ppm=0, crop=0, single_shot=False, device=0, sample_rate=2560000):
|
||||||
"""Setup rtl_power params"""
|
"""Setup rtl_power params"""
|
||||||
|
if bin_size > 2800:
|
||||||
|
bin_size = 2800
|
||||||
self.params = {
|
self.params = {
|
||||||
"start_freq": start_freq,
|
"start_freq": start_freq,
|
||||||
"stop_freq": stop_freq,
|
"stop_freq": stop_freq,
|
||||||
@ -235,6 +238,8 @@ class RtlPowerFftwThread(BasePowerThread):
|
|||||||
min_overhang = sample_rate * overlap * 0.01
|
min_overhang = sample_rate * overlap * 0.01
|
||||||
hops = math.ceil((freq_range - min_overhang) / (sample_rate - min_overhang))
|
hops = math.ceil((freq_range - min_overhang) / (sample_rate - min_overhang))
|
||||||
overhang = (hops * sample_rate - freq_range) / (hops - 1) if hops > 1 else 0
|
overhang = (hops * sample_rate - freq_range) / (hops - 1) if hops > 1 else 0
|
||||||
|
if bin_size > 2800:
|
||||||
|
bin_size = 2800
|
||||||
bins = math.ceil(sample_rate / (bin_size * 1e3))
|
bins = math.ceil(sample_rate / (bin_size * 1e3))
|
||||||
crop_freq = sample_rate * crop * 0.01
|
crop_freq = sample_rate * crop * 0.01
|
||||||
|
|
||||||
@ -450,3 +455,112 @@ class SoapyPowerThread(BasePowerThread):
|
|||||||
self.databuffer_hop["y"].append(power)
|
self.databuffer_hop["y"].append(power)
|
||||||
|
|
||||||
self.prev_line = line
|
self.prev_line = line
|
||||||
|
|
||||||
|
|
||||||
|
class HackRFSweepThread(BasePowerThread):
|
||||||
|
"""Thread which runs hackrf_sweep process"""
|
||||||
|
def setup(self, start_freq=0, stop_freq=6000, bin_size=1000,
|
||||||
|
interval=0.0, gain=40, ppm=0, crop=0, single_shot=False,
|
||||||
|
device_index=0, sample_rate=20000000):
|
||||||
|
"""Setup hackrf_sweep params"""
|
||||||
|
# theoretically we can support bins smaller than 40 kHz, but it is
|
||||||
|
# unlikely to result in acceptable performance
|
||||||
|
if bin_size < 40:
|
||||||
|
bin_size = 40
|
||||||
|
if bin_size > 5000:
|
||||||
|
bin_size = 5000
|
||||||
|
|
||||||
|
# We only support whole numbers of steps with bandwidth equal to the
|
||||||
|
# sample rate.
|
||||||
|
step_bandwidth = sample_rate / 1000000
|
||||||
|
total_bandwidth = stop_freq - start_freq
|
||||||
|
step_count = 1 + (total_bandwidth - 1) // step_bandwidth
|
||||||
|
total_bandwidth = step_count * step_bandwidth
|
||||||
|
stop_freq = start_freq + total_bandwidth
|
||||||
|
|
||||||
|
# distribute gain between two analog gain stages
|
||||||
|
if gain < 0:
|
||||||
|
gain = 0
|
||||||
|
if gain > 102:
|
||||||
|
gain = 102
|
||||||
|
lna_gain = 8 * (gain // 18)
|
||||||
|
vga_gain = 2 * ((gain - lna_gain) // 2)
|
||||||
|
|
||||||
|
self.params = {
|
||||||
|
"start_freq": start_freq, # MHz
|
||||||
|
"stop_freq": stop_freq, # MHz
|
||||||
|
"hops": 0,
|
||||||
|
"device_index": 0,
|
||||||
|
"sample_rate": 20e6, # sps
|
||||||
|
"bin_size": bin_size, # kHz
|
||||||
|
"interval": 0, # seconds
|
||||||
|
"gain": gain,
|
||||||
|
"lna_gain": lna_gain,
|
||||||
|
"vga_gain": vga_gain,
|
||||||
|
"ppm": 0,
|
||||||
|
"crop": 0,
|
||||||
|
"single_shot": single_shot
|
||||||
|
}
|
||||||
|
self.databuffer = {"timestamp": [], "x": [], "y": []}
|
||||||
|
|
||||||
|
print("hackrf_sweep params:")
|
||||||
|
pprint.pprint(self.params)
|
||||||
|
print()
|
||||||
|
|
||||||
|
def process_start(self):
|
||||||
|
"""Start hackrf_sweep process"""
|
||||||
|
if not self.process and self.params:
|
||||||
|
settings = QtCore.QSettings()
|
||||||
|
cmdline = [
|
||||||
|
settings.value("executable", "hackrf_sweep"),
|
||||||
|
"-f", "{}:{}".format(int(self.params["start_freq"]),
|
||||||
|
int(self.params["stop_freq"])),
|
||||||
|
"-B",
|
||||||
|
"-w", "{}".format(int(self.params["bin_size"]*1000)),
|
||||||
|
"-l", "{}".format(int(self.params["lna_gain"])),
|
||||||
|
"-g", "{}".format(int(self.params["vga_gain"])),
|
||||||
|
]
|
||||||
|
|
||||||
|
if self.params["single_shot"]:
|
||||||
|
cmdline.append("-1")
|
||||||
|
|
||||||
|
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"""
|
||||||
|
(low_edge, high_edge) = struct.unpack('QQ', buf[:16])
|
||||||
|
data = np.fromstring(buf[16:], dtype='<f4')
|
||||||
|
step = (high_edge - low_edge) / len(data)
|
||||||
|
|
||||||
|
if (low_edge//1000000) <= (self.params["start_freq"]):
|
||||||
|
# Reset databuffer at the start of each sweep even if we somehow
|
||||||
|
# did not complete the previous sweep.
|
||||||
|
self.databuffer = {"timestamp": [], "x": [], "y": []}
|
||||||
|
x_axis = list(np.arange(low_edge + step/2, high_edge, step))
|
||||||
|
self.databuffer["x"].extend(x_axis)
|
||||||
|
for i in range(len(data)):
|
||||||
|
self.databuffer["y"].append(data[i])
|
||||||
|
if (high_edge / 1e6) >= (self.params["stop_freq"]):
|
||||||
|
# We've reached the end of a pass, so sort and display it.
|
||||||
|
sorted_data = sorted(zip(self.databuffer["x"], self.databuffer["y"]))
|
||||||
|
self.databuffer["x"], self.databuffer["y"] = [list(x) for x in zip(*sorted_data)]
|
||||||
|
self.data_storage.update(self.databuffer)
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
"""hackrf_sweep thread main loop"""
|
||||||
|
self.process_start()
|
||||||
|
self.alive = True
|
||||||
|
self.powerThreadStarted.emit()
|
||||||
|
|
||||||
|
while self.alive:
|
||||||
|
buf = self.process.stdout.read(4)
|
||||||
|
if buf:
|
||||||
|
(record_length,) = struct.unpack('I', buf)
|
||||||
|
buf = self.process.stdout.read(record_length)
|
||||||
|
if buf:
|
||||||
|
self.parse_output(buf)
|
||||||
|
|
||||||
|
self.process_stop()
|
||||||
|
self.alive = False
|
||||||
|
self.powerThreadStopped.emit()
|
||||||
|
@ -81,7 +81,22 @@
|
|||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../__main__.py" line="472"/>
|
<location filename="../__main__.py" line="337"/>
|
||||||
|
<source>Frequency hops: {} | Sweep time: {:.2f} s | FPS: {:.2f}</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../__main__.py" line="337"/>
|
||||||
|
<source>N/A</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../__main__.py" line="504"/>
|
||||||
|
<source>About - QSpectrumAnalyzer</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../__main__.py" line="504"/>
|
||||||
<source>QSpectrumAnalyzer {}</source>
|
<source>QSpectrumAnalyzer {}</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
@ -111,23 +126,18 @@
|
|||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui_qspectrumanalyzer.py" line="341"/>
|
<location filename="../ui_qspectrumanalyzer.py" line="319"/>
|
||||||
<source>&Settings...</source>
|
<source>Start:</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui_qspectrumanalyzer.py" line="342"/>
|
<location filename="../ui_qspectrumanalyzer.py" line="321"/>
|
||||||
<source>&Quit</source>
|
<source>Stop:</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui_qspectrumanalyzer.py" line="343"/>
|
<location filename="../ui_qspectrumanalyzer.py" line="323"/>
|
||||||
<source>Ctrl+Q</source>
|
<source>Bin size:</source>
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../ui_qspectrumanalyzer.py" line="344"/>
|
|
||||||
<source>&About</source>
|
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
@ -151,18 +161,28 @@
|
|||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui_qspectrumanalyzer.py" line="319"/>
|
<location filename="../ui_qspectrumanalyzer.py" line="331"/>
|
||||||
<source>Start:</source>
|
<source>Main curve</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui_qspectrumanalyzer.py" line="321"/>
|
<location filename="../ui_qspectrumanalyzer.py" line="332"/>
|
||||||
<source>Stop:</source>
|
<source>Colors...</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui_qspectrumanalyzer.py" line="323"/>
|
<location filename="../ui_qspectrumanalyzer.py" line="333"/>
|
||||||
<source>Bin size:</source>
|
<source>Max. hold</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui_qspectrumanalyzer.py" line="334"/>
|
||||||
|
<source>Min. hold</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui_qspectrumanalyzer.py" line="335"/>
|
||||||
|
<source>Average</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
@ -175,49 +195,29 @@
|
|||||||
<source>...</source>
|
<source>...</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
|
||||||
<location filename="../__main__.py" line="305"/>
|
|
||||||
<source>N/A</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../__main__.py" line="472"/>
|
|
||||||
<source>About - QSpectrumAnalyzer</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui_qspectrumanalyzer.py" line="338"/>
|
<location filename="../ui_qspectrumanalyzer.py" line="338"/>
|
||||||
<source>Persistence</source>
|
<source>Persistence</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui_qspectrumanalyzer.py" line="335"/>
|
<location filename="../ui_qspectrumanalyzer.py" line="341"/>
|
||||||
<source>Average</source>
|
<source>&Settings...</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui_qspectrumanalyzer.py" line="332"/>
|
<location filename="../ui_qspectrumanalyzer.py" line="342"/>
|
||||||
<source>Colors...</source>
|
<source>&Quit</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui_qspectrumanalyzer.py" line="331"/>
|
<location filename="../ui_qspectrumanalyzer.py" line="343"/>
|
||||||
<source>Main curve</source>
|
<source>Ctrl+Q</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../__main__.py" line="305"/>
|
<location filename="../ui_qspectrumanalyzer.py" line="344"/>
|
||||||
<source>Frequency hops: {} | Sweep time: {:.2f} s | FPS: {:.2f}</source>
|
<source>&About</source>
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../ui_qspectrumanalyzer.py" line="333"/>
|
|
||||||
<source>Max. hold</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../ui_qspectrumanalyzer.py" line="334"/>
|
|
||||||
<source>Min. hold</source>
|
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
@ -228,11 +228,6 @@
|
|||||||
<source>Persistence - QSpectrumAnalyzer</source>
|
<source>Persistence - QSpectrumAnalyzer</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
|
||||||
<location filename="../ui_qspectrumanalyzer_persistence.py" line="72"/>
|
|
||||||
<source>Persistence length:</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui_qspectrumanalyzer_persistence.py" line="69"/>
|
<location filename="../ui_qspectrumanalyzer_persistence.py" line="69"/>
|
||||||
<source>Decay function:</source>
|
<source>Decay function:</source>
|
||||||
@ -248,72 +243,87 @@
|
|||||||
<source>exponential</source>
|
<source>exponential</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui_qspectrumanalyzer_persistence.py" line="72"/>
|
||||||
|
<source>Persistence length:</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
<name>QSpectrumAnalyzerSettings</name>
|
<name>QSpectrumAnalyzerSettings</name>
|
||||||
<message>
|
|
||||||
<location filename="../ui_qspectrumanalyzer_settings.py" line="111"/>
|
|
||||||
<source>rtl_power</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../ui_qspectrumanalyzer_settings.py" line="114"/>
|
|
||||||
<source>...</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../ui_qspectrumanalyzer_settings.py" line="110"/>
|
|
||||||
<source>rtl_power_fftw</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../ui_qspectrumanalyzer_settings.py" line="107"/>
|
|
||||||
<source>&Backend:</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../ui_qspectrumanalyzer_settings.py" line="112"/>
|
|
||||||
<source>E&xecutable:</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../ui_qspectrumanalyzer_settings.py" line="117"/>
|
|
||||||
<source>&Waterfall history size:</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../ui_qspectrumanalyzer_settings.py" line="116"/>
|
|
||||||
<source>Sa&mple rate:</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
<message>
|
||||||
<location filename="../__main__.py" line="50"/>
|
<location filename="../__main__.py" line="50"/>
|
||||||
<source>Select executable - QSpectrumAnalyzer</source>
|
<source>Select executable - QSpectrumAnalyzer</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui_qspectrumanalyzer_settings.py" line="106"/>
|
<location filename="../ui_qspectrumanalyzer_settings.py" line="107"/>
|
||||||
<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="113"/>
|
<location filename="../ui_qspectrumanalyzer_settings.py" line="108"/>
|
||||||
<source>soapy_power</source>
|
<source>&Backend:</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="115"/>
|
||||||
|
<source>soapy_power</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui_qspectrumanalyzer_settings.py" line="110"/>
|
||||||
|
<source>rx_power</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui_qspectrumanalyzer_settings.py" line="111"/>
|
||||||
|
<source>rtl_power_fftw</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui_qspectrumanalyzer_settings.py" line="112"/>
|
||||||
|
<source>rtl_power</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui_qspectrumanalyzer_settings.py" line="113"/>
|
||||||
|
<source>hackrf_sweep</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui_qspectrumanalyzer_settings.py" line="114"/>
|
||||||
|
<source>E&xecutable:</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui_qspectrumanalyzer_settings.py" line="116"/>
|
||||||
|
<source>...</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui_qspectrumanalyzer_settings.py" line="117"/>
|
||||||
<source>Device:</source>
|
<source>Device:</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui_qspectrumanalyzer_settings.py" line="109"/>
|
<location filename="../ui_qspectrumanalyzer_settings.py" line="118"/>
|
||||||
<source>rx_power</source>
|
<source>Sa&mple rate:</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui_qspectrumanalyzer_settings.py" line="119"/>
|
||||||
|
<source>&Waterfall history size:</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
<name>QSpectrumAnalyzerSmooth</name>
|
<name>QSpectrumAnalyzerSmooth</name>
|
||||||
|
<message>
|
||||||
|
<location filename="../ui_qspectrumanalyzer_smooth.py" line="73"/>
|
||||||
|
<source>Smoothing - QSpectrumAnalyzer</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../ui_qspectrumanalyzer_smooth.py" line="74"/>
|
<location filename="../ui_qspectrumanalyzer_smooth.py" line="74"/>
|
||||||
<source>&Window function:</source>
|
<source>&Window function:</source>
|
||||||
@ -349,10 +359,5 @@
|
|||||||
<source>Window len&gth:</source>
|
<source>Window len&gth:</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
|
||||||
<location filename="../ui_qspectrumanalyzer_smooth.py" line="73"/>
|
|
||||||
<source>Smoothing - QSpectrumAnalyzer</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
</context>
|
</context>
|
||||||
</TS>
|
</TS>
|
||||||
|
@ -37,7 +37,7 @@ class SpectrumPlotWidget:
|
|||||||
self.posLabel = self.layout.addLabel(row=0, col=0, justify="right")
|
self.posLabel = self.layout.addLabel(row=0, col=0, justify="right")
|
||||||
self.plot = self.layout.addPlot(row=1, col=0)
|
self.plot = self.layout.addPlot(row=1, col=0)
|
||||||
self.plot.showGrid(x=True, y=True)
|
self.plot.showGrid(x=True, y=True)
|
||||||
self.plot.setLabel("left", "Power", units="dBm")
|
self.plot.setLabel("left", "Power", units="dB")
|
||||||
self.plot.setLabel("bottom", "Frequency", units="Hz")
|
self.plot.setLabel("bottom", "Frequency", units="Hz")
|
||||||
self.plot.setLimits(xMin=0)
|
self.plot.setLimits(xMin=0)
|
||||||
self.plot.showButtons()
|
self.plot.showButtons()
|
||||||
@ -204,7 +204,7 @@ class SpectrumPlotWidget:
|
|||||||
if self.plot.sceneBoundingRect().contains(pos):
|
if self.plot.sceneBoundingRect().contains(pos):
|
||||||
mousePoint = self.plot.vb.mapSceneToView(pos)
|
mousePoint = self.plot.vb.mapSceneToView(pos)
|
||||||
self.posLabel.setText(
|
self.posLabel.setText(
|
||||||
"<span style='font-size: 12pt'>f={:0.3f} MHz, P={:0.3f} dBm</span>".format(
|
"<span style='font-size: 12pt'>f={:0.3f} MHz, P={:0.3f} dB</span>".format(
|
||||||
mousePoint.x() / 1e6,
|
mousePoint.x() / 1e6,
|
||||||
mousePoint.y()
|
mousePoint.y()
|
||||||
)
|
)
|
||||||
|
@ -48,6 +48,11 @@
|
|||||||
<string>rtl_power</string>
|
<string>rtl_power</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">
|
||||||
|
@ -39,6 +39,7 @@ class Ui_QSpectrumAnalyzerSettings(object):
|
|||||||
self.backendComboBox.addItem(_fromUtf8(""))
|
self.backendComboBox.addItem(_fromUtf8(""))
|
||||||
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"))
|
||||||
@ -109,6 +110,7 @@ class Ui_QSpectrumAnalyzerSettings(object):
|
|||||||
self.backendComboBox.setItemText(1, _translate("QSpectrumAnalyzerSettings", "rx_power", None))
|
self.backendComboBox.setItemText(1, _translate("QSpectrumAnalyzerSettings", "rx_power", None))
|
||||||
self.backendComboBox.setItemText(2, _translate("QSpectrumAnalyzerSettings", "rtl_power_fftw", None))
|
self.backendComboBox.setItemText(2, _translate("QSpectrumAnalyzerSettings", "rtl_power_fftw", None))
|
||||||
self.backendComboBox.setItemText(3, _translate("QSpectrumAnalyzerSettings", "rtl_power", None))
|
self.backendComboBox.setItemText(3, _translate("QSpectrumAnalyzerSettings", "rtl_power", None))
|
||||||
|
self.backendComboBox.setItemText(4, _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", "soapy_power", None))
|
self.executableEdit.setText(_translate("QSpectrumAnalyzerSettings", "soapy_power", None))
|
||||||
self.executableButton.setText(_translate("QSpectrumAnalyzerSettings", "...", None))
|
self.executableButton.setText(_translate("QSpectrumAnalyzerSettings", "...", None))
|
||||||
|
Loading…
Reference in New Issue
Block a user