From 8e6e1d62ef9beb978879bfd156b3ff51940c8725 Mon Sep 17 00:00:00 2001
From: Nao Pross <np@0hm.ch>
Date: Thu, 2 Dec 2021 12:50:55 +0100
Subject: Implement phase correction in test file with embedded python block

---
 tests/correlator/correlator.grc | 424 +++++++++++-----------------------------
 tests/correlator/correlator.py  | 274 +++++---------------------
 tests/correlator/epy_block_0.py |  75 +++++++
 3 files changed, 234 insertions(+), 539 deletions(-)
 create mode 100644 tests/correlator/epy_block_0.py

(limited to 'tests')

diff --git a/tests/correlator/correlator.grc b/tests/correlator/correlator.grc
index 9deec54..aa21770 100644
--- a/tests/correlator/correlator.grc
+++ b/tests/correlator/correlator.grc
@@ -1,7 +1,6 @@
 options:
   parameters:
     author: Naoki Pross
-    catch_exceptions: 'True'
     category: '[GRC Hier Blocks]'
     cmake_opt: ''
     comment: ''
@@ -23,6 +22,7 @@ options:
     sizing_mode: fixed
     thread_safe_setters: ''
     title: Correlator Test
+    window_size: ''
   states:
     bus_sink: false
     bus_source: false
@@ -72,7 +72,6 @@ blocks:
     comment: ''
     const_points: '[-1-1j, -1+1j, 1+1j, 1-1j]'
     dims: '1'
-    normalization: digital.constellation.AMPLITUDE_NORMALIZATION
     precision: '8'
     rot_sym: '4'
     soft_dec_lut: None
@@ -184,42 +183,6 @@ blocks:
     coordinate: [224, 1068.0]
     rotation: 0
     state: enabled
-- name: blocks_burst_tagger_0
-  id: blocks_burst_tagger
-  parameters:
-    affinity: ''
-    alias: ''
-    comment: ''
-    false_key: nothing
-    false_value: '0'
-    maxoutbuf: '0'
-    minoutbuf: '0'
-    true_key: peak
-    true_value: 'True'
-    type: float
-  states:
-    bus_sink: false
-    bus_source: false
-    bus_structure: null
-    coordinate: [944, 1580.0]
-    rotation: 0
-    state: disabled
-- name: blocks_char_to_short_0
-  id: blocks_char_to_short
-  parameters:
-    affinity: ''
-    alias: ''
-    comment: ''
-    maxoutbuf: '0'
-    minoutbuf: '0'
-    vlen: '1'
-  states:
-    bus_sink: false
-    bus_source: false
-    bus_structure: null
-    coordinate: [752, 1624.0]
-    rotation: 0
-    state: disabled
 - name: blocks_complex_to_magphase_0
   id: blocks_complex_to_magphase
   parameters:
@@ -235,7 +198,7 @@ blocks:
     bus_structure: null
     coordinate: [1048, 696.0]
     rotation: 0
-    state: enabled
+    state: disabled
 - name: blocks_complex_to_magphase_0_0
   id: blocks_complex_to_magphase
   parameters:
@@ -249,25 +212,9 @@ blocks:
     bus_sink: false
     bus_source: false
     bus_structure: null
-    coordinate: [1048, 1104.0]
+    coordinate: [1048, 1128.0]
     rotation: 0
     state: enabled
-- name: blocks_complex_to_magphase_0_1
-  id: blocks_complex_to_magphase
-  parameters:
-    affinity: ''
-    alias: ''
-    comment: ''
-    maxoutbuf: '0'
-    minoutbuf: '0'
-    vlen: '1'
-  states:
-    bus_sink: false
-    bus_source: false
-    bus_structure: null
-    coordinate: [256, 1592.0]
-    rotation: 0
-    state: disabled
 - name: blocks_multiply_const_vxx_0
   id: blocks_multiply_const_vxx
   parameters:
@@ -285,7 +232,7 @@ blocks:
     bus_structure: null
     coordinate: [1288, 724.0]
     rotation: 0
-    state: enabled
+    state: disabled
 - name: blocks_multiply_const_vxx_0_0
   id: blocks_multiply_const_vxx
   parameters:
@@ -301,41 +248,7 @@ blocks:
     bus_sink: false
     bus_source: false
     bus_structure: null
-    coordinate: [1336, 1180.0]
-    rotation: 0
-    state: disabled
-- name: blocks_null_sink_0
-  id: blocks_null_sink
-  parameters:
-    affinity: ''
-    alias: ''
-    bus_structure_sink: '[[0,],]'
-    comment: ''
-    num_inputs: '1'
-    type: byte
-    vlen: '1'
-  states:
-    bus_sink: false
-    bus_source: false
-    bus_structure: null
-    coordinate: [1504, 1696.0]
-    rotation: 0
-    state: disabled
-- name: blocks_null_sink_2
-  id: blocks_null_sink
-  parameters:
-    affinity: ''
-    alias: ''
-    bus_structure_sink: '[[0,],]'
-    comment: ''
-    num_inputs: '1'
-    type: float
-    vlen: '1'
-  states:
-    bus_sink: false
-    bus_source: false
-    bus_structure: null
-    coordinate: [528, 1720.0]
+    coordinate: [1336, 1204.0]
     rotation: 0
     state: disabled
 - name: blocks_null_sink_3
@@ -352,7 +265,7 @@ blocks:
     bus_sink: false
     bus_source: false
     bus_structure: null
-    coordinate: [1336, 1232.0]
+    coordinate: [1336, 1256.0]
     rotation: 0
     state: true
 - name: blocks_null_source_0
@@ -374,24 +287,6 @@ blocks:
     coordinate: [96, 344.0]
     rotation: 0
     state: enabled
-- name: blocks_peak_detector2_fb_0
-  id: blocks_peak_detector2_fb
-  parameters:
-    affinity: ''
-    alias: ''
-    alpha: '0.001'
-    comment: ''
-    look_ahead: '1000'
-    maxoutbuf: '0'
-    minoutbuf: '0'
-    threshold_factor_rise: '7'
-  states:
-    bus_sink: false
-    bus_source: false
-    bus_structure: null
-    coordinate: [528, 1620.0]
-    rotation: 0
-    state: disabled
 - name: blocks_stream_mux_0
   id: blocks_stream_mux
   parameters:
@@ -449,6 +344,22 @@ blocks:
     coordinate: [1272, 404.0]
     rotation: 0
     state: enabled
+- name: blocks_vector_sink_x_0
+  id: blocks_vector_sink_x
+  parameters:
+    affinity: ''
+    alias: ''
+    comment: ''
+    reserve_items: '1024'
+    type: byte
+    vlen: '1'
+  states:
+    bus_sink: false
+    bus_source: false
+    bus_structure: null
+    coordinate: [840, 1392.0]
+    rotation: 0
+    state: true
 - name: blocks_vector_source_x_0
   id: blocks_vector_source_x
   parameters:
@@ -457,7 +368,7 @@ blocks:
     comment: ''
     maxoutbuf: '0'
     minoutbuf: '0'
-    repeat: 'False'
+    repeat: 'True'
     tags: '[]'
     type: byte
     vector: testvec * 1600
@@ -497,7 +408,7 @@ blocks:
     block_tags: 'False'
     comment: ''
     epsilon: '1.0'
-    freq_offset: '0.000001'
+    freq_offset: '0.00001'
     maxoutbuf: '0'
     minoutbuf: '0'
     noise_voltage: '0.2'
@@ -542,9 +453,9 @@ blocks:
     bus_sink: false
     bus_source: false
     bus_structure: null
-    coordinate: [1232, 1692.0]
+    coordinate: [248, 1388.0]
     rotation: 0
-    state: disabled
+    state: enabled
 - name: digital_constellation_modulator_0
   id: digital_constellation_modulator
   parameters:
@@ -558,7 +469,6 @@ blocks:
     maxoutbuf: '0'
     minoutbuf: '0'
     samples_per_symbol: sps
-    truncate: 'False'
     verbose: 'False'
   states:
     bus_sink: false
@@ -610,71 +520,87 @@ blocks:
     coordinate: [224, 836.0]
     rotation: 0
     state: enabled
-- name: fir_filter_xxx_1
-  id: fir_filter_xxx
+- name: epy_block_0
+  id: epy_block
   parameters:
+    _source_code: "import pmt\n\nimport numpy as np\nfrom gnuradio import gr\n\n\n\
+      class blk(gr.sync_block):\n    def __init__(self):\n        gr.sync_block.__init__(\n\
+      \            self,\n            name='Phase Lock',\n            in_sig=[np.complex64],\n\
+      \            out_sig=[np.complex64]\n        )\n\n        # keep track of how\
+      \ many samples were processed,\n        # because tags have an absolute offset\n\
+      \        self.sampnr: np.complex64 = 0\n\n        # because of block processing\
+      \ a tagged block could\n        # be split in half so we need to keep track\
+      \ of the\n        # \"previous\" values\n        self.last_phase = 0\n\n   \
+      \ def work(self, input_items, output_items):\n        # TODO: interpolate phase\
+      \ values for frequency correction\n\n        out = output_items[0]\n       \
+      \ inp = input_items[0]\n\n        # create a phase correction vector\n     \
+      \   phase = np.zeros(len(inp), dtype=np.float64)\n\n        # read tags\n  \
+      \      tags = self.get_tags_in_window(0, 0, len(inp))\n\n        # get only\
+      \ phase tags\n        is_phase = lambda tag: pmt.to_python(tag.key) == \"phase_est\"\
+      \n        phase_tags = list(filter(is_phase, tags))\n\n        print(f\"Processing\
+      \ {len(inp)} samples, with {len(phase_tags)} tags\")\n\n        # compute correction\
+      \ from previous block\n        first_tag = phase_tags[0]\n        first_idx\
+      \ = first_tag.offset - self.sampnr\n        phase[:first_idx] = self.last_phase\n\
+      \n        # iterate phase tags \"in the middle\"\n        for prev_tag, next_tag\
+      \ in zip(phase_tags, phase_tags[1:]):\n            # unpack pmt values\n   \
+      \         pval = pmt.to_python(prev_tag.value)\n\n            # compute indexes\
+      \ in phase vector\n            pidx = prev_tag.offset - self.sampnr\n      \
+      \      idx = next_tag.offset - self.sampnr\n\n            # compute phase correction\
+      \ for block\n            phase[pidx:idx] = pval\n            print(f\"Correction\
+      \ for block {pidx} to {idx} is {pval}\")\n\n        # compute the remaining\
+      \ part of the block\n        last_tag = phase_tags[-1]\n        last_val = pmt.to_python(last_tag.value)\n\
+      \        last_idx = last_tag.offset - self.sampnr\n\n        phase[last_idx:]\
+      \ = last_val\n\n        # save values for next call\n        self.last_phase\
+      \ = last_val\n\n        # mark samples as processed and compute to output\n\
+      \        self.sampnr += len(inp)\n        out[:] = inp * np.exp(-1j * phase)\n\
+      \n        return len(out)\n"
     affinity: ''
     alias: ''
     comment: ''
-    decim: '1'
     maxoutbuf: '0'
     minoutbuf: '0'
-    samp_delay: '0'
-    taps: revconj_access_code_symbols
-    type: ccc
   states:
+    _io_cache: ('Phase Lock', 'blk', [], [('0', 'complex', 1)], [('0', 'complex',
+      1)], '', [])
     bus_sink: false
     bus_source: false
     bus_structure: null
-    coordinate: [776, 828.0]
+    coordinate: [1088, 1040.0]
     rotation: 0
     state: enabled
-- name: high_pass_filter_0
-  id: high_pass_filter
+- name: fadingui_deframer_0
+  id: fadingui_deframer
   parameters:
     affinity: ''
     alias: ''
-    beta: '6.76'
     comment: ''
-    cutoff_freq: 5e3
-    decim: '1'
-    gain: '1'
-    interp: '1'
+    frame_obj: ''
     maxoutbuf: '0'
     minoutbuf: '0'
-    samp_rate: samp_rate
-    type: fir_filter_fff
-    width: '.7'
-    win: window.WIN_HAMMING
   states:
     bus_sink: false
     bus_source: false
     bus_structure: null
-    coordinate: [528, 1420.0]
+    coordinate: [552, 1388.0]
     rotation: 0
-    state: disabled
-- name: low_pass_filter_0
-  id: low_pass_filter
+    state: true
+- name: fir_filter_xxx_1
+  id: fir_filter_xxx
   parameters:
     affinity: ''
     alias: ''
-    beta: '6.76'
     comment: ''
-    cutoff_freq: 7e3
     decim: '1'
-    gain: '1'
-    interp: '1'
     maxoutbuf: '0'
     minoutbuf: '0'
-    samp_rate: samp_rate
-    type: fir_filter_fff
-    width: '.8'
-    win: window.WIN_HAMMING
+    samp_delay: '0'
+    taps: revconj_access_code_symbols
+    type: ccc
   states:
     bus_sink: false
     bus_source: false
     bus_structure: null
-    coordinate: [528, 1252.0]
+    coordinate: [776, 828.0]
     rotation: 0
     state: disabled
 - name: qtgui_const_sink_x_0
@@ -769,12 +695,12 @@ blocks:
     coordinate: [776, 716.0]
     rotation: 0
     state: enabled
-- name: qtgui_const_sink_x_1
+- name: qtgui_const_sink_x_0_0
   id: qtgui_const_sink_x
   parameters:
     affinity: ''
     alias: ''
-    alpha1: '.5'
+    alpha1: '1.0'
     alpha10: '1.0'
     alpha2: '1.0'
     alpha3: '1.0'
@@ -784,7 +710,7 @@ blocks:
     alpha7: '1.0'
     alpha8: '1.0'
     alpha9: '1.0'
-    autoscale: 'True'
+    autoscale: 'False'
     axislabels: 'True'
     color1: '"blue"'
     color10: '"red"'
@@ -797,7 +723,7 @@ blocks:
     color8: '"red"'
     color9: '"red"'
     comment: ''
-    grid: 'True'
+    grid: 'False'
     gui_hint: 2,1,2,1
     label1: ''
     label10: ''
@@ -810,7 +736,7 @@ blocks:
     label8: ''
     label9: ''
     legend: 'True'
-    marker1: '9'
+    marker1: '0'
     marker10: '0'
     marker2: '0'
     marker3: '0'
@@ -820,10 +746,10 @@ blocks:
     marker7: '0'
     marker8: '0'
     marker9: '0'
-    name: '"Cross Correlation"'
+    name: '"Phase Locked Signal"'
     nconnections: '1'
     size: '1024'
-    style1: '2'
+    style1: '0'
     style10: '0'
     style2: '0'
     style3: '0'
@@ -858,15 +784,15 @@ blocks:
     bus_sink: false
     bus_source: false
     bus_structure: null
-    coordinate: [1048, 612.0]
+    coordinate: [1288, 940.0]
     rotation: 0
     state: enabled
-- name: qtgui_const_sink_x_2
+- name: qtgui_const_sink_x_1
   id: qtgui_const_sink_x
   parameters:
     affinity: ''
     alias: ''
-    alpha1: '1.0'
+    alpha1: '.5'
     alpha10: '1.0'
     alpha2: '1.0'
     alpha3: '1.0'
@@ -876,7 +802,7 @@ blocks:
     alpha7: '1.0'
     alpha8: '1.0'
     alpha9: '1.0'
-    autoscale: 'False'
+    autoscale: 'True'
     axislabels: 'True'
     color1: '"blue"'
     color10: '"red"'
@@ -889,8 +815,8 @@ blocks:
     color8: '"red"'
     color9: '"red"'
     comment: ''
-    grid: 'False'
-    gui_hint: '2,1,2,1 '
+    grid: 'True'
+    gui_hint: 2,1,2,1
     label1: ''
     label10: ''
     label2: ''
@@ -902,7 +828,7 @@ blocks:
     label8: ''
     label9: ''
     legend: 'True'
-    marker1: '0'
+    marker1: '9'
     marker10: '0'
     marker2: '0'
     marker3: '0'
@@ -912,10 +838,10 @@ blocks:
     marker7: '0'
     marker8: '0'
     marker9: '0'
-    name: '"Phase Correction"'
+    name: '"Cross Correlation"'
     nconnections: '1'
     size: '1024'
-    style1: '0'
+    style1: '2'
     style10: '0'
     style2: '0'
     style3: '0'
@@ -950,7 +876,7 @@ blocks:
     bus_sink: false
     bus_source: false
     bus_structure: null
-    coordinate: [1248, 1588.0]
+    coordinate: [1048, 612.0]
     rotation: 0
     state: disabled
 - name: qtgui_time_sink_x_0
@@ -1049,7 +975,7 @@ blocks:
     bus_structure: null
     coordinate: [1320, 604.0]
     rotation: 0
-    state: enabled
+    state: disabled
 - name: qtgui_time_sink_x_0_0
   id: qtgui_time_sink_x
   parameters:
@@ -1144,7 +1070,7 @@ blocks:
     bus_sink: false
     bus_source: false
     bus_structure: null
-    coordinate: [1336, 1084.0]
+    coordinate: [1336, 1108.0]
     rotation: 0
     state: enabled
 - name: qtgui_time_sink_x_0_0_0
@@ -1233,7 +1159,7 @@ blocks:
     width7: '1'
     width8: '1'
     width9: '1'
-    ylabel: XC Magnitude
+    ylabel: Equalized
     ymax: '2'
     ymin: '-2'
     yunit: '""'
@@ -1241,106 +1167,9 @@ blocks:
     bus_sink: false
     bus_source: false
     bus_structure: null
-    coordinate: [1048, 1020.0]
+    coordinate: [1048, 940.0]
     rotation: 0
     state: enabled
-- name: qtgui_time_sink_x_1
-  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: ''
-    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: '""'
-    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: float
-    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: '20'
-    ymin: '-5'
-    yunit: '""'
-  states:
-    bus_sink: false
-    bus_source: false
-    bus_structure: null
-    coordinate: [784, 1452.0]
-    rotation: 0
-    state: disabled
 - name: qtgui_time_sink_x_1_0
   id: qtgui_time_sink_x
   parameters:
@@ -1534,7 +1363,7 @@ blocks:
     bus_structure: null
     coordinate: [776, 612.0]
     rotation: 0
-    state: enabled
+    state: disabled
 - name: qtgui_time_sink_x_2
   id: qtgui_time_sink_x
   parameters:
@@ -1631,7 +1460,7 @@ blocks:
     bus_structure: null
     coordinate: [1480, 708.0]
     rotation: 0
-    state: enabled
+    state: disabled
 - name: qtgui_time_sink_x_2_0
   id: qtgui_time_sink_x
   parameters:
@@ -1726,7 +1555,7 @@ blocks:
     bus_sink: false
     bus_source: false
     bus_structure: null
-    coordinate: [1512, 1164.0]
+    coordinate: [1512, 1188.0]
     rotation: 0
     state: disabled
 - name: root_raised_cosine_filter_0
@@ -1765,30 +1594,17 @@ blocks:
     coordinate: [1480, 404.0]
     rotation: 0
     state: enabled
-- name: virtual_sink_1
+- name: virtual_sink_3
   id: virtual_sink
   parameters:
     alias: ''
     comment: ''
-    stream_id: symbols
+    stream_id: locked
   states:
     bus_sink: false
     bus_source: false
     bus_structure: null
-    coordinate: [776, 916.0]
-    rotation: 0
-    state: true
-- name: virtual_sink_2
-  id: virtual_sink
-  parameters:
-    alias: ''
-    comment: ''
-    stream_id: xcorrelation
-  states:
-    bus_sink: false
-    bus_source: false
-    bus_structure: null
-    coordinate: [1080, 836.0]
+    coordinate: [1336, 1036.0]
     rotation: 0
     state: true
 - name: virtual_source_0
@@ -1804,49 +1620,29 @@ blocks:
     coordinate: [32, 884.0]
     rotation: 0
     state: enabled
-- name: virtual_source_2
-  id: virtual_source
-  parameters:
-    alias: ''
-    comment: ''
-    stream_id: symbols
-  states:
-    bus_sink: false
-    bus_source: false
-    bus_structure: null
-    coordinate: [32, 1716.0]
-    rotation: 0
-    state: disabled
-- name: virtual_source_3
+- name: virtual_source_1
   id: virtual_source
   parameters:
     alias: ''
     comment: ''
-    stream_id: xcorrelation
+    stream_id: locked
   states:
     bus_sink: false
     bus_source: false
     bus_structure: null
-    coordinate: [32, 1604.0]
+    coordinate: [24, 1388.0]
     rotation: 0
-    state: disabled
+    state: true
 
 connections:
-- [blocks_char_to_short_0, '0', blocks_burst_tagger_0, '1']
 - [blocks_complex_to_magphase_0, '0', qtgui_time_sink_x_0, '0']
 - [blocks_complex_to_magphase_0, '1', blocks_multiply_const_vxx_0, '0']
 - [blocks_complex_to_magphase_0_0, '0', qtgui_time_sink_x_0_0, '0']
 - [blocks_complex_to_magphase_0_0, '1', blocks_multiply_const_vxx_0_0, '0']
 - [blocks_complex_to_magphase_0_0, '1', blocks_null_sink_3, '0']
-- [blocks_complex_to_magphase_0_1, '0', blocks_burst_tagger_0, '0']
-- [blocks_complex_to_magphase_0_1, '0', blocks_peak_detector2_fb_0, '0']
-- [blocks_complex_to_magphase_0_1, '0', high_pass_filter_0, '0']
-- [blocks_complex_to_magphase_0_1, '0', low_pass_filter_0, '0']
-- [blocks_complex_to_magphase_0_1, '1', blocks_null_sink_2, '0']
 - [blocks_multiply_const_vxx_0, '0', qtgui_time_sink_x_2, '0']
 - [blocks_multiply_const_vxx_0_0, '0', qtgui_time_sink_x_2_0, '0']
 - [blocks_null_source_0, '0', blocks_stream_mux_0, '0']
-- [blocks_peak_detector2_fb_0, '0', blocks_char_to_short_0, '0']
 - [blocks_stream_mux_0, '0', digital_constellation_modulator_0, '0']
 - [blocks_stream_mux_1, '0', channels_channel_model_0, '0']
 - [blocks_throttle_0, '0', virtual_sink_0, '0']
@@ -1857,22 +1653,22 @@ connections:
 - [digital_cma_equalizer_cc_0, '0', fir_filter_xxx_1, '0']
 - [digital_cma_equalizer_cc_0, '0', qtgui_const_sink_x_0, '0']
 - [digital_cma_equalizer_cc_0, '0', qtgui_time_sink_x_1_1, '0']
-- [digital_cma_equalizer_cc_0, '0', virtual_sink_1, '0']
-- [digital_constellation_decoder_cb_0, '0', blocks_null_sink_0, '0']
+- [digital_constellation_decoder_cb_0, '0', fadingui_deframer_0, '0']
 - [digital_constellation_modulator_0, '0', blocks_stream_mux_1, '1']
 - [digital_constellation_modulator_0, '0', channels_channel_model_0, '0']
 - [digital_constellation_modulator_0, '0', qtgui_time_sink_x_1_0, '0']
+- [digital_corr_est_cc_0, '0', epy_block_0, '0']
 - [digital_corr_est_cc_0, '0', qtgui_time_sink_x_0_0_0, '0']
 - [digital_corr_est_cc_0, '1', blocks_complex_to_magphase_0_0, '0']
 - [digital_pfb_clock_sync_xxx_0, '0', digital_cma_equalizer_cc_0, '0']
+- [epy_block_0, '0', qtgui_const_sink_x_0_0, '0']
+- [epy_block_0, '0', virtual_sink_3, '0']
+- [fadingui_deframer_0, '0', blocks_vector_sink_x_0, '0']
 - [fir_filter_xxx_1, '0', blocks_complex_to_magphase_0, '0']
 - [fir_filter_xxx_1, '0', qtgui_const_sink_x_1, '0']
-- [fir_filter_xxx_1, '0', virtual_sink_2, '0']
-- [high_pass_filter_0, '0', qtgui_time_sink_x_1, '0']
-- [low_pass_filter_0, '0', qtgui_time_sink_x_1, '0']
 - [root_raised_cosine_filter_0, '0', blocks_stream_mux_1, '0']
 - [virtual_source_0, '0', digital_pfb_clock_sync_xxx_0, '0']
-- [virtual_source_3, '0', blocks_complex_to_magphase_0_1, '0']
+- [virtual_source_1, '0', digital_constellation_decoder_cb_0, '0']
 
 metadata:
   file_format: 1
diff --git a/tests/correlator/correlator.py b/tests/correlator/correlator.py
index 376d061..a870cc0 100755
--- a/tests/correlator/correlator.py
+++ b/tests/correlator/correlator.py
@@ -7,7 +7,7 @@
 # GNU Radio Python Flow Graph
 # Title: Correlator Test
 # Author: Naoki Pross
-# GNU Radio version: 3.9.2.0
+# GNU Radio version: 3.8.2.0
 
 from distutils.version import StrictVersion
 
@@ -28,23 +28,20 @@ import sip
 from gnuradio import blocks
 from gnuradio import channels
 from gnuradio import digital
-from gnuradio import filter
 from gnuradio import gr
-from gnuradio.fft import window
 import sys
 import signal
 from argparse import ArgumentParser
 from gnuradio.eng_arg import eng_float, intx
 from gnuradio import eng_notation
-
-
+import epy_block_0
 
 from gnuradio import qtgui
 
 class correlator(gr.top_block, Qt.QWidget):
 
     def __init__(self):
-        gr.top_block.__init__(self, "Correlator Test", catch_exceptions=True)
+        gr.top_block.__init__(self, "Correlator Test")
         Qt.QWidget.__init__(self)
         self.setWindowTitle("Correlator Test")
         qtgui.util.check_set_qss()
@@ -92,119 +89,11 @@ class correlator(gr.top_block, Qt.QWidget):
         ##################################################
         # Blocks
         ##################################################
-        self.qtgui_time_sink_x_2 = qtgui.time_sink_f(
-            1024, #size
-            samp_rate, #samp_rate
-            "", #name
-            1, #number of inputs
-            None # parent
-        )
-        self.qtgui_time_sink_x_2.set_update_time(0.10)
-        self.qtgui_time_sink_x_2.set_y_axis(-1, 1)
-
-        self.qtgui_time_sink_x_2.set_y_label('XC Phase', "")
-
-        self.qtgui_time_sink_x_2.enable_tags(True)
-        self.qtgui_time_sink_x_2.set_trigger_mode(qtgui.TRIG_MODE_FREE, qtgui.TRIG_SLOPE_POS, 0.0, 0, 0, "")
-        self.qtgui_time_sink_x_2.enable_autoscale(True)
-        self.qtgui_time_sink_x_2.enable_grid(False)
-        self.qtgui_time_sink_x_2.enable_axis_labels(True)
-        self.qtgui_time_sink_x_2.enable_control_panel(False)
-        self.qtgui_time_sink_x_2.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(1):
-            if len(labels[i]) == 0:
-                self.qtgui_time_sink_x_2.set_line_label(i, "Data {0}".format(i))
-            else:
-                self.qtgui_time_sink_x_2.set_line_label(i, labels[i])
-            self.qtgui_time_sink_x_2.set_line_width(i, widths[i])
-            self.qtgui_time_sink_x_2.set_line_color(i, colors[i])
-            self.qtgui_time_sink_x_2.set_line_style(i, styles[i])
-            self.qtgui_time_sink_x_2.set_line_marker(i, markers[i])
-            self.qtgui_time_sink_x_2.set_line_alpha(i, alphas[i])
-
-        self._qtgui_time_sink_x_2_win = sip.wrapinstance(self.qtgui_time_sink_x_2.pyqwidget(), Qt.QWidget)
-        self.top_grid_layout.addWidget(self._qtgui_time_sink_x_2_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_time_sink_x_1_1 = qtgui.time_sink_c(
-            1024, #size
-            samp_rate, #samp_rate
-            "", #name
-            1, #number of inputs
-            None # parent
-        )
-        self.qtgui_time_sink_x_1_1.set_update_time(0.10)
-        self.qtgui_time_sink_x_1_1.set_y_axis(-2, 2)
-
-        self.qtgui_time_sink_x_1_1.set_y_label('Equalized', "")
-
-        self.qtgui_time_sink_x_1_1.enable_tags(True)
-        self.qtgui_time_sink_x_1_1.set_trigger_mode(qtgui.TRIG_MODE_FREE, qtgui.TRIG_SLOPE_POS, 0.0, 0, 0, "")
-        self.qtgui_time_sink_x_1_1.enable_autoscale(True)
-        self.qtgui_time_sink_x_1_1.enable_grid(True)
-        self.qtgui_time_sink_x_1_1.enable_axis_labels(True)
-        self.qtgui_time_sink_x_1_1.enable_control_panel(False)
-        self.qtgui_time_sink_x_1_1.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_1_1.set_line_label(i, "Re{{Data {0}}}".format(i/2))
-                else:
-                    self.qtgui_time_sink_x_1_1.set_line_label(i, "Im{{Data {0}}}".format(i/2))
-            else:
-                self.qtgui_time_sink_x_1_1.set_line_label(i, labels[i])
-            self.qtgui_time_sink_x_1_1.set_line_width(i, widths[i])
-            self.qtgui_time_sink_x_1_1.set_line_color(i, colors[i])
-            self.qtgui_time_sink_x_1_1.set_line_style(i, styles[i])
-            self.qtgui_time_sink_x_1_1.set_line_marker(i, markers[i])
-            self.qtgui_time_sink_x_1_1.set_line_alpha(i, alphas[i])
-
-        self._qtgui_time_sink_x_1_1_win = sip.wrapinstance(self.qtgui_time_sink_x_1_1.pyqwidget(), Qt.QWidget)
-        self.top_grid_layout.addWidget(self._qtgui_time_sink_x_1_1_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_1_0 = qtgui.time_sink_c(
             1024, #size
             samp_rate, #samp_rate
             "", #name
-            1, #number of inputs
-            None # parent
+            1 #number of inputs
         )
         self.qtgui_time_sink_x_1_0.set_update_time(0.10)
         self.qtgui_time_sink_x_1_0.set_y_axis(-2, 2)
@@ -258,13 +147,12 @@ class correlator(gr.top_block, Qt.QWidget):
             1024, #size
             samp_rate, #samp_rate
             "", #name
-            1, #number of inputs
-            None # parent
+            1 #number of inputs
         )
         self.qtgui_time_sink_x_0_0_0.set_update_time(0.10)
         self.qtgui_time_sink_x_0_0_0.set_y_axis(-2, 2)
 
-        self.qtgui_time_sink_x_0_0_0.set_y_label('XC Magnitude', "")
+        self.qtgui_time_sink_x_0_0_0.set_y_label('Equalized', "")
 
         self.qtgui_time_sink_x_0_0_0.enable_tags(True)
         self.qtgui_time_sink_x_0_0_0.set_trigger_mode(qtgui.TRIG_MODE_FREE, qtgui.TRIG_SLOPE_POS, 0.0, 0, 0, "")
@@ -304,13 +192,12 @@ class correlator(gr.top_block, Qt.QWidget):
             self.qtgui_time_sink_x_0_0_0.set_line_alpha(i, alphas[i])
 
         self._qtgui_time_sink_x_0_0_0_win = sip.wrapinstance(self.qtgui_time_sink_x_0_0_0.pyqwidget(), Qt.QWidget)
-        self.top_layout.addWidget(self._qtgui_time_sink_x_0_0_0_win)
+        self.top_grid_layout.addWidget(self._qtgui_time_sink_x_0_0_0_win)
         self.qtgui_time_sink_x_0_0 = qtgui.time_sink_f(
             1024, #size
             samp_rate, #samp_rate
             "", #name
-            1, #number of inputs
-            None # parent
+            1 #number of inputs
         )
         self.qtgui_time_sink_x_0_0.set_update_time(0.10)
         self.qtgui_time_sink_x_0_0.set_y_axis(0, 20)
@@ -352,72 +239,19 @@ class correlator(gr.top_block, Qt.QWidget):
             self.qtgui_time_sink_x_0_0.set_line_alpha(i, alphas[i])
 
         self._qtgui_time_sink_x_0_0_win = sip.wrapinstance(self.qtgui_time_sink_x_0_0.pyqwidget(), Qt.QWidget)
-        self.top_layout.addWidget(self._qtgui_time_sink_x_0_0_win)
-        self.qtgui_time_sink_x_0 = qtgui.time_sink_f(
+        self.top_grid_layout.addWidget(self._qtgui_time_sink_x_0_0_win)
+        self.qtgui_const_sink_x_0_0 = qtgui.const_sink_c(
             1024, #size
-            samp_rate, #samp_rate
-            "", #name
-            1, #number of inputs
-            None # parent
+            "Phase Locked Signal", #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(0, 20)
-
-        self.qtgui_time_sink_x_0.set_y_label('XC Magnitude', "")
-
-        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(True)
-        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(1):
-            if len(labels[i]) == 0:
-                self.qtgui_time_sink_x_0.set_line_label(i, "Data {0}".format(i))
-            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_const_sink_x_1 = qtgui.const_sink_c(
-            1024, #size
-            "Cross Correlation", #name
-            1, #number of inputs
-            None # parent
-        )
-        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(True)
-        self.qtgui_const_sink_x_1.enable_grid(True)
-        self.qtgui_const_sink_x_1.enable_axis_labels(True)
+        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 = ['', '', '', '', '',
@@ -426,26 +260,26 @@ class correlator(gr.top_block, Qt.QWidget):
             1, 1, 1, 1, 1]
         colors = ["blue", "red", "red", "red", "red",
             "red", "red", "red", "red", "red"]
-        styles = [2, 0, 0, 0, 0,
+        styles = [0, 0, 0, 0, 0,
             0, 0, 0, 0, 0]
-        markers = [9, 0, 0, 0, 0,
+        markers = [0, 0, 0, 0, 0,
             0, 0, 0, 0, 0]
-        alphas = [.5, 1.0, 1.0, 1.0, 1.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))
+                self.qtgui_const_sink_x_0_0.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.top_grid_layout.addWidget(self._qtgui_const_sink_x_1_win, 2, 1, 2, 1)
+                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, 2, 1, 2, 1)
         for r in range(2, 4):
             self.top_grid_layout.setRowStretch(r, 1)
         for c in range(1, 2):
@@ -453,8 +287,7 @@ class correlator(gr.top_block, Qt.QWidget):
         self.qtgui_const_sink_x_0 = qtgui.const_sink_c(
             1024, #size
             "Equalized Signal", #name
-            1, #number of inputs
-            None # parent
+            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)
@@ -495,8 +328,7 @@ class correlator(gr.top_block, Qt.QWidget):
             self.top_grid_layout.setRowStretch(r, 1)
         for c in range(1, 2):
             self.top_grid_layout.setColumnStretch(c, 1)
-        self.fir_filter_xxx_1 = filter.fir_filter_ccc(1, revconj_access_code_symbols)
-        self.fir_filter_xxx_1.declare_sample_delay(0)
+        self.epy_block_0 = epy_block_0.blk()
         self.digital_pfb_clock_sync_xxx_0 = digital.pfb_clock_sync_ccf(sps, timing_loop_bw, rrc_taps, nfilts, 16, 1.5, 1)
         self.digital_corr_est_cc_0 = digital.corr_est_cc(access_code_symbols, 1, 0, .8, digital.THRESHOLD_DYNAMIC)
         self.digital_constellation_modulator_0 = digital.generic_mod(
@@ -506,59 +338,52 @@ class correlator(gr.top_block, Qt.QWidget):
             pre_diff_code=True,
             excess_bw=excess_bw,
             verbose=False,
-            log=False,
-            truncate=False)
+            log=False)
+        self.digital_constellation_decoder_cb_0 = digital.constellation_decoder_cb(const)
         self.digital_cma_equalizer_cc_0 = digital.cma_equalizer_cc(15, 1, .002, 1)
         self.channels_channel_model_0 = channels.channel_model(
             noise_voltage=0.2,
-            frequency_offset=0.000001,
+            frequency_offset=0.00001,
             epsilon=1.0,
             taps=[-1.4 + .4j],
             noise_seed=243,
             block_tags=False)
-        self.blocks_vector_source_x_0 = blocks.vector_source_b(testvec * 1600, False, 1, [])
+        self.blocks_vector_source_x_0 = blocks.vector_source_b(testvec * 1600, True, 1, [])
+        self.blocks_vector_sink_x_0 = blocks.vector_sink_b(1, 1024)
         self.blocks_throttle_0 = blocks.throttle(gr.sizeof_gr_complex*1, samp_rate,True)
         self.blocks_stream_mux_0 = blocks.stream_mux(gr.sizeof_char*1, [10, len(testvec)])
         self.blocks_null_source_0 = blocks.null_source(gr.sizeof_char*1)
         self.blocks_null_sink_3 = blocks.null_sink(gr.sizeof_float*1)
-        self.blocks_multiply_const_vxx_0 = blocks.multiply_const_ff(180 / 3.141592653589793)
         self.blocks_complex_to_magphase_0_0 = blocks.complex_to_magphase(1)
-        self.blocks_complex_to_magphase_0 = blocks.complex_to_magphase(1)
 
 
 
         ##################################################
         # Connections
         ##################################################
-        self.connect((self.blocks_complex_to_magphase_0, 1), (self.blocks_multiply_const_vxx_0, 0))
-        self.connect((self.blocks_complex_to_magphase_0, 0), (self.qtgui_time_sink_x_0, 0))
         self.connect((self.blocks_complex_to_magphase_0_0, 1), (self.blocks_null_sink_3, 0))
         self.connect((self.blocks_complex_to_magphase_0_0, 0), (self.qtgui_time_sink_x_0_0, 0))
-        self.connect((self.blocks_multiply_const_vxx_0, 0), (self.qtgui_time_sink_x_2, 0))
         self.connect((self.blocks_null_source_0, 0), (self.blocks_stream_mux_0, 0))
         self.connect((self.blocks_stream_mux_0, 0), (self.digital_constellation_modulator_0, 0))
         self.connect((self.blocks_throttle_0, 0), (self.digital_pfb_clock_sync_xxx_0, 0))
         self.connect((self.blocks_vector_source_x_0, 0), (self.blocks_stream_mux_0, 1))
         self.connect((self.channels_channel_model_0, 0), (self.blocks_throttle_0, 0))
         self.connect((self.digital_cma_equalizer_cc_0, 0), (self.digital_corr_est_cc_0, 0))
-        self.connect((self.digital_cma_equalizer_cc_0, 0), (self.fir_filter_xxx_1, 0))
         self.connect((self.digital_cma_equalizer_cc_0, 0), (self.qtgui_const_sink_x_0, 0))
-        self.connect((self.digital_cma_equalizer_cc_0, 0), (self.qtgui_time_sink_x_1_1, 0))
+        self.connect((self.digital_constellation_decoder_cb_0, 0), (self.blocks_vector_sink_x_0, 0))
         self.connect((self.digital_constellation_modulator_0, 0), (self.channels_channel_model_0, 0))
         self.connect((self.digital_constellation_modulator_0, 0), (self.qtgui_time_sink_x_1_0, 0))
         self.connect((self.digital_corr_est_cc_0, 1), (self.blocks_complex_to_magphase_0_0, 0))
+        self.connect((self.digital_corr_est_cc_0, 0), (self.epy_block_0, 0))
         self.connect((self.digital_corr_est_cc_0, 0), (self.qtgui_time_sink_x_0_0_0, 0))
         self.connect((self.digital_pfb_clock_sync_xxx_0, 0), (self.digital_cma_equalizer_cc_0, 0))
-        self.connect((self.fir_filter_xxx_1, 0), (self.blocks_complex_to_magphase_0, 0))
-        self.connect((self.fir_filter_xxx_1, 0), (self.qtgui_const_sink_x_1, 0))
+        self.connect((self.epy_block_0, 0), (self.digital_constellation_decoder_cb_0, 0))
+        self.connect((self.epy_block_0, 0), (self.qtgui_const_sink_x_0_0, 0))
 
 
     def closeEvent(self, event):
         self.settings = Qt.QSettings("GNU Radio", "correlator")
         self.settings.setValue("geometry", self.saveGeometry())
-        self.stop()
-        self.wait()
-
         event.accept()
 
     def get_sps(self):
@@ -602,12 +427,9 @@ class correlator(gr.top_block, Qt.QWidget):
     def set_samp_rate(self, samp_rate):
         self.samp_rate = samp_rate
         self.blocks_throttle_0.set_sample_rate(self.samp_rate)
-        self.qtgui_time_sink_x_0.set_samp_rate(self.samp_rate)
         self.qtgui_time_sink_x_0_0.set_samp_rate(self.samp_rate)
         self.qtgui_time_sink_x_0_0_0.set_samp_rate(self.samp_rate)
         self.qtgui_time_sink_x_1_0.set_samp_rate(self.samp_rate)
-        self.qtgui_time_sink_x_1_1.set_samp_rate(self.samp_rate)
-        self.qtgui_time_sink_x_2.set_samp_rate(self.samp_rate)
 
     def get_rrc_taps(self):
         return self.rrc_taps
@@ -621,7 +443,6 @@ class correlator(gr.top_block, Qt.QWidget):
 
     def set_revconj_access_code_symbols(self, revconj_access_code_symbols):
         self.revconj_access_code_symbols = revconj_access_code_symbols
-        self.fir_filter_xxx_1.set_taps(self.revconj_access_code_symbols)
 
     def get_const(self):
         return self.const
@@ -644,6 +465,7 @@ class correlator(gr.top_block, Qt.QWidget):
 
 
 
+
 def main(top_block_cls=correlator, options=None):
 
     if StrictVersion("4.5.0") <= StrictVersion(Qt.qVersion()) < StrictVersion("5.0.0"):
@@ -658,9 +480,6 @@ def main(top_block_cls=correlator, options=None):
     tb.show()
 
     def sig_handler(sig=None, frame=None):
-        tb.stop()
-        tb.wait()
-
         Qt.QApplication.quit()
 
     signal.signal(signal.SIGINT, sig_handler)
@@ -670,6 +489,11 @@ def main(top_block_cls=correlator, options=None):
     timer.start(500)
     timer.timeout.connect(lambda: None)
 
+    def quitting():
+        tb.stop()
+        tb.wait()
+
+    qapp.aboutToQuit.connect(quitting)
     qapp.exec_()
 
 if __name__ == '__main__':
diff --git a/tests/correlator/epy_block_0.py b/tests/correlator/epy_block_0.py
new file mode 100644
index 0000000..1fa4794
--- /dev/null
+++ b/tests/correlator/epy_block_0.py
@@ -0,0 +1,75 @@
+import pmt
+
+import numpy as np
+from gnuradio import gr
+
+
+class blk(gr.sync_block):
+    def __init__(self):
+        gr.sync_block.__init__(
+            self,
+            name='Phase Lock',
+            in_sig=[np.complex64],
+            out_sig=[np.complex64]
+        )
+
+        # keep track of how many samples were processed,
+        # because tags have an absolute offset
+        self.sampnr: np.complex64 = 0
+
+        # because of block processing a tagged block could
+        # be split in half so we need to keep track of the
+        # "previous" values
+        self.last_phase = 0
+
+    def work(self, input_items, output_items):
+        # TODO: interpolate phase values for frequency correction
+
+        out = output_items[0]
+        inp = input_items[0]
+
+        # create a phase correction vector
+        phase = np.zeros(len(inp), dtype=np.float64)
+
+        # read tags
+        tags = self.get_tags_in_window(0, 0, len(inp))
+
+        # get only phase tags
+        is_phase = lambda tag: pmt.to_python(tag.key) == "phase_est"
+        phase_tags = list(filter(is_phase, tags))
+
+        print(f"Processing {len(inp)} samples, with {len(phase_tags)} tags")
+
+        # compute correction from previous block
+        first_tag = phase_tags[0]
+        first_idx = first_tag.offset - self.sampnr
+        phase[:first_idx] = self.last_phase
+
+        # iterate phase tags "in the middle"
+        for prev_tag, next_tag in zip(phase_tags, phase_tags[1:]):
+            # unpack pmt values
+            pval = pmt.to_python(prev_tag.value)
+
+            # compute indexes in phase vector
+            pidx = prev_tag.offset - self.sampnr
+            idx = next_tag.offset - self.sampnr
+
+            # compute phase correction for block
+            phase[pidx:idx] = pval
+            print(f"Correction for block {pidx} to {idx} is {pval}")
+
+        # compute the remaining part of the block
+        last_tag = phase_tags[-1]
+        last_val = pmt.to_python(last_tag.value)
+        last_idx = last_tag.offset - self.sampnr
+
+        phase[last_idx:] = last_val
+
+        # save values for next call
+        self.last_phase = last_val
+
+        # mark samples as processed and compute to output
+        self.sampnr += len(inp)
+        out[:] = inp * np.exp(-1j * phase)
+
+        return len(out)
-- 
cgit v1.2.1


From a396c568457bc4e36eac820c209d133e9a7b0b2d Mon Sep 17 00:00:00 2001
From: Nao Pross <np@0hm.ch>
Date: Thu, 2 Dec 2021 12:52:34 +0100
Subject: Delete ZMQ tests

---
 tests/zmq/lena512color.tiff | Bin 786572 -> 0 bytes
 tests/zmq/server.py         |   4 --
 tests/zmq/zmqtest.grc       | 112 --------------------------------------------
 tests/zmq/zmqtest.py        |  85 ---------------------------------
 4 files changed, 201 deletions(-)
 delete mode 100644 tests/zmq/lena512color.tiff
 delete mode 100644 tests/zmq/server.py
 delete mode 100644 tests/zmq/zmqtest.grc
 delete mode 100755 tests/zmq/zmqtest.py

(limited to 'tests')

diff --git a/tests/zmq/lena512color.tiff b/tests/zmq/lena512color.tiff
deleted file mode 100644
index ffe5c83..0000000
Binary files a/tests/zmq/lena512color.tiff and /dev/null differ
diff --git a/tests/zmq/server.py b/tests/zmq/server.py
deleted file mode 100644
index be4bede..0000000
--- a/tests/zmq/server.py
+++ /dev/null
@@ -1,4 +0,0 @@
-import zmq
-import pmt
-
-import numpy as np
diff --git a/tests/zmq/zmqtest.grc b/tests/zmq/zmqtest.grc
deleted file mode 100644
index ad1729d..0000000
--- a/tests/zmq/zmqtest.grc
+++ /dev/null
@@ -1,112 +0,0 @@
-options:
-  parameters:
-    author: Naoki Pross
-    category: '[GRC Hier Blocks]'
-    cmake_opt: ''
-    comment: ''
-    copyright: ''
-    description: ''
-    gen_cmake: 'On'
-    gen_linking: dynamic
-    generate_options: no_gui
-    hier_block_src_path: '.:'
-    id: zmqtest
-    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: ZMQ test
-    window_size: ''
-  states:
-    bus_sink: false
-    bus_source: false
-    bus_structure: null
-    coordinate: [8, 8]
-    rotation: 0
-    state: enabled
-
-blocks:
-- name: samp_rate
-  id: variable
-  parameters:
-    comment: ''
-    value: '32000'
-  states:
-    bus_sink: false
-    bus_source: false
-    bus_structure: null
-    coordinate: [184, 12]
-    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: [440, 324.0]
-    rotation: 0
-    state: true
-- name: zeromq_rep_sink_0
-  id: zeromq_rep_sink
-  parameters:
-    address: ''
-    affinity: ''
-    alias: ''
-    comment: ''
-    hwm: '-1'
-    pass_tags: 'False'
-    timeout: '100'
-    type: complex
-    vlen: '1'
-  states:
-    bus_sink: false
-    bus_source: false
-    bus_structure: null
-    coordinate: [664, 308.0]
-    rotation: 0
-    state: true
-- name: zeromq_req_source_0
-  id: zeromq_req_source
-  parameters:
-    address: ''
-    affinity: ''
-    alias: ''
-    comment: ''
-    hwm: '-1'
-    maxoutbuf: '0'
-    minoutbuf: '0'
-    pass_tags: 'False'
-    timeout: '100'
-    type: complex
-    vlen: '1'
-  states:
-    bus_sink: false
-    bus_source: false
-    bus_structure: null
-    coordinate: [216, 308.0]
-    rotation: 0
-    state: true
-
-connections:
-- [blocks_throttle_0, '0', zeromq_rep_sink_0, '0']
-- [zeromq_req_source_0, '0', blocks_throttle_0, '0']
-
-metadata:
-  file_format: 1
diff --git a/tests/zmq/zmqtest.py b/tests/zmq/zmqtest.py
deleted file mode 100755
index a046c13..0000000
--- a/tests/zmq/zmqtest.py
+++ /dev/null
@@ -1,85 +0,0 @@
-#!/usr/bin/env python3
-# -*- coding: utf-8 -*-
-
-#
-# SPDX-License-Identifier: GPL-3.0
-#
-# GNU Radio Python Flow Graph
-# Title: ZMQ test
-# Author: Naoki Pross
-# GNU Radio version: 3.8.2.0
-
-from gnuradio import blocks
-from gnuradio import gr
-from gnuradio.filter import firdes
-import sys
-import signal
-from argparse import ArgumentParser
-from gnuradio.eng_arg import eng_float, intx
-from gnuradio import eng_notation
-from gnuradio import zeromq
-
-
-class zmqtest(gr.top_block):
-
-    def __init__(self):
-        gr.top_block.__init__(self, "ZMQ test")
-
-        ##################################################
-        # Variables
-        ##################################################
-        self.samp_rate = samp_rate = 32000
-
-        ##################################################
-        # Blocks
-        ##################################################
-        self.zeromq_req_source_0 = zeromq.req_source(gr.sizeof_gr_complex, 1, '', 100, False, -1)
-        self.zeromq_rep_sink_0 = zeromq.rep_sink(gr.sizeof_gr_complex, 1, '', 100, False, -1)
-        self.blocks_throttle_0 = blocks.throttle(gr.sizeof_gr_complex*1, samp_rate,True)
-
-
-
-        ##################################################
-        # Connections
-        ##################################################
-        self.connect((self.blocks_throttle_0, 0), (self.zeromq_rep_sink_0, 0))
-        self.connect((self.zeromq_req_source_0, 0), (self.blocks_throttle_0, 0))
-
-
-    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)
-
-
-
-
-
-def main(top_block_cls=zmqtest, options=None):
-    if gr.enable_realtime_scheduling() != gr.RT_OK:
-        print("Error: failed to enable real-time scheduling.")
-    tb = top_block_cls()
-
-    def sig_handler(sig=None, frame=None):
-        tb.stop()
-        tb.wait()
-
-        sys.exit(0)
-
-    signal.signal(signal.SIGINT, sig_handler)
-    signal.signal(signal.SIGTERM, sig_handler)
-
-    tb.start()
-
-    try:
-        input('Press Enter to quit: ')
-    except EOFError:
-        pass
-    tb.stop()
-    tb.wait()
-
-
-if __name__ == '__main__':
-    main()
-- 
cgit v1.2.1


From 834febb9aa0dac463f43914cb028be931f85de73 Mon Sep 17 00:00:00 2001
From: sara <sara.halter@gmx.ch>
Date: Thu, 2 Dec 2021 20:02:16 +0100
Subject: =?UTF-8?q?BER=20Block=20erstellt,=20l=C3=A4uft=20noch=20nichtwie?=
 =?UTF-8?q?=20gew=C3=BCnscht?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 tests/BER/Bit_error.grc         |  98 +++++++++++++++++++++++++++
 tests/BER/Test_Bit_Errorrate.py | 143 ++++++++++++++++++++++++++++++++++++++++
 tests/correlator/correlator.py  |   5 +-
 3 files changed, 245 insertions(+), 1 deletion(-)
 create mode 100644 tests/BER/Bit_error.grc
 create mode 100755 tests/BER/Test_Bit_Errorrate.py

(limited to 'tests')

diff --git a/tests/BER/Bit_error.grc b/tests/BER/Bit_error.grc
new file mode 100644
index 0000000..04c624b
--- /dev/null
+++ b/tests/BER/Bit_error.grc
@@ -0,0 +1,98 @@
+options:
+  parameters:
+    author: 'Sara Halter '
+    category: '[GRC Hier Blocks]'
+    cmake_opt: ''
+    comment: ''
+    copyright: ''
+    description: ''
+    gen_cmake: 'On'
+    gen_linking: dynamic
+    generate_options: qt_gui
+    hier_block_src_path: '.:'
+    id: Test_Bit_Errorrate
+    max_nouts: '0'
+    output_language: python
+    placement: (0,0)
+    qt_qss_theme: ''
+    realtime_scheduling: ''
+    run: 'True'
+    run_command: '{python} -u {filename}'
+    run_options: prompt
+    sizing_mode: fixed
+    thread_safe_setters: ''
+    title: 'Bit Error Rate test '
+    window_size: ''
+  states:
+    bus_sink: false
+    bus_source: false
+    bus_structure: null
+    coordinate: [8, 8]
+    rotation: 0
+    state: enabled
+
+blocks:
+- name: samp_rate
+  id: variable
+  parameters:
+    comment: ''
+    value: '32000'
+  states:
+    bus_sink: false
+    bus_source: false
+    bus_structure: null
+    coordinate: [184, 12]
+    rotation: 0
+    state: enabled
+- name: testvec
+  id: variable
+  parameters:
+    comment: ''
+    value: '[31, 53] + [0x12, 0xe3, 0x9b, 0xee, 0x84, 0x23, 0x41, 0xf3]'
+  states:
+    bus_sink: false
+    bus_source: false
+    bus_structure: null
+    coordinate: [216, 396.0]
+    rotation: 0
+    state: enabled
+- name: blocks_vector_source_x_0
+  id: blocks_vector_source_x
+  parameters:
+    affinity: ''
+    alias: ''
+    comment: ''
+    maxoutbuf: '0'
+    minoutbuf: '0'
+    repeat: 'True'
+    tags: '[]'
+    type: byte
+    vector: testvec * 1600
+    vlen: '1'
+  states:
+    bus_sink: false
+    bus_source: false
+    bus_structure: null
+    coordinate: [216, 276.0]
+    rotation: 0
+    state: enabled
+- name: fadingui_ber_0
+  id: fadingui_ber
+  parameters:
+    affinity: ''
+    alias: ''
+    comment: ''
+    vgl: testvec
+  states:
+    bus_sink: false
+    bus_source: false
+    bus_structure: null
+    coordinate: [704, 296.0]
+    rotation: 0
+    state: true
+
+connections:
+- [blocks_vector_source_x_0, '0', fadingui_ber_0, '0']
+
+metadata:
+  file_format: 1
diff --git a/tests/BER/Test_Bit_Errorrate.py b/tests/BER/Test_Bit_Errorrate.py
new file mode 100755
index 0000000..4022997
--- /dev/null
+++ b/tests/BER/Test_Bit_Errorrate.py
@@ -0,0 +1,143 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+
+#
+# SPDX-License-Identifier: GPL-3.0
+#
+# GNU Radio Python Flow Graph
+# Title: Bit Error Rate test
+# Author: Sara Halter
+# 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 gnuradio import blocks
+from gnuradio import gr
+from gnuradio.filter import firdes
+import sys
+import signal
+from PyQt5 import Qt
+from argparse import ArgumentParser
+from gnuradio.eng_arg import eng_float, intx
+from gnuradio import eng_notation
+import fadingui
+
+from gnuradio import qtgui
+
+class Test_Bit_Errorrate(gr.top_block, Qt.QWidget):
+
+    def __init__(self):
+        gr.top_block.__init__(self, "Bit Error Rate test ")
+        Qt.QWidget.__init__(self)
+        self.setWindowTitle("Bit Error Rate test ")
+        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", "Test_Bit_Errorrate")
+
+        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.testvec = testvec = [31, 53] + [0x12, 0xe3, 0x9b, 0xee, 0x84, 0x23, 0x41, 0xf3]
+        self.samp_rate = samp_rate = 32000
+
+        ##################################################
+        # Blocks
+        ##################################################
+        self.fadingui_ber_0 = fadingui.ber(vgl=testvec)
+        self.blocks_vector_source_x_0 = blocks.vector_source_b(testvec * 1600, True, 1, [])
+
+
+
+        ##################################################
+        # Connections
+        ##################################################
+        self.connect((self.blocks_vector_source_x_0, 0), (self.fadingui_ber_0, 0))
+
+
+    def closeEvent(self, event):
+        self.settings = Qt.QSettings("GNU Radio", "Test_Bit_Errorrate")
+        self.settings.setValue("geometry", self.saveGeometry())
+        event.accept()
+
+    def get_testvec(self):
+        return self.testvec
+
+    def set_testvec(self, testvec):
+        self.testvec = testvec
+        self.blocks_vector_source_x_0.set_data(self.testvec * 1600, [])
+
+    def get_samp_rate(self):
+        return self.samp_rate
+
+    def set_samp_rate(self, samp_rate):
+        self.samp_rate = samp_rate
+
+
+
+
+
+def main(top_block_cls=Test_Bit_Errorrate, options=None):
+
+    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()
diff --git a/tests/correlator/correlator.py b/tests/correlator/correlator.py
index a870cc0..67def9f 100755
--- a/tests/correlator/correlator.py
+++ b/tests/correlator/correlator.py
@@ -35,6 +35,7 @@ from argparse import ArgumentParser
 from gnuradio.eng_arg import eng_float, intx
 from gnuradio import eng_notation
 import epy_block_0
+import fadingui
 
 from gnuradio import qtgui
 
@@ -328,6 +329,7 @@ class correlator(gr.top_block, Qt.QWidget):
             self.top_grid_layout.setRowStretch(r, 1)
         for c in range(1, 2):
             self.top_grid_layout.setColumnStretch(c, 1)
+        self.fadingui_deframer_0 = fadingui.deframer(frame_obj=)
         self.epy_block_0 = epy_block_0.blk()
         self.digital_pfb_clock_sync_xxx_0 = digital.pfb_clock_sync_ccf(sps, timing_loop_bw, rrc_taps, nfilts, 16, 1.5, 1)
         self.digital_corr_est_cc_0 = digital.corr_est_cc(access_code_symbols, 1, 0, .8, digital.THRESHOLD_DYNAMIC)
@@ -370,7 +372,7 @@ class correlator(gr.top_block, Qt.QWidget):
         self.connect((self.channels_channel_model_0, 0), (self.blocks_throttle_0, 0))
         self.connect((self.digital_cma_equalizer_cc_0, 0), (self.digital_corr_est_cc_0, 0))
         self.connect((self.digital_cma_equalizer_cc_0, 0), (self.qtgui_const_sink_x_0, 0))
-        self.connect((self.digital_constellation_decoder_cb_0, 0), (self.blocks_vector_sink_x_0, 0))
+        self.connect((self.digital_constellation_decoder_cb_0, 0), (self.fadingui_deframer_0, 0))
         self.connect((self.digital_constellation_modulator_0, 0), (self.channels_channel_model_0, 0))
         self.connect((self.digital_constellation_modulator_0, 0), (self.qtgui_time_sink_x_1_0, 0))
         self.connect((self.digital_corr_est_cc_0, 1), (self.blocks_complex_to_magphase_0_0, 0))
@@ -379,6 +381,7 @@ class correlator(gr.top_block, Qt.QWidget):
         self.connect((self.digital_pfb_clock_sync_xxx_0, 0), (self.digital_cma_equalizer_cc_0, 0))
         self.connect((self.epy_block_0, 0), (self.digital_constellation_decoder_cb_0, 0))
         self.connect((self.epy_block_0, 0), (self.qtgui_const_sink_x_0_0, 0))
+        self.connect((self.fadingui_deframer_0, 0), (self.blocks_vector_sink_x_0, 0))
 
 
     def closeEvent(self, event):
-- 
cgit v1.2.1


From de7b4dac4af5ff592258f48eee72d191201826d7 Mon Sep 17 00:00:00 2001
From: Nao Pross <np@0hm.ch>
Date: Thu, 2 Dec 2021 21:24:33 +0100
Subject: Begin frequency correction (incomplete)

---
 tests/correlator/correlator.grc | 65 +++++++++++++++++++++--------------
 tests/correlator/correlator.py  |  3 +-
 tests/correlator/epy_block_0.py | 75 +++++++++++++++++++++++++++--------------
 3 files changed, 92 insertions(+), 51 deletions(-)

(limited to 'tests')

diff --git a/tests/correlator/correlator.grc b/tests/correlator/correlator.grc
index aa21770..58cf3b4 100644
--- a/tests/correlator/correlator.grc
+++ b/tests/correlator/correlator.grc
@@ -408,7 +408,7 @@ blocks:
     block_tags: 'False'
     comment: ''
     epsilon: '1.0'
-    freq_offset: '0.00001'
+    freq_offset: '0.0001'
     maxoutbuf: '0'
     minoutbuf: '0'
     noise_voltage: '0.2'
@@ -530,30 +530,45 @@ blocks:
       \ many samples were processed,\n        # because tags have an absolute offset\n\
       \        self.sampnr: np.complex64 = 0\n\n        # because of block processing\
       \ a tagged block could\n        # be split in half so we need to keep track\
-      \ of the\n        # \"previous\" values\n        self.last_phase = 0\n\n   \
-      \ def work(self, input_items, output_items):\n        # TODO: interpolate phase\
-      \ values for frequency correction\n\n        out = output_items[0]\n       \
-      \ inp = input_items[0]\n\n        # create a phase correction vector\n     \
-      \   phase = np.zeros(len(inp), dtype=np.float64)\n\n        # read tags\n  \
-      \      tags = self.get_tags_in_window(0, 0, len(inp))\n\n        # get only\
-      \ phase tags\n        is_phase = lambda tag: pmt.to_python(tag.key) == \"phase_est\"\
-      \n        phase_tags = list(filter(is_phase, tags))\n\n        print(f\"Processing\
-      \ {len(inp)} samples, with {len(phase_tags)} tags\")\n\n        # compute correction\
-      \ from previous block\n        first_tag = phase_tags[0]\n        first_idx\
-      \ = first_tag.offset - self.sampnr\n        phase[:first_idx] = self.last_phase\n\
-      \n        # iterate phase tags \"in the middle\"\n        for prev_tag, next_tag\
-      \ in zip(phase_tags, phase_tags[1:]):\n            # unpack pmt values\n   \
-      \         pval = pmt.to_python(prev_tag.value)\n\n            # compute indexes\
+      \ of the\n        # \"previous\" values\n        self.last_tag = None\n\n  \
+      \  def work(self, input_items, output_items):\n        # nicer aliases\n   \
+      \     out = output_items[0]\n        inp = input_items[0]\n\n        def print_phase_correction(start,\
+      \ end, phase, freq):\n            print(f\"Correction for block {start:3d} to\
+      \ {end:3d} is phase = {phase: 2.4f} rad, freq = {freq * 1e3: 2.4f} milli rad/samp\"\
+      )\n\n        # read only phase tags\n        tags = self.get_tags_in_window(0,\
+      \ 0, len(inp))\n\n        is_phase = lambda tag: pmt.to_python(tag.key) == \"\
+      phase_est\"\n        phase_tags = list(filter(is_phase, tags))\n\n        #\
+      \ FIXME: what if there are no tags? check that!\n\n        print(f\"Processing\
+      \ {len(inp)} samples, with {len(phase_tags)} tags\")\n\n        # create a phase\
+      \ correction vector\n        phase = np.zeros(len(inp), dtype=np.float64)\n\n\
+      \        # compute correction from previous block (if present)\n        if self.last_tag:\n\
+      \            # variables for first and last phase values\n            lval =\
+      \ pmt.to_python(self.last_tag.value)\n            fval = pmt.to_python(phase_tags[0].value)\n\
+      \n            # compute index for phase vector\n            fidx = phase_tags[0].offset\
+      \ - self.sampnr\n\n            # compute frequency offset\n            nsamples\
+      \ = phase_tags[0].offset - self.last_tag.offset\n            freq = (fval -\
+      \ lval) / nsamples\n\n            # total phase correction is: phase + freq\
+      \ * time\n            phase[:fidx] = lval * np.ones(fidx) + freq * np.arange(0,\
+      \ fidx)\n\n            # compute correction\n            print_phase_correction(0,\
+      \ fidx, lval, freq)\n\n        # iterate phase tags \"in the middle\"\n    \
+      \    # FIXME: what if there are less than 2 tags?\n        #        the code\
+      \ below will probably crash\n        for prev_tag, next_tag in zip(phase_tags,\
+      \ phase_tags[1:]):\n            # unpack pmt values\n            pval = pmt.to_python(prev_tag.value)\n\
+      \            nval = pmt.to_python(next_tag.value)\n\n            # compute indexes\
       \ in phase vector\n            pidx = prev_tag.offset - self.sampnr\n      \
-      \      idx = next_tag.offset - self.sampnr\n\n            # compute phase correction\
-      \ for block\n            phase[pidx:idx] = pval\n            print(f\"Correction\
-      \ for block {pidx} to {idx} is {pval}\")\n\n        # compute the remaining\
-      \ part of the block\n        last_tag = phase_tags[-1]\n        last_val = pmt.to_python(last_tag.value)\n\
-      \        last_idx = last_tag.offset - self.sampnr\n\n        phase[last_idx:]\
-      \ = last_val\n\n        # save values for next call\n        self.last_phase\
-      \ = last_val\n\n        # mark samples as processed and compute to output\n\
-      \        self.sampnr += len(inp)\n        out[:] = inp * np.exp(-1j * phase)\n\
-      \n        return len(out)\n"
+      \      nidx = next_tag.offset - self.sampnr\n\n            # compute frquency\
+      \ correction for block by linearly interpolating\n            # frame values\n\
+      \            nsamples = nidx - pidx\n            freq = (nval - pval) / nsamples\n\
+      \n            # total correction is: phase + freq * time\n            phase[pidx:nidx]\
+      \ = pval * np.ones(nsamples) + freq * np.arange(0, nsamples)\n            print_phase_correction(pidx,\
+      \ nidx, pval, freq)\n\n        # for the last block because the next tag is\
+      \ unknown (in the future) we\n        # cannot predict the frequency offset.\
+      \ Thus we save the last tag for\n        # the next call.\n        self.last_tag\
+      \ = phase_tags[-1]\n        val = pmt.to_python(self.last_tag.value)\n     \
+      \   idx = self.last_tag.offset - self.sampnr\n\n        phase[idx:] = val\n\n\
+      \        # compute correction\n        out[:] = inp * np.exp(-1j * phase)\n\n\
+      \        # increment processed samples counter\n        self.sampnr += len(inp)\n\
+      \        return len(phase)\n"
     affinity: ''
     alias: ''
     comment: ''
@@ -583,7 +598,7 @@ blocks:
     bus_structure: null
     coordinate: [552, 1388.0]
     rotation: 0
-    state: true
+    state: bypassed
 - name: fir_filter_xxx_1
   id: fir_filter_xxx
   parameters:
diff --git a/tests/correlator/correlator.py b/tests/correlator/correlator.py
index a870cc0..e8eaaa8 100755
--- a/tests/correlator/correlator.py
+++ b/tests/correlator/correlator.py
@@ -35,6 +35,7 @@ from argparse import ArgumentParser
 from gnuradio.eng_arg import eng_float, intx
 from gnuradio import eng_notation
 import epy_block_0
+import fadingui
 
 from gnuradio import qtgui
 
@@ -343,7 +344,7 @@ class correlator(gr.top_block, Qt.QWidget):
         self.digital_cma_equalizer_cc_0 = digital.cma_equalizer_cc(15, 1, .002, 1)
         self.channels_channel_model_0 = channels.channel_model(
             noise_voltage=0.2,
-            frequency_offset=0.00001,
+            frequency_offset=0.0001,
             epsilon=1.0,
             taps=[-1.4 + .4j],
             noise_seed=243,
diff --git a/tests/correlator/epy_block_0.py b/tests/correlator/epy_block_0.py
index 1fa4794..90ad75e 100644
--- a/tests/correlator/epy_block_0.py
+++ b/tests/correlator/epy_block_0.py
@@ -20,56 +20,81 @@ class blk(gr.sync_block):
         # because of block processing a tagged block could
         # be split in half so we need to keep track of the
         # "previous" values
-        self.last_phase = 0
+        self.last_tag = None
 
     def work(self, input_items, output_items):
-        # TODO: interpolate phase values for frequency correction
-
+        # nicer aliases
         out = output_items[0]
         inp = input_items[0]
 
-        # create a phase correction vector
-        phase = np.zeros(len(inp), dtype=np.float64)
+        def print_phase_correction(start, end, phase, freq):
+            print(f"Correction for block {start:3d} to {end:3d} is phase = {phase: 2.4f} rad, freq = {freq * 1e3: 2.4f} milli rad/samp")
 
-        # read tags
+        # read only phase tags
         tags = self.get_tags_in_window(0, 0, len(inp))
 
-        # get only phase tags
         is_phase = lambda tag: pmt.to_python(tag.key) == "phase_est"
         phase_tags = list(filter(is_phase, tags))
 
+        # FIXME: what if there are no tags? check that!
+
         print(f"Processing {len(inp)} samples, with {len(phase_tags)} tags")
 
-        # compute correction from previous block
-        first_tag = phase_tags[0]
-        first_idx = first_tag.offset - self.sampnr
-        phase[:first_idx] = self.last_phase
+        # create a phase correction vector
+        phase = np.zeros(len(inp), dtype=np.float64)
+
+        # compute correction from previous block (if present)
+        if self.last_tag:
+            # variables for first and last phase values
+            lval = pmt.to_python(self.last_tag.value)
+            fval = pmt.to_python(phase_tags[0].value)
+
+            # compute index for phase vector
+            fidx = phase_tags[0].offset - self.sampnr
+
+            # compute frequency offset
+            nsamples = phase_tags[0].offset - self.last_tag.offset
+            freq = (fval - lval) / nsamples
+
+            # total phase correction is: phase + freq * time
+            phase[:fidx] = lval * np.ones(fidx) + freq * np.arange(0, fidx)
+
+            # compute correction
+            print_phase_correction(0, fidx, lval, freq)
 
         # iterate phase tags "in the middle"
+        # FIXME: what if there are less than 2 tags?
+        #        the code below will probably crash
         for prev_tag, next_tag in zip(phase_tags, phase_tags[1:]):
             # unpack pmt values
             pval = pmt.to_python(prev_tag.value)
+            nval = pmt.to_python(next_tag.value)
 
             # compute indexes in phase vector
             pidx = prev_tag.offset - self.sampnr
-            idx = next_tag.offset - self.sampnr
+            nidx = next_tag.offset - self.sampnr
 
-            # compute phase correction for block
-            phase[pidx:idx] = pval
-            print(f"Correction for block {pidx} to {idx} is {pval}")
+            # compute frquency correction for block by linearly interpolating
+            # frame values
+            nsamples = nidx - pidx
+            freq = (nval - pval) / nsamples
 
-        # compute the remaining part of the block
-        last_tag = phase_tags[-1]
-        last_val = pmt.to_python(last_tag.value)
-        last_idx = last_tag.offset - self.sampnr
+            # total correction is: phase + freq * time
+            phase[pidx:nidx] = pval * np.ones(nsamples) + freq * np.arange(0, nsamples)
+            print_phase_correction(pidx, nidx, pval, freq)
 
-        phase[last_idx:] = last_val
+        # for the last block because the next tag is unknown (in the future) we
+        # cannot predict the frequency offset. Thus we save the last tag for
+        # the next call.
+        self.last_tag = phase_tags[-1]
+        val = pmt.to_python(self.last_tag.value)
+        idx = self.last_tag.offset - self.sampnr
 
-        # save values for next call
-        self.last_phase = last_val
+        phase[idx:] = val
 
-        # mark samples as processed and compute to output
-        self.sampnr += len(inp)
+        # compute correction
         out[:] = inp * np.exp(-1j * phase)
 
-        return len(out)
+        # increment processed samples counter
+        self.sampnr += len(inp)
+        return len(phase)
-- 
cgit v1.2.1


From 6d56e1b35b061ffe4f677d0d6e7867f366068e82 Mon Sep 17 00:00:00 2001
From: Nao Pross <np@0hm.ch>
Date: Thu, 2 Dec 2021 21:27:17 +0100
Subject: Remove custom blocks from correlator test

---
 tests/correlator/correlator.grc | 21 ++-------------------
 tests/correlator/correlator.py  |  5 +----
 2 files changed, 3 insertions(+), 23 deletions(-)

(limited to 'tests')

diff --git a/tests/correlator/correlator.grc b/tests/correlator/correlator.grc
index 58cf3b4..f54430c 100644
--- a/tests/correlator/correlator.grc
+++ b/tests/correlator/correlator.grc
@@ -357,7 +357,7 @@ blocks:
     bus_sink: false
     bus_source: false
     bus_structure: null
-    coordinate: [840, 1392.0]
+    coordinate: [536, 1392.0]
     rotation: 0
     state: true
 - name: blocks_vector_source_x_0
@@ -583,22 +583,6 @@ blocks:
     coordinate: [1088, 1040.0]
     rotation: 0
     state: enabled
-- name: fadingui_deframer_0
-  id: fadingui_deframer
-  parameters:
-    affinity: ''
-    alias: ''
-    comment: ''
-    frame_obj: ''
-    maxoutbuf: '0'
-    minoutbuf: '0'
-  states:
-    bus_sink: false
-    bus_source: false
-    bus_structure: null
-    coordinate: [552, 1388.0]
-    rotation: 0
-    state: bypassed
 - name: fir_filter_xxx_1
   id: fir_filter_xxx
   parameters:
@@ -1668,7 +1652,7 @@ connections:
 - [digital_cma_equalizer_cc_0, '0', fir_filter_xxx_1, '0']
 - [digital_cma_equalizer_cc_0, '0', qtgui_const_sink_x_0, '0']
 - [digital_cma_equalizer_cc_0, '0', qtgui_time_sink_x_1_1, '0']
-- [digital_constellation_decoder_cb_0, '0', fadingui_deframer_0, '0']
+- [digital_constellation_decoder_cb_0, '0', blocks_vector_sink_x_0, '0']
 - [digital_constellation_modulator_0, '0', blocks_stream_mux_1, '1']
 - [digital_constellation_modulator_0, '0', channels_channel_model_0, '0']
 - [digital_constellation_modulator_0, '0', qtgui_time_sink_x_1_0, '0']
@@ -1678,7 +1662,6 @@ connections:
 - [digital_pfb_clock_sync_xxx_0, '0', digital_cma_equalizer_cc_0, '0']
 - [epy_block_0, '0', qtgui_const_sink_x_0_0, '0']
 - [epy_block_0, '0', virtual_sink_3, '0']
-- [fadingui_deframer_0, '0', blocks_vector_sink_x_0, '0']
 - [fir_filter_xxx_1, '0', blocks_complex_to_magphase_0, '0']
 - [fir_filter_xxx_1, '0', qtgui_const_sink_x_1, '0']
 - [root_raised_cosine_filter_0, '0', blocks_stream_mux_1, '0']
diff --git a/tests/correlator/correlator.py b/tests/correlator/correlator.py
index 93ee8bb..e080dbc 100755
--- a/tests/correlator/correlator.py
+++ b/tests/correlator/correlator.py
@@ -35,7 +35,6 @@ from argparse import ArgumentParser
 from gnuradio.eng_arg import eng_float, intx
 from gnuradio import eng_notation
 import epy_block_0
-import fadingui
 
 from gnuradio import qtgui
 
@@ -329,7 +328,6 @@ class correlator(gr.top_block, Qt.QWidget):
             self.top_grid_layout.setRowStretch(r, 1)
         for c in range(1, 2):
             self.top_grid_layout.setColumnStretch(c, 1)
-        self.fadingui_deframer_0 = fadingui.deframer(frame_obj=)
         self.epy_block_0 = epy_block_0.blk()
         self.digital_pfb_clock_sync_xxx_0 = digital.pfb_clock_sync_ccf(sps, timing_loop_bw, rrc_taps, nfilts, 16, 1.5, 1)
         self.digital_corr_est_cc_0 = digital.corr_est_cc(access_code_symbols, 1, 0, .8, digital.THRESHOLD_DYNAMIC)
@@ -372,7 +370,7 @@ class correlator(gr.top_block, Qt.QWidget):
         self.connect((self.channels_channel_model_0, 0), (self.blocks_throttle_0, 0))
         self.connect((self.digital_cma_equalizer_cc_0, 0), (self.digital_corr_est_cc_0, 0))
         self.connect((self.digital_cma_equalizer_cc_0, 0), (self.qtgui_const_sink_x_0, 0))
-        self.connect((self.digital_constellation_decoder_cb_0, 0), (self.fadingui_deframer_0, 0))
+        self.connect((self.digital_constellation_decoder_cb_0, 0), (self.blocks_vector_sink_x_0, 0))
         self.connect((self.digital_constellation_modulator_0, 0), (self.channels_channel_model_0, 0))
         self.connect((self.digital_constellation_modulator_0, 0), (self.qtgui_time_sink_x_1_0, 0))
         self.connect((self.digital_corr_est_cc_0, 1), (self.blocks_complex_to_magphase_0_0, 0))
@@ -381,7 +379,6 @@ class correlator(gr.top_block, Qt.QWidget):
         self.connect((self.digital_pfb_clock_sync_xxx_0, 0), (self.digital_cma_equalizer_cc_0, 0))
         self.connect((self.epy_block_0, 0), (self.digital_constellation_decoder_cb_0, 0))
         self.connect((self.epy_block_0, 0), (self.qtgui_const_sink_x_0_0, 0))
-        self.connect((self.fadingui_deframer_0, 0), (self.blocks_vector_sink_x_0, 0))
 
 
     def closeEvent(self, event):
-- 
cgit v1.2.1


From 3718e92fe6418e33a7e8d53192383d021d20c524 Mon Sep 17 00:00:00 2001
From: Nao Pross <np@0hm.ch>
Date: Fri, 3 Dec 2021 00:18:55 +0100
Subject: Refractor frequency correction

---
 tests/correlator/correlator.grc |  82 +++++++++++++-------------
 tests/correlator/epy_block_0.py | 124 ++++++++++++++++++----------------------
 2 files changed, 95 insertions(+), 111 deletions(-)

(limited to 'tests')

diff --git a/tests/correlator/correlator.grc b/tests/correlator/correlator.grc
index f54430c..57c1762 100644
--- a/tests/correlator/correlator.grc
+++ b/tests/correlator/correlator.grc
@@ -526,49 +526,45 @@ blocks:
     _source_code: "import pmt\n\nimport numpy as np\nfrom gnuradio import gr\n\n\n\
       class blk(gr.sync_block):\n    def __init__(self):\n        gr.sync_block.__init__(\n\
       \            self,\n            name='Phase Lock',\n            in_sig=[np.complex64],\n\
-      \            out_sig=[np.complex64]\n        )\n\n        # keep track of how\
-      \ many samples were processed,\n        # because tags have an absolute offset\n\
-      \        self.sampnr: np.complex64 = 0\n\n        # because of block processing\
-      \ a tagged block could\n        # be split in half so we need to keep track\
-      \ of the\n        # \"previous\" values\n        self.last_tag = None\n\n  \
-      \  def work(self, input_items, output_items):\n        # nicer aliases\n   \
-      \     out = output_items[0]\n        inp = input_items[0]\n\n        def print_phase_correction(start,\
-      \ end, phase, freq):\n            print(f\"Correction for block {start:3d} to\
-      \ {end:3d} is phase = {phase: 2.4f} rad, freq = {freq * 1e3: 2.4f} milli rad/samp\"\
-      )\n\n        # read only phase tags\n        tags = self.get_tags_in_window(0,\
-      \ 0, len(inp))\n\n        is_phase = lambda tag: pmt.to_python(tag.key) == \"\
-      phase_est\"\n        phase_tags = list(filter(is_phase, tags))\n\n        #\
-      \ FIXME: what if there are no tags? check that!\n\n        print(f\"Processing\
-      \ {len(inp)} samples, with {len(phase_tags)} tags\")\n\n        # create a phase\
-      \ correction vector\n        phase = np.zeros(len(inp), dtype=np.float64)\n\n\
-      \        # compute correction from previous block (if present)\n        if self.last_tag:\n\
-      \            # variables for first and last phase values\n            lval =\
-      \ pmt.to_python(self.last_tag.value)\n            fval = pmt.to_python(phase_tags[0].value)\n\
-      \n            # compute index for phase vector\n            fidx = phase_tags[0].offset\
-      \ - self.sampnr\n\n            # compute frequency offset\n            nsamples\
-      \ = phase_tags[0].offset - self.last_tag.offset\n            freq = (fval -\
-      \ lval) / nsamples\n\n            # total phase correction is: phase + freq\
-      \ * time\n            phase[:fidx] = lval * np.ones(fidx) + freq * np.arange(0,\
-      \ fidx)\n\n            # compute correction\n            print_phase_correction(0,\
-      \ fidx, lval, freq)\n\n        # iterate phase tags \"in the middle\"\n    \
-      \    # FIXME: what if there are less than 2 tags?\n        #        the code\
-      \ below will probably crash\n        for prev_tag, next_tag in zip(phase_tags,\
-      \ phase_tags[1:]):\n            # unpack pmt values\n            pval = pmt.to_python(prev_tag.value)\n\
-      \            nval = pmt.to_python(next_tag.value)\n\n            # compute indexes\
-      \ in phase vector\n            pidx = prev_tag.offset - self.sampnr\n      \
-      \      nidx = next_tag.offset - self.sampnr\n\n            # compute frquency\
-      \ correction for block by linearly interpolating\n            # frame values\n\
-      \            nsamples = nidx - pidx\n            freq = (nval - pval) / nsamples\n\
-      \n            # total correction is: phase + freq * time\n            phase[pidx:nidx]\
-      \ = pval * np.ones(nsamples) + freq * np.arange(0, nsamples)\n            print_phase_correction(pidx,\
-      \ nidx, pval, freq)\n\n        # for the last block because the next tag is\
-      \ unknown (in the future) we\n        # cannot predict the frequency offset.\
-      \ Thus we save the last tag for\n        # the next call.\n        self.last_tag\
-      \ = phase_tags[-1]\n        val = pmt.to_python(self.last_tag.value)\n     \
-      \   idx = self.last_tag.offset - self.sampnr\n\n        phase[idx:] = val\n\n\
-      \        # compute correction\n        out[:] = inp * np.exp(-1j * phase)\n\n\
-      \        # increment processed samples counter\n        self.sampnr += len(inp)\n\
-      \        return len(phase)\n"
+      \            out_sig=[np.complex64]\n        )\n\n        # we need to keep\
+      \ track of the aboslute number of samples that have\n        # been processed,\
+      \ because tags have an absolute offset\n        self.counter: np.uint64 = 0\n\
+      \n        # because we do block processing, we need to keep track of the last\
+      \ tag\n        # of the previous block to correct the first values of the next\
+      \ block\n        self.last = None\n\n    def block_phase(self, start, end):\n\
+      \        # compute number of samples in block\n        nsamples = end.offset\
+      \ - start.offset\n\n        # unpack pmt values into start and end phase\n \
+      \       sphase = pmt.to_python(start.value)\n        ephase = pmt.to_python(end.value)\n\
+      \n        # compute frequency offset between start and end\n        freq = (sphase\
+      \ - ephase) / nsamples\n\n        # debugging\n        print(f\"Correction for\
+      \ block of {nsamples:2d} samples is \" \\\n              f\"phase={sphase: .4f}\
+      \ rad and freq={freq*1e3: .4f} milli rad / sample\")\n\n        # compute block\
+      \ values\n        return sphase * np.ones(nsamples) + freq * np.arange(0, nsamples)\n\
+      \n    def work(self, input_items, output_items):\n        # FIXME: replace class\
+      \ counter with local variable\n        # self.counter = self.nitems_written(0)\n\
+      \n        # nicer aliases\n        inp = input_items[0]\n        out = output_items[0]\n\
+      \n        # read phase tags\n        is_phase = lambda tag: pmt.to_python(tag.key)\
+      \ == \"phase_est\"\n        tags = list(filter(is_phase, self.get_tags_in_window(0,\
+      \ 0, len(inp))))\n\n        # debugging\n        print(f\"Processing {len(tags)}\
+      \ tags = {tags[-1].offset - tags[0].offset} \" \\\n              f\"samples\
+      \ out of {len(inp)} input samples\")\n\n        # compute \"the middle\"\n \
+      \       enough_samples = lambda pair: ((pair[1].offset - pair[0].offset) > 0)\n\
+      \        pairs = list(filter(enough_samples, zip(tags, tags[1:])))\n       \
+      \ blocks = [ self.block_phase(start, end) for (start, end) in pairs ]\n    \
+      \    middle = np.concatenate(blocks) if blocks else []\n\n        # compute\
+      \ the remainder from the previous call\n        nfront = tags[0].offset - self.counter\n\
+      \        print(f\"Processing {nfront} samples at the front of the buffer\")\n\
+      \        start = self.block_phase(self.last, tags[0])[-nfront:] \\\n       \
+      \         if self.last else np.zeros(nfront)\n\n        # compute values at\
+      \ the end\n        nback = len(inp) - (tags[-1].offset - self.counter)\n   \
+      \     print(f\"Processing {nback} samples at the back of the buffer\")\n   \
+      \     end = np.ones(nback) * pmt.to_python(tags[-1].value)\n\n        # compute\
+      \ correction\n        correction = np.exp(-1j * np.concatenate([start, middle,\
+      \ end]))\n        length = len(correction)\n\n        # write outputs\n    \
+      \    out[:length] = inp[:length] * correction\n        self.counter += len(inp)\n\
+      \n        # save last tag for next call\n        self.last = tags[-1]\n\n  \
+      \      # FIXME: should return `length' but then the last sample is not\n   \
+      \     #        included and self.last does something weird\n        return len(out)\n"
     affinity: ''
     alias: ''
     comment: ''
diff --git a/tests/correlator/epy_block_0.py b/tests/correlator/epy_block_0.py
index 90ad75e..9cb25bb 100644
--- a/tests/correlator/epy_block_0.py
+++ b/tests/correlator/epy_block_0.py
@@ -13,88 +13,76 @@ class blk(gr.sync_block):
             out_sig=[np.complex64]
         )
 
-        # keep track of how many samples were processed,
-        # because tags have an absolute offset
-        self.sampnr: np.complex64 = 0
+        # we need to keep track of the aboslute number of samples that have
+        # been processed, because tags have an absolute offset
+        self.counter: np.uint64 = 0
 
-        # because of block processing a tagged block could
-        # be split in half so we need to keep track of the
-        # "previous" values
-        self.last_tag = None
+        # because we do block processing, we need to keep track of the last tag
+        # of the previous block to correct the first values of the next block
+        self.last = None
 
-    def work(self, input_items, output_items):
-        # nicer aliases
-        out = output_items[0]
-        inp = input_items[0]
-
-        def print_phase_correction(start, end, phase, freq):
-            print(f"Correction for block {start:3d} to {end:3d} is phase = {phase: 2.4f} rad, freq = {freq * 1e3: 2.4f} milli rad/samp")
-
-        # read only phase tags
-        tags = self.get_tags_in_window(0, 0, len(inp))
-
-        is_phase = lambda tag: pmt.to_python(tag.key) == "phase_est"
-        phase_tags = list(filter(is_phase, tags))
+    def block_phase(self, start, end):
+        # compute number of samples in block
+        nsamples = end.offset - start.offset
 
-        # FIXME: what if there are no tags? check that!
+        # unpack pmt values into start and end phase
+        sphase = pmt.to_python(start.value)
+        ephase = pmt.to_python(end.value)
 
-        print(f"Processing {len(inp)} samples, with {len(phase_tags)} tags")
+        # compute frequency offset between start and end
+        freq = (sphase - ephase) / nsamples
 
-        # create a phase correction vector
-        phase = np.zeros(len(inp), dtype=np.float64)
+        # debugging
+        print(f"Correction for block of {nsamples:2d} samples is " \
+              f"phase={sphase: .4f} rad and freq={freq*1e3: .4f} milli rad / sample")
 
-        # compute correction from previous block (if present)
-        if self.last_tag:
-            # variables for first and last phase values
-            lval = pmt.to_python(self.last_tag.value)
-            fval = pmt.to_python(phase_tags[0].value)
+        # compute block values
+        return sphase * np.ones(nsamples) + freq * np.arange(0, nsamples)
 
-            # compute index for phase vector
-            fidx = phase_tags[0].offset - self.sampnr
-
-            # compute frequency offset
-            nsamples = phase_tags[0].offset - self.last_tag.offset
-            freq = (fval - lval) / nsamples
+    def work(self, input_items, output_items):
+        # FIXME: replace class counter with local variable
+        # self.counter = self.nitems_written(0)
 
-            # total phase correction is: phase + freq * time
-            phase[:fidx] = lval * np.ones(fidx) + freq * np.arange(0, fidx)
+        # nicer aliases
+        inp = input_items[0]
+        out = output_items[0]
 
-            # compute correction
-            print_phase_correction(0, fidx, lval, freq)
+        # read phase tags
+        is_phase = lambda tag: pmt.to_python(tag.key) == "phase_est"
+        tags = list(filter(is_phase, self.get_tags_in_window(0, 0, len(inp))))
 
-        # iterate phase tags "in the middle"
-        # FIXME: what if there are less than 2 tags?
-        #        the code below will probably crash
-        for prev_tag, next_tag in zip(phase_tags, phase_tags[1:]):
-            # unpack pmt values
-            pval = pmt.to_python(prev_tag.value)
-            nval = pmt.to_python(next_tag.value)
+        # debugging
+        print(f"Processing {len(tags)} tags = {tags[-1].offset - tags[0].offset} " \
+              f"samples out of {len(inp)} input samples")
 
-            # compute indexes in phase vector
-            pidx = prev_tag.offset - self.sampnr
-            nidx = next_tag.offset - self.sampnr
+        # compute "the middle"
+        enough_samples = lambda pair: ((pair[1].offset - pair[0].offset) > 0)
+        pairs = list(filter(enough_samples, zip(tags, tags[1:])))
+        blocks = [ self.block_phase(start, end) for (start, end) in pairs ]
+        middle = np.concatenate(blocks) if blocks else []
 
-            # compute frquency correction for block by linearly interpolating
-            # frame values
-            nsamples = nidx - pidx
-            freq = (nval - pval) / nsamples
+        # compute the remainder from the previous call
+        nfront = tags[0].offset - self.counter
+        print(f"Processing {nfront} samples at the front of the buffer")
+        start = self.block_phase(self.last, tags[0])[-nfront:] \
+                if self.last else np.zeros(nfront)
 
-            # total correction is: phase + freq * time
-            phase[pidx:nidx] = pval * np.ones(nsamples) + freq * np.arange(0, nsamples)
-            print_phase_correction(pidx, nidx, pval, freq)
+        # compute values at the end
+        nback = len(inp) - (tags[-1].offset - self.counter)
+        print(f"Processing {nback} samples at the back of the buffer")
+        end = np.ones(nback) * pmt.to_python(tags[-1].value)
 
-        # for the last block because the next tag is unknown (in the future) we
-        # cannot predict the frequency offset. Thus we save the last tag for
-        # the next call.
-        self.last_tag = phase_tags[-1]
-        val = pmt.to_python(self.last_tag.value)
-        idx = self.last_tag.offset - self.sampnr
+        # compute correction
+        correction = np.exp(-1j * np.concatenate([start, middle, end]))
+        length = len(correction)
 
-        phase[idx:] = val
+        # write outputs
+        out[:length] = inp[:length] * correction
+        self.counter += len(inp)
 
-        # compute correction
-        out[:] = inp * np.exp(-1j * phase)
+        # save last tag for next call
+        self.last = tags[-1]
 
-        # increment processed samples counter
-        self.sampnr += len(inp)
-        return len(phase)
+        # FIXME: should return `length' but then the last sample is not
+        #        included and self.last does something weird
+        return len(out)
-- 
cgit v1.2.1


From 5d2f01fe71b736f2f5bb8a57bb2f4cd383290e9f Mon Sep 17 00:00:00 2001
From: Nao Pross <np@0hm.ch>
Date: Fri, 3 Dec 2021 00:29:03 +0100
Subject: Fix bug when tag is aligned with inp block

---
 tests/correlator/correlator.grc | 12 ++++++------
 tests/correlator/correlator.py  |  2 +-
 tests/correlator/epy_block_0.py |  4 ++--
 3 files changed, 9 insertions(+), 9 deletions(-)

(limited to 'tests')

diff --git a/tests/correlator/correlator.grc b/tests/correlator/correlator.grc
index 57c1762..5a73092 100644
--- a/tests/correlator/correlator.grc
+++ b/tests/correlator/correlator.grc
@@ -408,7 +408,7 @@ blocks:
     block_tags: 'False'
     comment: ''
     epsilon: '1.0'
-    freq_offset: '0.0001'
+    freq_offset: '0.0002'
     maxoutbuf: '0'
     minoutbuf: '0'
     noise_voltage: '0.2'
@@ -541,7 +541,7 @@ blocks:
       \ rad and freq={freq*1e3: .4f} milli rad / sample\")\n\n        # compute block\
       \ values\n        return sphase * np.ones(nsamples) + freq * np.arange(0, nsamples)\n\
       \n    def work(self, input_items, output_items):\n        # FIXME: replace class\
-      \ counter with local variable\n        # self.counter = self.nitems_written(0)\n\
+      \ counter with local variable\n        self.counter = self.nitems_written(0)\n\
       \n        # nicer aliases\n        inp = input_items[0]\n        out = output_items[0]\n\
       \n        # read phase tags\n        is_phase = lambda tag: pmt.to_python(tag.key)\
       \ == \"phase_est\"\n        tags = list(filter(is_phase, self.get_tags_in_window(0,\
@@ -555,10 +555,10 @@ blocks:
       \ the remainder from the previous call\n        nfront = tags[0].offset - self.counter\n\
       \        print(f\"Processing {nfront} samples at the front of the buffer\")\n\
       \        start = self.block_phase(self.last, tags[0])[-nfront:] \\\n       \
-      \         if self.last else np.zeros(nfront)\n\n        # compute values at\
-      \ the end\n        nback = len(inp) - (tags[-1].offset - self.counter)\n   \
-      \     print(f\"Processing {nback} samples at the back of the buffer\")\n   \
-      \     end = np.ones(nback) * pmt.to_python(tags[-1].value)\n\n        # compute\
+      \         if self.last and nfront else np.zeros(nfront)\n\n        # compute\
+      \ values at the end\n        nback = len(inp) - (tags[-1].offset - self.counter)\n\
+      \        print(f\"Processing {nback} samples at the back of the buffer\")\n\
+      \        end = np.ones(nback) * pmt.to_python(tags[-1].value)\n\n        # compute\
       \ correction\n        correction = np.exp(-1j * np.concatenate([start, middle,\
       \ end]))\n        length = len(correction)\n\n        # write outputs\n    \
       \    out[:length] = inp[:length] * correction\n        self.counter += len(inp)\n\
diff --git a/tests/correlator/correlator.py b/tests/correlator/correlator.py
index e080dbc..536ac00 100755
--- a/tests/correlator/correlator.py
+++ b/tests/correlator/correlator.py
@@ -343,7 +343,7 @@ class correlator(gr.top_block, Qt.QWidget):
         self.digital_cma_equalizer_cc_0 = digital.cma_equalizer_cc(15, 1, .002, 1)
         self.channels_channel_model_0 = channels.channel_model(
             noise_voltage=0.2,
-            frequency_offset=0.0001,
+            frequency_offset=0.0002,
             epsilon=1.0,
             taps=[-1.4 + .4j],
             noise_seed=243,
diff --git a/tests/correlator/epy_block_0.py b/tests/correlator/epy_block_0.py
index 9cb25bb..abf4486 100644
--- a/tests/correlator/epy_block_0.py
+++ b/tests/correlator/epy_block_0.py
@@ -41,7 +41,7 @@ class blk(gr.sync_block):
 
     def work(self, input_items, output_items):
         # FIXME: replace class counter with local variable
-        # self.counter = self.nitems_written(0)
+        self.counter = self.nitems_written(0)
 
         # nicer aliases
         inp = input_items[0]
@@ -65,7 +65,7 @@ class blk(gr.sync_block):
         nfront = tags[0].offset - self.counter
         print(f"Processing {nfront} samples at the front of the buffer")
         start = self.block_phase(self.last, tags[0])[-nfront:] \
-                if self.last else np.zeros(nfront)
+                if self.last and nfront else np.zeros(nfront)
 
         # compute values at the end
         nback = len(inp) - (tags[-1].offset - self.counter)
-- 
cgit v1.2.1


From edf08d1815772fc985a89c976a190b3fcd6fb087 Mon Sep 17 00:00:00 2001
From: Nao Pross <np@0hm.ch>
Date: Fri, 3 Dec 2021 00:45:23 +0100
Subject: Add a LPF on the frequency

---
 tests/correlator/correlator.grc | 52 ++++++++++++++++++++++++-----------------
 tests/correlator/correlator.py  |  2 +-
 tests/correlator/epy_block_0.py | 26 ++++++++++++++++-----
 3 files changed, 51 insertions(+), 29 deletions(-)

(limited to 'tests')

diff --git a/tests/correlator/correlator.grc b/tests/correlator/correlator.grc
index 5a73092..bf44544 100644
--- a/tests/correlator/correlator.grc
+++ b/tests/correlator/correlator.grc
@@ -163,7 +163,7 @@ blocks:
   id: variable
   parameters:
     comment: ''
-    value: '[31, 53] + [0x12, 0xe3, 0x9b, 0xee, 0x84, 0x23, 0x41, 0xf3]'
+    value: '[31, 53] + [0x12, 0xe3, 0x9b, 0xee, 0x84, 0x23, 0x41, 0xf3] * 2'
   states:
     bus_sink: false
     bus_source: false
@@ -531,17 +531,23 @@ blocks:
       \ because tags have an absolute offset\n        self.counter: np.uint64 = 0\n\
       \n        # because we do block processing, we need to keep track of the last\
       \ tag\n        # of the previous block to correct the first values of the next\
-      \ block\n        self.last = None\n\n    def block_phase(self, start, end):\n\
-      \        # compute number of samples in block\n        nsamples = end.offset\
-      \ - start.offset\n\n        # unpack pmt values into start and end phase\n \
-      \       sphase = pmt.to_python(start.value)\n        ephase = pmt.to_python(end.value)\n\
-      \n        # compute frequency offset between start and end\n        freq = (sphase\
-      \ - ephase) / nsamples\n\n        # debugging\n        print(f\"Correction for\
-      \ block of {nsamples:2d} samples is \" \\\n              f\"phase={sphase: .4f}\
-      \ rad and freq={freq*1e3: .4f} milli rad / sample\")\n\n        # compute block\
-      \ values\n        return sphase * np.ones(nsamples) + freq * np.arange(0, nsamples)\n\
-      \n    def work(self, input_items, output_items):\n        # FIXME: replace class\
-      \ counter with local variable\n        self.counter = self.nitems_written(0)\n\
+      \ block\n        self.last = None\n\n        # to compute the values that are\
+      \ at the end we need to know the frequency\n        # of the last block\n  \
+      \      self.freq = 1\n\n    def block_phase(self, start, end):\n        # compute\
+      \ number of samples in block\n        nsamples = end.offset - start.offset\n\
+      \n        # unpack pmt values into start and end phase\n        sphase = pmt.to_python(start.value)\n\
+      \        ephase = pmt.to_python(end.value)\n\n        # compute frequency offset\
+      \ between start and end\n        freq = (sphase - ephase) / nsamples\n\n   \
+      \     # save this frequency values to compute the end block, unless frequency\n\
+      \        # has changed too fast, in that case replace the current values with\n\
+      \        # the previous one . This is effectively like a low pass filter.\n\
+      \        if abs(freq / self.freq) > 4:\n            freq = self.freq\n     \
+      \   else:\n            self.freq = freq\n\n\n        # debugging\n        print(f\"\
+      Correction for block of {nsamples:2d} samples is \" \\\n              f\"phase={sphase:\
+      \ .4f} rad and freq={freq*1e3: .4f} milli rad / sample\")\n\n        # compute\
+      \ block values\n        return sphase * np.ones(nsamples) + freq * np.arange(0,\
+      \ nsamples)\n\n    def work(self, input_items, output_items):\n        # FIXME:\
+      \ replace class counter with local variable\n        self.counter = self.nitems_written(0)\n\
       \n        # nicer aliases\n        inp = input_items[0]\n        out = output_items[0]\n\
       \n        # read phase tags\n        is_phase = lambda tag: pmt.to_python(tag.key)\
       \ == \"phase_est\"\n        tags = list(filter(is_phase, self.get_tags_in_window(0,\
@@ -552,16 +558,18 @@ blocks:
       \        pairs = list(filter(enough_samples, zip(tags, tags[1:])))\n       \
       \ blocks = [ self.block_phase(start, end) for (start, end) in pairs ]\n    \
       \    middle = np.concatenate(blocks) if blocks else []\n\n        # compute\
-      \ the remainder from the previous call\n        nfront = tags[0].offset - self.counter\n\
-      \        print(f\"Processing {nfront} samples at the front of the buffer\")\n\
-      \        start = self.block_phase(self.last, tags[0])[-nfront:] \\\n       \
-      \         if self.last and nfront else np.zeros(nfront)\n\n        # compute\
-      \ values at the end\n        nback = len(inp) - (tags[-1].offset - self.counter)\n\
-      \        print(f\"Processing {nback} samples at the back of the buffer\")\n\
-      \        end = np.ones(nback) * pmt.to_python(tags[-1].value)\n\n        # compute\
-      \ correction\n        correction = np.exp(-1j * np.concatenate([start, middle,\
-      \ end]))\n        length = len(correction)\n\n        # write outputs\n    \
-      \    out[:length] = inp[:length] * correction\n        self.counter += len(inp)\n\
+      \ values at the end, we do not have informations about the future\n        #\
+      \ but we can use the frequency of the last block to approximate\n        nback\
+      \ = len(inp) - (tags[-1].offset - self.counter)\n        print(f\"Processing\
+      \ {nback} samples at the back of the buffer\")\n        end = np.ones(nback)\
+      \ * pmt.to_python(tags[-1].value) + self.freq * np.arange(0, nback)\n\n    \
+      \    # compute the \"start\", using the last tag from the previous call\n  \
+      \      nfront = tags[0].offset - self.counter\n        print(f\"Processing {nfront}\
+      \ samples at the front of the buffer\")\n        start = self.block_phase(self.last,\
+      \ tags[0])[-nfront:] \\\n                if self.last and nfront else np.zeros(nfront)\n\
+      \n        # compute correction\n        correction = np.exp(-1j * np.concatenate([start,\
+      \ middle, end]))\n        length = len(correction)\n\n        # write outputs\n\
+      \        out[:length] = inp[:length] * correction\n        self.counter += len(inp)\n\
       \n        # save last tag for next call\n        self.last = tags[-1]\n\n  \
       \      # FIXME: should return `length' but then the last sample is not\n   \
       \     #        included and self.last does something weird\n        return len(out)\n"
diff --git a/tests/correlator/correlator.py b/tests/correlator/correlator.py
index 536ac00..5edc8ee 100755
--- a/tests/correlator/correlator.py
+++ b/tests/correlator/correlator.py
@@ -78,7 +78,7 @@ class correlator(gr.top_block, Qt.QWidget):
         self.nfilts = nfilts = 32
         self.excess_bw = excess_bw = .35
         self.timing_loop_bw = timing_loop_bw = 2 * 3.141592653589793 / 100
-        self.testvec = testvec = [31, 53] + [0x12, 0xe3, 0x9b, 0xee, 0x84, 0x23, 0x41, 0xf3]
+        self.testvec = testvec = [31, 53] + [0x12, 0xe3, 0x9b, 0xee, 0x84, 0x23, 0x41, 0xf3] * 2
         self.samp_rate = samp_rate = 32000
         self.rrc_taps = rrc_taps = firdes.root_raised_cosine(nfilts, nfilts, 1.0/float(sps), excess_bw, 45*nfilts)
         self.revconj_access_code_symbols = revconj_access_code_symbols = [(1.4142135623730951+1.4142135623730951j), (1.4142135623730951+1.4142135623730951j), (1.4142135623730951-1.4142135623730951j), (-1.4142135623730951+1.4142135623730951j), (1.4142135623730951-1.4142135623730951j), (1.4142135623730951-1.4142135623730951j), (1.4142135623730951+1.4142135623730951j), (-1.4142135623730951+1.4142135623730951j)]
diff --git a/tests/correlator/epy_block_0.py b/tests/correlator/epy_block_0.py
index abf4486..6b47e80 100644
--- a/tests/correlator/epy_block_0.py
+++ b/tests/correlator/epy_block_0.py
@@ -21,6 +21,10 @@ class blk(gr.sync_block):
         # of the previous block to correct the first values of the next block
         self.last = None
 
+        # to compute the values that are at the end we need to know the frequency
+        # of the last block
+        self.freq = 1
+
     def block_phase(self, start, end):
         # compute number of samples in block
         nsamples = end.offset - start.offset
@@ -32,6 +36,15 @@ class blk(gr.sync_block):
         # compute frequency offset between start and end
         freq = (sphase - ephase) / nsamples
 
+        # save this frequency values to compute the end block, unless frequency
+        # has changed too fast, in that case replace the current values with
+        # the previous one . This is effectively like a low pass filter.
+        if abs(freq / self.freq) > 4:
+            freq = self.freq
+        else:
+            self.freq = freq
+
+
         # debugging
         print(f"Correction for block of {nsamples:2d} samples is " \
               f"phase={sphase: .4f} rad and freq={freq*1e3: .4f} milli rad / sample")
@@ -61,17 +74,18 @@ class blk(gr.sync_block):
         blocks = [ self.block_phase(start, end) for (start, end) in pairs ]
         middle = np.concatenate(blocks) if blocks else []
 
-        # compute the remainder from the previous call
+        # compute values at the end, we do not have informations about the future
+        # but we can use the frequency of the last block to approximate
+        nback = len(inp) - (tags[-1].offset - self.counter)
+        print(f"Processing {nback} samples at the back of the buffer")
+        end = np.ones(nback) * pmt.to_python(tags[-1].value) + self.freq * np.arange(0, nback)
+
+        # compute the "start", using the last tag from the previous call
         nfront = tags[0].offset - self.counter
         print(f"Processing {nfront} samples at the front of the buffer")
         start = self.block_phase(self.last, tags[0])[-nfront:] \
                 if self.last and nfront else np.zeros(nfront)
 
-        # compute values at the end
-        nback = len(inp) - (tags[-1].offset - self.counter)
-        print(f"Processing {nback} samples at the back of the buffer")
-        end = np.ones(nback) * pmt.to_python(tags[-1].value)
-
         # compute correction
         correction = np.exp(-1j * np.concatenate([start, middle, end]))
         length = len(correction)
-- 
cgit v1.2.1


From b389c8d00064d224a534d3c4a37bd4ee700a5022 Mon Sep 17 00:00:00 2001
From: Nao Pross <np@0hm.ch>
Date: Fri, 3 Dec 2021 13:01:42 +0100
Subject: Improve frequency LPF

---
 tests/correlator/correlator.grc | 100 +++++++++++++++++++++++++---------------
 tests/correlator/correlator.py  |  13 ++++--
 tests/correlator/epy_block_0.py |  36 +++++++++------
 3 files changed, 93 insertions(+), 56 deletions(-)

(limited to 'tests')

diff --git a/tests/correlator/correlator.grc b/tests/correlator/correlator.grc
index bf44544..220eaed 100644
--- a/tests/correlator/correlator.grc
+++ b/tests/correlator/correlator.grc
@@ -163,7 +163,7 @@ blocks:
   id: variable
   parameters:
     comment: ''
-    value: '[31, 53] + [0x12, 0xe3, 0x9b, 0xee, 0x84, 0x23, 0x41, 0xf3] * 2'
+    value: '[31, 53] + [0x12, 0xe3, 0x9b, 0xee, 0x84, 0x23, 0x41, 0xf3] '
   states:
     bus_sink: false
     bus_source: false
@@ -212,7 +212,7 @@ blocks:
     bus_sink: false
     bus_source: false
     bus_structure: null
-    coordinate: [1048, 1128.0]
+    coordinate: [1088, 1304.0]
     rotation: 0
     state: enabled
 - name: blocks_multiply_const_vxx_0
@@ -248,7 +248,7 @@ blocks:
     bus_sink: false
     bus_source: false
     bus_structure: null
-    coordinate: [1336, 1204.0]
+    coordinate: [1376, 1380.0]
     rotation: 0
     state: disabled
 - name: blocks_null_sink_3
@@ -265,7 +265,7 @@ blocks:
     bus_sink: false
     bus_source: false
     bus_structure: null
-    coordinate: [1336, 1256.0]
+    coordinate: [1376, 1432.0]
     rotation: 0
     state: true
 - name: blocks_null_source_0
@@ -408,7 +408,7 @@ blocks:
     block_tags: 'False'
     comment: ''
     epsilon: '1.0'
-    freq_offset: '0.0002'
+    freq_offset: '0.0001'
     maxoutbuf: '0'
     minoutbuf: '0'
     noise_voltage: '0.2'
@@ -497,6 +497,24 @@ blocks:
     coordinate: [776, 1020.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: 2 * 3.141592653589793 / 100
+  states:
+    bus_sink: false
+    bus_source: false
+    bus_structure: null
+    coordinate: [1088, 1128.0]
+    rotation: 0
+    state: true
 - name: digital_pfb_clock_sync_xxx_0
   id: digital_pfb_clock_sync_xxx
   parameters:
@@ -531,18 +549,20 @@ blocks:
       \ because tags have an absolute offset\n        self.counter: np.uint64 = 0\n\
       \n        # because we do block processing, we need to keep track of the last\
       \ tag\n        # of the previous block to correct the first values of the next\
-      \ block\n        self.last = None\n\n        # to compute the values that are\
-      \ at the end we need to know the frequency\n        # of the last block\n  \
-      \      self.freq = 1\n\n    def block_phase(self, start, end):\n        # compute\
-      \ number of samples in block\n        nsamples = end.offset - start.offset\n\
-      \n        # unpack pmt values into start and end phase\n        sphase = pmt.to_python(start.value)\n\
-      \        ephase = pmt.to_python(end.value)\n\n        # compute frequency offset\
-      \ between start and end\n        freq = (sphase - ephase) / nsamples\n\n   \
-      \     # save this frequency values to compute the end block, unless frequency\n\
-      \        # has changed too fast, in that case replace the current values with\n\
-      \        # the previous one . This is effectively like a low pass filter.\n\
-      \        if abs(freq / self.freq) > 4:\n            freq = self.freq\n     \
-      \   else:\n            self.freq = freq\n\n\n        # debugging\n        print(f\"\
+      \ block\n        self.last = None\n\n        # both the phase and frequency\
+      \ corrections should go through a low pass\n        # filter to avoid werid\
+      \ jumps in the correction. to do that, there are\n        # two buffers with\
+      \ an index\n        self.index = 0\n        self.length = 7\n        self.freq\
+      \ = np.zeros(self.length)\n\n    def lpf_freq(self, new_sample):\n        #\
+      \ save new sample\n        self.freq[self.index] = new_sample\n        # increment\
+      \ index\n        self.index = (self.index + 1) % self.length\n\n        return\
+      \ np.sum(self.freq) / self.length\n\n    def block_phase(self, start, end):\n\
+      \        # compute number of samples in block\n        nsamples = end.offset\
+      \ - start.offset\n\n        # unpack pmt values into start and end phase\n \
+      \       sphase = pmt.to_python(start.value)\n        ephase = pmt.to_python(end.value)\n\
+      \n        # compute frequency offset between start and end\n        # and run\
+      \ it through a low pass filter (mean)\n        freq = (sphase - ephase) / nsamples\n\
+      \        freq = self.lpf_freq(freq)\n\n        # debugging\n        print(f\"\
       Correction for block of {nsamples:2d} samples is \" \\\n              f\"phase={sphase:\
       \ .4f} rad and freq={freq*1e3: .4f} milli rad / sample\")\n\n        # compute\
       \ block values\n        return sphase * np.ones(nsamples) + freq * np.arange(0,\
@@ -551,20 +571,22 @@ blocks:
       \n        # nicer aliases\n        inp = input_items[0]\n        out = output_items[0]\n\
       \n        # read phase tags\n        is_phase = lambda tag: pmt.to_python(tag.key)\
       \ == \"phase_est\"\n        tags = list(filter(is_phase, self.get_tags_in_window(0,\
-      \ 0, len(inp))))\n\n        # debugging\n        print(f\"Processing {len(tags)}\
-      \ tags = {tags[-1].offset - tags[0].offset} \" \\\n              f\"samples\
-      \ out of {len(inp)} input samples\")\n\n        # compute \"the middle\"\n \
-      \       enough_samples = lambda pair: ((pair[1].offset - pair[0].offset) > 0)\n\
-      \        pairs = list(filter(enough_samples, zip(tags, tags[1:])))\n       \
-      \ blocks = [ self.block_phase(start, end) for (start, end) in pairs ]\n    \
-      \    middle = np.concatenate(blocks) if blocks else []\n\n        # compute\
-      \ values at the end, we do not have informations about the future\n        #\
-      \ but we can use the frequency of the last block to approximate\n        nback\
-      \ = len(inp) - (tags[-1].offset - self.counter)\n        print(f\"Processing\
-      \ {nback} samples at the back of the buffer\")\n        end = np.ones(nback)\
-      \ * pmt.to_python(tags[-1].value) + self.freq * np.arange(0, nback)\n\n    \
-      \    # compute the \"start\", using the last tag from the previous call\n  \
-      \      nfront = tags[0].offset - self.counter\n        print(f\"Processing {nfront}\
+      \ 0, len(inp))))\n\n        if not tags:\n            print(f\"There were no\
+      \ tags in {len(inp)} samples!\")\n            out[:] = inp\n            return\
+      \ len(out)\n\n        # debugging\n        print(f\"Processing {len(tags)} tags\
+      \ = {tags[-1].offset - tags[0].offset} \" \\\n              f\"samples out of\
+      \ {len(inp)} input samples\")\n\n        # compute \"the middle\"\n        enough_samples\
+      \ = lambda pair: ((pair[1].offset - pair[0].offset) > 0)\n        pairs = list(filter(enough_samples,\
+      \ zip(tags, tags[1:])))\n        blocks = [ self.block_phase(start, end) for\
+      \ (start, end) in pairs ]\n        middle = np.concatenate(blocks) if blocks\
+      \ else []\n\n        # compute values at the end, we do not have informations\
+      \ about the future\n        # but we can use the frequency of the last block\
+      \ to approximate\n        nback = len(inp) - (tags[-1].offset - self.counter)\n\
+      \        print(f\"Processing {nback} samples at the back of the buffer\")\n\
+      \        endfreq = self.lpf_freq(self.freq[-1])\n        end = np.ones(nback)\
+      \ * pmt.to_python(tags[-1].value) + endfreq * np.arange(0, nback)\n\n      \
+      \  # compute the \"start\", using the last tag from the previous call\n    \
+      \    nfront = tags[0].offset - self.counter\n        print(f\"Processing {nfront}\
       \ samples at the front of the buffer\")\n        start = self.block_phase(self.last,\
       \ tags[0])[-nfront:] \\\n                if self.last and nfront else np.zeros(nfront)\n\
       \n        # compute correction\n        correction = np.exp(-1j * np.concatenate([start,\
@@ -728,9 +750,9 @@ blocks:
     comment: ''
     grid: 'False'
     gui_hint: 2,1,2,1
-    label1: ''
+    label1: Custom Block
     label10: ''
-    label2: ''
+    label2: Costas Loop
     label3: ''
     label4: ''
     label5: ''
@@ -750,7 +772,7 @@ blocks:
     marker8: '0'
     marker9: '0'
     name: '"Phase Locked Signal"'
-    nconnections: '1'
+    nconnections: '2'
     size: '1024'
     style1: '0'
     style10: '0'
@@ -787,7 +809,7 @@ blocks:
     bus_sink: false
     bus_source: false
     bus_structure: null
-    coordinate: [1288, 940.0]
+    coordinate: [1368, 1092.0]
     rotation: 0
     state: enabled
 - name: qtgui_const_sink_x_1
@@ -1073,7 +1095,7 @@ blocks:
     bus_sink: false
     bus_source: false
     bus_structure: null
-    coordinate: [1336, 1108.0]
+    coordinate: [1376, 1284.0]
     rotation: 0
     state: enabled
 - name: qtgui_time_sink_x_0_0_0
@@ -1558,7 +1580,7 @@ blocks:
     bus_sink: false
     bus_source: false
     bus_structure: null
-    coordinate: [1512, 1188.0]
+    coordinate: [1552, 1364.0]
     rotation: 0
     state: disabled
 - name: root_raised_cosine_filter_0
@@ -1607,7 +1629,7 @@ blocks:
     bus_sink: false
     bus_source: false
     bus_structure: null
-    coordinate: [1336, 1036.0]
+    coordinate: [1368, 1036.0]
     rotation: 0
     state: true
 - name: virtual_source_0
@@ -1660,9 +1682,11 @@ connections:
 - [digital_constellation_modulator_0, '0', blocks_stream_mux_1, '1']
 - [digital_constellation_modulator_0, '0', channels_channel_model_0, '0']
 - [digital_constellation_modulator_0, '0', qtgui_time_sink_x_1_0, '0']
+- [digital_corr_est_cc_0, '0', digital_costas_loop_cc_0, '0']
 - [digital_corr_est_cc_0, '0', epy_block_0, '0']
 - [digital_corr_est_cc_0, '0', qtgui_time_sink_x_0_0_0, '0']
 - [digital_corr_est_cc_0, '1', blocks_complex_to_magphase_0_0, '0']
+- [digital_costas_loop_cc_0, '0', qtgui_const_sink_x_0_0, '1']
 - [digital_pfb_clock_sync_xxx_0, '0', digital_cma_equalizer_cc_0, '0']
 - [epy_block_0, '0', qtgui_const_sink_x_0_0, '0']
 - [epy_block_0, '0', virtual_sink_3, '0']
diff --git a/tests/correlator/correlator.py b/tests/correlator/correlator.py
index 5edc8ee..50283c0 100755
--- a/tests/correlator/correlator.py
+++ b/tests/correlator/correlator.py
@@ -78,7 +78,7 @@ class correlator(gr.top_block, Qt.QWidget):
         self.nfilts = nfilts = 32
         self.excess_bw = excess_bw = .35
         self.timing_loop_bw = timing_loop_bw = 2 * 3.141592653589793 / 100
-        self.testvec = testvec = [31, 53] + [0x12, 0xe3, 0x9b, 0xee, 0x84, 0x23, 0x41, 0xf3] * 2
+        self.testvec = testvec = [31, 53] + [0x12, 0xe3, 0x9b, 0xee, 0x84, 0x23, 0x41, 0xf3]
         self.samp_rate = samp_rate = 32000
         self.rrc_taps = rrc_taps = firdes.root_raised_cosine(nfilts, nfilts, 1.0/float(sps), excess_bw, 45*nfilts)
         self.revconj_access_code_symbols = revconj_access_code_symbols = [(1.4142135623730951+1.4142135623730951j), (1.4142135623730951+1.4142135623730951j), (1.4142135623730951-1.4142135623730951j), (-1.4142135623730951+1.4142135623730951j), (1.4142135623730951-1.4142135623730951j), (1.4142135623730951-1.4142135623730951j), (1.4142135623730951+1.4142135623730951j), (-1.4142135623730951+1.4142135623730951j)]
@@ -243,7 +243,7 @@ class correlator(gr.top_block, Qt.QWidget):
         self.qtgui_const_sink_x_0_0 = qtgui.const_sink_c(
             1024, #size
             "Phase Locked Signal", #name
-            1 #number of inputs
+            2 #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)
@@ -254,7 +254,7 @@ class correlator(gr.top_block, Qt.QWidget):
         self.qtgui_const_sink_x_0_0.enable_axis_labels(True)
 
 
-        labels = ['', '', '', '', '',
+        labels = ['Custom Block', 'Costas Loop', '', '', '',
             '', '', '', '', '']
         widths = [1, 1, 1, 1, 1,
             1, 1, 1, 1, 1]
@@ -267,7 +267,7 @@ class correlator(gr.top_block, Qt.QWidget):
         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):
+        for i in range(2):
             if len(labels[i]) == 0:
                 self.qtgui_const_sink_x_0_0.set_line_label(i, "Data {0}".format(i))
             else:
@@ -330,6 +330,7 @@ class correlator(gr.top_block, Qt.QWidget):
             self.top_grid_layout.setColumnStretch(c, 1)
         self.epy_block_0 = epy_block_0.blk()
         self.digital_pfb_clock_sync_xxx_0 = digital.pfb_clock_sync_ccf(sps, timing_loop_bw, rrc_taps, nfilts, 16, 1.5, 1)
+        self.digital_costas_loop_cc_0 = digital.costas_loop_cc(2 * 3.141592653589793 / 100, 4, False)
         self.digital_corr_est_cc_0 = digital.corr_est_cc(access_code_symbols, 1, 0, .8, digital.THRESHOLD_DYNAMIC)
         self.digital_constellation_modulator_0 = digital.generic_mod(
             constellation=const,
@@ -343,7 +344,7 @@ class correlator(gr.top_block, Qt.QWidget):
         self.digital_cma_equalizer_cc_0 = digital.cma_equalizer_cc(15, 1, .002, 1)
         self.channels_channel_model_0 = channels.channel_model(
             noise_voltage=0.2,
-            frequency_offset=0.0002,
+            frequency_offset=0.0001,
             epsilon=1.0,
             taps=[-1.4 + .4j],
             noise_seed=243,
@@ -374,8 +375,10 @@ class correlator(gr.top_block, Qt.QWidget):
         self.connect((self.digital_constellation_modulator_0, 0), (self.channels_channel_model_0, 0))
         self.connect((self.digital_constellation_modulator_0, 0), (self.qtgui_time_sink_x_1_0, 0))
         self.connect((self.digital_corr_est_cc_0, 1), (self.blocks_complex_to_magphase_0_0, 0))
+        self.connect((self.digital_corr_est_cc_0, 0), (self.digital_costas_loop_cc_0, 0))
         self.connect((self.digital_corr_est_cc_0, 0), (self.epy_block_0, 0))
         self.connect((self.digital_corr_est_cc_0, 0), (self.qtgui_time_sink_x_0_0_0, 0))
+        self.connect((self.digital_costas_loop_cc_0, 0), (self.qtgui_const_sink_x_0_0, 1))
         self.connect((self.digital_pfb_clock_sync_xxx_0, 0), (self.digital_cma_equalizer_cc_0, 0))
         self.connect((self.epy_block_0, 0), (self.digital_constellation_decoder_cb_0, 0))
         self.connect((self.epy_block_0, 0), (self.qtgui_const_sink_x_0_0, 0))
diff --git a/tests/correlator/epy_block_0.py b/tests/correlator/epy_block_0.py
index 6b47e80..e7599c9 100644
--- a/tests/correlator/epy_block_0.py
+++ b/tests/correlator/epy_block_0.py
@@ -21,9 +21,20 @@ class blk(gr.sync_block):
         # of the previous block to correct the first values of the next block
         self.last = None
 
-        # to compute the values that are at the end we need to know the frequency
-        # of the last block
-        self.freq = 1
+        # both the phase and frequency corrections should go through a low pass
+        # filter to avoid werid jumps in the correction. to do that, there are
+        # two buffers with an index
+        self.index = 0
+        self.length = 7
+        self.freq = np.zeros(self.length)
+
+    def lpf_freq(self, new_sample):
+        # save new sample
+        self.freq[self.index] = new_sample
+        # increment index
+        self.index = (self.index + 1) % self.length
+
+        return np.sum(self.freq) / self.length
 
     def block_phase(self, start, end):
         # compute number of samples in block
@@ -34,16 +45,9 @@ class blk(gr.sync_block):
         ephase = pmt.to_python(end.value)
 
         # compute frequency offset between start and end
+        # and run it through a low pass filter (mean)
         freq = (sphase - ephase) / nsamples
-
-        # save this frequency values to compute the end block, unless frequency
-        # has changed too fast, in that case replace the current values with
-        # the previous one . This is effectively like a low pass filter.
-        if abs(freq / self.freq) > 4:
-            freq = self.freq
-        else:
-            self.freq = freq
-
+        freq = self.lpf_freq(freq)
 
         # debugging
         print(f"Correction for block of {nsamples:2d} samples is " \
@@ -64,6 +68,11 @@ class blk(gr.sync_block):
         is_phase = lambda tag: pmt.to_python(tag.key) == "phase_est"
         tags = list(filter(is_phase, self.get_tags_in_window(0, 0, len(inp))))
 
+        if not tags:
+            print(f"There were no tags in {len(inp)} samples!")
+            out[:] = inp
+            return len(out)
+
         # debugging
         print(f"Processing {len(tags)} tags = {tags[-1].offset - tags[0].offset} " \
               f"samples out of {len(inp)} input samples")
@@ -78,7 +87,8 @@ class blk(gr.sync_block):
         # but we can use the frequency of the last block to approximate
         nback = len(inp) - (tags[-1].offset - self.counter)
         print(f"Processing {nback} samples at the back of the buffer")
-        end = np.ones(nback) * pmt.to_python(tags[-1].value) + self.freq * np.arange(0, nback)
+        endfreq = self.lpf_freq(self.freq[-1])
+        end = np.ones(nback) * pmt.to_python(tags[-1].value) + endfreq * np.arange(0, nback)
 
         # compute the "start", using the last tag from the previous call
         nfront = tags[0].offset - self.counter
-- 
cgit v1.2.1


From 0cb8ac7bd0e88d6d26c1fda3abcf0977c2e8150b Mon Sep 17 00:00:00 2001
From: Nao Pross <np@0hm.ch>
Date: Fri, 3 Dec 2021 17:54:07 +0100
Subject: Fix bug that makes jump estimated frequency to unreasonably high
 values

---
 tests/correlator/correlator.grc | 285 +++++++++++++++++++---------------------
 tests/correlator/correlator.py  |  41 +++---
 tests/correlator/epy_block_0.py |  16 ++-
 tests/correlator/epy_block_1.py |  27 ++++
 4 files changed, 191 insertions(+), 178 deletions(-)
 create mode 100644 tests/correlator/epy_block_1.py

(limited to 'tests')

diff --git a/tests/correlator/correlator.grc b/tests/correlator/correlator.grc
index 220eaed..0f82f27 100644
--- a/tests/correlator/correlator.grc
+++ b/tests/correlator/correlator.grc
@@ -44,26 +44,7 @@ blocks:
     bus_sink: false
     bus_source: false
     bus_structure: null
-    coordinate: [776, 1140.0]
-    rotation: 0
-    state: enabled
-- name: access_code_symbols_sps
-  id: variable
-  parameters:
-    comment: ''
-    value: '[(1.4142197+1.4142197j), (1.4142197+1.4142197j), (1.4142197+1.4142197j),
-      (1.4142197+1.4142197j), (1.4142197-1.4142197j), (1.4142197-1.4142197j), (1.4142197-1.4142197j),
-      (1.4142197-1.4142197j), (1.4142197-1.4142197j), (1.4142197-1.4142197j), (1.4142197-1.4142197j),
-      (1.4142197-1.4142197j), (-1.4142197-1.4142197j), (-1.4142197-1.4142197j), (-1.4142197-1.4142197j),
-      (-1.4142197-1.4142197j), (1.4142197-1.4142197j), (1.4142197-1.4142197j), (1.4142197-1.4142197j),
-      (1.4142197-1.4142197j), (1.4142197+1.4142197j), (1.4142197+1.4142197j), (1.4142197+1.4142197j),
-      (1.4142197+1.4142197j), (1.4142197+1.4142197j), (1.4142197+1.4142197j), (1.4142197+1.4142197j),
-      (1.4142197+1.4142197j)]'
-  states:
-    bus_sink: false
-    bus_source: false
-    bus_structure: null
-    coordinate: [224, 132.0]
+    coordinate: [768, 1016.0]
     rotation: 0
     state: enabled
 - name: const
@@ -81,7 +62,7 @@ blocks:
     bus_sink: false
     bus_source: false
     bus_structure: null
-    coordinate: [592, 484.0]
+    coordinate: [592, 360.0]
     rotation: 0
     state: enabled
 - name: excess_bw
@@ -93,7 +74,7 @@ blocks:
     bus_sink: false
     bus_source: false
     bus_structure: null
-    coordinate: [496, 484.0]
+    coordinate: [496, 360.0]
     rotation: 0
     state: enabled
 - name: nfilts
@@ -105,7 +86,7 @@ blocks:
     bus_sink: false
     bus_source: false
     bus_structure: null
-    coordinate: [224, 988.0]
+    coordinate: [224, 856.0]
     rotation: 0
     state: enabled
 - name: revconj_access_code_symbols
@@ -120,7 +101,7 @@ blocks:
     bus_sink: false
     bus_source: false
     bus_structure: null
-    coordinate: [48, 564.0]
+    coordinate: [48, 440.0]
     rotation: 0
     state: enabled
 - name: rrc_taps
@@ -132,14 +113,14 @@ blocks:
     bus_sink: false
     bus_source: false
     bus_structure: null
-    coordinate: [304, 988.0]
+    coordinate: [304, 856.0]
     rotation: 0
     state: enabled
 - name: samp_rate
   id: variable
   parameters:
     comment: ''
-    value: '32000'
+    value: int(1.5e6)
   states:
     bus_sink: false
     bus_source: false
@@ -163,24 +144,24 @@ blocks:
   id: variable
   parameters:
     comment: ''
-    value: '[31, 53] + [0x12, 0xe3, 0x9b, 0xee, 0x84, 0x23, 0x41, 0xf3] '
+    value: '[0x1f, 0x35] + [0x12, 0xe3, 0x9b, 0xee, 0x84, 0x23, 0x41, 0xf3] '
   states:
     bus_sink: false
     bus_source: false
     bus_structure: null
-    coordinate: [48, 492.0]
+    coordinate: [48, 360.0]
     rotation: 0
     state: enabled
 - name: timing_loop_bw
   id: variable
   parameters:
     comment: ''
-    value: 2 * 3.141592653589793 / 100
+    value: 2 * np.pi / 100
   states:
     bus_sink: false
     bus_source: false
     bus_structure: null
-    coordinate: [224, 1068.0]
+    coordinate: [224, 936.0]
     rotation: 0
     state: enabled
 - name: blocks_complex_to_magphase_0
@@ -196,7 +177,7 @@ blocks:
     bus_sink: false
     bus_source: false
     bus_structure: null
-    coordinate: [1048, 696.0]
+    coordinate: [1040, 568.0]
     rotation: 0
     state: disabled
 - name: blocks_complex_to_magphase_0_0
@@ -212,7 +193,7 @@ blocks:
     bus_sink: false
     bus_source: false
     bus_structure: null
-    coordinate: [1088, 1304.0]
+    coordinate: [1032, 1176.0]
     rotation: 0
     state: enabled
 - name: blocks_multiply_const_vxx_0
@@ -230,7 +211,7 @@ blocks:
     bus_sink: false
     bus_source: false
     bus_structure: null
-    coordinate: [1288, 724.0]
+    coordinate: [1288, 596.0]
     rotation: 0
     state: disabled
 - name: blocks_multiply_const_vxx_0_0
@@ -248,7 +229,7 @@ blocks:
     bus_sink: false
     bus_source: false
     bus_structure: null
-    coordinate: [1376, 1380.0]
+    coordinate: [1376, 1248.0]
     rotation: 0
     state: disabled
 - name: blocks_null_sink_3
@@ -265,7 +246,7 @@ blocks:
     bus_sink: false
     bus_source: false
     bus_structure: null
-    coordinate: [1376, 1432.0]
+    coordinate: [1376, 1304.0]
     rotation: 0
     state: true
 - name: blocks_null_source_0
@@ -284,47 +265,48 @@ blocks:
     bus_sink: false
     bus_source: false
     bus_structure: null
-    coordinate: [96, 344.0]
+    coordinate: [96, 200.0]
     rotation: 0
     state: enabled
-- name: blocks_stream_mux_0
-  id: blocks_stream_mux
+- name: blocks_repack_bits_bb_0
+  id: blocks_repack_bits_bb
   parameters:
     affinity: ''
     alias: ''
+    align_output: 'False'
     comment: ''
-    lengths: '[10, len(testvec)]'
+    endianness: gr.GR_MSB_FIRST
+    k: '2'
+    l: '8'
+    len_tag_key: '""'
     maxoutbuf: '0'
     minoutbuf: '0'
-    num_inputs: '2'
-    type: byte
-    vlen: '1'
   states:
     bus_sink: false
     bus_source: false
     bus_structure: null
-    coordinate: [288, 392.0]
+    coordinate: [672, 1252.0]
     rotation: 0
-    state: enabled
-- name: blocks_stream_mux_1
+    state: true
+- name: blocks_stream_mux_0
   id: blocks_stream_mux
   parameters:
     affinity: ''
     alias: ''
     comment: ''
-    lengths: '[len(access_code_symbols_sps), sps * (len(testvec) + 15)]'
+    lengths: '[5, len(testvec)]'
     maxoutbuf: '0'
     minoutbuf: '0'
     num_inputs: '2'
-    type: complex
+    type: byte
     vlen: '1'
   states:
     bus_sink: false
     bus_source: false
     bus_structure: null
-    coordinate: [776, 280.0]
+    coordinate: [288, 256.0]
     rotation: 0
-    state: disabled
+    state: enabled
 - name: blocks_throttle_0
   id: blocks_throttle
   parameters:
@@ -341,25 +323,9 @@ blocks:
     bus_sink: false
     bus_source: false
     bus_structure: null
-    coordinate: [1272, 404.0]
+    coordinate: [1272, 268.0]
     rotation: 0
     state: enabled
-- name: blocks_vector_sink_x_0
-  id: blocks_vector_sink_x
-  parameters:
-    affinity: ''
-    alias: ''
-    comment: ''
-    reserve_items: '1024'
-    type: byte
-    vlen: '1'
-  states:
-    bus_sink: false
-    bus_source: false
-    bus_structure: null
-    coordinate: [536, 1392.0]
-    rotation: 0
-    state: true
 - name: blocks_vector_source_x_0
   id: blocks_vector_source_x
   parameters:
@@ -371,35 +337,15 @@ blocks:
     repeat: 'True'
     tags: '[]'
     type: byte
-    vector: testvec * 1600
+    vector: testvec * 500
     vlen: '1'
   states:
     bus_sink: false
     bus_source: false
     bus_structure: null
-    coordinate: [48, 404.0]
+    coordinate: [48, 268.0]
     rotation: 0
     state: enabled
-- name: blocks_vector_source_x_1
-  id: blocks_vector_source_x
-  parameters:
-    affinity: ''
-    alias: ''
-    comment: ''
-    maxoutbuf: '0'
-    minoutbuf: '0'
-    repeat: 'True'
-    tags: '[]'
-    type: complex
-    vector: access_code_symbols_sps
-    vlen: '1'
-  states:
-    bus_sink: false
-    bus_source: false
-    bus_structure: null
-    coordinate: [224, 204.0]
-    rotation: 0
-    state: disabled
 - name: channels_channel_model_0
   id: channels_channel_model
   parameters:
@@ -411,14 +357,14 @@ blocks:
     freq_offset: '0.0001'
     maxoutbuf: '0'
     minoutbuf: '0'
-    noise_voltage: '0.2'
+    noise_voltage: '0.01'
     seed: '243'
-    taps: -1.4 + .4j
+    taps: np.exp(1j * 30 / 180 * np.pi)
   states:
     bus_sink: false
     bus_source: false
     bus_structure: null
-    coordinate: [992, 364.0]
+    coordinate: [1000, 228.0]
     rotation: 0
     state: enabled
 - name: digital_cma_equalizer_cc_0
@@ -437,7 +383,7 @@ blocks:
     bus_sink: false
     bus_source: false
     bus_structure: null
-    coordinate: [528, 812.0]
+    coordinate: [520, 676.0]
     rotation: 0
     state: enabled
 - name: digital_constellation_decoder_cb_0
@@ -453,7 +399,7 @@ blocks:
     bus_sink: false
     bus_source: false
     bus_structure: null
-    coordinate: [248, 1388.0]
+    coordinate: [224, 1260.0]
     rotation: 0
     state: enabled
 - name: digital_constellation_modulator_0
@@ -474,7 +420,7 @@ blocks:
     bus_sink: false
     bus_source: false
     bus_structure: null
-    coordinate: [496, 380.0]
+    coordinate: [504, 244.0]
     rotation: 0
     state: enabled
 - name: digital_corr_est_cc_0
@@ -494,7 +440,7 @@ blocks:
     bus_sink: false
     bus_source: false
     bus_structure: null
-    coordinate: [776, 1020.0]
+    coordinate: [768, 892.0]
     rotation: 0
     state: enabled
 - name: digital_costas_loop_cc_0
@@ -512,9 +458,25 @@ blocks:
     bus_sink: false
     bus_source: false
     bus_structure: null
-    coordinate: [1088, 1128.0]
+    coordinate: [1080, 1000.0]
     rotation: 0
     state: true
+- name: digital_map_bb_0
+  id: digital_map_bb
+  parameters:
+    affinity: ''
+    alias: ''
+    comment: ''
+    map: '[0, 1, 3, 2]'
+    maxoutbuf: '0'
+    minoutbuf: '0'
+  states:
+    bus_sink: false
+    bus_source: false
+    bus_structure: null
+    coordinate: [496, 1260.0]
+    rotation: 0
+    state: bypassed
 - name: digital_pfb_clock_sync_xxx_0
   id: digital_pfb_clock_sync_xxx
   parameters:
@@ -535,7 +497,7 @@ blocks:
     bus_sink: false
     bus_source: false
     bus_structure: null
-    coordinate: [224, 836.0]
+    coordinate: [224, 700.0]
     rotation: 0
     state: enabled
 - name: epy_block_0
@@ -552,7 +514,7 @@ blocks:
       \ block\n        self.last = None\n\n        # both the phase and frequency\
       \ corrections should go through a low pass\n        # filter to avoid werid\
       \ jumps in the correction. to do that, there are\n        # two buffers with\
-      \ an index\n        self.index = 0\n        self.length = 7\n        self.freq\
+      \ an index\n        self.index = 0\n        self.length = 5\n        self.freq\
       \ = np.zeros(self.length)\n\n    def lpf_freq(self, new_sample):\n        #\
       \ save new sample\n        self.freq[self.index] = new_sample\n        # increment\
       \ index\n        self.index = (self.index + 1) % self.length\n\n        return\
@@ -561,15 +523,18 @@ blocks:
       \ - start.offset\n\n        # unpack pmt values into start and end phase\n \
       \       sphase = pmt.to_python(start.value)\n        ephase = pmt.to_python(end.value)\n\
       \n        # compute frequency offset between start and end\n        # and run\
-      \ it through a low pass filter (mean)\n        freq = (sphase - ephase) / nsamples\n\
-      \        freq = self.lpf_freq(freq)\n\n        # debugging\n        print(f\"\
-      Correction for block of {nsamples:2d} samples is \" \\\n              f\"phase={sphase:\
-      \ .4f} rad and freq={freq*1e3: .4f} milli rad / sample\")\n\n        # compute\
-      \ block values\n        return sphase * np.ones(nsamples) + freq * np.arange(0,\
-      \ nsamples)\n\n    def work(self, input_items, output_items):\n        # FIXME:\
-      \ replace class counter with local variable\n        self.counter = self.nitems_written(0)\n\
-      \n        # nicer aliases\n        inp = input_items[0]\n        out = output_items[0]\n\
-      \n        # read phase tags\n        is_phase = lambda tag: pmt.to_python(tag.key)\
+      \ it through a low pass filter (mean)\n        phasediff = ephase - sphase\n\
+      \n        if phasediff > np.pi:\n            phasediff -= 2*np.pi\n\n      \
+      \  elif phasediff < -np.pi:\n            phasediff += 2*np.pi\n\n        freq\
+      \ = phasediff / nsamples\n        # freq = self.lpf_freq(freq)\n\n        #\
+      \ debugging\n        print(f\"Correction for block of {nsamples:2d} samples\
+      \ is \" \\\n              f\"sphase={sphase: .4f} rad and freq={freq*1e3: .4f}\
+      \ milli rad / sample\")\n\n        # compute block values\n        return sphase\
+      \ * np.ones(nsamples) + freq * np.arange(0, nsamples)\n\n    def work(self,\
+      \ input_items, output_items):\n        # FIXME: replace class counter with local\
+      \ variable\n        self.counter = self.nitems_written(0)\n\n        # nicer\
+      \ aliases\n        inp = input_items[0]\n        out = output_items[0]\n\n \
+      \       # read phase tags\n        is_phase = lambda tag: pmt.to_python(tag.key)\
       \ == \"phase_est\"\n        tags = list(filter(is_phase, self.get_tags_in_window(0,\
       \ 0, len(inp))))\n\n        if not tags:\n            print(f\"There were no\
       \ tags in {len(inp)} samples!\")\n            out[:] = inp\n            return\
@@ -606,9 +571,35 @@ blocks:
     bus_sink: false
     bus_source: false
     bus_structure: null
-    coordinate: [1088, 1040.0]
+    coordinate: [1208, 912.0]
     rotation: 0
     state: enabled
+- name: epy_block_1
+  id: epy_block
+  parameters:
+    _source_code: "\"\"\"\nEmbedded Python Blocks:\n\nEach time this file is saved,\
+      \ GRC will instantiate the first class it finds\nto get ports and parameters\
+      \ of your block. The arguments to __init__  will\nbe the parameters. All of\
+      \ them are required to have default values!\n\"\"\"\n\nimport numpy as np\n\
+      from gnuradio import gr\n\nnp.set_printoptions(formatter={'int':hex})\n\nclass\
+      \ blk(gr.sync_block):\n    def __init__(self):\n        gr.sync_block.__init__(\n\
+      \            self,\n            name='Printer',\n            in_sig=[np.byte],\n\
+      \            out_sig=[]\n        )\n\n    def work(self, input_items, output_items):\n\
+      \        inp = np.array(input_items[0], dtype=np.uint8)\n        print(f\"Decoded\
+      \ {len(inp)} samples:\\n{inp}\")\n\n        return len(inp)\n"
+    affinity: ''
+    alias: ''
+    comment: ''
+    maxoutbuf: '0'
+    minoutbuf: '0'
+  states:
+    _io_cache: ('Printer', 'blk', [], [('0', 'byte', 1)], [], '', [])
+    bus_sink: false
+    bus_source: false
+    bus_structure: null
+    coordinate: [920, 1264.0]
+    rotation: 0
+    state: true
 - name: fir_filter_xxx_1
   id: fir_filter_xxx
   parameters:
@@ -625,9 +616,22 @@ blocks:
     bus_sink: false
     bus_source: false
     bus_structure: null
-    coordinate: [776, 828.0]
+    coordinate: [776, 692.0]
     rotation: 0
     state: disabled
+- name: import_0
+  id: import
+  parameters:
+    alias: ''
+    comment: ''
+    imports: import numpy as np
+  states:
+    bus_sink: false
+    bus_source: false
+    bus_structure: null
+    coordinate: [184, 12.0]
+    rotation: 0
+    state: true
 - name: qtgui_const_sink_x_0
   id: qtgui_const_sink_x
   parameters:
@@ -717,7 +721,7 @@ blocks:
     bus_sink: false
     bus_source: false
     bus_structure: null
-    coordinate: [776, 716.0]
+    coordinate: [768, 592.0]
     rotation: 0
     state: enabled
 - name: qtgui_const_sink_x_0_0
@@ -809,7 +813,7 @@ blocks:
     bus_sink: false
     bus_source: false
     bus_structure: null
-    coordinate: [1368, 1092.0]
+    coordinate: [1408, 964.0]
     rotation: 0
     state: enabled
 - name: qtgui_const_sink_x_1
@@ -901,7 +905,7 @@ blocks:
     bus_sink: false
     bus_source: false
     bus_structure: null
-    coordinate: [1048, 612.0]
+    coordinate: [1040, 480.0]
     rotation: 0
     state: disabled
 - name: qtgui_time_sink_x_0
@@ -998,7 +1002,7 @@ blocks:
     bus_sink: false
     bus_source: false
     bus_structure: null
-    coordinate: [1320, 604.0]
+    coordinate: [1312, 480.0]
     rotation: 0
     state: disabled
 - name: qtgui_time_sink_x_0_0
@@ -1057,7 +1061,7 @@ blocks:
     name: '""'
     nconnections: '1'
     size: '1024'
-    srate: samp_rate
+    srate: samp_rate / sps
     stemplot: 'False'
     style1: '1'
     style10: '1'
@@ -1095,7 +1099,7 @@ blocks:
     bus_sink: false
     bus_source: false
     bus_structure: null
-    coordinate: [1376, 1284.0]
+    coordinate: [1376, 1152.0]
     rotation: 0
     state: enabled
 - name: qtgui_time_sink_x_0_0_0
@@ -1154,7 +1158,7 @@ blocks:
     name: '""'
     nconnections: '1'
     size: '1024'
-    srate: samp_rate
+    srate: samp_rate / sps
     stemplot: 'False'
     style1: '1'
     style10: '1'
@@ -1192,7 +1196,7 @@ blocks:
     bus_sink: false
     bus_source: false
     bus_structure: null
-    coordinate: [1048, 940.0]
+    coordinate: [1072, 788.0]
     rotation: 0
     state: enabled
 - name: qtgui_time_sink_x_1_0
@@ -1289,7 +1293,7 @@ blocks:
     bus_sink: false
     bus_source: false
     bus_structure: null
-    coordinate: [808, 452.0]
+    coordinate: [800, 320.0]
     rotation: 0
     state: enabled
 - name: qtgui_time_sink_x_1_1
@@ -1386,7 +1390,7 @@ blocks:
     bus_sink: false
     bus_source: false
     bus_structure: null
-    coordinate: [776, 612.0]
+    coordinate: [768, 480.0]
     rotation: 0
     state: disabled
 - name: qtgui_time_sink_x_2
@@ -1483,7 +1487,7 @@ blocks:
     bus_sink: false
     bus_source: false
     bus_structure: null
-    coordinate: [1480, 708.0]
+    coordinate: [1488, 580.0]
     rotation: 0
     state: disabled
 - name: qtgui_time_sink_x_2_0
@@ -1580,30 +1584,7 @@ blocks:
     bus_sink: false
     bus_source: false
     bus_structure: null
-    coordinate: [1552, 1364.0]
-    rotation: 0
-    state: disabled
-- name: root_raised_cosine_filter_0
-  id: root_raised_cosine_filter
-  parameters:
-    affinity: ''
-    alias: ''
-    alpha: excess_bw
-    comment: ''
-    decim: '1'
-    gain: '2'
-    interp: '1'
-    maxoutbuf: '0'
-    minoutbuf: '0'
-    ntaps: 11*samp_rate
-    samp_rate: samp_rate
-    sym_rate: sps * samp_rate
-    type: fir_filter_ccf
-  states:
-    bus_sink: false
-    bus_source: false
-    bus_structure: null
-    coordinate: [496, 180.0]
+    coordinate: [1552, 1232.0]
     rotation: 0
     state: disabled
 - name: virtual_sink_0
@@ -1616,7 +1597,7 @@ blocks:
     bus_sink: false
     bus_source: false
     bus_structure: null
-    coordinate: [1480, 404.0]
+    coordinate: [1488, 268.0]
     rotation: 0
     state: enabled
 - name: virtual_sink_3
@@ -1629,7 +1610,7 @@ blocks:
     bus_sink: false
     bus_source: false
     bus_structure: null
-    coordinate: [1368, 1036.0]
+    coordinate: [1400, 828.0]
     rotation: 0
     state: true
 - name: virtual_source_0
@@ -1642,7 +1623,7 @@ blocks:
     bus_sink: false
     bus_source: false
     bus_structure: null
-    coordinate: [32, 884.0]
+    coordinate: [16, 748.0]
     rotation: 0
     state: enabled
 - name: virtual_source_1
@@ -1655,7 +1636,7 @@ blocks:
     bus_sink: false
     bus_source: false
     bus_structure: null
-    coordinate: [24, 1388.0]
+    coordinate: [16, 1260.0]
     rotation: 0
     state: true
 
@@ -1668,18 +1649,16 @@ connections:
 - [blocks_multiply_const_vxx_0, '0', qtgui_time_sink_x_2, '0']
 - [blocks_multiply_const_vxx_0_0, '0', qtgui_time_sink_x_2_0, '0']
 - [blocks_null_source_0, '0', blocks_stream_mux_0, '0']
+- [blocks_repack_bits_bb_0, '0', epy_block_1, '0']
 - [blocks_stream_mux_0, '0', digital_constellation_modulator_0, '0']
-- [blocks_stream_mux_1, '0', channels_channel_model_0, '0']
 - [blocks_throttle_0, '0', virtual_sink_0, '0']
 - [blocks_vector_source_x_0, '0', blocks_stream_mux_0, '1']
-- [blocks_vector_source_x_1, '0', root_raised_cosine_filter_0, '0']
 - [channels_channel_model_0, '0', blocks_throttle_0, '0']
 - [digital_cma_equalizer_cc_0, '0', digital_corr_est_cc_0, '0']
 - [digital_cma_equalizer_cc_0, '0', fir_filter_xxx_1, '0']
 - [digital_cma_equalizer_cc_0, '0', qtgui_const_sink_x_0, '0']
 - [digital_cma_equalizer_cc_0, '0', qtgui_time_sink_x_1_1, '0']
-- [digital_constellation_decoder_cb_0, '0', blocks_vector_sink_x_0, '0']
-- [digital_constellation_modulator_0, '0', blocks_stream_mux_1, '1']
+- [digital_constellation_decoder_cb_0, '0', digital_map_bb_0, '0']
 - [digital_constellation_modulator_0, '0', channels_channel_model_0, '0']
 - [digital_constellation_modulator_0, '0', qtgui_time_sink_x_1_0, '0']
 - [digital_corr_est_cc_0, '0', digital_costas_loop_cc_0, '0']
@@ -1687,12 +1666,12 @@ connections:
 - [digital_corr_est_cc_0, '0', qtgui_time_sink_x_0_0_0, '0']
 - [digital_corr_est_cc_0, '1', blocks_complex_to_magphase_0_0, '0']
 - [digital_costas_loop_cc_0, '0', qtgui_const_sink_x_0_0, '1']
+- [digital_map_bb_0, '0', blocks_repack_bits_bb_0, '0']
 - [digital_pfb_clock_sync_xxx_0, '0', digital_cma_equalizer_cc_0, '0']
 - [epy_block_0, '0', qtgui_const_sink_x_0_0, '0']
 - [epy_block_0, '0', virtual_sink_3, '0']
 - [fir_filter_xxx_1, '0', blocks_complex_to_magphase_0, '0']
 - [fir_filter_xxx_1, '0', qtgui_const_sink_x_1, '0']
-- [root_raised_cosine_filter_0, '0', blocks_stream_mux_1, '0']
 - [virtual_source_0, '0', digital_pfb_clock_sync_xxx_0, '0']
 - [virtual_source_1, '0', digital_constellation_decoder_cb_0, '0']
 
diff --git a/tests/correlator/correlator.py b/tests/correlator/correlator.py
index 50283c0..255010a 100755
--- a/tests/correlator/correlator.py
+++ b/tests/correlator/correlator.py
@@ -35,6 +35,8 @@ from argparse import ArgumentParser
 from gnuradio.eng_arg import eng_float, intx
 from gnuradio import eng_notation
 import epy_block_0
+import epy_block_1
+import numpy as np
 
 from gnuradio import qtgui
 
@@ -77,13 +79,12 @@ class correlator(gr.top_block, Qt.QWidget):
         self.sps = sps = 4
         self.nfilts = nfilts = 32
         self.excess_bw = excess_bw = .35
-        self.timing_loop_bw = timing_loop_bw = 2 * 3.141592653589793 / 100
-        self.testvec = testvec = [31, 53] + [0x12, 0xe3, 0x9b, 0xee, 0x84, 0x23, 0x41, 0xf3]
-        self.samp_rate = samp_rate = 32000
+        self.timing_loop_bw = timing_loop_bw = 2 * np.pi / 100
+        self.testvec = testvec = [0x1f, 0x35] + [0x12, 0xe3, 0x9b, 0xee, 0x84, 0x23, 0x41, 0xf3]
+        self.samp_rate = samp_rate = int(1.5e6)
         self.rrc_taps = rrc_taps = firdes.root_raised_cosine(nfilts, nfilts, 1.0/float(sps), excess_bw, 45*nfilts)
         self.revconj_access_code_symbols = revconj_access_code_symbols = [(1.4142135623730951+1.4142135623730951j), (1.4142135623730951+1.4142135623730951j), (1.4142135623730951-1.4142135623730951j), (-1.4142135623730951+1.4142135623730951j), (1.4142135623730951-1.4142135623730951j), (1.4142135623730951-1.4142135623730951j), (1.4142135623730951+1.4142135623730951j), (-1.4142135623730951+1.4142135623730951j)]
         self.const = const = digital.constellation_qpsk().base()
-        self.access_code_symbols_sps = access_code_symbols_sps = [(1.4142197+1.4142197j), (1.4142197+1.4142197j), (1.4142197+1.4142197j), (1.4142197+1.4142197j), (1.4142197-1.4142197j), (1.4142197-1.4142197j), (1.4142197-1.4142197j), (1.4142197-1.4142197j), (1.4142197-1.4142197j), (1.4142197-1.4142197j), (1.4142197-1.4142197j), (1.4142197-1.4142197j), (-1.4142197-1.4142197j), (-1.4142197-1.4142197j), (-1.4142197-1.4142197j), (-1.4142197-1.4142197j), (1.4142197-1.4142197j), (1.4142197-1.4142197j), (1.4142197-1.4142197j), (1.4142197-1.4142197j), (1.4142197+1.4142197j), (1.4142197+1.4142197j), (1.4142197+1.4142197j), (1.4142197+1.4142197j), (1.4142197+1.4142197j), (1.4142197+1.4142197j), (1.4142197+1.4142197j), (1.4142197+1.4142197j)]
         self.access_code_symbols = access_code_symbols = [(-1.4142135623730951-1.4142135623730951j), (1.4142135623730951-1.4142135623730951j), (1.4142135623730951+1.4142135623730951j), (1.4142135623730951+1.4142135623730951j), (-1.4142135623730951-1.4142135623730951j), (1.4142135623730951+1.4142135623730951j), (1.4142135623730951-1.4142135623730951j), (1.4142135623730951-1.4142135623730951j)]
 
         ##################################################
@@ -145,7 +146,7 @@ class correlator(gr.top_block, Qt.QWidget):
             self.top_grid_layout.setColumnStretch(c, 1)
         self.qtgui_time_sink_x_0_0_0 = qtgui.time_sink_c(
             1024, #size
-            samp_rate, #samp_rate
+            samp_rate / sps, #samp_rate
             "", #name
             1 #number of inputs
         )
@@ -195,7 +196,7 @@ class correlator(gr.top_block, Qt.QWidget):
         self.top_grid_layout.addWidget(self._qtgui_time_sink_x_0_0_0_win)
         self.qtgui_time_sink_x_0_0 = qtgui.time_sink_f(
             1024, #size
-            samp_rate, #samp_rate
+            samp_rate / sps, #samp_rate
             "", #name
             1 #number of inputs
         )
@@ -328,6 +329,7 @@ class correlator(gr.top_block, Qt.QWidget):
             self.top_grid_layout.setRowStretch(r, 1)
         for c in range(1, 2):
             self.top_grid_layout.setColumnStretch(c, 1)
+        self.epy_block_1 = epy_block_1.blk()
         self.epy_block_0 = epy_block_0.blk()
         self.digital_pfb_clock_sync_xxx_0 = digital.pfb_clock_sync_ccf(sps, timing_loop_bw, rrc_taps, nfilts, 16, 1.5, 1)
         self.digital_costas_loop_cc_0 = digital.costas_loop_cc(2 * 3.141592653589793 / 100, 4, False)
@@ -343,16 +345,16 @@ class correlator(gr.top_block, Qt.QWidget):
         self.digital_constellation_decoder_cb_0 = digital.constellation_decoder_cb(const)
         self.digital_cma_equalizer_cc_0 = digital.cma_equalizer_cc(15, 1, .002, 1)
         self.channels_channel_model_0 = channels.channel_model(
-            noise_voltage=0.2,
+            noise_voltage=0.01,
             frequency_offset=0.0001,
             epsilon=1.0,
-            taps=[-1.4 + .4j],
+            taps=[np.exp(1j * 30 / 180 * np.pi)],
             noise_seed=243,
             block_tags=False)
-        self.blocks_vector_source_x_0 = blocks.vector_source_b(testvec * 1600, True, 1, [])
-        self.blocks_vector_sink_x_0 = blocks.vector_sink_b(1, 1024)
+        self.blocks_vector_source_x_0 = blocks.vector_source_b(testvec * 500, True, 1, [])
         self.blocks_throttle_0 = blocks.throttle(gr.sizeof_gr_complex*1, samp_rate,True)
-        self.blocks_stream_mux_0 = blocks.stream_mux(gr.sizeof_char*1, [10, len(testvec)])
+        self.blocks_stream_mux_0 = blocks.stream_mux(gr.sizeof_char*1, [5, len(testvec)])
+        self.blocks_repack_bits_bb_0 = blocks.repack_bits_bb(2, 8, "", False, gr.GR_MSB_FIRST)
         self.blocks_null_source_0 = blocks.null_source(gr.sizeof_char*1)
         self.blocks_null_sink_3 = blocks.null_sink(gr.sizeof_float*1)
         self.blocks_complex_to_magphase_0_0 = blocks.complex_to_magphase(1)
@@ -365,13 +367,14 @@ class correlator(gr.top_block, Qt.QWidget):
         self.connect((self.blocks_complex_to_magphase_0_0, 1), (self.blocks_null_sink_3, 0))
         self.connect((self.blocks_complex_to_magphase_0_0, 0), (self.qtgui_time_sink_x_0_0, 0))
         self.connect((self.blocks_null_source_0, 0), (self.blocks_stream_mux_0, 0))
+        self.connect((self.blocks_repack_bits_bb_0, 0), (self.epy_block_1, 0))
         self.connect((self.blocks_stream_mux_0, 0), (self.digital_constellation_modulator_0, 0))
         self.connect((self.blocks_throttle_0, 0), (self.digital_pfb_clock_sync_xxx_0, 0))
         self.connect((self.blocks_vector_source_x_0, 0), (self.blocks_stream_mux_0, 1))
         self.connect((self.channels_channel_model_0, 0), (self.blocks_throttle_0, 0))
         self.connect((self.digital_cma_equalizer_cc_0, 0), (self.digital_corr_est_cc_0, 0))
         self.connect((self.digital_cma_equalizer_cc_0, 0), (self.qtgui_const_sink_x_0, 0))
-        self.connect((self.digital_constellation_decoder_cb_0, 0), (self.blocks_vector_sink_x_0, 0))
+        self.connect((self.digital_constellation_decoder_cb_0, 0), (self.blocks_repack_bits_bb_0, 0))
         self.connect((self.digital_constellation_modulator_0, 0), (self.channels_channel_model_0, 0))
         self.connect((self.digital_constellation_modulator_0, 0), (self.qtgui_time_sink_x_1_0, 0))
         self.connect((self.digital_corr_est_cc_0, 1), (self.blocks_complex_to_magphase_0_0, 0))
@@ -395,6 +398,8 @@ class correlator(gr.top_block, Qt.QWidget):
     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), self.excess_bw, 45*self.nfilts))
+        self.qtgui_time_sink_x_0_0.set_samp_rate(self.samp_rate / self.sps)
+        self.qtgui_time_sink_x_0_0_0.set_samp_rate(self.samp_rate / self.sps)
 
     def get_nfilts(self):
         return self.nfilts
@@ -422,7 +427,7 @@ class correlator(gr.top_block, Qt.QWidget):
 
     def set_testvec(self, testvec):
         self.testvec = testvec
-        self.blocks_vector_source_x_0.set_data(self.testvec * 1600, [])
+        self.blocks_vector_source_x_0.set_data(self.testvec * 500, [])
 
     def get_samp_rate(self):
         return self.samp_rate
@@ -430,8 +435,8 @@ class correlator(gr.top_block, Qt.QWidget):
     def set_samp_rate(self, samp_rate):
         self.samp_rate = samp_rate
         self.blocks_throttle_0.set_sample_rate(self.samp_rate)
-        self.qtgui_time_sink_x_0_0.set_samp_rate(self.samp_rate)
-        self.qtgui_time_sink_x_0_0_0.set_samp_rate(self.samp_rate)
+        self.qtgui_time_sink_x_0_0.set_samp_rate(self.samp_rate / self.sps)
+        self.qtgui_time_sink_x_0_0_0.set_samp_rate(self.samp_rate / self.sps)
         self.qtgui_time_sink_x_1_0.set_samp_rate(self.samp_rate)
 
     def get_rrc_taps(self):
@@ -453,12 +458,6 @@ class correlator(gr.top_block, Qt.QWidget):
     def set_const(self, const):
         self.const = const
 
-    def get_access_code_symbols_sps(self):
-        return self.access_code_symbols_sps
-
-    def set_access_code_symbols_sps(self, access_code_symbols_sps):
-        self.access_code_symbols_sps = access_code_symbols_sps
-
     def get_access_code_symbols(self):
         return self.access_code_symbols
 
diff --git a/tests/correlator/epy_block_0.py b/tests/correlator/epy_block_0.py
index e7599c9..a581a3a 100644
--- a/tests/correlator/epy_block_0.py
+++ b/tests/correlator/epy_block_0.py
@@ -25,7 +25,7 @@ class blk(gr.sync_block):
         # filter to avoid werid jumps in the correction. to do that, there are
         # two buffers with an index
         self.index = 0
-        self.length = 7
+        self.length = 5
         self.freq = np.zeros(self.length)
 
     def lpf_freq(self, new_sample):
@@ -46,12 +46,20 @@ class blk(gr.sync_block):
 
         # compute frequency offset between start and end
         # and run it through a low pass filter (mean)
-        freq = (sphase - ephase) / nsamples
-        freq = self.lpf_freq(freq)
+        phasediff = ephase - sphase
+
+        if phasediff > np.pi:
+            phasediff -= 2*np.pi
+
+        elif phasediff < -np.pi:
+            phasediff += 2*np.pi
+
+        freq = phasediff / nsamples
+        # freq = self.lpf_freq(freq)
 
         # debugging
         print(f"Correction for block of {nsamples:2d} samples is " \
-              f"phase={sphase: .4f} rad and freq={freq*1e3: .4f} milli rad / sample")
+              f"sphase={sphase: .4f} rad and freq={freq*1e3: .4f} milli rad / sample")
 
         # compute block values
         return sphase * np.ones(nsamples) + freq * np.arange(0, nsamples)
diff --git a/tests/correlator/epy_block_1.py b/tests/correlator/epy_block_1.py
new file mode 100644
index 0000000..d30c2eb
--- /dev/null
+++ b/tests/correlator/epy_block_1.py
@@ -0,0 +1,27 @@
+"""
+Embedded Python Blocks:
+
+Each time this file is saved, GRC will instantiate the first class it finds
+to get ports and parameters of your block. The arguments to __init__  will
+be the parameters. All of them are required to have default values!
+"""
+
+import numpy as np
+from gnuradio import gr
+
+np.set_printoptions(formatter={'int':hex})
+
+class blk(gr.sync_block):
+    def __init__(self):
+        gr.sync_block.__init__(
+            self,
+            name='Printer',
+            in_sig=[np.byte],
+            out_sig=[]
+        )
+
+    def work(self, input_items, output_items):
+        inp = np.array(input_items[0], dtype=np.uint8)
+        print(f"Decoded {len(inp)} samples:\n{inp}")
+
+        return len(inp)
-- 
cgit v1.2.1


From cafce753722ec8d396cadfdf991b5c6f5a18dc12 Mon Sep 17 00:00:00 2001
From: sara <sara.halter@gmx.ch>
Date: Fri, 3 Dec 2021 20:46:20 +0100
Subject: BER Block Fertig gestellt

---
 tests/BER/Bit_error.grc         | 66 ++++++++++++++++++++++++++++++++++++++---
 tests/BER/Test_Bit_Errorrate.py | 26 +++++++++++++---
 2 files changed, 84 insertions(+), 8 deletions(-)

(limited to 'tests')

diff --git a/tests/BER/Bit_error.grc b/tests/BER/Bit_error.grc
index 04c624b..1a1a891 100644
--- a/tests/BER/Bit_error.grc
+++ b/tests/BER/Bit_error.grc
@@ -56,6 +56,49 @@ blocks:
     coordinate: [216, 396.0]
     rotation: 0
     state: enabled
+- name: vlen
+  id: variable
+  parameters:
+    comment: ''
+    value: '10'
+  states:
+    bus_sink: false
+    bus_source: false
+    bus_structure: null
+    coordinate: [216, 196.0]
+    rotation: 0
+    state: true
+- name: wrong
+  id: variable
+  parameters:
+    comment: ''
+    value: list(np.random.randint(0, 255, dtype=np.uint8, size=10))
+  states:
+    bus_sink: false
+    bus_source: false
+    bus_structure: null
+    coordinate: [216, 460.0]
+    rotation: 0
+    state: true
+- name: blocks_throttle_0
+  id: blocks_throttle
+  parameters:
+    affinity: ''
+    alias: ''
+    comment: ''
+    ignoretag: 'True'
+    maxoutbuf: '0'
+    minoutbuf: '0'
+    samples_per_second: samp_rate
+    type: byte
+    vlen: vlen
+  states:
+    bus_sink: false
+    bus_source: false
+    bus_structure: null
+    coordinate: [448, 292.0]
+    rotation: 0
+    state: true
 - name: blocks_vector_source_x_0
   id: blocks_vector_source_x
   parameters:
@@ -67,8 +110,8 @@ blocks:
     repeat: 'True'
     tags: '[]'
     type: byte
-    vector: testvec * 1600
-    vlen: '1'
+    vector: testvec + list(np.random.randint(0, 255, dtype=np.uint8, size=10))
+    vlen: vlen
   states:
     bus_sink: false
     bus_source: false
@@ -83,16 +126,31 @@ blocks:
     alias: ''
     comment: ''
     vgl: testvec
+    vlen: vlen
+  states:
+    bus_sink: false
+    bus_source: false
+    bus_structure: null
+    coordinate: [672, 292.0]
+    rotation: 0
+    state: true
+- name: import_0
+  id: import
+  parameters:
+    alias: ''
+    comment: ''
+    imports: import numpy as np
   states:
     bus_sink: false
     bus_source: false
     bus_structure: null
-    coordinate: [704, 296.0]
+    coordinate: [328, 20.0]
     rotation: 0
     state: true
 
 connections:
-- [blocks_vector_source_x_0, '0', fadingui_ber_0, '0']
+- [blocks_throttle_0, '0', fadingui_ber_0, '0']
+- [blocks_vector_source_x_0, '0', blocks_throttle_0, '0']
 
 metadata:
   file_format: 1
diff --git a/tests/BER/Test_Bit_Errorrate.py b/tests/BER/Test_Bit_Errorrate.py
index 4022997..a861ae7 100755
--- a/tests/BER/Test_Bit_Errorrate.py
+++ b/tests/BER/Test_Bit_Errorrate.py
@@ -31,6 +31,7 @@ from argparse import ArgumentParser
 from gnuradio.eng_arg import eng_float, intx
 from gnuradio import eng_notation
 import fadingui
+import numpy as np
 
 from gnuradio import qtgui
 
@@ -70,21 +71,25 @@ class Test_Bit_Errorrate(gr.top_block, Qt.QWidget):
         ##################################################
         # Variables
         ##################################################
+        self.wrong = wrong = list(np.random.randint(0, 255, dtype=np.uint8, size=10))
+        self.vlen = vlen = 10
         self.testvec = testvec = [31, 53] + [0x12, 0xe3, 0x9b, 0xee, 0x84, 0x23, 0x41, 0xf3]
         self.samp_rate = samp_rate = 32000
 
         ##################################################
         # Blocks
         ##################################################
-        self.fadingui_ber_0 = fadingui.ber(vgl=testvec)
-        self.blocks_vector_source_x_0 = blocks.vector_source_b(testvec * 1600, True, 1, [])
+        self.fadingui_ber_0 = fadingui.ber(vgl=testvec, vlen=vlen)
+        self.blocks_vector_source_x_0 = blocks.vector_source_b(testvec + list(np.random.randint(0, 255, dtype=np.uint8, size=10)), True, vlen, [])
+        self.blocks_throttle_0 = blocks.throttle(gr.sizeof_char*vlen, samp_rate,True)
 
 
 
         ##################################################
         # Connections
         ##################################################
-        self.connect((self.blocks_vector_source_x_0, 0), (self.fadingui_ber_0, 0))
+        self.connect((self.blocks_throttle_0, 0), (self.fadingui_ber_0, 0))
+        self.connect((self.blocks_vector_source_x_0, 0), (self.blocks_throttle_0, 0))
 
 
     def closeEvent(self, event):
@@ -92,18 +97,31 @@ class Test_Bit_Errorrate(gr.top_block, Qt.QWidget):
         self.settings.setValue("geometry", self.saveGeometry())
         event.accept()
 
+    def get_wrong(self):
+        return self.wrong
+
+    def set_wrong(self, wrong):
+        self.wrong = wrong
+
+    def get_vlen(self):
+        return self.vlen
+
+    def set_vlen(self, vlen):
+        self.vlen = vlen
+
     def get_testvec(self):
         return self.testvec
 
     def set_testvec(self, testvec):
         self.testvec = testvec
-        self.blocks_vector_source_x_0.set_data(self.testvec * 1600, [])
+        self.blocks_vector_source_x_0.set_data(self.testvec + list(np.random.randint(0, 255, dtype=np.uint8, size=10)), [])
 
     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)
 
 
 
-- 
cgit v1.2.1


From eb385ffb0c3c41d7097fb74260f3a39c2aaeb926 Mon Sep 17 00:00:00 2001
From: Nao Pross <np@0hm.ch>
Date: Fri, 3 Dec 2021 21:55:18 +0100
Subject: Remove frequency LPF and clean up

---
 tests/correlator/correlator.grc | 94 ++++++++++++++++++++---------------------
 tests/correlator/epy_block_0.py | 40 ++++++------------
 2 files changed, 58 insertions(+), 76 deletions(-)

(limited to 'tests')

diff --git a/tests/correlator/correlator.grc b/tests/correlator/correlator.grc
index 0f82f27..beea007 100644
--- a/tests/correlator/correlator.grc
+++ b/tests/correlator/correlator.grc
@@ -193,7 +193,7 @@ blocks:
     bus_sink: false
     bus_source: false
     bus_structure: null
-    coordinate: [1032, 1176.0]
+    coordinate: [1080, 1176.0]
     rotation: 0
     state: enabled
 - name: blocks_multiply_const_vxx_0
@@ -505,36 +505,34 @@ blocks:
   parameters:
     _source_code: "import pmt\n\nimport numpy as np\nfrom gnuradio import gr\n\n\n\
       class blk(gr.sync_block):\n    def __init__(self):\n        gr.sync_block.__init__(\n\
-      \            self,\n            name='Phase Lock',\n            in_sig=[np.complex64],\n\
-      \            out_sig=[np.complex64]\n        )\n\n        # we need to keep\
-      \ track of the aboslute number of samples that have\n        # been processed,\
-      \ because tags have an absolute offset\n        self.counter: np.uint64 = 0\n\
-      \n        # because we do block processing, we need to keep track of the last\
-      \ tag\n        # of the previous block to correct the first values of the next\
-      \ block\n        self.last = None\n\n        # both the phase and frequency\
-      \ corrections should go through a low pass\n        # filter to avoid werid\
-      \ jumps in the correction. to do that, there are\n        # two buffers with\
-      \ an index\n        self.index = 0\n        self.length = 5\n        self.freq\
-      \ = np.zeros(self.length)\n\n    def lpf_freq(self, new_sample):\n        #\
-      \ save new sample\n        self.freq[self.index] = new_sample\n        # increment\
-      \ index\n        self.index = (self.index + 1) % self.length\n\n        return\
-      \ np.sum(self.freq) / self.length\n\n    def block_phase(self, start, end):\n\
-      \        # compute number of samples in block\n        nsamples = end.offset\
-      \ - start.offset\n\n        # unpack pmt values into start and end phase\n \
-      \       sphase = pmt.to_python(start.value)\n        ephase = pmt.to_python(end.value)\n\
-      \n        # compute frequency offset between start and end\n        # and run\
-      \ it through a low pass filter (mean)\n        phasediff = ephase - sphase\n\
-      \n        if phasediff > np.pi:\n            phasediff -= 2*np.pi\n\n      \
-      \  elif phasediff < -np.pi:\n            phasediff += 2*np.pi\n\n        freq\
-      \ = phasediff / nsamples\n        # freq = self.lpf_freq(freq)\n\n        #\
-      \ debugging\n        print(f\"Correction for block of {nsamples:2d} samples\
-      \ is \" \\\n              f\"sphase={sphase: .4f} rad and freq={freq*1e3: .4f}\
-      \ milli rad / sample\")\n\n        # compute block values\n        return sphase\
-      \ * np.ones(nsamples) + freq * np.arange(0, nsamples)\n\n    def work(self,\
-      \ input_items, output_items):\n        # FIXME: replace class counter with local\
-      \ variable\n        self.counter = self.nitems_written(0)\n\n        # nicer\
-      \ aliases\n        inp = input_items[0]\n        out = output_items[0]\n\n \
-      \       # read phase tags\n        is_phase = lambda tag: pmt.to_python(tag.key)\
+      \            self,\n            name='Phase and Frequency Correction',\n   \
+      \         in_sig=[np.complex64],\n            out_sig=[np.complex64]\n     \
+      \   )\n\n        # tags should not be propagated, we then output our own tags\n\
+      \        self.set_tag_propagation_policy(gr.TPP_DONT)\n\n        # because we\
+      \ do block processing, we need to keep track of the last tag\n        # of the\
+      \ previous block to correct the first values of the next block\n        self.last\
+      \ = None\n        self.lastfreq = 0\n\n    def block_phase(self, start, end):\n\
+      \        \"\"\"\n        Compute a vector for the phase and frequency correction\
+      \ for the samples\n        between two tags (start and end).\n\n        @param\
+      \ start Tag where the samples should start to be corrected\n        @param end\
+      \   Tag where to stop correcting\n\n        @return A vector of phase values\
+      \ for each sample. If we call the ouput\n                `phase' to correct\
+      \ the samples between the start and end tags,\n                TODO: finish\n\
+      \        \"\"\"\n        # compute number of samples in block\n        nsamples\
+      \ = end.offset - start.offset\n\n        # unpack pmt values into start and\
+      \ end phase\n        sphase = pmt.to_python(start.value)\n        ephase = pmt.to_python(end.value)\n\
+      \n        # compute frequency offset between start and end\n        phasediff\
+      \ = ephase - sphase\n\n        if phasediff > np.pi:\n            phasediff\
+      \ -= 2*np.pi\n\n        elif phasediff < -np.pi:\n            phasediff += 2*np.pi\n\
+      \n        freq = phasediff / nsamples\n\n        # save this one for the last\
+      \ block (see variable `end' in self.work)\n        self.lastfreq = freq\n\n\
+      \        # debugging\n        print(f\"Correction for block of {nsamples:2d}\
+      \ samples is \" \\\n              f\"sphase={sphase: .4f} rad and freq={freq*1e3:\
+      \ .4f} milli rad / sample\")\n\n        # compute block values\n        return\
+      \ sphase * np.ones(nsamples) + freq * np.arange(0, nsamples)\n\n    def work(self,\
+      \ input_items, output_items):\n        counter = self.nitems_written(0)\n\n\
+      \        # nicer aliases\n        inp = input_items[0]\n        out = output_items[0]\n\
+      \n        # read phase tags\n        is_phase = lambda tag: pmt.to_python(tag.key)\
       \ == \"phase_est\"\n        tags = list(filter(is_phase, self.get_tags_in_window(0,\
       \ 0, len(inp))))\n\n        if not tags:\n            print(f\"There were no\
       \ tags in {len(inp)} samples!\")\n            out[:] = inp\n            return\
@@ -546,32 +544,32 @@ blocks:
       \ (start, end) in pairs ]\n        middle = np.concatenate(blocks) if blocks\
       \ else []\n\n        # compute values at the end, we do not have informations\
       \ about the future\n        # but we can use the frequency of the last block\
-      \ to approximate\n        nback = len(inp) - (tags[-1].offset - self.counter)\n\
-      \        print(f\"Processing {nback} samples at the back of the buffer\")\n\
-      \        endfreq = self.lpf_freq(self.freq[-1])\n        end = np.ones(nback)\
-      \ * pmt.to_python(tags[-1].value) + endfreq * np.arange(0, nback)\n\n      \
-      \  # compute the \"start\", using the last tag from the previous call\n    \
-      \    nfront = tags[0].offset - self.counter\n        print(f\"Processing {nfront}\
-      \ samples at the front of the buffer\")\n        start = self.block_phase(self.last,\
-      \ tags[0])[-nfront:] \\\n                if self.last and nfront else np.zeros(nfront)\n\
-      \n        # compute correction\n        correction = np.exp(-1j * np.concatenate([start,\
+      \ to approximate\n        nback = len(inp) - (tags[-1].offset - counter)\n \
+      \       print(f\"Processing {nback} samples at the back of the buffer\")\n \
+      \       end = np.ones(nback) * pmt.to_python(tags[-1].value) \\\n          \
+      \      + self.lastfreq * np.arange(0, nback)\n\n        # compute the \"start\"\
+      , using the last tag from the previous call\n        nfront = tags[0].offset\
+      \ - counter\n        print(f\"Processing {nfront} samples at the front of the\
+      \ buffer\")\n        start = self.block_phase(self.last, tags[0])[-nfront:]\
+      \ \\\n                if self.last and nfront else np.zeros(nfront)\n\n    \
+      \    # compute correction\n        correction = np.exp(-1j * np.concatenate([start,\
       \ middle, end]))\n        length = len(correction)\n\n        # write outputs\n\
-      \        out[:length] = inp[:length] * correction\n        self.counter += len(inp)\n\
-      \n        # save last tag for next call\n        self.last = tags[-1]\n\n  \
-      \      # FIXME: should return `length' but then the last sample is not\n   \
-      \     #        included and self.last does something weird\n        return len(out)\n"
+      \        out[:length] = inp[:length] * correction\n\n        # save last tag\
+      \ for next call\n        self.last = tags[-1]\n\n        # FIXME: should return\
+      \ `length' but then the last sample is not\n        #        included and self.last\
+      \ does something weird\n        return len(out)\n"
     affinity: ''
     alias: ''
     comment: ''
     maxoutbuf: '0'
     minoutbuf: '0'
   states:
-    _io_cache: ('Phase Lock', 'blk', [], [('0', 'complex', 1)], [('0', 'complex',
-      1)], '', [])
+    _io_cache: ('Phase and Frequency Correction', 'blk', [], [('0', 'complex', 1)],
+      [('0', 'complex', 1)], '', [])
     bus_sink: false
     bus_source: false
     bus_structure: null
-    coordinate: [1208, 912.0]
+    coordinate: [1072, 912.0]
     rotation: 0
     state: enabled
 - name: epy_block_1
@@ -1099,7 +1097,7 @@ blocks:
     bus_sink: false
     bus_source: false
     bus_structure: null
-    coordinate: [1376, 1152.0]
+    coordinate: [1376, 1156.0]
     rotation: 0
     state: enabled
 - name: qtgui_time_sink_x_0_0_0
diff --git a/tests/correlator/epy_block_0.py b/tests/correlator/epy_block_0.py
index a581a3a..ddae02a 100644
--- a/tests/correlator/epy_block_0.py
+++ b/tests/correlator/epy_block_0.py
@@ -8,33 +8,18 @@ class blk(gr.sync_block):
     def __init__(self):
         gr.sync_block.__init__(
             self,
-            name='Phase Lock',
+            name='Phase and Frequency Correction',
             in_sig=[np.complex64],
             out_sig=[np.complex64]
         )
 
-        # we need to keep track of the aboslute number of samples that have
-        # been processed, because tags have an absolute offset
-        self.counter: np.uint64 = 0
+        # tags should not be propagated, we then output our own tags
+        self.set_tag_propagation_policy(gr.TPP_DONT)
 
         # because we do block processing, we need to keep track of the last tag
         # of the previous block to correct the first values of the next block
         self.last = None
-
-        # both the phase and frequency corrections should go through a low pass
-        # filter to avoid werid jumps in the correction. to do that, there are
-        # two buffers with an index
-        self.index = 0
-        self.length = 5
-        self.freq = np.zeros(self.length)
-
-    def lpf_freq(self, new_sample):
-        # save new sample
-        self.freq[self.index] = new_sample
-        # increment index
-        self.index = (self.index + 1) % self.length
-
-        return np.sum(self.freq) / self.length
+        self.lastfreq = 0
 
     def block_phase(self, start, end):
         # compute number of samples in block
@@ -45,7 +30,6 @@ class blk(gr.sync_block):
         ephase = pmt.to_python(end.value)
 
         # compute frequency offset between start and end
-        # and run it through a low pass filter (mean)
         phasediff = ephase - sphase
 
         if phasediff > np.pi:
@@ -55,7 +39,9 @@ class blk(gr.sync_block):
             phasediff += 2*np.pi
 
         freq = phasediff / nsamples
-        # freq = self.lpf_freq(freq)
+
+        # save this one for the last block (see variable `end' in self.work)
+        self.lastfreq = freq
 
         # debugging
         print(f"Correction for block of {nsamples:2d} samples is " \
@@ -65,8 +51,7 @@ class blk(gr.sync_block):
         return sphase * np.ones(nsamples) + freq * np.arange(0, nsamples)
 
     def work(self, input_items, output_items):
-        # FIXME: replace class counter with local variable
-        self.counter = self.nitems_written(0)
+        counter = self.nitems_written(0)
 
         # nicer aliases
         inp = input_items[0]
@@ -93,13 +78,13 @@ class blk(gr.sync_block):
 
         # compute values at the end, we do not have informations about the future
         # but we can use the frequency of the last block to approximate
-        nback = len(inp) - (tags[-1].offset - self.counter)
+        nback = len(inp) - (tags[-1].offset - counter)
         print(f"Processing {nback} samples at the back of the buffer")
-        endfreq = self.lpf_freq(self.freq[-1])
-        end = np.ones(nback) * pmt.to_python(tags[-1].value) + endfreq * np.arange(0, nback)
+        end = np.ones(nback) * pmt.to_python(tags[-1].value) \
+                + self.lastfreq * np.arange(0, nback)
 
         # compute the "start", using the last tag from the previous call
-        nfront = tags[0].offset - self.counter
+        nfront = tags[0].offset - counter
         print(f"Processing {nfront} samples at the front of the buffer")
         start = self.block_phase(self.last, tags[0])[-nfront:] \
                 if self.last and nfront else np.zeros(nfront)
@@ -110,7 +95,6 @@ class blk(gr.sync_block):
 
         # write outputs
         out[:length] = inp[:length] * correction
-        self.counter += len(inp)
 
         # save last tag for next call
         self.last = tags[-1]
-- 
cgit v1.2.1


From 2d02a9787d3bbd7320f23a3c65ee8e8ed0369c1e Mon Sep 17 00:00:00 2001
From: Nao Pross <np@0hm.ch>
Date: Fri, 3 Dec 2021 22:19:57 +0100
Subject: Replace DearPyGui Sink with Network Sink

---
 tests/sockets/send.py | 21 +++++++++++++++++++++
 1 file changed, 21 insertions(+)
 create mode 100644 tests/sockets/send.py

(limited to 'tests')

diff --git a/tests/sockets/send.py b/tests/sockets/send.py
new file mode 100644
index 0000000..87faf5d
--- /dev/null
+++ b/tests/sockets/send.py
@@ -0,0 +1,21 @@
+import socket
+from urllib.parse import urlparse
+
+import numpy as np
+
+remote = "upd://localhost:31415"
+url = urlparse(remote)
+
+print(url.hostname)
+print(url.port)
+
+sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
+sock.connect((url.hostname, url.port))
+
+# sent some text
+sock.send(bytes("hello", "ascii"))
+
+arr = np.arange(0, 10)
+print(arr)
+
+sock.send(arr.tobytes())
-- 
cgit v1.2.1


From 13a2fda61a5cb1e6d3f807d0acda42c45e128434 Mon Sep 17 00:00:00 2001
From: Nao Pross <np@0hm.ch>
Date: Fri, 3 Dec 2021 23:46:33 +0100
Subject: Fix correlation peak detector and add frame_start tags

---
 tests/correlator/correlator.grc | 502 ++++++++++------------------------------
 tests/correlator/correlator.py  |  17 +-
 tests/correlator/epy_block_0.py |  32 ++-
 3 files changed, 157 insertions(+), 394 deletions(-)

(limited to 'tests')

diff --git a/tests/correlator/correlator.grc b/tests/correlator/correlator.grc
index beea007..c34e5a9 100644
--- a/tests/correlator/correlator.grc
+++ b/tests/correlator/correlator.grc
@@ -36,15 +36,15 @@ blocks:
   id: variable
   parameters:
     comment: ''
-    value: '[(-1.4142135623730951-1.4142135623730951j), (1.4142135623730951-1.4142135623730951j),
+    value: .5 * np.array([(-1.4142135623730951-1.4142135623730951j), (1.4142135623730951-1.4142135623730951j),
       (1.4142135623730951+1.4142135623730951j), (1.4142135623730951+1.4142135623730951j),
       (-1.4142135623730951-1.4142135623730951j), (1.4142135623730951+1.4142135623730951j),
-      (1.4142135623730951-1.4142135623730951j), (1.4142135623730951-1.4142135623730951j)]'
+      (1.4142135623730951-1.4142135623730951j), (1.4142135623730951-1.4142135623730951j)])
   states:
     bus_sink: false
     bus_source: false
     bus_structure: null
-    coordinate: [768, 1016.0]
+    coordinate: [792, 788.0]
     rotation: 0
     state: enabled
 - name: const
@@ -101,7 +101,7 @@ blocks:
     bus_sink: false
     bus_source: false
     bus_structure: null
-    coordinate: [48, 440.0]
+    coordinate: [784, 1052.0]
     rotation: 0
     state: enabled
 - name: rrc_taps
@@ -164,22 +164,6 @@ blocks:
     coordinate: [224, 936.0]
     rotation: 0
     state: enabled
-- name: blocks_complex_to_magphase_0
-  id: blocks_complex_to_magphase
-  parameters:
-    affinity: ''
-    alias: ''
-    comment: ''
-    maxoutbuf: '0'
-    minoutbuf: '0'
-    vlen: '1'
-  states:
-    bus_sink: false
-    bus_source: false
-    bus_structure: null
-    coordinate: [1040, 568.0]
-    rotation: 0
-    state: disabled
 - name: blocks_complex_to_magphase_0_0
   id: blocks_complex_to_magphase
   parameters:
@@ -193,27 +177,9 @@ blocks:
     bus_sink: false
     bus_source: false
     bus_structure: null
-    coordinate: [1080, 1176.0]
+    coordinate: [1056, 984.0]
     rotation: 0
     state: enabled
-- name: blocks_multiply_const_vxx_0
-  id: blocks_multiply_const_vxx
-  parameters:
-    affinity: ''
-    alias: ''
-    comment: ''
-    const: 180 / 3.141592653589793
-    maxoutbuf: '0'
-    minoutbuf: '0'
-    type: float
-    vlen: '1'
-  states:
-    bus_sink: false
-    bus_source: false
-    bus_structure: null
-    coordinate: [1288, 596.0]
-    rotation: 0
-    state: disabled
 - name: blocks_multiply_const_vxx_0_0
   id: blocks_multiply_const_vxx
   parameters:
@@ -229,7 +195,7 @@ blocks:
     bus_sink: false
     bus_source: false
     bus_structure: null
-    coordinate: [1376, 1248.0]
+    coordinate: [1312, 1076.0]
     rotation: 0
     state: disabled
 - name: blocks_null_sink_3
@@ -246,7 +212,7 @@ blocks:
     bus_sink: false
     bus_source: false
     bus_structure: null
-    coordinate: [1376, 1304.0]
+    coordinate: [1360, 1016.0]
     rotation: 0
     state: true
 - name: blocks_null_source_0
@@ -294,7 +260,7 @@ blocks:
     affinity: ''
     alias: ''
     comment: ''
-    lengths: '[5, len(testvec)]'
+    lengths: '[0, len(testvec)]'
     maxoutbuf: '0'
     minoutbuf: '0'
     num_inputs: '2'
@@ -307,6 +273,43 @@ blocks:
     coordinate: [288, 256.0]
     rotation: 0
     state: enabled
+- name: blocks_tag_debug_0
+  id: blocks_tag_debug
+  parameters:
+    affinity: ''
+    alias: ''
+    comment: ''
+    display: 'True'
+    filter: '""'
+    name: ''
+    num_inputs: '1'
+    type: byte
+    vlen: '1'
+  states:
+    bus_sink: false
+    bus_source: false
+    bus_structure: null
+    coordinate: [1208, 1164.0]
+    rotation: 0
+    state: disabled
+- name: blocks_tagged_stream_align_0
+  id: blocks_tagged_stream_align
+  parameters:
+    affinity: ''
+    alias: ''
+    comment: ''
+    lengthtagname: frame_start
+    maxoutbuf: '0'
+    minoutbuf: '0'
+    type: byte
+    vlen: '1'
+  states:
+    bus_sink: false
+    bus_source: false
+    bus_structure: null
+    coordinate: [928, 1260.0]
+    rotation: 0
+    state: true
 - name: blocks_throttle_0
   id: blocks_throttle
   parameters:
@@ -354,7 +357,7 @@ blocks:
     block_tags: 'False'
     comment: ''
     epsilon: '1.0'
-    freq_offset: '0.0001'
+    freq_offset: '0.002'
     maxoutbuf: '0'
     minoutbuf: '0'
     noise_voltage: '0.01'
@@ -429,18 +432,18 @@ blocks:
     affinity: ''
     alias: ''
     comment: ''
-    mark_delay: '0'
+    mark_delay: len(access_code_symbols) // 2
     maxoutbuf: '0'
     minoutbuf: '0'
     sps: '1'
     symbols: access_code_symbols
-    threshold: '.8'
-    threshold_method: digital.THRESHOLD_DYNAMIC
+    threshold: '.9'
+    threshold_method: digital.THRESHOLD_ABSOLUTE
   states:
     bus_sink: false
     bus_source: false
     bus_structure: null
-    coordinate: [768, 892.0]
+    coordinate: [792, 668.0]
     rotation: 0
     state: enabled
 - name: digital_costas_loop_cc_0
@@ -458,7 +461,7 @@ blocks:
     bus_sink: false
     bus_source: false
     bus_structure: null
-    coordinate: [1080, 1000.0]
+    coordinate: [1104, 808.0]
     rotation: 0
     state: true
 - name: digital_map_bb_0
@@ -476,7 +479,7 @@ blocks:
     bus_structure: null
     coordinate: [496, 1260.0]
     rotation: 0
-    state: bypassed
+    state: enabled
 - name: digital_pfb_clock_sync_xxx_0
   id: digital_pfb_clock_sync_xxx
   parameters:
@@ -504,31 +507,33 @@ blocks:
   id: epy_block
   parameters:
     _source_code: "import pmt\n\nimport numpy as np\nfrom gnuradio import gr\n\n\n\
-      class blk(gr.sync_block):\n    def __init__(self):\n        gr.sync_block.__init__(\n\
-      \            self,\n            name='Phase and Frequency Correction',\n   \
-      \         in_sig=[np.complex64],\n            out_sig=[np.complex64]\n     \
-      \   )\n\n        # tags should not be propagated, we then output our own tags\n\
-      \        self.set_tag_propagation_policy(gr.TPP_DONT)\n\n        # because we\
-      \ do block processing, we need to keep track of the last tag\n        # of the\
-      \ previous block to correct the first values of the next block\n        self.last\
-      \ = None\n        self.lastfreq = 0\n\n    def block_phase(self, start, end):\n\
-      \        \"\"\"\n        Compute a vector for the phase and frequency correction\
-      \ for the samples\n        between two tags (start and end).\n\n        @param\
-      \ start Tag where the samples should start to be corrected\n        @param end\
-      \   Tag where to stop correcting\n\n        @return A vector of phase values\
-      \ for each sample. If we call the ouput\n                `phase' to correct\
-      \ the samples between the start and end tags,\n                TODO: finish\n\
-      \        \"\"\"\n        # compute number of samples in block\n        nsamples\
-      \ = end.offset - start.offset\n\n        # unpack pmt values into start and\
-      \ end phase\n        sphase = pmt.to_python(start.value)\n        ephase = pmt.to_python(end.value)\n\
+      class blk(gr.sync_block):\n    \"\"\"\n    Apply phase and frequency correction\
+      \ where there is a correlation peak tag.\n\n    The correlation peak tags are\
+      \ NOT propagated, and instead replaced with a\n    frame_start tag.\n    \"\"\
+      \"\n    def __init__(self):\n        gr.sync_block.__init__(\n            self,\n\
+      \            name='Phase and Frequency Correction',\n            in_sig=[np.complex64],\n\
+      \            out_sig=[np.complex64]\n        )\n\n        # tags should not\
+      \ be propagated, we then output our own tags\n        self.set_tag_propagation_policy(gr.TPP_DONT)\n\
+      \n        # because we do block processing, we need to keep track of the last\
+      \ tag\n        # of the previous block to correct the first values of the next\
+      \ block\n        self.last = None\n        self.lastfreq = 0\n\n    def block_phase(self,\
+      \ start, end):\n        \"\"\"\n        Compute a vector for the phase and frequency\
+      \ correction for the samples\n        between two tags (start and end).\n\n\
+      \        @param start Tag where the samples should start to be corrected\n \
+      \       @param end   Tag where to stop correcting\n\n        @return A vector\
+      \ of phase values for each sample. To correct the samples\n                the\
+      \ data should be multiplied with np.exp(-1j * phase)\n        \"\"\"\n     \
+      \   # compute number of samples between tags\n        nsamples = end.offset\
+      \ - start.offset\n\n        # unpack pmt values into start and end phase\n \
+      \       sphase = pmt.to_python(start.value)\n        ephase = pmt.to_python(end.value)\n\
       \n        # compute frequency offset between start and end\n        phasediff\
       \ = ephase - sphase\n\n        if phasediff > np.pi:\n            phasediff\
       \ -= 2*np.pi\n\n        elif phasediff < -np.pi:\n            phasediff += 2*np.pi\n\
       \n        freq = phasediff / nsamples\n\n        # save this one for the last\
       \ block (see variable `end' in self.work)\n        self.lastfreq = freq\n\n\
-      \        # debugging\n        print(f\"Correction for block of {nsamples:2d}\
+      \        # debugging\n        print(f\"Correction for chunk of {nsamples:2d}\
       \ samples is \" \\\n              f\"sphase={sphase: .4f} rad and freq={freq*1e3:\
-      \ .4f} milli rad / sample\")\n\n        # compute block values\n        return\
+      \ .4f} milli rad / sample\")\n\n        # compute chunk values\n        return\
       \ sphase * np.ones(nsamples) + freq * np.arange(0, nsamples)\n\n    def work(self,\
       \ input_items, output_items):\n        counter = self.nitems_written(0)\n\n\
       \        # nicer aliases\n        inp = input_items[0]\n        out = output_items[0]\n\
@@ -540,14 +545,14 @@ blocks:
       \ = {tags[-1].offset - tags[0].offset} \" \\\n              f\"samples out of\
       \ {len(inp)} input samples\")\n\n        # compute \"the middle\"\n        enough_samples\
       \ = lambda pair: ((pair[1].offset - pair[0].offset) > 0)\n        pairs = list(filter(enough_samples,\
-      \ zip(tags, tags[1:])))\n        blocks = [ self.block_phase(start, end) for\
-      \ (start, end) in pairs ]\n        middle = np.concatenate(blocks) if blocks\
+      \ zip(tags, tags[1:])))\n        chunks = [ self.block_phase(start, end) for\
+      \ (start, end) in pairs ]\n        middle = np.concatenate(chunks) if chunks\
       \ else []\n\n        # compute values at the end, we do not have informations\
-      \ about the future\n        # but we can use the frequency of the last block\
-      \ to approximate\n        nback = len(inp) - (tags[-1].offset - counter)\n \
-      \       print(f\"Processing {nback} samples at the back of the buffer\")\n \
-      \       end = np.ones(nback) * pmt.to_python(tags[-1].value) \\\n          \
-      \      + self.lastfreq * np.arange(0, nback)\n\n        # compute the \"start\"\
+      \ about the future\n        # but we can use the frequency of the last tag to\
+      \ approximate\n        nback = len(inp) - (tags[-1].offset - counter)\n    \
+      \    print(f\"Processing {nback} samples at the back of the buffer\")\n    \
+      \    end = np.ones(nback) * pmt.to_python(tags[-1].value) \\\n             \
+      \   + self.lastfreq * np.arange(0, nback)\n\n        # compute the \"start\"\
       , using the last tag from the previous call\n        nfront = tags[0].offset\
       \ - counter\n        print(f\"Processing {nfront} samples at the front of the\
       \ buffer\")\n        start = self.block_phase(self.last, tags[0])[-nfront:]\
@@ -555,9 +560,11 @@ blocks:
       \    # compute correction\n        correction = np.exp(-1j * np.concatenate([start,\
       \ middle, end]))\n        length = len(correction)\n\n        # write outputs\n\
       \        out[:length] = inp[:length] * correction\n\n        # save last tag\
-      \ for next call\n        self.last = tags[-1]\n\n        # FIXME: should return\
-      \ `length' but then the last sample is not\n        #        included and self.last\
-      \ does something weird\n        return len(out)\n"
+      \ for next call\n        self.last = tags[-1]\n\n        # add tags\n      \
+      \  for tag in tags:\n            self.add_item_tag(0, tag.offset, pmt.intern(\"\
+      frame_start\"), pmt.PMT_T)\n\n        # FIXME: should return `length' but then\
+      \ the last sample is not\n        #        included and self.last does something\
+      \ weird\n        return len(out)\n"
     affinity: ''
     alias: ''
     comment: ''
@@ -565,11 +572,13 @@ blocks:
     minoutbuf: '0'
   states:
     _io_cache: ('Phase and Frequency Correction', 'blk', [], [('0', 'complex', 1)],
-      [('0', 'complex', 1)], '', [])
+      [('0', 'complex', 1)], '\n    Apply phase and frequency correction where there
+      is a correlation peak tag.\n\n    The correlation peak tags are NOT propagated,
+      and instead replaced with a\n    frame_start tag.\n    ', [])
     bus_sink: false
     bus_source: false
     bus_structure: null
-    coordinate: [1072, 912.0]
+    coordinate: [1088, 688.0]
     rotation: 0
     state: enabled
 - name: epy_block_1
@@ -595,7 +604,7 @@ blocks:
     bus_sink: false
     bus_source: false
     bus_structure: null
-    coordinate: [920, 1264.0]
+    coordinate: [1232, 1264.0]
     rotation: 0
     state: true
 - name: fir_filter_xxx_1
@@ -614,7 +623,7 @@ blocks:
     bus_sink: false
     bus_source: false
     bus_structure: null
-    coordinate: [776, 692.0]
+    coordinate: [784, 988.0]
     rotation: 0
     state: disabled
 - name: import_0
@@ -630,6 +639,23 @@ blocks:
     coordinate: [184, 12.0]
     rotation: 0
     state: true
+- name: note_0
+  id: note
+  parameters:
+    alias: ''
+    comment: 'THIS FLOWGRAPH MUST BE RUN
+
+      FROM THE TERMINAL BECAUSE
+
+      IT HAS A HUGE OUTPUT (PRINT)'
+    note: README
+  states:
+    bus_sink: false
+    bus_source: false
+    bus_structure: null
+    coordinate: [280, 12.0]
+    rotation: 0
+    state: true
 - name: qtgui_const_sink_x_0
   id: qtgui_const_sink_x
   parameters:
@@ -719,7 +745,7 @@ blocks:
     bus_sink: false
     bus_source: false
     bus_structure: null
-    coordinate: [768, 592.0]
+    coordinate: [792, 572.0]
     rotation: 0
     state: enabled
 - name: qtgui_const_sink_x_0_0
@@ -811,198 +837,9 @@ blocks:
     bus_sink: false
     bus_source: false
     bus_structure: null
-    coordinate: [1408, 964.0]
+    coordinate: [1416, 772.0]
     rotation: 0
     state: enabled
-- name: qtgui_const_sink_x_1
-  id: qtgui_const_sink_x
-  parameters:
-    affinity: ''
-    alias: ''
-    alpha1: '.5'
-    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: 'True'
-    axislabels: 'True'
-    color1: '"blue"'
-    color10: '"red"'
-    color2: '"red"'
-    color3: '"red"'
-    color4: '"red"'
-    color5: '"red"'
-    color6: '"red"'
-    color7: '"red"'
-    color8: '"red"'
-    color9: '"red"'
-    comment: ''
-    grid: 'True'
-    gui_hint: 2,1,2,1
-    label1: ''
-    label10: ''
-    label2: ''
-    label3: ''
-    label4: ''
-    label5: ''
-    label6: ''
-    label7: ''
-    label8: ''
-    label9: ''
-    legend: 'True'
-    marker1: '9'
-    marker10: '0'
-    marker2: '0'
-    marker3: '0'
-    marker4: '0'
-    marker5: '0'
-    marker6: '0'
-    marker7: '0'
-    marker8: '0'
-    marker9: '0'
-    name: '"Cross Correlation"'
-    nconnections: '1'
-    size: '1024'
-    style1: '2'
-    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: [1040, 480.0]
-    rotation: 0
-    state: disabled
-- 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: 'True'
-    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: '""'
-    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: float
-    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: XC Magnitude
-    ymax: '20'
-    ymin: '0'
-    yunit: '""'
-  states:
-    bus_sink: false
-    bus_source: false
-    bus_structure: null
-    coordinate: [1312, 480.0]
-    rotation: 0
-    state: disabled
 - name: qtgui_time_sink_x_0_0
   id: qtgui_time_sink_x
   parameters:
@@ -1097,7 +934,7 @@ blocks:
     bus_sink: false
     bus_source: false
     bus_structure: null
-    coordinate: [1376, 1156.0]
+    coordinate: [1472, 964.0]
     rotation: 0
     state: enabled
 - name: qtgui_time_sink_x_0_0_0
@@ -1194,7 +1031,7 @@ blocks:
     bus_sink: false
     bus_source: false
     bus_structure: null
-    coordinate: [1072, 788.0]
+    coordinate: [1096, 572.0]
     rotation: 0
     state: enabled
 - name: qtgui_time_sink_x_1_0
@@ -1291,7 +1128,7 @@ blocks:
     bus_sink: false
     bus_source: false
     bus_structure: null
-    coordinate: [800, 320.0]
+    coordinate: [800, 172.0]
     rotation: 0
     state: enabled
 - name: qtgui_time_sink_x_1_1
@@ -1388,104 +1225,7 @@ blocks:
     bus_sink: false
     bus_source: false
     bus_structure: null
-    coordinate: [768, 480.0]
-    rotation: 0
-    state: disabled
-- name: qtgui_time_sink_x_2
-  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: 'True'
-    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: 3,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: '""'
-    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: float
-    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: XC Phase
-    ymax: '1'
-    ymin: '-1'
-    yunit: '""'
-  states:
-    bus_sink: false
-    bus_source: false
-    bus_structure: null
-    coordinate: [1488, 580.0]
+    coordinate: [792, 484.0]
     rotation: 0
     state: disabled
 - name: qtgui_time_sink_x_2_0
@@ -1582,7 +1322,7 @@ blocks:
     bus_sink: false
     bus_source: false
     bus_structure: null
-    coordinate: [1552, 1232.0]
+    coordinate: [1472, 1060.0]
     rotation: 0
     state: disabled
 - name: virtual_sink_0
@@ -1608,7 +1348,7 @@ blocks:
     bus_sink: false
     bus_source: false
     bus_structure: null
-    coordinate: [1400, 828.0]
+    coordinate: [1416, 684.0]
     rotation: 0
     state: true
 - name: virtual_source_0
@@ -1639,16 +1379,15 @@ blocks:
     state: true
 
 connections:
-- [blocks_complex_to_magphase_0, '0', qtgui_time_sink_x_0, '0']
-- [blocks_complex_to_magphase_0, '1', blocks_multiply_const_vxx_0, '0']
 - [blocks_complex_to_magphase_0_0, '0', qtgui_time_sink_x_0_0, '0']
 - [blocks_complex_to_magphase_0_0, '1', blocks_multiply_const_vxx_0_0, '0']
 - [blocks_complex_to_magphase_0_0, '1', blocks_null_sink_3, '0']
-- [blocks_multiply_const_vxx_0, '0', qtgui_time_sink_x_2, '0']
 - [blocks_multiply_const_vxx_0_0, '0', qtgui_time_sink_x_2_0, '0']
 - [blocks_null_source_0, '0', blocks_stream_mux_0, '0']
-- [blocks_repack_bits_bb_0, '0', epy_block_1, '0']
+- [blocks_repack_bits_bb_0, '0', blocks_tagged_stream_align_0, '0']
 - [blocks_stream_mux_0, '0', digital_constellation_modulator_0, '0']
+- [blocks_tagged_stream_align_0, '0', blocks_tag_debug_0, '0']
+- [blocks_tagged_stream_align_0, '0', epy_block_1, '0']
 - [blocks_throttle_0, '0', virtual_sink_0, '0']
 - [blocks_vector_source_x_0, '0', blocks_stream_mux_0, '1']
 - [channels_channel_model_0, '0', blocks_throttle_0, '0']
@@ -1668,8 +1407,7 @@ connections:
 - [digital_pfb_clock_sync_xxx_0, '0', digital_cma_equalizer_cc_0, '0']
 - [epy_block_0, '0', qtgui_const_sink_x_0_0, '0']
 - [epy_block_0, '0', virtual_sink_3, '0']
-- [fir_filter_xxx_1, '0', blocks_complex_to_magphase_0, '0']
-- [fir_filter_xxx_1, '0', qtgui_const_sink_x_1, '0']
+- [fir_filter_xxx_1, '0', blocks_complex_to_magphase_0_0, '0']
 - [virtual_source_0, '0', digital_pfb_clock_sync_xxx_0, '0']
 - [virtual_source_1, '0', digital_constellation_decoder_cb_0, '0']
 
diff --git a/tests/correlator/correlator.py b/tests/correlator/correlator.py
index 255010a..d9dedb2 100755
--- a/tests/correlator/correlator.py
+++ b/tests/correlator/correlator.py
@@ -85,7 +85,7 @@ class correlator(gr.top_block, Qt.QWidget):
         self.rrc_taps = rrc_taps = firdes.root_raised_cosine(nfilts, nfilts, 1.0/float(sps), excess_bw, 45*nfilts)
         self.revconj_access_code_symbols = revconj_access_code_symbols = [(1.4142135623730951+1.4142135623730951j), (1.4142135623730951+1.4142135623730951j), (1.4142135623730951-1.4142135623730951j), (-1.4142135623730951+1.4142135623730951j), (1.4142135623730951-1.4142135623730951j), (1.4142135623730951-1.4142135623730951j), (1.4142135623730951+1.4142135623730951j), (-1.4142135623730951+1.4142135623730951j)]
         self.const = const = digital.constellation_qpsk().base()
-        self.access_code_symbols = access_code_symbols = [(-1.4142135623730951-1.4142135623730951j), (1.4142135623730951-1.4142135623730951j), (1.4142135623730951+1.4142135623730951j), (1.4142135623730951+1.4142135623730951j), (-1.4142135623730951-1.4142135623730951j), (1.4142135623730951+1.4142135623730951j), (1.4142135623730951-1.4142135623730951j), (1.4142135623730951-1.4142135623730951j)]
+        self.access_code_symbols = access_code_symbols = .5 * np.array([(-1.4142135623730951-1.4142135623730951j), (1.4142135623730951-1.4142135623730951j), (1.4142135623730951+1.4142135623730951j), (1.4142135623730951+1.4142135623730951j), (-1.4142135623730951-1.4142135623730951j), (1.4142135623730951+1.4142135623730951j), (1.4142135623730951-1.4142135623730951j), (1.4142135623730951-1.4142135623730951j)])
 
         ##################################################
         # Blocks
@@ -332,8 +332,9 @@ class correlator(gr.top_block, Qt.QWidget):
         self.epy_block_1 = epy_block_1.blk()
         self.epy_block_0 = epy_block_0.blk()
         self.digital_pfb_clock_sync_xxx_0 = digital.pfb_clock_sync_ccf(sps, timing_loop_bw, rrc_taps, nfilts, 16, 1.5, 1)
+        self.digital_map_bb_0 = digital.map_bb([0, 1, 3, 2])
         self.digital_costas_loop_cc_0 = digital.costas_loop_cc(2 * 3.141592653589793 / 100, 4, False)
-        self.digital_corr_est_cc_0 = digital.corr_est_cc(access_code_symbols, 1, 0, .8, digital.THRESHOLD_DYNAMIC)
+        self.digital_corr_est_cc_0 = digital.corr_est_cc(access_code_symbols, 1, len(access_code_symbols) // 2, .9, digital.THRESHOLD_ABSOLUTE)
         self.digital_constellation_modulator_0 = digital.generic_mod(
             constellation=const,
             differential=False,
@@ -346,14 +347,15 @@ class correlator(gr.top_block, Qt.QWidget):
         self.digital_cma_equalizer_cc_0 = digital.cma_equalizer_cc(15, 1, .002, 1)
         self.channels_channel_model_0 = channels.channel_model(
             noise_voltage=0.01,
-            frequency_offset=0.0001,
+            frequency_offset=0.002,
             epsilon=1.0,
             taps=[np.exp(1j * 30 / 180 * np.pi)],
             noise_seed=243,
             block_tags=False)
         self.blocks_vector_source_x_0 = blocks.vector_source_b(testvec * 500, True, 1, [])
         self.blocks_throttle_0 = blocks.throttle(gr.sizeof_gr_complex*1, samp_rate,True)
-        self.blocks_stream_mux_0 = blocks.stream_mux(gr.sizeof_char*1, [5, len(testvec)])
+        self.blocks_tagged_stream_align_0 = blocks.tagged_stream_align(gr.sizeof_char*1, 'frame_start')
+        self.blocks_stream_mux_0 = blocks.stream_mux(gr.sizeof_char*1, [0, len(testvec)])
         self.blocks_repack_bits_bb_0 = blocks.repack_bits_bb(2, 8, "", False, gr.GR_MSB_FIRST)
         self.blocks_null_source_0 = blocks.null_source(gr.sizeof_char*1)
         self.blocks_null_sink_3 = blocks.null_sink(gr.sizeof_float*1)
@@ -367,14 +369,15 @@ class correlator(gr.top_block, Qt.QWidget):
         self.connect((self.blocks_complex_to_magphase_0_0, 1), (self.blocks_null_sink_3, 0))
         self.connect((self.blocks_complex_to_magphase_0_0, 0), (self.qtgui_time_sink_x_0_0, 0))
         self.connect((self.blocks_null_source_0, 0), (self.blocks_stream_mux_0, 0))
-        self.connect((self.blocks_repack_bits_bb_0, 0), (self.epy_block_1, 0))
+        self.connect((self.blocks_repack_bits_bb_0, 0), (self.blocks_tagged_stream_align_0, 0))
         self.connect((self.blocks_stream_mux_0, 0), (self.digital_constellation_modulator_0, 0))
+        self.connect((self.blocks_tagged_stream_align_0, 0), (self.epy_block_1, 0))
         self.connect((self.blocks_throttle_0, 0), (self.digital_pfb_clock_sync_xxx_0, 0))
         self.connect((self.blocks_vector_source_x_0, 0), (self.blocks_stream_mux_0, 1))
         self.connect((self.channels_channel_model_0, 0), (self.blocks_throttle_0, 0))
         self.connect((self.digital_cma_equalizer_cc_0, 0), (self.digital_corr_est_cc_0, 0))
         self.connect((self.digital_cma_equalizer_cc_0, 0), (self.qtgui_const_sink_x_0, 0))
-        self.connect((self.digital_constellation_decoder_cb_0, 0), (self.blocks_repack_bits_bb_0, 0))
+        self.connect((self.digital_constellation_decoder_cb_0, 0), (self.digital_map_bb_0, 0))
         self.connect((self.digital_constellation_modulator_0, 0), (self.channels_channel_model_0, 0))
         self.connect((self.digital_constellation_modulator_0, 0), (self.qtgui_time_sink_x_1_0, 0))
         self.connect((self.digital_corr_est_cc_0, 1), (self.blocks_complex_to_magphase_0_0, 0))
@@ -382,6 +385,7 @@ class correlator(gr.top_block, Qt.QWidget):
         self.connect((self.digital_corr_est_cc_0, 0), (self.epy_block_0, 0))
         self.connect((self.digital_corr_est_cc_0, 0), (self.qtgui_time_sink_x_0_0_0, 0))
         self.connect((self.digital_costas_loop_cc_0, 0), (self.qtgui_const_sink_x_0_0, 1))
+        self.connect((self.digital_map_bb_0, 0), (self.blocks_repack_bits_bb_0, 0))
         self.connect((self.digital_pfb_clock_sync_xxx_0, 0), (self.digital_cma_equalizer_cc_0, 0))
         self.connect((self.epy_block_0, 0), (self.digital_constellation_decoder_cb_0, 0))
         self.connect((self.epy_block_0, 0), (self.qtgui_const_sink_x_0_0, 0))
@@ -463,6 +467,7 @@ class correlator(gr.top_block, Qt.QWidget):
 
     def set_access_code_symbols(self, access_code_symbols):
         self.access_code_symbols = access_code_symbols
+        self.digital_corr_est_cc_0.set_mark_delay(len(self.access_code_symbols) // 2)
 
 
 
diff --git a/tests/correlator/epy_block_0.py b/tests/correlator/epy_block_0.py
index ddae02a..dbdadd1 100644
--- a/tests/correlator/epy_block_0.py
+++ b/tests/correlator/epy_block_0.py
@@ -5,6 +5,12 @@ from gnuradio import gr
 
 
 class blk(gr.sync_block):
+    """
+    Apply phase and frequency correction where there is a correlation peak tag.
+
+    The correlation peak tags are NOT propagated, and instead replaced with a
+    frame_start tag.
+    """
     def __init__(self):
         gr.sync_block.__init__(
             self,
@@ -22,7 +28,17 @@ class blk(gr.sync_block):
         self.lastfreq = 0
 
     def block_phase(self, start, end):
-        # compute number of samples in block
+        """
+        Compute a vector for the phase and frequency correction for the samples
+        between two tags (start and end).
+
+        @param start Tag where the samples should start to be corrected
+        @param end   Tag where to stop correcting
+
+        @return A vector of phase values for each sample. To correct the samples
+                the data should be multiplied with np.exp(-1j * phase)
+        """
+        # compute number of samples between tags
         nsamples = end.offset - start.offset
 
         # unpack pmt values into start and end phase
@@ -44,10 +60,10 @@ class blk(gr.sync_block):
         self.lastfreq = freq
 
         # debugging
-        print(f"Correction for block of {nsamples:2d} samples is " \
+        print(f"Correction for chunk of {nsamples:2d} samples is " \
               f"sphase={sphase: .4f} rad and freq={freq*1e3: .4f} milli rad / sample")
 
-        # compute block values
+        # compute chunk values
         return sphase * np.ones(nsamples) + freq * np.arange(0, nsamples)
 
     def work(self, input_items, output_items):
@@ -73,11 +89,11 @@ class blk(gr.sync_block):
         # compute "the middle"
         enough_samples = lambda pair: ((pair[1].offset - pair[0].offset) > 0)
         pairs = list(filter(enough_samples, zip(tags, tags[1:])))
-        blocks = [ self.block_phase(start, end) for (start, end) in pairs ]
-        middle = np.concatenate(blocks) if blocks else []
+        chunks = [ self.block_phase(start, end) for (start, end) in pairs ]
+        middle = np.concatenate(chunks) if chunks else []
 
         # compute values at the end, we do not have informations about the future
-        # but we can use the frequency of the last block to approximate
+        # but we can use the frequency of the last tag to approximate
         nback = len(inp) - (tags[-1].offset - counter)
         print(f"Processing {nback} samples at the back of the buffer")
         end = np.ones(nback) * pmt.to_python(tags[-1].value) \
@@ -99,6 +115,10 @@ class blk(gr.sync_block):
         # save last tag for next call
         self.last = tags[-1]
 
+        # add tags
+        for tag in tags:
+            self.add_item_tag(0, tag.offset, pmt.intern("frame_start"), pmt.PMT_T)
+
         # FIXME: should return `length' but then the last sample is not
         #        included and self.last does something weird
         return len(out)
-- 
cgit v1.2.1


From b39b8351476679e2f89cefade40a1eca2566067f Mon Sep 17 00:00:00 2001
From: sara <sara.halter@gmx.ch>
Date: Sat, 4 Dec 2021 15:24:53 +0100
Subject: GNUR Radio Test Sockets

---
 tests/sockets/Socket_test.grc       | 140 ++++++++++++++++++++++++++++++++++++
 tests/sockets/Test_Bit_Errorrate.py | 139 +++++++++++++++++++++++++++++++++++
 2 files changed, 279 insertions(+)
 create mode 100644 tests/sockets/Socket_test.grc
 create mode 100755 tests/sockets/Test_Bit_Errorrate.py

(limited to 'tests')

diff --git a/tests/sockets/Socket_test.grc b/tests/sockets/Socket_test.grc
new file mode 100644
index 0000000..41c7f0a
--- /dev/null
+++ b/tests/sockets/Socket_test.grc
@@ -0,0 +1,140 @@
+options:
+  parameters:
+    author: 'Sara Halter '
+    category: '[GRC Hier Blocks]'
+    cmake_opt: ''
+    comment: ''
+    copyright: ''
+    description: ''
+    gen_cmake: 'On'
+    gen_linking: dynamic
+    generate_options: qt_gui
+    hier_block_src_path: '.:'
+    id: Test_Bit_Errorrate
+    max_nouts: '0'
+    output_language: python
+    placement: (0,0)
+    qt_qss_theme: ''
+    realtime_scheduling: ''
+    run: 'True'
+    run_command: '{python} -u {filename}'
+    run_options: prompt
+    sizing_mode: fixed
+    thread_safe_setters: ''
+    title: 'Bit Error Rate test '
+    window_size: ''
+  states:
+    bus_sink: false
+    bus_source: false
+    bus_structure: null
+    coordinate: [8, 8]
+    rotation: 0
+    state: enabled
+
+blocks:
+- name: samp_rate
+  id: variable
+  parameters:
+    comment: ''
+    value: '32000'
+  states:
+    bus_sink: false
+    bus_source: false
+    bus_structure: null
+    coordinate: [184, 12]
+    rotation: 0
+    state: enabled
+- name: analog_noise_source_x_0
+  id: analog_noise_source_x
+  parameters:
+    affinity: ''
+    alias: ''
+    amp: '1'
+    comment: ''
+    maxoutbuf: '0'
+    minoutbuf: '0'
+    noise_type: analog.GR_GAUSSIAN
+    seed: '0'
+    type: float
+  states:
+    bus_sink: false
+    bus_source: false
+    bus_structure: null
+    coordinate: [528, 108.0]
+    rotation: 0
+    state: disabled
+- name: blocks_null_source_0
+  id: blocks_null_source
+  parameters:
+    affinity: ''
+    alias: ''
+    bus_structure_source: '[[0,],]'
+    comment: ''
+    maxoutbuf: '0'
+    minoutbuf: '0'
+    num_outputs: '1'
+    type: byte
+    vlen: '1'
+  states:
+    bus_sink: false
+    bus_source: false
+    bus_structure: null
+    coordinate: [552, 224.0]
+    rotation: 0
+    state: true
+- name: blocks_throttle_1
+  id: blocks_throttle
+  parameters:
+    affinity: ''
+    alias: ''
+    comment: ''
+    ignoretag: 'True'
+    maxoutbuf: '0'
+    minoutbuf: '0'
+    samples_per_second: samp_rate
+    type: byte
+    vlen: '1'
+  states:
+    bus_sink: false
+    bus_source: false
+    bus_structure: null
+    coordinate: [800, 156.0]
+    rotation: 0
+    state: true
+- name: fadingui_netsink_0
+  id: fadingui_netsink
+  parameters:
+    address: udp://localhost:31415
+    affinity: ''
+    alias: ''
+    comment: ''
+    type: byte
+    veclen: '1'
+  states:
+    bus_sink: false
+    bus_source: false
+    bus_structure: null
+    coordinate: [1016, 156.0]
+    rotation: 0
+    state: true
+- name: import_0
+  id: import
+  parameters:
+    alias: ''
+    comment: ''
+    imports: import numpy as np
+  states:
+    bus_sink: false
+    bus_source: false
+    bus_structure: null
+    coordinate: [328, 20.0]
+    rotation: 0
+    state: true
+
+connections:
+- [analog_noise_source_x_0, '0', blocks_throttle_1, '0']
+- [blocks_null_source_0, '0', blocks_throttle_1, '0']
+- [blocks_throttle_1, '0', fadingui_netsink_0, '0']
+
+metadata:
+  file_format: 1
diff --git a/tests/sockets/Test_Bit_Errorrate.py b/tests/sockets/Test_Bit_Errorrate.py
new file mode 100755
index 0000000..b545104
--- /dev/null
+++ b/tests/sockets/Test_Bit_Errorrate.py
@@ -0,0 +1,139 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+
+#
+# SPDX-License-Identifier: GPL-3.0
+#
+# GNU Radio Python Flow Graph
+# Title: Bit Error Rate test
+# Author: Sara Halter
+# 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 gnuradio import blocks
+from gnuradio import gr
+from gnuradio.filter import firdes
+import sys
+import signal
+from PyQt5 import Qt
+from argparse import ArgumentParser
+from gnuradio.eng_arg import eng_float, intx
+from gnuradio import eng_notation
+import fadingui
+import numpy as np
+
+from gnuradio import qtgui
+
+class Test_Bit_Errorrate(gr.top_block, Qt.QWidget):
+
+    def __init__(self):
+        gr.top_block.__init__(self, "Bit Error Rate test ")
+        Qt.QWidget.__init__(self)
+        self.setWindowTitle("Bit Error Rate test ")
+        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", "Test_Bit_Errorrate")
+
+        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.samp_rate = samp_rate = 32000
+
+        ##################################################
+        # Blocks
+        ##################################################
+        self.fadingui_netsink_0 = fadingui.netsink(address='udp://localhost:31415', dtype="byte", vlen=1)
+        self.blocks_throttle_1 = blocks.throttle(gr.sizeof_char*1, samp_rate,True)
+        self.blocks_null_source_0 = blocks.null_source(gr.sizeof_char*1)
+
+
+
+        ##################################################
+        # Connections
+        ##################################################
+        self.connect((self.blocks_null_source_0, 0), (self.blocks_throttle_1, 0))
+        self.connect((self.blocks_throttle_1, 0), (self.fadingui_netsink_0, 0))
+
+
+    def closeEvent(self, event):
+        self.settings = Qt.QSettings("GNU Radio", "Test_Bit_Errorrate")
+        self.settings.setValue("geometry", self.saveGeometry())
+        event.accept()
+
+    def get_samp_rate(self):
+        return self.samp_rate
+
+    def set_samp_rate(self, samp_rate):
+        self.samp_rate = samp_rate
+        self.blocks_throttle_1.set_sample_rate(self.samp_rate)
+
+
+
+
+
+def main(top_block_cls=Test_Bit_Errorrate, options=None):
+
+    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()
-- 
cgit v1.2.1


From 30012258948049da894e260d78551d1de44c2f50 Mon Sep 17 00:00:00 2001
From: Nao Pross <np@0hm.ch>
Date: Sat, 4 Dec 2021 16:46:23 +0100
Subject: Update net.py to decode UDP data stream

---
 tests/sockets/Socket_test.grc       | 24 +++++------
 tests/sockets/Test_Bit_Errorrate.py | 83 ++++++-------------------------------
 2 files changed, 24 insertions(+), 83 deletions(-)

(limited to 'tests')

diff --git a/tests/sockets/Socket_test.grc b/tests/sockets/Socket_test.grc
index 41c7f0a..fbc3cdf 100644
--- a/tests/sockets/Socket_test.grc
+++ b/tests/sockets/Socket_test.grc
@@ -8,7 +8,7 @@ options:
     description: ''
     gen_cmake: 'On'
     gen_linking: dynamic
-    generate_options: qt_gui
+    generate_options: no_gui
     hier_block_src_path: '.:'
     id: Test_Bit_Errorrate
     max_nouts: '0'
@@ -18,7 +18,7 @@ options:
     realtime_scheduling: ''
     run: 'True'
     run_command: '{python} -u {filename}'
-    run_options: prompt
+    run_options: run
     sizing_mode: fixed
     thread_safe_setters: ''
     title: 'Bit Error Rate test '
@@ -41,7 +41,7 @@ blocks:
     bus_sink: false
     bus_source: false
     bus_structure: null
-    coordinate: [184, 12]
+    coordinate: [216, 20.0]
     rotation: 0
     state: enabled
 - name: analog_noise_source_x_0
@@ -60,9 +60,9 @@ blocks:
     bus_sink: false
     bus_source: false
     bus_structure: null
-    coordinate: [528, 108.0]
+    coordinate: [32, 148.0]
     rotation: 0
-    state: disabled
+    state: enabled
 - name: blocks_null_source_0
   id: blocks_null_source
   parameters:
@@ -73,15 +73,15 @@ blocks:
     maxoutbuf: '0'
     minoutbuf: '0'
     num_outputs: '1'
-    type: byte
+    type: complex
     vlen: '1'
   states:
     bus_sink: false
     bus_source: false
     bus_structure: null
-    coordinate: [552, 224.0]
+    coordinate: [64, 264.0]
     rotation: 0
-    state: true
+    state: disabled
 - name: blocks_throttle_1
   id: blocks_throttle
   parameters:
@@ -92,13 +92,13 @@ blocks:
     maxoutbuf: '0'
     minoutbuf: '0'
     samples_per_second: samp_rate
-    type: byte
+    type: float
     vlen: '1'
   states:
     bus_sink: false
     bus_source: false
     bus_structure: null
-    coordinate: [800, 156.0]
+    coordinate: [280, 164.0]
     rotation: 0
     state: true
 - name: fadingui_netsink_0
@@ -108,13 +108,13 @@ blocks:
     affinity: ''
     alias: ''
     comment: ''
-    type: byte
+    type: float
     veclen: '1'
   states:
     bus_sink: false
     bus_source: false
     bus_structure: null
-    coordinate: [1016, 156.0]
+    coordinate: [504, 164.0]
     rotation: 0
     state: true
 - name: import_0
diff --git a/tests/sockets/Test_Bit_Errorrate.py b/tests/sockets/Test_Bit_Errorrate.py
index b545104..6a989df 100755
--- a/tests/sockets/Test_Bit_Errorrate.py
+++ b/tests/sockets/Test_Bit_Errorrate.py
@@ -9,64 +9,23 @@
 # Author: Sara Halter
 # 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 gnuradio import analog
 from gnuradio import blocks
 from gnuradio import gr
 from gnuradio.filter import firdes
 import sys
 import signal
-from PyQt5 import Qt
 from argparse import ArgumentParser
 from gnuradio.eng_arg import eng_float, intx
 from gnuradio import eng_notation
 import fadingui
 import numpy as np
 
-from gnuradio import qtgui
 
-class Test_Bit_Errorrate(gr.top_block, Qt.QWidget):
+class Test_Bit_Errorrate(gr.top_block):
 
     def __init__(self):
         gr.top_block.__init__(self, "Bit Error Rate test ")
-        Qt.QWidget.__init__(self)
-        self.setWindowTitle("Bit Error Rate test ")
-        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", "Test_Bit_Errorrate")
-
-        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
@@ -76,24 +35,19 @@ class Test_Bit_Errorrate(gr.top_block, Qt.QWidget):
         ##################################################
         # Blocks
         ##################################################
-        self.fadingui_netsink_0 = fadingui.netsink(address='udp://localhost:31415', dtype="byte", vlen=1)
-        self.blocks_throttle_1 = blocks.throttle(gr.sizeof_char*1, samp_rate,True)
-        self.blocks_null_source_0 = blocks.null_source(gr.sizeof_char*1)
+        self.fadingui_netsink_0 = fadingui.netsink(address='udp://localhost:31415', dtype="float", vlen=1)
+        self.blocks_throttle_1 = blocks.throttle(gr.sizeof_float*1, samp_rate,True)
+        self.analog_noise_source_x_0 = analog.noise_source_f(analog.GR_GAUSSIAN, 1, 0)
 
 
 
         ##################################################
         # Connections
         ##################################################
-        self.connect((self.blocks_null_source_0, 0), (self.blocks_throttle_1, 0))
+        self.connect((self.analog_noise_source_x_0, 0), (self.blocks_throttle_1, 0))
         self.connect((self.blocks_throttle_1, 0), (self.fadingui_netsink_0, 0))
 
 
-    def closeEvent(self, event):
-        self.settings = Qt.QSettings("GNU Radio", "Test_Bit_Errorrate")
-        self.settings.setValue("geometry", self.saveGeometry())
-        event.accept()
-
     def get_samp_rate(self):
         return self.samp_rate
 
@@ -106,34 +60,21 @@ class Test_Bit_Errorrate(gr.top_block, Qt.QWidget):
 
 
 def main(top_block_cls=Test_Bit_Errorrate, options=None):
-
-    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()
+        tb.stop()
+        tb.wait()
+
+        sys.exit(0)
 
     signal.signal(signal.SIGINT, sig_handler)
     signal.signal(signal.SIGTERM, sig_handler)
 
-    timer = Qt.QTimer()
-    timer.start(500)
-    timer.timeout.connect(lambda: None)
+    tb.start()
 
-    def quitting():
-        tb.stop()
-        tb.wait()
+    tb.wait()
 
-    qapp.aboutToQuit.connect(quitting)
-    qapp.exec_()
 
 if __name__ == '__main__':
     main()
-- 
cgit v1.2.1