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 From a396c568457bc4e36eac820c209d133e9a7b0b2d Mon Sep 17 00:00:00 2001 From: Nao Pross Date: Thu, 2 Dec 2021 12:52:34 +0100 Subject: Delete ZMQ tests --- tests/zmq/lena512color.tiff | Bin 786572 -> 0 bytes tests/zmq/server.py | 4 -- tests/zmq/zmqtest.grc | 112 -------------------------------------------- tests/zmq/zmqtest.py | 85 --------------------------------- 4 files changed, 201 deletions(-) delete mode 100644 tests/zmq/lena512color.tiff delete mode 100644 tests/zmq/server.py delete mode 100644 tests/zmq/zmqtest.grc delete mode 100755 tests/zmq/zmqtest.py (limited to 'tests') diff --git a/tests/zmq/lena512color.tiff b/tests/zmq/lena512color.tiff deleted file mode 100644 index ffe5c83..0000000 Binary files a/tests/zmq/lena512color.tiff and /dev/null differ diff --git a/tests/zmq/server.py b/tests/zmq/server.py deleted file mode 100644 index be4bede..0000000 --- a/tests/zmq/server.py +++ /dev/null @@ -1,4 +0,0 @@ -import zmq -import pmt - -import numpy as np diff --git a/tests/zmq/zmqtest.grc b/tests/zmq/zmqtest.grc deleted file mode 100644 index ad1729d..0000000 --- a/tests/zmq/zmqtest.grc +++ /dev/null @@ -1,112 +0,0 @@ -options: - parameters: - author: Naoki Pross - category: '[GRC Hier Blocks]' - cmake_opt: '' - comment: '' - copyright: '' - description: '' - gen_cmake: 'On' - gen_linking: dynamic - generate_options: no_gui - hier_block_src_path: '.:' - id: zmqtest - max_nouts: '0' - output_language: python - placement: (0,0) - qt_qss_theme: '' - realtime_scheduling: '1' - run: 'True' - run_command: '{python} -u {filename}' - run_options: prompt - sizing_mode: fixed - thread_safe_setters: '' - title: ZMQ test - window_size: '' - states: - bus_sink: false - bus_source: false - bus_structure: null - coordinate: [8, 8] - rotation: 0 - state: enabled - -blocks: -- name: samp_rate - id: variable - parameters: - comment: '' - value: '32000' - states: - bus_sink: false - bus_source: false - bus_structure: null - coordinate: [184, 12] - rotation: 0 - state: enabled -- name: blocks_throttle_0 - id: blocks_throttle - parameters: - affinity: '' - alias: '' - comment: '' - ignoretag: 'True' - maxoutbuf: '0' - minoutbuf: '0' - samples_per_second: samp_rate - type: complex - vlen: '1' - states: - bus_sink: false - bus_source: false - bus_structure: null - coordinate: [440, 324.0] - rotation: 0 - state: true -- name: zeromq_rep_sink_0 - id: zeromq_rep_sink - parameters: - address: '' - affinity: '' - alias: '' - comment: '' - hwm: '-1' - pass_tags: 'False' - timeout: '100' - type: complex - vlen: '1' - states: - bus_sink: false - bus_source: false - bus_structure: null - coordinate: [664, 308.0] - rotation: 0 - state: true -- name: zeromq_req_source_0 - id: zeromq_req_source - parameters: - address: '' - affinity: '' - alias: '' - comment: '' - hwm: '-1' - maxoutbuf: '0' - minoutbuf: '0' - pass_tags: 'False' - timeout: '100' - type: complex - vlen: '1' - states: - bus_sink: false - bus_source: false - bus_structure: null - coordinate: [216, 308.0] - rotation: 0 - state: true - -connections: -- [blocks_throttle_0, '0', zeromq_rep_sink_0, '0'] -- [zeromq_req_source_0, '0', blocks_throttle_0, '0'] - -metadata: - file_format: 1 diff --git a/tests/zmq/zmqtest.py b/tests/zmq/zmqtest.py deleted file mode 100755 index a046c13..0000000 --- a/tests/zmq/zmqtest.py +++ /dev/null @@ -1,85 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- - -# -# SPDX-License-Identifier: GPL-3.0 -# -# GNU Radio Python Flow Graph -# Title: ZMQ test -# Author: Naoki Pross -# GNU Radio version: 3.8.2.0 - -from gnuradio import blocks -from gnuradio import gr -from gnuradio.filter import firdes -import sys -import signal -from argparse import ArgumentParser -from gnuradio.eng_arg import eng_float, intx -from gnuradio import eng_notation -from gnuradio import zeromq - - -class zmqtest(gr.top_block): - - def __init__(self): - gr.top_block.__init__(self, "ZMQ test") - - ################################################## - # Variables - ################################################## - self.samp_rate = samp_rate = 32000 - - ################################################## - # Blocks - ################################################## - self.zeromq_req_source_0 = zeromq.req_source(gr.sizeof_gr_complex, 1, '', 100, False, -1) - self.zeromq_rep_sink_0 = zeromq.rep_sink(gr.sizeof_gr_complex, 1, '', 100, False, -1) - self.blocks_throttle_0 = blocks.throttle(gr.sizeof_gr_complex*1, samp_rate,True) - - - - ################################################## - # Connections - ################################################## - self.connect((self.blocks_throttle_0, 0), (self.zeromq_rep_sink_0, 0)) - self.connect((self.zeromq_req_source_0, 0), (self.blocks_throttle_0, 0)) - - - def get_samp_rate(self): - return self.samp_rate - - def set_samp_rate(self, samp_rate): - self.samp_rate = samp_rate - self.blocks_throttle_0.set_sample_rate(self.samp_rate) - - - - - -def main(top_block_cls=zmqtest, options=None): - if gr.enable_realtime_scheduling() != gr.RT_OK: - print("Error: failed to enable real-time scheduling.") - tb = top_block_cls() - - def sig_handler(sig=None, frame=None): - tb.stop() - tb.wait() - - sys.exit(0) - - signal.signal(signal.SIGINT, sig_handler) - signal.signal(signal.SIGTERM, sig_handler) - - tb.start() - - try: - input('Press Enter to quit: ') - except EOFError: - pass - tb.stop() - tb.wait() - - -if __name__ == '__main__': - main() -- cgit v1.2.1 From 834febb9aa0dac463f43914cb028be931f85de73 Mon Sep 17 00:00:00 2001 From: sara Date: Thu, 2 Dec 2021 20:02:16 +0100 Subject: =?UTF-8?q?BER=20Block=20erstellt,=20l=C3=A4uft=20noch=20nichtwie?= =?UTF-8?q?=20gew=C3=BCnscht?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tests/BER/Bit_error.grc | 98 +++++++++++++++++++++++++++ tests/BER/Test_Bit_Errorrate.py | 143 ++++++++++++++++++++++++++++++++++++++++ tests/correlator/correlator.py | 5 +- 3 files changed, 245 insertions(+), 1 deletion(-) create mode 100644 tests/BER/Bit_error.grc create mode 100755 tests/BER/Test_Bit_Errorrate.py (limited to 'tests') diff --git a/tests/BER/Bit_error.grc b/tests/BER/Bit_error.grc new file mode 100644 index 0000000..04c624b --- /dev/null +++ b/tests/BER/Bit_error.grc @@ -0,0 +1,98 @@ +options: + parameters: + author: 'Sara Halter ' + category: '[GRC Hier Blocks]' + cmake_opt: '' + comment: '' + copyright: '' + description: '' + gen_cmake: 'On' + gen_linking: dynamic + generate_options: qt_gui + hier_block_src_path: '.:' + id: Test_Bit_Errorrate + max_nouts: '0' + output_language: python + placement: (0,0) + qt_qss_theme: '' + realtime_scheduling: '' + run: 'True' + run_command: '{python} -u {filename}' + run_options: prompt + sizing_mode: fixed + thread_safe_setters: '' + title: 'Bit Error Rate test ' + window_size: '' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [8, 8] + rotation: 0 + state: enabled + +blocks: +- name: samp_rate + id: variable + parameters: + comment: '' + value: '32000' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [184, 12] + rotation: 0 + state: enabled +- name: testvec + id: variable + parameters: + comment: '' + value: '[31, 53] + [0x12, 0xe3, 0x9b, 0xee, 0x84, 0x23, 0x41, 0xf3]' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [216, 396.0] + rotation: 0 + state: enabled +- name: blocks_vector_source_x_0 + id: blocks_vector_source_x + parameters: + affinity: '' + alias: '' + comment: '' + maxoutbuf: '0' + minoutbuf: '0' + repeat: 'True' + tags: '[]' + type: byte + vector: testvec * 1600 + vlen: '1' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [216, 276.0] + rotation: 0 + state: enabled +- name: fadingui_ber_0 + id: fadingui_ber + parameters: + affinity: '' + alias: '' + comment: '' + vgl: testvec + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [704, 296.0] + rotation: 0 + state: true + +connections: +- [blocks_vector_source_x_0, '0', fadingui_ber_0, '0'] + +metadata: + file_format: 1 diff --git a/tests/BER/Test_Bit_Errorrate.py b/tests/BER/Test_Bit_Errorrate.py new file mode 100755 index 0000000..4022997 --- /dev/null +++ b/tests/BER/Test_Bit_Errorrate.py @@ -0,0 +1,143 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +# +# SPDX-License-Identifier: GPL-3.0 +# +# GNU Radio Python Flow Graph +# Title: Bit Error Rate test +# Author: Sara Halter +# GNU Radio version: 3.8.2.0 + +from distutils.version import StrictVersion + +if __name__ == '__main__': + import ctypes + import sys + if sys.platform.startswith('linux'): + try: + x11 = ctypes.cdll.LoadLibrary('libX11.so') + x11.XInitThreads() + except: + print("Warning: failed to XInitThreads()") + +from gnuradio import blocks +from gnuradio import gr +from gnuradio.filter import firdes +import sys +import signal +from PyQt5 import Qt +from argparse import ArgumentParser +from gnuradio.eng_arg import eng_float, intx +from gnuradio import eng_notation +import fadingui + +from gnuradio import qtgui + +class Test_Bit_Errorrate(gr.top_block, Qt.QWidget): + + def __init__(self): + gr.top_block.__init__(self, "Bit Error Rate test ") + Qt.QWidget.__init__(self) + self.setWindowTitle("Bit Error Rate test ") + qtgui.util.check_set_qss() + try: + self.setWindowIcon(Qt.QIcon.fromTheme('gnuradio-grc')) + except: + pass + self.top_scroll_layout = Qt.QVBoxLayout() + self.setLayout(self.top_scroll_layout) + self.top_scroll = Qt.QScrollArea() + self.top_scroll.setFrameStyle(Qt.QFrame.NoFrame) + self.top_scroll_layout.addWidget(self.top_scroll) + self.top_scroll.setWidgetResizable(True) + self.top_widget = Qt.QWidget() + self.top_scroll.setWidget(self.top_widget) + self.top_layout = Qt.QVBoxLayout(self.top_widget) + self.top_grid_layout = Qt.QGridLayout() + self.top_layout.addLayout(self.top_grid_layout) + + self.settings = Qt.QSettings("GNU Radio", "Test_Bit_Errorrate") + + try: + if StrictVersion(Qt.qVersion()) < StrictVersion("5.0.0"): + self.restoreGeometry(self.settings.value("geometry").toByteArray()) + else: + self.restoreGeometry(self.settings.value("geometry")) + except: + pass + + ################################################## + # Variables + ################################################## + self.testvec = testvec = [31, 53] + [0x12, 0xe3, 0x9b, 0xee, 0x84, 0x23, 0x41, 0xf3] + self.samp_rate = samp_rate = 32000 + + ################################################## + # Blocks + ################################################## + self.fadingui_ber_0 = fadingui.ber(vgl=testvec) + self.blocks_vector_source_x_0 = blocks.vector_source_b(testvec * 1600, True, 1, []) + + + + ################################################## + # Connections + ################################################## + self.connect((self.blocks_vector_source_x_0, 0), (self.fadingui_ber_0, 0)) + + + def closeEvent(self, event): + self.settings = Qt.QSettings("GNU Radio", "Test_Bit_Errorrate") + self.settings.setValue("geometry", self.saveGeometry()) + event.accept() + + def get_testvec(self): + return self.testvec + + def set_testvec(self, testvec): + self.testvec = testvec + self.blocks_vector_source_x_0.set_data(self.testvec * 1600, []) + + def get_samp_rate(self): + return self.samp_rate + + def set_samp_rate(self, samp_rate): + self.samp_rate = samp_rate + + + + + +def main(top_block_cls=Test_Bit_Errorrate, options=None): + + if StrictVersion("4.5.0") <= StrictVersion(Qt.qVersion()) < StrictVersion("5.0.0"): + style = gr.prefs().get_string('qtgui', 'style', 'raster') + Qt.QApplication.setGraphicsSystem(style) + qapp = Qt.QApplication(sys.argv) + + tb = top_block_cls() + + tb.start() + + tb.show() + + def sig_handler(sig=None, frame=None): + Qt.QApplication.quit() + + signal.signal(signal.SIGINT, sig_handler) + signal.signal(signal.SIGTERM, sig_handler) + + timer = Qt.QTimer() + timer.start(500) + timer.timeout.connect(lambda: None) + + def quitting(): + tb.stop() + tb.wait() + + qapp.aboutToQuit.connect(quitting) + qapp.exec_() + +if __name__ == '__main__': + main() diff --git a/tests/correlator/correlator.py b/tests/correlator/correlator.py index a870cc0..67def9f 100755 --- a/tests/correlator/correlator.py +++ b/tests/correlator/correlator.py @@ -35,6 +35,7 @@ from argparse import ArgumentParser from gnuradio.eng_arg import eng_float, intx from gnuradio import eng_notation import epy_block_0 +import fadingui from gnuradio import qtgui @@ -328,6 +329,7 @@ class correlator(gr.top_block, Qt.QWidget): self.top_grid_layout.setRowStretch(r, 1) for c in range(1, 2): self.top_grid_layout.setColumnStretch(c, 1) + self.fadingui_deframer_0 = fadingui.deframer(frame_obj=) self.epy_block_0 = epy_block_0.blk() self.digital_pfb_clock_sync_xxx_0 = digital.pfb_clock_sync_ccf(sps, timing_loop_bw, rrc_taps, nfilts, 16, 1.5, 1) self.digital_corr_est_cc_0 = digital.corr_est_cc(access_code_symbols, 1, 0, .8, digital.THRESHOLD_DYNAMIC) @@ -370,7 +372,7 @@ class correlator(gr.top_block, Qt.QWidget): self.connect((self.channels_channel_model_0, 0), (self.blocks_throttle_0, 0)) self.connect((self.digital_cma_equalizer_cc_0, 0), (self.digital_corr_est_cc_0, 0)) self.connect((self.digital_cma_equalizer_cc_0, 0), (self.qtgui_const_sink_x_0, 0)) - self.connect((self.digital_constellation_decoder_cb_0, 0), (self.blocks_vector_sink_x_0, 0)) + self.connect((self.digital_constellation_decoder_cb_0, 0), (self.fadingui_deframer_0, 0)) self.connect((self.digital_constellation_modulator_0, 0), (self.channels_channel_model_0, 0)) self.connect((self.digital_constellation_modulator_0, 0), (self.qtgui_time_sink_x_1_0, 0)) self.connect((self.digital_corr_est_cc_0, 1), (self.blocks_complex_to_magphase_0_0, 0)) @@ -379,6 +381,7 @@ class correlator(gr.top_block, Qt.QWidget): self.connect((self.digital_pfb_clock_sync_xxx_0, 0), (self.digital_cma_equalizer_cc_0, 0)) self.connect((self.epy_block_0, 0), (self.digital_constellation_decoder_cb_0, 0)) self.connect((self.epy_block_0, 0), (self.qtgui_const_sink_x_0_0, 0)) + self.connect((self.fadingui_deframer_0, 0), (self.blocks_vector_sink_x_0, 0)) def closeEvent(self, event): -- cgit v1.2.1 From de7b4dac4af5ff592258f48eee72d191201826d7 Mon Sep 17 00:00:00 2001 From: Nao Pross Date: Thu, 2 Dec 2021 21:24:33 +0100 Subject: Begin frequency correction (incomplete) --- tests/correlator/correlator.grc | 65 +++++++++++++++++++++-------------- tests/correlator/correlator.py | 3 +- tests/correlator/epy_block_0.py | 75 +++++++++++++++++++++++++++-------------- 3 files changed, 92 insertions(+), 51 deletions(-) (limited to 'tests') diff --git a/tests/correlator/correlator.grc b/tests/correlator/correlator.grc index aa21770..58cf3b4 100644 --- a/tests/correlator/correlator.grc +++ b/tests/correlator/correlator.grc @@ -408,7 +408,7 @@ blocks: block_tags: 'False' comment: '' epsilon: '1.0' - freq_offset: '0.00001' + freq_offset: '0.0001' maxoutbuf: '0' minoutbuf: '0' noise_voltage: '0.2' @@ -530,30 +530,45 @@ blocks: \ many samples were processed,\n # because tags have an absolute offset\n\ \ self.sampnr: np.complex64 = 0\n\n # because of block processing\ \ a tagged block could\n # be split in half so we need to keep track\ - \ of the\n # \"previous\" values\n self.last_phase = 0\n\n \ - \ def work(self, input_items, output_items):\n # TODO: interpolate phase\ - \ values for frequency correction\n\n out = output_items[0]\n \ - \ inp = input_items[0]\n\n # create a phase correction vector\n \ - \ phase = np.zeros(len(inp), dtype=np.float64)\n\n # read tags\n \ - \ tags = self.get_tags_in_window(0, 0, len(inp))\n\n # get only\ - \ phase tags\n is_phase = lambda tag: pmt.to_python(tag.key) == \"phase_est\"\ - \n phase_tags = list(filter(is_phase, tags))\n\n print(f\"Processing\ - \ {len(inp)} samples, with {len(phase_tags)} tags\")\n\n # compute correction\ - \ from previous block\n first_tag = phase_tags[0]\n first_idx\ - \ = first_tag.offset - self.sampnr\n phase[:first_idx] = self.last_phase\n\ - \n # iterate phase tags \"in the middle\"\n for prev_tag, next_tag\ - \ in zip(phase_tags, phase_tags[1:]):\n # unpack pmt values\n \ - \ pval = pmt.to_python(prev_tag.value)\n\n # compute indexes\ + \ of the\n # \"previous\" values\n self.last_tag = None\n\n \ + \ def work(self, input_items, output_items):\n # nicer aliases\n \ + \ out = output_items[0]\n inp = input_items[0]\n\n def print_phase_correction(start,\ + \ end, phase, freq):\n print(f\"Correction for block {start:3d} to\ + \ {end:3d} is phase = {phase: 2.4f} rad, freq = {freq * 1e3: 2.4f} milli rad/samp\"\ + )\n\n # read only phase tags\n tags = self.get_tags_in_window(0,\ + \ 0, len(inp))\n\n is_phase = lambda tag: pmt.to_python(tag.key) == \"\ + phase_est\"\n phase_tags = list(filter(is_phase, tags))\n\n #\ + \ FIXME: what if there are no tags? check that!\n\n print(f\"Processing\ + \ {len(inp)} samples, with {len(phase_tags)} tags\")\n\n # create a phase\ + \ correction vector\n phase = np.zeros(len(inp), dtype=np.float64)\n\n\ + \ # compute correction from previous block (if present)\n if self.last_tag:\n\ + \ # variables for first and last phase values\n lval =\ + \ pmt.to_python(self.last_tag.value)\n fval = pmt.to_python(phase_tags[0].value)\n\ + \n # compute index for phase vector\n fidx = phase_tags[0].offset\ + \ - self.sampnr\n\n # compute frequency offset\n nsamples\ + \ = phase_tags[0].offset - self.last_tag.offset\n freq = (fval -\ + \ lval) / nsamples\n\n # total phase correction is: phase + freq\ + \ * time\n phase[:fidx] = lval * np.ones(fidx) + freq * np.arange(0,\ + \ fidx)\n\n # compute correction\n print_phase_correction(0,\ + \ fidx, lval, freq)\n\n # iterate phase tags \"in the middle\"\n \ + \ # FIXME: what if there are less than 2 tags?\n # the code\ + \ below will probably crash\n for prev_tag, next_tag in zip(phase_tags,\ + \ phase_tags[1:]):\n # unpack pmt values\n pval = pmt.to_python(prev_tag.value)\n\ + \ nval = pmt.to_python(next_tag.value)\n\n # compute indexes\ \ in phase vector\n pidx = prev_tag.offset - self.sampnr\n \ - \ idx = next_tag.offset - self.sampnr\n\n # compute phase correction\ - \ for block\n phase[pidx:idx] = pval\n print(f\"Correction\ - \ for block {pidx} to {idx} is {pval}\")\n\n # compute the remaining\ - \ part of the block\n last_tag = phase_tags[-1]\n last_val = pmt.to_python(last_tag.value)\n\ - \ last_idx = last_tag.offset - self.sampnr\n\n phase[last_idx:]\ - \ = last_val\n\n # save values for next call\n self.last_phase\ - \ = last_val\n\n # mark samples as processed and compute to output\n\ - \ self.sampnr += len(inp)\n out[:] = inp * np.exp(-1j * phase)\n\ - \n return len(out)\n" + \ nidx = next_tag.offset - self.sampnr\n\n # compute frquency\ + \ correction for block by linearly interpolating\n # frame values\n\ + \ nsamples = nidx - pidx\n freq = (nval - pval) / nsamples\n\ + \n # total correction is: phase + freq * time\n phase[pidx:nidx]\ + \ = pval * np.ones(nsamples) + freq * np.arange(0, nsamples)\n print_phase_correction(pidx,\ + \ nidx, pval, freq)\n\n # for the last block because the next tag is\ + \ unknown (in the future) we\n # cannot predict the frequency offset.\ + \ Thus we save the last tag for\n # the next call.\n self.last_tag\ + \ = phase_tags[-1]\n val = pmt.to_python(self.last_tag.value)\n \ + \ idx = self.last_tag.offset - self.sampnr\n\n phase[idx:] = val\n\n\ + \ # compute correction\n out[:] = inp * np.exp(-1j * phase)\n\n\ + \ # increment processed samples counter\n self.sampnr += len(inp)\n\ + \ return len(phase)\n" affinity: '' alias: '' comment: '' @@ -583,7 +598,7 @@ blocks: bus_structure: null coordinate: [552, 1388.0] rotation: 0 - state: true + state: bypassed - name: fir_filter_xxx_1 id: fir_filter_xxx parameters: diff --git a/tests/correlator/correlator.py b/tests/correlator/correlator.py index a870cc0..e8eaaa8 100755 --- a/tests/correlator/correlator.py +++ b/tests/correlator/correlator.py @@ -35,6 +35,7 @@ from argparse import ArgumentParser from gnuradio.eng_arg import eng_float, intx from gnuradio import eng_notation import epy_block_0 +import fadingui from gnuradio import qtgui @@ -343,7 +344,7 @@ class correlator(gr.top_block, Qt.QWidget): self.digital_cma_equalizer_cc_0 = digital.cma_equalizer_cc(15, 1, .002, 1) self.channels_channel_model_0 = channels.channel_model( noise_voltage=0.2, - frequency_offset=0.00001, + frequency_offset=0.0001, epsilon=1.0, taps=[-1.4 + .4j], noise_seed=243, diff --git a/tests/correlator/epy_block_0.py b/tests/correlator/epy_block_0.py index 1fa4794..90ad75e 100644 --- a/tests/correlator/epy_block_0.py +++ b/tests/correlator/epy_block_0.py @@ -20,56 +20,81 @@ class blk(gr.sync_block): # because of block processing a tagged block could # be split in half so we need to keep track of the # "previous" values - self.last_phase = 0 + self.last_tag = None def work(self, input_items, output_items): - # TODO: interpolate phase values for frequency correction - + # nicer aliases out = output_items[0] inp = input_items[0] - # create a phase correction vector - phase = np.zeros(len(inp), dtype=np.float64) + def print_phase_correction(start, end, phase, freq): + print(f"Correction for block {start:3d} to {end:3d} is phase = {phase: 2.4f} rad, freq = {freq * 1e3: 2.4f} milli rad/samp") - # read tags + # read only phase tags tags = self.get_tags_in_window(0, 0, len(inp)) - # get only phase tags is_phase = lambda tag: pmt.to_python(tag.key) == "phase_est" phase_tags = list(filter(is_phase, tags)) + # FIXME: what if there are no tags? check that! + print(f"Processing {len(inp)} samples, with {len(phase_tags)} tags") - # compute correction from previous block - first_tag = phase_tags[0] - first_idx = first_tag.offset - self.sampnr - phase[:first_idx] = self.last_phase + # create a phase correction vector + phase = np.zeros(len(inp), dtype=np.float64) + + # compute correction from previous block (if present) + if self.last_tag: + # variables for first and last phase values + lval = pmt.to_python(self.last_tag.value) + fval = pmt.to_python(phase_tags[0].value) + + # compute index for phase vector + fidx = phase_tags[0].offset - self.sampnr + + # compute frequency offset + nsamples = phase_tags[0].offset - self.last_tag.offset + freq = (fval - lval) / nsamples + + # total phase correction is: phase + freq * time + phase[:fidx] = lval * np.ones(fidx) + freq * np.arange(0, fidx) + + # compute correction + print_phase_correction(0, fidx, lval, freq) # iterate phase tags "in the middle" + # FIXME: what if there are less than 2 tags? + # the code below will probably crash for prev_tag, next_tag in zip(phase_tags, phase_tags[1:]): # unpack pmt values pval = pmt.to_python(prev_tag.value) + nval = pmt.to_python(next_tag.value) # compute indexes in phase vector pidx = prev_tag.offset - self.sampnr - idx = next_tag.offset - self.sampnr + nidx = next_tag.offset - self.sampnr - # compute phase correction for block - phase[pidx:idx] = pval - print(f"Correction for block {pidx} to {idx} is {pval}") + # compute frquency correction for block by linearly interpolating + # frame values + nsamples = nidx - pidx + freq = (nval - pval) / nsamples - # compute the remaining part of the block - last_tag = phase_tags[-1] - last_val = pmt.to_python(last_tag.value) - last_idx = last_tag.offset - self.sampnr + # total correction is: phase + freq * time + phase[pidx:nidx] = pval * np.ones(nsamples) + freq * np.arange(0, nsamples) + print_phase_correction(pidx, nidx, pval, freq) - phase[last_idx:] = last_val + # for the last block because the next tag is unknown (in the future) we + # cannot predict the frequency offset. Thus we save the last tag for + # the next call. + self.last_tag = phase_tags[-1] + val = pmt.to_python(self.last_tag.value) + idx = self.last_tag.offset - self.sampnr - # save values for next call - self.last_phase = last_val + phase[idx:] = val - # mark samples as processed and compute to output - self.sampnr += len(inp) + # compute correction out[:] = inp * np.exp(-1j * phase) - return len(out) + # increment processed samples counter + self.sampnr += len(inp) + return len(phase) -- cgit v1.2.1 From 6d56e1b35b061ffe4f677d0d6e7867f366068e82 Mon Sep 17 00:00:00 2001 From: Nao Pross Date: Thu, 2 Dec 2021 21:27:17 +0100 Subject: Remove custom blocks from correlator test --- tests/correlator/correlator.grc | 21 ++------------------- tests/correlator/correlator.py | 5 +---- 2 files changed, 3 insertions(+), 23 deletions(-) (limited to 'tests') diff --git a/tests/correlator/correlator.grc b/tests/correlator/correlator.grc index 58cf3b4..f54430c 100644 --- a/tests/correlator/correlator.grc +++ b/tests/correlator/correlator.grc @@ -357,7 +357,7 @@ blocks: bus_sink: false bus_source: false bus_structure: null - coordinate: [840, 1392.0] + coordinate: [536, 1392.0] rotation: 0 state: true - name: blocks_vector_source_x_0 @@ -583,22 +583,6 @@ blocks: coordinate: [1088, 1040.0] rotation: 0 state: enabled -- name: fadingui_deframer_0 - id: fadingui_deframer - parameters: - affinity: '' - alias: '' - comment: '' - frame_obj: '' - maxoutbuf: '0' - minoutbuf: '0' - states: - bus_sink: false - bus_source: false - bus_structure: null - coordinate: [552, 1388.0] - rotation: 0 - state: bypassed - name: fir_filter_xxx_1 id: fir_filter_xxx parameters: @@ -1668,7 +1652,7 @@ connections: - [digital_cma_equalizer_cc_0, '0', fir_filter_xxx_1, '0'] - [digital_cma_equalizer_cc_0, '0', qtgui_const_sink_x_0, '0'] - [digital_cma_equalizer_cc_0, '0', qtgui_time_sink_x_1_1, '0'] -- [digital_constellation_decoder_cb_0, '0', fadingui_deframer_0, '0'] +- [digital_constellation_decoder_cb_0, '0', blocks_vector_sink_x_0, '0'] - [digital_constellation_modulator_0, '0', blocks_stream_mux_1, '1'] - [digital_constellation_modulator_0, '0', channels_channel_model_0, '0'] - [digital_constellation_modulator_0, '0', qtgui_time_sink_x_1_0, '0'] @@ -1678,7 +1662,6 @@ connections: - [digital_pfb_clock_sync_xxx_0, '0', digital_cma_equalizer_cc_0, '0'] - [epy_block_0, '0', qtgui_const_sink_x_0_0, '0'] - [epy_block_0, '0', virtual_sink_3, '0'] -- [fadingui_deframer_0, '0', blocks_vector_sink_x_0, '0'] - [fir_filter_xxx_1, '0', blocks_complex_to_magphase_0, '0'] - [fir_filter_xxx_1, '0', qtgui_const_sink_x_1, '0'] - [root_raised_cosine_filter_0, '0', blocks_stream_mux_1, '0'] diff --git a/tests/correlator/correlator.py b/tests/correlator/correlator.py index 93ee8bb..e080dbc 100755 --- a/tests/correlator/correlator.py +++ b/tests/correlator/correlator.py @@ -35,7 +35,6 @@ from argparse import ArgumentParser from gnuradio.eng_arg import eng_float, intx from gnuradio import eng_notation import epy_block_0 -import fadingui from gnuradio import qtgui @@ -329,7 +328,6 @@ class correlator(gr.top_block, Qt.QWidget): self.top_grid_layout.setRowStretch(r, 1) for c in range(1, 2): self.top_grid_layout.setColumnStretch(c, 1) - self.fadingui_deframer_0 = fadingui.deframer(frame_obj=) self.epy_block_0 = epy_block_0.blk() self.digital_pfb_clock_sync_xxx_0 = digital.pfb_clock_sync_ccf(sps, timing_loop_bw, rrc_taps, nfilts, 16, 1.5, 1) self.digital_corr_est_cc_0 = digital.corr_est_cc(access_code_symbols, 1, 0, .8, digital.THRESHOLD_DYNAMIC) @@ -372,7 +370,7 @@ class correlator(gr.top_block, Qt.QWidget): self.connect((self.channels_channel_model_0, 0), (self.blocks_throttle_0, 0)) self.connect((self.digital_cma_equalizer_cc_0, 0), (self.digital_corr_est_cc_0, 0)) self.connect((self.digital_cma_equalizer_cc_0, 0), (self.qtgui_const_sink_x_0, 0)) - self.connect((self.digital_constellation_decoder_cb_0, 0), (self.fadingui_deframer_0, 0)) + self.connect((self.digital_constellation_decoder_cb_0, 0), (self.blocks_vector_sink_x_0, 0)) self.connect((self.digital_constellation_modulator_0, 0), (self.channels_channel_model_0, 0)) self.connect((self.digital_constellation_modulator_0, 0), (self.qtgui_time_sink_x_1_0, 0)) self.connect((self.digital_corr_est_cc_0, 1), (self.blocks_complex_to_magphase_0_0, 0)) @@ -381,7 +379,6 @@ class correlator(gr.top_block, Qt.QWidget): self.connect((self.digital_pfb_clock_sync_xxx_0, 0), (self.digital_cma_equalizer_cc_0, 0)) self.connect((self.epy_block_0, 0), (self.digital_constellation_decoder_cb_0, 0)) self.connect((self.epy_block_0, 0), (self.qtgui_const_sink_x_0_0, 0)) - self.connect((self.fadingui_deframer_0, 0), (self.blocks_vector_sink_x_0, 0)) def closeEvent(self, event): -- cgit v1.2.1 From 3718e92fe6418e33a7e8d53192383d021d20c524 Mon Sep 17 00:00:00 2001 From: Nao Pross Date: Fri, 3 Dec 2021 00:18:55 +0100 Subject: Refractor frequency correction --- tests/correlator/correlator.grc | 82 +++++++++++++------------- tests/correlator/epy_block_0.py | 124 ++++++++++++++++++---------------------- 2 files changed, 95 insertions(+), 111 deletions(-) (limited to 'tests') diff --git a/tests/correlator/correlator.grc b/tests/correlator/correlator.grc index f54430c..57c1762 100644 --- a/tests/correlator/correlator.grc +++ b/tests/correlator/correlator.grc @@ -526,49 +526,45 @@ blocks: _source_code: "import pmt\n\nimport numpy as np\nfrom gnuradio import gr\n\n\n\ class blk(gr.sync_block):\n def __init__(self):\n gr.sync_block.__init__(\n\ \ self,\n name='Phase Lock',\n in_sig=[np.complex64],\n\ - \ out_sig=[np.complex64]\n )\n\n # keep track of how\ - \ many samples were processed,\n # because tags have an absolute offset\n\ - \ self.sampnr: np.complex64 = 0\n\n # because of block processing\ - \ a tagged block could\n # be split in half so we need to keep track\ - \ of the\n # \"previous\" values\n self.last_tag = None\n\n \ - \ def work(self, input_items, output_items):\n # nicer aliases\n \ - \ out = output_items[0]\n inp = input_items[0]\n\n def print_phase_correction(start,\ - \ end, phase, freq):\n print(f\"Correction for block {start:3d} to\ - \ {end:3d} is phase = {phase: 2.4f} rad, freq = {freq * 1e3: 2.4f} milli rad/samp\"\ - )\n\n # read only phase tags\n tags = self.get_tags_in_window(0,\ - \ 0, len(inp))\n\n is_phase = lambda tag: pmt.to_python(tag.key) == \"\ - phase_est\"\n phase_tags = list(filter(is_phase, tags))\n\n #\ - \ FIXME: what if there are no tags? check that!\n\n print(f\"Processing\ - \ {len(inp)} samples, with {len(phase_tags)} tags\")\n\n # create a phase\ - \ correction vector\n phase = np.zeros(len(inp), dtype=np.float64)\n\n\ - \ # compute correction from previous block (if present)\n if self.last_tag:\n\ - \ # variables for first and last phase values\n lval =\ - \ pmt.to_python(self.last_tag.value)\n fval = pmt.to_python(phase_tags[0].value)\n\ - \n # compute index for phase vector\n fidx = phase_tags[0].offset\ - \ - self.sampnr\n\n # compute frequency offset\n nsamples\ - \ = phase_tags[0].offset - self.last_tag.offset\n freq = (fval -\ - \ lval) / nsamples\n\n # total phase correction is: phase + freq\ - \ * time\n phase[:fidx] = lval * np.ones(fidx) + freq * np.arange(0,\ - \ fidx)\n\n # compute correction\n print_phase_correction(0,\ - \ fidx, lval, freq)\n\n # iterate phase tags \"in the middle\"\n \ - \ # FIXME: what if there are less than 2 tags?\n # the code\ - \ below will probably crash\n for prev_tag, next_tag in zip(phase_tags,\ - \ phase_tags[1:]):\n # unpack pmt values\n pval = pmt.to_python(prev_tag.value)\n\ - \ nval = pmt.to_python(next_tag.value)\n\n # compute indexes\ - \ in phase vector\n pidx = prev_tag.offset - self.sampnr\n \ - \ nidx = next_tag.offset - self.sampnr\n\n # compute frquency\ - \ correction for block by linearly interpolating\n # frame values\n\ - \ nsamples = nidx - pidx\n freq = (nval - pval) / nsamples\n\ - \n # total correction is: phase + freq * time\n phase[pidx:nidx]\ - \ = pval * np.ones(nsamples) + freq * np.arange(0, nsamples)\n print_phase_correction(pidx,\ - \ nidx, pval, freq)\n\n # for the last block because the next tag is\ - \ unknown (in the future) we\n # cannot predict the frequency offset.\ - \ Thus we save the last tag for\n # the next call.\n self.last_tag\ - \ = phase_tags[-1]\n val = pmt.to_python(self.last_tag.value)\n \ - \ idx = self.last_tag.offset - self.sampnr\n\n phase[idx:] = val\n\n\ - \ # compute correction\n out[:] = inp * np.exp(-1j * phase)\n\n\ - \ # increment processed samples counter\n self.sampnr += len(inp)\n\ - \ return len(phase)\n" + \ out_sig=[np.complex64]\n )\n\n # we need to keep\ + \ track of the aboslute number of samples that have\n # been processed,\ + \ because tags have an absolute offset\n self.counter: np.uint64 = 0\n\ + \n # because we do block processing, we need to keep track of the last\ + \ tag\n # of the previous block to correct the first values of the next\ + \ block\n self.last = None\n\n def block_phase(self, start, end):\n\ + \ # compute number of samples in block\n nsamples = end.offset\ + \ - start.offset\n\n # unpack pmt values into start and end phase\n \ + \ sphase = pmt.to_python(start.value)\n ephase = pmt.to_python(end.value)\n\ + \n # compute frequency offset between start and end\n freq = (sphase\ + \ - ephase) / nsamples\n\n # debugging\n print(f\"Correction for\ + \ block of {nsamples:2d} samples is \" \\\n f\"phase={sphase: .4f}\ + \ rad and freq={freq*1e3: .4f} milli rad / sample\")\n\n # compute block\ + \ values\n return sphase * np.ones(nsamples) + freq * np.arange(0, nsamples)\n\ + \n def work(self, input_items, output_items):\n # FIXME: replace class\ + \ counter with local variable\n # self.counter = self.nitems_written(0)\n\ + \n # nicer aliases\n inp = input_items[0]\n out = output_items[0]\n\ + \n # read phase tags\n is_phase = lambda tag: pmt.to_python(tag.key)\ + \ == \"phase_est\"\n tags = list(filter(is_phase, self.get_tags_in_window(0,\ + \ 0, len(inp))))\n\n # debugging\n print(f\"Processing {len(tags)}\ + \ tags = {tags[-1].offset - tags[0].offset} \" \\\n f\"samples\ + \ out of {len(inp)} input samples\")\n\n # compute \"the middle\"\n \ + \ enough_samples = lambda pair: ((pair[1].offset - pair[0].offset) > 0)\n\ + \ pairs = list(filter(enough_samples, zip(tags, tags[1:])))\n \ + \ blocks = [ self.block_phase(start, end) for (start, end) in pairs ]\n \ + \ middle = np.concatenate(blocks) if blocks else []\n\n # compute\ + \ the remainder from the previous call\n nfront = tags[0].offset - self.counter\n\ + \ print(f\"Processing {nfront} samples at the front of the buffer\")\n\ + \ start = self.block_phase(self.last, tags[0])[-nfront:] \\\n \ + \ if self.last else np.zeros(nfront)\n\n # compute values at\ + \ the end\n nback = len(inp) - (tags[-1].offset - self.counter)\n \ + \ print(f\"Processing {nback} samples at the back of the buffer\")\n \ + \ end = np.ones(nback) * pmt.to_python(tags[-1].value)\n\n # compute\ + \ correction\n correction = np.exp(-1j * np.concatenate([start, middle,\ + \ end]))\n length = len(correction)\n\n # write outputs\n \ + \ out[:length] = inp[:length] * correction\n self.counter += len(inp)\n\ + \n # save last tag for next call\n self.last = tags[-1]\n\n \ + \ # FIXME: should return `length' but then the last sample is not\n \ + \ # included and self.last does something weird\n return len(out)\n" affinity: '' alias: '' comment: '' diff --git a/tests/correlator/epy_block_0.py b/tests/correlator/epy_block_0.py index 90ad75e..9cb25bb 100644 --- a/tests/correlator/epy_block_0.py +++ b/tests/correlator/epy_block_0.py @@ -13,88 +13,76 @@ class blk(gr.sync_block): out_sig=[np.complex64] ) - # keep track of how many samples were processed, - # because tags have an absolute offset - self.sampnr: np.complex64 = 0 + # we need to keep track of the aboslute number of samples that have + # been processed, because tags have an absolute offset + self.counter: np.uint64 = 0 - # because of block processing a tagged block could - # be split in half so we need to keep track of the - # "previous" values - self.last_tag = None + # because we do block processing, we need to keep track of the last tag + # of the previous block to correct the first values of the next block + self.last = None - def work(self, input_items, output_items): - # nicer aliases - out = output_items[0] - inp = input_items[0] - - def print_phase_correction(start, end, phase, freq): - print(f"Correction for block {start:3d} to {end:3d} is phase = {phase: 2.4f} rad, freq = {freq * 1e3: 2.4f} milli rad/samp") - - # read only phase tags - tags = self.get_tags_in_window(0, 0, len(inp)) - - is_phase = lambda tag: pmt.to_python(tag.key) == "phase_est" - phase_tags = list(filter(is_phase, tags)) + def block_phase(self, start, end): + # compute number of samples in block + nsamples = end.offset - start.offset - # FIXME: what if there are no tags? check that! + # unpack pmt values into start and end phase + sphase = pmt.to_python(start.value) + ephase = pmt.to_python(end.value) - print(f"Processing {len(inp)} samples, with {len(phase_tags)} tags") + # compute frequency offset between start and end + freq = (sphase - ephase) / nsamples - # create a phase correction vector - phase = np.zeros(len(inp), dtype=np.float64) + # debugging + print(f"Correction for block of {nsamples:2d} samples is " \ + f"phase={sphase: .4f} rad and freq={freq*1e3: .4f} milli rad / sample") - # compute correction from previous block (if present) - if self.last_tag: - # variables for first and last phase values - lval = pmt.to_python(self.last_tag.value) - fval = pmt.to_python(phase_tags[0].value) + # compute block values + return sphase * np.ones(nsamples) + freq * np.arange(0, nsamples) - # compute index for phase vector - fidx = phase_tags[0].offset - self.sampnr - - # compute frequency offset - nsamples = phase_tags[0].offset - self.last_tag.offset - freq = (fval - lval) / nsamples + def work(self, input_items, output_items): + # FIXME: replace class counter with local variable + # self.counter = self.nitems_written(0) - # total phase correction is: phase + freq * time - phase[:fidx] = lval * np.ones(fidx) + freq * np.arange(0, fidx) + # nicer aliases + inp = input_items[0] + out = output_items[0] - # compute correction - print_phase_correction(0, fidx, lval, freq) + # read phase tags + is_phase = lambda tag: pmt.to_python(tag.key) == "phase_est" + tags = list(filter(is_phase, self.get_tags_in_window(0, 0, len(inp)))) - # iterate phase tags "in the middle" - # FIXME: what if there are less than 2 tags? - # the code below will probably crash - for prev_tag, next_tag in zip(phase_tags, phase_tags[1:]): - # unpack pmt values - pval = pmt.to_python(prev_tag.value) - nval = pmt.to_python(next_tag.value) + # debugging + print(f"Processing {len(tags)} tags = {tags[-1].offset - tags[0].offset} " \ + f"samples out of {len(inp)} input samples") - # compute indexes in phase vector - pidx = prev_tag.offset - self.sampnr - nidx = next_tag.offset - self.sampnr + # compute "the middle" + enough_samples = lambda pair: ((pair[1].offset - pair[0].offset) > 0) + pairs = list(filter(enough_samples, zip(tags, tags[1:]))) + blocks = [ self.block_phase(start, end) for (start, end) in pairs ] + middle = np.concatenate(blocks) if blocks else [] - # compute frquency correction for block by linearly interpolating - # frame values - nsamples = nidx - pidx - freq = (nval - pval) / nsamples + # compute the remainder from the previous call + nfront = tags[0].offset - self.counter + print(f"Processing {nfront} samples at the front of the buffer") + start = self.block_phase(self.last, tags[0])[-nfront:] \ + if self.last else np.zeros(nfront) - # total correction is: phase + freq * time - phase[pidx:nidx] = pval * np.ones(nsamples) + freq * np.arange(0, nsamples) - print_phase_correction(pidx, nidx, pval, freq) + # compute values at the end + nback = len(inp) - (tags[-1].offset - self.counter) + print(f"Processing {nback} samples at the back of the buffer") + end = np.ones(nback) * pmt.to_python(tags[-1].value) - # for the last block because the next tag is unknown (in the future) we - # cannot predict the frequency offset. Thus we save the last tag for - # the next call. - self.last_tag = phase_tags[-1] - val = pmt.to_python(self.last_tag.value) - idx = self.last_tag.offset - self.sampnr + # compute correction + correction = np.exp(-1j * np.concatenate([start, middle, end])) + length = len(correction) - phase[idx:] = val + # write outputs + out[:length] = inp[:length] * correction + self.counter += len(inp) - # compute correction - out[:] = inp * np.exp(-1j * phase) + # save last tag for next call + self.last = tags[-1] - # increment processed samples counter - self.sampnr += len(inp) - return len(phase) + # FIXME: should return `length' but then the last sample is not + # included and self.last does something weird + return len(out) -- cgit v1.2.1 From 5d2f01fe71b736f2f5bb8a57bb2f4cd383290e9f Mon Sep 17 00:00:00 2001 From: Nao Pross Date: Fri, 3 Dec 2021 00:29:03 +0100 Subject: Fix bug when tag is aligned with inp block --- tests/correlator/correlator.grc | 12 ++++++------ tests/correlator/correlator.py | 2 +- tests/correlator/epy_block_0.py | 4 ++-- 3 files changed, 9 insertions(+), 9 deletions(-) (limited to 'tests') diff --git a/tests/correlator/correlator.grc b/tests/correlator/correlator.grc index 57c1762..5a73092 100644 --- a/tests/correlator/correlator.grc +++ b/tests/correlator/correlator.grc @@ -408,7 +408,7 @@ blocks: block_tags: 'False' comment: '' epsilon: '1.0' - freq_offset: '0.0001' + freq_offset: '0.0002' maxoutbuf: '0' minoutbuf: '0' noise_voltage: '0.2' @@ -541,7 +541,7 @@ blocks: \ rad and freq={freq*1e3: .4f} milli rad / sample\")\n\n # compute block\ \ values\n return sphase * np.ones(nsamples) + freq * np.arange(0, nsamples)\n\ \n def work(self, input_items, output_items):\n # FIXME: replace class\ - \ counter with local variable\n # self.counter = self.nitems_written(0)\n\ + \ counter with local variable\n self.counter = self.nitems_written(0)\n\ \n # nicer aliases\n inp = input_items[0]\n out = output_items[0]\n\ \n # read phase tags\n is_phase = lambda tag: pmt.to_python(tag.key)\ \ == \"phase_est\"\n tags = list(filter(is_phase, self.get_tags_in_window(0,\ @@ -555,10 +555,10 @@ blocks: \ the remainder from the previous call\n nfront = tags[0].offset - self.counter\n\ \ print(f\"Processing {nfront} samples at the front of the buffer\")\n\ \ start = self.block_phase(self.last, tags[0])[-nfront:] \\\n \ - \ if self.last else np.zeros(nfront)\n\n # compute values at\ - \ the end\n nback = len(inp) - (tags[-1].offset - self.counter)\n \ - \ print(f\"Processing {nback} samples at the back of the buffer\")\n \ - \ end = np.ones(nback) * pmt.to_python(tags[-1].value)\n\n # compute\ + \ if self.last and nfront else np.zeros(nfront)\n\n # compute\ + \ values at the end\n nback = len(inp) - (tags[-1].offset - self.counter)\n\ + \ print(f\"Processing {nback} samples at the back of the buffer\")\n\ + \ end = np.ones(nback) * pmt.to_python(tags[-1].value)\n\n # compute\ \ correction\n correction = np.exp(-1j * np.concatenate([start, middle,\ \ end]))\n length = len(correction)\n\n # write outputs\n \ \ out[:length] = inp[:length] * correction\n self.counter += len(inp)\n\ diff --git a/tests/correlator/correlator.py b/tests/correlator/correlator.py index e080dbc..536ac00 100755 --- a/tests/correlator/correlator.py +++ b/tests/correlator/correlator.py @@ -343,7 +343,7 @@ class correlator(gr.top_block, Qt.QWidget): self.digital_cma_equalizer_cc_0 = digital.cma_equalizer_cc(15, 1, .002, 1) self.channels_channel_model_0 = channels.channel_model( noise_voltage=0.2, - frequency_offset=0.0001, + frequency_offset=0.0002, epsilon=1.0, taps=[-1.4 + .4j], noise_seed=243, diff --git a/tests/correlator/epy_block_0.py b/tests/correlator/epy_block_0.py index 9cb25bb..abf4486 100644 --- a/tests/correlator/epy_block_0.py +++ b/tests/correlator/epy_block_0.py @@ -41,7 +41,7 @@ class blk(gr.sync_block): def work(self, input_items, output_items): # FIXME: replace class counter with local variable - # self.counter = self.nitems_written(0) + self.counter = self.nitems_written(0) # nicer aliases inp = input_items[0] @@ -65,7 +65,7 @@ class blk(gr.sync_block): nfront = tags[0].offset - self.counter print(f"Processing {nfront} samples at the front of the buffer") start = self.block_phase(self.last, tags[0])[-nfront:] \ - if self.last else np.zeros(nfront) + if self.last and nfront else np.zeros(nfront) # compute values at the end nback = len(inp) - (tags[-1].offset - self.counter) -- cgit v1.2.1 From edf08d1815772fc985a89c976a190b3fcd6fb087 Mon Sep 17 00:00:00 2001 From: Nao Pross Date: Fri, 3 Dec 2021 00:45:23 +0100 Subject: Add a LPF on the frequency --- tests/correlator/correlator.grc | 52 ++++++++++++++++++++++++----------------- tests/correlator/correlator.py | 2 +- tests/correlator/epy_block_0.py | 26 ++++++++++++++++----- 3 files changed, 51 insertions(+), 29 deletions(-) (limited to 'tests') diff --git a/tests/correlator/correlator.grc b/tests/correlator/correlator.grc index 5a73092..bf44544 100644 --- a/tests/correlator/correlator.grc +++ b/tests/correlator/correlator.grc @@ -163,7 +163,7 @@ blocks: id: variable parameters: comment: '' - value: '[31, 53] + [0x12, 0xe3, 0x9b, 0xee, 0x84, 0x23, 0x41, 0xf3]' + value: '[31, 53] + [0x12, 0xe3, 0x9b, 0xee, 0x84, 0x23, 0x41, 0xf3] * 2' states: bus_sink: false bus_source: false @@ -531,17 +531,23 @@ blocks: \ because tags have an absolute offset\n self.counter: np.uint64 = 0\n\ \n # because we do block processing, we need to keep track of the last\ \ tag\n # of the previous block to correct the first values of the next\ - \ block\n self.last = None\n\n def block_phase(self, start, end):\n\ - \ # compute number of samples in block\n nsamples = end.offset\ - \ - start.offset\n\n # unpack pmt values into start and end phase\n \ - \ sphase = pmt.to_python(start.value)\n ephase = pmt.to_python(end.value)\n\ - \n # compute frequency offset between start and end\n freq = (sphase\ - \ - ephase) / nsamples\n\n # debugging\n print(f\"Correction for\ - \ block of {nsamples:2d} samples is \" \\\n f\"phase={sphase: .4f}\ - \ rad and freq={freq*1e3: .4f} milli rad / sample\")\n\n # compute block\ - \ values\n return sphase * np.ones(nsamples) + freq * np.arange(0, nsamples)\n\ - \n def work(self, input_items, output_items):\n # FIXME: replace class\ - \ counter with local variable\n self.counter = self.nitems_written(0)\n\ + \ block\n self.last = None\n\n # to compute the values that are\ + \ at the end we need to know the frequency\n # of the last block\n \ + \ self.freq = 1\n\n def block_phase(self, start, end):\n # compute\ + \ number of samples in block\n nsamples = end.offset - start.offset\n\ + \n # unpack pmt values into start and end phase\n sphase = pmt.to_python(start.value)\n\ + \ ephase = pmt.to_python(end.value)\n\n # compute frequency offset\ + \ between start and end\n freq = (sphase - ephase) / nsamples\n\n \ + \ # save this frequency values to compute the end block, unless frequency\n\ + \ # has changed too fast, in that case replace the current values with\n\ + \ # the previous one . This is effectively like a low pass filter.\n\ + \ if abs(freq / self.freq) > 4:\n freq = self.freq\n \ + \ else:\n self.freq = freq\n\n\n # debugging\n print(f\"\ + Correction for block of {nsamples:2d} samples is \" \\\n f\"phase={sphase:\ + \ .4f} rad and freq={freq*1e3: .4f} milli rad / sample\")\n\n # compute\ + \ block values\n return sphase * np.ones(nsamples) + freq * np.arange(0,\ + \ nsamples)\n\n def work(self, input_items, output_items):\n # FIXME:\ + \ replace class counter with local variable\n self.counter = self.nitems_written(0)\n\ \n # nicer aliases\n inp = input_items[0]\n out = output_items[0]\n\ \n # read phase tags\n is_phase = lambda tag: pmt.to_python(tag.key)\ \ == \"phase_est\"\n tags = list(filter(is_phase, self.get_tags_in_window(0,\ @@ -552,16 +558,18 @@ blocks: \ pairs = list(filter(enough_samples, zip(tags, tags[1:])))\n \ \ blocks = [ self.block_phase(start, end) for (start, end) in pairs ]\n \ \ middle = np.concatenate(blocks) if blocks else []\n\n # compute\ - \ the remainder from the previous call\n nfront = tags[0].offset - self.counter\n\ - \ print(f\"Processing {nfront} samples at the front of the buffer\")\n\ - \ start = self.block_phase(self.last, tags[0])[-nfront:] \\\n \ - \ if self.last and nfront else np.zeros(nfront)\n\n # compute\ - \ values at the end\n nback = len(inp) - (tags[-1].offset - self.counter)\n\ - \ print(f\"Processing {nback} samples at the back of the buffer\")\n\ - \ end = np.ones(nback) * pmt.to_python(tags[-1].value)\n\n # compute\ - \ correction\n correction = np.exp(-1j * np.concatenate([start, middle,\ - \ end]))\n length = len(correction)\n\n # write outputs\n \ - \ out[:length] = inp[:length] * correction\n self.counter += len(inp)\n\ + \ values at the end, we do not have informations about the future\n #\ + \ but we can use the frequency of the last block to approximate\n nback\ + \ = len(inp) - (tags[-1].offset - self.counter)\n print(f\"Processing\ + \ {nback} samples at the back of the buffer\")\n end = np.ones(nback)\ + \ * pmt.to_python(tags[-1].value) + self.freq * np.arange(0, nback)\n\n \ + \ # compute the \"start\", using the last tag from the previous call\n \ + \ nfront = tags[0].offset - self.counter\n print(f\"Processing {nfront}\ + \ samples at the front of the buffer\")\n start = self.block_phase(self.last,\ + \ tags[0])[-nfront:] \\\n if self.last and nfront else np.zeros(nfront)\n\ + \n # compute correction\n correction = np.exp(-1j * np.concatenate([start,\ + \ middle, end]))\n length = len(correction)\n\n # write outputs\n\ + \ out[:length] = inp[:length] * correction\n self.counter += len(inp)\n\ \n # save last tag for next call\n self.last = tags[-1]\n\n \ \ # FIXME: should return `length' but then the last sample is not\n \ \ # included and self.last does something weird\n return len(out)\n" diff --git a/tests/correlator/correlator.py b/tests/correlator/correlator.py index 536ac00..5edc8ee 100755 --- a/tests/correlator/correlator.py +++ b/tests/correlator/correlator.py @@ -78,7 +78,7 @@ class correlator(gr.top_block, Qt.QWidget): self.nfilts = nfilts = 32 self.excess_bw = excess_bw = .35 self.timing_loop_bw = timing_loop_bw = 2 * 3.141592653589793 / 100 - self.testvec = testvec = [31, 53] + [0x12, 0xe3, 0x9b, 0xee, 0x84, 0x23, 0x41, 0xf3] + self.testvec = testvec = [31, 53] + [0x12, 0xe3, 0x9b, 0xee, 0x84, 0x23, 0x41, 0xf3] * 2 self.samp_rate = samp_rate = 32000 self.rrc_taps = rrc_taps = firdes.root_raised_cosine(nfilts, nfilts, 1.0/float(sps), excess_bw, 45*nfilts) self.revconj_access_code_symbols = revconj_access_code_symbols = [(1.4142135623730951+1.4142135623730951j), (1.4142135623730951+1.4142135623730951j), (1.4142135623730951-1.4142135623730951j), (-1.4142135623730951+1.4142135623730951j), (1.4142135623730951-1.4142135623730951j), (1.4142135623730951-1.4142135623730951j), (1.4142135623730951+1.4142135623730951j), (-1.4142135623730951+1.4142135623730951j)] diff --git a/tests/correlator/epy_block_0.py b/tests/correlator/epy_block_0.py index abf4486..6b47e80 100644 --- a/tests/correlator/epy_block_0.py +++ b/tests/correlator/epy_block_0.py @@ -21,6 +21,10 @@ class blk(gr.sync_block): # of the previous block to correct the first values of the next block self.last = None + # to compute the values that are at the end we need to know the frequency + # of the last block + self.freq = 1 + def block_phase(self, start, end): # compute number of samples in block nsamples = end.offset - start.offset @@ -32,6 +36,15 @@ class blk(gr.sync_block): # compute frequency offset between start and end freq = (sphase - ephase) / nsamples + # save this frequency values to compute the end block, unless frequency + # has changed too fast, in that case replace the current values with + # the previous one . This is effectively like a low pass filter. + if abs(freq / self.freq) > 4: + freq = self.freq + else: + self.freq = freq + + # debugging print(f"Correction for block of {nsamples:2d} samples is " \ f"phase={sphase: .4f} rad and freq={freq*1e3: .4f} milli rad / sample") @@ -61,17 +74,18 @@ class blk(gr.sync_block): blocks = [ self.block_phase(start, end) for (start, end) in pairs ] middle = np.concatenate(blocks) if blocks else [] - # compute the remainder from the previous call + # compute values at the end, we do not have informations about the future + # but we can use the frequency of the last block to approximate + nback = len(inp) - (tags[-1].offset - self.counter) + print(f"Processing {nback} samples at the back of the buffer") + end = np.ones(nback) * pmt.to_python(tags[-1].value) + self.freq * np.arange(0, nback) + + # compute the "start", using the last tag from the previous call nfront = tags[0].offset - self.counter print(f"Processing {nfront} samples at the front of the buffer") start = self.block_phase(self.last, tags[0])[-nfront:] \ if self.last and nfront else np.zeros(nfront) - # compute values at the end - nback = len(inp) - (tags[-1].offset - self.counter) - print(f"Processing {nback} samples at the back of the buffer") - end = np.ones(nback) * pmt.to_python(tags[-1].value) - # compute correction correction = np.exp(-1j * np.concatenate([start, middle, end])) length = len(correction) -- cgit v1.2.1 From b389c8d00064d224a534d3c4a37bd4ee700a5022 Mon Sep 17 00:00:00 2001 From: Nao Pross Date: Fri, 3 Dec 2021 13:01:42 +0100 Subject: Improve frequency LPF --- tests/correlator/correlator.grc | 100 +++++++++++++++++++++++++--------------- tests/correlator/correlator.py | 13 ++++-- tests/correlator/epy_block_0.py | 36 +++++++++------ 3 files changed, 93 insertions(+), 56 deletions(-) (limited to 'tests') diff --git a/tests/correlator/correlator.grc b/tests/correlator/correlator.grc index bf44544..220eaed 100644 --- a/tests/correlator/correlator.grc +++ b/tests/correlator/correlator.grc @@ -163,7 +163,7 @@ blocks: id: variable parameters: comment: '' - value: '[31, 53] + [0x12, 0xe3, 0x9b, 0xee, 0x84, 0x23, 0x41, 0xf3] * 2' + value: '[31, 53] + [0x12, 0xe3, 0x9b, 0xee, 0x84, 0x23, 0x41, 0xf3] ' states: bus_sink: false bus_source: false @@ -212,7 +212,7 @@ blocks: bus_sink: false bus_source: false bus_structure: null - coordinate: [1048, 1128.0] + coordinate: [1088, 1304.0] rotation: 0 state: enabled - name: blocks_multiply_const_vxx_0 @@ -248,7 +248,7 @@ blocks: bus_sink: false bus_source: false bus_structure: null - coordinate: [1336, 1204.0] + coordinate: [1376, 1380.0] rotation: 0 state: disabled - name: blocks_null_sink_3 @@ -265,7 +265,7 @@ blocks: bus_sink: false bus_source: false bus_structure: null - coordinate: [1336, 1256.0] + coordinate: [1376, 1432.0] rotation: 0 state: true - name: blocks_null_source_0 @@ -408,7 +408,7 @@ blocks: block_tags: 'False' comment: '' epsilon: '1.0' - freq_offset: '0.0002' + freq_offset: '0.0001' maxoutbuf: '0' minoutbuf: '0' noise_voltage: '0.2' @@ -497,6 +497,24 @@ blocks: coordinate: [776, 1020.0] rotation: 0 state: enabled +- name: digital_costas_loop_cc_0 + id: digital_costas_loop_cc + parameters: + affinity: '' + alias: '' + comment: '' + maxoutbuf: '0' + minoutbuf: '0' + order: '4' + use_snr: 'False' + w: 2 * 3.141592653589793 / 100 + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [1088, 1128.0] + rotation: 0 + state: true - name: digital_pfb_clock_sync_xxx_0 id: digital_pfb_clock_sync_xxx parameters: @@ -531,18 +549,20 @@ blocks: \ because tags have an absolute offset\n self.counter: np.uint64 = 0\n\ \n # because we do block processing, we need to keep track of the last\ \ tag\n # of the previous block to correct the first values of the next\ - \ block\n self.last = None\n\n # to compute the values that are\ - \ at the end we need to know the frequency\n # of the last block\n \ - \ self.freq = 1\n\n def block_phase(self, start, end):\n # compute\ - \ number of samples in block\n nsamples = end.offset - start.offset\n\ - \n # unpack pmt values into start and end phase\n sphase = pmt.to_python(start.value)\n\ - \ ephase = pmt.to_python(end.value)\n\n # compute frequency offset\ - \ between start and end\n freq = (sphase - ephase) / nsamples\n\n \ - \ # save this frequency values to compute the end block, unless frequency\n\ - \ # has changed too fast, in that case replace the current values with\n\ - \ # the previous one . This is effectively like a low pass filter.\n\ - \ if abs(freq / self.freq) > 4:\n freq = self.freq\n \ - \ else:\n self.freq = freq\n\n\n # debugging\n print(f\"\ + \ block\n self.last = None\n\n # both the phase and frequency\ + \ corrections should go through a low pass\n # filter to avoid werid\ + \ jumps in the correction. to do that, there are\n # two buffers with\ + \ an index\n self.index = 0\n self.length = 7\n self.freq\ + \ = np.zeros(self.length)\n\n def lpf_freq(self, new_sample):\n #\ + \ save new sample\n self.freq[self.index] = new_sample\n # increment\ + \ index\n self.index = (self.index + 1) % self.length\n\n return\ + \ np.sum(self.freq) / self.length\n\n def block_phase(self, start, end):\n\ + \ # compute number of samples in block\n nsamples = end.offset\ + \ - start.offset\n\n # unpack pmt values into start and end phase\n \ + \ sphase = pmt.to_python(start.value)\n ephase = pmt.to_python(end.value)\n\ + \n # compute frequency offset between start and end\n # and run\ + \ it through a low pass filter (mean)\n freq = (sphase - ephase) / nsamples\n\ + \ freq = self.lpf_freq(freq)\n\n # debugging\n print(f\"\ Correction for block of {nsamples:2d} samples is \" \\\n f\"phase={sphase:\ \ .4f} rad and freq={freq*1e3: .4f} milli rad / sample\")\n\n # compute\ \ block values\n return sphase * np.ones(nsamples) + freq * np.arange(0,\ @@ -551,20 +571,22 @@ blocks: \n # nicer aliases\n inp = input_items[0]\n out = output_items[0]\n\ \n # read phase tags\n is_phase = lambda tag: pmt.to_python(tag.key)\ \ == \"phase_est\"\n tags = list(filter(is_phase, self.get_tags_in_window(0,\ - \ 0, len(inp))))\n\n # debugging\n print(f\"Processing {len(tags)}\ - \ tags = {tags[-1].offset - tags[0].offset} \" \\\n f\"samples\ - \ out of {len(inp)} input samples\")\n\n # compute \"the middle\"\n \ - \ enough_samples = lambda pair: ((pair[1].offset - pair[0].offset) > 0)\n\ - \ pairs = list(filter(enough_samples, zip(tags, tags[1:])))\n \ - \ blocks = [ self.block_phase(start, end) for (start, end) in pairs ]\n \ - \ middle = np.concatenate(blocks) if blocks else []\n\n # compute\ - \ values at the end, we do not have informations about the future\n #\ - \ but we can use the frequency of the last block to approximate\n nback\ - \ = len(inp) - (tags[-1].offset - self.counter)\n print(f\"Processing\ - \ {nback} samples at the back of the buffer\")\n end = np.ones(nback)\ - \ * pmt.to_python(tags[-1].value) + self.freq * np.arange(0, nback)\n\n \ - \ # compute the \"start\", using the last tag from the previous call\n \ - \ nfront = tags[0].offset - self.counter\n print(f\"Processing {nfront}\ + \ 0, len(inp))))\n\n if not tags:\n print(f\"There were no\ + \ tags in {len(inp)} samples!\")\n out[:] = inp\n return\ + \ len(out)\n\n # debugging\n print(f\"Processing {len(tags)} tags\ + \ = {tags[-1].offset - tags[0].offset} \" \\\n f\"samples out of\ + \ {len(inp)} input samples\")\n\n # compute \"the middle\"\n enough_samples\ + \ = lambda pair: ((pair[1].offset - pair[0].offset) > 0)\n pairs = list(filter(enough_samples,\ + \ zip(tags, tags[1:])))\n blocks = [ self.block_phase(start, end) for\ + \ (start, end) in pairs ]\n middle = np.concatenate(blocks) if blocks\ + \ else []\n\n # compute values at the end, we do not have informations\ + \ about the future\n # but we can use the frequency of the last block\ + \ to approximate\n nback = len(inp) - (tags[-1].offset - self.counter)\n\ + \ print(f\"Processing {nback} samples at the back of the buffer\")\n\ + \ endfreq = self.lpf_freq(self.freq[-1])\n end = np.ones(nback)\ + \ * pmt.to_python(tags[-1].value) + endfreq * np.arange(0, nback)\n\n \ + \ # compute the \"start\", using the last tag from the previous call\n \ + \ nfront = tags[0].offset - self.counter\n print(f\"Processing {nfront}\ \ samples at the front of the buffer\")\n start = self.block_phase(self.last,\ \ tags[0])[-nfront:] \\\n if self.last and nfront else np.zeros(nfront)\n\ \n # compute correction\n correction = np.exp(-1j * np.concatenate([start,\ @@ -728,9 +750,9 @@ blocks: comment: '' grid: 'False' gui_hint: 2,1,2,1 - label1: '' + label1: Custom Block label10: '' - label2: '' + label2: Costas Loop label3: '' label4: '' label5: '' @@ -750,7 +772,7 @@ blocks: marker8: '0' marker9: '0' name: '"Phase Locked Signal"' - nconnections: '1' + nconnections: '2' size: '1024' style1: '0' style10: '0' @@ -787,7 +809,7 @@ blocks: bus_sink: false bus_source: false bus_structure: null - coordinate: [1288, 940.0] + coordinate: [1368, 1092.0] rotation: 0 state: enabled - name: qtgui_const_sink_x_1 @@ -1073,7 +1095,7 @@ blocks: bus_sink: false bus_source: false bus_structure: null - coordinate: [1336, 1108.0] + coordinate: [1376, 1284.0] rotation: 0 state: enabled - name: qtgui_time_sink_x_0_0_0 @@ -1558,7 +1580,7 @@ blocks: bus_sink: false bus_source: false bus_structure: null - coordinate: [1512, 1188.0] + coordinate: [1552, 1364.0] rotation: 0 state: disabled - name: root_raised_cosine_filter_0 @@ -1607,7 +1629,7 @@ blocks: bus_sink: false bus_source: false bus_structure: null - coordinate: [1336, 1036.0] + coordinate: [1368, 1036.0] rotation: 0 state: true - name: virtual_source_0 @@ -1660,9 +1682,11 @@ connections: - [digital_constellation_modulator_0, '0', blocks_stream_mux_1, '1'] - [digital_constellation_modulator_0, '0', channels_channel_model_0, '0'] - [digital_constellation_modulator_0, '0', qtgui_time_sink_x_1_0, '0'] +- [digital_corr_est_cc_0, '0', digital_costas_loop_cc_0, '0'] - [digital_corr_est_cc_0, '0', epy_block_0, '0'] - [digital_corr_est_cc_0, '0', qtgui_time_sink_x_0_0_0, '0'] - [digital_corr_est_cc_0, '1', blocks_complex_to_magphase_0_0, '0'] +- [digital_costas_loop_cc_0, '0', qtgui_const_sink_x_0_0, '1'] - [digital_pfb_clock_sync_xxx_0, '0', digital_cma_equalizer_cc_0, '0'] - [epy_block_0, '0', qtgui_const_sink_x_0_0, '0'] - [epy_block_0, '0', virtual_sink_3, '0'] diff --git a/tests/correlator/correlator.py b/tests/correlator/correlator.py index 5edc8ee..50283c0 100755 --- a/tests/correlator/correlator.py +++ b/tests/correlator/correlator.py @@ -78,7 +78,7 @@ class correlator(gr.top_block, Qt.QWidget): self.nfilts = nfilts = 32 self.excess_bw = excess_bw = .35 self.timing_loop_bw = timing_loop_bw = 2 * 3.141592653589793 / 100 - self.testvec = testvec = [31, 53] + [0x12, 0xe3, 0x9b, 0xee, 0x84, 0x23, 0x41, 0xf3] * 2 + self.testvec = testvec = [31, 53] + [0x12, 0xe3, 0x9b, 0xee, 0x84, 0x23, 0x41, 0xf3] self.samp_rate = samp_rate = 32000 self.rrc_taps = rrc_taps = firdes.root_raised_cosine(nfilts, nfilts, 1.0/float(sps), excess_bw, 45*nfilts) self.revconj_access_code_symbols = revconj_access_code_symbols = [(1.4142135623730951+1.4142135623730951j), (1.4142135623730951+1.4142135623730951j), (1.4142135623730951-1.4142135623730951j), (-1.4142135623730951+1.4142135623730951j), (1.4142135623730951-1.4142135623730951j), (1.4142135623730951-1.4142135623730951j), (1.4142135623730951+1.4142135623730951j), (-1.4142135623730951+1.4142135623730951j)] @@ -243,7 +243,7 @@ class correlator(gr.top_block, Qt.QWidget): self.qtgui_const_sink_x_0_0 = qtgui.const_sink_c( 1024, #size "Phase Locked Signal", #name - 1 #number of inputs + 2 #number of inputs ) self.qtgui_const_sink_x_0_0.set_update_time(0.10) self.qtgui_const_sink_x_0_0.set_y_axis(-2, 2) @@ -254,7 +254,7 @@ class correlator(gr.top_block, Qt.QWidget): self.qtgui_const_sink_x_0_0.enable_axis_labels(True) - labels = ['', '', '', '', '', + labels = ['Custom Block', 'Costas Loop', '', '', '', '', '', '', '', ''] widths = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1] @@ -267,7 +267,7 @@ class correlator(gr.top_block, Qt.QWidget): alphas = [1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0] - for i in range(1): + for i in range(2): if len(labels[i]) == 0: self.qtgui_const_sink_x_0_0.set_line_label(i, "Data {0}".format(i)) else: @@ -330,6 +330,7 @@ class correlator(gr.top_block, Qt.QWidget): self.top_grid_layout.setColumnStretch(c, 1) self.epy_block_0 = epy_block_0.blk() self.digital_pfb_clock_sync_xxx_0 = digital.pfb_clock_sync_ccf(sps, timing_loop_bw, rrc_taps, nfilts, 16, 1.5, 1) + self.digital_costas_loop_cc_0 = digital.costas_loop_cc(2 * 3.141592653589793 / 100, 4, False) self.digital_corr_est_cc_0 = digital.corr_est_cc(access_code_symbols, 1, 0, .8, digital.THRESHOLD_DYNAMIC) self.digital_constellation_modulator_0 = digital.generic_mod( constellation=const, @@ -343,7 +344,7 @@ class correlator(gr.top_block, Qt.QWidget): self.digital_cma_equalizer_cc_0 = digital.cma_equalizer_cc(15, 1, .002, 1) self.channels_channel_model_0 = channels.channel_model( noise_voltage=0.2, - frequency_offset=0.0002, + frequency_offset=0.0001, epsilon=1.0, taps=[-1.4 + .4j], noise_seed=243, @@ -374,8 +375,10 @@ class correlator(gr.top_block, Qt.QWidget): self.connect((self.digital_constellation_modulator_0, 0), (self.channels_channel_model_0, 0)) self.connect((self.digital_constellation_modulator_0, 0), (self.qtgui_time_sink_x_1_0, 0)) self.connect((self.digital_corr_est_cc_0, 1), (self.blocks_complex_to_magphase_0_0, 0)) + self.connect((self.digital_corr_est_cc_0, 0), (self.digital_costas_loop_cc_0, 0)) self.connect((self.digital_corr_est_cc_0, 0), (self.epy_block_0, 0)) self.connect((self.digital_corr_est_cc_0, 0), (self.qtgui_time_sink_x_0_0_0, 0)) + self.connect((self.digital_costas_loop_cc_0, 0), (self.qtgui_const_sink_x_0_0, 1)) self.connect((self.digital_pfb_clock_sync_xxx_0, 0), (self.digital_cma_equalizer_cc_0, 0)) self.connect((self.epy_block_0, 0), (self.digital_constellation_decoder_cb_0, 0)) self.connect((self.epy_block_0, 0), (self.qtgui_const_sink_x_0_0, 0)) diff --git a/tests/correlator/epy_block_0.py b/tests/correlator/epy_block_0.py index 6b47e80..e7599c9 100644 --- a/tests/correlator/epy_block_0.py +++ b/tests/correlator/epy_block_0.py @@ -21,9 +21,20 @@ class blk(gr.sync_block): # of the previous block to correct the first values of the next block self.last = None - # to compute the values that are at the end we need to know the frequency - # of the last block - self.freq = 1 + # both the phase and frequency corrections should go through a low pass + # filter to avoid werid jumps in the correction. to do that, there are + # two buffers with an index + self.index = 0 + self.length = 7 + self.freq = np.zeros(self.length) + + def lpf_freq(self, new_sample): + # save new sample + self.freq[self.index] = new_sample + # increment index + self.index = (self.index + 1) % self.length + + return np.sum(self.freq) / self.length def block_phase(self, start, end): # compute number of samples in block @@ -34,16 +45,9 @@ class blk(gr.sync_block): ephase = pmt.to_python(end.value) # compute frequency offset between start and end + # and run it through a low pass filter (mean) freq = (sphase - ephase) / nsamples - - # save this frequency values to compute the end block, unless frequency - # has changed too fast, in that case replace the current values with - # the previous one . This is effectively like a low pass filter. - if abs(freq / self.freq) > 4: - freq = self.freq - else: - self.freq = freq - + freq = self.lpf_freq(freq) # debugging print(f"Correction for block of {nsamples:2d} samples is " \ @@ -64,6 +68,11 @@ class blk(gr.sync_block): is_phase = lambda tag: pmt.to_python(tag.key) == "phase_est" tags = list(filter(is_phase, self.get_tags_in_window(0, 0, len(inp)))) + if not tags: + print(f"There were no tags in {len(inp)} samples!") + out[:] = inp + return len(out) + # debugging print(f"Processing {len(tags)} tags = {tags[-1].offset - tags[0].offset} " \ f"samples out of {len(inp)} input samples") @@ -78,7 +87,8 @@ class blk(gr.sync_block): # but we can use the frequency of the last block to approximate nback = len(inp) - (tags[-1].offset - self.counter) print(f"Processing {nback} samples at the back of the buffer") - end = np.ones(nback) * pmt.to_python(tags[-1].value) + self.freq * np.arange(0, nback) + endfreq = self.lpf_freq(self.freq[-1]) + end = np.ones(nback) * pmt.to_python(tags[-1].value) + endfreq * np.arange(0, nback) # compute the "start", using the last tag from the previous call nfront = tags[0].offset - self.counter -- cgit v1.2.1 From 0cb8ac7bd0e88d6d26c1fda3abcf0977c2e8150b Mon Sep 17 00:00:00 2001 From: Nao Pross Date: Fri, 3 Dec 2021 17:54:07 +0100 Subject: Fix bug that makes jump estimated frequency to unreasonably high values --- tests/correlator/correlator.grc | 285 +++++++++++++++++++--------------------- tests/correlator/correlator.py | 41 +++--- tests/correlator/epy_block_0.py | 16 ++- tests/correlator/epy_block_1.py | 27 ++++ 4 files changed, 191 insertions(+), 178 deletions(-) create mode 100644 tests/correlator/epy_block_1.py (limited to 'tests') diff --git a/tests/correlator/correlator.grc b/tests/correlator/correlator.grc index 220eaed..0f82f27 100644 --- a/tests/correlator/correlator.grc +++ b/tests/correlator/correlator.grc @@ -44,26 +44,7 @@ blocks: bus_sink: false bus_source: false bus_structure: null - coordinate: [776, 1140.0] - rotation: 0 - state: enabled -- name: access_code_symbols_sps - id: variable - parameters: - comment: '' - value: '[(1.4142197+1.4142197j), (1.4142197+1.4142197j), (1.4142197+1.4142197j), - (1.4142197+1.4142197j), (1.4142197-1.4142197j), (1.4142197-1.4142197j), (1.4142197-1.4142197j), - (1.4142197-1.4142197j), (1.4142197-1.4142197j), (1.4142197-1.4142197j), (1.4142197-1.4142197j), - (1.4142197-1.4142197j), (-1.4142197-1.4142197j), (-1.4142197-1.4142197j), (-1.4142197-1.4142197j), - (-1.4142197-1.4142197j), (1.4142197-1.4142197j), (1.4142197-1.4142197j), (1.4142197-1.4142197j), - (1.4142197-1.4142197j), (1.4142197+1.4142197j), (1.4142197+1.4142197j), (1.4142197+1.4142197j), - (1.4142197+1.4142197j), (1.4142197+1.4142197j), (1.4142197+1.4142197j), (1.4142197+1.4142197j), - (1.4142197+1.4142197j)]' - states: - bus_sink: false - bus_source: false - bus_structure: null - coordinate: [224, 132.0] + coordinate: [768, 1016.0] rotation: 0 state: enabled - name: const @@ -81,7 +62,7 @@ blocks: bus_sink: false bus_source: false bus_structure: null - coordinate: [592, 484.0] + coordinate: [592, 360.0] rotation: 0 state: enabled - name: excess_bw @@ -93,7 +74,7 @@ blocks: bus_sink: false bus_source: false bus_structure: null - coordinate: [496, 484.0] + coordinate: [496, 360.0] rotation: 0 state: enabled - name: nfilts @@ -105,7 +86,7 @@ blocks: bus_sink: false bus_source: false bus_structure: null - coordinate: [224, 988.0] + coordinate: [224, 856.0] rotation: 0 state: enabled - name: revconj_access_code_symbols @@ -120,7 +101,7 @@ blocks: bus_sink: false bus_source: false bus_structure: null - coordinate: [48, 564.0] + coordinate: [48, 440.0] rotation: 0 state: enabled - name: rrc_taps @@ -132,14 +113,14 @@ blocks: bus_sink: false bus_source: false bus_structure: null - coordinate: [304, 988.0] + coordinate: [304, 856.0] rotation: 0 state: enabled - name: samp_rate id: variable parameters: comment: '' - value: '32000' + value: int(1.5e6) states: bus_sink: false bus_source: false @@ -163,24 +144,24 @@ blocks: id: variable parameters: comment: '' - value: '[31, 53] + [0x12, 0xe3, 0x9b, 0xee, 0x84, 0x23, 0x41, 0xf3] ' + value: '[0x1f, 0x35] + [0x12, 0xe3, 0x9b, 0xee, 0x84, 0x23, 0x41, 0xf3] ' states: bus_sink: false bus_source: false bus_structure: null - coordinate: [48, 492.0] + coordinate: [48, 360.0] rotation: 0 state: enabled - name: timing_loop_bw id: variable parameters: comment: '' - value: 2 * 3.141592653589793 / 100 + value: 2 * np.pi / 100 states: bus_sink: false bus_source: false bus_structure: null - coordinate: [224, 1068.0] + coordinate: [224, 936.0] rotation: 0 state: enabled - name: blocks_complex_to_magphase_0 @@ -196,7 +177,7 @@ blocks: bus_sink: false bus_source: false bus_structure: null - coordinate: [1048, 696.0] + coordinate: [1040, 568.0] rotation: 0 state: disabled - name: blocks_complex_to_magphase_0_0 @@ -212,7 +193,7 @@ blocks: bus_sink: false bus_source: false bus_structure: null - coordinate: [1088, 1304.0] + coordinate: [1032, 1176.0] rotation: 0 state: enabled - name: blocks_multiply_const_vxx_0 @@ -230,7 +211,7 @@ blocks: bus_sink: false bus_source: false bus_structure: null - coordinate: [1288, 724.0] + coordinate: [1288, 596.0] rotation: 0 state: disabled - name: blocks_multiply_const_vxx_0_0 @@ -248,7 +229,7 @@ blocks: bus_sink: false bus_source: false bus_structure: null - coordinate: [1376, 1380.0] + coordinate: [1376, 1248.0] rotation: 0 state: disabled - name: blocks_null_sink_3 @@ -265,7 +246,7 @@ blocks: bus_sink: false bus_source: false bus_structure: null - coordinate: [1376, 1432.0] + coordinate: [1376, 1304.0] rotation: 0 state: true - name: blocks_null_source_0 @@ -284,47 +265,48 @@ blocks: bus_sink: false bus_source: false bus_structure: null - coordinate: [96, 344.0] + coordinate: [96, 200.0] rotation: 0 state: enabled -- name: blocks_stream_mux_0 - id: blocks_stream_mux +- name: blocks_repack_bits_bb_0 + id: blocks_repack_bits_bb parameters: affinity: '' alias: '' + align_output: 'False' comment: '' - lengths: '[10, len(testvec)]' + endianness: gr.GR_MSB_FIRST + k: '2' + l: '8' + len_tag_key: '""' maxoutbuf: '0' minoutbuf: '0' - num_inputs: '2' - type: byte - vlen: '1' states: bus_sink: false bus_source: false bus_structure: null - coordinate: [288, 392.0] + coordinate: [672, 1252.0] rotation: 0 - state: enabled -- name: blocks_stream_mux_1 + state: true +- name: blocks_stream_mux_0 id: blocks_stream_mux parameters: affinity: '' alias: '' comment: '' - lengths: '[len(access_code_symbols_sps), sps * (len(testvec) + 15)]' + lengths: '[5, len(testvec)]' maxoutbuf: '0' minoutbuf: '0' num_inputs: '2' - type: complex + type: byte vlen: '1' states: bus_sink: false bus_source: false bus_structure: null - coordinate: [776, 280.0] + coordinate: [288, 256.0] rotation: 0 - state: disabled + state: enabled - name: blocks_throttle_0 id: blocks_throttle parameters: @@ -341,25 +323,9 @@ blocks: bus_sink: false bus_source: false bus_structure: null - coordinate: [1272, 404.0] + coordinate: [1272, 268.0] rotation: 0 state: enabled -- name: blocks_vector_sink_x_0 - id: blocks_vector_sink_x - parameters: - affinity: '' - alias: '' - comment: '' - reserve_items: '1024' - type: byte - vlen: '1' - states: - bus_sink: false - bus_source: false - bus_structure: null - coordinate: [536, 1392.0] - rotation: 0 - state: true - name: blocks_vector_source_x_0 id: blocks_vector_source_x parameters: @@ -371,35 +337,15 @@ blocks: repeat: 'True' tags: '[]' type: byte - vector: testvec * 1600 + vector: testvec * 500 vlen: '1' states: bus_sink: false bus_source: false bus_structure: null - coordinate: [48, 404.0] + coordinate: [48, 268.0] rotation: 0 state: enabled -- name: blocks_vector_source_x_1 - id: blocks_vector_source_x - parameters: - affinity: '' - alias: '' - comment: '' - maxoutbuf: '0' - minoutbuf: '0' - repeat: 'True' - tags: '[]' - type: complex - vector: access_code_symbols_sps - vlen: '1' - states: - bus_sink: false - bus_source: false - bus_structure: null - coordinate: [224, 204.0] - rotation: 0 - state: disabled - name: channels_channel_model_0 id: channels_channel_model parameters: @@ -411,14 +357,14 @@ blocks: freq_offset: '0.0001' maxoutbuf: '0' minoutbuf: '0' - noise_voltage: '0.2' + noise_voltage: '0.01' seed: '243' - taps: -1.4 + .4j + taps: np.exp(1j * 30 / 180 * np.pi) states: bus_sink: false bus_source: false bus_structure: null - coordinate: [992, 364.0] + coordinate: [1000, 228.0] rotation: 0 state: enabled - name: digital_cma_equalizer_cc_0 @@ -437,7 +383,7 @@ blocks: bus_sink: false bus_source: false bus_structure: null - coordinate: [528, 812.0] + coordinate: [520, 676.0] rotation: 0 state: enabled - name: digital_constellation_decoder_cb_0 @@ -453,7 +399,7 @@ blocks: bus_sink: false bus_source: false bus_structure: null - coordinate: [248, 1388.0] + coordinate: [224, 1260.0] rotation: 0 state: enabled - name: digital_constellation_modulator_0 @@ -474,7 +420,7 @@ blocks: bus_sink: false bus_source: false bus_structure: null - coordinate: [496, 380.0] + coordinate: [504, 244.0] rotation: 0 state: enabled - name: digital_corr_est_cc_0 @@ -494,7 +440,7 @@ blocks: bus_sink: false bus_source: false bus_structure: null - coordinate: [776, 1020.0] + coordinate: [768, 892.0] rotation: 0 state: enabled - name: digital_costas_loop_cc_0 @@ -512,9 +458,25 @@ blocks: bus_sink: false bus_source: false bus_structure: null - coordinate: [1088, 1128.0] + coordinate: [1080, 1000.0] rotation: 0 state: true +- name: digital_map_bb_0 + id: digital_map_bb + parameters: + affinity: '' + alias: '' + comment: '' + map: '[0, 1, 3, 2]' + maxoutbuf: '0' + minoutbuf: '0' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [496, 1260.0] + rotation: 0 + state: bypassed - name: digital_pfb_clock_sync_xxx_0 id: digital_pfb_clock_sync_xxx parameters: @@ -535,7 +497,7 @@ blocks: bus_sink: false bus_source: false bus_structure: null - coordinate: [224, 836.0] + coordinate: [224, 700.0] rotation: 0 state: enabled - name: epy_block_0 @@ -552,7 +514,7 @@ blocks: \ block\n self.last = None\n\n # both the phase and frequency\ \ corrections should go through a low pass\n # filter to avoid werid\ \ jumps in the correction. to do that, there are\n # two buffers with\ - \ an index\n self.index = 0\n self.length = 7\n self.freq\ + \ an index\n self.index = 0\n self.length = 5\n self.freq\ \ = np.zeros(self.length)\n\n def lpf_freq(self, new_sample):\n #\ \ save new sample\n self.freq[self.index] = new_sample\n # increment\ \ index\n self.index = (self.index + 1) % self.length\n\n return\ @@ -561,15 +523,18 @@ blocks: \ - start.offset\n\n # unpack pmt values into start and end phase\n \ \ sphase = pmt.to_python(start.value)\n ephase = pmt.to_python(end.value)\n\ \n # compute frequency offset between start and end\n # and run\ - \ it through a low pass filter (mean)\n freq = (sphase - ephase) / nsamples\n\ - \ freq = self.lpf_freq(freq)\n\n # debugging\n print(f\"\ - Correction for block of {nsamples:2d} samples is \" \\\n f\"phase={sphase:\ - \ .4f} rad and freq={freq*1e3: .4f} milli rad / sample\")\n\n # compute\ - \ block values\n return sphase * np.ones(nsamples) + freq * np.arange(0,\ - \ nsamples)\n\n def work(self, input_items, output_items):\n # FIXME:\ - \ replace class counter with local variable\n self.counter = self.nitems_written(0)\n\ - \n # nicer aliases\n inp = input_items[0]\n out = output_items[0]\n\ - \n # read phase tags\n is_phase = lambda tag: pmt.to_python(tag.key)\ + \ it through a low pass filter (mean)\n phasediff = ephase - sphase\n\ + \n if phasediff > np.pi:\n phasediff -= 2*np.pi\n\n \ + \ elif phasediff < -np.pi:\n phasediff += 2*np.pi\n\n freq\ + \ = phasediff / nsamples\n # freq = self.lpf_freq(freq)\n\n #\ + \ debugging\n print(f\"Correction for block of {nsamples:2d} samples\ + \ is \" \\\n f\"sphase={sphase: .4f} rad and freq={freq*1e3: .4f}\ + \ milli rad / sample\")\n\n # compute block values\n return sphase\ + \ * np.ones(nsamples) + freq * np.arange(0, nsamples)\n\n def work(self,\ + \ input_items, output_items):\n # FIXME: replace class counter with local\ + \ variable\n self.counter = self.nitems_written(0)\n\n # nicer\ + \ aliases\n inp = input_items[0]\n out = output_items[0]\n\n \ + \ # read phase tags\n is_phase = lambda tag: pmt.to_python(tag.key)\ \ == \"phase_est\"\n tags = list(filter(is_phase, self.get_tags_in_window(0,\ \ 0, len(inp))))\n\n if not tags:\n print(f\"There were no\ \ tags in {len(inp)} samples!\")\n out[:] = inp\n return\ @@ -606,9 +571,35 @@ blocks: bus_sink: false bus_source: false bus_structure: null - coordinate: [1088, 1040.0] + coordinate: [1208, 912.0] rotation: 0 state: enabled +- name: epy_block_1 + id: epy_block + parameters: + _source_code: "\"\"\"\nEmbedded Python Blocks:\n\nEach time this file is saved,\ + \ GRC will instantiate the first class it finds\nto get ports and parameters\ + \ of your block. The arguments to __init__ will\nbe the parameters. All of\ + \ them are required to have default values!\n\"\"\"\n\nimport numpy as np\n\ + from gnuradio import gr\n\nnp.set_printoptions(formatter={'int':hex})\n\nclass\ + \ blk(gr.sync_block):\n def __init__(self):\n gr.sync_block.__init__(\n\ + \ self,\n name='Printer',\n in_sig=[np.byte],\n\ + \ out_sig=[]\n )\n\n def work(self, input_items, output_items):\n\ + \ inp = np.array(input_items[0], dtype=np.uint8)\n print(f\"Decoded\ + \ {len(inp)} samples:\\n{inp}\")\n\n return len(inp)\n" + affinity: '' + alias: '' + comment: '' + maxoutbuf: '0' + minoutbuf: '0' + states: + _io_cache: ('Printer', 'blk', [], [('0', 'byte', 1)], [], '', []) + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [920, 1264.0] + rotation: 0 + state: true - name: fir_filter_xxx_1 id: fir_filter_xxx parameters: @@ -625,9 +616,22 @@ blocks: bus_sink: false bus_source: false bus_structure: null - coordinate: [776, 828.0] + coordinate: [776, 692.0] rotation: 0 state: disabled +- name: import_0 + id: import + parameters: + alias: '' + comment: '' + imports: import numpy as np + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [184, 12.0] + rotation: 0 + state: true - name: qtgui_const_sink_x_0 id: qtgui_const_sink_x parameters: @@ -717,7 +721,7 @@ blocks: bus_sink: false bus_source: false bus_structure: null - coordinate: [776, 716.0] + coordinate: [768, 592.0] rotation: 0 state: enabled - name: qtgui_const_sink_x_0_0 @@ -809,7 +813,7 @@ blocks: bus_sink: false bus_source: false bus_structure: null - coordinate: [1368, 1092.0] + coordinate: [1408, 964.0] rotation: 0 state: enabled - name: qtgui_const_sink_x_1 @@ -901,7 +905,7 @@ blocks: bus_sink: false bus_source: false bus_structure: null - coordinate: [1048, 612.0] + coordinate: [1040, 480.0] rotation: 0 state: disabled - name: qtgui_time_sink_x_0 @@ -998,7 +1002,7 @@ blocks: bus_sink: false bus_source: false bus_structure: null - coordinate: [1320, 604.0] + coordinate: [1312, 480.0] rotation: 0 state: disabled - name: qtgui_time_sink_x_0_0 @@ -1057,7 +1061,7 @@ blocks: name: '""' nconnections: '1' size: '1024' - srate: samp_rate + srate: samp_rate / sps stemplot: 'False' style1: '1' style10: '1' @@ -1095,7 +1099,7 @@ blocks: bus_sink: false bus_source: false bus_structure: null - coordinate: [1376, 1284.0] + coordinate: [1376, 1152.0] rotation: 0 state: enabled - name: qtgui_time_sink_x_0_0_0 @@ -1154,7 +1158,7 @@ blocks: name: '""' nconnections: '1' size: '1024' - srate: samp_rate + srate: samp_rate / sps stemplot: 'False' style1: '1' style10: '1' @@ -1192,7 +1196,7 @@ blocks: bus_sink: false bus_source: false bus_structure: null - coordinate: [1048, 940.0] + coordinate: [1072, 788.0] rotation: 0 state: enabled - name: qtgui_time_sink_x_1_0 @@ -1289,7 +1293,7 @@ blocks: bus_sink: false bus_source: false bus_structure: null - coordinate: [808, 452.0] + coordinate: [800, 320.0] rotation: 0 state: enabled - name: qtgui_time_sink_x_1_1 @@ -1386,7 +1390,7 @@ blocks: bus_sink: false bus_source: false bus_structure: null - coordinate: [776, 612.0] + coordinate: [768, 480.0] rotation: 0 state: disabled - name: qtgui_time_sink_x_2 @@ -1483,7 +1487,7 @@ blocks: bus_sink: false bus_source: false bus_structure: null - coordinate: [1480, 708.0] + coordinate: [1488, 580.0] rotation: 0 state: disabled - name: qtgui_time_sink_x_2_0 @@ -1580,30 +1584,7 @@ blocks: bus_sink: false bus_source: false bus_structure: null - coordinate: [1552, 1364.0] - rotation: 0 - state: disabled -- name: root_raised_cosine_filter_0 - id: root_raised_cosine_filter - parameters: - affinity: '' - alias: '' - alpha: excess_bw - comment: '' - decim: '1' - gain: '2' - interp: '1' - maxoutbuf: '0' - minoutbuf: '0' - ntaps: 11*samp_rate - samp_rate: samp_rate - sym_rate: sps * samp_rate - type: fir_filter_ccf - states: - bus_sink: false - bus_source: false - bus_structure: null - coordinate: [496, 180.0] + coordinate: [1552, 1232.0] rotation: 0 state: disabled - name: virtual_sink_0 @@ -1616,7 +1597,7 @@ blocks: bus_sink: false bus_source: false bus_structure: null - coordinate: [1480, 404.0] + coordinate: [1488, 268.0] rotation: 0 state: enabled - name: virtual_sink_3 @@ -1629,7 +1610,7 @@ blocks: bus_sink: false bus_source: false bus_structure: null - coordinate: [1368, 1036.0] + coordinate: [1400, 828.0] rotation: 0 state: true - name: virtual_source_0 @@ -1642,7 +1623,7 @@ blocks: bus_sink: false bus_source: false bus_structure: null - coordinate: [32, 884.0] + coordinate: [16, 748.0] rotation: 0 state: enabled - name: virtual_source_1 @@ -1655,7 +1636,7 @@ blocks: bus_sink: false bus_source: false bus_structure: null - coordinate: [24, 1388.0] + coordinate: [16, 1260.0] rotation: 0 state: true @@ -1668,18 +1649,16 @@ connections: - [blocks_multiply_const_vxx_0, '0', qtgui_time_sink_x_2, '0'] - [blocks_multiply_const_vxx_0_0, '0', qtgui_time_sink_x_2_0, '0'] - [blocks_null_source_0, '0', blocks_stream_mux_0, '0'] +- [blocks_repack_bits_bb_0, '0', epy_block_1, '0'] - [blocks_stream_mux_0, '0', digital_constellation_modulator_0, '0'] -- [blocks_stream_mux_1, '0', channels_channel_model_0, '0'] - [blocks_throttle_0, '0', virtual_sink_0, '0'] - [blocks_vector_source_x_0, '0', blocks_stream_mux_0, '1'] -- [blocks_vector_source_x_1, '0', root_raised_cosine_filter_0, '0'] - [channels_channel_model_0, '0', blocks_throttle_0, '0'] - [digital_cma_equalizer_cc_0, '0', digital_corr_est_cc_0, '0'] - [digital_cma_equalizer_cc_0, '0', fir_filter_xxx_1, '0'] - [digital_cma_equalizer_cc_0, '0', qtgui_const_sink_x_0, '0'] - [digital_cma_equalizer_cc_0, '0', qtgui_time_sink_x_1_1, '0'] -- [digital_constellation_decoder_cb_0, '0', blocks_vector_sink_x_0, '0'] -- [digital_constellation_modulator_0, '0', blocks_stream_mux_1, '1'] +- [digital_constellation_decoder_cb_0, '0', digital_map_bb_0, '0'] - [digital_constellation_modulator_0, '0', channels_channel_model_0, '0'] - [digital_constellation_modulator_0, '0', qtgui_time_sink_x_1_0, '0'] - [digital_corr_est_cc_0, '0', digital_costas_loop_cc_0, '0'] @@ -1687,12 +1666,12 @@ connections: - [digital_corr_est_cc_0, '0', qtgui_time_sink_x_0_0_0, '0'] - [digital_corr_est_cc_0, '1', blocks_complex_to_magphase_0_0, '0'] - [digital_costas_loop_cc_0, '0', qtgui_const_sink_x_0_0, '1'] +- [digital_map_bb_0, '0', blocks_repack_bits_bb_0, '0'] - [digital_pfb_clock_sync_xxx_0, '0', digital_cma_equalizer_cc_0, '0'] - [epy_block_0, '0', qtgui_const_sink_x_0_0, '0'] - [epy_block_0, '0', virtual_sink_3, '0'] - [fir_filter_xxx_1, '0', blocks_complex_to_magphase_0, '0'] - [fir_filter_xxx_1, '0', qtgui_const_sink_x_1, '0'] -- [root_raised_cosine_filter_0, '0', blocks_stream_mux_1, '0'] - [virtual_source_0, '0', digital_pfb_clock_sync_xxx_0, '0'] - [virtual_source_1, '0', digital_constellation_decoder_cb_0, '0'] diff --git a/tests/correlator/correlator.py b/tests/correlator/correlator.py index 50283c0..255010a 100755 --- a/tests/correlator/correlator.py +++ b/tests/correlator/correlator.py @@ -35,6 +35,8 @@ from argparse import ArgumentParser from gnuradio.eng_arg import eng_float, intx from gnuradio import eng_notation import epy_block_0 +import epy_block_1 +import numpy as np from gnuradio import qtgui @@ -77,13 +79,12 @@ class correlator(gr.top_block, Qt.QWidget): self.sps = sps = 4 self.nfilts = nfilts = 32 self.excess_bw = excess_bw = .35 - self.timing_loop_bw = timing_loop_bw = 2 * 3.141592653589793 / 100 - self.testvec = testvec = [31, 53] + [0x12, 0xe3, 0x9b, 0xee, 0x84, 0x23, 0x41, 0xf3] - self.samp_rate = samp_rate = 32000 + self.timing_loop_bw = timing_loop_bw = 2 * np.pi / 100 + self.testvec = testvec = [0x1f, 0x35] + [0x12, 0xe3, 0x9b, 0xee, 0x84, 0x23, 0x41, 0xf3] + self.samp_rate = samp_rate = int(1.5e6) self.rrc_taps = rrc_taps = firdes.root_raised_cosine(nfilts, nfilts, 1.0/float(sps), excess_bw, 45*nfilts) self.revconj_access_code_symbols = revconj_access_code_symbols = [(1.4142135623730951+1.4142135623730951j), (1.4142135623730951+1.4142135623730951j), (1.4142135623730951-1.4142135623730951j), (-1.4142135623730951+1.4142135623730951j), (1.4142135623730951-1.4142135623730951j), (1.4142135623730951-1.4142135623730951j), (1.4142135623730951+1.4142135623730951j), (-1.4142135623730951+1.4142135623730951j)] self.const = const = digital.constellation_qpsk().base() - self.access_code_symbols_sps = access_code_symbols_sps = [(1.4142197+1.4142197j), (1.4142197+1.4142197j), (1.4142197+1.4142197j), (1.4142197+1.4142197j), (1.4142197-1.4142197j), (1.4142197-1.4142197j), (1.4142197-1.4142197j), (1.4142197-1.4142197j), (1.4142197-1.4142197j), (1.4142197-1.4142197j), (1.4142197-1.4142197j), (1.4142197-1.4142197j), (-1.4142197-1.4142197j), (-1.4142197-1.4142197j), (-1.4142197-1.4142197j), (-1.4142197-1.4142197j), (1.4142197-1.4142197j), (1.4142197-1.4142197j), (1.4142197-1.4142197j), (1.4142197-1.4142197j), (1.4142197+1.4142197j), (1.4142197+1.4142197j), (1.4142197+1.4142197j), (1.4142197+1.4142197j), (1.4142197+1.4142197j), (1.4142197+1.4142197j), (1.4142197+1.4142197j), (1.4142197+1.4142197j)] self.access_code_symbols = access_code_symbols = [(-1.4142135623730951-1.4142135623730951j), (1.4142135623730951-1.4142135623730951j), (1.4142135623730951+1.4142135623730951j), (1.4142135623730951+1.4142135623730951j), (-1.4142135623730951-1.4142135623730951j), (1.4142135623730951+1.4142135623730951j), (1.4142135623730951-1.4142135623730951j), (1.4142135623730951-1.4142135623730951j)] ################################################## @@ -145,7 +146,7 @@ class correlator(gr.top_block, Qt.QWidget): self.top_grid_layout.setColumnStretch(c, 1) self.qtgui_time_sink_x_0_0_0 = qtgui.time_sink_c( 1024, #size - samp_rate, #samp_rate + samp_rate / sps, #samp_rate "", #name 1 #number of inputs ) @@ -195,7 +196,7 @@ class correlator(gr.top_block, Qt.QWidget): self.top_grid_layout.addWidget(self._qtgui_time_sink_x_0_0_0_win) self.qtgui_time_sink_x_0_0 = qtgui.time_sink_f( 1024, #size - samp_rate, #samp_rate + samp_rate / sps, #samp_rate "", #name 1 #number of inputs ) @@ -328,6 +329,7 @@ class correlator(gr.top_block, Qt.QWidget): self.top_grid_layout.setRowStretch(r, 1) for c in range(1, 2): self.top_grid_layout.setColumnStretch(c, 1) + self.epy_block_1 = epy_block_1.blk() self.epy_block_0 = epy_block_0.blk() self.digital_pfb_clock_sync_xxx_0 = digital.pfb_clock_sync_ccf(sps, timing_loop_bw, rrc_taps, nfilts, 16, 1.5, 1) self.digital_costas_loop_cc_0 = digital.costas_loop_cc(2 * 3.141592653589793 / 100, 4, False) @@ -343,16 +345,16 @@ class correlator(gr.top_block, Qt.QWidget): self.digital_constellation_decoder_cb_0 = digital.constellation_decoder_cb(const) self.digital_cma_equalizer_cc_0 = digital.cma_equalizer_cc(15, 1, .002, 1) self.channels_channel_model_0 = channels.channel_model( - noise_voltage=0.2, + noise_voltage=0.01, frequency_offset=0.0001, epsilon=1.0, - taps=[-1.4 + .4j], + taps=[np.exp(1j * 30 / 180 * np.pi)], noise_seed=243, block_tags=False) - self.blocks_vector_source_x_0 = blocks.vector_source_b(testvec * 1600, True, 1, []) - self.blocks_vector_sink_x_0 = blocks.vector_sink_b(1, 1024) + self.blocks_vector_source_x_0 = blocks.vector_source_b(testvec * 500, True, 1, []) self.blocks_throttle_0 = blocks.throttle(gr.sizeof_gr_complex*1, samp_rate,True) - self.blocks_stream_mux_0 = blocks.stream_mux(gr.sizeof_char*1, [10, len(testvec)]) + self.blocks_stream_mux_0 = blocks.stream_mux(gr.sizeof_char*1, [5, len(testvec)]) + self.blocks_repack_bits_bb_0 = blocks.repack_bits_bb(2, 8, "", False, gr.GR_MSB_FIRST) self.blocks_null_source_0 = blocks.null_source(gr.sizeof_char*1) self.blocks_null_sink_3 = blocks.null_sink(gr.sizeof_float*1) self.blocks_complex_to_magphase_0_0 = blocks.complex_to_magphase(1) @@ -365,13 +367,14 @@ class correlator(gr.top_block, Qt.QWidget): self.connect((self.blocks_complex_to_magphase_0_0, 1), (self.blocks_null_sink_3, 0)) self.connect((self.blocks_complex_to_magphase_0_0, 0), (self.qtgui_time_sink_x_0_0, 0)) self.connect((self.blocks_null_source_0, 0), (self.blocks_stream_mux_0, 0)) + self.connect((self.blocks_repack_bits_bb_0, 0), (self.epy_block_1, 0)) self.connect((self.blocks_stream_mux_0, 0), (self.digital_constellation_modulator_0, 0)) self.connect((self.blocks_throttle_0, 0), (self.digital_pfb_clock_sync_xxx_0, 0)) self.connect((self.blocks_vector_source_x_0, 0), (self.blocks_stream_mux_0, 1)) self.connect((self.channels_channel_model_0, 0), (self.blocks_throttle_0, 0)) self.connect((self.digital_cma_equalizer_cc_0, 0), (self.digital_corr_est_cc_0, 0)) self.connect((self.digital_cma_equalizer_cc_0, 0), (self.qtgui_const_sink_x_0, 0)) - self.connect((self.digital_constellation_decoder_cb_0, 0), (self.blocks_vector_sink_x_0, 0)) + self.connect((self.digital_constellation_decoder_cb_0, 0), (self.blocks_repack_bits_bb_0, 0)) self.connect((self.digital_constellation_modulator_0, 0), (self.channels_channel_model_0, 0)) self.connect((self.digital_constellation_modulator_0, 0), (self.qtgui_time_sink_x_1_0, 0)) self.connect((self.digital_corr_est_cc_0, 1), (self.blocks_complex_to_magphase_0_0, 0)) @@ -395,6 +398,8 @@ class correlator(gr.top_block, Qt.QWidget): def set_sps(self, sps): self.sps = sps self.set_rrc_taps(firdes.root_raised_cosine(self.nfilts, self.nfilts, 1.0/float(self.sps), self.excess_bw, 45*self.nfilts)) + self.qtgui_time_sink_x_0_0.set_samp_rate(self.samp_rate / self.sps) + self.qtgui_time_sink_x_0_0_0.set_samp_rate(self.samp_rate / self.sps) def get_nfilts(self): return self.nfilts @@ -422,7 +427,7 @@ class correlator(gr.top_block, Qt.QWidget): def set_testvec(self, testvec): self.testvec = testvec - self.blocks_vector_source_x_0.set_data(self.testvec * 1600, []) + self.blocks_vector_source_x_0.set_data(self.testvec * 500, []) def get_samp_rate(self): return self.samp_rate @@ -430,8 +435,8 @@ class correlator(gr.top_block, Qt.QWidget): def set_samp_rate(self, samp_rate): self.samp_rate = samp_rate self.blocks_throttle_0.set_sample_rate(self.samp_rate) - self.qtgui_time_sink_x_0_0.set_samp_rate(self.samp_rate) - self.qtgui_time_sink_x_0_0_0.set_samp_rate(self.samp_rate) + self.qtgui_time_sink_x_0_0.set_samp_rate(self.samp_rate / self.sps) + self.qtgui_time_sink_x_0_0_0.set_samp_rate(self.samp_rate / self.sps) self.qtgui_time_sink_x_1_0.set_samp_rate(self.samp_rate) def get_rrc_taps(self): @@ -453,12 +458,6 @@ class correlator(gr.top_block, Qt.QWidget): def set_const(self, const): self.const = const - def get_access_code_symbols_sps(self): - return self.access_code_symbols_sps - - def set_access_code_symbols_sps(self, access_code_symbols_sps): - self.access_code_symbols_sps = access_code_symbols_sps - def get_access_code_symbols(self): return self.access_code_symbols diff --git a/tests/correlator/epy_block_0.py b/tests/correlator/epy_block_0.py index e7599c9..a581a3a 100644 --- a/tests/correlator/epy_block_0.py +++ b/tests/correlator/epy_block_0.py @@ -25,7 +25,7 @@ class blk(gr.sync_block): # filter to avoid werid jumps in the correction. to do that, there are # two buffers with an index self.index = 0 - self.length = 7 + self.length = 5 self.freq = np.zeros(self.length) def lpf_freq(self, new_sample): @@ -46,12 +46,20 @@ class blk(gr.sync_block): # compute frequency offset between start and end # and run it through a low pass filter (mean) - freq = (sphase - ephase) / nsamples - freq = self.lpf_freq(freq) + phasediff = ephase - sphase + + if phasediff > np.pi: + phasediff -= 2*np.pi + + elif phasediff < -np.pi: + phasediff += 2*np.pi + + freq = phasediff / nsamples + # freq = self.lpf_freq(freq) # debugging print(f"Correction for block of {nsamples:2d} samples is " \ - f"phase={sphase: .4f} rad and freq={freq*1e3: .4f} milli rad / sample") + f"sphase={sphase: .4f} rad and freq={freq*1e3: .4f} milli rad / sample") # compute block values return sphase * np.ones(nsamples) + freq * np.arange(0, nsamples) diff --git a/tests/correlator/epy_block_1.py b/tests/correlator/epy_block_1.py new file mode 100644 index 0000000..d30c2eb --- /dev/null +++ b/tests/correlator/epy_block_1.py @@ -0,0 +1,27 @@ +""" +Embedded Python Blocks: + +Each time this file is saved, GRC will instantiate the first class it finds +to get ports and parameters of your block. The arguments to __init__ will +be the parameters. All of them are required to have default values! +""" + +import numpy as np +from gnuradio import gr + +np.set_printoptions(formatter={'int':hex}) + +class blk(gr.sync_block): + def __init__(self): + gr.sync_block.__init__( + self, + name='Printer', + in_sig=[np.byte], + out_sig=[] + ) + + def work(self, input_items, output_items): + inp = np.array(input_items[0], dtype=np.uint8) + print(f"Decoded {len(inp)} samples:\n{inp}") + + return len(inp) -- cgit v1.2.1 From cafce753722ec8d396cadfdf991b5c6f5a18dc12 Mon Sep 17 00:00:00 2001 From: sara Date: Fri, 3 Dec 2021 20:46:20 +0100 Subject: BER Block Fertig gestellt --- tests/BER/Bit_error.grc | 66 ++++++++++++++++++++++++++++++++++++++--- tests/BER/Test_Bit_Errorrate.py | 26 +++++++++++++--- 2 files changed, 84 insertions(+), 8 deletions(-) (limited to 'tests') diff --git a/tests/BER/Bit_error.grc b/tests/BER/Bit_error.grc index 04c624b..1a1a891 100644 --- a/tests/BER/Bit_error.grc +++ b/tests/BER/Bit_error.grc @@ -56,6 +56,49 @@ blocks: coordinate: [216, 396.0] rotation: 0 state: enabled +- name: vlen + id: variable + parameters: + comment: '' + value: '10' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [216, 196.0] + rotation: 0 + state: true +- name: wrong + id: variable + parameters: + comment: '' + value: list(np.random.randint(0, 255, dtype=np.uint8, size=10)) + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [216, 460.0] + rotation: 0 + state: true +- name: blocks_throttle_0 + id: blocks_throttle + parameters: + affinity: '' + alias: '' + comment: '' + ignoretag: 'True' + maxoutbuf: '0' + minoutbuf: '0' + samples_per_second: samp_rate + type: byte + vlen: vlen + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [448, 292.0] + rotation: 0 + state: true - name: blocks_vector_source_x_0 id: blocks_vector_source_x parameters: @@ -67,8 +110,8 @@ blocks: repeat: 'True' tags: '[]' type: byte - vector: testvec * 1600 - vlen: '1' + vector: testvec + list(np.random.randint(0, 255, dtype=np.uint8, size=10)) + vlen: vlen states: bus_sink: false bus_source: false @@ -83,16 +126,31 @@ blocks: alias: '' comment: '' vgl: testvec + vlen: vlen + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [672, 292.0] + rotation: 0 + state: true +- name: import_0 + id: import + parameters: + alias: '' + comment: '' + imports: import numpy as np states: bus_sink: false bus_source: false bus_structure: null - coordinate: [704, 296.0] + coordinate: [328, 20.0] rotation: 0 state: true connections: -- [blocks_vector_source_x_0, '0', fadingui_ber_0, '0'] +- [blocks_throttle_0, '0', fadingui_ber_0, '0'] +- [blocks_vector_source_x_0, '0', blocks_throttle_0, '0'] metadata: file_format: 1 diff --git a/tests/BER/Test_Bit_Errorrate.py b/tests/BER/Test_Bit_Errorrate.py index 4022997..a861ae7 100755 --- a/tests/BER/Test_Bit_Errorrate.py +++ b/tests/BER/Test_Bit_Errorrate.py @@ -31,6 +31,7 @@ from argparse import ArgumentParser from gnuradio.eng_arg import eng_float, intx from gnuradio import eng_notation import fadingui +import numpy as np from gnuradio import qtgui @@ -70,21 +71,25 @@ class Test_Bit_Errorrate(gr.top_block, Qt.QWidget): ################################################## # Variables ################################################## + self.wrong = wrong = list(np.random.randint(0, 255, dtype=np.uint8, size=10)) + self.vlen = vlen = 10 self.testvec = testvec = [31, 53] + [0x12, 0xe3, 0x9b, 0xee, 0x84, 0x23, 0x41, 0xf3] self.samp_rate = samp_rate = 32000 ################################################## # Blocks ################################################## - self.fadingui_ber_0 = fadingui.ber(vgl=testvec) - self.blocks_vector_source_x_0 = blocks.vector_source_b(testvec * 1600, True, 1, []) + self.fadingui_ber_0 = fadingui.ber(vgl=testvec, vlen=vlen) + self.blocks_vector_source_x_0 = blocks.vector_source_b(testvec + list(np.random.randint(0, 255, dtype=np.uint8, size=10)), True, vlen, []) + self.blocks_throttle_0 = blocks.throttle(gr.sizeof_char*vlen, samp_rate,True) ################################################## # Connections ################################################## - self.connect((self.blocks_vector_source_x_0, 0), (self.fadingui_ber_0, 0)) + self.connect((self.blocks_throttle_0, 0), (self.fadingui_ber_0, 0)) + self.connect((self.blocks_vector_source_x_0, 0), (self.blocks_throttle_0, 0)) def closeEvent(self, event): @@ -92,18 +97,31 @@ class Test_Bit_Errorrate(gr.top_block, Qt.QWidget): self.settings.setValue("geometry", self.saveGeometry()) event.accept() + def get_wrong(self): + return self.wrong + + def set_wrong(self, wrong): + self.wrong = wrong + + def get_vlen(self): + return self.vlen + + def set_vlen(self, vlen): + self.vlen = vlen + def get_testvec(self): return self.testvec def set_testvec(self, testvec): self.testvec = testvec - self.blocks_vector_source_x_0.set_data(self.testvec * 1600, []) + self.blocks_vector_source_x_0.set_data(self.testvec + list(np.random.randint(0, 255, dtype=np.uint8, size=10)), []) def get_samp_rate(self): return self.samp_rate def set_samp_rate(self, samp_rate): self.samp_rate = samp_rate + self.blocks_throttle_0.set_sample_rate(self.samp_rate) -- cgit v1.2.1 From eb385ffb0c3c41d7097fb74260f3a39c2aaeb926 Mon Sep 17 00:00:00 2001 From: Nao Pross Date: Fri, 3 Dec 2021 21:55:18 +0100 Subject: Remove frequency LPF and clean up --- tests/correlator/correlator.grc | 94 ++++++++++++++++++++--------------------- tests/correlator/epy_block_0.py | 40 ++++++------------ 2 files changed, 58 insertions(+), 76 deletions(-) (limited to 'tests') diff --git a/tests/correlator/correlator.grc b/tests/correlator/correlator.grc index 0f82f27..beea007 100644 --- a/tests/correlator/correlator.grc +++ b/tests/correlator/correlator.grc @@ -193,7 +193,7 @@ blocks: bus_sink: false bus_source: false bus_structure: null - coordinate: [1032, 1176.0] + coordinate: [1080, 1176.0] rotation: 0 state: enabled - name: blocks_multiply_const_vxx_0 @@ -505,36 +505,34 @@ blocks: parameters: _source_code: "import pmt\n\nimport numpy as np\nfrom gnuradio import gr\n\n\n\ class blk(gr.sync_block):\n def __init__(self):\n gr.sync_block.__init__(\n\ - \ self,\n name='Phase Lock',\n in_sig=[np.complex64],\n\ - \ out_sig=[np.complex64]\n )\n\n # we need to keep\ - \ track of the aboslute number of samples that have\n # been processed,\ - \ because tags have an absolute offset\n self.counter: np.uint64 = 0\n\ - \n # because we do block processing, we need to keep track of the last\ - \ tag\n # of the previous block to correct the first values of the next\ - \ block\n self.last = None\n\n # both the phase and frequency\ - \ corrections should go through a low pass\n # filter to avoid werid\ - \ jumps in the correction. to do that, there are\n # two buffers with\ - \ an index\n self.index = 0\n self.length = 5\n self.freq\ - \ = np.zeros(self.length)\n\n def lpf_freq(self, new_sample):\n #\ - \ save new sample\n self.freq[self.index] = new_sample\n # increment\ - \ index\n self.index = (self.index + 1) % self.length\n\n return\ - \ np.sum(self.freq) / self.length\n\n def block_phase(self, start, end):\n\ - \ # compute number of samples in block\n nsamples = end.offset\ - \ - start.offset\n\n # unpack pmt values into start and end phase\n \ - \ sphase = pmt.to_python(start.value)\n ephase = pmt.to_python(end.value)\n\ - \n # compute frequency offset between start and end\n # and run\ - \ it through a low pass filter (mean)\n phasediff = ephase - sphase\n\ - \n if phasediff > np.pi:\n phasediff -= 2*np.pi\n\n \ - \ elif phasediff < -np.pi:\n phasediff += 2*np.pi\n\n freq\ - \ = phasediff / nsamples\n # freq = self.lpf_freq(freq)\n\n #\ - \ debugging\n print(f\"Correction for block of {nsamples:2d} samples\ - \ is \" \\\n f\"sphase={sphase: .4f} rad and freq={freq*1e3: .4f}\ - \ milli rad / sample\")\n\n # compute block values\n return sphase\ - \ * np.ones(nsamples) + freq * np.arange(0, nsamples)\n\n def work(self,\ - \ input_items, output_items):\n # FIXME: replace class counter with local\ - \ variable\n self.counter = self.nitems_written(0)\n\n # nicer\ - \ aliases\n inp = input_items[0]\n out = output_items[0]\n\n \ - \ # read phase tags\n is_phase = lambda tag: pmt.to_python(tag.key)\ + \ self,\n name='Phase and Frequency Correction',\n \ + \ in_sig=[np.complex64],\n out_sig=[np.complex64]\n \ + \ )\n\n # tags should not be propagated, we then output our own tags\n\ + \ self.set_tag_propagation_policy(gr.TPP_DONT)\n\n # because we\ + \ do block processing, we need to keep track of the last tag\n # of the\ + \ previous block to correct the first values of the next block\n self.last\ + \ = None\n self.lastfreq = 0\n\n def block_phase(self, start, end):\n\ + \ \"\"\"\n Compute a vector for the phase and frequency correction\ + \ for the samples\n between two tags (start and end).\n\n @param\ + \ start Tag where the samples should start to be corrected\n @param end\ + \ Tag where to stop correcting\n\n @return A vector of phase values\ + \ for each sample. If we call the ouput\n `phase' to correct\ + \ the samples between the start and end tags,\n TODO: finish\n\ + \ \"\"\"\n # compute number of samples in block\n nsamples\ + \ = end.offset - start.offset\n\n # unpack pmt values into start and\ + \ end phase\n sphase = pmt.to_python(start.value)\n ephase = pmt.to_python(end.value)\n\ + \n # compute frequency offset between start and end\n phasediff\ + \ = ephase - sphase\n\n if phasediff > np.pi:\n phasediff\ + \ -= 2*np.pi\n\n elif phasediff < -np.pi:\n phasediff += 2*np.pi\n\ + \n freq = phasediff / nsamples\n\n # save this one for the last\ + \ block (see variable `end' in self.work)\n self.lastfreq = freq\n\n\ + \ # debugging\n print(f\"Correction for block of {nsamples:2d}\ + \ samples is \" \\\n f\"sphase={sphase: .4f} rad and freq={freq*1e3:\ + \ .4f} milli rad / sample\")\n\n # compute block values\n return\ + \ sphase * np.ones(nsamples) + freq * np.arange(0, nsamples)\n\n def work(self,\ + \ input_items, output_items):\n counter = self.nitems_written(0)\n\n\ + \ # nicer aliases\n inp = input_items[0]\n out = output_items[0]\n\ + \n # read phase tags\n is_phase = lambda tag: pmt.to_python(tag.key)\ \ == \"phase_est\"\n tags = list(filter(is_phase, self.get_tags_in_window(0,\ \ 0, len(inp))))\n\n if not tags:\n print(f\"There were no\ \ tags in {len(inp)} samples!\")\n out[:] = inp\n return\ @@ -546,32 +544,32 @@ blocks: \ (start, end) in pairs ]\n middle = np.concatenate(blocks) if blocks\ \ else []\n\n # compute values at the end, we do not have informations\ \ about the future\n # but we can use the frequency of the last block\ - \ to approximate\n nback = len(inp) - (tags[-1].offset - self.counter)\n\ - \ print(f\"Processing {nback} samples at the back of the buffer\")\n\ - \ endfreq = self.lpf_freq(self.freq[-1])\n end = np.ones(nback)\ - \ * pmt.to_python(tags[-1].value) + endfreq * np.arange(0, nback)\n\n \ - \ # compute the \"start\", using the last tag from the previous call\n \ - \ nfront = tags[0].offset - self.counter\n print(f\"Processing {nfront}\ - \ samples at the front of the buffer\")\n start = self.block_phase(self.last,\ - \ tags[0])[-nfront:] \\\n if self.last and nfront else np.zeros(nfront)\n\ - \n # compute correction\n correction = np.exp(-1j * np.concatenate([start,\ + \ to approximate\n nback = len(inp) - (tags[-1].offset - counter)\n \ + \ print(f\"Processing {nback} samples at the back of the buffer\")\n \ + \ end = np.ones(nback) * pmt.to_python(tags[-1].value) \\\n \ + \ + self.lastfreq * np.arange(0, nback)\n\n # compute the \"start\"\ + , using the last tag from the previous call\n nfront = tags[0].offset\ + \ - counter\n print(f\"Processing {nfront} samples at the front of the\ + \ buffer\")\n start = self.block_phase(self.last, tags[0])[-nfront:]\ + \ \\\n if self.last and nfront else np.zeros(nfront)\n\n \ + \ # compute correction\n correction = np.exp(-1j * np.concatenate([start,\ \ middle, end]))\n length = len(correction)\n\n # write outputs\n\ - \ out[:length] = inp[:length] * correction\n self.counter += len(inp)\n\ - \n # save last tag for next call\n self.last = tags[-1]\n\n \ - \ # FIXME: should return `length' but then the last sample is not\n \ - \ # included and self.last does something weird\n return len(out)\n" + \ out[:length] = inp[:length] * correction\n\n # save last tag\ + \ for next call\n self.last = tags[-1]\n\n # FIXME: should return\ + \ `length' but then the last sample is not\n # included and self.last\ + \ does something weird\n return len(out)\n" affinity: '' alias: '' comment: '' maxoutbuf: '0' minoutbuf: '0' states: - _io_cache: ('Phase Lock', 'blk', [], [('0', 'complex', 1)], [('0', 'complex', - 1)], '', []) + _io_cache: ('Phase and Frequency Correction', 'blk', [], [('0', 'complex', 1)], + [('0', 'complex', 1)], '', []) bus_sink: false bus_source: false bus_structure: null - coordinate: [1208, 912.0] + coordinate: [1072, 912.0] rotation: 0 state: enabled - name: epy_block_1 @@ -1099,7 +1097,7 @@ blocks: bus_sink: false bus_source: false bus_structure: null - coordinate: [1376, 1152.0] + coordinate: [1376, 1156.0] rotation: 0 state: enabled - name: qtgui_time_sink_x_0_0_0 diff --git a/tests/correlator/epy_block_0.py b/tests/correlator/epy_block_0.py index a581a3a..ddae02a 100644 --- a/tests/correlator/epy_block_0.py +++ b/tests/correlator/epy_block_0.py @@ -8,33 +8,18 @@ class blk(gr.sync_block): def __init__(self): gr.sync_block.__init__( self, - name='Phase Lock', + name='Phase and Frequency Correction', in_sig=[np.complex64], out_sig=[np.complex64] ) - # we need to keep track of the aboslute number of samples that have - # been processed, because tags have an absolute offset - self.counter: np.uint64 = 0 + # tags should not be propagated, we then output our own tags + self.set_tag_propagation_policy(gr.TPP_DONT) # because we do block processing, we need to keep track of the last tag # of the previous block to correct the first values of the next block self.last = None - - # both the phase and frequency corrections should go through a low pass - # filter to avoid werid jumps in the correction. to do that, there are - # two buffers with an index - self.index = 0 - self.length = 5 - self.freq = np.zeros(self.length) - - def lpf_freq(self, new_sample): - # save new sample - self.freq[self.index] = new_sample - # increment index - self.index = (self.index + 1) % self.length - - return np.sum(self.freq) / self.length + self.lastfreq = 0 def block_phase(self, start, end): # compute number of samples in block @@ -45,7 +30,6 @@ class blk(gr.sync_block): ephase = pmt.to_python(end.value) # compute frequency offset between start and end - # and run it through a low pass filter (mean) phasediff = ephase - sphase if phasediff > np.pi: @@ -55,7 +39,9 @@ class blk(gr.sync_block): phasediff += 2*np.pi freq = phasediff / nsamples - # freq = self.lpf_freq(freq) + + # save this one for the last block (see variable `end' in self.work) + self.lastfreq = freq # debugging print(f"Correction for block of {nsamples:2d} samples is " \ @@ -65,8 +51,7 @@ class blk(gr.sync_block): return sphase * np.ones(nsamples) + freq * np.arange(0, nsamples) def work(self, input_items, output_items): - # FIXME: replace class counter with local variable - self.counter = self.nitems_written(0) + counter = self.nitems_written(0) # nicer aliases inp = input_items[0] @@ -93,13 +78,13 @@ class blk(gr.sync_block): # compute values at the end, we do not have informations about the future # but we can use the frequency of the last block to approximate - nback = len(inp) - (tags[-1].offset - self.counter) + nback = len(inp) - (tags[-1].offset - counter) print(f"Processing {nback} samples at the back of the buffer") - endfreq = self.lpf_freq(self.freq[-1]) - end = np.ones(nback) * pmt.to_python(tags[-1].value) + endfreq * np.arange(0, nback) + end = np.ones(nback) * pmt.to_python(tags[-1].value) \ + + self.lastfreq * np.arange(0, nback) # compute the "start", using the last tag from the previous call - nfront = tags[0].offset - self.counter + nfront = tags[0].offset - counter print(f"Processing {nfront} samples at the front of the buffer") start = self.block_phase(self.last, tags[0])[-nfront:] \ if self.last and nfront else np.zeros(nfront) @@ -110,7 +95,6 @@ class blk(gr.sync_block): # write outputs out[:length] = inp[:length] * correction - self.counter += len(inp) # save last tag for next call self.last = tags[-1] -- cgit v1.2.1 From 2d02a9787d3bbd7320f23a3c65ee8e8ed0369c1e Mon Sep 17 00:00:00 2001 From: Nao Pross Date: Fri, 3 Dec 2021 22:19:57 +0100 Subject: Replace DearPyGui Sink with Network Sink --- tests/sockets/send.py | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 tests/sockets/send.py (limited to 'tests') diff --git a/tests/sockets/send.py b/tests/sockets/send.py new file mode 100644 index 0000000..87faf5d --- /dev/null +++ b/tests/sockets/send.py @@ -0,0 +1,21 @@ +import socket +from urllib.parse import urlparse + +import numpy as np + +remote = "upd://localhost:31415" +url = urlparse(remote) + +print(url.hostname) +print(url.port) + +sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) +sock.connect((url.hostname, url.port)) + +# sent some text +sock.send(bytes("hello", "ascii")) + +arr = np.arange(0, 10) +print(arr) + +sock.send(arr.tobytes()) -- cgit v1.2.1 From 13a2fda61a5cb1e6d3f807d0acda42c45e128434 Mon Sep 17 00:00:00 2001 From: Nao Pross Date: Fri, 3 Dec 2021 23:46:33 +0100 Subject: Fix correlation peak detector and add frame_start tags --- tests/correlator/correlator.grc | 502 ++++++++++------------------------------ tests/correlator/correlator.py | 17 +- tests/correlator/epy_block_0.py | 32 ++- 3 files changed, 157 insertions(+), 394 deletions(-) (limited to 'tests') diff --git a/tests/correlator/correlator.grc b/tests/correlator/correlator.grc index beea007..c34e5a9 100644 --- a/tests/correlator/correlator.grc +++ b/tests/correlator/correlator.grc @@ -36,15 +36,15 @@ blocks: id: variable parameters: comment: '' - value: '[(-1.4142135623730951-1.4142135623730951j), (1.4142135623730951-1.4142135623730951j), + value: .5 * np.array([(-1.4142135623730951-1.4142135623730951j), (1.4142135623730951-1.4142135623730951j), (1.4142135623730951+1.4142135623730951j), (1.4142135623730951+1.4142135623730951j), (-1.4142135623730951-1.4142135623730951j), (1.4142135623730951+1.4142135623730951j), - (1.4142135623730951-1.4142135623730951j), (1.4142135623730951-1.4142135623730951j)]' + (1.4142135623730951-1.4142135623730951j), (1.4142135623730951-1.4142135623730951j)]) states: bus_sink: false bus_source: false bus_structure: null - coordinate: [768, 1016.0] + coordinate: [792, 788.0] rotation: 0 state: enabled - name: const @@ -101,7 +101,7 @@ blocks: bus_sink: false bus_source: false bus_structure: null - coordinate: [48, 440.0] + coordinate: [784, 1052.0] rotation: 0 state: enabled - name: rrc_taps @@ -164,22 +164,6 @@ blocks: coordinate: [224, 936.0] rotation: 0 state: enabled -- name: blocks_complex_to_magphase_0 - id: blocks_complex_to_magphase - parameters: - affinity: '' - alias: '' - comment: '' - maxoutbuf: '0' - minoutbuf: '0' - vlen: '1' - states: - bus_sink: false - bus_source: false - bus_structure: null - coordinate: [1040, 568.0] - rotation: 0 - state: disabled - name: blocks_complex_to_magphase_0_0 id: blocks_complex_to_magphase parameters: @@ -193,27 +177,9 @@ blocks: bus_sink: false bus_source: false bus_structure: null - coordinate: [1080, 1176.0] + coordinate: [1056, 984.0] rotation: 0 state: enabled -- name: blocks_multiply_const_vxx_0 - id: blocks_multiply_const_vxx - parameters: - affinity: '' - alias: '' - comment: '' - const: 180 / 3.141592653589793 - maxoutbuf: '0' - minoutbuf: '0' - type: float - vlen: '1' - states: - bus_sink: false - bus_source: false - bus_structure: null - coordinate: [1288, 596.0] - rotation: 0 - state: disabled - name: blocks_multiply_const_vxx_0_0 id: blocks_multiply_const_vxx parameters: @@ -229,7 +195,7 @@ blocks: bus_sink: false bus_source: false bus_structure: null - coordinate: [1376, 1248.0] + coordinate: [1312, 1076.0] rotation: 0 state: disabled - name: blocks_null_sink_3 @@ -246,7 +212,7 @@ blocks: bus_sink: false bus_source: false bus_structure: null - coordinate: [1376, 1304.0] + coordinate: [1360, 1016.0] rotation: 0 state: true - name: blocks_null_source_0 @@ -294,7 +260,7 @@ blocks: affinity: '' alias: '' comment: '' - lengths: '[5, len(testvec)]' + lengths: '[0, len(testvec)]' maxoutbuf: '0' minoutbuf: '0' num_inputs: '2' @@ -307,6 +273,43 @@ blocks: coordinate: [288, 256.0] rotation: 0 state: enabled +- name: blocks_tag_debug_0 + id: blocks_tag_debug + parameters: + affinity: '' + alias: '' + comment: '' + display: 'True' + filter: '""' + name: '' + num_inputs: '1' + type: byte + vlen: '1' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [1208, 1164.0] + rotation: 0 + state: disabled +- name: blocks_tagged_stream_align_0 + id: blocks_tagged_stream_align + parameters: + affinity: '' + alias: '' + comment: '' + lengthtagname: frame_start + maxoutbuf: '0' + minoutbuf: '0' + type: byte + vlen: '1' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [928, 1260.0] + rotation: 0 + state: true - name: blocks_throttle_0 id: blocks_throttle parameters: @@ -354,7 +357,7 @@ blocks: block_tags: 'False' comment: '' epsilon: '1.0' - freq_offset: '0.0001' + freq_offset: '0.002' maxoutbuf: '0' minoutbuf: '0' noise_voltage: '0.01' @@ -429,18 +432,18 @@ blocks: affinity: '' alias: '' comment: '' - mark_delay: '0' + mark_delay: len(access_code_symbols) // 2 maxoutbuf: '0' minoutbuf: '0' sps: '1' symbols: access_code_symbols - threshold: '.8' - threshold_method: digital.THRESHOLD_DYNAMIC + threshold: '.9' + threshold_method: digital.THRESHOLD_ABSOLUTE states: bus_sink: false bus_source: false bus_structure: null - coordinate: [768, 892.0] + coordinate: [792, 668.0] rotation: 0 state: enabled - name: digital_costas_loop_cc_0 @@ -458,7 +461,7 @@ blocks: bus_sink: false bus_source: false bus_structure: null - coordinate: [1080, 1000.0] + coordinate: [1104, 808.0] rotation: 0 state: true - name: digital_map_bb_0 @@ -476,7 +479,7 @@ blocks: bus_structure: null coordinate: [496, 1260.0] rotation: 0 - state: bypassed + state: enabled - name: digital_pfb_clock_sync_xxx_0 id: digital_pfb_clock_sync_xxx parameters: @@ -504,31 +507,33 @@ blocks: id: epy_block parameters: _source_code: "import pmt\n\nimport numpy as np\nfrom gnuradio import gr\n\n\n\ - class blk(gr.sync_block):\n def __init__(self):\n gr.sync_block.__init__(\n\ - \ self,\n name='Phase and Frequency Correction',\n \ - \ in_sig=[np.complex64],\n out_sig=[np.complex64]\n \ - \ )\n\n # tags should not be propagated, we then output our own tags\n\ - \ self.set_tag_propagation_policy(gr.TPP_DONT)\n\n # because we\ - \ do block processing, we need to keep track of the last tag\n # of the\ - \ previous block to correct the first values of the next block\n self.last\ - \ = None\n self.lastfreq = 0\n\n def block_phase(self, start, end):\n\ - \ \"\"\"\n Compute a vector for the phase and frequency correction\ - \ for the samples\n between two tags (start and end).\n\n @param\ - \ start Tag where the samples should start to be corrected\n @param end\ - \ Tag where to stop correcting\n\n @return A vector of phase values\ - \ for each sample. If we call the ouput\n `phase' to correct\ - \ the samples between the start and end tags,\n TODO: finish\n\ - \ \"\"\"\n # compute number of samples in block\n nsamples\ - \ = end.offset - start.offset\n\n # unpack pmt values into start and\ - \ end phase\n sphase = pmt.to_python(start.value)\n ephase = pmt.to_python(end.value)\n\ + class blk(gr.sync_block):\n \"\"\"\n Apply phase and frequency correction\ + \ where there is a correlation peak tag.\n\n The correlation peak tags are\ + \ NOT propagated, and instead replaced with a\n frame_start tag.\n \"\"\ + \"\n def __init__(self):\n gr.sync_block.__init__(\n self,\n\ + \ name='Phase and Frequency Correction',\n in_sig=[np.complex64],\n\ + \ out_sig=[np.complex64]\n )\n\n # tags should not\ + \ be propagated, we then output our own tags\n self.set_tag_propagation_policy(gr.TPP_DONT)\n\ + \n # because we do block processing, we need to keep track of the last\ + \ tag\n # of the previous block to correct the first values of the next\ + \ block\n self.last = None\n self.lastfreq = 0\n\n def block_phase(self,\ + \ start, end):\n \"\"\"\n Compute a vector for the phase and frequency\ + \ correction for the samples\n between two tags (start and end).\n\n\ + \ @param start Tag where the samples should start to be corrected\n \ + \ @param end Tag where to stop correcting\n\n @return A vector\ + \ of phase values for each sample. To correct the samples\n the\ + \ data should be multiplied with np.exp(-1j * phase)\n \"\"\"\n \ + \ # compute number of samples between tags\n nsamples = end.offset\ + \ - start.offset\n\n # unpack pmt values into start and end phase\n \ + \ sphase = pmt.to_python(start.value)\n ephase = pmt.to_python(end.value)\n\ \n # compute frequency offset between start and end\n phasediff\ \ = ephase - sphase\n\n if phasediff > np.pi:\n phasediff\ \ -= 2*np.pi\n\n elif phasediff < -np.pi:\n phasediff += 2*np.pi\n\ \n freq = phasediff / nsamples\n\n # save this one for the last\ \ block (see variable `end' in self.work)\n self.lastfreq = freq\n\n\ - \ # debugging\n print(f\"Correction for block of {nsamples:2d}\ + \ # debugging\n print(f\"Correction for chunk of {nsamples:2d}\ \ samples is \" \\\n f\"sphase={sphase: .4f} rad and freq={freq*1e3:\ - \ .4f} milli rad / sample\")\n\n # compute block values\n return\ + \ .4f} milli rad / sample\")\n\n # compute chunk values\n return\ \ sphase * np.ones(nsamples) + freq * np.arange(0, nsamples)\n\n def work(self,\ \ input_items, output_items):\n counter = self.nitems_written(0)\n\n\ \ # nicer aliases\n inp = input_items[0]\n out = output_items[0]\n\ @@ -540,14 +545,14 @@ blocks: \ = {tags[-1].offset - tags[0].offset} \" \\\n f\"samples out of\ \ {len(inp)} input samples\")\n\n # compute \"the middle\"\n enough_samples\ \ = lambda pair: ((pair[1].offset - pair[0].offset) > 0)\n pairs = list(filter(enough_samples,\ - \ zip(tags, tags[1:])))\n blocks = [ self.block_phase(start, end) for\ - \ (start, end) in pairs ]\n middle = np.concatenate(blocks) if blocks\ + \ zip(tags, tags[1:])))\n chunks = [ self.block_phase(start, end) for\ + \ (start, end) in pairs ]\n middle = np.concatenate(chunks) if chunks\ \ else []\n\n # compute values at the end, we do not have informations\ - \ about the future\n # but we can use the frequency of the last block\ - \ to approximate\n nback = len(inp) - (tags[-1].offset - counter)\n \ - \ print(f\"Processing {nback} samples at the back of the buffer\")\n \ - \ end = np.ones(nback) * pmt.to_python(tags[-1].value) \\\n \ - \ + self.lastfreq * np.arange(0, nback)\n\n # compute the \"start\"\ + \ about the future\n # but we can use the frequency of the last tag to\ + \ approximate\n nback = len(inp) - (tags[-1].offset - counter)\n \ + \ print(f\"Processing {nback} samples at the back of the buffer\")\n \ + \ end = np.ones(nback) * pmt.to_python(tags[-1].value) \\\n \ + \ + self.lastfreq * np.arange(0, nback)\n\n # compute the \"start\"\ , using the last tag from the previous call\n nfront = tags[0].offset\ \ - counter\n print(f\"Processing {nfront} samples at the front of the\ \ buffer\")\n start = self.block_phase(self.last, tags[0])[-nfront:]\ @@ -555,9 +560,11 @@ blocks: \ # compute correction\n correction = np.exp(-1j * np.concatenate([start,\ \ middle, end]))\n length = len(correction)\n\n # write outputs\n\ \ out[:length] = inp[:length] * correction\n\n # save last tag\ - \ for next call\n self.last = tags[-1]\n\n # FIXME: should return\ - \ `length' but then the last sample is not\n # included and self.last\ - \ does something weird\n return len(out)\n" + \ for next call\n self.last = tags[-1]\n\n # add tags\n \ + \ for tag in tags:\n self.add_item_tag(0, tag.offset, pmt.intern(\"\ + frame_start\"), pmt.PMT_T)\n\n # FIXME: should return `length' but then\ + \ the last sample is not\n # included and self.last does something\ + \ weird\n return len(out)\n" affinity: '' alias: '' comment: '' @@ -565,11 +572,13 @@ blocks: minoutbuf: '0' states: _io_cache: ('Phase and Frequency Correction', 'blk', [], [('0', 'complex', 1)], - [('0', 'complex', 1)], '', []) + [('0', 'complex', 1)], '\n Apply phase and frequency correction where there + is a correlation peak tag.\n\n The correlation peak tags are NOT propagated, + and instead replaced with a\n frame_start tag.\n ', []) bus_sink: false bus_source: false bus_structure: null - coordinate: [1072, 912.0] + coordinate: [1088, 688.0] rotation: 0 state: enabled - name: epy_block_1 @@ -595,7 +604,7 @@ blocks: bus_sink: false bus_source: false bus_structure: null - coordinate: [920, 1264.0] + coordinate: [1232, 1264.0] rotation: 0 state: true - name: fir_filter_xxx_1 @@ -614,7 +623,7 @@ blocks: bus_sink: false bus_source: false bus_structure: null - coordinate: [776, 692.0] + coordinate: [784, 988.0] rotation: 0 state: disabled - name: import_0 @@ -630,6 +639,23 @@ blocks: coordinate: [184, 12.0] rotation: 0 state: true +- name: note_0 + id: note + parameters: + alias: '' + comment: 'THIS FLOWGRAPH MUST BE RUN + + FROM THE TERMINAL BECAUSE + + IT HAS A HUGE OUTPUT (PRINT)' + note: README + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [280, 12.0] + rotation: 0 + state: true - name: qtgui_const_sink_x_0 id: qtgui_const_sink_x parameters: @@ -719,7 +745,7 @@ blocks: bus_sink: false bus_source: false bus_structure: null - coordinate: [768, 592.0] + coordinate: [792, 572.0] rotation: 0 state: enabled - name: qtgui_const_sink_x_0_0 @@ -811,198 +837,9 @@ blocks: bus_sink: false bus_source: false bus_structure: null - coordinate: [1408, 964.0] + coordinate: [1416, 772.0] rotation: 0 state: enabled -- name: qtgui_const_sink_x_1 - id: qtgui_const_sink_x - parameters: - affinity: '' - alias: '' - alpha1: '.5' - alpha10: '1.0' - alpha2: '1.0' - alpha3: '1.0' - alpha4: '1.0' - alpha5: '1.0' - alpha6: '1.0' - alpha7: '1.0' - alpha8: '1.0' - alpha9: '1.0' - autoscale: 'True' - axislabels: 'True' - color1: '"blue"' - color10: '"red"' - color2: '"red"' - color3: '"red"' - color4: '"red"' - color5: '"red"' - color6: '"red"' - color7: '"red"' - color8: '"red"' - color9: '"red"' - comment: '' - grid: 'True' - gui_hint: 2,1,2,1 - label1: '' - label10: '' - label2: '' - label3: '' - label4: '' - label5: '' - label6: '' - label7: '' - label8: '' - label9: '' - legend: 'True' - marker1: '9' - marker10: '0' - marker2: '0' - marker3: '0' - marker4: '0' - marker5: '0' - marker6: '0' - marker7: '0' - marker8: '0' - marker9: '0' - name: '"Cross Correlation"' - nconnections: '1' - size: '1024' - style1: '2' - style10: '0' - style2: '0' - style3: '0' - style4: '0' - style5: '0' - style6: '0' - style7: '0' - style8: '0' - style9: '0' - tr_chan: '0' - tr_level: '0.0' - tr_mode: qtgui.TRIG_MODE_FREE - tr_slope: qtgui.TRIG_SLOPE_POS - tr_tag: '""' - type: complex - update_time: '0.10' - width1: '1' - width10: '1' - width2: '1' - width3: '1' - width4: '1' - width5: '1' - width6: '1' - width7: '1' - width8: '1' - width9: '1' - xmax: '2' - xmin: '-2' - ymax: '2' - ymin: '-2' - states: - bus_sink: false - bus_source: false - bus_structure: null - coordinate: [1040, 480.0] - rotation: 0 - state: disabled -- name: qtgui_time_sink_x_0 - id: qtgui_time_sink_x - parameters: - affinity: '' - alias: '' - alpha1: '1.0' - alpha10: '1.0' - alpha2: '1.0' - alpha3: '1.0' - alpha4: '1.0' - alpha5: '1.0' - alpha6: '1.0' - alpha7: '1.0' - alpha8: '1.0' - alpha9: '1.0' - autoscale: 'True' - axislabels: 'True' - color1: blue - color10: dark blue - color2: red - color3: green - color4: black - color5: cyan - color6: magenta - color7: yellow - color8: dark red - color9: dark green - comment: '' - ctrlpanel: 'False' - entags: 'True' - grid: 'False' - gui_hint: 2,0,1,1 - label1: Signal 1 - label10: Signal 10 - label2: Signal 2 - label3: Signal 3 - label4: Signal 4 - label5: Signal 5 - label6: Signal 6 - label7: Signal 7 - label8: Signal 8 - label9: Signal 9 - legend: 'True' - marker1: '-1' - marker10: '-1' - marker2: '-1' - marker3: '-1' - marker4: '-1' - marker5: '-1' - marker6: '-1' - marker7: '-1' - marker8: '-1' - marker9: '-1' - name: '""' - nconnections: '1' - size: '1024' - srate: samp_rate - stemplot: 'False' - style1: '1' - style10: '1' - style2: '1' - style3: '1' - style4: '1' - style5: '1' - style6: '1' - style7: '1' - style8: '1' - style9: '1' - tr_chan: '0' - tr_delay: '0' - tr_level: '0.0' - tr_mode: qtgui.TRIG_MODE_FREE - tr_slope: qtgui.TRIG_SLOPE_POS - tr_tag: '""' - type: float - update_time: '0.10' - width1: '1' - width10: '1' - width2: '1' - width3: '1' - width4: '1' - width5: '1' - width6: '1' - width7: '1' - width8: '1' - width9: '1' - ylabel: XC Magnitude - ymax: '20' - ymin: '0' - yunit: '""' - states: - bus_sink: false - bus_source: false - bus_structure: null - coordinate: [1312, 480.0] - rotation: 0 - state: disabled - name: qtgui_time_sink_x_0_0 id: qtgui_time_sink_x parameters: @@ -1097,7 +934,7 @@ blocks: bus_sink: false bus_source: false bus_structure: null - coordinate: [1376, 1156.0] + coordinate: [1472, 964.0] rotation: 0 state: enabled - name: qtgui_time_sink_x_0_0_0 @@ -1194,7 +1031,7 @@ blocks: bus_sink: false bus_source: false bus_structure: null - coordinate: [1072, 788.0] + coordinate: [1096, 572.0] rotation: 0 state: enabled - name: qtgui_time_sink_x_1_0 @@ -1291,7 +1128,7 @@ blocks: bus_sink: false bus_source: false bus_structure: null - coordinate: [800, 320.0] + coordinate: [800, 172.0] rotation: 0 state: enabled - name: qtgui_time_sink_x_1_1 @@ -1388,104 +1225,7 @@ blocks: bus_sink: false bus_source: false bus_structure: null - coordinate: [768, 480.0] - rotation: 0 - state: disabled -- name: qtgui_time_sink_x_2 - id: qtgui_time_sink_x - parameters: - affinity: '' - alias: '' - alpha1: '1.0' - alpha10: '1.0' - alpha2: '1.0' - alpha3: '1.0' - alpha4: '1.0' - alpha5: '1.0' - alpha6: '1.0' - alpha7: '1.0' - alpha8: '1.0' - alpha9: '1.0' - autoscale: 'True' - axislabels: 'True' - color1: blue - color10: dark blue - color2: red - color3: green - color4: black - color5: cyan - color6: magenta - color7: yellow - color8: dark red - color9: dark green - comment: '' - ctrlpanel: 'False' - entags: 'True' - grid: 'False' - gui_hint: 3,0,1,1 - label1: Signal 1 - label10: Signal 10 - label2: Signal 2 - label3: Signal 3 - label4: Signal 4 - label5: Signal 5 - label6: Signal 6 - label7: Signal 7 - label8: Signal 8 - label9: Signal 9 - legend: 'True' - marker1: '-1' - marker10: '-1' - marker2: '-1' - marker3: '-1' - marker4: '-1' - marker5: '-1' - marker6: '-1' - marker7: '-1' - marker8: '-1' - marker9: '-1' - name: '""' - nconnections: '1' - size: '1024' - srate: samp_rate - stemplot: 'False' - style1: '1' - style10: '1' - style2: '1' - style3: '1' - style4: '1' - style5: '1' - style6: '1' - style7: '1' - style8: '1' - style9: '1' - tr_chan: '0' - tr_delay: '0' - tr_level: '0.0' - tr_mode: qtgui.TRIG_MODE_FREE - tr_slope: qtgui.TRIG_SLOPE_POS - tr_tag: '""' - type: float - update_time: '0.10' - width1: '1' - width10: '1' - width2: '1' - width3: '1' - width4: '1' - width5: '1' - width6: '1' - width7: '1' - width8: '1' - width9: '1' - ylabel: XC Phase - ymax: '1' - ymin: '-1' - yunit: '""' - states: - bus_sink: false - bus_source: false - bus_structure: null - coordinate: [1488, 580.0] + coordinate: [792, 484.0] rotation: 0 state: disabled - name: qtgui_time_sink_x_2_0 @@ -1582,7 +1322,7 @@ blocks: bus_sink: false bus_source: false bus_structure: null - coordinate: [1552, 1232.0] + coordinate: [1472, 1060.0] rotation: 0 state: disabled - name: virtual_sink_0 @@ -1608,7 +1348,7 @@ blocks: bus_sink: false bus_source: false bus_structure: null - coordinate: [1400, 828.0] + coordinate: [1416, 684.0] rotation: 0 state: true - name: virtual_source_0 @@ -1639,16 +1379,15 @@ blocks: state: true connections: -- [blocks_complex_to_magphase_0, '0', qtgui_time_sink_x_0, '0'] -- [blocks_complex_to_magphase_0, '1', blocks_multiply_const_vxx_0, '0'] - [blocks_complex_to_magphase_0_0, '0', qtgui_time_sink_x_0_0, '0'] - [blocks_complex_to_magphase_0_0, '1', blocks_multiply_const_vxx_0_0, '0'] - [blocks_complex_to_magphase_0_0, '1', blocks_null_sink_3, '0'] -- [blocks_multiply_const_vxx_0, '0', qtgui_time_sink_x_2, '0'] - [blocks_multiply_const_vxx_0_0, '0', qtgui_time_sink_x_2_0, '0'] - [blocks_null_source_0, '0', blocks_stream_mux_0, '0'] -- [blocks_repack_bits_bb_0, '0', epy_block_1, '0'] +- [blocks_repack_bits_bb_0, '0', blocks_tagged_stream_align_0, '0'] - [blocks_stream_mux_0, '0', digital_constellation_modulator_0, '0'] +- [blocks_tagged_stream_align_0, '0', blocks_tag_debug_0, '0'] +- [blocks_tagged_stream_align_0, '0', epy_block_1, '0'] - [blocks_throttle_0, '0', virtual_sink_0, '0'] - [blocks_vector_source_x_0, '0', blocks_stream_mux_0, '1'] - [channels_channel_model_0, '0', blocks_throttle_0, '0'] @@ -1668,8 +1407,7 @@ connections: - [digital_pfb_clock_sync_xxx_0, '0', digital_cma_equalizer_cc_0, '0'] - [epy_block_0, '0', qtgui_const_sink_x_0_0, '0'] - [epy_block_0, '0', virtual_sink_3, '0'] -- [fir_filter_xxx_1, '0', blocks_complex_to_magphase_0, '0'] -- [fir_filter_xxx_1, '0', qtgui_const_sink_x_1, '0'] +- [fir_filter_xxx_1, '0', blocks_complex_to_magphase_0_0, '0'] - [virtual_source_0, '0', digital_pfb_clock_sync_xxx_0, '0'] - [virtual_source_1, '0', digital_constellation_decoder_cb_0, '0'] diff --git a/tests/correlator/correlator.py b/tests/correlator/correlator.py index 255010a..d9dedb2 100755 --- a/tests/correlator/correlator.py +++ b/tests/correlator/correlator.py @@ -85,7 +85,7 @@ class correlator(gr.top_block, Qt.QWidget): self.rrc_taps = rrc_taps = firdes.root_raised_cosine(nfilts, nfilts, 1.0/float(sps), excess_bw, 45*nfilts) self.revconj_access_code_symbols = revconj_access_code_symbols = [(1.4142135623730951+1.4142135623730951j), (1.4142135623730951+1.4142135623730951j), (1.4142135623730951-1.4142135623730951j), (-1.4142135623730951+1.4142135623730951j), (1.4142135623730951-1.4142135623730951j), (1.4142135623730951-1.4142135623730951j), (1.4142135623730951+1.4142135623730951j), (-1.4142135623730951+1.4142135623730951j)] self.const = const = digital.constellation_qpsk().base() - self.access_code_symbols = access_code_symbols = [(-1.4142135623730951-1.4142135623730951j), (1.4142135623730951-1.4142135623730951j), (1.4142135623730951+1.4142135623730951j), (1.4142135623730951+1.4142135623730951j), (-1.4142135623730951-1.4142135623730951j), (1.4142135623730951+1.4142135623730951j), (1.4142135623730951-1.4142135623730951j), (1.4142135623730951-1.4142135623730951j)] + self.access_code_symbols = access_code_symbols = .5 * np.array([(-1.4142135623730951-1.4142135623730951j), (1.4142135623730951-1.4142135623730951j), (1.4142135623730951+1.4142135623730951j), (1.4142135623730951+1.4142135623730951j), (-1.4142135623730951-1.4142135623730951j), (1.4142135623730951+1.4142135623730951j), (1.4142135623730951-1.4142135623730951j), (1.4142135623730951-1.4142135623730951j)]) ################################################## # Blocks @@ -332,8 +332,9 @@ class correlator(gr.top_block, Qt.QWidget): self.epy_block_1 = epy_block_1.blk() self.epy_block_0 = epy_block_0.blk() self.digital_pfb_clock_sync_xxx_0 = digital.pfb_clock_sync_ccf(sps, timing_loop_bw, rrc_taps, nfilts, 16, 1.5, 1) + self.digital_map_bb_0 = digital.map_bb([0, 1, 3, 2]) self.digital_costas_loop_cc_0 = digital.costas_loop_cc(2 * 3.141592653589793 / 100, 4, False) - self.digital_corr_est_cc_0 = digital.corr_est_cc(access_code_symbols, 1, 0, .8, digital.THRESHOLD_DYNAMIC) + self.digital_corr_est_cc_0 = digital.corr_est_cc(access_code_symbols, 1, len(access_code_symbols) // 2, .9, digital.THRESHOLD_ABSOLUTE) self.digital_constellation_modulator_0 = digital.generic_mod( constellation=const, differential=False, @@ -346,14 +347,15 @@ class correlator(gr.top_block, Qt.QWidget): self.digital_cma_equalizer_cc_0 = digital.cma_equalizer_cc(15, 1, .002, 1) self.channels_channel_model_0 = channels.channel_model( noise_voltage=0.01, - frequency_offset=0.0001, + frequency_offset=0.002, epsilon=1.0, taps=[np.exp(1j * 30 / 180 * np.pi)], noise_seed=243, block_tags=False) self.blocks_vector_source_x_0 = blocks.vector_source_b(testvec * 500, True, 1, []) self.blocks_throttle_0 = blocks.throttle(gr.sizeof_gr_complex*1, samp_rate,True) - self.blocks_stream_mux_0 = blocks.stream_mux(gr.sizeof_char*1, [5, len(testvec)]) + self.blocks_tagged_stream_align_0 = blocks.tagged_stream_align(gr.sizeof_char*1, 'frame_start') + self.blocks_stream_mux_0 = blocks.stream_mux(gr.sizeof_char*1, [0, len(testvec)]) self.blocks_repack_bits_bb_0 = blocks.repack_bits_bb(2, 8, "", False, gr.GR_MSB_FIRST) self.blocks_null_source_0 = blocks.null_source(gr.sizeof_char*1) self.blocks_null_sink_3 = blocks.null_sink(gr.sizeof_float*1) @@ -367,14 +369,15 @@ class correlator(gr.top_block, Qt.QWidget): self.connect((self.blocks_complex_to_magphase_0_0, 1), (self.blocks_null_sink_3, 0)) self.connect((self.blocks_complex_to_magphase_0_0, 0), (self.qtgui_time_sink_x_0_0, 0)) self.connect((self.blocks_null_source_0, 0), (self.blocks_stream_mux_0, 0)) - self.connect((self.blocks_repack_bits_bb_0, 0), (self.epy_block_1, 0)) + self.connect((self.blocks_repack_bits_bb_0, 0), (self.blocks_tagged_stream_align_0, 0)) self.connect((self.blocks_stream_mux_0, 0), (self.digital_constellation_modulator_0, 0)) + self.connect((self.blocks_tagged_stream_align_0, 0), (self.epy_block_1, 0)) self.connect((self.blocks_throttle_0, 0), (self.digital_pfb_clock_sync_xxx_0, 0)) self.connect((self.blocks_vector_source_x_0, 0), (self.blocks_stream_mux_0, 1)) self.connect((self.channels_channel_model_0, 0), (self.blocks_throttle_0, 0)) self.connect((self.digital_cma_equalizer_cc_0, 0), (self.digital_corr_est_cc_0, 0)) self.connect((self.digital_cma_equalizer_cc_0, 0), (self.qtgui_const_sink_x_0, 0)) - self.connect((self.digital_constellation_decoder_cb_0, 0), (self.blocks_repack_bits_bb_0, 0)) + self.connect((self.digital_constellation_decoder_cb_0, 0), (self.digital_map_bb_0, 0)) self.connect((self.digital_constellation_modulator_0, 0), (self.channels_channel_model_0, 0)) self.connect((self.digital_constellation_modulator_0, 0), (self.qtgui_time_sink_x_1_0, 0)) self.connect((self.digital_corr_est_cc_0, 1), (self.blocks_complex_to_magphase_0_0, 0)) @@ -382,6 +385,7 @@ class correlator(gr.top_block, Qt.QWidget): self.connect((self.digital_corr_est_cc_0, 0), (self.epy_block_0, 0)) self.connect((self.digital_corr_est_cc_0, 0), (self.qtgui_time_sink_x_0_0_0, 0)) self.connect((self.digital_costas_loop_cc_0, 0), (self.qtgui_const_sink_x_0_0, 1)) + self.connect((self.digital_map_bb_0, 0), (self.blocks_repack_bits_bb_0, 0)) self.connect((self.digital_pfb_clock_sync_xxx_0, 0), (self.digital_cma_equalizer_cc_0, 0)) self.connect((self.epy_block_0, 0), (self.digital_constellation_decoder_cb_0, 0)) self.connect((self.epy_block_0, 0), (self.qtgui_const_sink_x_0_0, 0)) @@ -463,6 +467,7 @@ class correlator(gr.top_block, Qt.QWidget): def set_access_code_symbols(self, access_code_symbols): self.access_code_symbols = access_code_symbols + self.digital_corr_est_cc_0.set_mark_delay(len(self.access_code_symbols) // 2) diff --git a/tests/correlator/epy_block_0.py b/tests/correlator/epy_block_0.py index ddae02a..dbdadd1 100644 --- a/tests/correlator/epy_block_0.py +++ b/tests/correlator/epy_block_0.py @@ -5,6 +5,12 @@ from gnuradio import gr class blk(gr.sync_block): + """ + Apply phase and frequency correction where there is a correlation peak tag. + + The correlation peak tags are NOT propagated, and instead replaced with a + frame_start tag. + """ def __init__(self): gr.sync_block.__init__( self, @@ -22,7 +28,17 @@ class blk(gr.sync_block): self.lastfreq = 0 def block_phase(self, start, end): - # compute number of samples in block + """ + Compute a vector for the phase and frequency correction for the samples + between two tags (start and end). + + @param start Tag where the samples should start to be corrected + @param end Tag where to stop correcting + + @return A vector of phase values for each sample. To correct the samples + the data should be multiplied with np.exp(-1j * phase) + """ + # compute number of samples between tags nsamples = end.offset - start.offset # unpack pmt values into start and end phase @@ -44,10 +60,10 @@ class blk(gr.sync_block): self.lastfreq = freq # debugging - print(f"Correction for block of {nsamples:2d} samples is " \ + print(f"Correction for chunk of {nsamples:2d} samples is " \ f"sphase={sphase: .4f} rad and freq={freq*1e3: .4f} milli rad / sample") - # compute block values + # compute chunk values return sphase * np.ones(nsamples) + freq * np.arange(0, nsamples) def work(self, input_items, output_items): @@ -73,11 +89,11 @@ class blk(gr.sync_block): # compute "the middle" enough_samples = lambda pair: ((pair[1].offset - pair[0].offset) > 0) pairs = list(filter(enough_samples, zip(tags, tags[1:]))) - blocks = [ self.block_phase(start, end) for (start, end) in pairs ] - middle = np.concatenate(blocks) if blocks else [] + chunks = [ self.block_phase(start, end) for (start, end) in pairs ] + middle = np.concatenate(chunks) if chunks else [] # compute values at the end, we do not have informations about the future - # but we can use the frequency of the last block to approximate + # but we can use the frequency of the last tag to approximate nback = len(inp) - (tags[-1].offset - counter) print(f"Processing {nback} samples at the back of the buffer") end = np.ones(nback) * pmt.to_python(tags[-1].value) \ @@ -99,6 +115,10 @@ class blk(gr.sync_block): # save last tag for next call self.last = tags[-1] + # add tags + for tag in tags: + self.add_item_tag(0, tag.offset, pmt.intern("frame_start"), pmt.PMT_T) + # FIXME: should return `length' but then the last sample is not # included and self.last does something weird return len(out) -- cgit v1.2.1 From b39b8351476679e2f89cefade40a1eca2566067f Mon Sep 17 00:00:00 2001 From: sara Date: Sat, 4 Dec 2021 15:24:53 +0100 Subject: GNUR Radio Test Sockets --- tests/sockets/Socket_test.grc | 140 ++++++++++++++++++++++++++++++++++++ tests/sockets/Test_Bit_Errorrate.py | 139 +++++++++++++++++++++++++++++++++++ 2 files changed, 279 insertions(+) create mode 100644 tests/sockets/Socket_test.grc create mode 100755 tests/sockets/Test_Bit_Errorrate.py (limited to 'tests') diff --git a/tests/sockets/Socket_test.grc b/tests/sockets/Socket_test.grc new file mode 100644 index 0000000..41c7f0a --- /dev/null +++ b/tests/sockets/Socket_test.grc @@ -0,0 +1,140 @@ +options: + parameters: + author: 'Sara Halter ' + category: '[GRC Hier Blocks]' + cmake_opt: '' + comment: '' + copyright: '' + description: '' + gen_cmake: 'On' + gen_linking: dynamic + generate_options: qt_gui + hier_block_src_path: '.:' + id: Test_Bit_Errorrate + max_nouts: '0' + output_language: python + placement: (0,0) + qt_qss_theme: '' + realtime_scheduling: '' + run: 'True' + run_command: '{python} -u {filename}' + run_options: prompt + sizing_mode: fixed + thread_safe_setters: '' + title: 'Bit Error Rate test ' + window_size: '' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [8, 8] + rotation: 0 + state: enabled + +blocks: +- name: samp_rate + id: variable + parameters: + comment: '' + value: '32000' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [184, 12] + rotation: 0 + state: enabled +- name: analog_noise_source_x_0 + id: analog_noise_source_x + parameters: + affinity: '' + alias: '' + amp: '1' + comment: '' + maxoutbuf: '0' + minoutbuf: '0' + noise_type: analog.GR_GAUSSIAN + seed: '0' + type: float + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [528, 108.0] + rotation: 0 + state: disabled +- name: blocks_null_source_0 + id: blocks_null_source + parameters: + affinity: '' + alias: '' + bus_structure_source: '[[0,],]' + comment: '' + maxoutbuf: '0' + minoutbuf: '0' + num_outputs: '1' + type: byte + vlen: '1' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [552, 224.0] + rotation: 0 + state: true +- name: blocks_throttle_1 + id: blocks_throttle + parameters: + affinity: '' + alias: '' + comment: '' + ignoretag: 'True' + maxoutbuf: '0' + minoutbuf: '0' + samples_per_second: samp_rate + type: byte + vlen: '1' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [800, 156.0] + rotation: 0 + state: true +- name: fadingui_netsink_0 + id: fadingui_netsink + parameters: + address: udp://localhost:31415 + affinity: '' + alias: '' + comment: '' + type: byte + veclen: '1' + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [1016, 156.0] + rotation: 0 + state: true +- name: import_0 + id: import + parameters: + alias: '' + comment: '' + imports: import numpy as np + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [328, 20.0] + rotation: 0 + state: true + +connections: +- [analog_noise_source_x_0, '0', blocks_throttle_1, '0'] +- [blocks_null_source_0, '0', blocks_throttle_1, '0'] +- [blocks_throttle_1, '0', fadingui_netsink_0, '0'] + +metadata: + file_format: 1 diff --git a/tests/sockets/Test_Bit_Errorrate.py b/tests/sockets/Test_Bit_Errorrate.py new file mode 100755 index 0000000..b545104 --- /dev/null +++ b/tests/sockets/Test_Bit_Errorrate.py @@ -0,0 +1,139 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +# +# SPDX-License-Identifier: GPL-3.0 +# +# GNU Radio Python Flow Graph +# Title: Bit Error Rate test +# Author: Sara Halter +# GNU Radio version: 3.8.2.0 + +from distutils.version import StrictVersion + +if __name__ == '__main__': + import ctypes + import sys + if sys.platform.startswith('linux'): + try: + x11 = ctypes.cdll.LoadLibrary('libX11.so') + x11.XInitThreads() + except: + print("Warning: failed to XInitThreads()") + +from gnuradio import blocks +from gnuradio import gr +from gnuradio.filter import firdes +import sys +import signal +from PyQt5 import Qt +from argparse import ArgumentParser +from gnuradio.eng_arg import eng_float, intx +from gnuradio import eng_notation +import fadingui +import numpy as np + +from gnuradio import qtgui + +class Test_Bit_Errorrate(gr.top_block, Qt.QWidget): + + def __init__(self): + gr.top_block.__init__(self, "Bit Error Rate test ") + Qt.QWidget.__init__(self) + self.setWindowTitle("Bit Error Rate test ") + qtgui.util.check_set_qss() + try: + self.setWindowIcon(Qt.QIcon.fromTheme('gnuradio-grc')) + except: + pass + self.top_scroll_layout = Qt.QVBoxLayout() + self.setLayout(self.top_scroll_layout) + self.top_scroll = Qt.QScrollArea() + self.top_scroll.setFrameStyle(Qt.QFrame.NoFrame) + self.top_scroll_layout.addWidget(self.top_scroll) + self.top_scroll.setWidgetResizable(True) + self.top_widget = Qt.QWidget() + self.top_scroll.setWidget(self.top_widget) + self.top_layout = Qt.QVBoxLayout(self.top_widget) + self.top_grid_layout = Qt.QGridLayout() + self.top_layout.addLayout(self.top_grid_layout) + + self.settings = Qt.QSettings("GNU Radio", "Test_Bit_Errorrate") + + try: + if StrictVersion(Qt.qVersion()) < StrictVersion("5.0.0"): + self.restoreGeometry(self.settings.value("geometry").toByteArray()) + else: + self.restoreGeometry(self.settings.value("geometry")) + except: + pass + + ################################################## + # Variables + ################################################## + self.samp_rate = samp_rate = 32000 + + ################################################## + # Blocks + ################################################## + self.fadingui_netsink_0 = fadingui.netsink(address='udp://localhost:31415', dtype="byte", vlen=1) + self.blocks_throttle_1 = blocks.throttle(gr.sizeof_char*1, samp_rate,True) + self.blocks_null_source_0 = blocks.null_source(gr.sizeof_char*1) + + + + ################################################## + # Connections + ################################################## + self.connect((self.blocks_null_source_0, 0), (self.blocks_throttle_1, 0)) + self.connect((self.blocks_throttle_1, 0), (self.fadingui_netsink_0, 0)) + + + def closeEvent(self, event): + self.settings = Qt.QSettings("GNU Radio", "Test_Bit_Errorrate") + self.settings.setValue("geometry", self.saveGeometry()) + event.accept() + + def get_samp_rate(self): + return self.samp_rate + + def set_samp_rate(self, samp_rate): + self.samp_rate = samp_rate + self.blocks_throttle_1.set_sample_rate(self.samp_rate) + + + + + +def main(top_block_cls=Test_Bit_Errorrate, options=None): + + if StrictVersion("4.5.0") <= StrictVersion(Qt.qVersion()) < StrictVersion("5.0.0"): + style = gr.prefs().get_string('qtgui', 'style', 'raster') + Qt.QApplication.setGraphicsSystem(style) + qapp = Qt.QApplication(sys.argv) + + tb = top_block_cls() + + tb.start() + + tb.show() + + def sig_handler(sig=None, frame=None): + Qt.QApplication.quit() + + signal.signal(signal.SIGINT, sig_handler) + signal.signal(signal.SIGTERM, sig_handler) + + timer = Qt.QTimer() + timer.start(500) + timer.timeout.connect(lambda: None) + + def quitting(): + tb.stop() + tb.wait() + + qapp.aboutToQuit.connect(quitting) + qapp.exec_() + +if __name__ == '__main__': + main() -- cgit v1.2.1 From 30012258948049da894e260d78551d1de44c2f50 Mon Sep 17 00:00:00 2001 From: Nao Pross Date: Sat, 4 Dec 2021 16:46:23 +0100 Subject: Update net.py to decode UDP data stream --- tests/sockets/Socket_test.grc | 24 +++++------ tests/sockets/Test_Bit_Errorrate.py | 83 ++++++------------------------------- 2 files changed, 24 insertions(+), 83 deletions(-) (limited to 'tests') diff --git a/tests/sockets/Socket_test.grc b/tests/sockets/Socket_test.grc index 41c7f0a..fbc3cdf 100644 --- a/tests/sockets/Socket_test.grc +++ b/tests/sockets/Socket_test.grc @@ -8,7 +8,7 @@ options: description: '' gen_cmake: 'On' gen_linking: dynamic - generate_options: qt_gui + generate_options: no_gui hier_block_src_path: '.:' id: Test_Bit_Errorrate max_nouts: '0' @@ -18,7 +18,7 @@ options: realtime_scheduling: '' run: 'True' run_command: '{python} -u {filename}' - run_options: prompt + run_options: run sizing_mode: fixed thread_safe_setters: '' title: 'Bit Error Rate test ' @@ -41,7 +41,7 @@ blocks: bus_sink: false bus_source: false bus_structure: null - coordinate: [184, 12] + coordinate: [216, 20.0] rotation: 0 state: enabled - name: analog_noise_source_x_0 @@ -60,9 +60,9 @@ blocks: bus_sink: false bus_source: false bus_structure: null - coordinate: [528, 108.0] + coordinate: [32, 148.0] rotation: 0 - state: disabled + state: enabled - name: blocks_null_source_0 id: blocks_null_source parameters: @@ -73,15 +73,15 @@ blocks: maxoutbuf: '0' minoutbuf: '0' num_outputs: '1' - type: byte + type: complex vlen: '1' states: bus_sink: false bus_source: false bus_structure: null - coordinate: [552, 224.0] + coordinate: [64, 264.0] rotation: 0 - state: true + state: disabled - name: blocks_throttle_1 id: blocks_throttle parameters: @@ -92,13 +92,13 @@ blocks: maxoutbuf: '0' minoutbuf: '0' samples_per_second: samp_rate - type: byte + type: float vlen: '1' states: bus_sink: false bus_source: false bus_structure: null - coordinate: [800, 156.0] + coordinate: [280, 164.0] rotation: 0 state: true - name: fadingui_netsink_0 @@ -108,13 +108,13 @@ blocks: affinity: '' alias: '' comment: '' - type: byte + type: float veclen: '1' states: bus_sink: false bus_source: false bus_structure: null - coordinate: [1016, 156.0] + coordinate: [504, 164.0] rotation: 0 state: true - name: import_0 diff --git a/tests/sockets/Test_Bit_Errorrate.py b/tests/sockets/Test_Bit_Errorrate.py index b545104..6a989df 100755 --- a/tests/sockets/Test_Bit_Errorrate.py +++ b/tests/sockets/Test_Bit_Errorrate.py @@ -9,64 +9,23 @@ # Author: Sara Halter # GNU Radio version: 3.8.2.0 -from distutils.version import StrictVersion - -if __name__ == '__main__': - import ctypes - import sys - if sys.platform.startswith('linux'): - try: - x11 = ctypes.cdll.LoadLibrary('libX11.so') - x11.XInitThreads() - except: - print("Warning: failed to XInitThreads()") - +from gnuradio import analog from gnuradio import blocks from gnuradio import gr from gnuradio.filter import firdes import sys import signal -from PyQt5 import Qt from argparse import ArgumentParser from gnuradio.eng_arg import eng_float, intx from gnuradio import eng_notation import fadingui import numpy as np -from gnuradio import qtgui -class Test_Bit_Errorrate(gr.top_block, Qt.QWidget): +class Test_Bit_Errorrate(gr.top_block): def __init__(self): gr.top_block.__init__(self, "Bit Error Rate test ") - Qt.QWidget.__init__(self) - self.setWindowTitle("Bit Error Rate test ") - qtgui.util.check_set_qss() - try: - self.setWindowIcon(Qt.QIcon.fromTheme('gnuradio-grc')) - except: - pass - self.top_scroll_layout = Qt.QVBoxLayout() - self.setLayout(self.top_scroll_layout) - self.top_scroll = Qt.QScrollArea() - self.top_scroll.setFrameStyle(Qt.QFrame.NoFrame) - self.top_scroll_layout.addWidget(self.top_scroll) - self.top_scroll.setWidgetResizable(True) - self.top_widget = Qt.QWidget() - self.top_scroll.setWidget(self.top_widget) - self.top_layout = Qt.QVBoxLayout(self.top_widget) - self.top_grid_layout = Qt.QGridLayout() - self.top_layout.addLayout(self.top_grid_layout) - - self.settings = Qt.QSettings("GNU Radio", "Test_Bit_Errorrate") - - try: - if StrictVersion(Qt.qVersion()) < StrictVersion("5.0.0"): - self.restoreGeometry(self.settings.value("geometry").toByteArray()) - else: - self.restoreGeometry(self.settings.value("geometry")) - except: - pass ################################################## # Variables @@ -76,24 +35,19 @@ class Test_Bit_Errorrate(gr.top_block, Qt.QWidget): ################################################## # Blocks ################################################## - self.fadingui_netsink_0 = fadingui.netsink(address='udp://localhost:31415', dtype="byte", vlen=1) - self.blocks_throttle_1 = blocks.throttle(gr.sizeof_char*1, samp_rate,True) - self.blocks_null_source_0 = blocks.null_source(gr.sizeof_char*1) + self.fadingui_netsink_0 = fadingui.netsink(address='udp://localhost:31415', dtype="float", vlen=1) + self.blocks_throttle_1 = blocks.throttle(gr.sizeof_float*1, samp_rate,True) + self.analog_noise_source_x_0 = analog.noise_source_f(analog.GR_GAUSSIAN, 1, 0) ################################################## # Connections ################################################## - self.connect((self.blocks_null_source_0, 0), (self.blocks_throttle_1, 0)) + self.connect((self.analog_noise_source_x_0, 0), (self.blocks_throttle_1, 0)) self.connect((self.blocks_throttle_1, 0), (self.fadingui_netsink_0, 0)) - def closeEvent(self, event): - self.settings = Qt.QSettings("GNU Radio", "Test_Bit_Errorrate") - self.settings.setValue("geometry", self.saveGeometry()) - event.accept() - def get_samp_rate(self): return self.samp_rate @@ -106,34 +60,21 @@ class Test_Bit_Errorrate(gr.top_block, Qt.QWidget): def main(top_block_cls=Test_Bit_Errorrate, options=None): - - if StrictVersion("4.5.0") <= StrictVersion(Qt.qVersion()) < StrictVersion("5.0.0"): - style = gr.prefs().get_string('qtgui', 'style', 'raster') - Qt.QApplication.setGraphicsSystem(style) - qapp = Qt.QApplication(sys.argv) - tb = top_block_cls() - tb.start() - - tb.show() - def sig_handler(sig=None, frame=None): - Qt.QApplication.quit() + tb.stop() + tb.wait() + + sys.exit(0) signal.signal(signal.SIGINT, sig_handler) signal.signal(signal.SIGTERM, sig_handler) - timer = Qt.QTimer() - timer.start(500) - timer.timeout.connect(lambda: None) + tb.start() - def quitting(): - tb.stop() - tb.wait() + tb.wait() - qapp.aboutToQuit.connect(quitting) - qapp.exec_() if __name__ == '__main__': main() -- cgit v1.2.1