diff --git a/grc/CMakeLists.txt b/grc/CMakeLists.txt index ab1f4ef9a53ea89a3e3b4c1eebfce6cd76dee255..cd500415b647c169f6783d716d007a5bd76362b0 100644 --- a/grc/CMakeLists.txt +++ b/grc/CMakeLists.txt @@ -7,5 +7,7 @@ # install(FILES - elen90089_corr_est_cc.block.yml DESTINATION share/gnuradio/grc/blocks + elen90089_corr_est_cc.block.yml + elen90089_moe_symbol_sync_cc.block.yml + DESTINATION share/gnuradio/grc/blocks ) diff --git a/grc/elen90089_moe_symbol_sync_cc.block.yml b/grc/elen90089_moe_symbol_sync_cc.block.yml new file mode 100644 index 0000000000000000000000000000000000000000..3d4f239eca6967e945dfeaf1adc091ee1ce769e6 --- /dev/null +++ b/grc/elen90089_moe_symbol_sync_cc.block.yml @@ -0,0 +1,31 @@ +id: elen90089_moe_symbol_sync_cc +label: CDC MOE Symbol Sync +category: '[elen90089]' + +templates: + imports: import elen90089 + make: elen90089.moe_symbol_sync_cc(${sps}, ${nsymbols}) + +parameters: +- id: sps + label: Samples per symbol + dtype: int +- id: nsymbols + label: Num symbol + dtype: int + +inputs: +- label: in + domain: stream + dtype: complex + +outputs: +- label: out0 + domain: stream + dtype: complex +- label: out1 + domain: stream + dtype: int + optional: True + +file_format: 1 diff --git a/include/elen90089/CMakeLists.txt b/include/elen90089/CMakeLists.txt index 1091fdada7bfb1c50398c98ebbfbee26a719471b..7ad10f5f6c1f20a95cda5262f0e84db3e3ec0866 100644 --- a/include/elen90089/CMakeLists.txt +++ b/include/elen90089/CMakeLists.txt @@ -12,5 +12,6 @@ install(FILES api.h corr_est_cc.h + moe_symbol_sync_cc.h DESTINATION include/elen90089 ) diff --git a/include/elen90089/moe_symbol_sync_cc.h b/include/elen90089/moe_symbol_sync_cc.h new file mode 100644 index 0000000000000000000000000000000000000000..1fb5768bc76daa5ef7f9c0313e4fdd6560d3a6f2 --- /dev/null +++ b/include/elen90089/moe_symbol_sync_cc.h @@ -0,0 +1,50 @@ +/* -*- c++ -*- */ +/* + * Copyright 2022 University of Melbourne. + * + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +#ifndef INCLUDED_ELEN90089_MOE_SYMBOL_SYNC_CC_H +#define INCLUDED_ELEN90089_MOE_SYMBOL_SYNC_CC_H + +#include <elen90089/api.h> +#include <gnuradio/sync_decimator.h> + +namespace gr { +namespace elen90089 { + +/*! + * \brief Maximum output energy (MOE) symbol synchronization. + * \ingroup elen90089 + * + * \details + * Input: + * \li Complex stream of symbols oversampled by factor of sps + * + * Output: + * \li Downsampled + * \li Optional second output stream of ints + */ +class ELEN90089_API moe_symbol_sync_cc : virtual public gr::sync_decimator +{ +public: + typedef std::shared_ptr<moe_symbol_sync_cc> sptr; + + /*! + * \brief Make a block that selects \p sps samples per symbol period. + * + * \param sps Samples per symbol + * \param nsymbols Symbols in averaging period + */ + static sptr make(int sps, + int nsymbols); + + virtual int nsymbols() const = 0; + virtual void set_nsymbols(int nsymbols) = 0; +}; + +} // namespace elen90089 +} // namespace gr + +#endif /* INCLUDED_ELEN90089_MOE_SYMBOL_SYNC_CC_H */ diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index 4c6376a2a8f3d35df68aadcb8cee041ca7c9cc5d..f05d33b12649a0da5d038c2d595bb3478072f802 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -13,6 +13,7 @@ include(GrPlatform) #define LIB_SUFFIX list(APPEND elen90089_sources corr_est_cc_impl.cc + moe_symbol_sync_cc_impl.cc ) set(elen90089_sources "${elen90089_sources}" PARENT_SCOPE) diff --git a/lib/moe_symbol_sync_cc_impl.cc b/lib/moe_symbol_sync_cc_impl.cc new file mode 100644 index 0000000000000000000000000000000000000000..8cbea76602ae4d77e6773871190f20df73ba8b33 --- /dev/null +++ b/lib/moe_symbol_sync_cc_impl.cc @@ -0,0 +1,78 @@ +/* -*- c++ -*- */ +/* + * Copyright 2022 University of Melbourne. + * + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +#include <gnuradio/io_signature.h> +#include "moe_symbol_sync_cc_impl.h" + +namespace gr { +namespace elen90089 { + +moe_symbol_sync_cc::sptr moe_symbol_sync_cc::make(int sps, + int nsymbols) +{ + return gnuradio::make_block_sptr<moe_symbol_sync_cc_impl>(sps, nsymbols); +} + +moe_symbol_sync_cc_impl::moe_symbol_sync_cc_impl(int sps, + int nsymbols) + : gr::sync_decimator("moe_symbol_sync_cc", + gr::io_signature::make(1, 1, sizeof(gr_complex)), + gr::io_signature::make2(1, 2, sizeof(gr_complex), sizeof(int)), + sps), + d_nsymbols(nsymbols), + d_index(0), + d_mag_sq(sps, 0.0), + d_sum(sps, 0.0) +{} + +moe_symbol_sync_cc_impl::~moe_symbol_sync_cc_impl() { } + +int moe_symbol_sync_cc_impl::nsymbols() const { + return d_nsymbols; +} + +void moe_symbol_sync_cc_impl::set_nsymbols(int nsymbols) { + d_nsymbols = nsymbols; +} + +int moe_symbol_sync_cc_impl::work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + auto in = static_cast<const gr_complex*>(input_items[0]); + auto out0 = static_cast<gr_complex*>(output_items[0]); + + int *out1 = nullptr; + if (output_items.size() > 1) + out1 = static_cast<int*>(output_items[1]); + + int sps = decimation(); + auto mag_sq = d_mag_sq.data(); + auto sum = d_sum.data(); + + int isymb = 0; + while(isymb < noutput_items) { + out0[isymb] = in[d_index]; + if(out1 != nullptr) + out1[isymb] = static_cast<int>(d_index); + + volk_32fc_magnitude_squared_32f(mag_sq, in, sps); + volk_32f_x2_add_32f(sum, sum, mag_sq, sps); + + if (++isymb % d_nsymbols == 0) { + volk_32f_index_max_32u(&d_index, sum, sps); + std::fill(d_sum.begin(), d_sum.end(), 0.0); + } + + in += sps; // increment input one symbol period + } + + return noutput_items; +} + +} /* namespace elen90089 */ +} /* namespace gr */ diff --git a/lib/moe_symbol_sync_cc_impl.h b/lib/moe_symbol_sync_cc_impl.h new file mode 100644 index 0000000000000000000000000000000000000000..b7785dfd6b760b1e04aac35e4f83eda13020600a --- /dev/null +++ b/lib/moe_symbol_sync_cc_impl.h @@ -0,0 +1,42 @@ +/* -*- c++ -*- */ +/* + * Copyright 2022 University of Melbourne. + * + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +#ifndef INCLUDED_ELEN90089_MOE_SYMBOL_SYNC_CC_IMPL_H +#define INCLUDED_ELEN90089_MOE_SYMBOL_SYNC_CC_IMPL_H + +#include <elen90089/moe_symbol_sync_cc.h> +#include <volk/volk_alloc.hh> + +namespace gr { +namespace elen90089 { + +class moe_symbol_sync_cc_impl : public moe_symbol_sync_cc +{ +private: + int d_nsymbols; + uint32_t d_index; + volk::vector<float> d_mag_sq; + volk::vector<float> d_sum; + +public: + moe_symbol_sync_cc_impl(int sps, + int nsymbols); + + ~moe_symbol_sync_cc_impl(); + + int nsymbols() const override; + void set_nsymbols(int nsymbols) override; + + int work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +} // namespace elen90089 +} // namespace gr + +#endif /* INCLUDED_ELEN90089_MOE_SYMBOL_SYNC_CC_IMPL_H */ diff --git a/python/CMakeLists.txt b/python/CMakeLists.txt index 9e056f9275e2e42d439e4bdcbb4e028d293b1b48..6c242766ff2cb44608eeda67c542ef988be61004 100644 --- a/python/CMakeLists.txt +++ b/python/CMakeLists.txt @@ -39,3 +39,5 @@ add_custom_target( COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_BINARY_DIR}/test_modules/elen90089/ ) +GR_ADD_TEST(qa_corr_est_cc ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa_corr_est_cc.py) +GR_ADD_TEST(qa_moe_symbol_sync_cc ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa_moe_symbol_sync_cc.py) diff --git a/python/bindings/CMakeLists.txt b/python/bindings/CMakeLists.txt index 3c360f53dc91f633be59d0ff3af5286ab08d87f6..9ed43664351ad1cc647674b233ebd94d58006b7e 100644 --- a/python/bindings/CMakeLists.txt +++ b/python/bindings/CMakeLists.txt @@ -29,7 +29,9 @@ include(GrPybind) ######################################################################## list(APPEND elen90089_python_files - corr_est_cc_python.cc python_bindings.cc) + corr_est_cc_python.cc + moe_symbol_sync_cc_python.cc + python_bindings.cc) GR_PYBIND_MAKE_OOT(elen90089 ../.. diff --git a/python/bindings/docstrings/moe_symbol_sync_cc_pydoc_template.h b/python/bindings/docstrings/moe_symbol_sync_cc_pydoc_template.h new file mode 100644 index 0000000000000000000000000000000000000000..c318afbcdd57184b1d80b09fc15f67675b3d7fec --- /dev/null +++ b/python/bindings/docstrings/moe_symbol_sync_cc_pydoc_template.h @@ -0,0 +1,36 @@ +/* + * Copyright 2022 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,elen90089, __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_elen90089_moe_symbol_sync_cc = R"doc()doc"; + + + static const char *__doc_gr_elen90089_moe_symbol_sync_cc_moe_symbol_sync_cc_0 = R"doc()doc"; + + + static const char *__doc_gr_elen90089_moe_symbol_sync_cc_moe_symbol_sync_cc_1 = R"doc()doc"; + + + static const char *__doc_gr_elen90089_moe_symbol_sync_cc_make = R"doc()doc"; + + + static const char *__doc_gr_elen90089_moe_symbol_sync_cc_nsymbols = R"doc()doc"; + + + static const char *__doc_gr_elen90089_moe_symbol_sync_cc_set_nsymbols = R"doc()doc"; + + diff --git a/python/bindings/moe_symbol_sync_cc_python.cc b/python/bindings/moe_symbol_sync_cc_python.cc new file mode 100644 index 0000000000000000000000000000000000000000..31a6bb3e1545b4aefbb5b72c923f12ccd4f40a93 --- /dev/null +++ b/python/bindings/moe_symbol_sync_cc_python.cc @@ -0,0 +1,74 @@ +/* + * Copyright 2022 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(moe_symbol_sync_cc.h) */ +/* BINDTOOL_HEADER_FILE_HASH(9795612b9fef9511155dcc9ea55123c1) */ +/***********************************************************************************/ + +#include <pybind11/complex.h> +#include <pybind11/pybind11.h> +#include <pybind11/stl.h> + +namespace py = pybind11; + +#include <elen90089/moe_symbol_sync_cc.h> +// pydoc.h is automatically generated in the build directory +#include <moe_symbol_sync_cc_pydoc.h> + +void bind_moe_symbol_sync_cc(py::module& m) +{ + + using moe_symbol_sync_cc = ::gr::elen90089::moe_symbol_sync_cc; + + + py::class_<moe_symbol_sync_cc, gr::sync_decimator, + std::shared_ptr<moe_symbol_sync_cc>>(m, "moe_symbol_sync_cc", D(moe_symbol_sync_cc)) + + .def(py::init(&moe_symbol_sync_cc::make), + py::arg("sps"), + py::arg("nsymbols"), + D(moe_symbol_sync_cc,make) + ) + + + + + + + .def("nsymbols",&moe_symbol_sync_cc::nsymbols, + D(moe_symbol_sync_cc,nsymbols) + ) + + + + .def("set_nsymbols",&moe_symbol_sync_cc::set_nsymbols, + py::arg("nsymbols"), + D(moe_symbol_sync_cc,set_nsymbols) + ) + + ; + + + + +} + + + + + + + + diff --git a/python/bindings/python_bindings.cc b/python/bindings/python_bindings.cc index f3152253fbc8e008943fb9c9d006597da61a4cce..fff3f49b3ae58c0bf1446a5b9bad7880c0d35c6b 100644 --- a/python/bindings/python_bindings.cc +++ b/python/bindings/python_bindings.cc @@ -22,6 +22,7 @@ namespace py = pybind11; /**************************************/ // BINDING_FUNCTION_PROTOTYPES( void bind_corr_est_cc(py::module& m); + void bind_moe_symbol_sync_cc(py::module& m); // ) END BINDING_FUNCTION_PROTOTYPES @@ -51,5 +52,6 @@ PYBIND11_MODULE(elen90089_python, m) /**************************************/ // BINDING_FUNCTION_CALLS( bind_corr_est_cc(m); + bind_moe_symbol_sync_cc(m); // ) END BINDING_FUNCTION_CALLS } \ No newline at end of file diff --git a/python/qa_corr_est_cc.py b/python/qa_corr_est_cc.py old mode 100644 new mode 100755 index d9bfa1fdef74197705265c988acddc5604ad8560..26c90685124dcc4a91471d8078494ef16ad6479c --- a/python/qa_corr_est_cc.py +++ b/python/qa_corr_est_cc.py @@ -1,8 +1,23 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +# Copyright 2022 University of Melbourne. +# +# SPDX-License-Identifier: GPL-3.0-or-later +# + from gnuradio import gr, gr_unittest from gnuradio import blocks import pmt -import elen90089 import numpy as np +try: + from elen90089 import corr_est_cc +except ImportError: + import os + import sys + dirname, filename = os.path.split(os.path.abspath(__file__)) + sys.path.append(os.path.join(dirname, "bindings")) + from elen90089 import corr_est_cc class qa_corr_est_cc(gr_unittest.TestCase): @@ -13,8 +28,8 @@ class qa_corr_est_cc(gr_unittest.TestCase): def tearDown(self): self.tb = None - def test_001(self): - """Test correlation result""" + def test_001_sequence_detection(self): + """Test basic sequence detection of correlator.""" pad = (0,) * 16 code = (1, 0, 1, 1, 1, 0, 1, 1) code_sym = [(2.0*x - 1.0) for x in code] @@ -22,7 +37,7 @@ class qa_corr_est_cc(gr_unittest.TestCase): src_data = [(2.0*x - 1.0) for x in src_bits] # build flowgraph src = blocks.vector_source_c(src_data) - cor = elen90089.corr_est_cc(code_sym, threshold=0.5) + cor = corr_est_cc(code_sym, threshold=0.5) dst = blocks.tag_debug(gr.sizeof_gr_complex, "", "corr_start") dst.set_display(False) self.tb.connect(src, cor, dst) @@ -35,7 +50,7 @@ class qa_corr_est_cc(gr_unittest.TestCase): corr_mag = pmt.to_python(result_data[0].value) self.assertAlmostEqual(corr_mag, 1.0, places=6) - def test_002(self): + def test_002_frequency_estimate(self): """Test coarse frequency offset estimate.""" phase_inc = 2*np.pi*0.02 # freq offset pad = (0,) * 16 @@ -46,7 +61,7 @@ class qa_corr_est_cc(gr_unittest.TestCase): # build flowgraph src = blocks.vector_source_c(src_data) rot = blocks.rotator_cc(phase_inc) - cor = elen90089.corr_est_cc(code_sym, threshold=0.5) + cor = corr_est_cc(code_sym, threshold=0.5) dst = blocks.tag_debug(gr.sizeof_gr_complex, "", "freq_est") dst.set_display(False) self.tb.connect(src, rot, cor, dst) diff --git a/python/qa_moe_symbol_sync_cc.py b/python/qa_moe_symbol_sync_cc.py new file mode 100755 index 0000000000000000000000000000000000000000..4c203347f4f64693dda680cc636c1dc961e5be08 --- /dev/null +++ b/python/qa_moe_symbol_sync_cc.py @@ -0,0 +1,46 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +# Copyright 2022 University of Melbourne. +# +# SPDX-License-Identifier: GPL-3.0-or-later +# + +from gnuradio import gr, gr_unittest +from gnuradio import blocks +try: + from elen90089 import moe_symbol_sync_cc +except ImportError: + import os + import sys + dirname, filename = os.path.split(os.path.abspath(__file__)) + sys.path.append(os.path.join(dirname, "bindings")) + from elen90089 import moe_symbol_sync_cc + +class qa_moe_symbol_sync_cc(gr_unittest.TestCase): + + def setUp(self): + self.tb = gr.top_block() + + def tearDown(self): + self.tb = None + + def test_001_moe_symbol_sync_cc(self): + sps, nsymbols = 4, 2 + src_data = (1, 2, 3, 1,) * 4 + expected_result = ((1+0j), (1+0j), (3+0j), (3+0j)) + src = blocks.vector_source_c(src_data) + moe = moe_symbol_sync_cc(sps, nsymbols) + dst = blocks.vector_sink_c() + + self.tb.connect(src, moe, dst) + self.tb.run() + + actual_result = dst.data() + #print('expected_result', expected_result) + #print('actual_result', actual_result) + self.assertEqual(len(actual_result), len(src_data)//sps) + self.assertFloatTuplesAlmostEqual(expected_result, actual_result) + +if __name__ == '__main__': + gr_unittest.run(qa_moe_symbol_sync_cc)