aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/gr-fadingui/grc/CMakeLists.txt4
-rw-r--r--src/gr-fadingui/grc/fadingui_netsink.block.yml (renamed from src/gr-fadingui/grc/fadingui_dearpygui_sink.block.yml)34
-rw-r--r--src/gr-fadingui/python/CMakeLists.txt4
-rw-r--r--src/gr-fadingui/python/__init__.py3
-rw-r--r--src/gr-fadingui/python/dearpygui_sink.py36
-rw-r--r--src/gr-fadingui/python/netsink.py59
-rw-r--r--tests/correlator/correlator.grc345
-rwxr-xr-xtests/correlator/correlator.py41
-rw-r--r--tests/correlator/epy_block_0.py52
-rw-r--r--tests/correlator/epy_block_1.py27
-rw-r--r--tests/sockets/send.py21
11 files changed, 338 insertions, 288 deletions
diff --git a/src/gr-fadingui/grc/CMakeLists.txt b/src/gr-fadingui/grc/CMakeLists.txt
index 297ae8d..79c1a31 100644
--- a/src/gr-fadingui/grc/CMakeLists.txt
+++ b/src/gr-fadingui/grc/CMakeLists.txt
@@ -19,9 +19,9 @@
# Boston, MA 02110-1301, USA.
install(FILES
fadingui_datasource.block.yml
- fadingui_dearpygui_sink.block.yml
fadingui_deframer.block.yml
fadingui_frame_obj.block.yml
fadingui_multipath_fading.block.yml
- fadingui_ber.block.yml DESTINATION share/gnuradio/grc/blocks
+ fadingui_ber.block.yml
+ fadingui_netsink.block.yml DESTINATION share/gnuradio/grc/blocks
)
diff --git a/src/gr-fadingui/grc/fadingui_dearpygui_sink.block.yml b/src/gr-fadingui/grc/fadingui_netsink.block.yml
index dbe6198..4e5b01b 100644
--- a/src/gr-fadingui/grc/fadingui_dearpygui_sink.block.yml
+++ b/src/gr-fadingui/grc/fadingui_netsink.block.yml
@@ -1,10 +1,11 @@
-id: fadingui_dearpygui_sink
-label: UI Sink
+id: fadingui_netsink
+label: Network Sink
category: '[fadingui]'
+flags: [ python ]
templates:
imports: import fadingui
- make: fadingui.dearpygui_sink(sock_addr=${sock_addr}, ui_element_id=${ui_element_id})
+ make: fadingui.netsink(${address}, ${dtype}, ${vlen})
# Make one 'parameters' list entry for every parameter you want settable from the GUI.
# Keys include:
@@ -12,15 +13,22 @@ templates:
# * label (label shown in the GUI)
# * dtype (e.g. int, float, complex, byte, short, xxx_vector, ...)
parameters:
-- id: sock_addr
- label: Socket address
+- id: dtype
+ label: Type
+ dtype: enum
+ options: [complex, float, int, short, byte]
+ option_attributes:
+ size: [gr.sizeof_gr_complex, gr.sizeof_floar, gr.sizeof_int, gr.sizeof_short, gr.sizeof_char ]
+ hide: part
+- id: vlen
+ label: Vec Length
+ dtype: int
+ default: 1
+ hide: ${ 'part' if vlen == 1 else 'none' }
+- id: address
+ label: Address
dtype: string
- default: udp://
-
-- id: ui_element_id
- label: UI element ID
- dtype: raw
-
+ default: "udp://localhost:31415"
# Make one 'inputs' list entry per input and one 'outputs' list entry per output.
# Keys include:
@@ -31,7 +39,9 @@ parameters:
# * optional (optional - set to 1 for optional inputs. Default is 0)
inputs:
- label: in
- dtype: complex
+ domain: stream
+ dtype: ${dtype}
+ vlen: ${vlen}
# 'file_format' specifies the version of the GRC yml format used in the file
# and should usually not be changed.
diff --git a/src/gr-fadingui/python/CMakeLists.txt b/src/gr-fadingui/python/CMakeLists.txt
index e04eb5b..bf484cc 100644
--- a/src/gr-fadingui/python/CMakeLists.txt
+++ b/src/gr-fadingui/python/CMakeLists.txt
@@ -34,11 +34,11 @@ GR_PYTHON_INSTALL(
__init__.py
logger.py
datasource.py
- dearpygui_sink.py
deframer.py
frame_obj.py
multipath_fading.py
- ber.py DESTINATION ${GR_PYTHON_DIR}/fadingui
+ ber.py
+ netsink.py DESTINATION ${GR_PYTHON_DIR}/fadingui
)
########################################################################
diff --git a/src/gr-fadingui/python/__init__.py b/src/gr-fadingui/python/__init__.py
index 9fe45d5..56dbdd3 100644
--- a/src/gr-fadingui/python/__init__.py
+++ b/src/gr-fadingui/python/__init__.py
@@ -33,11 +33,12 @@ except ImportError:
# import any pure python here
from .datasource import datasource
-from .dearpygui_sink import dearpygui_sink
+
from .deframer import deframer
from .frame_obj import frame_obj
from .multipath_fading import multipath_fading
from .ber import ber
+from .netsink import netsink
#
diff --git a/src/gr-fadingui/python/dearpygui_sink.py b/src/gr-fadingui/python/dearpygui_sink.py
deleted file mode 100644
index 6153611..0000000
--- a/src/gr-fadingui/python/dearpygui_sink.py
+++ /dev/null
@@ -1,36 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-#
-# Copyright 2021 Naoki Pross.
-
-import socket
-from urllib.parse import urlparse
-
-import numpy as np
-from gnuradio import gr
-
-class dearpygui_sink(gr.sync_block):
- """
- DearPyGUI Sink
- """
- def __init__(self, sock_addr, ui_element_id):
- gr.sync_block.__init__(self,
- name="dearpygui_sink",
- in_sig=[np.complex64],
- out_sig=None)
-
- # sockets
- self.socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
- self.srv = urlparse(sock_addr)
-
- def send(self, value):
- data = value.tobytes()
- sent = self.socket.sendto(data, (self.srv.hostname, self.srv.port))
-
- return len(data) == sent
-
- def work(self, input_items, output_items):
- in0 = input_items[0]
- self.send(in0)
- return len(input_items[0])
-
diff --git a/src/gr-fadingui/python/netsink.py b/src/gr-fadingui/python/netsink.py
new file mode 100644
index 0000000..9df81f5
--- /dev/null
+++ b/src/gr-fadingui/python/netsink.py
@@ -0,0 +1,59 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+#
+# Copyright 2021 Sara Cinzia Halter, Naoki Pross.
+
+import socket
+from urllib.parse import urlparse
+
+import numpy as np
+from gnuradio import gr
+
+class netsink(gr.sync_block):
+ """
+ Sink that sends the data over the network using UDP.
+ Keep in mind that is quite slow.
+ """
+ def __init__(self, address, dtype, vlen):
+ gr.sync_block.__init__(self,
+ name="Network Sink",
+ in_sig=[],
+ out_sig=None)
+
+ # Create a socket and parse remote machine url
+ self.socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
+ self.url = urlparse(sock_addr)
+ self.srv = (self.srv.hostname, self.srv.port)
+
+ def send(self, data):
+ """
+ Send the data to self.srv
+
+ @param data Data as python bytes
+ @return Number of bytes that were actually sent
+ """
+ assert type(data) == bytes
+ return self.socket.sendto(data, self.srv)
+
+ def encode(self, data):
+ """
+ Encode the data into a dead simple format
+
+ @param data Array like type
+ @return Bytes of ASCII encoded comma separated string of numbers
+ """
+ # no data (what are you doing?)
+ if not data:
+ return bytes()
+
+ values = "[" + ",".join(map(str, data)) + "]"
+ return bytes(values, "ascii")
+
+ def work(self, input_items, output_items):
+ inp = input_items[0]
+
+ # TODO: Check that inp has a reasonable size
+ self.send(self.encode(inp))
+
+ return len(input_items[0])
+
diff --git a/tests/correlator/correlator.grc b/tests/correlator/correlator.grc
index 220eaed..beea007 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: [1080, 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
@@ -543,32 +505,33 @@ 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 = 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,\
- \ 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\
+ \ 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\
@@ -581,34 +544,60 @@ 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: [1088, 1040.0]
+ coordinate: [1072, 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 +614,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 +719,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 +811,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 +903,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 +1000,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 +1059,7 @@ blocks:
name: '""'
nconnections: '1'
size: '1024'
- srate: samp_rate
+ srate: samp_rate / sps
stemplot: 'False'
style1: '1'
style10: '1'
@@ -1095,7 +1097,7 @@ blocks:
bus_sink: false
bus_source: false
bus_structure: null
- coordinate: [1376, 1284.0]
+ coordinate: [1376, 1156.0]
rotation: 0
state: enabled
- name: qtgui_time_sink_x_0_0_0
@@ -1154,7 +1156,7 @@ blocks:
name: '""'
nconnections: '1'
size: '1024'
- srate: samp_rate
+ srate: samp_rate / sps
stemplot: 'False'
style1: '1'
style10: '1'
@@ -1192,7 +1194,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 +1291,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 +1388,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 +1485,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 +1582,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 +1595,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 +1608,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 +1621,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 +1634,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 +1647,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 +1664,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..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 = 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
+ self.lastfreq = 0
def block_phase(self, start, end):
# compute number of samples in block
@@ -45,20 +30,28 @@ 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
- 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
+
+ # 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 " \
- 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)
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]
@@ -85,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)
@@ -102,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]
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)
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())