diff --git a/grc/CMakeLists.txt b/grc/CMakeLists.txt index 63f095b0a6c8946419de11c6622b68f7605df3eb..2cb52e997313825379a3758515b466f0f08d692d 100644 --- a/grc/CMakeLists.txt +++ b/grc/CMakeLists.txt @@ -10,5 +10,6 @@ install(FILES cdc_preamble_detect_cc.block.yml cdc_phy_tx.block.yml cdc_phy_rx.block.yml - cdc_insert_burst_c.block.yml DESTINATION share/gnuradio/grc/blocks + cdc_insert_burst_c.block.yml + cdc_dsa_pu_scenario_cc.block.yml DESTINATION share/gnuradio/grc/blocks ) diff --git a/grc/cdc_dsa_pu_scenario_cc.block.yml b/grc/cdc_dsa_pu_scenario_cc.block.yml new file mode 100644 index 0000000000000000000000000000000000000000..94b5c22efcb74cf4695c09d9fd1f1540f2bda1b3 --- /dev/null +++ b/grc/cdc_dsa_pu_scenario_cc.block.yml @@ -0,0 +1,54 @@ +id: cdc_dsa_pu_scenario_cc +label: 'CDC DSA PU Scenario' +category: '[CDC]' + +templates: + imports: from gnuradio import cdc + make: cdc.dsa_pu_scenario_cc(${samp_rate}, ${duration_ms}, ${random}, ${seed}, ${scenario}) + callbacks: + - set_scenario(${scenario}) + - set_random(${random}) + - set_duration_ms(${duration_ms}) + +parameters: +- id: num_channels + label: Num Channels + default: '1' + dtype: int +- id: samp_rate + label: Samp rate + dtype: int + default: 'samp_rate' +- id: duration_ms + label: Duration (ms) + dtype: float + default: 50.0 +- id: random + label: Randomize Scenario + dtype: raw + default: 'False' +- id: seed + label: Seed + dtype: int + default: 1 +- id: scenario + label: Scenario + dtype: int + default: 0 + +inputs: +- label: in + domain: stream + dtype: complex + multiplicity: ${num_channels} + +outputs: +- label: out + domain: stream + dtype: complex + multiplicity: ${num_channels} +- label: mode + domain: message + optional: True + +file_format: 1 diff --git a/include/gnuradio/cdc/CMakeLists.txt b/include/gnuradio/cdc/CMakeLists.txt index 09498fcc6592f3460af778b4616b54bbb5642519..91025a06f98fa23e2f0adeabeaa95dcf8916de8b 100644 --- a/include/gnuradio/cdc/CMakeLists.txt +++ b/include/gnuradio/cdc/CMakeLists.txt @@ -13,5 +13,6 @@ install(FILES api.h tag_tx_burst_cc.h preamble_detect_cc.h - insert_burst_c.h DESTINATION include/gnuradio/cdc + insert_burst_c.h + dsa_pu_scenario_cc.h DESTINATION include/gnuradio/cdc ) diff --git a/include/gnuradio/cdc/dsa_pu_scenario_cc.h b/include/gnuradio/cdc/dsa_pu_scenario_cc.h new file mode 100644 index 0000000000000000000000000000000000000000..8805ac44fdf7affbf9f0c12a35c55fd87ad48228 --- /dev/null +++ b/include/gnuradio/cdc/dsa_pu_scenario_cc.h @@ -0,0 +1,69 @@ +/* -*- c++ -*- */ +/* + * Copyright 2023 University of Melbourne. + * + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +#ifndef INCLUDED_CDC_DSA_PU_SCENARIO_CC_H +#define INCLUDED_CDC_DSA_PU_SCENARIO_CC_H + +#include <gnuradio/cdc/api.h> +#include <gnuradio/sync_block.h> + +namespace gr { +namespace cdc { + +/*! + * \brief Implements primary user scenario control for CDC dynamic spectrum + access project. + * \ingroup cdc + * + */ +class CDC_API dsa_pu_scenario_cc : virtual public gr::sync_block +{ +public: + typedef std::shared_ptr<dsa_pu_scenario_cc> sptr; + + /*! + * \brief DSA PU Scenario Constructor + * + * \param samp_rate Sample rate of incoming data streams + * \param duration_ms Duration (in ms) of scenario before randomly + * \param random Randomly select primary user scenario + * \param seed Seed used in random scenario selection. + * \param scenario Initial primary user scenario - bitmap of active + * channels, e.g., for 4 PU channels SCENARIO = 0b1010 + * indicates channels 2 and 4 are active. + * selecting new scenario. + */ + static sptr make(int samp_rate, + float duration_ms, + bool random, + int seed = 0, + int scenario = 0); + + //! Set primary user scenario + virtual void set_scenario(int scenario) = 0; + + //! Get current primary user scenario + virtual int get_scenario(void) = 0; + + //! Set random selection of primary user scenarios + virtual void set_random(bool random) = 0; + + //! Get random selection of primary user scenarios + virtual bool get_random(void) = 0; + + //! Set duration (in ms) of random primary user scenarios + virtual void set_duration_ms(float duration_ms) = 0; + + //! Get duration (in ms) of random primary user scenarios + virtual float get_duration_ms(void) = 0; + +}; + +} // namespace cdc +} // namespace gr + +#endif /* INCLUDED_CDC_DSA_PU_SCENARIO_CC_H */ diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index 9e28825fd259fd5d92832b89f61843e13c417630..0066e1d356f52a930796a404a695362df4d75b76 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -13,7 +13,8 @@ include(GrPlatform) #define LIB_SUFFIX list(APPEND cdc_sources tag_tx_burst_cc_impl.cc preamble_detect_cc_impl.cc - insert_burst_c_impl.cc ) + insert_burst_c_impl.cc + dsa_pu_scenario_cc_impl.cc ) set(cdc_sources "${cdc_sources}" PARENT_SCOPE) if(NOT cdc_sources) diff --git a/lib/dsa_pu_scenario_cc_impl.cc b/lib/dsa_pu_scenario_cc_impl.cc new file mode 100644 index 0000000000000000000000000000000000000000..c8e8ae51555cafc56b53d0cb2bb743c88073b5c1 --- /dev/null +++ b/lib/dsa_pu_scenario_cc_impl.cc @@ -0,0 +1,94 @@ +/* -*- c++ -*- */ +/* + * Copyright 2023 University of Melbourne. + * + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +#include <gnuradio/io_signature.h> +#include "dsa_pu_scenario_cc_impl.h" + +namespace gr { +namespace cdc { + +dsa_pu_scenario_cc::sptr +dsa_pu_scenario_cc::make(int samp_rate, + float duration_ms, + bool random, + int seed, + int scenario) +{ + return gnuradio::make_block_sptr<dsa_pu_scenario_cc_impl>( + samp_rate, duration_ms, random, seed, scenario); +} + +dsa_pu_scenario_cc_impl::dsa_pu_scenario_cc_impl(int samp_rate, + float duration_ms, + bool random, + int seed, + int scenario) + : gr::sync_block("dsa_pu_scenario_cc", + gr::io_signature::make(1, -1, sizeof(gr_complex)), + gr::io_signature::make(1, -1, sizeof(gr_complex))), + d_samp_rate(samp_rate), + d_duration_ms(duration_ms), + d_engine(seed), + d_random(random), + d_scenario(scenario) +{ + message_port_register_out(pmt::mp("mode")); +} + +dsa_pu_scenario_cc_impl::~dsa_pu_scenario_cc_impl() +{ + if (d_uniform) delete d_uniform; +} + +void +dsa_pu_scenario_cc_impl::update_scenario(int n_chan) +{ + if (!d_active.size()) + { + d_active.resize(n_chan); + int n_scenarios = (0x1 << n_chan); + d_uniform = new std::uniform_int_distribution<int>(0, n_scenarios - 1); + } + + if (d_samp_cnt <= 0) + { + d_samp_cnt = int(d_duration_ms * d_samp_rate / 1000.0); + if (d_random) + d_scenario = (*d_uniform)(d_engine); + message_port_pub(pmt::mp("mode"), pmt::mp(d_scenario)); + } + + for (int i_chan=0; i_chan < n_chan; i_chan++) + d_active[i_chan] = d_scenario & (0x1 << i_chan); +} + +int +dsa_pu_scenario_cc_impl::work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + int n_chan = output_items.size(); + + update_scenario(n_chan); + + int n_samps = (d_samp_cnt < noutput_items) ? d_samp_cnt : noutput_items; + for (int i_chan = 0; i_chan < n_chan; i_chan++) + { + gr_complex *in = (gr_complex *)input_items[i_chan]; + gr_complex *out = (gr_complex *)output_items[i_chan]; + if (d_active[i_chan]) + memcpy(out, in, n_samps * sizeof(gr_complex)); + else + memset(out, 0x0, n_samps * sizeof(gr_complex)); + } + d_samp_cnt -= n_samps; + + return n_samps; +} + +} /* namespace cdc */ +} /* namespace gr */ diff --git a/lib/dsa_pu_scenario_cc_impl.h b/lib/dsa_pu_scenario_cc_impl.h new file mode 100644 index 0000000000000000000000000000000000000000..8dcd25aad3908e60e8f84c2dc488484eb2ef1605 --- /dev/null +++ b/lib/dsa_pu_scenario_cc_impl.h @@ -0,0 +1,62 @@ +/* -*- c++ -*- */ +/* + * Copyright 2023 University of Melbourne. + * + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +#ifndef INCLUDED_CDC_DSA_PU_SCENARIO_CC_IMPL_H +#define INCLUDED_CDC_DSA_PU_SCENARIO_CC_IMPL_H + +#include <gnuradio/cdc/dsa_pu_scenario_cc.h> +#include <random> + +namespace gr { +namespace cdc { + +class dsa_pu_scenario_cc_impl : public dsa_pu_scenario_cc +{ +private: + int d_samp_rate; + float d_duration_ms; + bool d_random; + int d_scenario; + + std::default_random_engine d_engine; + std::uniform_int_distribution<int>* d_uniform = nullptr; + std::vector<bool> d_active; + int d_samp_cnt = 0; + + void update_scenario(int n_chan); + +public: + dsa_pu_scenario_cc_impl(int samp_rate, + float duration_ms, + bool random, + int seed, + int scenario); + + ~dsa_pu_scenario_cc_impl(); + + void set_scenario(int scenario) { d_scenario = scenario; }; + + int get_scenario(void) { return d_scenario; }; + + void set_random(bool random) { d_random = random; }; + + bool get_random(void) { return random; }; + + void set_duration_ms(float duration_ms) { d_duration_ms = duration_ms; }; + + float get_duration_ms(void) { return d_duration_ms; }; + + int work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + +}; + +} // namespace cdc +} // namespace gr + +#endif /* INCLUDED_CDC_DSA_PU_SCENARIO_CC_IMPL_H */ diff --git a/python/cdc/bindings/CMakeLists.txt b/python/cdc/bindings/CMakeLists.txt index 2e33c2239bc862793cbcd77ad96bdb885203d445..a955da9cde1118b906c2b700ba85fe85df10d797 100644 --- a/python/cdc/bindings/CMakeLists.txt +++ b/python/cdc/bindings/CMakeLists.txt @@ -30,7 +30,8 @@ include(GrPybind) list(APPEND cdc_python_files tag_tx_burst_cc_python.cc preamble_detect_cc_python.cc - insert_burst_c_python.cc python_bindings.cc) + insert_burst_c_python.cc + dsa_pu_scenario_cc_python.cc python_bindings.cc) GR_PYBIND_MAKE_OOT(cdc ../../.. diff --git a/python/cdc/bindings/docstrings/dsa_pu_scenario_cc_pydoc_template.h b/python/cdc/bindings/docstrings/dsa_pu_scenario_cc_pydoc_template.h new file mode 100644 index 0000000000000000000000000000000000000000..5dad6ffef2da01e8c112d2ed9a58a3577b8df7ad --- /dev/null +++ b/python/cdc/bindings/docstrings/dsa_pu_scenario_cc_pydoc_template.h @@ -0,0 +1,48 @@ +/* + * 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,cdc, __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_cdc_dsa_pu_scenario_cc = R"doc()doc"; + + + static const char *__doc_gr_cdc_dsa_pu_scenario_cc_dsa_pu_scenario_cc_0 = R"doc()doc"; + + + static const char *__doc_gr_cdc_dsa_pu_scenario_cc_dsa_pu_scenario_cc_1 = R"doc()doc"; + + + static const char *__doc_gr_cdc_dsa_pu_scenario_cc_make = R"doc()doc"; + + + static const char *__doc_gr_cdc_dsa_pu_scenario_cc_set_scenario = R"doc()doc"; + + + static const char *__doc_gr_cdc_dsa_pu_scenario_cc_get_scenario = R"doc()doc"; + + + static const char *__doc_gr_cdc_dsa_pu_scenario_cc_set_random = R"doc()doc"; + + + static const char *__doc_gr_cdc_dsa_pu_scenario_cc_get_random = R"doc()doc"; + + + static const char *__doc_gr_cdc_dsa_pu_scenario_cc_set_duration_ms = R"doc()doc"; + + + static const char *__doc_gr_cdc_dsa_pu_scenario_cc_get_duration_ms = R"doc()doc"; + + diff --git a/python/cdc/bindings/dsa_pu_scenario_cc_python.cc b/python/cdc/bindings/dsa_pu_scenario_cc_python.cc new file mode 100644 index 0000000000000000000000000000000000000000..bb3de020625e08874a358e583523966a46149efa --- /dev/null +++ b/python/cdc/bindings/dsa_pu_scenario_cc_python.cc @@ -0,0 +1,103 @@ +/* + * 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(dsa_pu_scenario_cc.h) */ +/* BINDTOOL_HEADER_FILE_HASH(219f58bccfee90b520aae47f5b3325c2) */ +/***********************************************************************************/ + +#include <pybind11/complex.h> +#include <pybind11/pybind11.h> +#include <pybind11/stl.h> + +namespace py = pybind11; + +#include <gnuradio/cdc/dsa_pu_scenario_cc.h> +// pydoc.h is automatically generated in the build directory +#include <dsa_pu_scenario_cc_pydoc.h> + +void bind_dsa_pu_scenario_cc(py::module& m) +{ + + using dsa_pu_scenario_cc = ::gr::cdc::dsa_pu_scenario_cc; + + + py::class_<dsa_pu_scenario_cc, gr::sync_block, gr::block, gr::basic_block, + std::shared_ptr<dsa_pu_scenario_cc>>(m, "dsa_pu_scenario_cc", D(dsa_pu_scenario_cc)) + + .def(py::init(&dsa_pu_scenario_cc::make), + py::arg("samp_rate"), + py::arg("duration_ms"), + py::arg("random"), + py::arg("seed") = 0, + py::arg("scenario") = 0, + D(dsa_pu_scenario_cc,make) + ) + + + + + + + .def("set_scenario",&dsa_pu_scenario_cc::set_scenario, + py::arg("scenario"), + D(dsa_pu_scenario_cc,set_scenario) + ) + + + + .def("get_scenario",&dsa_pu_scenario_cc::get_scenario, + D(dsa_pu_scenario_cc,get_scenario) + ) + + + + .def("set_random",&dsa_pu_scenario_cc::set_random, + py::arg("random"), + D(dsa_pu_scenario_cc,set_random) + ) + + + + .def("get_random",&dsa_pu_scenario_cc::get_random, + D(dsa_pu_scenario_cc,get_random) + ) + + + + .def("set_duration_ms",&dsa_pu_scenario_cc::set_duration_ms, + py::arg("duration_ms"), + D(dsa_pu_scenario_cc,set_duration_ms) + ) + + + + .def("get_duration_ms",&dsa_pu_scenario_cc::get_duration_ms, + D(dsa_pu_scenario_cc,get_duration_ms) + ) + + ; + + + + +} + + + + + + + + diff --git a/python/cdc/bindings/python_bindings.cc b/python/cdc/bindings/python_bindings.cc index d11cd00ddf619a9fcbe904299916a1cc97ec4dfc..9f463592a128d75d3cf6e20c6b95d8a144917e29 100644 --- a/python/cdc/bindings/python_bindings.cc +++ b/python/cdc/bindings/python_bindings.cc @@ -24,6 +24,7 @@ namespace py = pybind11; void bind_tag_tx_burst_cc(py::module& m); void bind_preamble_detect_cc(py::module& m); void bind_insert_burst_c(py::module& m); + void bind_dsa_pu_scenario_cc(py::module& m); // ) END BINDING_FUNCTION_PROTOTYPES @@ -55,5 +56,6 @@ PYBIND11_MODULE(cdc_python, m) bind_tag_tx_burst_cc(m); bind_preamble_detect_cc(m); bind_insert_burst_c(m); + bind_dsa_pu_scenario_cc(m); // ) END BINDING_FUNCTION_CALLS } \ No newline at end of file