From f7b154f2485b2d897db449890684928e12b1734e Mon Sep 17 00:00:00 2001 From: Nao Pross Date: Thu, 2 Dec 2021 12:54:32 +0100 Subject: Delete XOR Correlator (replaced with by phase correction) --- src/gr-fadingui/grc/CMakeLists.txt | 1 - .../grc/fadingui_xor_frame_sync.block.yml | 42 ------ src/gr-fadingui/python/CMakeLists.txt | 2 - src/gr-fadingui/python/__init__.py | 2 +- src/gr-fadingui/python/qa_xor_frame_sync.py | 57 -------- src/gr-fadingui/python/xor_frame_sync.py | 152 --------------------- 6 files changed, 1 insertion(+), 255 deletions(-) delete mode 100644 src/gr-fadingui/grc/fadingui_xor_frame_sync.block.yml delete mode 100644 src/gr-fadingui/python/qa_xor_frame_sync.py delete mode 100644 src/gr-fadingui/python/xor_frame_sync.py (limited to 'src') diff --git a/src/gr-fadingui/grc/CMakeLists.txt b/src/gr-fadingui/grc/CMakeLists.txt index 2394de4..d5f23a6 100644 --- a/src/gr-fadingui/grc/CMakeLists.txt +++ b/src/gr-fadingui/grc/CMakeLists.txt @@ -20,7 +20,6 @@ install(FILES fadingui_datasource.block.yml fadingui_dearpygui_sink.block.yml - fadingui_xor_frame_sync.block.yml fadingui_deframer.block.yml fadingui_frame_obj.block.yml fadingui_multipath_fading.block.yml DESTINATION share/gnuradio/grc/blocks diff --git a/src/gr-fadingui/grc/fadingui_xor_frame_sync.block.yml b/src/gr-fadingui/grc/fadingui_xor_frame_sync.block.yml deleted file mode 100644 index 1a8640d..0000000 --- a/src/gr-fadingui/grc/fadingui_xor_frame_sync.block.yml +++ /dev/null @@ -1,42 +0,0 @@ -id: fadingui_xor_frame_sync -label: XOR Correlation Synchronizer -category: '[fadingui]' -flags: [ python ] - -templates: - imports: import fadingui - make: fadingui.xor_frame_sync(sync_pattern=${pattern}, buffer_size=${buffer_size}) - -# Make one 'parameters' list entry for every parameter you want settable from the GUI. -# Keys include: -# * id (makes the value accessible as \$keyname, e.g. in the make entry) -# * label (label shown in the GUI) -# * dtype (e.g. int, float, complex, byte, short, xxx_vector, ...) -parameters: -- id: pattern - label: Bit pattern - dtype: raw -- id: buffer_size - label: Delay buffer size - dtype: raw - -# Make one 'inputs' list entry per input and one 'outputs' list entry per output. -# Keys include: -# * label (an identifier for the GUI) -# * domain (optional - stream or message. Default is stream) -# * dtype (e.g. int, float, complex, byte, short, xxx_vector, ...) -# * vlen (optional - data stream vector length. Default is 1) -# * optional (optional - set to 1 for optional inputs. Default is 0) -inputs: -- label: in - domain: stream - dtype: byte - -outputs: -- label: out - domain: stream - dtype: byte - -# 'file_format' specifies the version of the GRC yml format used in the file -# and should usually not be changed. -file_format: 1 diff --git a/src/gr-fadingui/python/CMakeLists.txt b/src/gr-fadingui/python/CMakeLists.txt index 95bb852..eb0e7cc 100644 --- a/src/gr-fadingui/python/CMakeLists.txt +++ b/src/gr-fadingui/python/CMakeLists.txt @@ -35,7 +35,6 @@ GR_PYTHON_INSTALL( logger.py datasource.py dearpygui_sink.py - xor_frame_sync.py deframer.py frame_obj.py multipath_fading.py DESTINATION ${GR_PYTHON_DIR}/fadingui @@ -48,5 +47,4 @@ include(GrTest) set(GR_TEST_TARGET_DEPS gnuradio-fadingui) set(GR_TEST_PYTHON_DIRS ${CMAKE_BINARY_DIR}/swig) -GR_ADD_TEST(qa_xor_frame_sync ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa_xor_frame_sync.py) GR_ADD_TEST(qa_multipath_fading ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa_multipath_fading.py) diff --git a/src/gr-fadingui/python/__init__.py b/src/gr-fadingui/python/__init__.py index 5a7b546..dba999e 100644 --- a/src/gr-fadingui/python/__init__.py +++ b/src/gr-fadingui/python/__init__.py @@ -34,7 +34,7 @@ except ImportError: # import any pure python here from .datasource import datasource from .dearpygui_sink import dearpygui_sink -from .xor_frame_sync import xor_frame_sync + from .deframer import deframer from .frame_obj import frame_obj from .multipath_fading import multipath_fading diff --git a/src/gr-fadingui/python/qa_xor_frame_sync.py b/src/gr-fadingui/python/qa_xor_frame_sync.py deleted file mode 100644 index 9c480a0..0000000 --- a/src/gr-fadingui/python/qa_xor_frame_sync.py +++ /dev/null @@ -1,57 +0,0 @@ -#!/usr/bin/env python - -from gnuradio import gr, gr_unittest, blocks - -from xor_frame_sync import xor_frame_sync -import numpy as np - - -class test_xor_frame_sync(gr_unittest.TestCase): - - def setUp(self): - self.tb = gr.top_block() - - def tearDown(self): - self.tb = None - - def test_001(self): - """Test a byte aligned delay""" - pattern = np.array([0xc0, 0xff, 0xee], dtype=np.uint8) - testdata = np.packbits(np.concatenate([ - np.unpackbits(np.arange(0, 5, dtype=np.uint8)), - np.random.randint(0, 2, size = 8 * 5), - np.unpackbits(pattern), - np.random.randint(0, 2, size = 64) - ])) - - src = blocks.vector_source_b(testdata) - op = xor_frame_sync(pattern, 2048) - dst = blocks.vector_sink_b() - - self.tb.connect(src, op, dst) - self.tb.run() - - self.assertEqual(op.synchronized, True) - - # FIXME: implement feature - # def test_002(self): - # """Test a byte unaligned delay""" - # pattern = np.array([0xbe, 0xef], dtype=np.uint8) - # testdata = np.packbits(np.concatenate([ - # np.unpackbits(np.arange(0, 10, dtype=np.uint8)), - # np.random.randint(0, 2, size = (2 + 8 * 5)), np.unpackbits(pattern), - # np.random.randint(0, 2, size = 64) - # ])) - - # src = blocks.vector_source_b(testdata) - # op = xor_frame_sync(pattern, 2048) - # dst = blocks.vector_sink_b() - - # self.tb.connect(src, op, dst) - # self.tb.run() - - # self.assertEqual(op.synchronized, True) - - -if __name__ == "__main__": - gr_unittest.run(test_xor_frame_sync) diff --git a/src/gr-fadingui/python/xor_frame_sync.py b/src/gr-fadingui/python/xor_frame_sync.py deleted file mode 100644 index bb5cfb1..0000000 --- a/src/gr-fadingui/python/xor_frame_sync.py +++ /dev/null @@ -1,152 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -# Copyright 2021 Naoki Pross. - - -import numpy as np -from numpy_ringbuffer import RingBuffer - -from gnuradio import gr - -from fadingui.logger import get_logger -log = get_logger("xor_frame_sync") - - -class xor_frame_sync(gr.sync_block): - """ - Performs a frame synchronization by XOR matching a preamble bit sequence - """ - def __init__(self, sync_pattern, buffer_size): - # TODO: buffer size should be in packets - gr.sync_block.__init__(self, - name="xor_frame_sync", - in_sig=[np.byte], - out_sig=[np.byte]) - - # binary pattern to match - self.pattern = sync_pattern - self.nbytes = len(self.pattern) - - self.pattern_bits = np.unpackbits(np.array(self.pattern, dtype=np.uint8))[::-1] - self.nbits = len(self.pattern_bits) - - log.debug(f"Loaded pattern {self.pattern_bits} length={self.nbits}") - assert(self.nbits % 8 == 0) - - # packed buffer to delay the data - self.delaybuf = RingBuffer(buffer_size, dtype=np.uint8) - self.delay = 0 - - log.debug(f"Created delay ring buffer of size {self.delaybuf.maxlen}") - - # unpacked buffer to compute correlation values, initially filled with zeros - self.corrbuf = RingBuffer(self.nbits, dtype=np.uint8) - self.corrbuf.extend(np.zeros(self.corrbuf.maxlen)) - - # synchronization state - self.synchronized = False - - def xcorrelation(self, v): - """ - Compute the binary correlations between the stored pattern and - correlation buffer, while shifting v into the buffer. - - Binary correlation between two bit vectors is just size of the - vector(s) minus the number of bits that differ. - - @return: Number of bits of v that were shifted into the buffer - when the correlation matched. If no match is found - the return value is None. - """ - # this could be much faster with shifts, bitwise or and xor - # but this should do alright for the moment - v_bits = np.unpackbits(np.array(v, dtype=np.uint8)) - for bitnr, b in enumerate(v_bits): - self.corrbuf.appendleft(b) - if (np.bitwise_xor(self.corrbuf, self.pattern_bits) == 0).all(): - return bitnr - - # no cross correlation found - return None - - def work(self, input_items, output_items): - """ - Process the inputs, that means: - - - Check that the buffer is synchronized, i.e. there is the sync - pattern appears every k bits, where k is the size of the packet. - - - If the buffer is not synchronized, compute a binary cross - correlation to find how much the stream should be delayed. - """ - # array of samples, growing index = forward in time - inp = input_items[0] - inp_len = len(inp) - - if not self.synchronized: - if inp_len > self.delaybuf.maxlen: - log.error("Input is bigger than delay buffer") - - # FIXME: Makes the QA hang for some reason - raise NotImplemented - - # create space for new samples in the delay buffer - self.delaybuf.extendleft(np.zeros(inp_len)) - - # Add values and while processing - for bytenr, value in enumerate(inp): - # save value in the buffer - # FIXME: this is wrong, it should be in reverse order - self.delaybuf.appendleft(value) - - # compute the cross correlation - bitnr = self.xcorrelation(value) - if bitnr is not None: - # correlation was found - delay_bits = (bitnr - 7) - delay_bytes = 8 * (bytenr -1) - - log.debug(f"Synchronized with delay_bytes={delay_bytes} delay_bits={delay_bits}") - - # FIXME: add bit delay - self.delay = delay_bytes - self.synchronized = True - - # Not aligned to bytes - if delay_bits != 0: - log.error("Not implemented: byte unaligned delay") - self.synchronized = False - self.delay = 0 - - # FIXME: Makes the QA hang for some reason - # raise NotImplemented - - # stop processing inputs - break - - if not self.synchronized: - log.warning(f"Processed {inp_len} samples but could not synchronize") - else: - self.delaybuf.extendleft(inp) - - # return data with delay - out = output_items[0] - # FIXME: this is also wrong - # out[:] = self.delaybuf[:len(out)] - out[:] = inp[:] - - - inptmp = np.array(inp[:12], dtype=np.uint8) - inphex = np.array(list(map(hex, inptmp))) - inpbits = np.array(list(map("{:08b}".format, inptmp))) - - log.debug(f"inp={inptmp}") - log.debug(f"inp={inphex}") - log.debug(f"inp={inpbits}") - - # outtmp = np.array(out[:12], dtype=np.uint8) - # log.debug(f"out={outtmp}") - - return inp_len - -- 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 --- src/gr-fadingui/grc/CMakeLists.txt | 3 +- src/gr-fadingui/grc/fadingui_ber.block.yml | 37 ++++++++++++++++++++ src/gr-fadingui/python/CMakeLists.txt | 4 ++- src/gr-fadingui/python/__init__.py | 1 + src/gr-fadingui/python/ber.py | 55 ++++++++++++++++++++++++++++++ src/gr-fadingui/python/qa_ber.py | 41 ++++++++++++++++++++++ 6 files changed, 139 insertions(+), 2 deletions(-) create mode 100644 src/gr-fadingui/grc/fadingui_ber.block.yml create mode 100644 src/gr-fadingui/python/ber.py create mode 100755 src/gr-fadingui/python/qa_ber.py (limited to 'src') diff --git a/src/gr-fadingui/grc/CMakeLists.txt b/src/gr-fadingui/grc/CMakeLists.txt index d5f23a6..297ae8d 100644 --- a/src/gr-fadingui/grc/CMakeLists.txt +++ b/src/gr-fadingui/grc/CMakeLists.txt @@ -22,5 +22,6 @@ install(FILES fadingui_dearpygui_sink.block.yml fadingui_deframer.block.yml fadingui_frame_obj.block.yml - fadingui_multipath_fading.block.yml DESTINATION share/gnuradio/grc/blocks + fadingui_multipath_fading.block.yml + fadingui_ber.block.yml DESTINATION share/gnuradio/grc/blocks ) diff --git a/src/gr-fadingui/grc/fadingui_ber.block.yml b/src/gr-fadingui/grc/fadingui_ber.block.yml new file mode 100644 index 0000000..3383df5 --- /dev/null +++ b/src/gr-fadingui/grc/fadingui_ber.block.yml @@ -0,0 +1,37 @@ +id: fadingui_ber +label: BER +category: '[fadingui]' + +templates: + imports: import fadingui + make: fadingui.ber(vgl=${vgl}) + +# Make one 'parameters' list entry for every parameter you want settable from the GUI. +# Keys include: +# * id (makes the value accessible as \$keyname, e.g. in the make entry) +# * label (label shown in the GUI) +# * dtype (e.g. int, float, complex, byte, short, xxx_vector, ...) +parameters: + - id: vgl + label: Vergleichsparameter + dtype: raw +# - id: ... +# label: ... +# dtype: ... + +# Make one 'inputs' list entry per input and one 'outputs' list entry per output. +# Keys include: +# * label (an identifier for the GUI) +# * domain (optional - stream or message. Default is stream) +# * dtype (e.g. int, float, complex, byte, short, xxx_vector, ...) +# * vlen (optional - data stream vector length. Default is 1) +# * optional (optional - set to 1 for optional inputs. Default is 0) +inputs: +- label: in + domain: stream + dtype: byte + + +# 'file_format' specifies the version of the GRC yml format used in the file +# and should usually not be changed. +file_format: 1 diff --git a/src/gr-fadingui/python/CMakeLists.txt b/src/gr-fadingui/python/CMakeLists.txt index eb0e7cc..e04eb5b 100644 --- a/src/gr-fadingui/python/CMakeLists.txt +++ b/src/gr-fadingui/python/CMakeLists.txt @@ -37,7 +37,8 @@ GR_PYTHON_INSTALL( dearpygui_sink.py deframer.py frame_obj.py - multipath_fading.py DESTINATION ${GR_PYTHON_DIR}/fadingui + multipath_fading.py + ber.py DESTINATION ${GR_PYTHON_DIR}/fadingui ) ######################################################################## @@ -48,3 +49,4 @@ include(GrTest) set(GR_TEST_TARGET_DEPS gnuradio-fadingui) set(GR_TEST_PYTHON_DIRS ${CMAKE_BINARY_DIR}/swig) GR_ADD_TEST(qa_multipath_fading ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa_multipath_fading.py) +GR_ADD_TEST(qa_ber ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa_ber.py) diff --git a/src/gr-fadingui/python/__init__.py b/src/gr-fadingui/python/__init__.py index dba999e..9fe45d5 100644 --- a/src/gr-fadingui/python/__init__.py +++ b/src/gr-fadingui/python/__init__.py @@ -38,5 +38,6 @@ 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 # diff --git a/src/gr-fadingui/python/ber.py b/src/gr-fadingui/python/ber.py new file mode 100644 index 0000000..387b75f --- /dev/null +++ b/src/gr-fadingui/python/ber.py @@ -0,0 +1,55 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +# Copyright 2021 Sara Cinzia Halter. +# +# This is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# This software is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this software; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + + +import numpy as np +from gnuradio import gr + +from fadingui.logger import get_logger +log = get_logger("ber") + +class ber(gr.sync_block): + """ + docstring for block ber + """ + def __init__(self, vgl): + gr.sync_block.__init__(self, + name="ber", + in_sig=[np.byte, ], + out_sig=None) + self.vgl=vgl + + + + def work(self, input_items, output_items): + inp = input_items[0] + # <+signal processing here+> + + v = self.vgl^inp + v_array= np.array(v,dtype = np.uint8) + + ber = sum(np.unpackbits(v_array)) + + + log.debug(ber) + + return len(input_items[0]) + diff --git a/src/gr-fadingui/python/qa_ber.py b/src/gr-fadingui/python/qa_ber.py new file mode 100755 index 0000000..8b6d56e --- /dev/null +++ b/src/gr-fadingui/python/qa_ber.py @@ -0,0 +1,41 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +# Copyright 2021 Sara Cinzia Halter. +# +# This is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# This software is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this software; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +from gnuradio import gr, gr_unittest +from gnuradio import blocks +from ber import ber + +class qa_ber(gr_unittest.TestCase): + + def setUp(self): + self.tb = gr.top_block() + + def tearDown(self): + self.tb = None + + def test_001_t(self): + # set up fg + self.tb.run() + # check data + + +if __name__ == '__main__': + gr_unittest.run(qa_ber) -- 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 --- src/gr-fadingui/grc/fadingui_ber.block.yml | 16 ++++++++-------- src/gr-fadingui/python/ber.py | 29 ++++++++++++++++------------- src/gr-fadingui/python/qa_ber.py | 13 ++++++++++--- 3 files changed, 34 insertions(+), 24 deletions(-) (limited to 'src') diff --git a/src/gr-fadingui/grc/fadingui_ber.block.yml b/src/gr-fadingui/grc/fadingui_ber.block.yml index 3383df5..3070311 100644 --- a/src/gr-fadingui/grc/fadingui_ber.block.yml +++ b/src/gr-fadingui/grc/fadingui_ber.block.yml @@ -4,7 +4,7 @@ category: '[fadingui]' templates: imports: import fadingui - make: fadingui.ber(vgl=${vgl}) + make: fadingui.ber(vgl=${vgl}, vlen=${vlen}) # Make one 'parameters' list entry for every parameter you want settable from the GUI. # Keys include: @@ -12,12 +12,12 @@ templates: # * label (label shown in the GUI) # * dtype (e.g. int, float, complex, byte, short, xxx_vector, ...) parameters: - - id: vgl - label: Vergleichsparameter - dtype: raw -# - id: ... -# label: ... -# dtype: ... +- id: vgl + label: Vergleichsparameter + dtype: raw +- id: vlen + label: Vec Length + dtype: int # Make one 'inputs' list entry per input and one 'outputs' list entry per output. # Keys include: @@ -30,7 +30,7 @@ inputs: - label: in domain: stream dtype: byte - + 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/ber.py b/src/gr-fadingui/python/ber.py index 387b75f..e966f17 100644 --- a/src/gr-fadingui/python/ber.py +++ b/src/gr-fadingui/python/ber.py @@ -30,26 +30,29 @@ class ber(gr.sync_block): """ docstring for block ber """ - def __init__(self, vgl): + def __init__(self, vgl, vlen): gr.sync_block.__init__(self, name="ber", - in_sig=[np.byte, ], + in_sig=[np.dtype(str(vlen) + "b")], out_sig=None) self.vgl=vgl - - + self.vlen=vlen def work(self, input_items, output_items): + inp = input_items[0] - # <+signal processing here+> - - v = self.vgl^inp - v_array= np.array(v,dtype = np.uint8) - - ber = sum(np.unpackbits(v_array)) - - - log.debug(ber) + ber_tot = 0 + log.debug(f"Length: {len(inp)}") + log.debug(f"Inp_vector:{inp}") + + for i in inp: + log.debug(f"In Schlaufe{i}") + v = np.array(self.vgl, dtype=np.uint8)^np.array(i, dtype=np.uint8) + ber = sum(np.unpackbits(v)) + log.debug(f"BER {ber} in Paket {i}") + ber_tot+=ber + log.debug(f"BER Total{ber_tot}") + return len(input_items[0]) diff --git a/src/gr-fadingui/python/qa_ber.py b/src/gr-fadingui/python/qa_ber.py index 8b6d56e..cb6c198 100755 --- a/src/gr-fadingui/python/qa_ber.py +++ b/src/gr-fadingui/python/qa_ber.py @@ -22,6 +22,7 @@ from gnuradio import gr, gr_unittest from gnuradio import blocks from ber import ber +import numpy as np class qa_ber(gr_unittest.TestCase): @@ -32,9 +33,15 @@ class qa_ber(gr_unittest.TestCase): self.tb = None def test_001_t(self): - # set up fg - self.tb.run() - # check data + # pattern = np.array([0xaa], dtype=np.uint8) + # testdata = np.array([0xc0, 0xfa, 0xae] * 4, dtype=np.uint8) + + # src = blocks.vector_source_b(testdata) + # op = ber(pattern) + + # self.tb.connect(src, op) + # self.tb.run() + pass if __name__ == '__main__': -- 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 --- src/gr-fadingui/grc/CMakeLists.txt | 4 +- .../grc/fadingui_dearpygui_sink.block.yml | 38 -------------- src/gr-fadingui/grc/fadingui_netsink.block.yml | 48 ++++++++++++++++++ src/gr-fadingui/python/CMakeLists.txt | 4 +- src/gr-fadingui/python/__init__.py | 3 +- src/gr-fadingui/python/dearpygui_sink.py | 36 ------------- src/gr-fadingui/python/netsink.py | 59 ++++++++++++++++++++++ 7 files changed, 113 insertions(+), 79 deletions(-) delete mode 100644 src/gr-fadingui/grc/fadingui_dearpygui_sink.block.yml create mode 100644 src/gr-fadingui/grc/fadingui_netsink.block.yml delete mode 100644 src/gr-fadingui/python/dearpygui_sink.py create mode 100644 src/gr-fadingui/python/netsink.py (limited to 'src') 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_dearpygui_sink.block.yml deleted file mode 100644 index dbe6198..0000000 --- a/src/gr-fadingui/grc/fadingui_dearpygui_sink.block.yml +++ /dev/null @@ -1,38 +0,0 @@ -id: fadingui_dearpygui_sink -label: UI Sink -category: '[fadingui]' - -templates: - imports: import fadingui - make: fadingui.dearpygui_sink(sock_addr=${sock_addr}, ui_element_id=${ui_element_id}) - -# Make one 'parameters' list entry for every parameter you want settable from the GUI. -# Keys include: -# * id (makes the value accessible as \$keyname, e.g. in the make entry) -# * label (label shown in the GUI) -# * dtype (e.g. int, float, complex, byte, short, xxx_vector, ...) -parameters: -- id: sock_addr - label: Socket address - dtype: string - default: udp:// - -- id: ui_element_id - label: UI element ID - dtype: raw - - -# Make one 'inputs' list entry per input and one 'outputs' list entry per output. -# Keys include: -# * label (an identifier for the GUI) -# * domain (optional - stream or message. Default is stream) -# * dtype (e.g. int, float, complex, byte, short, xxx_vector, ...) -# * vlen (optional - data stream vector length. Default is 1) -# * optional (optional - set to 1 for optional inputs. Default is 0) -inputs: -- label: in - dtype: complex - -# 'file_format' specifies the version of the GRC yml format used in the file -# and should usually not be changed. -file_format: 1 diff --git a/src/gr-fadingui/grc/fadingui_netsink.block.yml b/src/gr-fadingui/grc/fadingui_netsink.block.yml new file mode 100644 index 0000000..4e5b01b --- /dev/null +++ b/src/gr-fadingui/grc/fadingui_netsink.block.yml @@ -0,0 +1,48 @@ +id: fadingui_netsink +label: Network Sink +category: '[fadingui]' +flags: [ python ] + +templates: + imports: import fadingui + make: fadingui.netsink(${address}, ${dtype}, ${vlen}) + +# Make one 'parameters' list entry for every parameter you want settable from the GUI. +# Keys include: +# * id (makes the value accessible as \$keyname, e.g. in the make entry) +# * label (label shown in the GUI) +# * dtype (e.g. int, float, complex, byte, short, xxx_vector, ...) +parameters: +- 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://localhost:31415" + +# Make one 'inputs' list entry per input and one 'outputs' list entry per output. +# Keys include: +# * label (an identifier for the GUI) +# * domain (optional - stream or message. Default is stream) +# * dtype (e.g. int, float, complex, byte, short, xxx_vector, ...) +# * vlen (optional - data stream vector length. Default is 1) +# * optional (optional - set to 1 for optional inputs. Default is 0) +inputs: +- label: in + 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. +file_format: 1 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]) + -- cgit v1.2.1 From 97217d7eb3d0dbd07ea7deea1ec13620b8676e2d Mon Sep 17 00:00:00 2001 From: Nao Pross Date: Fri, 3 Dec 2021 22:57:16 +0100 Subject: Fix network sink block The block can be tested with: $ netcat -l4kuv localhost 31415 | hexdump -C --- src/gr-fadingui/grc/fadingui_netsink.block.yml | 23 +++++++++-------- src/gr-fadingui/python/netsink.py | 35 ++++++++++++++++++-------- 2 files changed, 38 insertions(+), 20 deletions(-) (limited to 'src') diff --git a/src/gr-fadingui/grc/fadingui_netsink.block.yml b/src/gr-fadingui/grc/fadingui_netsink.block.yml index 4e5b01b..a23dc52 100644 --- a/src/gr-fadingui/grc/fadingui_netsink.block.yml +++ b/src/gr-fadingui/grc/fadingui_netsink.block.yml @@ -4,8 +4,10 @@ category: '[fadingui]' flags: [ python ] templates: - imports: import fadingui - make: fadingui.netsink(${address}, ${dtype}, ${vlen}) + imports: |- + import fadingui + import numpy as np + make: fadingui.netsink(address=${address}, dtype=${type}, vlen=${veclen}) # Make one 'parameters' list entry for every parameter you want settable from the GUI. # Keys include: @@ -13,18 +15,19 @@ templates: # * label (label shown in the GUI) # * dtype (e.g. int, float, complex, byte, short, xxx_vector, ...) parameters: -- id: dtype +- id: type label: Type dtype: enum - options: [complex, float, int, short, byte] + options: [complex, float, int, np.short, np.byte] + option_labels: [complex, float, int, short, byte] option_attributes: - size: [gr.sizeof_gr_complex, gr.sizeof_floar, gr.sizeof_int, gr.sizeof_short, gr.sizeof_char ] + size: [gr.sizeof_gr_complex, gr.sizeof_float, gr.sizeof_int, gr.sizeof_short, gr.sizeof_char] hide: part -- id: vlen +- id: veclen label: Vec Length dtype: int - default: 1 - hide: ${ 'part' if vlen == 1 else 'none' } + default: '1' + hide: ${ 'part' if veclen == 1 else 'none' } - id: address label: Address dtype: string @@ -40,8 +43,8 @@ parameters: inputs: - label: in domain: stream - dtype: ${dtype} - vlen: ${vlen} + dtype: ${type} + vlen: ${veclen} # '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/netsink.py b/src/gr-fadingui/python/netsink.py index 9df81f5..d2dfc92 100644 --- a/src/gr-fadingui/python/netsink.py +++ b/src/gr-fadingui/python/netsink.py @@ -15,15 +15,18 @@ class netsink(gr.sync_block): Keep in mind that is quite slow. """ def __init__(self, address, dtype, vlen): + dt = np.dtype(dtype, (vlen,)) if vlen > 1 else dtype + print(dt) + gr.sync_block.__init__(self, name="Network Sink", - in_sig=[], + in_sig=[dt], 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) + self.url = urlparse(address) + self.srv = (self.url.hostname, self.url.port) def send(self, data): """ @@ -42,18 +45,30 @@ class netsink(gr.sync_block): @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() - + # FIXME: this could be (very) slow, is there a faster way with numpy? values = "[" + ",".join(map(str, data)) + "]" return bytes(values, "ascii") def work(self, input_items, output_items): + # FIXME: it is probably better NOT to send *every* sample inp = input_items[0] + inp_len = len(inp) + blocksize = 1024 + + # Check that the packet is not huge + if len(inp) < blocksize: + self.send(self.encode(inp)) + else: + # compute how to split inp into blocks + nblocks = inp_len // blocksize + index = blocksize * nblocks - # TODO: Check that inp has a reasonable size - self.send(self.encode(inp)) + # send blocks + blocks = np.array(inp[:index]).reshape((blocksize, nblocks)) + for block in blocks: + self.send(self.encode(block)) - return len(input_items[0]) + # sent the rest + self.send(self.encode(inp[index:])) + return len(inp) -- cgit v1.2.1 From eca32bbd53d4fc51095700621525ac479f06c06c Mon Sep 17 00:00:00 2001 From: sara Date: Sat, 4 Dec 2021 15:19:24 +0100 Subject: Fix network sink block (again) --- src/gr-fadingui/grc/fadingui_netsink.block.yml | 5 ++--- src/gr-fadingui/python/netsink.py | 12 +++++++++++- 2 files changed, 13 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/gr-fadingui/grc/fadingui_netsink.block.yml b/src/gr-fadingui/grc/fadingui_netsink.block.yml index a23dc52..3cd8ae7 100644 --- a/src/gr-fadingui/grc/fadingui_netsink.block.yml +++ b/src/gr-fadingui/grc/fadingui_netsink.block.yml @@ -7,7 +7,7 @@ templates: imports: |- import fadingui import numpy as np - make: fadingui.netsink(address=${address}, dtype=${type}, vlen=${veclen}) + make: fadingui.netsink(address=${address}, dtype="${type}", vlen=${veclen}) # Make one 'parameters' list entry for every parameter you want settable from the GUI. # Keys include: @@ -18,8 +18,7 @@ parameters: - id: type label: Type dtype: enum - options: [complex, float, int, np.short, np.byte] - option_labels: [complex, float, int, short, byte] + options: [complex, float, int, short, byte] option_attributes: size: [gr.sizeof_gr_complex, gr.sizeof_float, gr.sizeof_int, gr.sizeof_short, gr.sizeof_char] hide: part diff --git a/src/gr-fadingui/python/netsink.py b/src/gr-fadingui/python/netsink.py index d2dfc92..130e5dc 100644 --- a/src/gr-fadingui/python/netsink.py +++ b/src/gr-fadingui/python/netsink.py @@ -15,7 +15,17 @@ class netsink(gr.sync_block): Keep in mind that is quite slow. """ def __init__(self, address, dtype, vlen): - dt = np.dtype(dtype, (vlen,)) if vlen > 1 else dtype + to_numpy = { + "complex": np.complex64, + "float": np.float32, + "int": np.int32, + "short": np.short, + "byte": np.byte, + } + + dt = to_numpy[dtype] + if vlen > 1: + dt = np.dtype(dt, (vlen,)) print(dt) gr.sync_block.__init__(self, -- 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 --- src/gui/gui.py | 7 +++--- src/gui/net.py | 67 +++++++++++++++++++++++++++++++++++++--------------------- 2 files changed, 47 insertions(+), 27 deletions(-) (limited to 'src') diff --git a/src/gui/gui.py b/src/gui/gui.py index b2cbebb..d817f63 100755 --- a/src/gui/gui.py +++ b/src/gui/gui.py @@ -98,7 +98,8 @@ with window(label="RX DSP Flow Graph", width=800, height=400, pos=(25,25), tag=" #================================================ # Network plots Window -recv_plot = net.network_plot(url="udp://localhost:31415", nsamples=100, label="Test", height=300, width=800) +recv_plot = net.network_plot(url="udp://localhost:31415", dtype=float, nsamples=100, \ + label="Test", height=300, width=800) plots = { recv_plot: "plt_ampl" @@ -107,9 +108,9 @@ plots = { with window(label="Time domain plots", width=800, height=400, pos=(850,25)): with recv_plot: add_plot_axis(mvXAxis, label="Time") - add_plot_axis(mvYAxis, label="Amplitude", tag="plt_ampl") + add_plot_axis(mvYAxis, label="Amplitude", tag="axis") - add_line_series(recv_plot.x_data, recv_plot.y_data, parent="plt_ampl") + add_line_series(recv_plot.xdata, recv_plot.ydata, parent="axis", tag="plt_ampl") #================================================ # Start GUI and main loop diff --git a/src/gui/net.py b/src/gui/net.py index 2c91bb8..c7008cd 100644 --- a/src/gui/net.py +++ b/src/gui/net.py @@ -1,6 +1,7 @@ import select import socket from urllib.parse import urlparse +import re import numpy as np from numpy_ringbuffer import RingBuffer @@ -11,9 +12,10 @@ class udpsource: """ Creates an UDP listening socket """ - def __init__(self, url): + def __init__(self, url, dtype): self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) self.url = urlparse(url) + self.dtype = dtype def __del__(self): self.sock.close() @@ -23,32 +25,46 @@ class udpsource: self.sock.bind((self.url.hostname, self.url.port)) # self.sock.listen() - def read(self, nbytes): - ready_to_read, ready_to_write, in_err = \ - select.select([self.sock], [], [], 1) - - if ready_to_read: - data = sock.recv(nbytes) - print(data) - else: + def read(self, nblocks): + ready, _, _ = select.select([self.sock], [], []) + if not ready: return None + # read from socket + blocksize = 1024 * 4 + string = ready[0].recv(nblocks * blocksize).decode("ascii") + + # decode string, remove empty values + chunks = filter(None, re.split(r"\[(.+?)\]", string)) + + def chunk_to_samples(chunk): + samples = chunk.split(",") + if samples: + return list(map(self.dtype, samples)) + + # convert each chunk into a list of samples + chunk_values = map(chunk_to_samples, chunks) + + # flatten list of lists into a single list + values = sum(chunk_values, []) + + return values class network_plot(udpsource): - def __init__(self, url, nsamples, **kwargs): - udpsource.__init__(self, url) + def __init__(self, url, dtype, nsamples, **kwargs): + udpsource.__init__(self, url, dtype) + # create buffers for x and y values self.nsamples = nsamples - self.plot = dpg.plot(**kwargs) - - # create buffer and fill with zeroes - self.buffer = RingBuffer(capacity=nsamples, dtype=(float, 2)) - for i in range(nsamples): - # TODO: remove random data used for testing - self.buffer.append(np.array([i, 1 + np.random.rand() / 5])) + self.xvalues = np.arange(0, self.nsamples) + self.yvalues = RingBuffer(capacity=self.nsamples, dtype=np.dtype(dtype)) + self.yvalues.extend(np.zeros(self.nsamples)) + # create a plot + self.plot = dpg.plot(**kwargs) self.bind() + # Map `with' expressions to the underlying plot def __enter__(self): return self.plot.__enter__() @@ -56,13 +72,16 @@ class network_plot(udpsource): self.plot.__exit__(t, val, tb) @property - def x_data(self): - return np.array(self.buffer[:,0]) + def xdata(self): + return self.xvalues @property - def y_data(self): - return np.array(self.buffer[:,1]) + def ydata(self): + return np.array(self.yvalues) def refresh_series(self, tag): - dpg.set_value(tag, [self.x_data, self.y_data]) - pass + new_values = self.read(1) + + if new_values: + self.yvalues.extendleft(new_values) + dpg.set_value(tag, [self.xdata, self.ydata]) -- cgit v1.2.1