diff --git a/README.md b/README.md
index 9e529ab1..e1320633 100644
--- a/README.md
+++ b/README.md
@@ -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
diff --git a/src/urh/FFTSceneManager.py b/src/urh/FFTSceneManager.py
index d3f956e1..c8fbc105 100644
--- a/src/urh/FFTSceneManager.py
+++ b/src/urh/FFTSceneManager.py
@@ -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
diff --git a/src/urh/controller/CompareFrameController.py b/src/urh/controller/CompareFrameController.py
index 4a53c044..bd8677b5 100644
--- a/src/urh/controller/CompareFrameController.py
+++ b/src/urh/controller/CompareFrameController.py
@@ -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):
diff --git a/src/urh/controller/GeneratorTabController.py b/src/urh/controller/GeneratorTabController.py
index 5a91cfde..0a6eda2d 100644
--- a/src/urh/controller/GeneratorTabController.py
+++ b/src/urh/controller/GeneratorTabController.py
@@ -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...)"
diff --git a/src/urh/controller/MainController.py b/src/urh/controller/MainController.py
index 9e3a9926..1fc63247 100644
--- a/src/urh/controller/MainController.py
+++ b/src/urh/controller/MainController.py
@@ -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("Universal Radio Hacker
Version: {0}
GitHub: https://github.com/jopohl/urh
Contributors:").format(version.VERSION))
@pyqtSlot(CompareFrameController, int, int, int, int)
def show_protocol_selection_in_interpretation(self, startblock, start, endblock, end):
diff --git a/src/urh/controller/ModulatorDialogController.py b/src/urh/controller/ModulatorDialogController.py
index 7288f7b0..9c2e9a6c 100644
--- a/src/urh/controller/ModulatorDialogController.py
+++ b/src/urh/controller/ModulatorDialogController.py
@@ -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)
\ No newline at end of file
diff --git a/src/urh/controller/ProtocolLabelController.py b/src/urh/controller/ProtocolLabelController.py
index 0a00d44b..69ca880c 100644
--- a/src/urh/controller/ProtocolLabelController.py
+++ b/src/urh/controller/ProtocolLabelController.py
@@ -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()
\ No newline at end of file
+ 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()
diff --git a/src/urh/controller/SendRecvDialogController.py b/src/urh/controller/SendRecvDialogController.py
index a5ae1f29..f7414ecf 100644
--- a/src/urh/controller/SendRecvDialogController.py
+++ b/src/urh/controller/SendRecvDialogController.py
@@ -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):
diff --git a/src/urh/controller/SignalFrameController.py b/src/urh/controller/SignalFrameController.py
index 26450611..12bfbed6 100644
--- a/src/urh/controller/SignalFrameController.py
+++ b/src/urh/controller/SignalFrameController.py
@@ -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
diff --git a/src/urh/controller/SignalTabController.py b/src/urh/controller/SignalTabController.py
index 4fd373ff..1c338860 100644
--- a/src/urh/controller/SignalTabController.py
+++ b/src/urh/controller/SignalTabController.py
@@ -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:
diff --git a/src/urh/models/PLabelTableModel.py b/src/urh/models/PLabelTableModel.py
index 2fbf66c6..e3adea2a 100644
--- a/src/urh/models/PLabelTableModel.py
+++ b/src/urh/models/PLabelTableModel.py
@@ -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)
\ No newline at end of file
+ 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
+
diff --git a/src/urh/models/ProtocolTreeModel.py b/src/urh/models/ProtocolTreeModel.py
index 0e5b30da..0e101480 100644
--- a/src/urh/models/ProtocolTreeModel.py
+++ b/src/urh/models/ProtocolTreeModel.py
@@ -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:
diff --git a/src/urh/models/TableModel.py b/src/urh/models/TableModel.py
index 647ca085..9d55c4b7 100644
--- a/src/urh/models/TableModel.py
+++ b/src/urh/models/TableModel.py
@@ -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):
diff --git a/src/urh/signalprocessing/Modulator.py b/src/urh/signalprocessing/Modulator.py
index dab09e50..10d7e233 100644
--- a/src/urh/signalprocessing/Modulator.py
+++ b/src/urh/signalprocessing/Modulator.py
@@ -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:
diff --git a/src/urh/signalprocessing/ProtocolAnalyzerContainer.py b/src/urh/signalprocessing/ProtocolAnalyzerContainer.py
index 92836f16..b8044b4c 100644
--- a/src/urh/signalprocessing/ProtocolAnalyzerContainer.py
+++ b/src/urh/signalprocessing/ProtocolAnalyzerContainer.py
@@ -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):
"""
diff --git a/src/urh/signalprocessing/ProtocolGroup.py b/src/urh/signalprocessing/ProtocolGroup.py
index 27986117..6f88dd5b 100644
--- a/src/urh/signalprocessing/ProtocolGroup.py
+++ b/src/urh/signalprocessing/ProtocolGroup.py
@@ -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):
diff --git a/src/urh/ui/GridScene.py b/src/urh/ui/GridScene.py
index 4ccfcf97..8742d902 100644
--- a/src/urh/ui/GridScene.py
+++ b/src/urh/ui/GridScene.py
@@ -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,
diff --git a/src/urh/ui/KillerDoubleSpinBox.py b/src/urh/ui/KillerDoubleSpinBox.py
index 81d4b563..3db53b79 100644
--- a/src/urh/ui/KillerDoubleSpinBox.py
+++ b/src/urh/ui/KillerDoubleSpinBox.py
@@ -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
diff --git a/src/urh/ui/views/EpicGraphicView.py b/src/urh/ui/views/EpicGraphicView.py
index bb8524b0..7ffc56c7 100644
--- a/src/urh/ui/views/EpicGraphicView.py
+++ b/src/urh/ui/views/EpicGraphicView.py
@@ -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)
\ No newline at end of file
+ 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()
\ No newline at end of file
diff --git a/src/urh/ui/views/LiveGraphicView.py b/src/urh/ui/views/LiveGraphicView.py
index 2d242753..4b9a9447 100644
--- a/src/urh/ui/views/LiveGraphicView.py
+++ b/src/urh/ui/views/LiveGraphicView.py
@@ -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):
diff --git a/src/urh/util/Formatter.py b/src/urh/util/Formatter.py
index 12c2ea27..92416cf3 100644
--- a/src/urh/util/Formatter.py
+++ b/src/urh/util/Formatter.py
@@ -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)
diff --git a/tests/GFSK.py b/tests/GFSK.py
new file mode 100644
index 00000000..516fd82e
--- /dev/null
+++ b/tests/GFSK.py
@@ -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()
\ No newline at end of file
diff --git a/tests/TestLoadProtocolFile.py b/tests/TestLoadProtocolFile.py
deleted file mode 100644
index 3c0af747..00000000
--- a/tests/TestLoadProtocolFile.py
+++ /dev/null
@@ -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()
\ No newline at end of file
diff --git a/ui/modulation.ui b/ui/modulation.ui
index dfd6e110..5d2d34fa 100644
--- a/ui/modulation.ui
+++ b/ui/modulation.ui
@@ -342,180 +342,6 @@
- -
-
-
-
-
-
-
- 0
- 0
-
-
-
- 3
-
-
- 0.001000000000000
-
-
- 999999999.990000009536743
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
- Amplitude for 1:
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
- Amplitude for 0:
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
- Lock SIV to original signal
-
-
-
- -
-
-
- Qt::Vertical
-
-
-
- 20
- 40
-
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
-
- 0
- 0
-
-
-
-
- 16777215
- 16777215
-
-
-
-
-
- Amplitude Shift Keying (ASK)
-
-
- -
-
- Frequency Shift Keying (FSK)
-
-
- -
-
- Phase Shift Keying (PSK)
-
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
- 3
-
-
- 0.001000000000000
-
-
- 999999999.990000009536743
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
- Samples in View:
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
- <html><head/><body><p>Shown Samples in View:</p><p><span style=" font-weight:600; color:#ff0000;">Red</span> - if samples in view differ from original signal</p><p><span style=" font-weight:600;">Normal</span> - if samples in view are equal to the original signal</p></body></html>
-
-
- 101010121
-
-
-
- -
-
-
- Samples selected:
-
-
-
- -
-
-
- 0
-
-
-
-
-
-
@@ -926,6 +752,228 @@
+ -
+
+
-
+
+
+ 0.010000000000000
+
+
+ 0.990000000000000
+
+
+ 0.010000000000000
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ 3
+
+
+ 0.001000000000000
+
+
+ 999999999.990000009536743
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ Amplitude for 1:
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ Amplitude for 0:
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ Lock SIV to original signal
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+
+ 20
+ 40
+
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 0
+ 0
+
+
+
+
+ 16777215
+ 16777215
+
+
+
-
+
+ Amplitude Shift Keying (ASK)
+
+
+ -
+
+ Frequency Shift Keying (FSK)
+
+
+ -
+
+ Gaussian Frequency Shift Keying (GFSK)
+
+
+ -
+
+ Phase Shift Keying (PSK)
+
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ 3
+
+
+ 0.001000000000000
+
+
+ 999999999.990000009536743
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ Samples in View:
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ <html><head/><body><p>Shown Samples in View:</p><p><span style=" font-weight:600; color:#ff0000;">Red</span> - if samples in view differ from original signal</p><p><span style=" font-weight:600;">Normal</span> - if samples in view are equal to the original signal</p></body></html>
+
+
+ 101010121
+
+
+
+ -
+
+
+ Samples selected:
+
+
+
+ -
+
+
+ 0
+
+
+
+ -
+
+
+ Gauss BT:
+
+
+
+ -
+
+
+ Gauss filter width:
+
+
+
+ -
+
+
+ 0.010000000000000
+
+
+ 100.000000000000000
+
+
+ 0.010000000000000
+
+
+ 1.000000000000000
+
+
+
+
+
diff --git a/ui/send_recv.ui b/ui/send_recv.ui
index ce3cbb97..a5067854 100644
--- a/ui/send_recv.ui
+++ b/ui/send_recv.ui
@@ -501,7 +501,7 @@
Qt::ScrollBarAlwaysOff
- Qt::ScrollBarAlwaysOn
+ Qt::ScrollBarAsNeeded
@@ -544,8 +544,19 @@
cbDevice
+ lineEditIP
+ spinBoxFreq
+ spinBoxSampleRate
+ spinBoxBandwidth
spinBoxGain
+ spinBoxNRepeat
+ btnStart
+ btnStop
+ btnSave
+ btnClear
graphicsView
+ sliderYscale
+ txtEditErrors
diff --git a/ui/signal_frame.ui b/ui/signal_frame.ui
index 537955fa..3123cea7 100644
--- a/ui/signal_frame.ui
+++ b/ui/signal_frame.ui
@@ -67,26 +67,16 @@
QLayout::SetFixedSize
- -
-
-
- Replay signal...
-
-
-
- ..
-
-
-
- -
-
+
-
+
- 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.
+ If this is set to true, your selected protocol bits will show up in the signal view, and vice versa.
- Show Signal as
+ Sync Selection
+
+
+ true
@@ -106,18 +96,17 @@ If you want your protocol to be better seperated, edit the PauseLen using right-
- -
-
-
- Qt::Vertical
+
-
+
+
+ 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.
-
-
- 20
- 40
-
+
+ Show Signal as
-
+
-
@@ -201,6 +190,28 @@ If you want your protocol to be better seperated, edit the PauseLen using right-
+ -
+
+
+
+ 100
+ 0
+
+
+
+
+ 16777215
+ 16777215
+
+
+
+ <html><head/><body><p>This is the error tolerance for determining the <span style=" font-weight:600;">pulse lengths</span> in the demodulated signal.</p><p><span style=" text-decoration: underline;">Example:</span> Say, we are reading a ones pulse and the tolerance value was set to 5. Then 5 errors (which must follow sequentially) are accepted.</p><p>Tune this value if you have <span style=" font-weight:600;">spiky data</span> after demodulation.</p></body></html>
+
+
+ 9999
+
+
+
-
@@ -229,7 +240,7 @@ If you want your protocol to be better seperated, edit the PauseLen using right-
- -
+
-
@@ -239,7 +250,7 @@ If you want your protocol to be better seperated, edit the PauseLen using right-
- true
+ false
@@ -247,29 +258,7 @@ If you want your protocol to be better seperated, edit the PauseLen using right-
- -
-
-
-
- 100
- 0
-
-
-
-
- 16777215
- 16777215
-
-
-
- <html><head/><body><p>This is the error tolerance for determining the <span style=" font-weight:600;">pulse lengths</span> in the demodulated signal.</p><p><span style=" text-decoration: underline;">Example:</span> Say, we are reading a ones pulse and the tolerance value was set to 5. Then 5 errors (which must follow sequentially) are accepted.</p><p>Tune this value if you have <span style=" font-weight:600;">spiky data</span> after demodulation.</p></body></html>
-
-
- 9999
-
-
-
- -
+
-
-
@@ -288,22 +277,9 @@ If you want your protocol to be better seperated, edit the PauseLen using right-
- -
-
-
- If this is set to true, your selected protocol bits will show up in the signal view, and vice versa.
-
-
- Sync Selection
-
-
- true
-
-
-
-
-
-
+
-
@@ -374,7 +350,7 @@ If you want your protocol to be better seperated, edit the PauseLen using right-
- -
+
-
@@ -441,7 +417,7 @@ If you want your protocol to be better seperated, edit the PauseLen using right-
- -
+
-
@@ -464,6 +440,32 @@ If you want your protocol to be better seperated, edit the PauseLen using right-
+ -
+
+
+
+ 24
+ 24
+
+
+
+
+ 24
+ 24
+
+
+
+ Replay signal
+
+
+
+
+
+
+ ..
+
+
+
-
@@ -528,7 +530,7 @@ If you want your protocol to be better seperated, edit the PauseLen using right-
- -
+
-
@@ -566,13 +568,67 @@ If you want your protocol to be better seperated, edit the PauseLen using right-
- -
+
-
+
+
+ Modulation:
+
+
+
+ -
+
+
+ FSK
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+
+ 20
+ 40
+
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+
+ 20
+ 40
+
+
+
+
+ -
<html><head/><body><p>Automatically detect Center and Bit Length, when you change the demodulation type. You can disable this behaviour for faster switching between demodulations.</p></body></html>
- Auto-Detect
+ Autodetect parameters
@@ -592,20 +648,6 @@ If you want your protocol to be better seperated, edit the PauseLen using right-
- -
-
-
- Modulation:
-
-
-
- -
-
-
- FSK
-
-
-
-
@@ -1086,10 +1128,13 @@ If you want your protocol to be better seperated, edit the PauseLen using right-
- btnMinimize
btnSaveSignal
+ btnInfo
+ btnMinimize
btnCloseSignal
lineEditSignalName
+ spinBoxNoiseTreshold
+ spinBoxCenterOffset
spinBoxInfoLen
spinBoxTolerance
cbSignalView
@@ -1103,6 +1148,7 @@ If you want your protocol to be better seperated, edit the PauseLen using right-
btnShowHideStartEnd
spinBoxSelectionStart
spinBoxSelectionEnd
+ spinBoxXZoom