From 30a6bf47ac6e13e9060b89456200647f2aa92d1d Mon Sep 17 00:00:00 2001 From: Nao Pross Date: Thu, 14 Oct 2021 16:39:49 +0200 Subject: Add Equalizer and Phase + Freq. correction to QPKS simulation Continuing the work of commit 20e54b3cf198f17e05a3c7e8716138717447aa32 Important: - The diagram has been updated to include a CMA equalizer and a costas loop (for phase correction and small frequency correction). TODO: - Decode the signal - Create USRP hardware sinks (RX side, for later) It would be very nice if we manage to find a 'switch' block that allows to have in a single flow diagram both the simulated and "real" signals. NOTE: recall that the USRP gives directly a baseband signal, which means that everything between the channel the costas loop (both included) will not be used when the hardware is connected. Only the (not yet) implemented decoder (and eventually some more filters if needed) will be used. Other notes: - The layout has been updated to use QT Tab widgets (defined on the top left corner). GUI elements can be put into tabs by giving a string '@: ' as GUI hint. - To make the diagram nicer, all GUI sinks (eg. constellations plots of time / freq. plots) are vertically aligned. Constellation above, and time and freq. sinks below. Variables ought to be placed near their respective block, unless they are global, in which case they should go on the top left. --- tests/Simulation/QPKS/qpks.py | 303 +++++++++++++++++++++++++++++------------- 1 file changed, 208 insertions(+), 95 deletions(-) (limited to 'tests/Simulation/QPKS/qpks.py') diff --git a/tests/Simulation/QPKS/qpks.py b/tests/Simulation/QPKS/qpks.py index 4027eb3..c8d5f82 100755 --- a/tests/Simulation/QPKS/qpks.py +++ b/tests/Simulation/QPKS/qpks.py @@ -6,6 +6,7 @@ # # GNU Radio Python Flow Graph # Title: QPSK +# Author: Pross Naoki, Halter Sara Cinzia # GNU Radio version: 3.8.2.0 from distutils.version import StrictVersion @@ -78,106 +79,99 @@ class qpks(gr.top_block, Qt.QWidget): 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.phase_bw = phase_bw = 2 * 3.141592653589793 / 100 self.noise_volt = noise_volt = 0.0001 self.freq_offset = freq_offset = 0 self.excess_bw = excess_bw = 350e-3 + self.eq_ntaps = eq_ntaps = 15 + self.eq_mod = eq_mod = 1 + self.eq_gain = eq_gain = .01 + self.chn_taps = chn_taps = [1.0 + 0.0j, ] ################################################## # Blocks ################################################## + self.params = Qt.QTabWidget() + self.params_widget_0 = Qt.QWidget() + self.params_layout_0 = Qt.QBoxLayout(Qt.QBoxLayout.TopToBottom, self.params_widget_0) + self.params_grid_layout_0 = Qt.QGridLayout() + self.params_layout_0.addLayout(self.params_grid_layout_0) + self.params.addTab(self.params_widget_0, 'Channel') + self.params_widget_1 = Qt.QWidget() + self.params_layout_1 = Qt.QBoxLayout(Qt.QBoxLayout.TopToBottom, self.params_widget_1) + self.params_grid_layout_1 = Qt.QGridLayout() + self.params_layout_1.addLayout(self.params_grid_layout_1) + self.params.addTab(self.params_widget_1, 'Receiver') + self.top_grid_layout.addWidget(self.params) 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) + self._timing_loop_bw_win = RangeWidget(self._timing_loop_bw_range, self.set_timing_loop_bw, 'Time Bandwidth', "counter_slider", float) + self.params_grid_layout_0.addWidget(self._timing_loop_bw_win, 1, 1, 1, 1) for r in range(1, 2): - self.top_grid_layout.setRowStretch(r, 1) + self.params_grid_layout_0.setRowStretch(r, 1) for c in range(1, 2): - self.top_grid_layout.setColumnStretch(c, 1) + self.params_grid_layout_0.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) + self.params_grid_layout_0.addWidget(self._time_offset_win, 0, 1, 1, 1) for r in range(0, 1): - self.top_grid_layout.setRowStretch(r, 1) + self.params_grid_layout_0.setRowStretch(r, 1) for c in range(1, 2): - self.top_grid_layout.setColumnStretch(c, 1) + self.params_grid_layout_0.setColumnStretch(c, 1) + self.plots = Qt.QTabWidget() + self.plots_widget_0 = Qt.QWidget() + self.plots_layout_0 = Qt.QBoxLayout(Qt.QBoxLayout.TopToBottom, self.plots_widget_0) + self.plots_grid_layout_0 = Qt.QGridLayout() + self.plots_layout_0.addLayout(self.plots_grid_layout_0) + self.plots.addTab(self.plots_widget_0, 'Constellations') + self.plots_widget_1 = Qt.QWidget() + self.plots_layout_1 = Qt.QBoxLayout(Qt.QBoxLayout.TopToBottom, self.plots_widget_1) + self.plots_grid_layout_1 = Qt.QGridLayout() + self.plots_layout_1.addLayout(self.plots_grid_layout_1) + self.plots.addTab(self.plots_widget_1, 'Frequency') + self.plots_widget_2 = Qt.QWidget() + self.plots_layout_2 = Qt.QBoxLayout(Qt.QBoxLayout.TopToBottom, self.plots_widget_2) + self.plots_grid_layout_2 = Qt.QGridLayout() + self.plots_layout_2.addLayout(self.plots_grid_layout_2) + self.plots.addTab(self.plots_widget_2, 'Time') + self.top_grid_layout.addWidget(self.plots) + self._phase_bw_range = Range(0, 1, .01, 2 * 3.141592653589793 / 100, 200) + self._phase_bw_win = RangeWidget(self._phase_bw_range, self.set_phase_bw, 'Phase Bandwidth', "counter_slider", float) + self.params_grid_layout_1.addWidget(self._phase_bw_win, 1, 0, 1, 1) + for r in range(1, 2): + self.params_grid_layout_1.setRowStretch(r, 1) + for c in range(0, 1): + self.params_grid_layout_1.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) + self.params_grid_layout_0.addWidget(self._noise_volt_win, 0, 0, 1, 1) for r in range(0, 1): - self.top_grid_layout.setRowStretch(r, 1) + self.params_grid_layout_0.setRowStretch(r, 1) for c in range(0, 1): - self.top_grid_layout.setColumnStretch(c, 1) + self.params_grid_layout_0.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) + self.params_grid_layout_0.addWidget(self._freq_offset_win, 1, 0, 1, 1) for r in range(1, 2): - self.top_grid_layout.setRowStretch(r, 1) + self.params_grid_layout_0.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) + self.params_grid_layout_0.setColumnStretch(c, 1) + self._eq_gain_range = Range(0, .1, .001, .01, 200) + self._eq_gain_win = RangeWidget(self._eq_gain_range, self.set_eq_gain, 'Equalizer Rate', "counter_slider", float) + self.params_grid_layout_1.addWidget(self._eq_gain_win, 0, 0, 1, 1) + for r in range(0, 1): + self.params_grid_layout_1.setRowStretch(r, 1) for c in range(0, 1): - self.top_grid_layout.setColumnStretch(c, 1) + self.params_grid_layout_1.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 + "Channel", #name 1 ) self.qtgui_freq_sink_x_0.set_update_time(0.10) @@ -211,14 +205,102 @@ class qpks(gr.top_block, Qt.QWidget): 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) + self.plots_grid_layout_1.addWidget(self._qtgui_freq_sink_x_0_win, 0, 0, 1, 1) + for r in range(0, 1): + self.plots_grid_layout_1.setRowStretch(r, 1) + for c in range(0, 1): + self.plots_grid_layout_1.setColumnStretch(c, 1) + self.qtgui_const_sink_x_2 = qtgui.const_sink_c( + 1024, #size + "Locked", #name + 1 #number of inputs + ) + self.qtgui_const_sink_x_2.set_update_time(0.10) + self.qtgui_const_sink_x_2.set_y_axis(-2, 2) + self.qtgui_const_sink_x_2.set_x_axis(-2, 2) + self.qtgui_const_sink_x_2.set_trigger_mode(qtgui.TRIG_MODE_FREE, qtgui.TRIG_SLOPE_POS, 0.0, 0, "") + self.qtgui_const_sink_x_2.enable_autoscale(False) + self.qtgui_const_sink_x_2.enable_grid(False) + self.qtgui_const_sink_x_2.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_2.set_line_label(i, "Data {0}".format(i)) + else: + self.qtgui_const_sink_x_2.set_line_label(i, labels[i]) + self.qtgui_const_sink_x_2.set_line_width(i, widths[i]) + self.qtgui_const_sink_x_2.set_line_color(i, colors[i]) + self.qtgui_const_sink_x_2.set_line_style(i, styles[i]) + self.qtgui_const_sink_x_2.set_line_marker(i, markers[i]) + self.qtgui_const_sink_x_2.set_line_alpha(i, alphas[i]) + + self._qtgui_const_sink_x_2_win = sip.wrapinstance(self.qtgui_const_sink_x_2.pyqwidget(), Qt.QWidget) + self.plots_grid_layout_0.addWidget(self._qtgui_const_sink_x_2_win, 1, 1, 1, 1) + for r in range(1, 2): + self.plots_grid_layout_0.setRowStretch(r, 1) + for c in range(1, 2): + self.plots_grid_layout_0.setColumnStretch(c, 1) + self.qtgui_const_sink_x_1 = qtgui.const_sink_c( + 1024, #size + "Equalized", #name + 1 #number of inputs + ) + self.qtgui_const_sink_x_1.set_update_time(0.10) + self.qtgui_const_sink_x_1.set_y_axis(-2, 2) + self.qtgui_const_sink_x_1.set_x_axis(-2, 2) + self.qtgui_const_sink_x_1.set_trigger_mode(qtgui.TRIG_MODE_FREE, qtgui.TRIG_SLOPE_POS, 0.0, 0, "") + self.qtgui_const_sink_x_1.enable_autoscale(False) + self.qtgui_const_sink_x_1.enable_grid(False) + self.qtgui_const_sink_x_1.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_1.set_line_label(i, "Data {0}".format(i)) + else: + self.qtgui_const_sink_x_1.set_line_label(i, labels[i]) + self.qtgui_const_sink_x_1.set_line_width(i, widths[i]) + self.qtgui_const_sink_x_1.set_line_color(i, colors[i]) + self.qtgui_const_sink_x_1.set_line_style(i, styles[i]) + self.qtgui_const_sink_x_1.set_line_marker(i, markers[i]) + self.qtgui_const_sink_x_1.set_line_alpha(i, alphas[i]) + + self._qtgui_const_sink_x_1_win = sip.wrapinstance(self.qtgui_const_sink_x_1.pyqwidget(), Qt.QWidget) + self.plots_grid_layout_0.addWidget(self._qtgui_const_sink_x_1_win, 1, 0, 1, 1) + for r in range(1, 2): + self.plots_grid_layout_0.setRowStretch(r, 1) for c in range(0, 1): - self.top_grid_layout.setColumnStretch(c, 1) + self.plots_grid_layout_0.setColumnStretch(c, 1) self.qtgui_const_sink_x_0_0 = qtgui.const_sink_c( 2048, #size - "After Clock Sync", #name + "Synchronized", #name 1 #number of inputs ) self.qtgui_const_sink_x_0_0.set_update_time(0.10) @@ -255,14 +337,14 @@ class qpks(gr.top_block, Qt.QWidget): 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) + self.plots_grid_layout_0.addWidget(self._qtgui_const_sink_x_0_0_win, 0, 1, 1, 1) + for r in range(0, 1): + self.plots_grid_layout_0.setRowStretch(r, 1) for c in range(1, 2): - self.top_grid_layout.setColumnStretch(c, 1) + self.plots_grid_layout_0.setColumnStretch(c, 1) self.qtgui_const_sink_x_0 = qtgui.const_sink_c( 2048, #size - "After Channel", #name + "Channel", #name 1 #number of inputs ) self.qtgui_const_sink_x_0.set_update_time(0.10) @@ -299,12 +381,13 @@ class qpks(gr.top_block, Qt.QWidget): 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.plots_grid_layout_0.addWidget(self._qtgui_const_sink_x_0_win, 0, 0, 1, 1) + for r in range(0, 1): + self.plots_grid_layout_0.setRowStretch(r, 1) + for c in range(0, 1): + self.plots_grid_layout_0.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, 2) + self.digital_costas_loop_cc_0 = digital.costas_loop_cc(phase_bw, 4, False) self.digital_constellation_modulator_0 = digital.generic_mod( constellation=qpsk_const, differential=True, @@ -313,15 +396,16 @@ class qpks(gr.top_block, Qt.QWidget): excess_bw=excess_bw, verbose=False, log=False) + self.digital_cma_equalizer_cc_0 = digital.cma_equalizer_cc(eq_ntaps, eq_mod, eq_gain, 2) self.channels_channel_model_0 = channels.channel_model( noise_voltage=noise_volt, frequency_offset=freq_offset, epsilon=time_offset, - taps=taps, + taps=chn_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) + self.analog_random_source_x_0 = blocks.vector_source_b(list(map(int, numpy.random.randint(0, 256, 1000))), True) @@ -333,8 +417,11 @@ class qpks(gr.top_block, Qt.QWidget): 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_cma_equalizer_cc_0, 0), (self.digital_costas_loop_cc_0, 0)) + self.connect((self.digital_cma_equalizer_cc_0, 0), (self.qtgui_const_sink_x_1, 0)) self.connect((self.digital_constellation_modulator_0, 0), (self.blocks_throttle_0, 0)) + self.connect((self.digital_costas_loop_cc_0, 0), (self.qtgui_const_sink_x_2, 0)) + self.connect((self.digital_pfb_clock_sync_xxx_0, 0), (self.digital_cma_equalizer_cc_0, 0)) self.connect((self.digital_pfb_clock_sync_xxx_0, 0), (self.qtgui_const_sink_x_0_0, 0)) @@ -371,13 +458,6 @@ class qpks(gr.top_block, Qt.QWidget): 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 @@ -385,7 +465,6 @@ class qpks(gr.top_block, Qt.QWidget): 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 @@ -400,6 +479,13 @@ class qpks(gr.top_block, Qt.QWidget): def set_qpsk_const(self, qpsk_const): self.qpsk_const = qpsk_const + def get_phase_bw(self): + return self.phase_bw + + def set_phase_bw(self, phase_bw): + self.phase_bw = phase_bw + self.digital_costas_loop_cc_0.set_loop_bandwidth(self.phase_bw) + def get_noise_volt(self): return self.noise_volt @@ -420,6 +506,33 @@ class qpks(gr.top_block, Qt.QWidget): def set_excess_bw(self, excess_bw): self.excess_bw = excess_bw + def get_eq_ntaps(self): + return self.eq_ntaps + + def set_eq_ntaps(self, eq_ntaps): + self.eq_ntaps = eq_ntaps + + def get_eq_mod(self): + return self.eq_mod + + def set_eq_mod(self, eq_mod): + self.eq_mod = eq_mod + self.digital_cma_equalizer_cc_0.set_modulus(self.eq_mod) + + def get_eq_gain(self): + return self.eq_gain + + def set_eq_gain(self, eq_gain): + self.eq_gain = eq_gain + self.digital_cma_equalizer_cc_0.set_gain(self.eq_gain) + + def get_chn_taps(self): + return self.chn_taps + + def set_chn_taps(self, chn_taps): + self.chn_taps = chn_taps + self.channels_channel_model_0.set_taps(self.chn_taps) + -- cgit v1.2.1