diff --git a/grc/CMakeLists.txt b/grc/CMakeLists.txt index 4034c00..b5f317f 100644 --- a/grc/CMakeLists.txt +++ b/grc/CMakeLists.txt @@ -11,5 +11,6 @@ install(FILES UTAT_HERON_esttc_framer.block.yml UTAT_HERON_esttc_deframer.block.yml UTAT_HERON_tagged_stream_tail_tagger.block.yml - UTAT_HERON_tagged_stream_bufferer.block.yml DESTINATION share/gnuradio/grc/blocks + UTAT_HERON_tagged_stream_bufferer.block.yml + UTAT_HERON_tagged_stream_fixed_length_padder.block.yml DESTINATION share/gnuradio/grc/blocks ) diff --git a/grc/UTAT_HERON_tagged_stream_fixed_length_padder.block.yml b/grc/UTAT_HERON_tagged_stream_fixed_length_padder.block.yml new file mode 100644 index 0000000..4b4ca96 --- /dev/null +++ b/grc/UTAT_HERON_tagged_stream_fixed_length_padder.block.yml @@ -0,0 +1,50 @@ +id: UTAT_HERON_tagged_stream_fixed_length_padder +label: Tagged Stream Fixed Length Padder +category: '[UTAT]' + +templates: + imports: from gnuradio import UTAT_HERON + make: UTAT_HERON.tagged_stream_fixed_length_padder(${len_tag_key}, ${final_samples_per_symbol}, ${final_buffer_len}) + +# 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, ...) +# * default +parameters: +- id: len_tag_key + label: Length Tag Name + dtype: string + default: packet_len +- id: final_samples_per_symbol + label: Final Samples per Symbol + dtype: float +- id: final_buffer_len + label: Final buffer Length + dtype: int +# - id: threshold +# label: Threshold +# dtype: float +# default: 1 + +# 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/include/gnuradio/UTAT_HERON/CMakeLists.txt b/include/gnuradio/UTAT_HERON/CMakeLists.txt index 1e9db4a..31c3d4a 100644 --- a/include/gnuradio/UTAT_HERON/CMakeLists.txt +++ b/include/gnuradio/UTAT_HERON/CMakeLists.txt @@ -16,5 +16,6 @@ install(FILES esttc_framer.h esttc_deframer.h tagged_stream_tail_tagger.h - tagged_stream_bufferer.h DESTINATION include/gnuradio/UTAT_HERON + tagged_stream_bufferer.h + tagged_stream_fixed_length_padder.h DESTINATION include/gnuradio/UTAT_HERON ) diff --git a/include/gnuradio/UTAT_HERON/tagged_stream_fixed_length_padder.h b/include/gnuradio/UTAT_HERON/tagged_stream_fixed_length_padder.h new file mode 100644 index 0000000..a77a493 --- /dev/null +++ b/include/gnuradio/UTAT_HERON/tagged_stream_fixed_length_padder.h @@ -0,0 +1,48 @@ +/* -*- c++ -*- */ +/* + * Copyright 2023 University of Toronto Aerospace Team. + * + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +#ifndef INCLUDED_UTAT_HERON_TAGGED_STREAM_FIXED_LENGTH_PADDER_H +#define INCLUDED_UTAT_HERON_TAGGED_STREAM_FIXED_LENGTH_PADDER_H + +#include +#include + +namespace gr { +namespace UTAT_HERON { + +/*! + * \brief <+description of block+> + * \ingroup UTAT_HERON + * + */ +class UTAT_HERON_API tagged_stream_fixed_length_padder + : virtual public gr::tagged_stream_block +{ +public: + typedef std::shared_ptr sptr; + + /*! + * \brief Return a shared_ptr to a new instance of + * UTAT_HERON::tagged_stream_fixed_length_padder. + * + * To avoid accidental use of raw pointers, + * UTAT_HERON::tagged_stream_fixed_length_padder's constructor is in a private + * implementation class. UTAT_HERON::tagged_stream_fixed_length_padder::make is the + * public interface for creating new instances. + */ + static sptr make( + const std::string& len_tag_key, + float final_samples_per_symbol, + int final_buffer_len + // float threshold + ); +}; + +} // namespace UTAT_HERON +} // namespace gr + +#endif /* INCLUDED_UTAT_HERON_TAGGED_STREAM_FIXED_LENGTH_PADDER_H */ diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index b7f9231..e15edb8 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -26,7 +26,8 @@ list(APPEND UTAT_HERON_sources esttc_framer_impl.cc esttc_deframer_impl.cc tagged_stream_tail_tagger_impl.cc - tagged_stream_bufferer_impl.cc ) + tagged_stream_bufferer_impl.cc + tagged_stream_fixed_length_padder_impl.cc ) set(DEBUG_FILE "${CMAKE_BINARY_DIR}/debug_log.txt" CACHE FILEPATH "Log debug to this file when CMAKE_BULD_TYPE is Debug or RelWithDebInfo") diff --git a/lib/tagged_stream_fixed_length_padder_impl.cc b/lib/tagged_stream_fixed_length_padder_impl.cc new file mode 100644 index 0000000..51b636d --- /dev/null +++ b/lib/tagged_stream_fixed_length_padder_impl.cc @@ -0,0 +1,97 @@ +/* -*- c++ -*- */ +/* + * Copyright 2023 University of Toronto Aerospace Team. + * + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +#include "tagged_stream_fixed_length_padder_impl.h" +#include + +namespace gr { +namespace UTAT_HERON { + +using input_type = uint8_t; +using output_type = uint8_t; + +tagged_stream_fixed_length_padder::sptr tagged_stream_fixed_length_padder::make( + const std::string& len_tag_key, + float final_samples_per_symbol, + int final_buffer_len + // float threshold +) +{ + return gnuradio::make_block_sptr( + len_tag_key, + final_samples_per_symbol, + final_buffer_len + // threshold + ); +} + + +/* + * The private constructor + */ +tagged_stream_fixed_length_padder_impl::tagged_stream_fixed_length_padder_impl( + const std::string& len_tag_key, + float final_samples_per_symbol, + int final_buffer_len + // float threshold +) : + gr::tagged_stream_block( + "tagged_stream_fixed_length_padder", + gr::io_signature::make(1,1,sizeof(input_type)), + gr::io_signature::make(1,1,sizeof(output_type)), + len_tag_key), + d_sps(final_samples_per_symbol), + d_buffer_len(final_buffer_len), + // d_threshold(threshold), + // d_min_samps(std::ceil(d_buffer_len + d_threshold)), + d_samps_out(0) +{} + +/* + * Our virtual destructor. + */ +tagged_stream_fixed_length_padder_impl::~tagged_stream_fixed_length_padder_impl() {} + +int tagged_stream_fixed_length_padder_impl::calculate_output_stream_length( + const gr_vector_int& ninput_items) +{ + // int len = static_cast(std::ceil((d_min_samps - d_samps_out)/d_sps)); + int len = d_buffer_len + 1*d_sps; + if(len/d_sps < ninput_items[0]) + throw std::runtime_error("Input needs to be smaller!"); + return len; +} + +int tagged_stream_fixed_length_padder_impl::work(int noutput_items, + gr_vector_int& ninput_items, + gr_vector_const_void_star& input_items, + gr_vector_void_star& output_items) +{ + auto in = static_cast(input_items[0]); + auto out = static_cast(output_items[0]); + + int produced = 0; + + std::memcpy(out, in, ninput_items[0]*sizeof(input_type)); + d_samps_out += ninput_items[0]*d_sps; + produced = ninput_items[0]; + + while(d_samps_out < d_buffer_len && produced < noutput_items){ + out[produced++] = 0xCC; + d_samps_out += d_sps; + } + + if(d_samps_out < d_buffer_len) + throw std::runtime_error("Output needs to be larger!"); + + d_samps_out -= produced*d_sps; + return produced; + +} + +} /* namespace UTAT_HERON */ +} /* namespace gr */ diff --git a/lib/tagged_stream_fixed_length_padder_impl.h b/lib/tagged_stream_fixed_length_padder_impl.h new file mode 100644 index 0000000..6a25f12 --- /dev/null +++ b/lib/tagged_stream_fixed_length_padder_impl.h @@ -0,0 +1,48 @@ +/* -*- c++ -*- */ +/* + * Copyright 2023 University of Toronto Aerospace Team. + * + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +#ifndef INCLUDED_UTAT_HERON_TAGGED_STREAM_FIXED_LENGTH_PADDER_IMPL_H +#define INCLUDED_UTAT_HERON_TAGGED_STREAM_FIXED_LENGTH_PADDER_IMPL_H + +#include + +namespace gr { +namespace UTAT_HERON { + +class tagged_stream_fixed_length_padder_impl : public tagged_stream_fixed_length_padder +{ +private: + // Nothing to declare in this block. + float d_sps; + int d_buffer_len; + // float d_threshold; + // int d_min_samps; + float d_samps_out; + +protected: + int calculate_output_stream_length(const gr_vector_int& ninput_items); + +public: + tagged_stream_fixed_length_padder_impl( + const std::string& len_tag_key, + float final_samples_per_symbol, + int final_buffer_len + // float threshold + ); + ~tagged_stream_fixed_length_padder_impl(); + + // Where all the action really happens + int work(int noutput_items, + gr_vector_int& ninput_items, + gr_vector_const_void_star& input_items, + gr_vector_void_star& output_items); +}; + +} // namespace UTAT_HERON +} // namespace gr + +#endif /* INCLUDED_UTAT_HERON_TAGGED_STREAM_FIXED_LENGTH_PADDER_IMPL_H */ diff --git a/python/UTAT_HERON/CMakeLists.txt b/python/UTAT_HERON/CMakeLists.txt index c071ebe..d11f13a 100644 --- a/python/UTAT_HERON/CMakeLists.txt +++ b/python/UTAT_HERON/CMakeLists.txt @@ -44,3 +44,4 @@ GR_ADD_TEST(qa_esttc_framer ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa_ GR_ADD_TEST(qa_esttc_deframer ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa_esttc_deframer.py) GR_ADD_TEST(qa_tagged_stream_tail_tagger ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa_tagged_stream_tail_tagger.py) GR_ADD_TEST(qa_tagged_stream_bufferer ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa_tagged_stream_bufferer.py) +GR_ADD_TEST(qa_tagged_stream_fixed_length_padder ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa_tagged_stream_fixed_length_padder.py) diff --git a/python/UTAT_HERON/bindings/CMakeLists.txt b/python/UTAT_HERON/bindings/CMakeLists.txt index e01071d..7f1a34b 100644 --- a/python/UTAT_HERON/bindings/CMakeLists.txt +++ b/python/UTAT_HERON/bindings/CMakeLists.txt @@ -33,7 +33,8 @@ list(APPEND UTAT_HERON_python_files esttc_framer_python.cc esttc_deframer_python.cc tagged_stream_tail_tagger_python.cc - tagged_stream_bufferer_python.cc python_bindings.cc) + tagged_stream_bufferer_python.cc + tagged_stream_fixed_length_padder_python.cc python_bindings.cc) GR_PYBIND_MAKE_OOT(UTAT_HERON ../../.. diff --git a/python/UTAT_HERON/bindings/docstrings/tagged_stream_fixed_length_padder_pydoc_template.h b/python/UTAT_HERON/bindings/docstrings/tagged_stream_fixed_length_padder_pydoc_template.h new file mode 100644 index 0000000..9dd18fd --- /dev/null +++ b/python/UTAT_HERON/bindings/docstrings/tagged_stream_fixed_length_padder_pydoc_template.h @@ -0,0 +1,22 @@ +/* + * Copyright 2023 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, UTAT_HERON, __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_UTAT_HERON_tagged_stream_fixed_length_padder = R"doc()doc"; + + +static const char* __doc_gr_UTAT_HERON_tagged_stream_fixed_length_padder_make = + R"doc()doc"; diff --git a/python/UTAT_HERON/bindings/python_bindings.cc b/python/UTAT_HERON/bindings/python_bindings.cc index 5a98154..42c9654 100644 --- a/python/UTAT_HERON/bindings/python_bindings.cc +++ b/python/UTAT_HERON/bindings/python_bindings.cc @@ -27,6 +27,7 @@ namespace py = pybind11; void bind_esttc_deframer(py::module& m); void bind_tagged_stream_tail_tagger(py::module& m); void bind_tagged_stream_bufferer(py::module& m); + void bind_tagged_stream_fixed_length_padder(py::module& m); // ) END BINDING_FUNCTION_PROTOTYPES @@ -62,5 +63,6 @@ PYBIND11_MODULE(UTAT_HERON_python, m) bind_esttc_deframer(m); bind_tagged_stream_tail_tagger(m); bind_tagged_stream_bufferer(m); + bind_tagged_stream_fixed_length_padder(m); // ) END BINDING_FUNCTION_CALLS } \ No newline at end of file diff --git a/python/UTAT_HERON/bindings/tagged_stream_fixed_length_padder_python.cc b/python/UTAT_HERON/bindings/tagged_stream_fixed_length_padder_python.cc new file mode 100644 index 0000000..d10d56e --- /dev/null +++ b/python/UTAT_HERON/bindings/tagged_stream_fixed_length_padder_python.cc @@ -0,0 +1,51 @@ +/* + * Copyright 2023 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(tagged_stream_fixed_length_padder.h) */ +/* BINDTOOL_HEADER_FILE_HASH(e8323f50cc6fbf2d718fb4d63b0947d6) */ +/***********************************************************************************/ + +#include +#include +#include + +namespace py = pybind11; + +#include +// pydoc.h is automatically generated in the build directory +#include + +void bind_tagged_stream_fixed_length_padder(py::module& m) +{ + + using tagged_stream_fixed_length_padder = + gr::UTAT_HERON::tagged_stream_fixed_length_padder; + + + py::class_>( + m, "tagged_stream_fixed_length_padder", D(tagged_stream_fixed_length_padder)) + + .def(py::init(&tagged_stream_fixed_length_padder::make), + py::arg("len_tag_key"), + py::arg("final_samples_per_symbol"), + py::arg("final_buffer_len//floatthreshold"), + D(tagged_stream_fixed_length_padder, make)) + + + ; +} diff --git a/python/UTAT_HERON/qa_tagged_stream_fixed_length_padder.py b/python/UTAT_HERON/qa_tagged_stream_fixed_length_padder.py new file mode 100755 index 0000000..cdd2a45 --- /dev/null +++ b/python/UTAT_HERON/qa_tagged_stream_fixed_length_padder.py @@ -0,0 +1,39 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +# Copyright 2023 University of Toronto Aerospace Team. +# +# SPDX-License-Identifier: GPL-3.0-or-later +# + +from gnuradio import gr, gr_unittest +# from gnuradio import blocks +try: + from gnuradio.UTAT_HERON import tagged_stream_fixed_length_padder +except ImportError: + import os + import sys + dirname, filename = os.path.split(os.path.abspath(__file__)) + sys.path.append(os.path.join(dirname, "bindings")) + from gnuradio.UTAT_HERON import tagged_stream_fixed_length_padder + +class qa_tagged_stream_fixed_length_padder(gr_unittest.TestCase): + + def setUp(self): + self.tb = gr.top_block() + + def tearDown(self): + self.tb = None + + def test_instance(self): + # FIXME: Test will fail until you pass sensible arguments to the constructor + instance = tagged_stream_fixed_length_padder('packet_len') + + def test_001_descriptive_test_name(self): + # set up fg + self.tb.run() + # check data + + +if __name__ == '__main__': + gr_unittest.run(qa_tagged_stream_fixed_length_padder)