summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gr-blocks/examples/CMakeLists.txt1
-rw-r--r--gr-blocks/examples/matrix_interleaver.grc341
-rw-r--r--gr-blocks/grc/blocks.tree.yml1
-rw-r--r--gr-blocks/grc/blocks_matrix_interleaver.block.yml63
-rw-r--r--gr-blocks/python/blocks/CMakeLists.txt1
-rw-r--r--gr-blocks/python/blocks/__init__.py1
-rw-r--r--gr-blocks/python/blocks/matrix_interleaver.py63
-rwxr-xr-xgr-blocks/python/blocks/qa_matrix_interleaver.py62
8 files changed, 533 insertions, 0 deletions
diff --git a/gr-blocks/examples/CMakeLists.txt b/gr-blocks/examples/CMakeLists.txt
index 4529e7fe62..cf7fd90d24 100644
--- a/gr-blocks/examples/CMakeLists.txt
+++ b/gr-blocks/examples/CMakeLists.txt
@@ -7,6 +7,7 @@
install(
FILES
+ matrix_interleaver.grc
matrix_multiplexer.grc
peak_detector2.grc
py_snippets_demo.grc
diff --git a/gr-blocks/examples/matrix_interleaver.grc b/gr-blocks/examples/matrix_interleaver.grc
new file mode 100644
index 0000000000..5358dbe275
--- /dev/null
+++ b/gr-blocks/examples/matrix_interleaver.grc
@@ -0,0 +1,341 @@
+options:
+ parameters:
+ author: Jared Dulmage
+ category: '[GRC Hier Blocks]'
+ cmake_opt: ''
+ comment: ''
+ copyright: 2020 Caliola Engineering, LLC
+ description: Matrix interleaver, inputs along rows, outputs along columns
+ gen_cmake: 'On'
+ gen_linking: dynamic
+ generate_options: qt_gui
+ hier_block_src_path: '.:'
+ id: matrix_interleaver_example
+ 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: Block Interleaver Test
+ window_size: ''
+ states:
+ bus_sink: false
+ bus_source: false
+ bus_structure: null
+ coordinate: [8, 8]
+ rotation: 0
+ state: enabled
+
+blocks:
+- name: cols
+ id: variable
+ parameters:
+ comment: ''
+ value: '8'
+ states:
+ bus_sink: false
+ bus_source: false
+ bus_structure: null
+ coordinate: [8, 215]
+ rotation: 0
+ state: enabled
+- name: rows
+ id: variable
+ parameters:
+ comment: ''
+ value: '4'
+ states:
+ bus_sink: false
+ bus_source: false
+ bus_structure: null
+ coordinate: [8, 152]
+ rotation: 0
+ state: enabled
+- 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_add_const_vxx_0
+ id: blocks_add_const_vxx
+ parameters:
+ affinity: ''
+ alias: ''
+ comment: Offset for visual
+ const: '1'
+ maxoutbuf: '0'
+ minoutbuf: '0'
+ type: float
+ vlen: '1'
+ states:
+ bus_sink: false
+ bus_source: false
+ bus_structure: null
+ coordinate: [640, 215]
+ rotation: 0
+ state: true
+- name: blocks_add_const_vxx_0_0
+ id: blocks_add_const_vxx
+ parameters:
+ affinity: ''
+ alias: ''
+ comment: Offset for visual
+ const: '1'
+ maxoutbuf: '0'
+ minoutbuf: '0'
+ type: float
+ vlen: '1'
+ states:
+ bus_sink: false
+ bus_source: false
+ bus_structure: null
+ coordinate: [640, 318]
+ rotation: 0
+ state: true
+- name: blocks_matrix_interleaver_0
+ id: blocks_matrix_interleaver
+ parameters:
+ affinity: ''
+ alias: ''
+ cols: cols
+ comment: ''
+ deint: 'False'
+ maxoutbuf: '0'
+ minoutbuf: '0'
+ rows: rows
+ type: float
+ vlen: '1'
+ states:
+ bus_sink: false
+ bus_source: false
+ bus_structure: null
+ coordinate: [447, 199]
+ rotation: 0
+ state: true
+- name: blocks_matrix_interleaver_0_0
+ id: blocks_matrix_interleaver
+ parameters:
+ affinity: ''
+ alias: ''
+ cols: cols
+ comment: ''
+ deint: 'True'
+ maxoutbuf: '0'
+ minoutbuf: '0'
+ rows: rows
+ type: float
+ vlen: '1'
+ states:
+ bus_sink: false
+ bus_source: false
+ bus_structure: null
+ coordinate: [448, 302]
+ rotation: 0
+ state: true
+- name: blocks_stream_to_vector_0
+ id: blocks_stream_to_vector
+ parameters:
+ affinity: ''
+ alias: ''
+ comment: ''
+ maxoutbuf: '0'
+ minoutbuf: '0'
+ num_items: rows * cols
+ type: float
+ vlen: '1'
+ states:
+ bus_sink: false
+ bus_source: false
+ bus_structure: null
+ coordinate: [824, 219]
+ rotation: 0
+ state: true
+- name: blocks_stream_to_vector_0_0
+ id: blocks_stream_to_vector
+ parameters:
+ affinity: ''
+ alias: ''
+ comment: ''
+ maxoutbuf: '0'
+ minoutbuf: '0'
+ num_items: rows * cols
+ type: float
+ vlen: '1'
+ states:
+ bus_sink: false
+ bus_source: false
+ bus_structure: null
+ coordinate: [824, 152]
+ rotation: 0
+ state: true
+- name: blocks_stream_to_vector_0_1
+ id: blocks_stream_to_vector
+ parameters:
+ affinity: ''
+ alias: ''
+ comment: ''
+ maxoutbuf: '0'
+ minoutbuf: '0'
+ num_items: rows * cols
+ type: float
+ vlen: '1'
+ states:
+ bus_sink: false
+ bus_source: false
+ bus_structure: null
+ coordinate: [824, 283]
+ 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: float
+ vlen: '1'
+ states:
+ bus_sink: false
+ bus_source: false
+ bus_structure: null
+ coordinate: [452, 148]
+ rotation: 0
+ state: true
+- name: blocks_vector_source_x_0
+ id: blocks_vector_source_x
+ parameters:
+ affinity: ''
+ alias: ''
+ comment: ''
+ maxoutbuf: '0'
+ minoutbuf: '0'
+ repeat: 'True'
+ tags: '[]'
+ type: float
+ vector: np.kron(np.ones(cols), np.arange(rows))
+ vlen: '1'
+ states:
+ bus_sink: false
+ bus_source: false
+ bus_structure: null
+ coordinate: [115, 199]
+ 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: [300, 15]
+ rotation: 0
+ state: true
+- name: qtgui_vector_sink_f_0
+ id: qtgui_vector_sink_f
+ parameters:
+ affinity: ''
+ alias: ''
+ alpha1: '0.4'
+ alpha10: '1.0'
+ alpha2: '0.4'
+ alpha3: '0.4'
+ alpha4: '1.0'
+ alpha5: '1.0'
+ alpha6: '1.0'
+ alpha7: '1.0'
+ alpha8: '1.0'
+ alpha9: '1.0'
+ autoscale: 'False'
+ average: '1.0'
+ color1: '"blue"'
+ color10: '"dark blue"'
+ color2: '"red"'
+ color3: '"green"'
+ color4: '"black"'
+ color5: '"cyan"'
+ color6: '"magenta"'
+ color7: '"yellow"'
+ color8: '"dark red"'
+ color9: '"dark green"'
+ comment: ''
+ grid: 'True'
+ gui_hint: ''
+ label1: Input
+ label10: ''
+ label2: Interleaved
+ label3: Deinterleaved
+ label4: ''
+ label5: ''
+ label6: ''
+ label7: ''
+ label8: ''
+ label9: ''
+ maxoutbuf: '0'
+ minoutbuf: '0'
+ name: '""'
+ nconnections: '3'
+ ref_level: '0'
+ showports: 'False'
+ update_time: '0.10'
+ vlen: rows * cols
+ width1: '1'
+ width10: '1'
+ width2: '1'
+ width3: '1'
+ width4: '1'
+ width5: '1'
+ width6: '1'
+ width7: '1'
+ width8: '1'
+ width9: '1'
+ x_axis_label: index
+ x_start: '0'
+ x_step: '1.0'
+ x_units: '""'
+ y_axis_label: value
+ y_units: '""'
+ ymax: max(rows, cols) + 1
+ ymin: '-1'
+ states:
+ bus_sink: false
+ bus_source: false
+ bus_structure: null
+ coordinate: [1040, 159]
+ rotation: 0
+ state: true
+
+connections:
+- [blocks_add_const_vxx_0, '0', blocks_matrix_interleaver_0_0, '0']
+- [blocks_add_const_vxx_0, '0', blocks_stream_to_vector_0, '0']
+- [blocks_add_const_vxx_0_0, '0', blocks_stream_to_vector_0_1, '0']
+- [blocks_matrix_interleaver_0, '0', blocks_add_const_vxx_0, '0']
+- [blocks_matrix_interleaver_0_0, '0', blocks_add_const_vxx_0_0, '0']
+- [blocks_stream_to_vector_0, '0', qtgui_vector_sink_f_0, '1']
+- [blocks_stream_to_vector_0_0, '0', qtgui_vector_sink_f_0, '0']
+- [blocks_stream_to_vector_0_1, '0', qtgui_vector_sink_f_0, '2']
+- [blocks_throttle_0, '0', blocks_stream_to_vector_0_0, '0']
+- [blocks_vector_source_x_0, '0', blocks_matrix_interleaver_0, '0']
+- [blocks_vector_source_x_0, '0', blocks_throttle_0, '0']
+
+metadata:
+ file_format: 1
diff --git a/gr-blocks/grc/blocks.tree.yml b/gr-blocks/grc/blocks.tree.yml
index 5fb790efd1..48540f7b72 100644
--- a/gr-blocks/grc/blocks.tree.yml
+++ b/gr-blocks/grc/blocks.tree.yml
@@ -122,6 +122,7 @@
- blocks_stream_to_vector_decimator
- blocks_vector_to_stream
- blocks_vector_to_streams
+ - blocks_matrix_interleaver
- blocks_patterned_interleaver
- blocks_endian_swap
- blocks_vector_insert_x
diff --git a/gr-blocks/grc/blocks_matrix_interleaver.block.yml b/gr-blocks/grc/blocks_matrix_interleaver.block.yml
new file mode 100644
index 0000000000..d2a664a361
--- /dev/null
+++ b/gr-blocks/grc/blocks_matrix_interleaver.block.yml
@@ -0,0 +1,63 @@
+id: blocks_matrix_interleaver
+label: Matrix Interleaver
+flags: [ python ]
+
+templates:
+ imports: from gnuradio import blocks
+ make: |-
+ blocks.matrix_interleaver(
+ itemsize=${ type.size } * ${ vlen }, rows=${ rows }, cols=${ cols }, deint=${ deint }
+ )
+ callbacks:
+ - set_rowsandcols(${ rows }, ${ cols }, ${ deint })
+
+parameters:
+- id: type
+ label: IO Type
+ dtype: enum
+ 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
+- id: vlen
+ label: Vec Length
+ dtype: int
+ default: '1'
+ hide: ${ 'part' if vlen == 1 else 'none' }
+- id: rows
+ label: Rows
+ dtype: int
+ default: '1'
+ hide: none
+- id: cols
+ label: Columns
+ dtype: int
+ default: '1'
+ hide: none
+- id: deint
+ label: Deinterleave
+ dtype: bool
+ options: [True, False]
+ default: False
+ hide: none
+
+inputs:
+- label: in
+ dtype: ${ type }
+ vlen: ${ vlen }
+
+outputs:
+- label: out
+ dtype: ${ type }
+ vlen: ${ vlen }
+
+asserts:
+- ${ vlen > 0 }
+
+documentation: 'Jared Dulmage
+
+ Block interleaver reads inputs into rows and writes outputs by cols
+
+ python/matrix_interleaver.py'
+
+file_format: 1
diff --git a/gr-blocks/python/blocks/CMakeLists.txt b/gr-blocks/python/blocks/CMakeLists.txt
index 25ae7755d5..587c7c7ca2 100644
--- a/gr-blocks/python/blocks/CMakeLists.txt
+++ b/gr-blocks/python/blocks/CMakeLists.txt
@@ -11,6 +11,7 @@ include(GrPython)
GR_PYTHON_INSTALL(
FILES
__init__.py
+ matrix_interleaver.py
parse_file_metadata.py
stream_to_vector_decimator.py
msg_pair_to_var.py
diff --git a/gr-blocks/python/blocks/__init__.py b/gr-blocks/python/blocks/__init__.py
index 4a3bc1ccaf..c9a4b3f756 100644
--- a/gr-blocks/python/blocks/__init__.py
+++ b/gr-blocks/python/blocks/__init__.py
@@ -25,6 +25,7 @@ from .stream_to_vector_decimator import *
from .msg_meta_to_pair import meta_to_pair
from .msg_pair_to_var import msg_pair_to_var
from .var_to_msg import var_to_msg_pair
+from .matrix_interleaver import *
#alias old add_vXX and multiply_vXX
add_vcc = add_cc
diff --git a/gr-blocks/python/blocks/matrix_interleaver.py b/gr-blocks/python/blocks/matrix_interleaver.py
new file mode 100644
index 0000000000..26a8e86a6e
--- /dev/null
+++ b/gr-blocks/python/blocks/matrix_interleaver.py
@@ -0,0 +1,63 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+#
+# Copyright 2021 Caliola Engineering, LLC.
+#
+# This file is part of GNU Radio
+#
+# SPDX-License-Identifier: GPL-3.0-or-later
+#
+
+from gnuradio import gr, blocks
+
+class matrix_interleaver(gr.hier_block2):
+ """
+ Block interleaver writes inputs into conceptual rows of the matrix
+ and reads outputs by conceptual columns of the matrix.
+ In deinterleaver mode it writes inputs into conceptual columns
+ and reads outputs by conceptual rows.
+ """
+
+ def __init__(self, itemsize, rows=1, cols=1, deint=False):
+ gr.hier_block2.__init__(
+ self, "Matrix Interleaver",
+ gr.io_signature(1, 1, itemsize),
+ gr.io_signature(1, 1, itemsize),
+ )
+
+ self.itemsize = itemsize
+ self.set_rowsandcols(rows, cols, deint)
+
+ def set_rowsandcols(self, rows, cols, deint):
+ self.disconnect_all()
+
+ self.passthrough = None
+ self.interleaver = None
+ self.deinterleaver = None
+
+ ##################################################
+ # Parameters
+ ##################################################
+ self.rows = rows
+ self.cols = cols
+ self.deint = deint
+
+ ##################################################
+ # Blocks
+ ##################################################
+ # short circuit for unitary rows / columns
+ if rows == 1 or cols == 1:
+ self.passthrough = blocks.copy(self.itemsize)
+ self.connect((self, 0), (self.passthrough, 0), (self, 0))
+ return
+
+ self.deinterleaver = blocks.deinterleave(self.itemsize, 1 if deint else cols)
+ self.interleaver = blocks.interleave(self.itemsize, cols if deint else 1)
+
+ ##################################################
+ # Connections
+ ##################################################
+ self.connect((self, 0), (self.deinterleaver, 0))
+ for n in range(rows):
+ self.connect((self.deinterleaver, n), (self.interleaver, n))
+ self.connect((self.interleaver, 0), (self, 0))
diff --git a/gr-blocks/python/blocks/qa_matrix_interleaver.py b/gr-blocks/python/blocks/qa_matrix_interleaver.py
new file mode 100755
index 0000000000..d254ef6b55
--- /dev/null
+++ b/gr-blocks/python/blocks/qa_matrix_interleaver.py
@@ -0,0 +1,62 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+#
+# Copyright 2021 Caliola Engineering, LLC.
+#
+# This file is part of GNU Radio
+#
+# SPDX-License-Identifier: GPL-3.0-or-later
+#
+
+from gnuradio import gr, gr_unittest
+from gnuradio import blocks
+from matrix_interleaver import matrix_interleaver
+
+class qa_matrix_interleaver(gr_unittest.TestCase):
+
+ def setUp(self):
+ self.tb = gr.top_block()
+
+ def tearDown(self):
+ self.tb = None
+
+ def test_interleave(self):
+ tb = self.tb
+
+ # set up fg
+ cols, rows = 4, 10
+ vec = sum((cols * [x,] for x in range(rows)), [])
+ expected = cols * list(range(rows))
+
+ src = blocks.vector_source_f(vec, False)
+ itlv = matrix_interleaver(gr.sizeof_float, rows=rows, cols=cols)
+ snk = blocks.vector_sink_f()
+
+ tb.connect(src, itlv, snk)
+ tb.run()
+ result = snk.data()
+
+ # check data
+ self.assertFloatTuplesAlmostEqual(expected, result)
+
+ def test_deinterleave(self):
+ tb = self.tb
+
+ # set up fg
+ cols, rows = 4, 10
+ vec = sum((rows * [x,] for x in range(cols)), [])
+ expected = rows * list(range(cols))
+
+ src = blocks.vector_source_f(vec, False)
+ itlv = matrix_interleaver(gr.sizeof_float, rows=rows, cols=cols, deint=True)
+ snk = blocks.vector_sink_f()
+
+ tb.connect(src, itlv, snk)
+ tb.run()
+ result = snk.data()
+
+ # check data
+ self.assertFloatTuplesAlmostEqual(expected, result)
+
+if __name__ == '__main__':
+ gr_unittest.run(qa_matrix_interleaver)