Add support for rtl_power_fftw backend

This commit is contained in:
Michal Krenek (Mikos) 2015-12-07 03:36:43 +01:00
parent 1f48ebf351
commit 314118a7ff
9 changed files with 397 additions and 142 deletions

View File

@ -1,6 +1,6 @@
# Maintainer: Michal Krenek (Mikos) <m.krenek@gmail.com>
pkgname=qspectrumanalyzer
pkgver=1.1.1
pkgver=1.2.0
pkgrel=1
pkgdesc="Spectrum analyzer for RTL-SDR (GUI for rtl_power based on PyQtGraph)"
arch=('any')
@ -8,6 +8,7 @@ url="https://github.com/xmikos/qspectrumanalyzer"
license=('GPL3')
depends=('python-pyqt4' 'python-pyqtgraph' 'rtl-sdr')
makedepends=('python-setuptools')
optdepends=('rtl_power_fftw-git: alternative rtl_power implementation using FFTW library')
source=(https://github.com/xmikos/qspectrumanalyzer/archive/v$pkgver.tar.gz)
build() {

View File

@ -1,6 +1,6 @@
[Desktop Entry]
Encoding=UTF-8
Version=1.1.1
Version=1.2.0
Name=QSpectrumAnalyzer
GenericName=Spectrum analyzer
Comment=Spectrum analyzer for RTL-SDR (GUI for rtl_power based on PyQtGraph)

View File

@ -1,6 +1,6 @@
#!/usr/bin/env python
import sys, csv, subprocess, signal
import sys, subprocess, signal, math, time, pprint
import numpy as np
import pyqtgraph as pg
@ -28,21 +28,36 @@ class QSpectrumAnalyzerSettings(QtGui.QDialog, Ui_QSpectrumAnalyzerSettings):
# Load settings
settings = QtCore.QSettings()
self.rtlPowerExecutableEdit.setText(str(settings.value("rtl_power_executable") or "rtl_power"))
self.executableEdit.setText(str(settings.value("rtl_power_executable") or "rtl_power"))
self.waterfallHistorySizeSpinBox.setValue(int(settings.value("waterfall_history_size") or 100))
self.sampleRateSpinBox.setValue(int(settings.value("sample_rate") or 2560000))
backend = str(settings.value("backend") or "rtl_power")
i = self.backendComboBox.findText(backend)
if i == -1:
self.backendComboBox.setCurrentIndex(0)
else:
self.backendComboBox.setCurrentIndex(i)
@QtCore.pyqtSlot()
def on_rtlPowerExecutableButton_clicked(self):
def on_executableButton_clicked(self):
"""Open file dialog when button is clicked"""
filename = QtGui.QFileDialog.getOpenFileName(self, "QSpectrumAnalyzer - rtl_power executable")
filename = QtGui.QFileDialog.getOpenFileName(self, "QSpectrumAnalyzer - executable")
if filename:
self.rtlPowerExecutableEdit.setText(filename)
self.executableEdit.setText(filename)
@QtCore.pyqtSlot(str)
def on_backendComboBox_currentIndexChanged(self, text):
"""Change executable when backend is changed"""
self.executableEdit.setText(text)
def accept(self):
"""Save settings when dialog is accepted"""
settings = QtCore.QSettings()
settings.setValue("rtl_power_executable", self.rtlPowerExecutableEdit.text())
settings.setValue("rtl_power_executable", self.executableEdit.text())
settings.setValue("waterfall_history_size", self.waterfallHistorySizeSpinBox.value())
settings.setValue("sample_rate", self.sampleRateSpinBox.value())
settings.setValue("backend", self.backendComboBox.currentText())
QtGui.QDialog.accept(self)
@ -56,10 +71,9 @@ class QSpectrumAnalyzerMainWindow(QtGui.QMainWindow, Ui_QSpectrumAnalyzerMainWin
# Setup rtl_power thread and connect signals
self.waterfall_history_size = 100
self.datacounter = 0
self.rtl_power_thread = RtlPowerThread()
self.rtl_power_thread.dataUpdated.connect(self.update_data)
self.rtl_power_thread.rtlPowerStarted.connect(self.update_buttons)
self.rtl_power_thread.rtlPowerStopped.connect(self.update_buttons)
self.datatimestamp = 0
self.rtl_power_thread = None
self.setup_rtl_power_thread()
# Update UI
self.create_plot()
@ -67,6 +81,22 @@ class QSpectrumAnalyzerMainWindow(QtGui.QMainWindow, Ui_QSpectrumAnalyzerMainWin
self.update_buttons()
self.load_settings()
def setup_rtl_power_thread(self):
"""Create rtl_power_thread and connect signals to slots"""
if self.rtl_power_thread:
self.stop()
settings = QtCore.QSettings()
backend = str(settings.value("backend") or "rtl_power")
if backend == "rtl_power_fftw":
self.rtl_power_thread = RtlPowerFftwThread()
else:
self.rtl_power_thread = RtlPowerThread()
self.rtl_power_thread.dataUpdated.connect(self.update_data)
self.rtl_power_thread.rtlPowerStarted.connect(self.update_buttons)
self.rtl_power_thread.rtlPowerStopped.connect(self.update_buttons)
def create_plot(self):
"""Create main spectrum plot"""
self.posLabel = self.mainPlotLayout.addLabel(row=0, col=0, justify="right")
@ -135,6 +165,10 @@ class QSpectrumAnalyzerMainWindow(QtGui.QMainWindow, Ui_QSpectrumAnalyzerMainWin
self.update_plot(data)
self.update_waterfall(data)
timestamp = time.time()
self.show_status("Sweep time: {:.2f} s".format(timestamp - self.datatimestamp), timeout=0)
self.datatimestamp = timestamp
def update_plot(self, data):
"""Update main spectrum plot"""
self.curve.setData(data["x"], data["y"])
@ -171,7 +205,7 @@ class QSpectrumAnalyzerMainWindow(QtGui.QMainWindow, Ui_QSpectrumAnalyzerMainWin
self.startFreqSpinBox.setValue(float(settings.value("start_freq") or 87.0))
self.stopFreqSpinBox.setValue(float(settings.value("stop_freq") or 108.0))
self.binSizeSpinBox.setValue(float(settings.value("bin_size") or 10.0))
self.intervalSpinBox.setValue(int(settings.value("interval") or 10))
self.intervalSpinBox.setValue(float(settings.value("interval") or 10.0))
self.gainSpinBox.setValue(int(settings.value("gain") or 0))
self.ppmSpinBox.setValue(int(settings.value("ppm") or 0))
self.cropSpinBox.setValue(int(settings.value("crop") or 0))
@ -189,7 +223,7 @@ class QSpectrumAnalyzerMainWindow(QtGui.QMainWindow, Ui_QSpectrumAnalyzerMainWin
settings.setValue("start_freq", float(self.startFreqSpinBox.value()))
settings.setValue("stop_freq", float(self.stopFreqSpinBox.value()))
settings.setValue("bin_size", float(self.binSizeSpinBox.value()))
settings.setValue("interval", int(self.intervalSpinBox.value()))
settings.setValue("interval", float(self.intervalSpinBox.value()))
settings.setValue("gain", int(self.gainSpinBox.value()))
settings.setValue("ppm", int(self.ppmSpinBox.value()))
settings.setValue("crop", int(self.cropSpinBox.value()))
@ -207,15 +241,17 @@ class QSpectrumAnalyzerMainWindow(QtGui.QMainWindow, Ui_QSpectrumAnalyzerMainWin
settings = QtCore.QSettings()
self.waterfall_history_size = int(settings.value("waterfall_history_size") or 100)
self.datacounter = 0
self.datatimestamp = time.time()
if not self.rtl_power_thread.alive:
self.rtl_power_thread.setup(float(self.startFreqSpinBox.value()),
float(self.stopFreqSpinBox.value()),
float(self.binSizeSpinBox.value()),
interval=int(self.intervalSpinBox.value()),
interval=float(self.intervalSpinBox.value()),
gain=int(self.gainSpinBox.value()),
ppm=int(self.ppmSpinBox.value()),
crop=int(self.cropSpinBox.value()) / 100.0,
single_shot=single_shot)
single_shot=single_shot,
sample_rate=int(settings.value("sample_rate") or 2560000))
self.rtl_power_thread.start()
def stop(self):
@ -238,7 +274,8 @@ class QSpectrumAnalyzerMainWindow(QtGui.QMainWindow, Ui_QSpectrumAnalyzerMainWin
@QtCore.pyqtSlot()
def on_action_Settings_triggered(self):
dialog = QSpectrumAnalyzerSettings(self)
dialog.exec_()
if dialog.exec_():
self.setup_rtl_power_thread()
@QtCore.pyqtSlot()
def on_action_About_triggered(self):
@ -250,11 +287,11 @@ class QSpectrumAnalyzerMainWindow(QtGui.QMainWindow, Ui_QSpectrumAnalyzerMainWin
def closeEvent(self, event):
"""Save settings when main window is closed"""
self.rtl_power_thread.stop()
self.stop()
self.save_settings()
class RtlPowerThread(QtCore.QThread):
class RtlPowerBaseThread(QtCore.QThread):
"""Thread which runs rtl_power process"""
dataUpdated = QtCore.pyqtSignal(object)
rtlPowerStarted = QtCore.pyqtSignal()
@ -264,9 +301,6 @@ class RtlPowerThread(QtCore.QThread):
super().__init__(parent)
self.alive = False
self.process = None
self.params = {}
self.databuffer = {}
self.last_timestamp = ""
def stop(self):
"""Stop rtl_power thread"""
@ -274,8 +308,49 @@ class RtlPowerThread(QtCore.QThread):
self.alive = False
self.wait()
def setup(self, start_freq, stop_freq, bin_size, interval=10,
gain=-1, ppm=0, crop=0, single_shot=False):
def setup(self, start_freq, stop_freq, bin_size, interval=10.0, gain=-1,
ppm=0, crop=0, single_shot=False, sample_rate=2560000):
"""Setup rtl_power params"""
raise NotImplementedError
def process_start(self):
"""Start rtl_power process"""
raise NotImplementedError
def process_stop(self):
"""Terminate rtl_power process"""
if self.process:
try:
self.process.terminate()
except ProcessLookupError:
pass
self.process.wait()
self.process = None
def parse_output(self, line):
"""Parse one line of output from rtl_power"""
raise NotImplementedError
def run(self):
"""Rtl_power thread main loop"""
self.process_start()
self.alive = True
self.rtlPowerStarted.emit()
for line in self.process.stdout:
if not self.alive:
break
self.parse_output(line)
self.process_stop()
self.alive = False
self.rtlPowerStopped.emit()
class RtlPowerThread(RtlPowerBaseThread):
"""Thread which runs rtl_power process"""
def setup(self, start_freq, stop_freq, bin_size, interval=10.0, gain=-1,
ppm=0, crop=0, single_shot=False, sample_rate=2560000):
"""Setup rtl_power params"""
self.params = {
"start_freq": start_freq,
@ -287,16 +362,12 @@ class RtlPowerThread(QtCore.QThread):
"crop": crop,
"single_shot": single_shot
}
self.databuffer = {}
self.last_timestamp = ""
def process_stop(self):
"""Terminate rtl_power process"""
if self.process:
try:
self.process.terminate()
except ProcessLookupError:
pass
self.process.wait()
self.process = None
print("rtl_power params:")
pprint.pprint(self.params)
print()
def process_start(self):
"""Start rtl_power process"""
@ -321,7 +392,8 @@ class RtlPowerThread(QtCore.QThread):
universal_newlines=True)
def parse_output(self, line):
"""Parse one preprocessed line of output from rtl_power"""
"""Parse one line of output from rtl_power"""
line = [col.strip() for col in line.split(",")]
timestamp = " ".join(line[:2])
start_freq = int(line[2])
stop_freq = int(line[3])
@ -352,24 +424,131 @@ class RtlPowerThread(QtCore.QThread):
# if stop_freq == self.params["stop_freq"] * 1e6:
if stop_freq > (self.params["stop_freq"] * 1e6) - step:
self.dataUpdated.emit(self.databuffer)
return self.databuffer
def run(self):
"""Rtl_power thread main loop"""
self.process_start()
self.alive = True
self.rtlPowerStarted.emit()
reader = csv.reader(self.process.stdout, skipinitialspace=True,
delimiter=",", quoting=csv.QUOTE_NONE)
for line in reader:
if not self.alive:
break
self.parse_output(line)
class RtlPowerFftwThread(RtlPowerBaseThread):
"""Thread which runs rtl_power_fftw process"""
def setup(self, start_freq, stop_freq, bin_size, interval=10.0, gain=-1,
ppm=0, crop=0, single_shot=False, sample_rate=2560000):
"""Setup rtl_power_fftw 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.process_stop()
self.alive = False
self.rtlPowerStopped.emit()
self.params = {
"start_freq": start_freq,
"stop_freq": stop_freq,
"freq_range": freq_range,
"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("rtl_power_fftw 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 rtl_power_fftw process"""
if not self.process and self.params:
settings = QtCore.QSettings()
cmdline = [
str(settings.value("rtl_power_executable") or "rtl_power_fftw"),
"-f", "{}M:{}M".format(self.params["start_freq"],
self.params["stop_freq"]),
"-b", "{}".format(self.params["bins"]),
"-t", "{}".format(self.params["time"]),
"-r", "{}".format(self.params["sample_rate"]),
"-p", "{}".format(self.params["ppm"]),
]
if self.params["gain"] >= 0:
cmdline.extend(["-g", "{}".format(self.params["gain"])])
if self.params["overlap"] > 0:
cmdline.extend(["-o", "{}".format(self.params["overlap"])])
if not self.params["single_shot"]:
cmdline.append("-c")
self.process = subprocess.Popen(cmdline, stdout=subprocess.PIPE, stderr=subprocess.DEVNULL,
universal_newlines=True)
def parse_output(self, line):
"""Parse one line of output from rtl_power_fftw"""
line = line.strip()
# One empty line => new hop
if not line and self.prev_line:
self.hop += 1
self.databuffer["x"].extend(self.databuffer_hop["x"])
self.databuffer["y"].extend(self.databuffer_hop["y"])
self.databuffer_hop = {"timestamp": [], "x": [], "y": []}
# Two empty lines => new set
elif not line and not self.prev_line:
self.hop = 0
self.dataUpdated.emit(self.databuffer)
self.databuffer = {"timestamp": [], "x": [], "y": []}
# Get timestamp for new hop and set
elif line.startswith("# Acquisition start:"):
timestamp = line.split(":", 1)[1].strip()
if not self.databuffer_hop["timestamp"]:
self.databuffer_hop["timestamp"] = timestamp
if not self.databuffer["timestamp"]:
self.databuffer["timestamp"] = timestamp
# Skip other comments
elif line.startswith("#"):
pass
# Parse frequency and power
elif line[0].isdigit():
freq, power = line.split()
freq, power = float(freq), float(power)
start_freq, stop_freq = self.freqs_crop[self.hop]
# Apply cropping
if freq >= start_freq and freq <= stop_freq:
# Skip overlapping frequencies
if not self.databuffer["x"] or freq > self.databuffer["x"][-1]:
#print(" {:.3f} MHz".format(freq / 1e6))
self.databuffer_hop["x"].append(freq)
self.databuffer_hop["y"].append(power)
else:
#print(" Overlapping {:.3f} MHz".format(freq / 1e6))
pass
else:
#print(" Cropping {:.3f} MHz".format(freq / 1e6))
pass
self.prev_line = line
def main():

View File

@ -3,132 +3,132 @@
<context>
<name>QSpectrumAnalyzerMainWindow</name>
<message>
<location filename="ui_qspectrumanalyzer.py" line="219"/>
<location filename="ui_qspectrumanalyzer.py" line="217"/>
<source>QSpectrumAnalyzer</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="ui_qspectrumanalyzer.py" line="233"/>
<location filename="ui_qspectrumanalyzer.py" line="231"/>
<source>Settings</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="ui_qspectrumanalyzer.py" line="230"/>
<location filename="ui_qspectrumanalyzer.py" line="228"/>
<source> MHz</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="ui_qspectrumanalyzer.py" line="232"/>
<location filename="ui_qspectrumanalyzer.py" line="230"/>
<source> kHz</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="ui_qspectrumanalyzer.py" line="236"/>
<location filename="ui_qspectrumanalyzer.py" line="234"/>
<source>auto</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="ui_qspectrumanalyzer.py" line="226"/>
<location filename="ui_qspectrumanalyzer.py" line="224"/>
<source>Frequency</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="ui_qspectrumanalyzer.py" line="222"/>
<location filename="ui_qspectrumanalyzer.py" line="220"/>
<source>Controls</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="ui_qspectrumanalyzer.py" line="239"/>
<location filename="ui_qspectrumanalyzer.py" line="237"/>
<source>Levels</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qspectrumanalyzer.py" line="241"/>
<location filename="__main__.py" line="282"/>
<source>About</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="qspectrumanalyzer.py" line="241"/>
<location filename="__main__.py" line="282"/>
<source>QSpectrumAnalyzer {}</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="ui_qspectrumanalyzer.py" line="220"/>
<location filename="ui_qspectrumanalyzer.py" line="218"/>
<source>&amp;File</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="ui_qspectrumanalyzer.py" line="221"/>
<location filename="ui_qspectrumanalyzer.py" line="219"/>
<source>&amp;Help</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="ui_qspectrumanalyzer.py" line="223"/>
<location filename="ui_qspectrumanalyzer.py" line="221"/>
<source>&amp;Start</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="ui_qspectrumanalyzer.py" line="224"/>
<location filename="ui_qspectrumanalyzer.py" line="222"/>
<source>S&amp;top</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="ui_qspectrumanalyzer.py" line="225"/>
<location filename="ui_qspectrumanalyzer.py" line="223"/>
<source>Si&amp;ngle shot</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="ui_qspectrumanalyzer.py" line="240"/>
<location filename="ui_qspectrumanalyzer.py" line="238"/>
<source>&amp;Settings...</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="ui_qspectrumanalyzer.py" line="241"/>
<location filename="ui_qspectrumanalyzer.py" line="239"/>
<source>&amp;Quit</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="ui_qspectrumanalyzer.py" line="242"/>
<location filename="ui_qspectrumanalyzer.py" line="240"/>
<source>Ctrl+Q</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="ui_qspectrumanalyzer.py" line="243"/>
<location filename="ui_qspectrumanalyzer.py" line="241"/>
<source>&amp;About</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="ui_qspectrumanalyzer.py" line="234"/>
<location filename="ui_qspectrumanalyzer.py" line="232"/>
<source>Interval [s]:</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="ui_qspectrumanalyzer.py" line="235"/>
<location filename="ui_qspectrumanalyzer.py" line="233"/>
<source>Gain [dB]:</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="ui_qspectrumanalyzer.py" line="237"/>
<location filename="ui_qspectrumanalyzer.py" line="235"/>
<source>Corr. [ppm]:</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="ui_qspectrumanalyzer.py" line="238"/>
<location filename="ui_qspectrumanalyzer.py" line="236"/>
<source>Crop [%]:</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="ui_qspectrumanalyzer.py" line="227"/>
<location filename="ui_qspectrumanalyzer.py" line="225"/>
<source>Start:</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="ui_qspectrumanalyzer.py" line="229"/>
<location filename="ui_qspectrumanalyzer.py" line="227"/>
<source>Stop:</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="ui_qspectrumanalyzer.py" line="231"/>
<location filename="ui_qspectrumanalyzer.py" line="229"/>
<source>Bin size:</source>
<translation type="unfinished"></translation>
</message>
@ -136,29 +136,44 @@
<context>
<name>QSpectrumAnalyzerSettings</name>
<message>
<location filename="ui_qspectrumanalyzer_settings.py" line="73"/>
<location filename="ui_qspectrumanalyzer_settings.py" line="90"/>
<source>QSpectrumAnalyzer - Settings</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="ui_qspectrumanalyzer_settings.py" line="74"/>
<source>Rtl_power executable:</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="ui_qspectrumanalyzer_settings.py" line="75"/>
<location filename="ui_qspectrumanalyzer_settings.py" line="95"/>
<source>rtl_power</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="ui_qspectrumanalyzer_settings.py" line="76"/>
<location filename="ui_qspectrumanalyzer_settings.py" line="96"/>
<source>...</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="ui_qspectrumanalyzer_settings.py" line="77"/>
<location filename="ui_qspectrumanalyzer_settings.py" line="97"/>
<source>Waterfall history size:</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="ui_qspectrumanalyzer_settings.py" line="91"/>
<source>Backend:</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="ui_qspectrumanalyzer_settings.py" line="93"/>
<source>rtl_power_fftw</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="ui_qspectrumanalyzer_settings.py" line="94"/>
<source>Executable:</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="ui_qspectrumanalyzer_settings.py" line="98"/>
<source>Sample rate:</source>
<translation type="unfinished"></translation>
</message>
</context>
</TS>

View File

@ -7,7 +7,7 @@
<x>0</x>
<y>0</y>
<width>1100</width>
<height>680</height>
<height>731</height>
</rect>
</property>
<property name="windowTitle">
@ -52,7 +52,7 @@
<x>0</x>
<y>0</y>
<width>1100</width>
<height>27</height>
<height>30</height>
</rect>
</property>
<widget class="QMenu" name="menu_File">
@ -240,22 +240,6 @@
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QSpinBox" name="intervalSpinBox">
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>3600</number>
</property>
<property name="value">
<number>10</number>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QSpinBox" name="gainSpinBox">
<property name="alignment">
@ -315,6 +299,19 @@
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QDoubleSpinBox" name="intervalSpinBox">
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="maximum">
<double>999.000000000000000</double>
</property>
<property name="value">
<double>1.000000000000000</double>
</property>
</widget>
</item>
</layout>
</widget>
</item>

View File

@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>500</width>
<height>150</height>
<width>350</width>
<height>210</height>
</rect>
</property>
<property name="windowTitle">
@ -17,23 +17,44 @@
<item>
<layout class="QFormLayout" name="formLayout">
<item row="0" column="0">
<widget class="QLabel" name="label">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Rtl_power executable:</string>
<string>Backend:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QComboBox" name="backendComboBox">
<item>
<property name="text">
<string>rtl_power</string>
</property>
</item>
<item>
<property name="text">
<string>rtl_power_fftw</string>
</property>
</item>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Executable:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLineEdit" name="rtlPowerExecutableEdit">
<widget class="QLineEdit" name="executableEdit">
<property name="text">
<string>rtl_power</string>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="rtlPowerExecutableButton">
<widget class="QToolButton" name="executableButton">
<property name="text">
<string>...</string>
</property>
@ -41,14 +62,14 @@
</item>
</layout>
</item>
<item row="1" column="0">
<item row="2" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Waterfall history size:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<item row="2" column="1">
<widget class="QSpinBox" name="waterfallHistorySizeSpinBox">
<property name="minimum">
<number>1</number>
@ -61,6 +82,29 @@
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>Sample rate:</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QSpinBox" name="sampleRateSpinBox">
<property name="minimum">
<number>0</number>
</property>
<property name="maximum">
<number>25000000</number>
</property>
<property name="singleStep">
<number>10000</number>
</property>
<property name="value">
<number>2560000</number>
</property>
</widget>
</item>
</layout>
</item>
<item>
@ -89,8 +133,8 @@
</layout>
</widget>
<tabstops>
<tabstop>rtlPowerExecutableEdit</tabstop>
<tabstop>rtlPowerExecutableButton</tabstop>
<tabstop>executableEdit</tabstop>
<tabstop>executableButton</tabstop>
<tabstop>waterfallHistorySizeSpinBox</tabstop>
<tabstop>buttonBox</tabstop>
</tabstops>

View File

@ -2,8 +2,7 @@
# Form implementation generated from reading ui file 'qspectrumanalyzer/qspectrumanalyzer.ui'
#
# Created: Mon Mar 2 23:12:42 2015
# by: PyQt4 UI code generator 4.11.3
# Created by: PyQt4 UI code generator 4.11.4
#
# WARNING! All changes made in this file will be lost!
@ -26,7 +25,7 @@ except AttributeError:
class Ui_QSpectrumAnalyzerMainWindow(object):
def setupUi(self, QSpectrumAnalyzerMainWindow):
QSpectrumAnalyzerMainWindow.setObjectName(_fromUtf8("QSpectrumAnalyzerMainWindow"))
QSpectrumAnalyzerMainWindow.resize(1100, 680)
QSpectrumAnalyzerMainWindow.resize(1100, 731)
self.centralwidget = QtGui.QWidget(QSpectrumAnalyzerMainWindow)
self.centralwidget.setObjectName(_fromUtf8("centralwidget"))
self.horizontalLayout = QtGui.QHBoxLayout(self.centralwidget)
@ -56,7 +55,7 @@ class Ui_QSpectrumAnalyzerMainWindow(object):
self.horizontalLayout.addWidget(self.plotSplitter)
QSpectrumAnalyzerMainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtGui.QMenuBar(QSpectrumAnalyzerMainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 1100, 27))
self.menubar.setGeometry(QtCore.QRect(0, 0, 1100, 30))
self.menubar.setObjectName(_fromUtf8("menubar"))
self.menu_File = QtGui.QMenu(self.menubar)
self.menu_File.setObjectName(_fromUtf8("menu_File"))
@ -134,13 +133,6 @@ class Ui_QSpectrumAnalyzerMainWindow(object):
self.label_6 = QtGui.QLabel(self.groupBox_3)
self.label_6.setObjectName(_fromUtf8("label_6"))
self.gridLayout_2.addWidget(self.label_6, 0, 1, 1, 1)
self.intervalSpinBox = QtGui.QSpinBox(self.groupBox_3)
self.intervalSpinBox.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
self.intervalSpinBox.setMinimum(1)
self.intervalSpinBox.setMaximum(3600)
self.intervalSpinBox.setProperty("value", 10)
self.intervalSpinBox.setObjectName(_fromUtf8("intervalSpinBox"))
self.gridLayout_2.addWidget(self.intervalSpinBox, 1, 0, 1, 1)
self.gainSpinBox = QtGui.QSpinBox(self.groupBox_3)
self.gainSpinBox.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
self.gainSpinBox.setMinimum(-1)
@ -164,6 +156,12 @@ class Ui_QSpectrumAnalyzerMainWindow(object):
self.cropSpinBox.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
self.cropSpinBox.setObjectName(_fromUtf8("cropSpinBox"))
self.gridLayout_2.addWidget(self.cropSpinBox, 3, 1, 1, 1)
self.intervalSpinBox = QtGui.QDoubleSpinBox(self.groupBox_3)
self.intervalSpinBox.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
self.intervalSpinBox.setMaximum(999.0)
self.intervalSpinBox.setProperty("value", 1.0)
self.intervalSpinBox.setObjectName(_fromUtf8("intervalSpinBox"))
self.gridLayout_2.addWidget(self.intervalSpinBox, 1, 0, 1, 1)
self.verticalLayout_3.addWidget(self.groupBox_3)
self.groupBox_4 = QtGui.QGroupBox(self.dockWidgetContents)
self.groupBox_4.setObjectName(_fromUtf8("groupBox_4"))

View File

@ -2,8 +2,7 @@
# Form implementation generated from reading ui file 'qspectrumanalyzer/qspectrumanalyzer_settings.ui'
#
# Created: Mon Mar 2 23:12:42 2015
# by: PyQt4 UI code generator 4.11.3
# Created by: PyQt4 UI code generator 4.11.4
#
# WARNING! All changes made in this file will be lost!
@ -26,32 +25,50 @@ except AttributeError:
class Ui_QSpectrumAnalyzerSettings(object):
def setupUi(self, QSpectrumAnalyzerSettings):
QSpectrumAnalyzerSettings.setObjectName(_fromUtf8("QSpectrumAnalyzerSettings"))
QSpectrumAnalyzerSettings.resize(500, 150)
QSpectrumAnalyzerSettings.resize(350, 210)
self.verticalLayout = QtGui.QVBoxLayout(QSpectrumAnalyzerSettings)
self.verticalLayout.setObjectName(_fromUtf8("verticalLayout"))
self.formLayout = QtGui.QFormLayout()
self.formLayout.setObjectName(_fromUtf8("formLayout"))
self.label_3 = QtGui.QLabel(QSpectrumAnalyzerSettings)
self.label_3.setObjectName(_fromUtf8("label_3"))
self.formLayout.setWidget(0, QtGui.QFormLayout.LabelRole, self.label_3)
self.backendComboBox = QtGui.QComboBox(QSpectrumAnalyzerSettings)
self.backendComboBox.setObjectName(_fromUtf8("backendComboBox"))
self.backendComboBox.addItem(_fromUtf8(""))
self.backendComboBox.addItem(_fromUtf8(""))
self.formLayout.setWidget(0, QtGui.QFormLayout.FieldRole, self.backendComboBox)
self.label = QtGui.QLabel(QSpectrumAnalyzerSettings)
self.label.setObjectName(_fromUtf8("label"))
self.formLayout.setWidget(0, QtGui.QFormLayout.LabelRole, self.label)
self.formLayout.setWidget(1, QtGui.QFormLayout.LabelRole, self.label)
self.horizontalLayout = QtGui.QHBoxLayout()
self.horizontalLayout.setObjectName(_fromUtf8("horizontalLayout"))
self.rtlPowerExecutableEdit = QtGui.QLineEdit(QSpectrumAnalyzerSettings)
self.rtlPowerExecutableEdit.setObjectName(_fromUtf8("rtlPowerExecutableEdit"))
self.horizontalLayout.addWidget(self.rtlPowerExecutableEdit)
self.rtlPowerExecutableButton = QtGui.QToolButton(QSpectrumAnalyzerSettings)
self.rtlPowerExecutableButton.setObjectName(_fromUtf8("rtlPowerExecutableButton"))
self.horizontalLayout.addWidget(self.rtlPowerExecutableButton)
self.formLayout.setLayout(0, QtGui.QFormLayout.FieldRole, self.horizontalLayout)
self.executableEdit = QtGui.QLineEdit(QSpectrumAnalyzerSettings)
self.executableEdit.setObjectName(_fromUtf8("executableEdit"))
self.horizontalLayout.addWidget(self.executableEdit)
self.executableButton = QtGui.QToolButton(QSpectrumAnalyzerSettings)
self.executableButton.setObjectName(_fromUtf8("executableButton"))
self.horizontalLayout.addWidget(self.executableButton)
self.formLayout.setLayout(1, QtGui.QFormLayout.FieldRole, self.horizontalLayout)
self.label_2 = QtGui.QLabel(QSpectrumAnalyzerSettings)
self.label_2.setObjectName(_fromUtf8("label_2"))
self.formLayout.setWidget(1, QtGui.QFormLayout.LabelRole, self.label_2)
self.formLayout.setWidget(2, QtGui.QFormLayout.LabelRole, self.label_2)
self.waterfallHistorySizeSpinBox = QtGui.QSpinBox(QSpectrumAnalyzerSettings)
self.waterfallHistorySizeSpinBox.setMinimum(1)
self.waterfallHistorySizeSpinBox.setMaximum(10000000)
self.waterfallHistorySizeSpinBox.setProperty("value", 100)
self.waterfallHistorySizeSpinBox.setObjectName(_fromUtf8("waterfallHistorySizeSpinBox"))
self.formLayout.setWidget(1, QtGui.QFormLayout.FieldRole, self.waterfallHistorySizeSpinBox)
self.formLayout.setWidget(2, QtGui.QFormLayout.FieldRole, self.waterfallHistorySizeSpinBox)
self.label_4 = QtGui.QLabel(QSpectrumAnalyzerSettings)
self.label_4.setObjectName(_fromUtf8("label_4"))
self.formLayout.setWidget(3, QtGui.QFormLayout.LabelRole, self.label_4)
self.sampleRateSpinBox = QtGui.QSpinBox(QSpectrumAnalyzerSettings)
self.sampleRateSpinBox.setMinimum(0)
self.sampleRateSpinBox.setMaximum(25000000)
self.sampleRateSpinBox.setSingleStep(10000)
self.sampleRateSpinBox.setProperty("value", 2560000)
self.sampleRateSpinBox.setObjectName(_fromUtf8("sampleRateSpinBox"))
self.formLayout.setWidget(3, QtGui.QFormLayout.FieldRole, self.sampleRateSpinBox)
self.verticalLayout.addLayout(self.formLayout)
spacerItem = QtGui.QSpacerItem(20, 21, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding)
self.verticalLayout.addItem(spacerItem)
@ -65,14 +82,18 @@ class Ui_QSpectrumAnalyzerSettings(object):
QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL(_fromUtf8("accepted()")), QSpectrumAnalyzerSettings.accept)
QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL(_fromUtf8("rejected()")), QSpectrumAnalyzerSettings.reject)
QtCore.QMetaObject.connectSlotsByName(QSpectrumAnalyzerSettings)
QSpectrumAnalyzerSettings.setTabOrder(self.rtlPowerExecutableEdit, self.rtlPowerExecutableButton)
QSpectrumAnalyzerSettings.setTabOrder(self.rtlPowerExecutableButton, self.waterfallHistorySizeSpinBox)
QSpectrumAnalyzerSettings.setTabOrder(self.executableEdit, self.executableButton)
QSpectrumAnalyzerSettings.setTabOrder(self.executableButton, self.waterfallHistorySizeSpinBox)
QSpectrumAnalyzerSettings.setTabOrder(self.waterfallHistorySizeSpinBox, self.buttonBox)
def retranslateUi(self, QSpectrumAnalyzerSettings):
QSpectrumAnalyzerSettings.setWindowTitle(_translate("QSpectrumAnalyzerSettings", "QSpectrumAnalyzer - Settings", None))
self.label.setText(_translate("QSpectrumAnalyzerSettings", "Rtl_power executable:", None))
self.rtlPowerExecutableEdit.setText(_translate("QSpectrumAnalyzerSettings", "rtl_power", None))
self.rtlPowerExecutableButton.setText(_translate("QSpectrumAnalyzerSettings", "...", None))
self.label_3.setText(_translate("QSpectrumAnalyzerSettings", "Backend:", None))
self.backendComboBox.setItemText(0, _translate("QSpectrumAnalyzerSettings", "rtl_power", None))
self.backendComboBox.setItemText(1, _translate("QSpectrumAnalyzerSettings", "rtl_power_fftw", None))
self.label.setText(_translate("QSpectrumAnalyzerSettings", "Executable:", None))
self.executableEdit.setText(_translate("QSpectrumAnalyzerSettings", "rtl_power", None))
self.executableButton.setText(_translate("QSpectrumAnalyzerSettings", "...", None))
self.label_2.setText(_translate("QSpectrumAnalyzerSettings", "Waterfall history size:", None))
self.label_4.setText(_translate("QSpectrumAnalyzerSettings", "Sample rate:", None))

View File

@ -1 +1 @@
__version__ = "1.1.1"
__version__ = "1.2.0"