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/correlator')

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