summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJacob Gilbert <jacob.gilbert@protonmail.com>2021-06-11 08:34:20 -0600
committermormj <34754695+mormj@users.noreply.github.com>2021-07-19 06:44:24 -0400
commit98cadbf3d54176b474d8257ae0f2ae6f7c01fc3a (patch)
tree3dfcac84566b837c139f1dcad7e8093e69d51979
parent15a8cce4dadaa895081d1d9816f37e65117cffb5 (diff)
pdu: Adding new blocks
Added take_skip_to_pdu block and pdu lambda blocks, needs examples still Signed-off-by: Jacob Gilbert <jacob.gilbert@protonmail.com>
-rw-r--r--gnuradio-runtime/include/gnuradio/pdu.h4
-rw-r--r--gnuradio-runtime/lib/pdu.cc9
-rw-r--r--gnuradio-runtime/python/gnuradio/gr/bindings/docstrings/pdu_pydoc_template.h3
-rw-r--r--gnuradio-runtime/python/gnuradio/gr/bindings/pdu_python.cc8
-rw-r--r--gr-pdu/grc/pdu.tree.yml2
-rw-r--r--gr-pdu/grc/pdu_pdu_lambda.block.yml41
-rw-r--r--gr-pdu/grc/pdu_take_skip_to_pdu.block.yml43
-rw-r--r--gr-pdu/include/gnuradio/pdu/CMakeLists.txt1
-rw-r--r--gr-pdu/include/gnuradio/pdu/take_skip_to_pdu.h57
-rw-r--r--gr-pdu/lib/CMakeLists.txt1
-rw-r--r--gr-pdu/lib/take_skip_to_pdu_impl.cc157
-rw-r--r--gr-pdu/lib/take_skip_to_pdu_impl.h79
-rw-r--r--gr-pdu/python/pdu/CMakeLists.txt1
-rw-r--r--gr-pdu/python/pdu/__init__.py1
-rw-r--r--gr-pdu/python/pdu/bindings/CMakeLists.txt1
-rw-r--r--gr-pdu/python/pdu/bindings/docstrings/take_skip_to_pdu_pydoc_template.h27
-rw-r--r--gr-pdu/python/pdu/bindings/python_bindings.cc2
-rw-r--r--gr-pdu/python/pdu/bindings/take_skip_to_pdu_python.cc65
-rw-r--r--gr-pdu/python/pdu/pdu_lambda.py87
-rwxr-xr-xgr-pdu/python/pdu/qa_pdu_lambda.py33
-rwxr-xr-xgr-pdu/python/pdu/qa_take_skip_to_pdu.py103
21 files changed, 724 insertions, 1 deletions
diff --git a/gnuradio-runtime/include/gnuradio/pdu.h b/gnuradio-runtime/include/gnuradio/pdu.h
index 187f01abd0..d7dc0a2550 100644
--- a/gnuradio-runtime/include/gnuradio/pdu.h
+++ b/gnuradio-runtime/include/gnuradio/pdu.h
@@ -16,6 +16,10 @@
#include <pmt/pmt.h>
namespace gr {
+namespace metadata_keys {
+GR_RUNTIME_API const pmt::pmt_t pdu_num();
+} /* namespace metadata_keys */
+
namespace msgport_names {
// static const PMT interned string getters for standard port names
GR_RUNTIME_API const pmt::pmt_t bpdu();
diff --git a/gnuradio-runtime/lib/pdu.cc b/gnuradio-runtime/lib/pdu.cc
index 0c0468419a..f860bf395d 100644
--- a/gnuradio-runtime/lib/pdu.cc
+++ b/gnuradio-runtime/lib/pdu.cc
@@ -15,6 +15,15 @@
#include <pmt/pmt.h>
namespace gr {
+namespace metadata_keys {
+
+const pmt::pmt_t pdu_num()
+{
+ static const pmt::pmt_t val = pmt::mp("pdu_num");
+ return val;
+}
+
+} /* namespace metadata_keys */
namespace msgport_names {
const pmt::pmt_t bpdu()
diff --git a/gnuradio-runtime/python/gnuradio/gr/bindings/docstrings/pdu_pydoc_template.h b/gnuradio-runtime/python/gnuradio/gr/bindings/docstrings/pdu_pydoc_template.h
index 8ba6b5ddd0..95180a0309 100644
--- a/gnuradio-runtime/python/gnuradio/gr/bindings/docstrings/pdu_pydoc_template.h
+++ b/gnuradio-runtime/python/gnuradio/gr/bindings/docstrings/pdu_pydoc_template.h
@@ -15,6 +15,9 @@
*/
+static const char* __doc_gr_metadata_keys_pdu_num = R"doc()doc";
+
+
static const char* __doc_gr_msgport_names_bpdu = R"doc()doc";
diff --git a/gnuradio-runtime/python/gnuradio/gr/bindings/pdu_python.cc b/gnuradio-runtime/python/gnuradio/gr/bindings/pdu_python.cc
index 29af603677..e6dec295e7 100644
--- a/gnuradio-runtime/python/gnuradio/gr/bindings/pdu_python.cc
+++ b/gnuradio-runtime/python/gnuradio/gr/bindings/pdu_python.cc
@@ -14,7 +14,7 @@
/* BINDTOOL_GEN_AUTOMATIC(0) */
/* BINDTOOL_USE_PYGCCXML(0) */
/* BINDTOOL_HEADER_FILE(pdu.h) */
-/* BINDTOOL_HEADER_FILE_HASH(d5f32198890a9b1099e6b7ed492650f9) */
+/* BINDTOOL_HEADER_FILE_HASH(e6887fee8ea637d80f0ed7b6f2ffc552) */
/***********************************************************************************/
#include <pybind11/complex.h>
@@ -43,6 +43,12 @@ void bind_pdu(py::module& m)
py::implicitly_convertible<int, ::gr::types::vector_type>();
+ py::module m_metadata_keys = m.def_submodule("metadata_keys");
+
+ m_metadata_keys.def(
+ "pdu_num", &::gr::metadata_keys::pdu_num, D(metadata_keys, pdu_num));
+
+
py::module m_msgport_names = m.def_submodule("msgport_names");
m_msgport_names.def("bpdu", &::gr::msgport_names::bpdu, D(msgport_names, bpdu));
diff --git a/gr-pdu/grc/pdu.tree.yml b/gr-pdu/grc/pdu.tree.yml
index 2c1d2a2c9c..c1e6a5aca5 100644
--- a/gr-pdu/grc/pdu.tree.yml
+++ b/gr-pdu/grc/pdu.tree.yml
@@ -2,10 +2,12 @@
- PDU Tools:
- pdu_add_system_time
- pdu_pdu_filter
+ - pdu_pdu_lambda
- pdu_pdu_remove
- pdu_pdu_set
- pdu_pdu_split
- pdu_pdu_to_tagged_stream
- pdu_tagged_stream_to_pdu
- pdu_random_pdu
+ - pdu_take_skip_to_pdu
- pdu_time_delta
diff --git a/gr-pdu/grc/pdu_pdu_lambda.block.yml b/gr-pdu/grc/pdu_pdu_lambda.block.yml
new file mode 100644
index 0000000000..c483d840e4
--- /dev/null
+++ b/gr-pdu/grc/pdu_pdu_lambda.block.yml
@@ -0,0 +1,41 @@
+id: pdu_pdu_lambda
+label: PDU Lambda
+flags: [ python ]
+
+parameters:
+- id: fn
+ label: Function
+ dtype: raw
+ default: 'lambda x: x*10'
+- id: metadict
+ label: Mode
+ dtype: enum
+ options: [Metadata, Uniform Vector]
+ option_attributes:
+ mode: [True, False]
+ default: True
+ hide: part
+- id: key
+ label: Key
+ dtype: raw
+ default: 'pmt.intern("key")'
+ hide: ${ 'none' if metadict.mode else 'all' }
+
+inputs:
+- id: pdu
+ domain: message
+ optional: true
+
+outputs:
+- id: pdu
+ domain: message
+ optional: true
+
+templates:
+ imports: import pylambda, pmt, numpy as np
+ make: pylambda.pdu_lambda(${fn}, ${metadict.mode}, ${key})
+ callbacks:
+ - set_fn(${fn})
+ - set_fn(${key})
+
+file_format: 1
diff --git a/gr-pdu/grc/pdu_take_skip_to_pdu.block.yml b/gr-pdu/grc/pdu_take_skip_to_pdu.block.yml
new file mode 100644
index 0000000000..293d22c82f
--- /dev/null
+++ b/gr-pdu/grc/pdu_take_skip_to_pdu.block.yml
@@ -0,0 +1,43 @@
+id: pdu_take_skip_to_pdu
+label: Take/Skip To PDU
+flags: [ python ]
+
+parameters:
+- id: type
+ label: PDU Type
+ dtype: enum
+ options: [complex, float, int, short, byte]
+ option_labels: [Complex, Float, Int, Short, Byte]
+ option_attributes:
+ t: [c, f, i, s, b]
+ hide: part
+- id: take
+ label: Take
+ dtype: int
+ default: '1024'
+- id: skip
+ label: Skip
+ dtype: int
+ default: '4096'
+
+inputs:
+- domain: stream
+ dtype: ${ type }
+
+outputs:
+- domain: message
+ id: pdus
+ optional: true
+
+asserts:
+- ${ take >= 1 }
+- ${ skip >= 0 }
+
+templates:
+ imports: from gnuradio import pdu
+ make: pdu.take_skip_to_pdu_${type.t}(${take}, ${skip})
+ callbacks:
+ - set_take(${take})
+ - set_skip(${skip})
+
+file_format: 1
diff --git a/gr-pdu/include/gnuradio/pdu/CMakeLists.txt b/gr-pdu/include/gnuradio/pdu/CMakeLists.txt
index c3d626a3be..89057c021d 100644
--- a/gr-pdu/include/gnuradio/pdu/CMakeLists.txt
+++ b/gr-pdu/include/gnuradio/pdu/CMakeLists.txt
@@ -18,6 +18,7 @@ install(FILES
pdu_to_tagged_stream.h
random_pdu.h
tagged_stream_to_pdu.h
+ take_skip_to_pdu.h
time_delta.h
DESTINATION ${GR_INCLUDE_DIR}/gnuradio/pdu
)
diff --git a/gr-pdu/include/gnuradio/pdu/take_skip_to_pdu.h b/gr-pdu/include/gnuradio/pdu/take_skip_to_pdu.h
new file mode 100644
index 0000000000..3952a64918
--- /dev/null
+++ b/gr-pdu/include/gnuradio/pdu/take_skip_to_pdu.h
@@ -0,0 +1,57 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2021 NTESS LLC.
+ *
+ * This file is part of GNU Radio
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ *
+ */
+
+#ifndef INCLUDED_PDU_TAKE_SKIP_TO_PDU_H
+#define INCLUDED_PDU_TAKE_SKIP_TO_PDU_H
+
+#include <gnuradio/pdu/api.h>
+#include <gnuradio/sync_block.h>
+
+namespace gr {
+namespace pdu {
+
+#ifndef MAXIMUM_PDU_SIZE
+#define MAXIMUM_PDU_SIZE
+#endif
+
+/*!
+ * \brief Extract periodic PDUs from a data stream.
+ * \ingroup pdu_blk
+ *
+ * This block will generate PDUs of size TAKE skipping SKIP samples between
+ *
+ */
+template <class T>
+class PDU_API take_skip_to_pdu : virtual public gr::sync_block
+{
+public:
+ typedef std::shared_ptr<take_skip_to_pdu<T>> sptr;
+
+ /*!
+ * \brief Return a shared_ptr to a new instance of pdu::take_skip_to_pdu.
+ *
+ * @param take - size of generated PDUs in samples
+ * @param skip - number of samples to skip between takes
+ */
+ static sptr make(uint32_t take, uint32_t skip);
+
+ virtual void set_take(uint32_t take) = 0;
+ virtual void set_skip(uint32_t skip) = 0;
+};
+
+typedef take_skip_to_pdu<unsigned char> take_skip_to_pdu_b;
+typedef take_skip_to_pdu<short> take_skip_to_pdu_s;
+typedef take_skip_to_pdu<int> take_skip_to_pdu_i;
+typedef take_skip_to_pdu<float> take_skip_to_pdu_f;
+typedef take_skip_to_pdu<gr_complex> take_skip_to_pdu_c;
+} // namespace pdu
+} // namespace gr
+
+#endif /* INCLUDED_PDU_TAKE_SKIP_TO_PDU_H */
diff --git a/gr-pdu/lib/CMakeLists.txt b/gr-pdu/lib/CMakeLists.txt
index cd071cf73f..331fe0c6ef 100644
--- a/gr-pdu/lib/CMakeLists.txt
+++ b/gr-pdu/lib/CMakeLists.txt
@@ -17,6 +17,7 @@ add_library(gnuradio-pdu
pdu_to_tagged_stream_impl.cc
random_pdu_impl.cc
tagged_stream_to_pdu_impl.cc
+ take_skip_to_pdu_impl.cc
time_delta_impl.cc
)
diff --git a/gr-pdu/lib/take_skip_to_pdu_impl.cc b/gr-pdu/lib/take_skip_to_pdu_impl.cc
new file mode 100644
index 0000000000..0e035fc94b
--- /dev/null
+++ b/gr-pdu/lib/take_skip_to_pdu_impl.cc
@@ -0,0 +1,157 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2021 NTESS LLC.
+ *
+ * This file is part of GNU Radio
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "take_skip_to_pdu_impl.h"
+#include <gnuradio/io_signature.h>
+#include <gnuradio/pdu.h>
+
+namespace gr {
+namespace pdu {
+
+template <class T>
+typename take_skip_to_pdu<T>::sptr take_skip_to_pdu<T>::make(uint32_t take, uint32_t skip)
+{
+ return gnuradio::make_block_sptr<take_skip_to_pdu_impl<T>>(take, skip);
+}
+
+/*
+ * The private constructor
+ */
+template <class T>
+take_skip_to_pdu_impl<T>::take_skip_to_pdu_impl(uint32_t take, uint32_t skip)
+ : gr::sync_block("take_skip_to_pdu",
+ gr::io_signature::make(1, 1, sizeof(T)),
+ gr::io_signature::make(0, 0, 0)),
+ d_take(take),
+ d_skip(skip),
+ d_next(take),
+ d_triggered(true),
+ d_burst_counter(0),
+ d_prev_byte(0)
+{
+ if (d_take == 0) {
+ GR_LOG_FATAL(this->d_logger, "TAKE value too small, must be > 0");
+ throw std::invalid_argument("TAKE value out of bounds");
+ }
+
+ d_vector.clear();
+ d_meta_dict = pmt::make_dict();
+ this->message_port_register_out(msgport_names::pdus());
+
+ GR_LOG_INFO(this->d_logger, "Starting Take Skip PDU Generator!");
+}
+
+
+/*
+ * Our virtual destructor.
+ */
+template <class T>
+take_skip_to_pdu_impl<T>::~take_skip_to_pdu_impl()
+{
+}
+
+template <class T>
+bool take_skip_to_pdu_impl<T>::stop()
+{
+ GR_LOG_NOTICE(this->d_logger, boost::format("Generated %d PDUs") % d_burst_counter);
+ return true;
+}
+
+template <class T>
+void take_skip_to_pdu_impl<T>::publish_message()
+{
+ d_meta_dict = pmt::dict_add(
+ d_meta_dict, metadata_keys::pdu_num(), pmt::from_uint64(d_burst_counter));
+
+ // publish mesage
+ this->message_port_pub(msgport_names::pdus(),
+ pmt::cons(d_meta_dict, this->init_data(d_vector)));
+
+ // prepare for next burst
+ d_burst_counter++;
+ d_triggered = false;
+ d_vector.clear();
+}
+
+
+template <class T>
+int take_skip_to_pdu_impl<T>::work(int noutput_items,
+ gr_vector_const_void_star& input_items,
+ gr_vector_void_star& output_items)
+{
+ gr::thread::scoped_lock l(this->d_setlock);
+
+ const T* in = (const T*)input_items[0];
+ uint64_t consumed = noutput_items;
+ bool start_stop = false;
+
+ // figure out where the next start/stop point is
+ if (d_next <= (this->nitems_read(0) + noutput_items)) {
+ // we are going to start/stop during this buffer
+ consumed = d_next - this->nitems_read(0);
+ start_stop = true;
+ if (d_triggered) {
+ d_next += d_skip;
+ } else {
+ d_next += d_take;
+ }
+ }
+
+ if (d_triggered) {
+ // we are saving data
+ // std::cout << " adding " << consumed << " items to the queue" << std::endl;
+ d_vector.insert(d_vector.end(), &in[0], &in[consumed]);
+ if (start_stop) {
+ // std::cout << " publishing message with " << d_vector.size() << " items"
+ // << std::endl;
+ publish_message();
+ if (d_skip == 0) {
+ d_triggered = true;
+ d_next += d_take;
+ }
+ }
+ } else {
+ // if we are not saving data but need to start next time:
+ if (start_stop)
+ d_triggered = true;
+ }
+
+ // Tell runtime system how many output items we produced.
+ return consumed;
+}
+
+template <class T>
+void take_skip_to_pdu_impl<T>::set_take(uint32_t take)
+{
+ gr::thread::scoped_lock l(this->d_setlock);
+
+ d_take = take;
+}
+
+
+template <class T>
+void take_skip_to_pdu_impl<T>::set_skip(uint32_t skip)
+{
+ gr::thread::scoped_lock l(this->d_setlock);
+
+ d_skip = skip;
+}
+
+template class take_skip_to_pdu<unsigned char>;
+template class take_skip_to_pdu<short>;
+template class take_skip_to_pdu<int>;
+template class take_skip_to_pdu<float>;
+template class take_skip_to_pdu<gr_complex>;
+} /* namespace pdu */
+} /* namespace gr */
diff --git a/gr-pdu/lib/take_skip_to_pdu_impl.h b/gr-pdu/lib/take_skip_to_pdu_impl.h
new file mode 100644
index 0000000000..f4dc8828be
--- /dev/null
+++ b/gr-pdu/lib/take_skip_to_pdu_impl.h
@@ -0,0 +1,79 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2021 NTESS LLC.
+ *
+ * This file is part of GNU Radio
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ *
+ */
+
+#ifndef INCLUDED_PDU_TAKE_SKIP_TO_PDU_IMPL_H
+#define INCLUDED_PDU_TAKE_SKIP_TO_PDU_IMPL_H
+
+#include <gnuradio/pdu/take_skip_to_pdu.h>
+
+namespace gr {
+namespace pdu {
+
+template <class T>
+class PDU_API take_skip_to_pdu_impl : public take_skip_to_pdu<T>
+{
+private:
+ // overloaded pmt uniform vector initializers
+ inline pmt::pmt_t init_data(const std::vector<unsigned char> data)
+ {
+ return pmt::init_u8vector(data.size(), (const unsigned char*)&data[0]);
+ }
+ inline pmt::pmt_t init_data(const std::vector<short> data)
+ {
+ return pmt::init_s16vector(data.size(), (const short*)&data[0]);
+ }
+ inline pmt::pmt_t init_data(const std::vector<int> data)
+ {
+ return pmt::init_s32vector(data.size(), (const int*)&data[0]);
+ }
+ inline pmt::pmt_t init_data(const std::vector<float> data)
+ {
+ return pmt::init_f32vector(data.size(), (const float*)&data[0]);
+ }
+ inline pmt::pmt_t init_data(const std::vector<gr_complex> data)
+ {
+ return pmt::init_c32vector(data.size(), (const gr_complex*)&data[0]);
+ }
+
+private:
+ uint32_t d_take;
+ uint32_t d_skip;
+ uint64_t d_next;
+ bool d_triggered;
+ uint64_t d_burst_counter;
+ uint8_t d_prev_byte;
+
+ std::vector<T> d_vector;
+ pmt::pmt_t d_meta_dict;
+
+ /*!
+ * \brief Publishes accumulated data as a PDU.
+ */
+ void publish_message();
+
+public:
+ take_skip_to_pdu_impl(uint32_t take, uint32_t skip);
+
+ ~take_skip_to_pdu_impl() override;
+ bool stop() override;
+
+ void set_take(const uint32_t take) override;
+ void set_skip(const uint32_t skip) override;
+
+ // Where all the action really happens
+ int work(int noutput_items,
+ gr_vector_const_void_star& input_items,
+ gr_vector_void_star& output_items) override;
+};
+
+} // namespace pdu
+} // namespace gr
+
+#endif /* INCLUDED_PDU_TAKE_SKIP_TO_PDU_IMPL_H */
diff --git a/gr-pdu/python/pdu/CMakeLists.txt b/gr-pdu/python/pdu/CMakeLists.txt
index 1a1bb25f8e..902dadc2f5 100644
--- a/gr-pdu/python/pdu/CMakeLists.txt
+++ b/gr-pdu/python/pdu/CMakeLists.txt
@@ -11,6 +11,7 @@ include(GrPython)
GR_PYTHON_INSTALL(
FILES
__init__.py
+ pdu_lambda.py
DESTINATION ${GR_PYTHON_DIR}/gnuradio/pdu
)
diff --git a/gr-pdu/python/pdu/__init__.py b/gr-pdu/python/pdu/__init__.py
index 01e94a056c..c1b7861d7d 100644
--- a/gr-pdu/python/pdu/__init__.py
+++ b/gr-pdu/python/pdu/__init__.py
@@ -21,3 +21,4 @@ except ImportError:
from .pdu_python import *
# import any pure python here
+from .pdu_lambda import pdu_lambda
diff --git a/gr-pdu/python/pdu/bindings/CMakeLists.txt b/gr-pdu/python/pdu/bindings/CMakeLists.txt
index 79334e2440..c462de7a97 100644
--- a/gr-pdu/python/pdu/bindings/CMakeLists.txt
+++ b/gr-pdu/python/pdu/bindings/CMakeLists.txt
@@ -13,6 +13,7 @@ list(APPEND pdu_python_files
pdu_to_tagged_stream_python.cc
random_pdu_python.cc
tagged_stream_to_pdu_python.cc
+ take_skip_to_pdu_python.cc
time_delta_python.cc
python_bindings.cc)
diff --git a/gr-pdu/python/pdu/bindings/docstrings/take_skip_to_pdu_pydoc_template.h b/gr-pdu/python/pdu/bindings/docstrings/take_skip_to_pdu_pydoc_template.h
new file mode 100644
index 0000000000..4437743663
--- /dev/null
+++ b/gr-pdu/python/pdu/bindings/docstrings/take_skip_to_pdu_pydoc_template.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2021 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ *
+ */
+#include "pydoc_macros.h"
+#define D(...) DOC(gr, pdu, __VA_ARGS__)
+/*
+ This file contains placeholders for docstrings for the Python bindings.
+ Do not edit! These were automatically extracted during the binding process
+ and will be overwritten during the build process
+ */
+
+
+static const char* __doc_gr_pdu_take_skip_to_pdu = R"doc()doc";
+
+
+static const char* __doc_gr_pdu_take_skip_to_pdu_make = R"doc()doc";
+
+
+static const char* __doc_gr_pdu_take_skip_to_pdu_set_take = R"doc()doc";
+
+
+static const char* __doc_gr_pdu_take_skip_to_pdu_set_skip = R"doc()doc";
diff --git a/gr-pdu/python/pdu/bindings/python_bindings.cc b/gr-pdu/python/pdu/bindings/python_bindings.cc
index 0739908789..7929b89d88 100644
--- a/gr-pdu/python/pdu/bindings/python_bindings.cc
+++ b/gr-pdu/python/pdu/bindings/python_bindings.cc
@@ -23,6 +23,7 @@ void bind_pdu_split(py::module&);
void bind_pdu_to_tagged_stream(py::module&);
void bind_random_pdu(py::module&);
void bind_tagged_stream_to_pdu(py::module&);
+void bind_take_skip_to_pdu(py::module&);
void bind_time_delta(py::module&);
// We need this hack because import_array() returns NULL
@@ -52,5 +53,6 @@ PYBIND11_MODULE(pdu_python, m)
bind_pdu_to_tagged_stream(m);
bind_random_pdu(m);
bind_tagged_stream_to_pdu(m);
+ bind_take_skip_to_pdu(m);
bind_time_delta(m);
}
diff --git a/gr-pdu/python/pdu/bindings/take_skip_to_pdu_python.cc b/gr-pdu/python/pdu/bindings/take_skip_to_pdu_python.cc
new file mode 100644
index 0000000000..6cf9fa3fd0
--- /dev/null
+++ b/gr-pdu/python/pdu/bindings/take_skip_to_pdu_python.cc
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2021 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ *
+ */
+
+/***********************************************************************************/
+/* This file is automatically generated using bindtool and can be manually edited */
+/* The following lines can be configured to regenerate this file during cmake */
+/* If manual edits are made, the following tags should be modified accordingly. */
+/* BINDTOOL_GEN_AUTOMATIC(0) */
+/* BINDTOOL_USE_PYGCCXML(0) */
+/* BINDTOOL_HEADER_FILE(take_skip_to_pdu.h) */
+/* BINDTOOL_HEADER_FILE_HASH(0fd64d6f3ff06d4bdfa2031a0afffd27) */
+/***********************************************************************************/
+
+#include <pybind11/complex.h>
+#include <pybind11/pybind11.h>
+#include <pybind11/stl.h>
+
+namespace py = pybind11;
+
+#include <gnuradio/pdu/take_skip_to_pdu.h>
+// pydoc.h is automatically generated in the build directory
+#include <take_skip_to_pdu_pydoc.h>
+
+template <typename T>
+void bind_take_skip_to_pdu_template(py::module& m, const char* classname)
+{
+
+ using take_skip_to_pdu = ::gr::pdu::take_skip_to_pdu<T>;
+
+
+ py::class_<take_skip_to_pdu,
+ gr::sync_block,
+ gr::block,
+ gr::basic_block,
+ std::shared_ptr<take_skip_to_pdu>>(m, classname)
+
+ .def(py::init(&gr::pdu::take_skip_to_pdu<T>::make),
+ py::arg("take"),
+ py::arg("skip"),
+ D(take_skip_to_pdu, make))
+
+ .def("set_take",
+ &take_skip_to_pdu::set_take,
+ py::arg("take"),
+ D(take_skip_to_pdu, set_take))
+
+ .def("set_skip",
+ &take_skip_to_pdu::set_skip,
+ py::arg("skip"),
+ D(take_skip_to_pdu, set_skip));
+}
+
+void bind_take_skip_to_pdu(py::module& m)
+{
+ bind_take_skip_to_pdu_template<unsigned char>(m, "take_skip_to_pdu_b");
+ bind_take_skip_to_pdu_template<short>(m, "take_skip_to_pdu_s");
+ bind_take_skip_to_pdu_template<float>(m, "take_skip_to_pdu_f");
+ bind_take_skip_to_pdu_template<gr_complex>(m, "take_skip_to_pdu_c");
+}
diff --git a/gr-pdu/python/pdu/pdu_lambda.py b/gr-pdu/python/pdu/pdu_lambda.py
new file mode 100644
index 0000000000..6eeb2223a1
--- /dev/null
+++ b/gr-pdu/python/pdu/pdu_lambda.py
@@ -0,0 +1,87 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+#
+# Copyright 2015,2021 Tim O'Shea, Jacob Gilbert.
+#
+# SPDX-License-Identifier: GPL-3.0-or-later
+#
+#
+
+
+from gnuradio import gr
+import numpy as np
+import math, pmt, time
+
+
+class pdu_lambda(gr.basic_block):
+ """
+ PDU Lambda Block
+
+ This block allows stateless manipulation of PDU metadata fields and uniform vectors
+ through python lambda functions. In uniform vector mode the lamnda function will be
+ applied with the python-ified uniform vector as the argument. In metadata dictionary
+ mode the lambda function will be applied to the python-ified value associated with
+ the PMT key the block is configured with.
+
+ The following python modules are imported for use:
+ `import numpy as np`
+ `import pmt, math, time`
+ These should also be imported in the flowgraph implementing this block if utilized.
+
+ Errors are generally silently dropped as all function application is done within a
+ try/catch statement. In the event an exception is thrown the data will be emitted
+ as it was received.
+
+ Examples of use:
+ - Phase demodulation of a complex PDU: Uniform Vector Mode with function:
+ `lambda x: np.unwrap(np.angle(x))`
+ - Scale metadata field `val1`: Metadata mode, separate QT range block with name `k`:
+ `lambda x: k*x`
+
+ This block cannot add or remove metadata fields, which should be done with the
+ application specific blocks in-tree or the more generic `message_lambda` block. This
+ block also designed to accept and return explicitly PDU type objects, if the PMT
+ object type needs to change, use the `message_lambda` block.
+ """
+
+ def __init__(self, fn, metadict, key=pmt.PMT_NIL):
+ gr.basic_block.__init__(self,
+ name="pdu_lambda",
+ in_sig=[],out_sig=[])
+ self.set_fn(fn)
+ self.set_key(key)
+ self.metadict_mode = metadict
+ self.message_port_register_in(pmt.intern("pdu"))
+ self.message_port_register_out(pmt.intern("pdu"))
+ self.set_msg_handler(pmt.intern("pdu"), self.handle_msg)
+
+ def handle_msg(self, pdu):
+ if self.metadict_mode:
+ meta = pmt.car(pdu)
+ try:
+ val = pmt.to_python(pmt.dict_ref(meta, self.key, pmt.PMT_NIL))
+ if val:
+ val = self.fn(val)
+ meta = pmt.dict_add(meta, self.key, pmt.to_pmt(val))
+ except Exception as e:
+ print(e)
+ pass
+ self.message_port_pub(pmt.intern("pdu"),
+ pmt.cons(meta, pmt.cdr(pdu)));
+
+ else: # PDU Vector mode
+ vec = pmt.cdr(pdu)
+ try:
+ vec = pmt.to_pmt(self.fn(pmt.to_python(vec)))
+ except Exception as e:
+ print(e)
+ pass
+
+ self.message_port_pub(pmt.intern("pdu"),
+ pmt.cons(pmt.car(pdu), vec));
+
+ def set_fn(self,fn):
+ self.fn = fn
+
+ def set_key(self,key):
+ self.key = key
diff --git a/gr-pdu/python/pdu/qa_pdu_lambda.py b/gr-pdu/python/pdu/qa_pdu_lambda.py
new file mode 100755
index 0000000000..f93475b8d9
--- /dev/null
+++ b/gr-pdu/python/pdu/qa_pdu_lambda.py
@@ -0,0 +1,33 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+#
+# Copyright 2021 Jacob Gilbert.
+#
+# SPDX-License-Identifier: GPL-3.0-or-later
+#
+#
+
+
+from gnuradio import gr, gr_unittest
+from gnuradio import pdu
+
+class qa_pdu_lambda(gr_unittest.TestCase):
+
+ def setUp(self):
+ self.tb = gr.top_block()
+
+ def tearDown(self):
+ self.tb = None
+
+ def test_smoketest(self):
+ # FIXME: Test will fail until you pass sensible arguments to the constructor
+ instance = pdu.pdu_lambda(lambda uvec: uvec*10, False)
+
+ def test_001_descriptive_test_name(self):
+ # set up fg
+ self.tb.run()
+ # check data
+
+
+if __name__ == '__main__':
+ gr_unittest.run(qa_pdu_lambda)
diff --git a/gr-pdu/python/pdu/qa_take_skip_to_pdu.py b/gr-pdu/python/pdu/qa_take_skip_to_pdu.py
new file mode 100755
index 0000000000..76414c857a
--- /dev/null
+++ b/gr-pdu/python/pdu/qa_take_skip_to_pdu.py
@@ -0,0 +1,103 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+#
+# Copyright 2018-2021 National Technology & Engineering Solutions of Sandia, LLC
+# (NTESS). Under the terms of Contract DE-NA0003525 with NTESS, the U.S. Government
+# retains certain rights in this software.
+#
+# SPDX-License-Identifier: GPL-3.0-or-later
+#
+
+from builtins import range
+from gnuradio import gr, gr_unittest, blocks, pdu
+import pmt
+import time
+import numpy
+
+class qa_take_skip_to_pdu_X (gr_unittest.TestCase):
+
+ # this method is necessary because by default pmt.equal does not evaluate
+ # the *contents* of a uniform vector
+ def assertEqualPDU(self, pdu1, pdu2):
+ # first check the equal() function:
+ if not pmt.equal(pdu1, pdu2):
+ self.assertTrue(False)
+ # then check the dictionaries:
+ if not pmt.equal(pmt.car(pdu1), pmt.car(pdu2)):
+ self.assertTrue(False)
+ # then check the elements of the respective vectors
+ vec1 = pmt.cdr(pdu1)
+ vec2 = pmt.cdr(pdu2)
+ if not pmt.equal(vec1, vec2):
+ self.assertTrue(False)
+ if not (pmt.to_python(vec1) == pmt.to_python(vec2)).all():
+ print("vectors not equal? " + repr(vec1) + repr(vec2))
+ self.assertTrue(False)
+
+ def setUp (self):
+ self.tb = gr.top_block ()
+
+ def tearDown (self):
+ self.tb = None
+
+ def test_001_f_32 (self):
+ self.source = blocks.vector_source_f(range(0,32*3), False, 1, [])
+ self.ts_pdu = pdu.take_skip_to_pdu_f(32, 32)
+ self.debug = blocks.message_debug()
+ self.tb.connect((self.source, 0), (self.ts_pdu, 0))
+ self.tb.msg_connect((self.ts_pdu, 'pdus'), (self.debug, 'store'))
+
+ dic = pmt.dict_add(pmt.make_dict(), pmt.intern("pdu_num"), pmt.from_uint64(0))
+ vec = pmt.init_f32vector(32, range(0,32))
+ expected = pmt.cons(dic,vec)
+ self.tb.run ()
+ actual = self.debug.get_message(0)
+ self.assertEqualPDU(actual, expected)
+
+ def test_002_c_80 (self):
+ self.source = blocks.vector_source_c(range(0,32*3), False, 1, [])
+ self.ts_pdu = pdu.take_skip_to_pdu_c(80, 32)
+ self.debug = blocks.message_debug()
+ self.tb.connect((self.source, 0), (self.ts_pdu, 0))
+ self.tb.msg_connect((self.ts_pdu, 'pdus'), (self.debug, 'store'))
+
+ dic = pmt.dict_add(pmt.make_dict(), pmt.intern("pdu_num"), pmt.from_uint64(0))
+ vec = pmt.init_c32vector(80, range(0,80))
+ expected = pmt.cons(dic,vec)
+ self.tb.run ()
+ actual = self.debug.get_message(0)
+ self.assertEqualPDU(actual, expected)
+
+
+ def test_003_s_2_11_7 (self):
+ self.source = blocks.vector_source_s(range(0,32*3), False, 1, [])
+ self.ts_pdu = pdu.take_skip_to_pdu_s(2, 11)
+ self.debug = blocks.message_debug()
+ self.tb.connect((self.source, 0), (self.ts_pdu, 0))
+ self.tb.msg_connect((self.ts_pdu, 'pdus'), (self.debug, 'store'))
+
+ dic = pmt.dict_add(pmt.make_dict(), pmt.intern("pdu_num"), pmt.from_uint64(7))
+ vec = pmt.init_s16vector(2, list(range(91,93)))
+ expected = pmt.cons(dic,vec)
+ self.tb.run ()
+ actual = self.debug.get_message(7)
+ self.assertEqualPDU(actual, expected)
+
+
+ def test_004_b_512 (self):
+ self.source = blocks.vector_source_b(list(range(0,256))*4, False, 1, [])
+ self.ts_pdu = pdu.take_skip_to_pdu_b(512,1)
+ self.debug = blocks.message_debug()
+ self.tb.connect((self.source, 0), (self.ts_pdu, 0))
+ self.tb.msg_connect((self.ts_pdu, 'pdus'), (self.debug, 'store'))
+
+ dic = pmt.dict_add(pmt.make_dict(), pmt.intern("pdu_num"), pmt.from_uint64(0))
+ vec = pmt.init_u8vector(512, list(range(0,256))*2)
+ expected = pmt.cons(dic,vec)
+ self.tb.run ()
+ actual = self.debug.get_message(0)
+ self.assertEqualPDU(actual, expected)
+
+
+if __name__ == '__main__':
+ gr_unittest.run(qa_take_skip_to_pdu_X)