This commit is contained in:
jopohl
2016-04-23 22:05:58 +02:00
26 changed files with 670 additions and 400 deletions

View File

@@ -11,7 +11,7 @@ sudo python setup.py install
```
# Running from source
To run urh without installation, just run:
To execute urh without installation, just run:
```bash
cd bin
./urh

View File

@@ -35,8 +35,9 @@ class FFTSceneManager(SceneManager):
self.path_item.setPath(path)
try:
peak_path = path_creator.create_path(np.log10(self.peak), start, end)
self.peak_item.setPath(peak_path)
if len(self.peak) > 0:
peak_path = path_creator.create_path(np.log10(self.peak), start, end)
self.peak_item.setPath(peak_path)
except RuntimeWarning:
pass

View File

@@ -11,8 +11,7 @@ from PyQt5.QtWidgets import QMessageBox, QFrame, QAbstractItemView, QUndoStack,
from urh import constants
from urh.controller.OptionsController import OptionsController
from urh.controller.ProtocolLabelController import ProtocolLabelController
from urh.controller.ProtocolSniffDialogController import \
ProtocolSniffDialogController
from urh.controller.ProtocolSniffDialogController import ProtocolSniffDialogController
from urh.models.LabelValueTableModel import LabelValueTableModel
from urh.models.ProtocolLabelListModel import ProtocolLabelListModel
from urh.models.ProtocolTableModel import ProtocolTableModel
@@ -57,6 +56,7 @@ class CompareFrameController(QFrame):
self.decimal_point = clocale.decimalPoint()
self.__active_group_ids = [0]
self.selected_protocols = set()
self.protocol_model = ProtocolTableModel(self.proto_analyzer, self)
""":type: ProtocolTableModel"""
@@ -665,6 +665,7 @@ class CompareFrameController(QFrame):
active_group_ids = set()
selection = QItemSelection()
self.selected_protocols.clear()
for group, tree_items in self.proto_tree_model.protocol_tree_items.items():
for i, tree_item in enumerate(tree_items):
@@ -673,11 +674,9 @@ class CompareFrameController(QFrame):
#index = self.proto_tree_model.createIndex(i, 0, tree_item)
#selection.select(index, index)
active_group_ids.add(group)
self.selected_protocols.add(proto)
if active_group_ids == set(self.active_group_ids):
ignore_table_model_on_update = True
else:
ignore_table_model_on_update = False
if active_group_ids != set(self.active_group_ids):
self.active_group_ids = list(active_group_ids)
self.active_group_ids.sort()
@@ -698,7 +697,7 @@ class CompareFrameController(QFrame):
self.ui.treeViewProtocols.selectionModel().select(selection, QItemSelectionModel.ClearAndSelect)
self.ui.treeViewProtocols.blockSignals(False)
self.updateUI(ignore_table_model=ignore_table_model_on_update, resize_table=False)
self.updateUI(ignore_table_model=True, resize_table=False)
@pyqtSlot(int)
def handle_ref_index_changed(self, new_ref_index):

View File

@@ -172,7 +172,7 @@ class GeneratorTabController(QWidget):
prefix = "Amplitude"
elif mod_type == "PSK":
prefix = "Phase"
elif mod_type == "FSK":
elif mod_type in ("FSK", "GFSK"):
prefix = "Frequency"
else:
prefix = "Unknown Modulation Type (This should not happen...)"

View File

@@ -31,7 +31,6 @@ from urh.util.ProjectManager import ProjectManager
class MainController(QMainWindow):
resized = pyqtSignal()
def __init__(self, *args):
super().__init__(*args)
@@ -343,7 +342,6 @@ class MainController(QMainWindow):
sframe.refresh(draw_full_signal=True) # Hier wird das Protokoll ausgelesen
sframe.ui.gvSignal.autofit_view()
self.resized.connect(sframe.redraw_after_resize)
self.set_frame_numbers()
self.ui.progressBar.setValue(99)
QApplication.processEvents()
@@ -383,10 +381,6 @@ class MainController(QMainWindow):
self.set_frame_numbers()
self.refresh_main_menu()
def resizeEvent(self, event: QResizeEvent):
event.accept()
self.resized.emit()
def updateRecentActionList(self):
recentFilePaths = constants.SETTINGS.value("recentFiles")
recentFilePaths = [p for p in recentFilePaths if os.path.exists(p)] if recentFilePaths else []
@@ -435,7 +429,7 @@ class MainController(QMainWindow):
@pyqtSlot()
def show_about(self):
QMessageBox.about(self, self.tr("About"), self.tr("Version: {0}").format(version.VERSION))
QMessageBox.about(self, self.tr("About"), self.tr("<b><h2>Universal Radio Hacker</h2></b>Version: {0}<br />GitHub: <a href='https://github.com/jopohl/urh'>https://github.com/jopohl/urh</a><br /><br />Contributors:<i><ul><li>Johannes Pohl &lt;<a href='mailto:joahnnes.pohl90@gmail.com'>johannes.pohl90@gmail.com</a>&gt;</li><li>Andreas Noack &lt;<a href='mailto:andreas.noack@fh-stralsund.de'>andreas.noack@fh-stralsund.de</a>&gt;</li></ul></i>").format(version.VERSION))
@pyqtSlot(CompareFrameController, int, int, int, int)
def show_protocol_selection_in_interpretation(self, startblock, start, endblock, end):

View File

@@ -27,13 +27,8 @@ class ModulatorDialogController(QDialog):
self.modulators = modulators
self.set_ui_for_current_modulator()
self.ui.doubleSpinBoxCarrierFreq.setValue(self.current_modulator.carrier_freq_hz)
self.ui.doubleSpinBoxCarrierPhase.setValue(self.current_modulator.carrier_phase_deg)
self.ui.spinBoxBitLength.setValue(self.current_modulator.samples_per_bit)
self.ui.spinBoxSampleRate.setValue(self.current_modulator.sample_rate)
self.ui.spinBoxParameter0.setValue(self.current_modulator.param_for_zero)
self.ui.spinBoxParameter1.setValue(self.current_modulator.param_for_one)
self.ui.cbShowDataBitsOnly.setText(self.tr("Show Only Data Sequence\n"))
self.ui.cbShowDataBitsOnly.setEnabled(False)
self.protocol = None
@@ -45,7 +40,7 @@ class ModulatorDialogController(QDialog):
self.ui.chkBoxLockSIV.setDisabled(True)
self.ui.comboBoxModulationType.setCurrentIndex(self.current_modulator.modulation_type)
self.create_connects()
self.on_modulation_type_changed()
@@ -58,14 +53,25 @@ class ModulatorDialogController(QDialog):
mod = self.modulators[self.ui.comboBoxCustomModulations.currentIndex()]
return mod
def set_ui_for_current_modulator(self):
index = self.ui.comboBoxModulationType.findText("*("+self.current_modulator.modulation_type_str+")", Qt.MatchWildcard)
self.ui.comboBoxModulationType.setCurrentIndex(index)
self.ui.doubleSpinBoxCarrierFreq.setValue(self.current_modulator.carrier_freq_hz)
self.ui.doubleSpinBoxCarrierPhase.setValue(self.current_modulator.carrier_phase_deg)
self.ui.spinBoxBitLength.setValue(self.current_modulator.samples_per_bit)
self.ui.spinBoxSampleRate.setValue(self.current_modulator.sample_rate)
self.ui.spinBoxParameter0.setValue(self.current_modulator.param_for_zero)
self.ui.spinBoxParameter1.setValue(self.current_modulator.param_for_one)
def create_connects(self):
self.ui.doubleSpinBoxCarrierFreq.valueChanged.connect(self.on_carrier_freq_changed)
self.ui.doubleSpinBoxCarrierPhase.valueChanged.connect(self.on_carrier_phase_changed)
self.ui.spinBoxBitLength.valueChanged.connect(self.on_bit_len_changed)
self.ui.spinBoxSampleRate.valueChanged.connect(self.on_sample_rate_changed)
self.ui.doubleSpinBoxCarrierFreq.editingFinished.connect(self.on_carrier_freq_changed)
self.ui.doubleSpinBoxCarrierPhase.editingFinished.connect(self.on_carrier_phase_changed)
self.ui.spinBoxBitLength.editingFinished.connect(self.on_bit_len_changed)
self.ui.spinBoxSampleRate.editingFinished.connect(self.on_sample_rate_changed)
self.ui.linEdDataBits.textChanged.connect(self.on_data_bits_changed)
self.ui.spinBoxParameter0.valueChanged.connect(self.on_modulation_parameter_zero_changed)
self.ui.spinBoxParameter1.valueChanged.connect(self.on_modulation_parameter_one_changed)
self.ui.spinBoxParameter0.editingFinished.connect(self.on_modulation_parameter_zero_changed)
self.ui.spinBoxParameter1.editingFinished.connect(self.on_modulation_parameter_one_changed)
self.ui.comboBoxModulationType.currentIndexChanged.connect(self.on_modulation_type_changed)
self.ui.gVOriginalSignal.zoomed.connect(self.on_orig_signal_zoomed)
self.ui.cbShowDataBitsOnly.stateChanged.connect(self.on_show_data_bits_only_changed)
@@ -80,6 +86,8 @@ class ModulatorDialogController(QDialog):
self.ui.gVData.zoomed.connect(self.on_carrier_data_modulated_zoomed)
self.ui.gVModulated.sel_area_width_changed.connect(self.on_modulated_selection_changed)
self.ui.gVOriginalSignal.sel_area_width_changed.connect(self.on_original_selection_changed)
self.ui.spinBoxGaussBT.editingFinished.connect(self.on_gauss_bt_edited)
self.ui.spinBoxGaussFilterWidth.editingFinished.connect(self.on_gaus_filter_wdith_edited)
self.ui.chkBoxLockSIV.stateChanged.connect(self.on_lock_siv_changed)
self.ui.btnRestoreBits.clicked.connect(self.on_btn_restore_bits_clicked)
@@ -166,6 +174,11 @@ class ModulatorDialogController(QDialog):
else:
self.ui.btnRestoreBits.setEnabled(True)
def __cur_selected_mod_type(self):
s = self.ui.comboBoxModulationType.currentText()
return s[s.rindex("(")+1:s.rindex(")")]
@pyqtSlot()
def on_sample_rate_changed(self):
if int(self.ui.spinBoxSampleRate.value()) > 0:
@@ -183,15 +196,27 @@ class ModulatorDialogController(QDialog):
self.current_modulator.param_for_one = self.ui.spinBoxParameter1.value()
self.draw_modulated()
@pyqtSlot()
def on_gauss_bt_edited(self):
self.current_modulator.gauss_bt = self.ui.spinBoxGaussBT.value()
self.draw_modulated()
@pyqtSlot()
def on_gaus_filter_wdith_edited(self):
self.current_modulator.gauss_filter_width = self.ui.spinBoxGaussFilterWidth.value()
self.draw_modulated()
@pyqtSlot()
def on_modulation_type_changed(self):
if self.current_modulator.modulation_type == self.ui.comboBoxModulationType.currentIndex():
if self.current_modulator.modulation_type_str == self.__cur_selected_mod_type():
write_standard_parameters = False
else:
self.current_modulator.modulation_type = self.ui.comboBoxModulationType.currentIndex()
self.current_modulator.modulation_type_str = self.__cur_selected_mod_type()
write_standard_parameters = True
if self.ui.comboBoxModulationType.currentIndex() == 0:
self.__set_gauss_ui_visibility(self.__cur_selected_mod_type() == "GFSK")
if self.__cur_selected_mod_type() == "ASK":
self.ui.lParameterfor0.setText(self.tr("Amplitude for 0:"))
self.ui.lParameterfor1.setText(self.tr("Amplitude for 1:"))
self.ui.spinBoxParameter0.auto_suffix = False
@@ -211,7 +236,7 @@ class ModulatorDialogController(QDialog):
self.ui.spinBoxParameter0.setValue(self.current_modulator.param_for_zero)
self.ui.spinBoxParameter1.setValue(self.current_modulator.param_for_one)
elif self.ui.comboBoxModulationType.currentIndex() == 1:
elif self.__cur_selected_mod_type() in ("FSK", "GFSK"):
self.ui.spinBoxParameter0.auto_suffix = True
self.ui.spinBoxParameter1.auto_suffix = True
self.ui.lParameterfor0.setText(self.tr("Frequency for 0:"))
@@ -219,18 +244,16 @@ class ModulatorDialogController(QDialog):
self.ui.spinBoxParameter0.setMaximum(1e12)
self.ui.spinBoxParameter0.setMinimum(-1e12)
self.ui.spinBoxParameter0.setDecimals(4)
self.ui.spinBoxParameter0.setSuffix("")
self.ui.spinBoxParameter1.setMaximum(1e12)
self.ui.spinBoxParameter1.setMinimum(-1e12)
self.ui.spinBoxParameter1.setDecimals(4)
self.ui.spinBoxParameter1.setSuffix("")
if write_standard_parameters:
self.autodetect_fsk_freqs()
else:
self.ui.spinBoxParameter0.setValue(self.current_modulator.param_for_zero)
self.ui.spinBoxParameter1.setValue(self.current_modulator.param_for_one)
elif self.ui.comboBoxModulationType.currentIndex() == 2:
elif self.__cur_selected_mod_type() == "PSK":
self.ui.spinBoxParameter0.auto_suffix = False
self.ui.spinBoxParameter1.auto_suffix = False
self.ui.lParameterfor0.setText(self.tr("Phase (degree) for 0:"))
@@ -250,7 +273,8 @@ class ModulatorDialogController(QDialog):
self.ui.spinBoxParameter0.setValue(self.current_modulator.param_for_zero)
self.ui.spinBoxParameter1.setValue(self.current_modulator.param_for_one)
self.draw_modulated()
self.ui.spinBoxParameter0.editingFinished.emit()
self.ui.spinBoxParameter1.editingFinished.emit()
def resizeEvent(self, event: QResizeEvent):
@@ -327,6 +351,7 @@ class ModulatorDialogController(QDialog):
@pyqtSlot()
def on_custom_modulation_index_changed(self):
self.set_ui_for_current_modulator()
self.draw_carrier()
self.draw_data_bits()
self.draw_modulated()
@@ -472,7 +497,7 @@ class ModulatorDialogController(QDialog):
self.autodetect_fsk_freqs()
def autodetect_fsk_freqs(self):
if self.ui.comboBoxModulationType.currentIndex() != 1:
if self.__cur_selected_mod_type() not in ("FSK", "GFSK"):
return
try:
@@ -530,3 +555,13 @@ class ModulatorDialogController(QDialog):
@pyqtSlot(int)
def on_original_selection_changed(self, new_width: int):
self.ui.lOriginalSignalSamplesSelected.setText(str(abs(new_width)))
def __set_gauss_ui_visibility(self, show:bool):
self.ui.lGaussBT.setVisible(show)
self.ui.lGaussWidth.setVisible(show)
self.ui.spinBoxGaussBT.setVisible(show)
self.ui.spinBoxGaussFilterWidth.setVisible(show)
self.ui.spinBoxGaussFilterWidth.setValue(self.current_modulator.gauss_filter_width)
self.ui.spinBoxGaussBT.setValue(self.current_modulator.gauss_bt)

View File

@@ -1,6 +1,6 @@
import numpy
from PyQt5.QtCore import Qt, pyqtSlot
from PyQt5.QtWidgets import QDialog, QApplication
from PyQt5.QtCore import Qt, pyqtSlot, QModelIndex
from PyQt5.QtWidgets import QDialog, QApplication, QInputDialog
from urh import constants
from urh.models.PLabelTableModel import PLabelTableModel
@@ -30,9 +30,6 @@ class ProtocolLabelController(QDialog):
self.ui.tblViewProtoLabels.setItemDelegateForColumn(1, SpinBoxDelegate(1, maxval, self))
self.ui.tblViewProtoLabels.setItemDelegateForColumn(2, SpinBoxDelegate(1, maxval, self))
self.ui.tblViewProtoLabels.setItemDelegateForColumn(3, CheckBoxDelegate(self))
self.ui.tblViewProtoLabels.setItemDelegateForColumn(4, SpinBoxDelegate(offset+1,
offset+proto_group.num_blocks,
self))
self.ui.tblViewProtoLabels.setItemDelegateForColumn(5,
ComboBoxDelegate([""] * len(constants.LABEL_COLORS), True,
@@ -57,6 +54,7 @@ class ProtocolLabelController(QDialog):
self.ui.btnConfirm.clicked.connect(self.confirm)
self.ui.cbProtoView.currentIndexChanged.connect(self.set_view_index)
self.model.restrictive_changed.connect(self.handle_restrictive_changed)
self.ui.tblViewProtoLabels.clicked.connect(self.on_table_clicked)
@pyqtSlot()
def confirm(self):
@@ -67,21 +65,30 @@ class ProtocolLabelController(QDialog):
self.ui.tblViewProtoLabels.openPersistentEditor(self.model.index(row, 2))
self.ui.tblViewProtoLabels.openPersistentEditor(self.model.index(row, 3))
if self.model.protocol_labels[row].restrictive:
self.ui.tblViewProtoLabels.openPersistentEditor(self.model.index(row, 4))
self.ui.tblViewProtoLabels.openPersistentEditor(self.model.index(row, 5))
self.ui.tblViewProtoLabels.openPersistentEditor(self.model.index(row, 6))
self.ui.tblViewProtoLabels.openPersistentEditor(self.model.index(row, 7))
@pyqtSlot(int, bool)
def handle_restrictive_changed(self, row: int, restrictive: bool):
if restrictive:
self.ui.tblViewProtoLabels.openPersistentEditor(self.model.index(row, 4))
else:
self.ui.tblViewProtoLabels.closePersistentEditor(self.model.index(row, 4))
self.model.update()
@pyqtSlot(int)
def set_view_index(self, ind):
self.model.proto_view = ind
self.model.update()
self.model.update()
@pyqtSlot(QModelIndex)
def on_table_clicked(self, index: QModelIndex):
if not index.isValid():
return
i = index.row()
lbl = self.model.protocol_labels[i]
j = index.column()
if j == 4 and lbl.restrictive:
seqs, indexes = self.model.get_protocol_sequences(lbl.start, lbl.end)
item, ok = QInputDialog.getItem(self, "Choose matching pattern", "Pattern", seqs)
if ok and item:
self.model.set_refblock(lbl, indexes[seqs.index(item)])
self.model.update()

View File

@@ -158,6 +158,7 @@ class SendRecvDialogController(QDialog):
self.device.frequency = self.ui.spinBoxFreq.value()
if self.mode == Mode.spectrum:
self.scene_creator.scene.center_freq = self.ui.spinBoxFreq.value()
self.scene_creator.clear_path()
@pyqtSlot()
def on_bw_changed(self):

View File

@@ -1021,13 +1021,6 @@ class SignalFrameController(QFrame):
self.ui.btnSaveSignal.hide()
self.ui.lineEditSignalName.setFont(font)
def redraw_after_resize(self):
if self.ui.gvSignal.view_rect().width() > self.ui.gvSignal.sceneRect().width():
x_factor = self.ui.gvSignal.width() / self.ui.gvSignal.sceneRect().width()
self.ui.gvSignal.scale(x_factor / self.ui.gvSignal.transform().m11(), 1)
self.ui.gvSignal.autofit_view()
def contextMenuEvent(self, event: QContextMenuEvent):
if self.signal is None:
return

View File

@@ -148,7 +148,6 @@ class SignalTabController(QWidget):
sig_frame.files_dropped.connect(self.handle_files_dropped)
sig_frame.apply_to_all_clicked.connect(self.handle_apply_to_all_clicked)
sig_frame.sort_action_clicked.connect(self.sort_frames_by_name)
self.splitter.splitterMoved.connect(sig_frame.redraw_after_resize)
if prev_signal_frame is not None:

View File

@@ -7,7 +7,7 @@ from urh.signalprocessing.ProtocolGroup import ProtocolGroup
class PLabelTableModel(QAbstractTableModel):
header_labels = ["Name", "Start", "End", 'Match exactly',
"Matching Block", 'Color', 'Apply decoding', 'Delete']
"Matching sequence", 'Color', 'Apply decoding', 'Delete']
restrictive_changed = pyqtSignal(int, bool)
label_removed = pyqtSignal(ProtocolLabel)
@@ -56,7 +56,15 @@ class PLabelTableModel(QAbstractTableModel):
return lbl.restrictive
elif j == 4:
if lbl.restrictive:
return lbl.refblock + self.offset + 1
start = int(self.proto_group.convert_index(lbl.start, 0, self.proto_view, True)[0])
end = int(self.proto_group.convert_index(lbl.end, 0, self.proto_view, True)[1])
block = self.proto_group.blocks[lbl.refblock]
if self.proto_view == 0:
return block.decoded_bits_str[start:end]
elif self.proto_view == 1:
return block.decoded_hex_str[start:end]
else:
return block.decoded_ascii_str[start:end]
else:
return "-"
elif j == 5:
@@ -99,9 +107,8 @@ class PLabelTableModel(QAbstractTableModel):
self.restrictive_changed.emit(i, value)
lbl.find_block_numbers(proto)
elif j == 4:
lbl.refblock = int(value) - self.offset - 1
lbl.reference_bits = proto[lbl.refblock][lbl.start:lbl.end]
lbl.find_block_numbers(proto)
# Pass Reference bits via seperate dialog
pass
elif j == 5:
lbl.color_index = value
elif j == 6:
@@ -111,6 +118,13 @@ class PLabelTableModel(QAbstractTableModel):
return True
def set_refblock(self, lbl: ProtocolLabel, refblock: int):
proto = self.proto_group.decoded_bits_str
lbl.refblock = int(refblock) - self.offset
lbl.reference_bits = proto[lbl.refblock][lbl.start:lbl.end]
lbl.find_block_numbers(proto)
def flags(self, index):
if not index.isValid():
return Qt.NoItemFlags
@@ -121,11 +135,35 @@ class PLabelTableModel(QAbstractTableModel):
return Qt.NoItemFlags
if index.column() == 4 and not lbl.restrictive:
return Qt.ItemIsSelectable
return Qt.NoItemFlags
elif index.column() == 4 and lbl.restrictive:
return Qt.ItemIsSelectable | Qt.ItemIsEnabled
return Qt.ItemIsEditable | Qt.ItemIsEnabled
def remove_label(self, label):
self.proto_group.remove_label(label)
self.update()
self.label_removed.emit(label)
self.label_removed.emit(label)
def get_protocol_sequences(self, start: int, end: int):
sequences = []
indexes = []
start = int(self.proto_group.convert_index(start, 0, self.proto_view, True)[0])
end = int(self.proto_group.convert_index(end, 0, self.proto_view, True)[0])
for i, block in enumerate(self.proto_group.blocks):
if self.proto_view == 0:
data = block.decoded_bits_str[start:end]
elif self.proto_view == 1:
data = block.decoded_hex_str[start:end]
else:
data = block.decoded_ascii_str[start:end]
if len(data) == end - start and data not in sequences:
sequences.append(data)
indexes.append(i) # For setting refblock later
return sequences, indexes

View File

@@ -121,11 +121,15 @@ class ProtocolTreeModel(QAbstractItemModel):
return QIcon.fromTheme("folder")
elif role == Qt.CheckStateRole:
return item.show
elif role == Qt.FontRole and item.is_group and\
self.rootItem.index_of(item) in self.controller.active_group_ids:
font = QFont()
font.setBold(True)
return font
elif role == Qt.FontRole:
if item.is_group and self.rootItem.index_of(item) in self.controller.active_group_ids:
font = QFont()
font.setBold(True)
return font
elif item.protocol in self.controller.selected_protocols:
font = QFont()
font.setBold(True)
return font
elif role == Qt.TextColorRole and item.protocol == self.reference_protocol:
return constants.SELECTED_ROW_COLOR
elif role == Qt.ToolTipRole:

View File

@@ -120,14 +120,13 @@ class TableModel(QAbstractTableModel):
offset = 0
for group in self.controller.groups:
if group in self.controller.active_groups:
for lbl in group.labels:
bg_color = label_colors[lbl.color_index]
for i in lbl.block_numbers:
start, end = group.get_label_range(lbl, self.proto_view, self.decode)
for j in range(start, end):
self.background_colors[i+offset, j] = bg_color
self.tooltips[i+offset, j] = lbl.name
for lbl in group.labels:
bg_color = label_colors[lbl.color_index]
for i in lbl.block_numbers:
start, end = group.get_label_range(lbl, self.proto_view, self.decode)
for j in range(start, end):
self.background_colors[i+offset, j] = bg_color
self.tooltips[i+offset, j] = lbl.name
offset += group.num_blocks
def refresh_fonts(self):

View File

@@ -10,13 +10,13 @@ from urh.cythonext import path_creator
from urh.cythonext.signalFunctions import Symbol
from urh.ui.ZoomableScene import ZoomableScene
class Modulator(object):
"""
This class can modulate bits to a carrier.
Very useful in generation phase.
"""
MODULATION_TYPES = ["ASK", "FSK", "PSK"]
MODULATION_TYPES = ["ASK", "FSK", "PSK", "GFSK"]
def __init__(self, name: str):
@@ -30,6 +30,9 @@ class Modulator(object):
self.modulation_type = 0
self.name = name
self.gauss_bt = 0.5 # bt product for gaussian filter (GFSK)
self.gauss_filter_width = 1 # filter width for gaussian filter (GFSK)
self.param_for_zero = 0 # Freq, Amplitude (0..100%) or Phase (0..360)
self.param_for_one = 100 # Freq, Amplitude (0..100%) or Phase (0..360)
@@ -85,12 +88,18 @@ class Modulator(object):
def modulation_type_str(self):
return self.MODULATION_TYPES[self.modulation_type]
@modulation_type_str.setter
def modulation_type_str(self, val: str):
val = val.upper()
if val in self.MODULATION_TYPES:
self.modulation_type = self.MODULATION_TYPES.index(val)
@property
def param_for_zero_str(self):
mod = self.MODULATION_TYPES[self.modulation_type]
if mod == "ASK":
return str(self.param_for_zero) + "%"
elif mod == "FSK":
elif mod == "FSK" or mod == "GFSK":
return self.get_value_with_suffix(self.param_for_zero) + "Hz"
elif mod == "PSK":
return str(self.param_for_zero) + "°"
@@ -100,7 +109,7 @@ class Modulator(object):
mod = self.MODULATION_TYPES[self.modulation_type]
if mod == "ASK":
return str(self.param_for_one) + "%"
elif mod == "FSK":
elif mod == "FSK" or mod == "GFSK":
return self.get_value_with_suffix(self.param_for_one) + "Hz"
elif mod == "PSK":
return str(self.param_for_one) + "°"
@@ -161,19 +170,57 @@ class Modulator(object):
log_bit = bit
samples_per_bit = self.samples_per_bit
param = self.param_for_one if log_bit else self.param_for_zero
if mod_type == "FSK" or mod_type == "GFSK":
param = 1 if log_bit else -1
else:
param = self.param_for_one if log_bit else self.param_for_zero
paramvector[sample_pos:sample_pos + samples_per_bit] = np.full(samples_per_bit, param, dtype=np.float64)
sample_pos += samples_per_bit
t = np.arange(start, start + total_samples - pause) / self.sample_rate
a = paramvector / 100 if mod_type == "ASK" else self.carrier_amplitude
phi = paramvector * (np.pi / 180) if mod_type == "PSK" else self.carrier_phase_deg * (np.pi / 180)
f = paramvector if mod_type == "FSK" else self.carrier_freq_hz
if mod_type == "FSK" or mod_type == "GFSK":
fmid = (self.param_for_one + self.param_for_zero)/2
dist = abs(fmid - self.param_for_one)
if mod_type == "GFSK":
gfir = self.gauss_fir(bt=self.gauss_bt, filter_width=self.gauss_filter_width)
if len(paramvector) >= len(gfir):
paramvector = np.convolve(paramvector, gfir, mode="same")
else:
# Prevent dimension crash later, because gaussian finite impulse response is longer then paramvector
paramvector = np.convolve(gfir, paramvector, mode="same")[:len(paramvector)]
f = fmid + dist * paramvector
# sin(2*pi*f_1*t_1 + phi_1) = sin(2*pi*f_2*t_1 + phi_2) <=> phi_2 = 2*pi*t_1*(f_1 - f_2) + phi_1
phi = np.empty(len(f))
phi[0] = self.carrier_phase_deg
for i in range(0, len(phi) - 1):
phi[i+1] = 2 * np.pi * t[i] * (f[i]-f[i+1]) + phi[i] # Correct the phase to prevent spiky jumps
else:
f = self.carrier_freq_hz
self.modulated_samples.imag[:total_samples - pause] = a * np.sin(2 * np.pi * f * t + phi)
self.modulated_samples.real[:total_samples - pause] = a * np.cos(2 * np.pi * f * t + phi)
def gauss_fir(self, bt=0.5, filter_width=1):
"""
:param bt: normalized 3-dB bandwidth-symbol time product
:param span: filter span in symbols
:return:
"""
# http://onlinelibrary.wiley.com/doi/10.1002/9780470041956.app2/pdf
k = np.arange(-int(filter_width * self.samples_per_bit), int(filter_width * self.samples_per_bit)+1)
ts = self.samples_per_bit / self.sample_rate # symbol time
#a = np.sqrt(np.log(2)/2)*(ts/bt)
#B = a / np.sqrt(np.log(2)/2) # filter bandwidth
h = np.sqrt((2*np.pi)/(np.log(2))) * bt/ts * np.exp(-(((np.sqrt(2)*np.pi)/np.sqrt(np.log(2))*bt*k/self.samples_per_bit)**2))
return h / h.sum()
@staticmethod
def get_value_with_suffix(value):
if abs(value) >= 10 ** 9:

View File

@@ -94,7 +94,7 @@ class ProtocolAnalyzerContainer(ProtocolAnalyzer):
l.refblock += proto_analyzer.num_blocks
for p in proto_labels:
self.__group.add_label(p)
self.__group.add_label(p, decode=False)
for block in self.blocks:
block.fuzz_labels[index:0] = [p for p in proto_labels if p not in block.fuzz_labels]
@@ -114,7 +114,7 @@ class ProtocolAnalyzerContainer(ProtocolAnalyzer):
self.qt_signals.line_duplicated.emit()
def refresh_protolabel_blocks(self):
self.__group.refresh_labels()
self.__group.refresh_labels(decode=False)
def fuzz_successive(self):
"""

View File

@@ -110,17 +110,20 @@ class ProtocolGroup(object):
except IndexError:
return None
def refresh_label(self, lbl: ProtocolLabel):
def refresh_label(self, lbl: ProtocolLabel, decode=True):
if lbl not in self.labels:
print("Label {0} is not in Group {1}".format(lbl.name, self.name), file=sys.stderr)
return
lbl.find_block_numbers(self.decoded_bits_str)
if decode:
lbl.find_block_numbers(self.decoded_bits_str)
else:
lbl.find_block_numbers(self.plain_bits_str)
def refresh_labels(self):
def refresh_labels(self, decode=True):
for lbl in self.labels:
#lbl.signals.apply_decoding_changed.emit(lbl) # Update DnD Labels for new blocks
self.refresh_label(lbl)
self.refresh_label(lbl, decode)
def convert_index(self, index: int, from_view: int, to_view: int, decoded: bool, block_indx=-1) -> tuple:
"""
@@ -224,12 +227,12 @@ class ProtocolGroup(object):
return proto_label
def add_label(self, lbl: ProtocolLabel, refresh=True):
def add_label(self, lbl: ProtocolLabel, refresh=True, decode=True):
if lbl not in self.labels:
lbl.signals.apply_decoding_changed.connect(self.handle_plabel_apply_decoding_changed)
self.labels.append(lbl)
if refresh:
self.refresh_label(lbl)
self.refresh_label(lbl, decode=decode)
self.labels.sort()
def handle_plabel_apply_decoding_changed(self, lbl: ProtocolLabel):

View File

@@ -46,13 +46,20 @@ class GridScene(ZoomableScene):
painter.scale(scale_x, scale_y)
font_height = self.font_metrics.height()
counter = -1 # Counter for Label for every second line
for x in x_range:
freq = self.frequencies[x]
counter += 1
if freq != 0 and (counter % 2 != 0): # Label for every second line
continue
if freq != 0:
prefix = "+" if freq > 0 else ""
value = prefix+Formatter.big_value_with_suffix(freq)
value = prefix+Formatter.big_value_with_suffix(freq, 2)
else:
counter = 0
value = Formatter.big_value_with_suffix(self.center_freq)
font_width = self.font_metrics.width(value)
painter.drawText(x / scale_x - font_width / 2,

View File

@@ -22,12 +22,10 @@ class KillerDoubleSpinBox(QDoubleSpinBox):
if self.suffix() != text[-1]:
if self.auto_suffix:
self.setSuffix(text[-1])
self.on_text_edited()
else:
if self.suffix() != "":
if self.auto_suffix:
self.setSuffix("")
self.on_text_edited()
def on_text_edited(self):
self.lineEdit().setText(self.lineEdit().text().upper())
@@ -39,7 +37,6 @@ class KillerDoubleSpinBox(QDoubleSpinBox):
def setUnit(self):
value = abs(self.value())
if 10 ** 9 <= value <= 10 ** 11:
if self.suffix() != "G" and self.auto_suffix:
self.setSuffix("G")
@@ -85,6 +82,6 @@ class KillerDoubleSpinBox(QDoubleSpinBox):
return super().valueFromText(text)
def validate(self, inpt: str, pos: int):
rx = QRegExp("^(-?[0-9]+)[.]?[0-9]*[kKmMgG]?$")
rx = QRegExp("^(-?[0-9]+)[.]?[0-9]*[kKmMgG"+str(self.suffix())+"]?$")
result = QValidator.Acceptable if rx.exactMatch(inpt.replace(",", ".")) else QValidator.Invalid
return result, inpt, pos

View File

@@ -223,6 +223,7 @@ class EpicGraphicView(SelectableGraphicView):
self.resetTransform()
x_factor = self.width() / self.sceneRect().width()
self.scale(x_factor, y_factor)
self.centerOn(0, self.y_center)
def zoom_to_selection(self, start: int, end: int):
if start == end:
@@ -249,4 +250,12 @@ class EpicGraphicView(SelectableGraphicView):
self.zoom_all_signals(0.9)
def clear_selection(self):
self.set_selection_area(0, 0)
self.set_selection_area(0, 0)
def resizeEvent(self, event):
if self.view_rect().width() > self.sceneRect().width():
x_factor = self.width() / self.sceneRect().width()
self.scale(x_factor / self.transform().m11(), 1)
self.autofit_view()

View File

@@ -42,13 +42,10 @@ class LiveGraphicView(QGraphicsView):
self.zoomed.emit(zoom_factor)
def mouseMoveEvent(self, event: QMouseEvent):
try:
if isinstance(self.scene(), GridScene):
freq = self.scene().get_freq_for_pos(int(self.mapToScene(event.pos()).x()))
if freq is not None:
QToolTip.showText(self.mapToGlobal(event.pos()), Formatter.big_value_with_suffix(freq), None, QRect(), 10000)
except TypeError:
pass # Frequency not ready yet
if isinstance(self.scene(), GridScene):
freq = self.scene().get_freq_for_pos(int(self.mapToScene(event.pos()).x()))
if freq is not None:
QToolTip.showText(self.mapToGlobal(event.pos()), "Tune to:"+Formatter.big_value_with_suffix(freq), None, QRect(), 10000)
def mousePressEvent(self, event: QMouseEvent):
if isinstance(self.scene(), GridScene):

View File

@@ -22,12 +22,13 @@ class Formatter():
return locale.format_string("%.2f " + suffix, value) + "s"
@staticmethod
def big_value_with_suffix(value: float) -> str:
def big_value_with_suffix(value: float, decimals=3) -> str:
fmt_str = "%.{0:d}f".format(decimals)
if abs(value) >= 1e9:
return locale.format_string("%.3fG", value / 1e9)
return locale.format_string(fmt_str+"G", value / 1e9)
elif abs(value) >= 1e6:
return locale.format_string("%.3fM", value / 1e6)
return locale.format_string(fmt_str+"M", value / 1e6)
elif abs(value) >= 1e3:
return locale.format_string("%.3fK", value / 1e3)
return locale.format_string(fmt_str+"K", value / 1e3)
else:
return locale.format_string("%.3f", value)
return locale.format_string(fmt_str, value)

60
tests/GFSK.py Normal file
View File

@@ -0,0 +1,60 @@
import copy
import unittest
import matplotlib.pyplot as plt
import numpy as np
from urh.signalprocessing.Modulator import Modulator
from urh.signalprocessing.ProtocolAnalyzer import ProtocolAnalyzer
from urh.signalprocessing.Signal import Signal
from urh.cythonext import signalFunctions
class GFSK(unittest.TestCase):
def test_plot(self):
modulator = Modulator("gfsk")
modulator.modulation_type_str = "GFSK"
modulator.samples_per_bit = 100
modulator.sample_rate = 1e6
modulator.param_for_one = 20e3
modulator.param_for_zero = 10e3
modulator.carrier_freq_hz = 15e3
modulator.carrier_phase_deg = 90
modulator.modulate([True, False, True, False, False], 77)
data = copy.deepcopy(modulator.modulated_samples)
modulator.modulate([False, True, True, True, True, False, True], 100, start=len(data))
data = np.concatenate((data, modulator.modulated_samples))
plt.subplot(2, 1, 1)
axes = plt.gca()
axes.set_ylim([-2,2])
plt.plot(data.real)
plt.title("Modulated Wave")
plt.subplot(2, 1, 2)
qad = signalFunctions.afp_demod(np.ascontiguousarray(data), 0, 1)
plt.plot(qad)
plt.title("Quad Demod")
plt.show()
def test_gfsk(self):
modulator = Modulator("gfsk")
modulator.modulation_type_str = "FSK"
modulator.samples_per_bit = 100
modulator.sample_rate = 1e6
modulator.param_for_one = 20e3
modulator.param_for_zero = -10e3
modulator.modulate([True, False, False, True, False], 9437)
s = modulator.modulated_samples
modulator.modulate([True, False, True], 9845) #, start=len(s))
s = np.concatenate((s, modulator.modulated_samples))
modulator.modulate([True, False, True, False], 8457) #, start=len(s))
s = np.concatenate((s, modulator.modulated_samples))
s.tofile("/tmp/test.complex")
pa = ProtocolAnalyzer(Signal("/tmp/test.complex", "test", modulation="FSK"))
pa.get_protocol_from_signal()

View File

@@ -1,26 +0,0 @@
import os
import unittest
from urh import constants
from urh.signalprocessing.ProtocolAnalyzer import ProtocolAnalyzer
from urh.signalprocessing.ProtocolBlock import ProtocolBlock
from urh.signalprocessing.encoding import encoding
class TestLoadProtocolFile(unittest.TestCase):
# Testmethode muss immer mit Präfix test_* starten
def test_proto_block_from_str(self):
bits = "1011AB11"
pb = ProtocolBlock.from_plain_bits_str(bits)
self.assertEqual(bits, pb.plain_bits_str)
# def test_proto_analyzer_from_file(self):
# # TODO Compareframe methode nutzen, auch testen ob Labels da sind
# self.assertTrue(os.path.isfile("./data/protocol.txt"))
# pa, view_type, encoding = ProtocolAnalyzer.from_file("./data/protocol.txt")
# self.assertEqual(pa.blocks[0].plain_bits_str,
# "10101010110100111011010111011101110111011100110001011101010001011101110110110101101")
if __name__ == "__main__":
unittest.main()

View File

@@ -342,180 +342,6 @@
</property>
</widget>
</item>
<item row="6" column="0">
<layout class="QGridLayout" name="gridLayout_3">
<item row="2" column="1" colspan="2">
<widget class="KillerDoubleSpinBox" name="spinBoxParameter1">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="decimals">
<number>3</number>
</property>
<property name="minimum">
<double>0.001000000000000</double>
</property>
<property name="maximum">
<double>999999999.990000009536743</double>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="lParameterfor1">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Amplitude for 1:</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="lParameterfor0">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Amplitude for 0:</string>
</property>
</widget>
</item>
<item row="5" column="0" colspan="3">
<widget class="QCheckBox" name="chkBoxLockSIV">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Lock SIV to original signal</string>
</property>
</widget>
</item>
<item row="6" column="1">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item row="0" column="0" colspan="3">
<widget class="QComboBox" name="comboBoxModulationType">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>16777215</height>
</size>
</property>
<item>
<property name="text">
<string>Amplitude Shift Keying (ASK)</string>
</property>
</item>
<item>
<property name="text">
<string>Frequency Shift Keying (FSK)</string>
</property>
</item>
<item>
<property name="text">
<string>Phase Shift Keying (PSK)</string>
</property>
</item>
</widget>
</item>
<item row="1" column="1" colspan="2">
<widget class="KillerDoubleSpinBox" name="spinBoxParameter0">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="decimals">
<number>3</number>
</property>
<property name="minimum">
<double>0.001000000000000</double>
</property>
<property name="maximum">
<double>999999999.990000009536743</double>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="lSamplesInViewModulatedText">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Samples in View:</string>
</property>
</widget>
</item>
<item row="3" column="1" colspan="2">
<widget class="QLabel" name="lSamplesInViewModulated">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Shown Samples in View:&lt;/p&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600; color:#ff0000;&quot;&gt;Red&lt;/span&gt; - if samples in view differ from original signal&lt;/p&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Normal&lt;/span&gt; - if samples in view are equal to the original signal&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>101010121</string>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="label_9">
<property name="text">
<string>Samples selected:</string>
</property>
</widget>
</item>
<item row="4" column="1" colspan="2">
<widget class="QLabel" name="lModulatedSelectedSamples">
<property name="text">
<string>0</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="7" column="0">
<widget class="QLabel" name="label_7">
<property name="font">
@@ -926,6 +752,228 @@
</property>
</widget>
</item>
<item row="6" column="0">
<layout class="QGridLayout" name="gridLayout_3">
<item row="3" column="1" colspan="2">
<widget class="QDoubleSpinBox" name="spinBoxGaussBT">
<property name="minimum">
<double>0.010000000000000</double>
</property>
<property name="maximum">
<double>0.990000000000000</double>
</property>
<property name="singleStep">
<double>0.010000000000000</double>
</property>
</widget>
</item>
<item row="2" column="1" colspan="2">
<widget class="KillerDoubleSpinBox" name="spinBoxParameter1">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="decimals">
<number>3</number>
</property>
<property name="minimum">
<double>0.001000000000000</double>
</property>
<property name="maximum">
<double>999999999.990000009536743</double>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="lParameterfor1">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Amplitude for 1:</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="lParameterfor0">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Amplitude for 0:</string>
</property>
</widget>
</item>
<item row="9" column="0" colspan="3">
<widget class="QCheckBox" name="chkBoxLockSIV">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Lock SIV to original signal</string>
</property>
</widget>
</item>
<item row="10" column="1">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item row="0" column="0" colspan="3">
<widget class="QComboBox" name="comboBoxModulationType">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>16777215</height>
</size>
</property>
<item>
<property name="text">
<string>Amplitude Shift Keying (ASK)</string>
</property>
</item>
<item>
<property name="text">
<string>Frequency Shift Keying (FSK)</string>
</property>
</item>
<item>
<property name="text">
<string>Gaussian Frequency Shift Keying (GFSK)</string>
</property>
</item>
<item>
<property name="text">
<string>Phase Shift Keying (PSK)</string>
</property>
</item>
</widget>
</item>
<item row="1" column="1" colspan="2">
<widget class="KillerDoubleSpinBox" name="spinBoxParameter0">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="decimals">
<number>3</number>
</property>
<property name="minimum">
<double>0.001000000000000</double>
</property>
<property name="maximum">
<double>999999999.990000009536743</double>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QLabel" name="lSamplesInViewModulatedText">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Samples in View:</string>
</property>
</widget>
</item>
<item row="5" column="1" colspan="2">
<widget class="QLabel" name="lSamplesInViewModulated">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Shown Samples in View:&lt;/p&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600; color:#ff0000;&quot;&gt;Red&lt;/span&gt; - if samples in view differ from original signal&lt;/p&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Normal&lt;/span&gt; - if samples in view are equal to the original signal&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>101010121</string>
</property>
</widget>
</item>
<item row="8" column="0">
<widget class="QLabel" name="label_9">
<property name="text">
<string>Samples selected:</string>
</property>
</widget>
</item>
<item row="8" column="1" colspan="2">
<widget class="QLabel" name="lModulatedSelectedSamples">
<property name="text">
<string>0</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="lGaussBT">
<property name="text">
<string>Gauss BT:</string>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="lGaussWidth">
<property name="text">
<string>Gauss filter width:</string>
</property>
</widget>
</item>
<item row="4" column="1" colspan="2">
<widget class="QDoubleSpinBox" name="spinBoxGaussFilterWidth">
<property name="minimum">
<double>0.010000000000000</double>
</property>
<property name="maximum">
<double>100.000000000000000</double>
</property>
<property name="singleStep">
<double>0.010000000000000</double>
</property>
<property name="value">
<double>1.000000000000000</double>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</item>
</layout>

View File

@@ -501,7 +501,7 @@
<enum>Qt::ScrollBarAlwaysOff</enum>
</property>
<property name="horizontalScrollBarPolicy">
<enum>Qt::ScrollBarAlwaysOn</enum>
<enum>Qt::ScrollBarAsNeeded</enum>
</property>
</widget>
</item>
@@ -544,8 +544,19 @@
</customwidgets>
<tabstops>
<tabstop>cbDevice</tabstop>
<tabstop>lineEditIP</tabstop>
<tabstop>spinBoxFreq</tabstop>
<tabstop>spinBoxSampleRate</tabstop>
<tabstop>spinBoxBandwidth</tabstop>
<tabstop>spinBoxGain</tabstop>
<tabstop>spinBoxNRepeat</tabstop>
<tabstop>btnStart</tabstop>
<tabstop>btnStop</tabstop>
<tabstop>btnSave</tabstop>
<tabstop>btnClear</tabstop>
<tabstop>graphicsView</tabstop>
<tabstop>sliderYscale</tabstop>
<tabstop>txtEditErrors</tabstop>
</tabstops>
<resources/>
<connections/>

View File

@@ -67,26 +67,16 @@
<property name="sizeConstraint">
<enum>QLayout::SetFixedSize</enum>
</property>
<item row="12" column="0">
<widget class="QPushButton" name="btnReplay">
<property name="text">
<string>Replay signal...</string>
</property>
<property name="icon">
<iconset theme="media-playback-start">
<normaloff>.</normaloff>.</iconset>
</property>
</widget>
</item>
<item row="14" column="0">
<widget class="QCheckBox" name="chkBoxShowProtocol">
<item row="19" column="0">
<widget class="QCheckBox" name="chkBoxSyncSelection">
<property name="toolTip">
<string>Show the extracted protocol based on the parameters InfoLen, PauseLen and ZeroTreshold (in QuadratureDemod-View).
If you want your protocol to be better seperated, edit the PauseLen using right-click menu from a selection in SignalView or ProtocolView.</string>
<string>If this is set to true, your selected protocol bits will show up in the signal view, and vice versa.</string>
</property>
<property name="text">
<string>Show Signal as</string>
<string>Sync Selection</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
@@ -106,18 +96,17 @@ If you want your protocol to be better seperated, edit the PauseLen using right-
</property>
</widget>
</item>
<item row="13" column="0">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
<item row="18" column="0">
<widget class="QCheckBox" name="chkBoxShowProtocol">
<property name="toolTip">
<string>Show the extracted protocol based on the parameters InfoLen, PauseLen and ZeroTreshold (in QuadratureDemod-View).
If you want your protocol to be better seperated, edit the PauseLen using right-click menu from a selection in SignalView or ProtocolView.</string>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
<property name="text">
<string>Show Signal as</string>
</property>
</spacer>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label">
@@ -201,6 +190,28 @@ If you want your protocol to be better seperated, edit the PauseLen using right-
</property>
</widget>
</item>
<item row="7" column="1">
<widget class="QSpinBox" name="spinBoxTolerance">
<property name="minimumSize">
<size>
<width>100</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>16777215</height>
</size>
</property>
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;This is the error tolerance for determining the &lt;span style=&quot; font-weight:600;&quot;&gt;pulse lengths&lt;/span&gt; in the demodulated signal.&lt;/p&gt;&lt;p&gt;&lt;span style=&quot; text-decoration: underline;&quot;&gt;Example:&lt;/span&gt; Say, we are reading a ones pulse and the tolerance value was set to 5. Then 5 errors (which must follow sequentially) are accepted.&lt;/p&gt;&lt;p&gt;Tune this value if you have &lt;span style=&quot; font-weight:600;&quot;&gt;spiky data&lt;/span&gt; after demodulation.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="maximum">
<number>9999</number>
</property>
</widget>
</item>
<item row="7" column="0">
<widget class="QLabel" name="lErrorTolerance">
<property name="sizePolicy">
@@ -229,7 +240,7 @@ If you want your protocol to be better seperated, edit the PauseLen using right-
</property>
</widget>
</item>
<item row="10" column="0">
<item row="13" column="0">
<widget class="QLabel" name="lSignalViewText">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
@@ -239,7 +250,7 @@ If you want your protocol to be better seperated, edit the PauseLen using right-
</property>
<property name="font">
<font>
<underline>true</underline>
<underline>false</underline>
</font>
</property>
<property name="text">
@@ -247,29 +258,7 @@ If you want your protocol to be better seperated, edit the PauseLen using right-
</property>
</widget>
</item>
<item row="7" column="1">
<widget class="QSpinBox" name="spinBoxTolerance">
<property name="minimumSize">
<size>
<width>100</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>16777215</height>
</size>
</property>
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;This is the error tolerance for determining the &lt;span style=&quot; font-weight:600;&quot;&gt;pulse lengths&lt;/span&gt; in the demodulated signal.&lt;/p&gt;&lt;p&gt;&lt;span style=&quot; text-decoration: underline;&quot;&gt;Example:&lt;/span&gt; Say, we are reading a ones pulse and the tolerance value was set to 5. Then 5 errors (which must follow sequentially) are accepted.&lt;/p&gt;&lt;p&gt;Tune this value if you have &lt;span style=&quot; font-weight:600;&quot;&gt;spiky data&lt;/span&gt; after demodulation.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="maximum">
<number>9999</number>
</property>
</widget>
</item>
<item row="14" column="1">
<item row="18" column="1">
<widget class="QComboBox" name="cbProtoView">
<item>
<property name="text">
@@ -288,22 +277,9 @@ If you want your protocol to be better seperated, edit the PauseLen using right-
</item>
</widget>
</item>
<item row="15" column="0">
<widget class="QCheckBox" name="chkBoxSyncSelection">
<property name="toolTip">
<string>If this is set to true, your selected protocol bits will show up in the signal view, and vice versa.</string>
</property>
<property name="text">
<string>Sync Selection</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item row="0" column="0" colspan="2">
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="5">
<item row="0" column="9">
<widget class="QToolButton" name="btnMinimize">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
@@ -374,7 +350,7 @@ If you want your protocol to be better seperated, edit the PauseLen using right-
</property>
</spacer>
</item>
<item row="0" column="6">
<item row="0" column="10">
<widget class="QToolButton" name="btnCloseSignal">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
@@ -441,7 +417,7 @@ If you want your protocol to be better seperated, edit the PauseLen using right-
</property>
</widget>
</item>
<item row="0" column="4">
<item row="0" column="6">
<widget class="QToolButton" name="btnInfo">
<property name="minimumSize">
<size>
@@ -464,6 +440,32 @@ If you want your protocol to be better seperated, edit the PauseLen using right-
</property>
</widget>
</item>
<item row="0" column="5">
<widget class="QToolButton" name="btnReplay">
<property name="minimumSize">
<size>
<width>24</width>
<height>24</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>24</width>
<height>24</height>
</size>
</property>
<property name="toolTip">
<string>Replay signal</string>
</property>
<property name="text">
<string/>
</property>
<property name="icon">
<iconset theme="media-playback-start">
<normaloff>.</normaloff>.</iconset>
</property>
</widget>
</item>
</layout>
</item>
<item row="3" column="0">
@@ -528,7 +530,7 @@ If you want your protocol to be better seperated, edit the PauseLen using right-
</property>
</widget>
</item>
<item row="11" column="0" colspan="2">
<item row="14" column="0" colspan="2">
<widget class="QComboBox" name="cbSignalView">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
@@ -566,13 +568,67 @@ If you want your protocol to be better seperated, edit the PauseLen using right-
</item>
</widget>
</item>
<item row="10" column="1">
<item row="9" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Modulation:</string>
</property>
</widget>
</item>
<item row="9" column="1">
<widget class="QLabel" name="labelModulation">
<property name="text">
<string>FSK</string>
</property>
</widget>
</item>
<item row="17" column="0">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item row="11" column="0" colspan="2">
<widget class="Line" name="line">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="16" column="0" colspan="2">
<widget class="Line" name="line_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="10" column="0">
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item row="15" column="0" colspan="2">
<widget class="QPushButton" name="btnAutoDetect">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Automatically detect Center and Bit Length, when you change the demodulation type. You can disable this behaviour for faster switching between demodulations.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>Auto-Detect</string>
<string>Autodetect parameters</string>
</property>
<property name="icon">
<iconset theme="system-software-update">
@@ -592,20 +648,6 @@ If you want your protocol to be better seperated, edit the PauseLen using right-
</property>
</widget>
</item>
<item row="9" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Modulation:</string>
</property>
</widget>
</item>
<item row="9" column="1">
<widget class="QLabel" name="labelModulation">
<property name="text">
<string>FSK</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
@@ -1086,10 +1128,13 @@ If you want your protocol to be better seperated, edit the PauseLen using right-
</customwidget>
</customwidgets>
<tabstops>
<tabstop>btnMinimize</tabstop>
<tabstop>btnSaveSignal</tabstop>
<tabstop>btnInfo</tabstop>
<tabstop>btnMinimize</tabstop>
<tabstop>btnCloseSignal</tabstop>
<tabstop>lineEditSignalName</tabstop>
<tabstop>spinBoxNoiseTreshold</tabstop>
<tabstop>spinBoxCenterOffset</tabstop>
<tabstop>spinBoxInfoLen</tabstop>
<tabstop>spinBoxTolerance</tabstop>
<tabstop>cbSignalView</tabstop>
@@ -1103,6 +1148,7 @@ If you want your protocol to be better seperated, edit the PauseLen using right-
<tabstop>btnShowHideStartEnd</tabstop>
<tabstop>spinBoxSelectionStart</tabstop>
<tabstop>spinBoxSelectionEnd</tabstop>
<tabstop>spinBoxXZoom</tabstop>
</tabstops>
<resources>
<include location="../urh.qrc"/>