From 8e6e1d62ef9beb978879bfd156b3ff51940c8725 Mon Sep 17 00:00:00 2001 From: Nao Pross 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