From 30a6bf47ac6e13e9060b89456200647f2aa92d1d Mon Sep 17 00:00:00 2001
From: Nao Pross <np@0hm.ch>
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 '<tab name>@<tab nr>: <grid options>' 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.grc | 535 ++++++++++++++++++++++++++++++-----------
 tests/Simulation/QPKS/qpks.py  | 303 +++++++++++++++--------
 2 files changed, 606 insertions(+), 232 deletions(-)

(limited to 'tests/Simulation/QPKS')

diff --git a/tests/Simulation/QPKS/qpks.grc b/tests/Simulation/QPKS/qpks.grc
index b799dc7..cf3454a 100644
--- a/tests/Simulation/QPKS/qpks.grc
+++ b/tests/Simulation/QPKS/qpks.grc
@@ -1,6 +1,6 @@
 options:
   parameters:
-    author: ''
+    author: Pross Naoki, Halter Sara Cinzia
     category: '[GRC Hier Blocks]'
     cmake_opt: ''
     comment: ''
@@ -32,6 +32,63 @@ options:
     state: enabled
 
 blocks:
+- name: chn_taps
+  id: variable
+  parameters:
+    comment: ''
+    value: '[1.0 + 0.0j, ]'
+  states:
+    bus_sink: false
+    bus_source: false
+    bus_structure: null
+    coordinate: [640, 252.0]
+    rotation: 0
+    state: true
+- name: eq_gain
+  id: variable_qtgui_range
+  parameters:
+    comment: ''
+    gui_hint: 'params@1: 0,0,1,1'
+    label: Equalizer Rate
+    min_len: '200'
+    orient: Qt.Horizontal
+    rangeType: float
+    start: '0'
+    step: '.001'
+    stop: '.1'
+    value: '.01'
+    widget: counter_slider
+  states:
+    bus_sink: false
+    bus_source: false
+    bus_structure: null
+    coordinate: [1336, 460.0]
+    rotation: 0
+    state: true
+- name: eq_mod
+  id: variable
+  parameters:
+    comment: ''
+    value: '1'
+  states:
+    bus_sink: false
+    bus_source: false
+    bus_structure: null
+    coordinate: [1336, 388.0]
+    rotation: 0
+    state: true
+- name: eq_ntaps
+  id: variable
+  parameters:
+    comment: ''
+    value: '15'
+  states:
+    bus_sink: false
+    bus_source: false
+    bus_structure: null
+    coordinate: [1416, 388.0]
+    rotation: 0
+    state: true
 - name: excess_bw
   id: variable
   parameters:
@@ -41,14 +98,14 @@ blocks:
     bus_sink: false
     bus_source: false
     bus_structure: null
-    coordinate: [320, 140.0]
+    coordinate: [320, 268.0]
     rotation: 0
     state: true
 - name: freq_offset
   id: variable_qtgui_range
   parameters:
     comment: ''
-    gui_hint: 1,0,1,1
+    gui_hint: 'params@0: 1,0,1,1'
     label: Frequency Offset
     min_len: '200'
     orient: Qt.Horizontal
@@ -62,7 +119,7 @@ blocks:
     bus_sink: false
     bus_source: false
     bus_structure: null
-    coordinate: [648, 340.0]
+    coordinate: [640, 460.0]
     rotation: 0
     state: true
 - name: nfilts
@@ -74,14 +131,14 @@ blocks:
     bus_sink: false
     bus_source: false
     bus_structure: null
-    coordinate: [920, 540.0]
+    coordinate: [1008, 476.0]
     rotation: 0
     state: true
 - name: noise_volt
   id: variable_qtgui_range
   parameters:
     comment: ''
-    gui_hint: 0,0,1,1
+    gui_hint: 'params@0: 0,0,1,1'
     label: Noise Voltage
     min_len: '200'
     orient: Qt.Horizontal
@@ -95,7 +152,28 @@ blocks:
     bus_sink: false
     bus_source: false
     bus_structure: null
-    coordinate: [488, 340.0]
+    coordinate: [504, 460.0]
+    rotation: 0
+    state: true
+- name: phase_bw
+  id: variable_qtgui_range
+  parameters:
+    comment: ''
+    gui_hint: 'params@1: 1,0,1,1'
+    label: Phase Bandwidth
+    min_len: '200'
+    orient: Qt.Horizontal
+    rangeType: float
+    start: '0'
+    step: '.01'
+    stop: '1'
+    value: 2 * 3.141592653589793 / 100
+    widget: counter_slider
+  states:
+    bus_sink: false
+    bus_source: false
+    bus_structure: null
+    coordinate: [1640, 428.0]
     rotation: 0
     state: true
 - name: qpsk_const
@@ -115,7 +193,7 @@ blocks:
     bus_sink: false
     bus_source: false
     bus_structure: null
-    coordinate: [224, 316.0]
+    coordinate: [224, 444.0]
     rotation: 0
     state: true
 - name: rrc_taps
@@ -127,7 +205,7 @@ blocks:
     bus_sink: false
     bus_source: false
     bus_structure: null
-    coordinate: [992, 540.0]
+    coordinate: [1080, 476.0]
     rotation: 0
     state: true
 - name: samp_rate
@@ -151,26 +229,14 @@ blocks:
     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]
+    coordinate: [224, 268.0]
     rotation: 0
     state: true
 - name: time_offset
   id: variable_qtgui_range
   parameters:
     comment: ''
-    gui_hint: 0,1,1,1
+    gui_hint: 'params@0: 0,1,1,1'
     label: Timing Offset
     min_len: '200'
     orient: Qt.Horizontal
@@ -184,15 +250,15 @@ blocks:
     bus_sink: false
     bus_source: false
     bus_structure: null
-    coordinate: [488, 484.0]
+    coordinate: [504, 604.0]
     rotation: 0
     state: true
 - name: timing_loop_bw
   id: variable_qtgui_range
   parameters:
     comment: ''
-    gui_hint: 1,1,1,1
-    label: 'Time: BW'
+    gui_hint: 'params@0: 1,1,1,1'
+    label: Time Bandwidth
     min_len: '200'
     orient: Qt.Horizontal
     rangeType: float
@@ -205,7 +271,7 @@ blocks:
     bus_sink: false
     bus_source: false
     bus_structure: null
-    coordinate: [648, 484.0]
+    coordinate: [640, 604.0]
     rotation: 0
     state: true
 - name: analog_random_source_x_0
@@ -214,7 +280,7 @@ blocks:
     affinity: ''
     alias: ''
     comment: ''
-    max: '2'
+    max: '256'
     maxoutbuf: '0'
     min: '0'
     minoutbuf: '0'
@@ -225,7 +291,7 @@ blocks:
     bus_sink: false
     bus_source: false
     bus_structure: null
-    coordinate: [32, 204.0]
+    coordinate: [32, 332.0]
     rotation: 0
     state: enabled
 - name: blocks_throttle_0
@@ -244,7 +310,7 @@ blocks:
     bus_sink: false
     bus_source: false
     bus_structure: null
-    coordinate: [464, 228.0]
+    coordinate: [464, 356.0]
     rotation: 0
     state: enabled
 - name: channels_channel_model_0
@@ -260,14 +326,33 @@ blocks:
     minoutbuf: '0'
     noise_voltage: noise_volt
     seed: '0'
-    taps: taps
+    taps: chn_taps
   states:
     bus_sink: false
     bus_source: false
     bus_structure: null
-    coordinate: [648, 188.0]
+    coordinate: [640, 316.0]
     rotation: 0
     state: enabled
+- name: digital_cma_equalizer_cc_0
+  id: digital_cma_equalizer_cc
+  parameters:
+    affinity: ''
+    alias: ''
+    comment: ''
+    maxoutbuf: '0'
+    minoutbuf: '0'
+    modulus: eq_mod
+    mu: eq_gain
+    num_taps: eq_ntaps
+    sps: '2'
+  states:
+    bus_sink: false
+    bus_source: false
+    bus_structure: null
+    coordinate: [1336, 284.0]
+    rotation: 0
+    state: true
 - name: digital_constellation_modulator_0
   id: digital_constellation_modulator
   parameters:
@@ -286,9 +371,27 @@ blocks:
     bus_sink: false
     bus_source: false
     bus_structure: null
-    coordinate: [224, 204.0]
+    coordinate: [224, 332.0]
     rotation: 0
     state: enabled
+- name: digital_costas_loop_cc_0
+  id: digital_costas_loop_cc
+  parameters:
+    affinity: ''
+    alias: ''
+    comment: ''
+    maxoutbuf: '0'
+    minoutbuf: '0'
+    order: '4'
+    use_snr: 'False'
+    w: phase_bw
+  states:
+    bus_sink: false
+    bus_source: false
+    bus_structure: null
+    coordinate: [1640, 280.0]
+    rotation: 0
+    state: true
 - name: digital_pfb_clock_sync_xxx_0
   id: digital_pfb_clock_sync_xxx
   parameters:
@@ -301,7 +404,7 @@ blocks:
     max_dev: '1.5'
     maxoutbuf: '0'
     minoutbuf: '0'
-    osps: '1'
+    osps: '2'
     sps: sps * 1.001
     taps: rrc_taps
     type: ccf
@@ -309,7 +412,75 @@ blocks:
     bus_sink: false
     bus_source: false
     bus_structure: null
-    coordinate: [920, 380.0]
+    coordinate: [1000, 308.0]
+    rotation: 0
+    state: true
+- name: params
+  id: qtgui_tab_widget
+  parameters:
+    alias: ''
+    comment: ''
+    gui_hint: ''
+    label0: Channel
+    label1: Receiver
+    label10: Tab 10
+    label11: Tab 11
+    label12: Tab 12
+    label13: Tab 13
+    label14: Tab 14
+    label15: Tab 15
+    label16: Tab 16
+    label17: Tab 17
+    label18: Tab 18
+    label19: Tab 19
+    label2: Tab 2
+    label3: Tab 3
+    label4: Tab 4
+    label5: Tab 5
+    label6: Tab 6
+    label7: Tab 7
+    label8: Tab 8
+    label9: Tab 9
+    num_tabs: '2'
+  states:
+    bus_sink: false
+    bus_source: false
+    bus_structure: null
+    coordinate: [296, 12.0]
+    rotation: 0
+    state: true
+- name: plots
+  id: qtgui_tab_widget
+  parameters:
+    alias: ''
+    comment: ''
+    gui_hint: ''
+    label0: Constellations
+    label1: Frequency
+    label10: Tab 10
+    label11: Tab 11
+    label12: Tab 12
+    label13: Tab 13
+    label14: Tab 14
+    label15: Tab 15
+    label16: Tab 16
+    label17: Tab 17
+    label18: Tab 18
+    label19: Tab 19
+    label2: Time
+    label3: Tab 3
+    label4: Tab 4
+    label5: Tab 5
+    label6: Tab 6
+    label7: Tab 7
+    label8: Tab 8
+    label9: Tab 9
+    num_tabs: '3'
+  states:
+    bus_sink: false
+    bus_source: false
+    bus_structure: null
+    coordinate: [448, 12.0]
     rotation: 0
     state: true
 - name: qtgui_const_sink_x_0
@@ -341,7 +512,7 @@ blocks:
     color9: '"red"'
     comment: ''
     grid: 'False'
-    gui_hint: 2,1,1,1
+    gui_hint: 'plots@0: 0,0,1,1'
     label1: ''
     label10: ''
     label2: ''
@@ -363,7 +534,7 @@ blocks:
     marker7: '0'
     marker8: '0'
     marker9: '0'
-    name: '"After Channel"'
+    name: '"Channel"'
     nconnections: '1'
     size: '2048'
     style1: '0'
@@ -401,8 +572,8 @@ blocks:
     bus_sink: false
     bus_source: false
     bus_structure: null
-    coordinate: [920, 284.0]
-    rotation: 0
+    coordinate: [836.0, 128]
+    rotation: 90
     state: enabled
 - name: qtgui_const_sink_x_0_0
   id: qtgui_const_sink_x
@@ -433,7 +604,7 @@ blocks:
     color9: '"red"'
     comment: ''
     grid: 'False'
-    gui_hint: 3,1,1,1
+    gui_hint: 'plots@0: 0,1,1,1'
     label1: ''
     label10: ''
     label2: ''
@@ -455,7 +626,7 @@ blocks:
     marker7: '0'
     marker8: '0'
     marker9: '0'
-    name: '"After Clock Sync"'
+    name: '"Synchronized"'
     nconnections: '1'
     size: '2048'
     style1: '0'
@@ -493,11 +664,11 @@ blocks:
     bus_sink: false
     bus_source: false
     bus_structure: null
-    coordinate: [1200, 364.0]
-    rotation: 0
+    coordinate: [1228.0, 88]
+    rotation: 90
     state: enabled
-- name: qtgui_freq_sink_x_0
-  id: qtgui_freq_sink_x
+- name: qtgui_const_sink_x_1
+  id: qtgui_const_sink_x
   parameters:
     affinity: ''
     alias: ''
@@ -512,49 +683,60 @@ blocks:
     alpha8: '1.0'
     alpha9: '1.0'
     autoscale: 'False'
-    average: '1.0'
     axislabels: 'True'
-    bw: samp_rate
     color1: '"blue"'
-    color10: '"dark blue"'
+    color10: '"red"'
     color2: '"red"'
-    color3: '"green"'
-    color4: '"black"'
-    color5: '"cyan"'
-    color6: '"magenta"'
-    color7: '"yellow"'
-    color8: '"dark red"'
-    color9: '"dark green"'
+    color3: '"red"'
+    color4: '"red"'
+    color5: '"red"'
+    color6: '"red"'
+    color7: '"red"'
+    color8: '"red"'
+    color9: '"red"'
     comment: ''
-    ctrlpanel: 'False'
-    fc: '0'
-    fftsize: '1024'
-    freqhalf: 'True'
     grid: 'False'
-    gui_hint: 3,0,1,1
-    label: Relative Gain
+    gui_hint: 'plots@0: 1,0,1,1'
     label1: ''
-    label10: ''''''
-    label2: ''''''
-    label3: ''''''
-    label4: ''''''
-    label5: ''''''
-    label6: ''''''
-    label7: ''''''
-    label8: ''''''
-    label9: ''''''
+    label10: ''
+    label2: ''
+    label3: ''
+    label4: ''
+    label5: ''
+    label6: ''
+    label7: ''
+    label8: ''
+    label9: ''
     legend: 'True'
-    maxoutbuf: '0'
-    minoutbuf: '0'
-    name: '"Channel Input"'
+    marker1: '0'
+    marker10: '0'
+    marker2: '0'
+    marker3: '0'
+    marker4: '0'
+    marker5: '0'
+    marker6: '0'
+    marker7: '0'
+    marker8: '0'
+    marker9: '0'
+    name: '"Equalized"'
     nconnections: '1'
-    showports: 'False'
+    size: '1024'
+    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
-    units: dB
     update_time: '0.10'
     width1: '1'
     width10: '1'
@@ -566,18 +748,19 @@ blocks:
     width7: '1'
     width8: '1'
     width9: '1'
-    wintype: firdes.WIN_BLACKMAN_hARRIS
-    ymax: '10'
-    ymin: '-140'
+    xmax: '2'
+    xmin: '-2'
+    ymax: '2'
+    ymin: '-2'
   states:
     bus_sink: false
     bus_source: false
     bus_structure: null
-    coordinate: [920, 56.0]
-    rotation: 0
+    coordinate: [1524.0, 88]
+    rotation: 90
     state: true
-- name: qtgui_time_sink_x_0
-  id: qtgui_time_sink_x
+- name: qtgui_const_sink_x_2
+  id: qtgui_const_sink_x
   parameters:
     affinity: ''
     alias: ''
@@ -593,59 +776,54 @@ blocks:
     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
+    color1: '"blue"'
+    color10: '"red"'
+    color2: '"red"'
+    color3: '"red"'
+    color4: '"red"'
+    color5: '"red"'
+    color6: '"red"'
+    color7: '"red"'
+    color8: '"red"'
+    color9: '"red"'
     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
+    gui_hint: 'plots@0: 1,1,1,1'
+    label1: ''
+    label10: ''
+    label2: ''
+    label3: ''
+    label4: ''
+    label5: ''
+    label6: ''
+    label7: ''
+    label8: ''
+    label9: ''
     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"'
+    marker1: '0'
+    marker10: '0'
+    marker2: '0'
+    marker3: '0'
+    marker4: '0'
+    marker5: '0'
+    marker6: '0'
+    marker7: '0'
+    marker8: '0'
+    marker9: '0'
+    name: '"Locked"'
     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'
+    style1: '0'
+    style10: '0'
+    style2: '0'
+    style3: '0'
+    style4: '0'
+    style5: '0'
+    style6: '0'
+    style7: '0'
+    style8: '0'
+    style9: '0'
     tr_chan: '0'
-    tr_delay: '0'
     tr_level: '0.0'
     tr_mode: qtgui.TRIG_MODE_FREE
     tr_slope: qtgui.TRIG_SLOPE_POS
@@ -662,17 +840,97 @@ blocks:
     width7: '1'
     width8: '1'
     width9: '1'
-    ylabel: Amplitude
-    ymax: '1'
-    ymin: '-1'
-    yunit: '""'
+    xmax: '2'
+    xmin: '-2'
+    ymax: '2'
+    ymin: '-2'
   states:
     bus_sink: false
     bus_source: false
     bus_structure: null
-    coordinate: [920, 172.0]
-    rotation: 0
-    state: enabled
+    coordinate: [1860.0, 64]
+    rotation: 90
+    state: true
+- 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: 'plots@1: 0,0,1,1'
+    label: Relative Gain
+    label1: ''
+    label10: ''''''
+    label2: ''''''
+    label3: ''''''
+    label4: ''''''
+    label5: ''''''
+    label6: ''''''
+    label7: ''''''
+    label8: ''''''
+    label9: ''''''
+    legend: 'True'
+    maxoutbuf: '0'
+    minoutbuf: '0'
+    name: '"Channel"'
+    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: [856.0, 472]
+    rotation: 270
+    state: true
 
 connections:
 - [analog_random_source_x_0, '0', digital_constellation_modulator_0, '0']
@@ -680,8 +938,11 @@ connections:
 - [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_cma_equalizer_cc_0, '0', digital_costas_loop_cc_0, '0']
+- [digital_cma_equalizer_cc_0, '0', qtgui_const_sink_x_1, '0']
 - [digital_constellation_modulator_0, '0', blocks_throttle_0, '0']
+- [digital_costas_loop_cc_0, '0', qtgui_const_sink_x_2, '0']
+- [digital_pfb_clock_sync_xxx_0, '0', digital_cma_equalizer_cc_0, '0']
 - [digital_pfb_clock_sync_xxx_0, '0', qtgui_const_sink_x_0_0, '0']
 
 metadata:
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