aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--tests/correlator/correlator.grc424
-rwxr-xr-xtests/correlator/correlator.py274
-rw-r--r--tests/correlator/epy_block_0.py75
3 files changed, 234 insertions, 539 deletions
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)