aboutsummaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
authorNao Pross <np@0hm.ch>2021-10-13 18:12:08 +0200
committerNao Pross <np@0hm.ch>2021-10-13 18:16:26 +0200
commit20e54b3cf198f17e05a3c7e8716138717447aa32 (patch)
tree38afe78b2fe6b71d59e6c3051ca0ac746d35bc70 /tests
parentMove paragraph to introduction (diff)
downloadFading-20e54b3cf198f17e05a3c7e8716138717447aa32.tar.gz
Fading-20e54b3cf198f17e05a3c7e8716138717447aa32.zip
Create QPKS simulation
The current flow diagram does the following: - Generate a QPKS constellation from a random bit source. The constellation is parametrized by the 'Constellation Rect. Object' and the variables 'sps' (Samples Per Symbol) and 'excess_bw' (Excess Bandwidth). - Send the modulated signal through a AWGN channel. Noise channel taps are controlled with the 'taps' variable, the other paramters are given through the 'QT GUI Range' objects. - Display the constellation diagram as well as the time and frequency domain plots of the signal after the channel (receiver side). - Synchronize the clock using a polyphase clock sync with root raised cosine filters. The number of filters is stored in 'nfilts' and the filter themselves are in 'rcc_taps'. - Finally, display the constellation after the RCC filters. What is still missing: - Multipath fading taps in the channel model (for later) - Equalization on the receiver side. PROBLEM: The wiki tutorial targets GNU Radio 3.9, and uses 'Linear Equlizer' and 'Adaptive Algorithm' blocks which are not available in GNU Radio 3.8. We need to use 'CMA Equalizer' and 'LMS DD Equalizer' and figure out their parameters instead. Though this should not be hard. - Phase and Fine Frequency Correction. - Decode the message.
Diffstat (limited to 'tests')
-rw-r--r--tests/Simulation/QPKS/qpks.grc688
-rwxr-xr-xtests/Simulation/QPKS/qpks.py460
2 files changed, 1148 insertions, 0 deletions
diff --git a/tests/Simulation/QPKS/qpks.grc b/tests/Simulation/QPKS/qpks.grc
new file mode 100644
index 0000000..b799dc7
--- /dev/null
+++ b/tests/Simulation/QPKS/qpks.grc
@@ -0,0 +1,688 @@
+options:
+ parameters:
+ author: ''
+ category: '[GRC Hier Blocks]'
+ cmake_opt: ''
+ comment: ''
+ copyright: ''
+ description: ''
+ gen_cmake: 'On'
+ gen_linking: dynamic
+ generate_options: qt_gui
+ hier_block_src_path: '.:'
+ id: qpks
+ max_nouts: '0'
+ output_language: python
+ placement: (0,0)
+ qt_qss_theme: ''
+ realtime_scheduling: '1'
+ run: 'True'
+ run_command: '{python} -u {filename}'
+ run_options: prompt
+ sizing_mode: fixed
+ thread_safe_setters: ''
+ title: QPSK
+ window_size: ''
+ states:
+ bus_sink: false
+ bus_source: false
+ bus_structure: null
+ coordinate: [8, 8]
+ rotation: 0
+ state: enabled
+
+blocks:
+- name: excess_bw
+ id: variable
+ parameters:
+ comment: ''
+ value: 350e-3
+ states:
+ bus_sink: false
+ bus_source: false
+ bus_structure: null
+ coordinate: [320, 140.0]
+ rotation: 0
+ state: true
+- name: freq_offset
+ id: variable_qtgui_range
+ parameters:
+ comment: ''
+ gui_hint: 1,0,1,1
+ label: Frequency Offset
+ min_len: '200'
+ orient: Qt.Horizontal
+ rangeType: float
+ start: -100e-3
+ step: 1e-3
+ stop: 100e-3
+ value: '0'
+ widget: counter_slider
+ states:
+ bus_sink: false
+ bus_source: false
+ bus_structure: null
+ coordinate: [648, 340.0]
+ rotation: 0
+ state: true
+- name: nfilts
+ id: variable
+ parameters:
+ comment: ''
+ value: '32'
+ states:
+ bus_sink: false
+ bus_source: false
+ bus_structure: null
+ coordinate: [920, 540.0]
+ rotation: 0
+ state: true
+- name: noise_volt
+ id: variable_qtgui_range
+ parameters:
+ comment: ''
+ gui_hint: 0,0,1,1
+ label: Noise Voltage
+ min_len: '200'
+ orient: Qt.Horizontal
+ rangeType: float
+ start: '0'
+ step: '0.01'
+ stop: '1'
+ value: '0.0001'
+ widget: counter_slider
+ states:
+ bus_sink: false
+ bus_source: false
+ bus_structure: null
+ coordinate: [488, 340.0]
+ rotation: 0
+ state: true
+- name: qpsk_const
+ id: variable_constellation_rect
+ parameters:
+ comment: ''
+ const_points: '[0.707+0.707j, -0.707+0.707j, -0.707-0.707j, 0.707-0.707j]'
+ imag_sect: '2'
+ precision: '8'
+ real_sect: '2'
+ rot_sym: '4'
+ soft_dec_lut: None
+ sym_map: '[0, 1, 3, 2]'
+ w_imag_sect: '1'
+ w_real_sect: '1'
+ states:
+ bus_sink: false
+ bus_source: false
+ bus_structure: null
+ coordinate: [224, 316.0]
+ rotation: 0
+ state: true
+- name: rrc_taps
+ id: variable
+ parameters:
+ comment: ''
+ value: firdes.root_raised_cosine(nfilts, nfilts, 1.0/float(sps), 0.35, 45*nfilts)
+ states:
+ bus_sink: false
+ bus_source: false
+ bus_structure: null
+ coordinate: [992, 540.0]
+ rotation: 0
+ state: true
+- name: samp_rate
+ id: variable
+ parameters:
+ comment: ''
+ value: '32000'
+ states:
+ bus_sink: false
+ bus_source: false
+ bus_structure: null
+ coordinate: [192, 12.0]
+ rotation: 0
+ state: enabled
+- name: sps
+ id: variable
+ parameters:
+ comment: ''
+ value: '4'
+ states:
+ bus_sink: false
+ bus_source: false
+ bus_structure: null
+ coordinate: [224, 140.0]
+ rotation: 0
+ state: true
+- name: taps
+ id: variable
+ parameters:
+ comment: ''
+ value: '[1.0 + 0.0j, ]'
+ states:
+ bus_sink: false
+ bus_source: false
+ bus_structure: null
+ coordinate: [648, 124.0]
+ rotation: 0
+ state: true
+- name: time_offset
+ id: variable_qtgui_range
+ parameters:
+ comment: ''
+ gui_hint: 0,1,1,1
+ label: Timing Offset
+ min_len: '200'
+ orient: Qt.Horizontal
+ rangeType: float
+ start: '0.999'
+ step: '0.0001'
+ stop: '1.001'
+ value: '1.0'
+ widget: counter_slider
+ states:
+ bus_sink: false
+ bus_source: false
+ bus_structure: null
+ coordinate: [488, 484.0]
+ rotation: 0
+ state: true
+- name: timing_loop_bw
+ id: variable_qtgui_range
+ parameters:
+ comment: ''
+ gui_hint: 1,1,1,1
+ label: 'Time: BW'
+ min_len: '200'
+ orient: Qt.Horizontal
+ rangeType: float
+ start: '0'
+ step: 10e-3
+ stop: 200e-3
+ value: 2 * 3.141592653589793 / 100
+ widget: counter_slider
+ states:
+ bus_sink: false
+ bus_source: false
+ bus_structure: null
+ coordinate: [648, 484.0]
+ rotation: 0
+ state: true
+- name: analog_random_source_x_0
+ id: analog_random_source_x
+ parameters:
+ affinity: ''
+ alias: ''
+ comment: ''
+ max: '2'
+ maxoutbuf: '0'
+ min: '0'
+ minoutbuf: '0'
+ num_samps: '1000'
+ repeat: 'True'
+ type: byte
+ states:
+ bus_sink: false
+ bus_source: false
+ bus_structure: null
+ coordinate: [32, 204.0]
+ rotation: 0
+ state: enabled
+- name: blocks_throttle_0
+ id: blocks_throttle
+ parameters:
+ affinity: ''
+ alias: ''
+ comment: ''
+ ignoretag: 'True'
+ maxoutbuf: '0'
+ minoutbuf: '0'
+ samples_per_second: samp_rate
+ type: complex
+ vlen: '1'
+ states:
+ bus_sink: false
+ bus_source: false
+ bus_structure: null
+ coordinate: [464, 228.0]
+ rotation: 0
+ state: enabled
+- name: channels_channel_model_0
+ id: channels_channel_model
+ parameters:
+ affinity: ''
+ alias: ''
+ block_tags: 'False'
+ comment: ''
+ epsilon: time_offset
+ freq_offset: freq_offset
+ maxoutbuf: '0'
+ minoutbuf: '0'
+ noise_voltage: noise_volt
+ seed: '0'
+ taps: taps
+ states:
+ bus_sink: false
+ bus_source: false
+ bus_structure: null
+ coordinate: [648, 188.0]
+ rotation: 0
+ state: enabled
+- name: digital_constellation_modulator_0
+ id: digital_constellation_modulator
+ parameters:
+ affinity: ''
+ alias: ''
+ comment: ''
+ constellation: qpsk_const
+ differential: 'True'
+ excess_bw: excess_bw
+ log: 'False'
+ maxoutbuf: '0'
+ minoutbuf: '0'
+ samples_per_symbol: sps
+ verbose: 'False'
+ states:
+ bus_sink: false
+ bus_source: false
+ bus_structure: null
+ coordinate: [224, 204.0]
+ rotation: 0
+ state: enabled
+- name: digital_pfb_clock_sync_xxx_0
+ id: digital_pfb_clock_sync_xxx
+ parameters:
+ affinity: ''
+ alias: ''
+ comment: ''
+ filter_size: nfilts
+ init_phase: nfilts/2
+ loop_bw: timing_loop_bw
+ max_dev: '1.5'
+ maxoutbuf: '0'
+ minoutbuf: '0'
+ osps: '1'
+ sps: sps * 1.001
+ taps: rrc_taps
+ type: ccf
+ states:
+ bus_sink: false
+ bus_source: false
+ bus_structure: null
+ coordinate: [920, 380.0]
+ rotation: 0
+ state: true
+- name: qtgui_const_sink_x_0
+ id: qtgui_const_sink_x
+ parameters:
+ affinity: ''
+ alias: ''
+ alpha1: '1.0'
+ alpha10: '1.0'
+ alpha2: '1.0'
+ alpha3: '1.0'
+ alpha4: '1.0'
+ alpha5: '1.0'
+ alpha6: '1.0'
+ alpha7: '1.0'
+ alpha8: '1.0'
+ alpha9: '1.0'
+ autoscale: 'False'
+ axislabels: 'True'
+ color1: '"blue"'
+ color10: '"red"'
+ color2: '"red"'
+ color3: '"red"'
+ color4: '"red"'
+ color5: '"red"'
+ color6: '"red"'
+ color7: '"red"'
+ color8: '"red"'
+ color9: '"red"'
+ comment: ''
+ grid: 'False'
+ gui_hint: 2,1,1,1
+ label1: ''
+ label10: ''
+ label2: ''
+ label3: ''
+ label4: ''
+ label5: ''
+ label6: ''
+ label7: ''
+ label8: ''
+ label9: ''
+ legend: 'True'
+ marker1: '0'
+ marker10: '0'
+ marker2: '0'
+ marker3: '0'
+ marker4: '0'
+ marker5: '0'
+ marker6: '0'
+ marker7: '0'
+ marker8: '0'
+ marker9: '0'
+ name: '"After Channel"'
+ nconnections: '1'
+ size: '2048'
+ style1: '0'
+ style10: '0'
+ style2: '0'
+ style3: '0'
+ style4: '0'
+ style5: '0'
+ style6: '0'
+ style7: '0'
+ style8: '0'
+ style9: '0'
+ tr_chan: '0'
+ tr_level: '0.0'
+ tr_mode: qtgui.TRIG_MODE_FREE
+ tr_slope: qtgui.TRIG_SLOPE_POS
+ tr_tag: '""'
+ type: complex
+ update_time: '0.10'
+ width1: '1'
+ width10: '1'
+ width2: '1'
+ width3: '1'
+ width4: '1'
+ width5: '1'
+ width6: '1'
+ width7: '1'
+ width8: '1'
+ width9: '1'
+ xmax: '2'
+ xmin: '-2'
+ ymax: '2'
+ ymin: '-2'
+ states:
+ bus_sink: false
+ bus_source: false
+ bus_structure: null
+ coordinate: [920, 284.0]
+ rotation: 0
+ state: enabled
+- name: qtgui_const_sink_x_0_0
+ id: qtgui_const_sink_x
+ parameters:
+ affinity: ''
+ alias: ''
+ alpha1: '1.0'
+ alpha10: '1.0'
+ alpha2: '1.0'
+ alpha3: '1.0'
+ alpha4: '1.0'
+ alpha5: '1.0'
+ alpha6: '1.0'
+ alpha7: '1.0'
+ alpha8: '1.0'
+ alpha9: '1.0'
+ autoscale: 'False'
+ axislabels: 'True'
+ color1: '"blue"'
+ color10: '"red"'
+ color2: '"red"'
+ color3: '"red"'
+ color4: '"red"'
+ color5: '"red"'
+ color6: '"red"'
+ color7: '"red"'
+ color8: '"red"'
+ color9: '"red"'
+ comment: ''
+ grid: 'False'
+ gui_hint: 3,1,1,1
+ label1: ''
+ label10: ''
+ label2: ''
+ label3: ''
+ label4: ''
+ label5: ''
+ label6: ''
+ label7: ''
+ label8: ''
+ label9: ''
+ legend: 'True'
+ marker1: '0'
+ marker10: '0'
+ marker2: '0'
+ marker3: '0'
+ marker4: '0'
+ marker5: '0'
+ marker6: '0'
+ marker7: '0'
+ marker8: '0'
+ marker9: '0'
+ name: '"After Clock Sync"'
+ nconnections: '1'
+ size: '2048'
+ style1: '0'
+ style10: '0'
+ style2: '0'
+ style3: '0'
+ style4: '0'
+ style5: '0'
+ style6: '0'
+ style7: '0'
+ style8: '0'
+ style9: '0'
+ tr_chan: '0'
+ tr_level: '0.0'
+ tr_mode: qtgui.TRIG_MODE_FREE
+ tr_slope: qtgui.TRIG_SLOPE_POS
+ tr_tag: '""'
+ type: complex
+ update_time: '0.10'
+ width1: '1'
+ width10: '1'
+ width2: '1'
+ width3: '1'
+ width4: '1'
+ width5: '1'
+ width6: '1'
+ width7: '1'
+ width8: '1'
+ width9: '1'
+ xmax: '2'
+ xmin: '-2'
+ ymax: '2'
+ ymin: '-2'
+ states:
+ bus_sink: false
+ bus_source: false
+ bus_structure: null
+ coordinate: [1200, 364.0]
+ rotation: 0
+ state: enabled
+- name: qtgui_freq_sink_x_0
+ id: qtgui_freq_sink_x
+ parameters:
+ affinity: ''
+ alias: ''
+ alpha1: '1.0'
+ alpha10: '1.0'
+ alpha2: '1.0'
+ alpha3: '1.0'
+ alpha4: '1.0'
+ alpha5: '1.0'
+ alpha6: '1.0'
+ alpha7: '1.0'
+ alpha8: '1.0'
+ alpha9: '1.0'
+ autoscale: 'False'
+ average: '1.0'
+ axislabels: 'True'
+ bw: samp_rate
+ color1: '"blue"'
+ color10: '"dark blue"'
+ color2: '"red"'
+ color3: '"green"'
+ color4: '"black"'
+ color5: '"cyan"'
+ color6: '"magenta"'
+ color7: '"yellow"'
+ color8: '"dark red"'
+ color9: '"dark green"'
+ comment: ''
+ ctrlpanel: 'False'
+ fc: '0'
+ fftsize: '1024'
+ freqhalf: 'True'
+ grid: 'False'
+ gui_hint: 3,0,1,1
+ label: Relative Gain
+ label1: ''
+ label10: ''''''
+ label2: ''''''
+ label3: ''''''
+ label4: ''''''
+ label5: ''''''
+ label6: ''''''
+ label7: ''''''
+ label8: ''''''
+ label9: ''''''
+ legend: 'True'
+ maxoutbuf: '0'
+ minoutbuf: '0'
+ name: '"Channel Input"'
+ nconnections: '1'
+ showports: 'False'
+ tr_chan: '0'
+ tr_level: '0.0'
+ tr_mode: qtgui.TRIG_MODE_FREE
+ tr_tag: '""'
+ type: complex
+ units: dB
+ update_time: '0.10'
+ width1: '1'
+ width10: '1'
+ width2: '1'
+ width3: '1'
+ width4: '1'
+ width5: '1'
+ width6: '1'
+ width7: '1'
+ width8: '1'
+ width9: '1'
+ wintype: firdes.WIN_BLACKMAN_hARRIS
+ ymax: '10'
+ ymin: '-140'
+ states:
+ bus_sink: false
+ bus_source: false
+ bus_structure: null
+ coordinate: [920, 56.0]
+ rotation: 0
+ state: true
+- name: qtgui_time_sink_x_0
+ id: qtgui_time_sink_x
+ parameters:
+ affinity: ''
+ alias: ''
+ alpha1: '1.0'
+ alpha10: '1.0'
+ alpha2: '1.0'
+ alpha3: '1.0'
+ alpha4: '1.0'
+ alpha5: '1.0'
+ alpha6: '1.0'
+ alpha7: '1.0'
+ alpha8: '1.0'
+ alpha9: '1.0'
+ autoscale: 'False'
+ axislabels: 'True'
+ color1: blue
+ color10: dark blue
+ color2: red
+ color3: green
+ color4: black
+ color5: cyan
+ color6: magenta
+ color7: yellow
+ color8: dark red
+ color9: dark green
+ comment: ''
+ ctrlpanel: 'False'
+ entags: 'True'
+ grid: 'False'
+ gui_hint: 2,0,1,1
+ label1: Signal 1
+ label10: Signal 10
+ label2: Signal 2
+ label3: Signal 3
+ label4: Signal 4
+ label5: Signal 5
+ label6: Signal 6
+ label7: Signal 7
+ label8: Signal 8
+ label9: Signal 9
+ legend: 'True'
+ marker1: '-1'
+ marker10: '-1'
+ marker2: '-1'
+ marker3: '-1'
+ marker4: '-1'
+ marker5: '-1'
+ marker6: '-1'
+ marker7: '-1'
+ marker8: '-1'
+ marker9: '-1'
+ name: '"Channel Input Spectrum"'
+ nconnections: '1'
+ size: '1024'
+ srate: samp_rate
+ stemplot: 'False'
+ style1: '1'
+ style10: '1'
+ style2: '1'
+ style3: '1'
+ style4: '1'
+ style5: '1'
+ style6: '1'
+ style7: '1'
+ style8: '1'
+ style9: '1'
+ tr_chan: '0'
+ tr_delay: '0'
+ tr_level: '0.0'
+ tr_mode: qtgui.TRIG_MODE_FREE
+ tr_slope: qtgui.TRIG_SLOPE_POS
+ tr_tag: '""'
+ type: complex
+ update_time: '0.10'
+ width1: '1'
+ width10: '1'
+ width2: '1'
+ width3: '1'
+ width4: '1'
+ width5: '1'
+ width6: '1'
+ width7: '1'
+ width8: '1'
+ width9: '1'
+ ylabel: Amplitude
+ ymax: '1'
+ ymin: '-1'
+ yunit: '""'
+ states:
+ bus_sink: false
+ bus_source: false
+ bus_structure: null
+ coordinate: [920, 172.0]
+ rotation: 0
+ state: enabled
+
+connections:
+- [analog_random_source_x_0, '0', digital_constellation_modulator_0, '0']
+- [blocks_throttle_0, '0', channels_channel_model_0, '0']
+- [channels_channel_model_0, '0', digital_pfb_clock_sync_xxx_0, '0']
+- [channels_channel_model_0, '0', qtgui_const_sink_x_0, '0']
+- [channels_channel_model_0, '0', qtgui_freq_sink_x_0, '0']
+- [channels_channel_model_0, '0', qtgui_time_sink_x_0, '0']
+- [digital_constellation_modulator_0, '0', blocks_throttle_0, '0']
+- [digital_pfb_clock_sync_xxx_0, '0', qtgui_const_sink_x_0_0, '0']
+
+metadata:
+ file_format: 1
diff --git a/tests/Simulation/QPKS/qpks.py b/tests/Simulation/QPKS/qpks.py
new file mode 100755
index 0000000..4027eb3
--- /dev/null
+++ b/tests/Simulation/QPKS/qpks.py
@@ -0,0 +1,460 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+
+#
+# SPDX-License-Identifier: GPL-3.0
+#
+# GNU Radio Python Flow Graph
+# Title: QPSK
+# GNU Radio version: 3.8.2.0
+
+from distutils.version import StrictVersion
+
+if __name__ == '__main__':
+ import ctypes
+ import sys
+ if sys.platform.startswith('linux'):
+ try:
+ x11 = ctypes.cdll.LoadLibrary('libX11.so')
+ x11.XInitThreads()
+ except:
+ print("Warning: failed to XInitThreads()")
+
+from PyQt5 import Qt
+from gnuradio import qtgui
+from gnuradio.filter import firdes
+import sip
+from gnuradio import blocks
+import numpy
+from gnuradio import channels
+from gnuradio import digital
+from gnuradio import gr
+import sys
+import signal
+from argparse import ArgumentParser
+from gnuradio.eng_arg import eng_float, intx
+from gnuradio import eng_notation
+from gnuradio.qtgui import Range, RangeWidget
+
+from gnuradio import qtgui
+
+class qpks(gr.top_block, Qt.QWidget):
+
+ def __init__(self):
+ gr.top_block.__init__(self, "QPSK")
+ Qt.QWidget.__init__(self)
+ self.setWindowTitle("QPSK")
+ qtgui.util.check_set_qss()
+ try:
+ self.setWindowIcon(Qt.QIcon.fromTheme('gnuradio-grc'))
+ except:
+ pass
+ self.top_scroll_layout = Qt.QVBoxLayout()
+ self.setLayout(self.top_scroll_layout)
+ self.top_scroll = Qt.QScrollArea()
+ self.top_scroll.setFrameStyle(Qt.QFrame.NoFrame)
+ self.top_scroll_layout.addWidget(self.top_scroll)
+ self.top_scroll.setWidgetResizable(True)
+ self.top_widget = Qt.QWidget()
+ self.top_scroll.setWidget(self.top_widget)
+ self.top_layout = Qt.QVBoxLayout(self.top_widget)
+ self.top_grid_layout = Qt.QGridLayout()
+ self.top_layout.addLayout(self.top_grid_layout)
+
+ self.settings = Qt.QSettings("GNU Radio", "qpks")
+
+ try:
+ if StrictVersion(Qt.qVersion()) < StrictVersion("5.0.0"):
+ self.restoreGeometry(self.settings.value("geometry").toByteArray())
+ else:
+ self.restoreGeometry(self.settings.value("geometry"))
+ except:
+ pass
+
+ ##################################################
+ # Variables
+ ##################################################
+ self.sps = sps = 4
+ self.nfilts = nfilts = 32
+ self.timing_loop_bw = timing_loop_bw = 2 * 3.141592653589793 / 100
+ self.time_offset = time_offset = 1.0
+ self.taps = taps = [1.0 + 0.0j, ]
+ self.samp_rate = samp_rate = 32000
+ self.rrc_taps = rrc_taps = firdes.root_raised_cosine(nfilts, nfilts, 1.0/float(sps), 0.35, 45*nfilts)
+ self.qpsk_const = qpsk_const = digital.constellation_rect([0.707+0.707j, -0.707+0.707j, -0.707-0.707j, 0.707-0.707j], [0, 1, 3, 2],
+ 4, 2, 2, 1, 1).base()
+ self.noise_volt = noise_volt = 0.0001
+ self.freq_offset = freq_offset = 0
+ self.excess_bw = excess_bw = 350e-3
+
+ ##################################################
+ # Blocks
+ ##################################################
+ self._timing_loop_bw_range = Range(0, 200e-3, 10e-3, 2 * 3.141592653589793 / 100, 200)
+ self._timing_loop_bw_win = RangeWidget(self._timing_loop_bw_range, self.set_timing_loop_bw, 'Time: BW', "counter_slider", float)
+ self.top_grid_layout.addWidget(self._timing_loop_bw_win, 1, 1, 1, 1)
+ for r in range(1, 2):
+ self.top_grid_layout.setRowStretch(r, 1)
+ for c in range(1, 2):
+ self.top_grid_layout.setColumnStretch(c, 1)
+ self._time_offset_range = Range(0.999, 1.001, 0.0001, 1.0, 200)
+ self._time_offset_win = RangeWidget(self._time_offset_range, self.set_time_offset, 'Timing Offset', "counter_slider", float)
+ self.top_grid_layout.addWidget(self._time_offset_win, 0, 1, 1, 1)
+ for r in range(0, 1):
+ self.top_grid_layout.setRowStretch(r, 1)
+ for c in range(1, 2):
+ self.top_grid_layout.setColumnStretch(c, 1)
+ self._noise_volt_range = Range(0, 1, 0.01, 0.0001, 200)
+ self._noise_volt_win = RangeWidget(self._noise_volt_range, self.set_noise_volt, 'Noise Voltage', "counter_slider", float)
+ self.top_grid_layout.addWidget(self._noise_volt_win, 0, 0, 1, 1)
+ for r in range(0, 1):
+ self.top_grid_layout.setRowStretch(r, 1)
+ for c in range(0, 1):
+ self.top_grid_layout.setColumnStretch(c, 1)
+ self._freq_offset_range = Range(-100e-3, 100e-3, 1e-3, 0, 200)
+ self._freq_offset_win = RangeWidget(self._freq_offset_range, self.set_freq_offset, 'Frequency Offset', "counter_slider", float)
+ self.top_grid_layout.addWidget(self._freq_offset_win, 1, 0, 1, 1)
+ for r in range(1, 2):
+ self.top_grid_layout.setRowStretch(r, 1)
+ for c in range(0, 1):
+ self.top_grid_layout.setColumnStretch(c, 1)
+ self.qtgui_time_sink_x_0 = qtgui.time_sink_c(
+ 1024, #size
+ samp_rate, #samp_rate
+ "Channel Input Spectrum", #name
+ 1 #number of inputs
+ )
+ self.qtgui_time_sink_x_0.set_update_time(0.10)
+ self.qtgui_time_sink_x_0.set_y_axis(-1, 1)
+
+ self.qtgui_time_sink_x_0.set_y_label('Amplitude', "")
+
+ self.qtgui_time_sink_x_0.enable_tags(True)
+ self.qtgui_time_sink_x_0.set_trigger_mode(qtgui.TRIG_MODE_FREE, qtgui.TRIG_SLOPE_POS, 0.0, 0, 0, "")
+ self.qtgui_time_sink_x_0.enable_autoscale(False)
+ self.qtgui_time_sink_x_0.enable_grid(False)
+ self.qtgui_time_sink_x_0.enable_axis_labels(True)
+ self.qtgui_time_sink_x_0.enable_control_panel(False)
+ self.qtgui_time_sink_x_0.enable_stem_plot(False)
+
+
+ labels = ['Signal 1', 'Signal 2', 'Signal 3', 'Signal 4', 'Signal 5',
+ 'Signal 6', 'Signal 7', 'Signal 8', 'Signal 9', 'Signal 10']
+ widths = [1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1]
+ colors = ['blue', 'red', 'green', 'black', 'cyan',
+ 'magenta', 'yellow', 'dark red', 'dark green', 'dark blue']
+ alphas = [1.0, 1.0, 1.0, 1.0, 1.0,
+ 1.0, 1.0, 1.0, 1.0, 1.0]
+ styles = [1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1]
+ markers = [-1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1]
+
+
+ for i in range(2):
+ if len(labels[i]) == 0:
+ if (i % 2 == 0):
+ self.qtgui_time_sink_x_0.set_line_label(i, "Re{{Data {0}}}".format(i/2))
+ else:
+ self.qtgui_time_sink_x_0.set_line_label(i, "Im{{Data {0}}}".format(i/2))
+ else:
+ self.qtgui_time_sink_x_0.set_line_label(i, labels[i])
+ self.qtgui_time_sink_x_0.set_line_width(i, widths[i])
+ self.qtgui_time_sink_x_0.set_line_color(i, colors[i])
+ self.qtgui_time_sink_x_0.set_line_style(i, styles[i])
+ self.qtgui_time_sink_x_0.set_line_marker(i, markers[i])
+ self.qtgui_time_sink_x_0.set_line_alpha(i, alphas[i])
+
+ self._qtgui_time_sink_x_0_win = sip.wrapinstance(self.qtgui_time_sink_x_0.pyqwidget(), Qt.QWidget)
+ self.top_grid_layout.addWidget(self._qtgui_time_sink_x_0_win, 2, 0, 1, 1)
+ for r in range(2, 3):
+ self.top_grid_layout.setRowStretch(r, 1)
+ for c in range(0, 1):
+ self.top_grid_layout.setColumnStretch(c, 1)
+ self.qtgui_freq_sink_x_0 = qtgui.freq_sink_c(
+ 1024, #size
+ firdes.WIN_BLACKMAN_hARRIS, #wintype
+ 0, #fc
+ samp_rate, #bw
+ "Channel Input", #name
+ 1
+ )
+ self.qtgui_freq_sink_x_0.set_update_time(0.10)
+ self.qtgui_freq_sink_x_0.set_y_axis(-140, 10)
+ self.qtgui_freq_sink_x_0.set_y_label('Relative Gain', 'dB')
+ self.qtgui_freq_sink_x_0.set_trigger_mode(qtgui.TRIG_MODE_FREE, 0.0, 0, "")
+ self.qtgui_freq_sink_x_0.enable_autoscale(False)
+ self.qtgui_freq_sink_x_0.enable_grid(False)
+ self.qtgui_freq_sink_x_0.set_fft_average(1.0)
+ self.qtgui_freq_sink_x_0.enable_axis_labels(True)
+ self.qtgui_freq_sink_x_0.enable_control_panel(False)
+
+
+
+ labels = ['', '', '', '', '',
+ '', '', '', '', '']
+ widths = [1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1]
+ colors = ["blue", "red", "green", "black", "cyan",
+ "magenta", "yellow", "dark red", "dark green", "dark blue"]
+ alphas = [1.0, 1.0, 1.0, 1.0, 1.0,
+ 1.0, 1.0, 1.0, 1.0, 1.0]
+
+ for i in range(1):
+ if len(labels[i]) == 0:
+ self.qtgui_freq_sink_x_0.set_line_label(i, "Data {0}".format(i))
+ else:
+ self.qtgui_freq_sink_x_0.set_line_label(i, labels[i])
+ self.qtgui_freq_sink_x_0.set_line_width(i, widths[i])
+ self.qtgui_freq_sink_x_0.set_line_color(i, colors[i])
+ self.qtgui_freq_sink_x_0.set_line_alpha(i, alphas[i])
+
+ self._qtgui_freq_sink_x_0_win = sip.wrapinstance(self.qtgui_freq_sink_x_0.pyqwidget(), Qt.QWidget)
+ self.top_grid_layout.addWidget(self._qtgui_freq_sink_x_0_win, 3, 0, 1, 1)
+ for r in range(3, 4):
+ self.top_grid_layout.setRowStretch(r, 1)
+ for c in range(0, 1):
+ self.top_grid_layout.setColumnStretch(c, 1)
+ self.qtgui_const_sink_x_0_0 = qtgui.const_sink_c(
+ 2048, #size
+ "After Clock Sync", #name
+ 1 #number of inputs
+ )
+ self.qtgui_const_sink_x_0_0.set_update_time(0.10)
+ self.qtgui_const_sink_x_0_0.set_y_axis(-2, 2)
+ self.qtgui_const_sink_x_0_0.set_x_axis(-2, 2)
+ self.qtgui_const_sink_x_0_0.set_trigger_mode(qtgui.TRIG_MODE_FREE, qtgui.TRIG_SLOPE_POS, 0.0, 0, "")
+ self.qtgui_const_sink_x_0_0.enable_autoscale(False)
+ self.qtgui_const_sink_x_0_0.enable_grid(False)
+ self.qtgui_const_sink_x_0_0.enable_axis_labels(True)
+
+
+ labels = ['', '', '', '', '',
+ '', '', '', '', '']
+ widths = [1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1]
+ colors = ["blue", "red", "red", "red", "red",
+ "red", "red", "red", "red", "red"]
+ styles = [0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0]
+ markers = [0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0]
+ alphas = [1.0, 1.0, 1.0, 1.0, 1.0,
+ 1.0, 1.0, 1.0, 1.0, 1.0]
+
+ for i in range(1):
+ if len(labels[i]) == 0:
+ self.qtgui_const_sink_x_0_0.set_line_label(i, "Data {0}".format(i))
+ else:
+ self.qtgui_const_sink_x_0_0.set_line_label(i, labels[i])
+ self.qtgui_const_sink_x_0_0.set_line_width(i, widths[i])
+ self.qtgui_const_sink_x_0_0.set_line_color(i, colors[i])
+ self.qtgui_const_sink_x_0_0.set_line_style(i, styles[i])
+ self.qtgui_const_sink_x_0_0.set_line_marker(i, markers[i])
+ self.qtgui_const_sink_x_0_0.set_line_alpha(i, alphas[i])
+
+ self._qtgui_const_sink_x_0_0_win = sip.wrapinstance(self.qtgui_const_sink_x_0_0.pyqwidget(), Qt.QWidget)
+ self.top_grid_layout.addWidget(self._qtgui_const_sink_x_0_0_win, 3, 1, 1, 1)
+ for r in range(3, 4):
+ self.top_grid_layout.setRowStretch(r, 1)
+ for c in range(1, 2):
+ self.top_grid_layout.setColumnStretch(c, 1)
+ self.qtgui_const_sink_x_0 = qtgui.const_sink_c(
+ 2048, #size
+ "After Channel", #name
+ 1 #number of inputs
+ )
+ self.qtgui_const_sink_x_0.set_update_time(0.10)
+ self.qtgui_const_sink_x_0.set_y_axis(-2, 2)
+ self.qtgui_const_sink_x_0.set_x_axis(-2, 2)
+ self.qtgui_const_sink_x_0.set_trigger_mode(qtgui.TRIG_MODE_FREE, qtgui.TRIG_SLOPE_POS, 0.0, 0, "")
+ self.qtgui_const_sink_x_0.enable_autoscale(False)
+ self.qtgui_const_sink_x_0.enable_grid(False)
+ self.qtgui_const_sink_x_0.enable_axis_labels(True)
+
+
+ labels = ['', '', '', '', '',
+ '', '', '', '', '']
+ widths = [1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1]
+ colors = ["blue", "red", "red", "red", "red",
+ "red", "red", "red", "red", "red"]
+ styles = [0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0]
+ markers = [0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0]
+ alphas = [1.0, 1.0, 1.0, 1.0, 1.0,
+ 1.0, 1.0, 1.0, 1.0, 1.0]
+
+ for i in range(1):
+ if len(labels[i]) == 0:
+ self.qtgui_const_sink_x_0.set_line_label(i, "Data {0}".format(i))
+ else:
+ self.qtgui_const_sink_x_0.set_line_label(i, labels[i])
+ self.qtgui_const_sink_x_0.set_line_width(i, widths[i])
+ self.qtgui_const_sink_x_0.set_line_color(i, colors[i])
+ self.qtgui_const_sink_x_0.set_line_style(i, styles[i])
+ self.qtgui_const_sink_x_0.set_line_marker(i, markers[i])
+ self.qtgui_const_sink_x_0.set_line_alpha(i, alphas[i])
+
+ self._qtgui_const_sink_x_0_win = sip.wrapinstance(self.qtgui_const_sink_x_0.pyqwidget(), Qt.QWidget)
+ self.top_grid_layout.addWidget(self._qtgui_const_sink_x_0_win, 2, 1, 1, 1)
+ for r in range(2, 3):
+ self.top_grid_layout.setRowStretch(r, 1)
+ for c in range(1, 2):
+ self.top_grid_layout.setColumnStretch(c, 1)
+ self.digital_pfb_clock_sync_xxx_0 = digital.pfb_clock_sync_ccf(sps * 1.001, timing_loop_bw, rrc_taps, nfilts, nfilts/2, 1.5, 1)
+ self.digital_constellation_modulator_0 = digital.generic_mod(
+ constellation=qpsk_const,
+ differential=True,
+ samples_per_symbol=sps,
+ pre_diff_code=True,
+ excess_bw=excess_bw,
+ verbose=False,
+ log=False)
+ self.channels_channel_model_0 = channels.channel_model(
+ noise_voltage=noise_volt,
+ frequency_offset=freq_offset,
+ epsilon=time_offset,
+ taps=taps,
+ noise_seed=0,
+ block_tags=False)
+ self.blocks_throttle_0 = blocks.throttle(gr.sizeof_gr_complex*1, samp_rate,True)
+ self.analog_random_source_x_0 = blocks.vector_source_b(list(map(int, numpy.random.randint(0, 2, 1000))), True)
+
+
+
+ ##################################################
+ # Connections
+ ##################################################
+ self.connect((self.analog_random_source_x_0, 0), (self.digital_constellation_modulator_0, 0))
+ self.connect((self.blocks_throttle_0, 0), (self.channels_channel_model_0, 0))
+ self.connect((self.channels_channel_model_0, 0), (self.digital_pfb_clock_sync_xxx_0, 0))
+ self.connect((self.channels_channel_model_0, 0), (self.qtgui_const_sink_x_0, 0))
+ self.connect((self.channels_channel_model_0, 0), (self.qtgui_freq_sink_x_0, 0))
+ self.connect((self.channels_channel_model_0, 0), (self.qtgui_time_sink_x_0, 0))
+ self.connect((self.digital_constellation_modulator_0, 0), (self.blocks_throttle_0, 0))
+ self.connect((self.digital_pfb_clock_sync_xxx_0, 0), (self.qtgui_const_sink_x_0_0, 0))
+
+
+ def closeEvent(self, event):
+ self.settings = Qt.QSettings("GNU Radio", "qpks")
+ self.settings.setValue("geometry", self.saveGeometry())
+ event.accept()
+
+ def get_sps(self):
+ return self.sps
+
+ def set_sps(self, sps):
+ self.sps = sps
+ self.set_rrc_taps(firdes.root_raised_cosine(self.nfilts, self.nfilts, 1.0/float(self.sps), 0.35, 45*self.nfilts))
+
+ def get_nfilts(self):
+ return self.nfilts
+
+ def set_nfilts(self, nfilts):
+ self.nfilts = nfilts
+ self.set_rrc_taps(firdes.root_raised_cosine(self.nfilts, self.nfilts, 1.0/float(self.sps), 0.35, 45*self.nfilts))
+
+ def get_timing_loop_bw(self):
+ return self.timing_loop_bw
+
+ def set_timing_loop_bw(self, timing_loop_bw):
+ self.timing_loop_bw = timing_loop_bw
+ self.digital_pfb_clock_sync_xxx_0.set_loop_bandwidth(self.timing_loop_bw)
+
+ def get_time_offset(self):
+ return self.time_offset
+
+ def set_time_offset(self, time_offset):
+ self.time_offset = time_offset
+ self.channels_channel_model_0.set_timing_offset(self.time_offset)
+
+ def get_taps(self):
+ return self.taps
+
+ def set_taps(self, taps):
+ self.taps = taps
+ self.channels_channel_model_0.set_taps(self.taps)
+
+ def get_samp_rate(self):
+ return self.samp_rate
+
+ def set_samp_rate(self, samp_rate):
+ self.samp_rate = samp_rate
+ self.blocks_throttle_0.set_sample_rate(self.samp_rate)
+ self.qtgui_freq_sink_x_0.set_frequency_range(0, self.samp_rate)
+ self.qtgui_time_sink_x_0.set_samp_rate(self.samp_rate)
+
+ def get_rrc_taps(self):
+ return self.rrc_taps
+
+ def set_rrc_taps(self, rrc_taps):
+ self.rrc_taps = rrc_taps
+ self.digital_pfb_clock_sync_xxx_0.update_taps(self.rrc_taps)
+
+ def get_qpsk_const(self):
+ return self.qpsk_const
+
+ def set_qpsk_const(self, qpsk_const):
+ self.qpsk_const = qpsk_const
+
+ def get_noise_volt(self):
+ return self.noise_volt
+
+ def set_noise_volt(self, noise_volt):
+ self.noise_volt = noise_volt
+ self.channels_channel_model_0.set_noise_voltage(self.noise_volt)
+
+ def get_freq_offset(self):
+ return self.freq_offset
+
+ def set_freq_offset(self, freq_offset):
+ self.freq_offset = freq_offset
+ self.channels_channel_model_0.set_frequency_offset(self.freq_offset)
+
+ def get_excess_bw(self):
+ return self.excess_bw
+
+ def set_excess_bw(self, excess_bw):
+ self.excess_bw = excess_bw
+
+
+
+
+
+def main(top_block_cls=qpks, options=None):
+ if gr.enable_realtime_scheduling() != gr.RT_OK:
+ print("Error: failed to enable real-time scheduling.")
+
+ if StrictVersion("4.5.0") <= StrictVersion(Qt.qVersion()) < StrictVersion("5.0.0"):
+ style = gr.prefs().get_string('qtgui', 'style', 'raster')
+ Qt.QApplication.setGraphicsSystem(style)
+ qapp = Qt.QApplication(sys.argv)
+
+ tb = top_block_cls()
+
+ tb.start()
+
+ tb.show()
+
+ def sig_handler(sig=None, frame=None):
+ Qt.QApplication.quit()
+
+ signal.signal(signal.SIGINT, sig_handler)
+ signal.signal(signal.SIGTERM, sig_handler)
+
+ timer = Qt.QTimer()
+ timer.start(500)
+ timer.timeout.connect(lambda: None)
+
+ def quitting():
+ tb.stop()
+ tb.wait()
+
+ qapp.aboutToQuit.connect(quitting)
+ qapp.exec_()
+
+if __name__ == '__main__':
+ main()