From 73db5d15cedd3e191733d56b1db75df703955569 Mon Sep 17 00:00:00 2001 From: Josh Bailey Date: Sat, 16 Sep 2023 16:28:11 +1200 Subject: [PATCH] Implement pre FFT tuning, which eliminates FFT offload latency from retuning delay. --- .github/workflows/test.yaml | 2 +- .gitignore | 1 + grc/CMakeLists.txt | 14 +- grc/iqtlabs_retune_fft.block.yml | 19 +- grc/iqtlabs_retune_pre_fft.block.yml | 62 ++++ include/gnuradio/iqtlabs/CMakeLists.txt | 1 + include/gnuradio/iqtlabs/retune_fft.h | 3 +- include/gnuradio/iqtlabs/retune_pre_fft.h | 242 ++++++++++++++ lib/CMakeLists.txt | 2 + lib/base_impl.h | 2 +- lib/retune_fft_impl.cc | 142 ++------ lib/retune_fft_impl.h | 31 +- lib/retune_pre_fft_impl.cc | 310 +++++++++++++++++ lib/retune_pre_fft_impl.h | 239 +++++++++++++ lib/retuner_impl.cc | 313 ++++++++++++++++++ lib/retuner_impl.h | 248 ++++++++++++++ python/iqtlabs/bindings/CMakeLists.txt | 2 +- .../retune_pre_fft_pydoc_template.h | 24 ++ .../iqtlabs/bindings/failed_conversions.txt | 1 - python/iqtlabs/bindings/python_bindings.cc | 4 +- python/iqtlabs/bindings/retune_fft_python.cc | 3 +- .../iqtlabs/bindings/retune_pre_fft_python.cc | 53 +++ python/iqtlabs/qa_retune_fft.py | 60 +++- 23 files changed, 1605 insertions(+), 173 deletions(-) create mode 100644 grc/iqtlabs_retune_pre_fft.block.yml create mode 100644 include/gnuradio/iqtlabs/retune_pre_fft.h create mode 100644 lib/retune_pre_fft_impl.cc create mode 100644 lib/retune_pre_fft_impl.h create mode 100644 lib/retuner_impl.cc create mode 100644 lib/retuner_impl.h create mode 100644 python/iqtlabs/bindings/docstrings/retune_pre_fft_pydoc_template.h delete mode 100644 python/iqtlabs/bindings/failed_conversions.txt create mode 100644 python/iqtlabs/bindings/retune_pre_fft_python.cc diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index e0dd4734..bb33082c 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -20,7 +20,7 @@ jobs: fetch-depth: 0 - name: clang-format run: | - sudo apt-get update -yq && sudo apt-get install -yq clang-format python3-pip && pip3 install cmake_format && bin/run_c_format.sh $(pwd) lib include/gnuradio/iqtlabs + sudo apt-get update -yq && sudo apt-get install -yq clang-format python3-pip && pip3 install cmake_format && bin/run_c_format.sh $(pwd) lib include/gnuradio/iqtlabs grc test-latest: runs-on: ubuntu-latest steps: diff --git a/.gitignore b/.gitignore index ad8667ab..2b3b9866 100644 --- a/.gitignore +++ b/.gitignore @@ -5,5 +5,6 @@ libsigmf/ flatbuffers/ json/ VkFFT/ +SPIRV-Tools/ test_flow_graphs/test/ diff --git a/grc/CMakeLists.txt b/grc/CMakeLists.txt index c4ad8f85..c8c49103 100644 --- a/grc/CMakeLists.txt +++ b/grc/CMakeLists.txt @@ -3,11 +3,15 @@ # install( - FILES iqtlabs_tuneable_test_source.block.yml iqtlabs_retune_fft.block.yml - iqtlabs_write_freq_samples.block.yml iqtlabs_image_inference.block.yml + FILES iqtlabs_tuneable_test_source.block.yml + iqtlabs_retune_fft.block.yml + iqtlabs_write_freq_samples.block.yml + iqtlabs_image_inference.block.yml iqtlabs_vector_to_json.block.yml - iqtlabs_vector_roll.block.yml - iqtlabs_vkfft_short.block.yml DESTINATION share/gnuradio/grc/blocks) + iqtlabs_vector_roll.block.yml + iqtlabs_retune_pre_fft.block.yml + DESTINATION share/gnuradio/grc/blocks) if(Vulkan_FOUND) - install(FILES iqtlabs_vkfft.block.yml DESTINATION share/gnuradio/grc/blocks) + install(FILES iqtlabs_vkfft.block.yml iqtlabs_vkfft_short.block.yml + DESTINATION share/gnuradio/grc/blocks) endif() diff --git a/grc/iqtlabs_retune_fft.block.yml b/grc/iqtlabs_retune_fft.block.yml index 23b4a0d5..e7ab4ea3 100644 --- a/grc/iqtlabs_retune_fft.block.yml +++ b/grc/iqtlabs_retune_fft.block.yml @@ -13,12 +13,16 @@ documentation: |- input: vector of floats, representing FFT bucket values, tagged with center frequency. + cmd: + connection from retune_pre_fft to control tuning (optional). output: JSON scan summaries, one per line, containing "bucket" keys (with frequency: mean values), and "config" keys (representing block config). - tune: - connect to radio command port, generally "cmd". + tune: + connect to radio command port, generally "cmd". + json: + output buckets as zstd compressed JSON object (optional). parameters: tag: expected PMT tag containing center frequency @@ -43,6 +47,7 @@ documentation: |- "2.2e9-2.4e9,5.1e9-5.9e9". description: a string description to be included with each update. rotate_secs: if > 0, use a new epoch timestamped directory every N seconds. + pre_fft: if True, tuning is controlled by the retune_pre_fft block. example JSON output: { "ts": , "sweep start": , @@ -59,7 +64,7 @@ templates: iqtlabs.retune_fft(${tag}, ${vlen}, ${nfft}, ${samp_rate}, ${freq_start}, ${freq_end}, ${tune_step_hz}, ${tune_step_fft}, ${skip_tune_step_fft}, ${fft_min}, ${fft_max}, ${sdir}, ${write_step_fft}, ${bucket_range}, - ${tuning_ranges}, ${description}, ${rotate_secs}) + ${tuning_ranges}, ${description}, ${rotate_secs}, ${pre_fft}) cpp_templates: includes: ['#include '] @@ -68,7 +73,8 @@ cpp_templates: this->${id} = gr::iqtlabs::retune_fft::make(${tag}, ${vlen}, ${nfft}, ${samp_rate}, ${freq_start}, ${freq_end}, ${tune_step_hz}, ${tune_step_fft}, ${skip_tune_step_fft}, ${fft_min}, ${fft_max}, ${sdir}, ${write_step_fft}, - ${bucket_range}, ${tuning_ranges}, ${description}, ${rotate_secs}); + ${bucket_range}, ${tuning_ranges}, ${description}, ${rotate_secs}, + ${pre_fft}); link: ['libgnuradio-iqtlabs.so'] asserts: @@ -121,6 +127,8 @@ inputs: domain: stream dtype: float vlen: ${ vlen } + - label: cmd + domain: message outputs: - label: output @@ -129,5 +137,8 @@ outputs: vlen: 1 - label: tune domain: message + - label: json + domain: message + file_format: 1 diff --git a/grc/iqtlabs_retune_pre_fft.block.yml b/grc/iqtlabs_retune_pre_fft.block.yml new file mode 100644 index 00000000..4e33322d --- /dev/null +++ b/grc/iqtlabs_retune_pre_fft.block.yml @@ -0,0 +1,62 @@ +--- +id: iqtlabs_retune_pre_fft +label: retune_pre_fft +category: '[iqtlabs]' +flags: [python, cpp] + +templates: + imports: from gnuradio import iqtlabs + make: > + iqtlabs.retune_pre_fft( + ${nfft}, ${fft_batch_size}, + ${tag}, ${freq_start}, ${freq_end}, + ${tune_step_hz}, ${tune_step_fft}, ${skip_tune_step_fft}, + ${tuning_ranges}) + +cpp_templates: + includes: ['#include '] + declarations: 'gr::iqtlabs::retune_pre_fft::sptr ${id};' + make: > + this->${id} = gr::iqtlabs::retune_pre_fft::make( + ${nfft}, ${fft_batch_size}, + ${tag}, {freq_start}, ${freq_end}, + ${tune_step_hz}, ${tune_step_fft}, ${skip_tune_step_fft}, + ${tuning_ranges}); + link: ['libgnuradio-iqtlabs.so'] + +parameters: + - id: nfft + dtype: int + - id: fft_batch_size + dtype: int + - id: tag + dtype: string + default: 'rx_freq' + - id: freq_start + dtype: raw + - id: freq_end + dtype: raw + - id: tune_step_hz + dtype: int + - id: tune_step_fft + dtype: int + - id: skip_tune_step_fft + dtype: int + - id: tuning_ranges + dtype: string + +inputs: + - label: input + domain: stream + dtype: complex + vlen: 1 + +outputs: + - label: input + domain: stream + dtype: complex + vlen: ${ nfft * fft_batch_size } + - label: tune + domain: message + +file_format: 1 diff --git a/include/gnuradio/iqtlabs/CMakeLists.txt b/include/gnuradio/iqtlabs/CMakeLists.txt index acce82ac..eb21b75f 100644 --- a/include/gnuradio/iqtlabs/CMakeLists.txt +++ b/include/gnuradio/iqtlabs/CMakeLists.txt @@ -12,6 +12,7 @@ install( FILES api.h tuneable_test_source.h retune_fft.h + retune_pre_fft.h write_freq_samples.h image_inference.h vector_to_json.h diff --git a/include/gnuradio/iqtlabs/retune_fft.h b/include/gnuradio/iqtlabs/retune_fft.h index ee3a4542..8bd92bf0 100644 --- a/include/gnuradio/iqtlabs/retune_fft.h +++ b/include/gnuradio/iqtlabs/retune_fft.h @@ -234,7 +234,8 @@ class IQTLABS_API retune_fft : virtual public gr::block { uint64_t skip_tune_step_fft, double fft_min, double fft_max, const std::string &sdir, uint64_t write_step_fft, double bucket_range, const std::string &tuning_ranges, - const std::string &description, uint64_t rotate_secs); + const std::string &description, uint64_t rotate_secs, + bool pre_fft); }; } // namespace iqtlabs diff --git a/include/gnuradio/iqtlabs/retune_pre_fft.h b/include/gnuradio/iqtlabs/retune_pre_fft.h new file mode 100644 index 00000000..e165dfd9 --- /dev/null +++ b/include/gnuradio/iqtlabs/retune_pre_fft.h @@ -0,0 +1,242 @@ +/* -*- c++ -*- */ +/* Apache License + * Version 2.0, January 2004 + * http://www.apache.org/licenses/ + * + * TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + * + * 1. Definitions. + * + * "License" shall mean the terms and conditions for use, reproduction, + * and distribution as defined by Sections 1 through 9 of this document. + * + * "Licensor" shall mean the copyright owner or entity authorized by + * the copyright owner that is granting the License. + * + * "Legal Entity" shall mean the union of the acting entity and all + * other entities that control, are controlled by, or are under common + * control with that entity. For the purposes of this definition, + * "control" means (i) the power, direct or indirect, to cause the + * direction or management of such entity, whether by contract or + * otherwise, or (ii) ownership of fifty percent (50%) or more of the + * outstanding shares, or (iii) beneficial ownership of such entity. + * + * "You" (or "Your") shall mean an individual or Legal Entity + * exercising permissions granted by this License. + * + * "Source" form shall mean the preferred form for making modifications, + * including but not limited to software source code, documentation + * source, and configuration files. + * + * "Object" form shall mean any form resulting from mechanical + * transformation or translation of a Source form, including but + * not limited to compiled object code, generated documentation, + * and conversions to other media types. + * + * "Work" shall mean the work of authorship, whether in Source or + * Object form, made available under the License, as indicated by a + * copyright notice that is included in or attached to the work + * (an example is provided in the Appendix below). + * + * "Derivative Works" shall mean any work, whether in Source or Object + * form, that is based on (or derived from) the Work and for which the + * editorial revisions, annotations, elaborations, or other modifications + * represent, as a whole, an original work of authorship. For the purposes + * of this License, Derivative Works shall not include works that remain + * separable from, or merely link (or bind by name) to the interfaces of, + * the Work and Derivative Works thereof. + * + * "Contribution" shall mean any work of authorship, including + * the original version of the Work and any modifications or additions + * to that Work or Derivative Works thereof, that is intentionally + * submitted to Licensor for inclusion in the Work by the copyright owner + * or by an individual or Legal Entity authorized to submit on behalf of + * the copyright owner. For the purposes of this definition, "submitted" + * means any form of electronic, verbal, or written communication sent + * to the Licensor or its representatives, including but not limited to + * communication on electronic mailing lists, source code control systems, + * and issue tracking systems that are managed by, or on behalf of, the + * Licensor for the purpose of discussing and improving the Work, but + * excluding communication that is conspicuously marked or otherwise + * designated in writing by the copyright owner as "Not a Contribution." + * + * "Contributor" shall mean Licensor and any individual or Legal Entity + * on behalf of whom a Contribution has been received by Licensor and + * subsequently incorporated within the Work. + * + * 2. Grant of Copyright License. Subject to the terms and conditions of + * this License, each Contributor hereby grants to You a perpetual, + * worldwide, non-exclusive, no-charge, royalty-free, irrevocable + * copyright license to reproduce, prepare Derivative Works of, + * publicly display, publicly perform, sublicense, and distribute the + * Work and such Derivative Works in Source or Object form. + * + * 3. Grant of Patent License. Subject to the terms and conditions of + * this License, each Contributor hereby grants to You a perpetual, + * worldwide, non-exclusive, no-charge, royalty-free, irrevocable + * (except as stated in this section) patent license to make, have made, + * use, offer to sell, sell, import, and otherwise transfer the Work, + * where such license applies only to those patent claims licensable + * by such Contributor that are necessarily infringed by their + * Contribution(s) alone or by combination of their Contribution(s) + * with the Work to which such Contribution(s) was submitted. If You + * institute patent litigation against any entity (including a + * cross-claim or counterclaim in a lawsuit) alleging that the Work + * or a Contribution incorporated within the Work constitutes direct + * or contributory patent infringement, then any patent licenses + * granted to You under this License for that Work shall terminate + * as of the date such litigation is filed. + * + * 4. Redistribution. You may reproduce and distribute copies of the + * Work or Derivative Works thereof in any medium, with or without + * modifications, and in Source or Object form, provided that You + * meet the following conditions: + * + * (a) You must give any other recipients of the Work or + * Derivative Works a copy of this License; and + * + * (b) You must cause any modified files to carry prominent notices + * stating that You changed the files; and + * + * (c) You must retain, in the Source form of any Derivative Works + * that You distribute, all copyright, patent, trademark, and + * attribution notices from the Source form of the Work, + * excluding those notices that do not pertain to any part of + * the Derivative Works; and + * + * (d) If the Work includes a "NOTICE" text file as part of its + * distribution, then any Derivative Works that You distribute must + * include a readable copy of the attribution notices contained + * within such NOTICE file, excluding those notices that do not + * pertain to any part of the Derivative Works, in at least one + * of the following places: within a NOTICE text file distributed + * as part of the Derivative Works; within the Source form or + * documentation, if provided along with the Derivative Works; or, + * within a display generated by the Derivative Works, if and + * wherever such third-party notices normally appear. The contents + * of the NOTICE file are for informational purposes only and + * do not modify the License. You may add Your own attribution + * notices within Derivative Works that You distribute, alongside + * or as an addendum to the NOTICE text from the Work, provided + * that such additional attribution notices cannot be construed + * as modifying the License. + * + * You may add Your own copyright statement to Your modifications and + * may provide additional or different license terms and conditions + * for use, reproduction, or distribution of Your modifications, or + * for any such Derivative Works as a whole, provided Your use, + * reproduction, and distribution of the Work otherwise complies with + * the conditions stated in this License. + * + * 5. Submission of Contributions. Unless You explicitly state otherwise, + * any Contribution intentionally submitted for inclusion in the Work + * by You to the Licensor shall be under the terms and conditions of + * this License, without any additional terms or conditions. + * Notwithstanding the above, nothing herein shall supersede or modify + * the terms of any separate license agreement you may have executed + * with Licensor regarding such Contributions. + * + * 6. Trademarks. This License does not grant permission to use the trade + * names, trademarks, service marks, or product names of the Licensor, + * except as required for reasonable and customary use in describing the + * origin of the Work and reproducing the content of the NOTICE file. + * + * 7. Disclaimer of Warranty. Unless required by applicable law or + * agreed to in writing, Licensor provides the Work (and each + * Contributor provides its Contributions) on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied, including, without limitation, any warranties or conditions + * of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + * PARTICULAR PURPOSE. You are solely responsible for determining the + * appropriateness of using or redistributing the Work and assume any + * risks associated with Your exercise of permissions under this License. + * + * 8. Limitation of Liability. In no event and under no legal theory, + * whether in tort (including negligence), contract, or otherwise, + * unless required by applicable law (such as deliberate and grossly + * negligent acts) or agreed to in writing, shall any Contributor be + * liable to You for damages, including any direct, indirect, special, + * incidental, or consequential damages of any character arising as a + * result of this License or out of the use or inability to use the + * Work (including but not limited to damages for loss of goodwill, + * work stoppage, computer failure or malfunction, or any and all + * other commercial damages or losses), even if such Contributor + * has been advised of the possibility of such damages. + * + * 9. Accepting Warranty or Additional Liability. While redistributing + * the Work or Derivative Works thereof, You may choose to offer, + * and charge a fee for, acceptance of support, warranty, indemnity, + * or other liability obligations and/or rights consistent with this + * License. However, in accepting such obligations, You may act only + * on Your own behalf and on Your sole responsibility, not on behalf + * of any other Contributor, and only if You agree to indemnify, + * defend, and hold each Contributor harmless for any liability + * incurred by, or claims asserted against, such Contributor by reason + * of your accepting any such warranty or additional liability. + * + * END OF TERMS AND CONDITIONS + * + * APPENDIX: How to apply the Apache License to your work. + * + * To apply the Apache License to your work, attach the following + * boilerplate notice, with the fields enclosed by brackets "[]" + * replaced with your own identifying information. (Don't include + * the brackets!) The text should be enclosed in the appropriate + * comment syntax for the file format. We also recommend that a + * file or class name and description of purpose be included on the + * same "printed page" as the copyright notice for easier + * identification within third-party archives. + * + * Copyright [yyyy] [name of copyright owner] + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef INCLUDED_IQTLABS_RETUNE_PRE_FFT_H +#define INCLUDED_IQTLABS_RETUNE_PRE_FFT_H + +#include +#include + +namespace gr { +namespace iqtlabs { + +/*! + * \brief <+description of block+> + * \ingroup iqtlabs + * + */ +class IQTLABS_API retune_pre_fft : virtual public gr::sync_decimator { +public: + typedef std::shared_ptr sptr; + + /*! + * \brief Return a shared_ptr to a new instance of iqtlabs::retune_pre_fft. + * + * To avoid accidental use of raw pointers, iqtlabs::retune_pre_fft's + * constructor is in a private implementation + * class. iqtlabs::retune_pre_fft::make is the public interface for + * creating new instances. + */ + + static sptr make(size_t nfft, size_t fft_batch_size, const std::string &tag, + uint64_t freq_start, uint64_t freq_end, + uint64_t tune_step_hz, uint64_t tune_step_fft, + uint64_t skip_tune_step_fft, + const std::string &tuning_ranges); +}; + +} // namespace iqtlabs +} // namespace gr + +#endif /* INCLUDED_IQTLABS_RETUNE_PRE_FFT_H */ diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index 561866a6..4eacb046 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -46,8 +46,10 @@ list( APPEND iqtlabs_sources base_impl.cc + retuner_impl.cc image_inference_impl.cc retune_fft_impl.cc + retune_pre_fft_impl.cc tuneable_test_source_impl.cc write_freq_samples_impl.cc vector_to_json_impl.cc diff --git a/lib/base_impl.h b/lib/base_impl.h index 2328cf26..7b27fed8 100644 --- a/lib/base_impl.h +++ b/lib/base_impl.h @@ -209,7 +209,7 @@ namespace gr { namespace iqtlabs { const pmt::pmt_t CMD_KEY = pmt::mp("cmd"); const pmt::pmt_t FREQ_KEY = pmt::mp("freq"); -const pmt::pmt_t TUNE = pmt::mp("tune"); +const pmt::pmt_t TUNE_KEY = pmt::mp("tune"); const pmt::pmt_t RX_TIME_KEY = pmt::string_to_symbol("rx_time"); const pmt::pmt_t RX_FREQ_KEY = pmt::string_to_symbol("rx_freq"); diff --git a/lib/retune_fft_impl.cc b/lib/retune_fft_impl.cc index 13736c37..755c10b7 100644 --- a/lib/retune_fft_impl.cc +++ b/lib/retune_fft_impl.cc @@ -203,7 +203,6 @@ */ #include "retune_fft_impl.h" -#include #include #include #include @@ -215,22 +214,21 @@ namespace gr { namespace iqtlabs { -const pmt::pmt_t JSON_OUTPUT = pmt::mp("json_output"); +const pmt::pmt_t JSON_KEY = pmt::mp("json"); const boost::iostreams::zstd_params zstd_params = boost::iostreams::zstd_params(boost::iostreams::zstd::default_compression); -retune_fft::sptr -retune_fft::make(const std::string &tag, size_t vlen, size_t nfft, - uint64_t samp_rate, uint64_t freq_start, uint64_t freq_end, - uint64_t tune_step_hz, uint64_t tune_step_fft, - uint64_t skip_tune_step_fft, double fft_min, double fft_max, - const std::string &sdir, uint64_t write_step_fft, - double bucket_range, const std::string &tuning_ranges, - const std::string &description, uint64_t rotate_secs) { +retune_fft::sptr retune_fft::make( + const std::string &tag, size_t vlen, size_t nfft, uint64_t samp_rate, + uint64_t freq_start, uint64_t freq_end, uint64_t tune_step_hz, + uint64_t tune_step_fft, uint64_t skip_tune_step_fft, double fft_min, + double fft_max, const std::string &sdir, uint64_t write_step_fft, + double bucket_range, const std::string &tuning_ranges, + const std::string &description, uint64_t rotate_secs, bool pre_fft) { return gnuradio::make_block_sptr( tag, vlen, nfft, samp_rate, freq_start, freq_end, tune_step_hz, tune_step_fft, skip_tune_step_fft, fft_min, fft_max, sdir, write_step_fft, - bucket_range, tuning_ranges, description, rotate_secs); + bucket_range, tuning_ranges, description, rotate_secs, pre_fft); } retune_fft_impl::retune_fft_impl( @@ -239,88 +237,26 @@ retune_fft_impl::retune_fft_impl( uint64_t tune_step_fft, uint64_t skip_tune_step_fft, double fft_min, double fft_max, const std::string &sdir, uint64_t write_step_fft, double bucket_range, const std::string &tuning_ranges, - const std::string &description, uint64_t rotate_secs) + const std::string &description, uint64_t rotate_secs, bool pre_fft) : gr::block("retune_fft", gr::io_signature::make(1 /* min inputs */, 1 /* max inputs */, vlen * sizeof(input_type)), gr::io_signature::make(1 /* min outputs */, 1 /*max outputs */, sizeof(output_type))), + retuner_impl(freq_start, freq_end, tune_step_hz, tune_step_fft, + skip_tune_step_fft, tuning_ranges), tag_(pmt::intern(tag)), vlen_(vlen), nfft_(nfft), samp_rate_(samp_rate), - freq_start_(freq_start), freq_end_(freq_end), tune_step_hz_(tune_step_hz), - tune_step_fft_(tune_step_fft), skip_tune_step_fft_(skip_tune_step_fft), - skip_fft_count_(skip_tune_step_fft), fft_min_(fft_min), fft_max_(fft_max), - sample_(nfft), sample_count_(0), last_rx_freq_(0), last_rx_time_(0), - fft_count_(0), last_sweep_start_(0), pending_retune_(0), - total_tune_count_(0), sdir_(sdir), write_step_fft_(write_step_fft), + fft_min_(fft_min), fft_max_(fft_max), sample_(nfft), sample_count_(0), + sdir_(sdir), write_step_fft_(write_step_fft), write_step_fft_count_(write_step_fft), bucket_range_(bucket_range), - description_(description), rotate_secs_(rotate_secs) { - outbuf_p.reset(new boost::iostreams::filtering_ostream()); - message_port_register_out(TUNE); - message_port_register_out(JSON_OUTPUT); + description_(description), rotate_secs_(rotate_secs), pre_fft_(pre_fft) { bucket_offset_ = round(float((vlen_ - round(bucket_range_ * vlen_)) / 2)); - if (tuning_ranges.length() == 0) { - if (freq_end <= freq_start) { - throw std::invalid_argument( - "invalid freq_start/freq_end (end must be greater than start)"); - } - d_logger->debug("tuning_ranges empty, will scan from {} to {}", freq_start_, - freq_end_); - add_range_(freq_start_, freq_end_); - } else { - std::vector tuning_ranges_raw; - boost::split(tuning_ranges_raw, tuning_ranges, boost::is_any_of(","), - boost::token_compress_on); - d_logger->debug("using tuning_ranges"); - freq_start_ = UINT64_MAX; - freq_end_ = 0; - for (size_t i = 0; i < tuning_ranges_raw.size(); ++i) { - std::vector tuning_range_raw; - boost::split(tuning_range_raw, tuning_ranges_raw[i], - boost::is_any_of("-"), boost::token_compress_on); - if (tuning_range_raw.size() != 2) { - throw std::invalid_argument("invalid tuning_range (must be min-max)"); - } - uint64_t tuning_range_freq_start = - (uint64_t)strtold(tuning_range_raw[0].c_str(), NULL); - if (!tuning_range_freq_start) { - throw std::invalid_argument("tuning range min cannot be 0"); - } - uint64_t tuning_range_freq_end = - (uint64_t)strtold(tuning_range_raw[1].c_str(), NULL); - if (!tuning_range_freq_end) { - throw std::invalid_argument("tuning range max cannot be 0"); - } - if (tuning_range_freq_end <= tuning_range_freq_start) { - throw std::invalid_argument( - "invalid tuning_range (max must be greater than min)"); - } - if (i) { - if (tuning_ranges_.back().freq_end >= tuning_range_freq_start) { - throw std::invalid_argument("tuning_ranges must be sorted - cannot " - "have overlapping tuning ranges"); - } - } - freq_start_ = std::min(freq_start_, tuning_range_freq_start); - freq_end_ = std::max(freq_end_, tuning_range_freq_end); - d_logger->debug("tuning range {} will scan from {} to {}", i, - tuning_range_freq_start, tuning_range_freq_end); - add_range_(tuning_range_freq_start, tuning_range_freq_end); - } - d_logger->debug( - "resetting freq_start to {} and freq_end to {} from tuning_ranges", - freq_start_, freq_end_); - } - tuning_range_ = 0; - last_tuning_range_ = 0; - tune_freq_ = tuning_ranges_[0].freq_start; - tuning_range_step_ = 0; - d_logger->debug("bucket_offset {}", bucket_offset_); -} - -void retune_fft_impl::add_range_(uint64_t freq_start, uint64_t freq_end) { - uint64_t steps = (freq_end - freq_start) / tune_step_hz_ + 1; - tuning_ranges_.push_back({freq_start, freq_end, steps}); - d_logger->debug("add range {} to {} step {}", freq_start, freq_end, steps); + outbuf_p.reset(new boost::iostreams::filtering_ostream()); + message_port_register_out(TUNE_KEY); + message_port_register_out(JSON_KEY); + message_port_register_in(CMD_KEY); + set_msg_handler(CMD_KEY, + [this](const pmt::pmt_t &msg) { next_retune_(host_now_()); }); } retune_fft_impl::~retune_fft_impl() { close_(); } @@ -350,39 +286,16 @@ void retune_fft_impl::close_() { void retune_fft_impl::send_retune_(uint64_t tune_freq) { d_logger->debug("retuning to {}", tune_freq); - ++total_tune_count_; - ++pending_retune_; pmt::pmt_t tune_rx = pmt::make_dict(); tune_rx = pmt::dict_add(tune_rx, pmt::mp("freq"), pmt::from_long(tune_freq)); tune_rx = pmt::dict_add(tune_rx, pmt::mp("tag"), pmt::mp("now")); - message_port_pub(TUNE, tune_rx); + message_port_pub(TUNE_KEY, tune_rx); } void retune_fft_impl::retune_now_() { const double host_now = host_now_(); send_retune_(tune_freq_); - last_tuning_range_ = tuning_range_; - size_t range_steps = tuning_ranges_[tuning_range_].steps; - if (range_steps == 1) { - last_sweep_start_ = host_now; - return; - } - tune_freq_ = std::min(tune_freq_ + tune_step_hz_, - tuning_ranges_[tuning_range_].freq_end); - ++tuning_range_step_; - if (last_sweep_start_ == 0) { - last_sweep_start_ = host_now; - } else { - if (tuning_range_step_ == range_steps) { - tuning_range_step_ = 0; - tuning_range_ = (tuning_range_ + 1) % tuning_ranges_.size(); - d_logger->debug("moving to tuning range {}", tuning_range_); - tune_freq_ = tuning_ranges_[tuning_range_].freq_start; - if (tuning_range_ == 0) { - last_sweep_start_ = host_now; - } - } - } + next_retune_(host_now); } void retune_fft_impl::write_items_(const input_type *in) { @@ -415,9 +328,10 @@ void retune_fft_impl::process_items_(size_t c, const input_type *&in) { write_items_(in); sum_items_(in); ++sample_count_; - if ((pending_retune_ == 0 || total_tune_count_ == 0) && - ++fft_count_ >= tune_step_fft_) { - retune_now_(); + if (need_retune_(1)) { + if (!pre_fft_) { + retune_now_(); + } } } } @@ -503,7 +417,7 @@ void retune_fft_impl::write_buckets_(double host_now, uint64_t rx_freq) { pmt::cons(pmt::make_dict(), pmt::init_u8vector(compressed_s.length(), (const uint8_t *)compressed_s.c_str())); - message_port_pub(JSON_OUTPUT, pdu); + message_port_pub(JSON_KEY, pdu); } void retune_fft_impl::process_buckets_(uint64_t rx_freq, double rx_time) { diff --git a/lib/retune_fft_impl.h b/lib/retune_fft_impl.h index b8c55564..99a03f86 100644 --- a/lib/retune_fft_impl.h +++ b/lib/retune_fft_impl.h @@ -206,6 +206,7 @@ #define INCLUDED_IQTLABS_RETUNE_FFT_IMPL_H #include "base_impl.h" +#include "retuner_impl.h" #include #include #include @@ -218,15 +219,8 @@ namespace iqtlabs { using input_type = float; using output_type = char; -typedef struct { - uint64_t freq_start; - uint64_t freq_end; - size_t steps; -} tuning_range_t; - -class retune_fft_impl : public retune_fft, base_impl { +class retune_fft_impl : public retune_fft, base_impl, retuner_impl { private: - void add_range_(uint64_t freq_start, uint64_t freq_end); void retune_now_(); void write_items_(const input_type *in); void sum_items_(const input_type *in); @@ -247,16 +241,12 @@ class retune_fft_impl : public retune_fft, base_impl { size_t vlen_; size_t nfft_; uint64_t samp_rate_; - uint64_t freq_start_; - uint64_t freq_end_; - uint64_t tune_step_hz_; - uint64_t tune_step_fft_; - uint64_t skip_tune_step_fft_; uint64_t write_step_fft_; uint64_t rotate_secs_; double bucket_range_; std::string sdir_; std::string description_; + bool pre_fft_; double fft_min_; double fft_max_; @@ -264,20 +254,8 @@ class retune_fft_impl : public retune_fft, base_impl { std::deque out_buf_; std::vector sample_; size_t sample_count_; - uint64_t tune_freq_; - uint64_t last_rx_freq_; - double last_rx_time_; - uint64_t fft_count_; - double last_sweep_start_; - uint64_t skip_fft_count_; - uint64_t total_tune_count_; - uint64_t pending_retune_; uint64_t write_step_fft_count_; size_t bucket_offset_; - std::vector tuning_ranges_; - size_t tuning_range_; - size_t last_tuning_range_; - size_t tuning_range_step_; boost::scoped_ptr outbuf_p; std::string file_; @@ -289,7 +267,8 @@ class retune_fft_impl : public retune_fft, base_impl { uint64_t skip_tune_step_fft, double fft_min, double fft_max, const std::string &sdir, uint64_t write_step_fft, double bucket_range, const std::string &tuning_ranges, - const std::string &description, uint64_t rotate_secs); + const std::string &description, uint64_t rotate_secs, + bool pre_fft); ~retune_fft_impl(); void forecast(int noutput_items, gr_vector_int &ninput_items_required); int general_work(int noutput_items, gr_vector_int &ninput_items, diff --git a/lib/retune_pre_fft_impl.cc b/lib/retune_pre_fft_impl.cc new file mode 100644 index 00000000..3c5c91f4 --- /dev/null +++ b/lib/retune_pre_fft_impl.cc @@ -0,0 +1,310 @@ +/* -*- c++ -*- */ +/* Apache License + * Version 2.0, January 2004 + * http://www.apache.org/licenses/ + * + * TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + * + * 1. Definitions. + * + * "License" shall mean the terms and conditions for use, reproduction, + * and distribution as defined by Sections 1 through 9 of this document. + * + * "Licensor" shall mean the copyright owner or entity authorized by + * the copyright owner that is granting the License. + * + * "Legal Entity" shall mean the union of the acting entity and all + * other entities that control, are controlled by, or are under common + * control with that entity. For the purposes of this definition, + * "control" means (i) the power, direct or indirect, to cause the + * direction or management of such entity, whether by contract or + * otherwise, or (ii) ownership of fifty percent (50%) or more of the + * outstanding shares, or (iii) beneficial ownership of such entity. + * + * "You" (or "Your") shall mean an individual or Legal Entity + * exercising permissions granted by this License. + * + * "Source" form shall mean the preferred form for making modifications, + * including but not limited to software source code, documentation + * source, and configuration files. + * + * "Object" form shall mean any form resulting from mechanical + * transformation or translation of a Source form, including but + * not limited to compiled object code, generated documentation, + * and conversions to other media types. + * + * "Work" shall mean the work of authorship, whether in Source or + * Object form, made available under the License, as indicated by a + * copyright notice that is included in or attached to the work + * (an example is provided in the Appendix below). + * + * "Derivative Works" shall mean any work, whether in Source or Object + * form, that is based on (or derived from) the Work and for which the + * editorial revisions, annotations, elaborations, or other modifications + * represent, as a whole, an original work of authorship. For the purposes + * of this License, Derivative Works shall not include works that remain + * separable from, or merely link (or bind by name) to the interfaces of, + * the Work and Derivative Works thereof. + * + * "Contribution" shall mean any work of authorship, including + * the original version of the Work and any modifications or additions + * to that Work or Derivative Works thereof, that is intentionally + * submitted to Licensor for inclusion in the Work by the copyright owner + * or by an individual or Legal Entity authorized to submit on behalf of + * the copyright owner. For the purposes of this definition, "submitted" + * means any form of electronic, verbal, or written communication sent + * to the Licensor or its representatives, including but not limited to + * communication on electronic mailing lists, source code control systems, + * and issue tracking systems that are managed by, or on behalf of, the + * Licensor for the purpose of discussing and improving the Work, but + * excluding communication that is conspicuously marked or otherwise + * designated in writing by the copyright owner as "Not a Contribution." + * + * "Contributor" shall mean Licensor and any individual or Legal Entity + * on behalf of whom a Contribution has been received by Licensor and + * subsequently incorporated within the Work. + * + * 2. Grant of Copyright License. Subject to the terms and conditions of + * this License, each Contributor hereby grants to You a perpetual, + * worldwide, non-exclusive, no-charge, royalty-free, irrevocable + * copyright license to reproduce, prepare Derivative Works of, + * publicly display, publicly perform, sublicense, and distribute the + * Work and such Derivative Works in Source or Object form. + * + * 3. Grant of Patent License. Subject to the terms and conditions of + * this License, each Contributor hereby grants to You a perpetual, + * worldwide, non-exclusive, no-charge, royalty-free, irrevocable + * (except as stated in this section) patent license to make, have made, + * use, offer to sell, sell, import, and otherwise transfer the Work, + * where such license applies only to those patent claims licensable + * by such Contributor that are necessarily infringed by their + * Contribution(s) alone or by combination of their Contribution(s) + * with the Work to which such Contribution(s) was submitted. If You + * institute patent litigation against any entity (including a + * cross-claim or counterclaim in a lawsuit) alleging that the Work + * or a Contribution incorporated within the Work constitutes direct + * or contributory patent infringement, then any patent licenses + * granted to You under this License for that Work shall terminate + * as of the date such litigation is filed. + * + * 4. Redistribution. You may reproduce and distribute copies of the + * Work or Derivative Works thereof in any medium, with or without + * modifications, and in Source or Object form, provided that You + * meet the following conditions: + * + * (a) You must give any other recipients of the Work or + * Derivative Works a copy of this License; and + * + * (b) You must cause any modified files to carry prominent notices + * stating that You changed the files; and + * + * (c) You must retain, in the Source form of any Derivative Works + * that You distribute, all copyright, patent, trademark, and + * attribution notices from the Source form of the Work, + * excluding those notices that do not pertain to any part of + * the Derivative Works; and + * + * (d) If the Work includes a "NOTICE" text file as part of its + * distribution, then any Derivative Works that You distribute must + * include a readable copy of the attribution notices contained + * within such NOTICE file, excluding those notices that do not + * pertain to any part of the Derivative Works, in at least one + * of the following places: within a NOTICE text file distributed + * as part of the Derivative Works; within the Source form or + * documentation, if provided along with the Derivative Works; or, + * within a display generated by the Derivative Works, if and + * wherever such third-party notices normally appear. The contents + * of the NOTICE file are for informational purposes only and + * do not modify the License. You may add Your own attribution + * notices within Derivative Works that You distribute, alongside + * or as an addendum to the NOTICE text from the Work, provided + * that such additional attribution notices cannot be construed + * as modifying the License. + * + * You may add Your own copyright statement to Your modifications and + * may provide additional or different license terms and conditions + * for use, reproduction, or distribution of Your modifications, or + * for any such Derivative Works as a whole, provided Your use, + * reproduction, and distribution of the Work otherwise complies with + * the conditions stated in this License. + * + * 5. Submission of Contributions. Unless You explicitly state otherwise, + * any Contribution intentionally submitted for inclusion in the Work + * by You to the Licensor shall be under the terms and conditions of + * this License, without any additional terms or conditions. + * Notwithstanding the above, nothing herein shall supersede or modify + * the terms of any separate license agreement you may have executed + * with Licensor regarding such Contributions. + * + * 6. Trademarks. This License does not grant permission to use the trade + * names, trademarks, service marks, or product names of the Licensor, + * except as required for reasonable and customary use in describing the + * origin of the Work and reproducing the content of the NOTICE file. + * + * 7. Disclaimer of Warranty. Unless required by applicable law or + * agreed to in writing, Licensor provides the Work (and each + * Contributor provides its Contributions) on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied, including, without limitation, any warranties or conditions + * of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + * PARTICULAR PURPOSE. You are solely responsible for determining the + * appropriateness of using or redistributing the Work and assume any + * risks associated with Your exercise of permissions under this License. + * + * 8. Limitation of Liability. In no event and under no legal theory, + * whether in tort (including negligence), contract, or otherwise, + * unless required by applicable law (such as deliberate and grossly + * negligent acts) or agreed to in writing, shall any Contributor be + * liable to You for damages, including any direct, indirect, special, + * incidental, or consequential damages of any character arising as a + * result of this License or out of the use or inability to use the + * Work (including but not limited to damages for loss of goodwill, + * work stoppage, computer failure or malfunction, or any and all + * other commercial damages or losses), even if such Contributor + * has been advised of the possibility of such damages. + * + * 9. Accepting Warranty or Additional Liability. While redistributing + * the Work or Derivative Works thereof, You may choose to offer, + * and charge a fee for, acceptance of support, warranty, indemnity, + * or other liability obligations and/or rights consistent with this + * License. However, in accepting such obligations, You may act only + * on Your own behalf and on Your sole responsibility, not on behalf + * of any other Contributor, and only if You agree to indemnify, + * defend, and hold each Contributor harmless for any liability + * incurred by, or claims asserted against, such Contributor by reason + * of your accepting any such warranty or additional liability. + * + * END OF TERMS AND CONDITIONS + * + * APPENDIX: How to apply the Apache License to your work. + * + * To apply the Apache License to your work, attach the following + * boilerplate notice, with the fields enclosed by brackets "[]" + * replaced with your own identifying information. (Don't include + * the brackets!) The text should be enclosed in the appropriate + * comment syntax for the file format. We also recommend that a + * file or class name and description of purpose be included on the + * same "printed page" as the copyright notice for easier + * identification within third-party archives. + * + * Copyright [yyyy] [name of copyright owner] + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "retune_pre_fft_impl.h" +#include +#include + +namespace gr { +namespace iqtlabs { + +using block_type = gr_complex; + +retune_pre_fft::sptr +retune_pre_fft::make(size_t nfft, size_t fft_batch_size, const std::string &tag, + uint64_t freq_start, uint64_t freq_end, + uint64_t tune_step_hz, uint64_t tune_step_fft, + uint64_t skip_tune_step_fft, + const std::string &tuning_ranges) { + return gnuradio::make_block_sptr( + nfft, fft_batch_size, tag, freq_start, freq_end, tune_step_hz, + tune_step_fft, skip_tune_step_fft, tuning_ranges); +} + +retune_pre_fft_impl::retune_pre_fft_impl(size_t nfft, size_t fft_batch_size, + const std::string &tag, + uint64_t freq_start, uint64_t freq_end, + uint64_t tune_step_hz, + uint64_t tune_step_fft, + uint64_t skip_tune_step_fft, + const std::string &tuning_ranges) + : gr::sync_decimator( + "retune_pre_fft", + gr::io_signature::make(1 /* min inputs */, 1 /* max inputs */, + sizeof(block_type)), + gr::io_signature::make(1 /* min outputs */, 1 /* max outputs */, + sizeof(block_type) * nfft * fft_batch_size), + nfft * fft_batch_size /*<+decimation+>*/), + retuner_impl(freq_start, freq_end, tune_step_hz, tune_step_fft, + skip_tune_step_fft, tuning_ranges), + nfft_(nfft), fft_batch_size_(fft_batch_size), tag_(pmt::intern(tag)) { + message_port_register_out(TUNE_KEY); +} + +retune_pre_fft_impl::~retune_pre_fft_impl() {} + +void retune_pre_fft_impl::send_retune_(uint64_t tune_freq) { + d_logger->debug("retuning to {}", tune_freq); + pmt::pmt_t tune_rx = pmt::make_dict(); + tune_rx = pmt::dict_add(tune_rx, pmt::mp("freq"), pmt::from_long(tune_freq)); + tune_rx = pmt::dict_add(tune_rx, pmt::mp("tag"), pmt::mp("now")); + message_port_pub(TUNE_KEY, tune_rx); +} + +void retune_pre_fft_impl::retune_now_() { + const double host_now = host_now_(); + send_retune_(tune_freq_); + next_retune_(host_now); +} + +int retune_pre_fft_impl::work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) { + const block_type *in = static_cast(input_items[0]); + auto out = static_cast(output_items[0]); + const size_t block_size = nfft_ * fft_batch_size_; + const size_t out_ffts = noutput_items * fft_batch_size_; + size_t in_count = noutput_items * block_size; + size_t in_first = nitems_read(0); + std::vector all_tags, rx_freq_tags; + std::vector rx_times; + get_tags_in_window(all_tags, 0, 0, in_count); + get_tags(tag_, all_tags, rx_freq_tags, rx_times, in_count); + + if (skip_fft_count_) { + if (out_ffts > skip_fft_count_) { + skip_fft_count_ = 0; + } else { + skip_fft_count_ -= out_ffts; + } + return 0; + } + + if (need_retune_(out_ffts)) { + retune_now_(); + } + + memcpy((void *)out, (void *)in, + sizeof(block_type) * block_size * noutput_items); + + // TODO: handle more than one retune per batch. + for (size_t t = 0; t < rx_freq_tags.size(); ++t) { + const auto &tag = rx_freq_tags[t]; + const uint64_t rx_freq = (uint64_t)pmt::to_double(tag.value); + const double rx_time = rx_times[t]; + d_logger->debug("new rx_freq tag: {}, last {}", rx_freq, last_rx_freq_); + if (pending_retune_) { + --pending_retune_; + fft_count_ = 0; + skip_fft_count_ = skip_tune_step_fft_; + last_rx_freq_ = rx_freq; + last_rx_time_ = rx_time; + } + } + + return noutput_items; +} + +} /* namespace iqtlabs */ +} /* namespace gr */ diff --git a/lib/retune_pre_fft_impl.h b/lib/retune_pre_fft_impl.h new file mode 100644 index 00000000..c633b7f9 --- /dev/null +++ b/lib/retune_pre_fft_impl.h @@ -0,0 +1,239 @@ +/* -*- c++ -*- */ +/* Apache License + * Version 2.0, January 2004 + * http://www.apache.org/licenses/ + * + * TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + * + * 1. Definitions. + * + * "License" shall mean the terms and conditions for use, reproduction, + * and distribution as defined by Sections 1 through 9 of this document. + * + * "Licensor" shall mean the copyright owner or entity authorized by + * the copyright owner that is granting the License. + * + * "Legal Entity" shall mean the union of the acting entity and all + * other entities that control, are controlled by, or are under common + * control with that entity. For the purposes of this definition, + * "control" means (i) the power, direct or indirect, to cause the + * direction or management of such entity, whether by contract or + * otherwise, or (ii) ownership of fifty percent (50%) or more of the + * outstanding shares, or (iii) beneficial ownership of such entity. + * + * "You" (or "Your") shall mean an individual or Legal Entity + * exercising permissions granted by this License. + * + * "Source" form shall mean the preferred form for making modifications, + * including but not limited to software source code, documentation + * source, and configuration files. + * + * "Object" form shall mean any form resulting from mechanical + * transformation or translation of a Source form, including but + * not limited to compiled object code, generated documentation, + * and conversions to other media types. + * + * "Work" shall mean the work of authorship, whether in Source or + * Object form, made available under the License, as indicated by a + * copyright notice that is included in or attached to the work + * (an example is provided in the Appendix below). + * + * "Derivative Works" shall mean any work, whether in Source or Object + * form, that is based on (or derived from) the Work and for which the + * editorial revisions, annotations, elaborations, or other modifications + * represent, as a whole, an original work of authorship. For the purposes + * of this License, Derivative Works shall not include works that remain + * separable from, or merely link (or bind by name) to the interfaces of, + * the Work and Derivative Works thereof. + * + * "Contribution" shall mean any work of authorship, including + * the original version of the Work and any modifications or additions + * to that Work or Derivative Works thereof, that is intentionally + * submitted to Licensor for inclusion in the Work by the copyright owner + * or by an individual or Legal Entity authorized to submit on behalf of + * the copyright owner. For the purposes of this definition, "submitted" + * means any form of electronic, verbal, or written communication sent + * to the Licensor or its representatives, including but not limited to + * communication on electronic mailing lists, source code control systems, + * and issue tracking systems that are managed by, or on behalf of, the + * Licensor for the purpose of discussing and improving the Work, but + * excluding communication that is conspicuously marked or otherwise + * designated in writing by the copyright owner as "Not a Contribution." + * + * "Contributor" shall mean Licensor and any individual or Legal Entity + * on behalf of whom a Contribution has been received by Licensor and + * subsequently incorporated within the Work. + * + * 2. Grant of Copyright License. Subject to the terms and conditions of + * this License, each Contributor hereby grants to You a perpetual, + * worldwide, non-exclusive, no-charge, royalty-free, irrevocable + * copyright license to reproduce, prepare Derivative Works of, + * publicly display, publicly perform, sublicense, and distribute the + * Work and such Derivative Works in Source or Object form. + * + * 3. Grant of Patent License. Subject to the terms and conditions of + * this License, each Contributor hereby grants to You a perpetual, + * worldwide, non-exclusive, no-charge, royalty-free, irrevocable + * (except as stated in this section) patent license to make, have made, + * use, offer to sell, sell, import, and otherwise transfer the Work, + * where such license applies only to those patent claims licensable + * by such Contributor that are necessarily infringed by their + * Contribution(s) alone or by combination of their Contribution(s) + * with the Work to which such Contribution(s) was submitted. If You + * institute patent litigation against any entity (including a + * cross-claim or counterclaim in a lawsuit) alleging that the Work + * or a Contribution incorporated within the Work constitutes direct + * or contributory patent infringement, then any patent licenses + * granted to You under this License for that Work shall terminate + * as of the date such litigation is filed. + * + * 4. Redistribution. You may reproduce and distribute copies of the + * Work or Derivative Works thereof in any medium, with or without + * modifications, and in Source or Object form, provided that You + * meet the following conditions: + * + * (a) You must give any other recipients of the Work or + * Derivative Works a copy of this License; and + * + * (b) You must cause any modified files to carry prominent notices + * stating that You changed the files; and + * + * (c) You must retain, in the Source form of any Derivative Works + * that You distribute, all copyright, patent, trademark, and + * attribution notices from the Source form of the Work, + * excluding those notices that do not pertain to any part of + * the Derivative Works; and + * + * (d) If the Work includes a "NOTICE" text file as part of its + * distribution, then any Derivative Works that You distribute must + * include a readable copy of the attribution notices contained + * within such NOTICE file, excluding those notices that do not + * pertain to any part of the Derivative Works, in at least one + * of the following places: within a NOTICE text file distributed + * as part of the Derivative Works; within the Source form or + * documentation, if provided along with the Derivative Works; or, + * within a display generated by the Derivative Works, if and + * wherever such third-party notices normally appear. The contents + * of the NOTICE file are for informational purposes only and + * do not modify the License. You may add Your own attribution + * notices within Derivative Works that You distribute, alongside + * or as an addendum to the NOTICE text from the Work, provided + * that such additional attribution notices cannot be construed + * as modifying the License. + * + * You may add Your own copyright statement to Your modifications and + * may provide additional or different license terms and conditions + * for use, reproduction, or distribution of Your modifications, or + * for any such Derivative Works as a whole, provided Your use, + * reproduction, and distribution of the Work otherwise complies with + * the conditions stated in this License. + * + * 5. Submission of Contributions. Unless You explicitly state otherwise, + * any Contribution intentionally submitted for inclusion in the Work + * by You to the Licensor shall be under the terms and conditions of + * this License, without any additional terms or conditions. + * Notwithstanding the above, nothing herein shall supersede or modify + * the terms of any separate license agreement you may have executed + * with Licensor regarding such Contributions. + * + * 6. Trademarks. This License does not grant permission to use the trade + * names, trademarks, service marks, or product names of the Licensor, + * except as required for reasonable and customary use in describing the + * origin of the Work and reproducing the content of the NOTICE file. + * + * 7. Disclaimer of Warranty. Unless required by applicable law or + * agreed to in writing, Licensor provides the Work (and each + * Contributor provides its Contributions) on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied, including, without limitation, any warranties or conditions + * of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + * PARTICULAR PURPOSE. You are solely responsible for determining the + * appropriateness of using or redistributing the Work and assume any + * risks associated with Your exercise of permissions under this License. + * + * 8. Limitation of Liability. In no event and under no legal theory, + * whether in tort (including negligence), contract, or otherwise, + * unless required by applicable law (such as deliberate and grossly + * negligent acts) or agreed to in writing, shall any Contributor be + * liable to You for damages, including any direct, indirect, special, + * incidental, or consequential damages of any character arising as a + * result of this License or out of the use or inability to use the + * Work (including but not limited to damages for loss of goodwill, + * work stoppage, computer failure or malfunction, or any and all + * other commercial damages or losses), even if such Contributor + * has been advised of the possibility of such damages. + * + * 9. Accepting Warranty or Additional Liability. While redistributing + * the Work or Derivative Works thereof, You may choose to offer, + * and charge a fee for, acceptance of support, warranty, indemnity, + * or other liability obligations and/or rights consistent with this + * License. However, in accepting such obligations, You may act only + * on Your own behalf and on Your sole responsibility, not on behalf + * of any other Contributor, and only if You agree to indemnify, + * defend, and hold each Contributor harmless for any liability + * incurred by, or claims asserted against, such Contributor by reason + * of your accepting any such warranty or additional liability. + * + * END OF TERMS AND CONDITIONS + * + * APPENDIX: How to apply the Apache License to your work. + * + * To apply the Apache License to your work, attach the following + * boilerplate notice, with the fields enclosed by brackets "[]" + * replaced with your own identifying information. (Don't include + * the brackets!) The text should be enclosed in the appropriate + * comment syntax for the file format. We also recommend that a + * file or class name and description of purpose be included on the + * same "printed page" as the copyright notice for easier + * identification within third-party archives. + * + * Copyright [yyyy] [name of copyright owner] + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef INCLUDED_IQTLABS_RETUNE_PRE_FFT_IMPL_H +#define INCLUDED_IQTLABS_RETUNE_PRE_FFT_IMPL_H + +#include "base_impl.h" +#include "retuner_impl.h" +#include + +namespace gr { +namespace iqtlabs { + +class retune_pre_fft_impl : public retune_pre_fft, base_impl, retuner_impl { +private: + void send_retune_(uint64_t tune_freq); + void retune_now_(); + + size_t nfft_; + size_t fft_batch_size_; + pmt::pmt_t tag_; + +public: + retune_pre_fft_impl(size_t nfft, size_t fft_batch_size, + const std::string &tag, uint64_t freq_start, + uint64_t freq_end, uint64_t tune_step_hz, + uint64_t tune_step_fft, uint64_t skip_tune_step_fft, + const std::string &tuning_ranges); + ~retune_pre_fft_impl(); + + int work(int noutput_items, gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +} // namespace iqtlabs +} // namespace gr + +#endif /* INCLUDED_IQTLABS_RETUNE_PRE_FFT_IMPL_H */ diff --git a/lib/retuner_impl.cc b/lib/retuner_impl.cc new file mode 100644 index 00000000..f636abd4 --- /dev/null +++ b/lib/retuner_impl.cc @@ -0,0 +1,313 @@ +/* -*- c++ -*- */ +/* Apache License + * Version 2.0, January 2004 + * http://www.apache.org/licenses/ + * + * TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + * + * 1. Definitions. + * + * "License" shall mean the terms and conditions for use, reproduction, + * and distribution as defined by Sections 1 through 9 of this document. + * + * "Licensor" shall mean the copyright owner or entity authorized by + * the copyright owner that is granting the License. + * + * "Legal Entity" shall mean the union of the acting entity and all + * other entities that control, are controlled by, or are under common + * control with that entity. For the purposes of this definition, + * "control" means (i) the power, direct or indirect, to cause the + * direction or management of such entity, whether by contract or + * otherwise, or (ii) ownership of fifty percent (50%) or more of the + * outstanding shares, or (iii) beneficial ownership of such entity. + * + * "You" (or "Your") shall mean an individual or Legal Entity + * exercising permissions granted by this License. + * + * "Source" form shall mean the preferred form for making modifications, + * including but not limited to software source code, documentation + * source, and configuration files. + * + * "Object" form shall mean any form resulting from mechanical + * transformation or translation of a Source form, including but + * not limited to compiled object code, generated documentation, + * and conversions to other media types. + * + * "Work" shall mean the work of authorship, whether in Source or + * Object form, made available under the License, as indicated by a + * copyright notice that is included in or attached to the work + * (an example is provided in the Appendix below). + * + * "Derivative Works" shall mean any work, whether in Source or Object + * form, that is based on (or derived from) the Work and for which the + * editorial revisions, annotations, elaborations, or other modifications + * represent, as a whole, an original work of authorship. For the purposes + * of this License, Derivative Works shall not include works that remain + * separable from, or merely link (or bind by name) to the interfaces of, + * the Work and Derivative Works thereof. + * + * "Contribution" shall mean any work of authorship, including + * the original version of the Work and any modifications or additions + * to that Work or Derivative Works thereof, that is intentionally + * submitted to Licensor for inclusion in the Work by the copyright owner + * or by an individual or Legal Entity authorized to submit on behalf of + * the copyright owner. For the purposes of this definition, "submitted" + * means any form of electronic, verbal, or written communication sent + * to the Licensor or its representatives, including but not limited to + * communication on electronic mailing lists, source code control systems, + * and issue tracking systems that are managed by, or on behalf of, the + * Licensor for the purpose of discussing and improving the Work, but + * excluding communication that is conspicuously marked or otherwise + * designated in writing by the copyright owner as "Not a Contribution." + * + * "Contributor" shall mean Licensor and any individual or Legal Entity + * on behalf of whom a Contribution has been received by Licensor and + * subsequently incorporated within the Work. + * + * 2. Grant of Copyright License. Subject to the terms and conditions of + * this License, each Contributor hereby grants to You a perpetual, + * worldwide, non-exclusive, no-charge, royalty-free, irrevocable + * copyright license to reproduce, prepare Derivative Works of, + * publicly display, publicly perform, sublicense, and distribute the + * Work and such Derivative Works in Source or Object form. + * + * 3. Grant of Patent License. Subject to the terms and conditions of + * this License, each Contributor hereby grants to You a perpetual, + * worldwide, non-exclusive, no-charge, royalty-free, irrevocable + * (except as stated in this section) patent license to make, have made, + * use, offer to sell, sell, import, and otherwise transfer the Work, + * where such license applies only to those patent claims licensable + * by such Contributor that are necessarily infringed by their + * Contribution(s) alone or by combination of their Contribution(s) + * with the Work to which such Contribution(s) was submitted. If You + * institute patent litigation against any entity (including a + * cross-claim or counterclaim in a lawsuit) alleging that the Work + * or a Contribution incorporated within the Work constitutes direct + * or contributory patent infringement, then any patent licenses + * granted to You under this License for that Work shall terminate + * as of the date such litigation is filed. + * + * 4. Redistribution. You may reproduce and distribute copies of the + * Work or Derivative Works thereof in any medium, with or without + * modifications, and in Source or Object form, provided that You + * meet the following conditions: + * + * (a) You must give any other recipients of the Work or + * Derivative Works a copy of this License; and + * + * (b) You must cause any modified files to carry prominent notices + * stating that You changed the files; and + * + * (c) You must retain, in the Source form of any Derivative Works + * that You distribute, all copyright, patent, trademark, and + * attribution notices from the Source form of the Work, + * excluding those notices that do not pertain to any part of + * the Derivative Works; and + * + * (d) If the Work includes a "NOTICE" text file as part of its + * distribution, then any Derivative Works that You distribute must + * include a readable copy of the attribution notices contained + * within such NOTICE file, excluding those notices that do not + * pertain to any part of the Derivative Works, in at least one + * of the following places: within a NOTICE text file distributed + * as part of the Derivative Works; within the Source form or + * documentation, if provided along with the Derivative Works; or, + * within a display generated by the Derivative Works, if and + * wherever such third-party notices normally appear. The contents + * of the NOTICE file are for informational purposes only and + * do not modify the License. You may add Your own attribution + * notices within Derivative Works that You distribute, alongside + * or as an addendum to the NOTICE text from the Work, provided + * that such additional attribution notices cannot be construed + * as modifying the License. + * + * You may add Your own copyright statement to Your modifications and + * may provide additional or different license terms and conditions + * for use, reproduction, or distribution of Your modifications, or + * for any such Derivative Works as a whole, provided Your use, + * reproduction, and distribution of the Work otherwise complies with + * the conditions stated in this License. + * + * 5. Submission of Contributions. Unless You explicitly state otherwise, + * any Contribution intentionally submitted for inclusion in the Work + * by You to the Licensor shall be under the terms and conditions of + * this License, without any additional terms or conditions. + * Notwithstanding the above, nothing herein shall supersede or modify + * the terms of any separate license agreement you may have executed + * with Licensor regarding such Contributions. + * + * 6. Trademarks. This License does not grant permission to use the trade + * names, trademarks, service marks, or product names of the Licensor, + * except as required for reasonable and customary use in describing the + * origin of the Work and reproducing the content of the NOTICE file. + * + * 7. Disclaimer of Warranty. Unless required by applicable law or + * agreed to in writing, Licensor provides the Work (and each + * Contributor provides its Contributions) on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied, including, without limitation, any warranties or conditions + * of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + * PARTICULAR PURPOSE. You are solely responsible for determining the + * appropriateness of using or redistributing the Work and assume any + * risks associated with Your exercise of permissions under this License. + * + * 8. Limitation of Liability. In no event and under no legal theory, + * whether in tort (including negligence), contract, or otherwise, + * unless required by applicable law (such as deliberate and grossly + * negligent acts) or agreed to in writing, shall any Contributor be + * liable to You for damages, including any direct, indirect, special, + * incidental, or consequential damages of any character arising as a + * result of this License or out of the use or inability to use the + * Work (including but not limited to damages for loss of goodwill, + * work stoppage, computer failure or malfunction, or any and all + * other commercial damages or losses), even if such Contributor + * has been advised of the possibility of such damages. + * + * 9. Accepting Warranty or Additional Liability. While redistributing + * the Work or Derivative Works thereof, You may choose to offer, + * and charge a fee for, acceptance of support, warranty, indemnity, + * or other liability obligations and/or rights consistent with this + * License. However, in accepting such obligations, You may act only + * on Your own behalf and on Your sole responsibility, not on behalf + * of any other Contributor, and only if You agree to indemnify, + * defend, and hold each Contributor harmless for any liability + * incurred by, or claims asserted against, such Contributor by reason + * of your accepting any such warranty or additional liability. + * + * END OF TERMS AND CONDITIONS + * + * APPENDIX: How to apply the Apache License to your work. + * + * To apply the Apache License to your work, attach the following + * boilerplate notice, with the fields enclosed by brackets "[]" + * replaced with your own identifying information. (Don't include + * the brackets!) The text should be enclosed in the appropriate + * comment syntax for the file format. We also recommend that a + * file or class name and description of purpose be included on the + * same "printed page" as the copyright notice for easier + * identification within third-party archives. + * + * Copyright [yyyy] [name of copyright owner] + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "retuner_impl.h" +#include + +namespace gr { +namespace iqtlabs { + +retuner_impl::retuner_impl(uint64_t freq_start, uint64_t freq_end, + uint64_t tune_step_hz, uint64_t tune_step_fft, + uint64_t skip_tune_step_fft, + const std::string &tuning_ranges) + : freq_start_(freq_start), freq_end_(freq_end), tune_step_hz_(tune_step_hz), + tune_step_fft_(tune_step_fft), skip_tune_step_fft_(skip_tune_step_fft), + tuning_range_(0), last_tuning_range_(0), tuning_range_step_(0), + last_rx_freq_(0), last_rx_time_(0), last_sweep_start_(0), fft_count_(0), + pending_retune_(0), total_tune_count_(0), tune_freq_(0), + skip_fft_count_(skip_tune_step_fft) { + parse_tuning_ranges_(tuning_ranges); +} + +void retuner_impl::add_range_(uint64_t freq_start, uint64_t freq_end) { + uint64_t steps = (freq_end - freq_start) / tune_step_hz_ + 1; + tuning_ranges_.push_back({freq_start, freq_end, steps}); +} + +bool retuner_impl::need_retune_(size_t n) { + fft_count_ += n; + if ((pending_retune_ == 0 || total_tune_count_ == 0) && + fft_count_ >= tune_step_fft_) { + return true; + } + return false; +} + +void retuner_impl::parse_tuning_ranges_(const std::string &tuning_ranges) { + if (tuning_ranges.length() == 0) { + if (freq_end_ <= freq_start_) { + throw std::invalid_argument( + "invalid freq_start/freq_end (end must be greater than start)"); + } + add_range_(freq_start_, freq_end_); + } else { + std::vector tuning_ranges_raw; + boost::split(tuning_ranges_raw, tuning_ranges, boost::is_any_of(","), + boost::token_compress_on); + freq_start_ = UINT64_MAX; + freq_end_ = 0; + for (size_t i = 0; i < tuning_ranges_raw.size(); ++i) { + std::vector tuning_range_raw; + boost::split(tuning_range_raw, tuning_ranges_raw[i], + boost::is_any_of("-"), boost::token_compress_on); + if (tuning_range_raw.size() != 2) { + throw std::invalid_argument("invalid tuning_range (must be min-max)"); + } + uint64_t tuning_range_freq_start = + (uint64_t)strtold(tuning_range_raw[0].c_str(), NULL); + if (!tuning_range_freq_start) { + throw std::invalid_argument("tuning range min cannot be 0"); + } + uint64_t tuning_range_freq_end = + (uint64_t)strtold(tuning_range_raw[1].c_str(), NULL); + if (!tuning_range_freq_end) { + throw std::invalid_argument("tuning range max cannot be 0"); + } + if (tuning_range_freq_end <= tuning_range_freq_start) { + throw std::invalid_argument( + "invalid tuning_range (max must be greater than min)"); + } + if (i) { + if (tuning_ranges_.back().freq_end >= tuning_range_freq_start) { + throw std::invalid_argument("tuning_ranges must be sorted - cannot " + "have overlapping tuning ranges"); + } + } + freq_start_ = std::min(freq_start_, tuning_range_freq_start); + freq_end_ = std::max(freq_end_, tuning_range_freq_end); + add_range_(tuning_range_freq_start, tuning_range_freq_end); + } + } + tune_freq_ = tuning_ranges_[0].freq_start; +} + +void retuner_impl::next_retune_(double host_now) { + ++total_tune_count_; + ++pending_retune_; + last_tuning_range_ = tuning_range_; + size_t range_steps = tuning_ranges_[tuning_range_].steps; + if (range_steps == 1) { + last_sweep_start_ = host_now; + return; + } + tune_freq_ = std::min(tune_freq_ + tune_step_hz_, + tuning_ranges_[tuning_range_].freq_end); + ++tuning_range_step_; + if (last_sweep_start_ == 0) { + last_sweep_start_ = host_now; + } else { + if (tuning_range_step_ == range_steps) { + tuning_range_step_ = 0; + tuning_range_ = (tuning_range_ + 1) % tuning_ranges_.size(); + tune_freq_ = tuning_ranges_[tuning_range_].freq_start; + if (tuning_range_ == 0) { + last_sweep_start_ = host_now; + } + } + } +} + +} /* namespace iqtlabs */ +} /* namespace gr */ diff --git a/lib/retuner_impl.h b/lib/retuner_impl.h new file mode 100644 index 00000000..b05e1a67 --- /dev/null +++ b/lib/retuner_impl.h @@ -0,0 +1,248 @@ +/* -*- c++ -*- */ +/* Apache License + * Version 2.0, January 2004 + * http://www.apache.org/licenses/ + * + * TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + * + * 1. Definitions. + * + * "License" shall mean the terms and conditions for use, reproduction, + * and distribution as defined by Sections 1 through 9 of this document. + * + * "Licensor" shall mean the copyright owner or entity authorized by + * the copyright owner that is granting the License. + * + * "Legal Entity" shall mean the union of the acting entity and all + * other entities that control, are controlled by, or are under common + * control with that entity. For the purposes of this definition, + * "control" means (i) the power, direct or indirect, to cause the + * direction or management of such entity, whether by contract or + * otherwise, or (ii) ownership of fifty percent (50%) or more of the + * outstanding shares, or (iii) beneficial ownership of such entity. + * + * "You" (or "Your") shall mean an individual or Legal Entity + * exercising permissions granted by this License. + * + * "Source" form shall mean the preferred form for making modifications, + * including but not limited to software source code, documentation + * source, and configuration files. + * + * "Object" form shall mean any form resulting from mechanical + * transformation or translation of a Source form, including but + * not limited to compiled object code, generated documentation, + * and conversions to other media types. + * + * "Work" shall mean the work of authorship, whether in Source or + * Object form, made available under the License, as indicated by a + * copyright notice that is included in or attached to the work + * (an example is provided in the Appendix below). + * + * "Derivative Works" shall mean any work, whether in Source or Object + * form, that is based on (or derived from) the Work and for which the + * editorial revisions, annotations, elaborations, or other modifications + * represent, as a whole, an original work of authorship. For the purposes + * of this License, Derivative Works shall not include works that remain + * separable from, or merely link (or bind by name) to the interfaces of, + * the Work and Derivative Works thereof. + * + * "Contribution" shall mean any work of authorship, including + * the original version of the Work and any modifications or additions + * to that Work or Derivative Works thereof, that is intentionally + * submitted to Licensor for inclusion in the Work by the copyright owner + * or by an individual or Legal Entity authorized to submit on behalf of + * the copyright owner. For the purposes of this definition, "submitted" + * means any form of electronic, verbal, or written communication sent + * to the Licensor or its representatives, including but not limited to + * communication on electronic mailing lists, source code control systems, + * and issue tracking systems that are managed by, or on behalf of, the + * Licensor for the purpose of discussing and improving the Work, but + * excluding communication that is conspicuously marked or otherwise + * designated in writing by the copyright owner as "Not a Contribution." + * + * "Contributor" shall mean Licensor and any individual or Legal Entity + * on behalf of whom a Contribution has been received by Licensor and + * subsequently incorporated within the Work. + * + * 2. Grant of Copyright License. Subject to the terms and conditions of + * this License, each Contributor hereby grants to You a perpetual, + * worldwide, non-exclusive, no-charge, royalty-free, irrevocable + * copyright license to reproduce, prepare Derivative Works of, + * publicly display, publicly perform, sublicense, and distribute the + * Work and such Derivative Works in Source or Object form. + * + * 3. Grant of Patent License. Subject to the terms and conditions of + * this License, each Contributor hereby grants to You a perpetual, + * worldwide, non-exclusive, no-charge, royalty-free, irrevocable + * (except as stated in this section) patent license to make, have made, + * use, offer to sell, sell, import, and otherwise transfer the Work, + * where such license applies only to those patent claims licensable + * by such Contributor that are necessarily infringed by their + * Contribution(s) alone or by combination of their Contribution(s) + * with the Work to which such Contribution(s) was submitted. If You + * institute patent litigation against any entity (including a + * cross-claim or counterclaim in a lawsuit) alleging that the Work + * or a Contribution incorporated within the Work constitutes direct + * or contributory patent infringement, then any patent licenses + * granted to You under this License for that Work shall terminate + * as of the date such litigation is filed. + * + * 4. Redistribution. You may reproduce and distribute copies of the + * Work or Derivative Works thereof in any medium, with or without + * modifications, and in Source or Object form, provided that You + * meet the following conditions: + * + * (a) You must give any other recipients of the Work or + * Derivative Works a copy of this License; and + * + * (b) You must cause any modified files to carry prominent notices + * stating that You changed the files; and + * + * (c) You must retain, in the Source form of any Derivative Works + * that You distribute, all copyright, patent, trademark, and + * attribution notices from the Source form of the Work, + * excluding those notices that do not pertain to any part of + * the Derivative Works; and + * + * (d) If the Work includes a "NOTICE" text file as part of its + * distribution, then any Derivative Works that You distribute must + * include a readable copy of the attribution notices contained + * within such NOTICE file, excluding those notices that do not + * pertain to any part of the Derivative Works, in at least one + * of the following places: within a NOTICE text file distributed + * as part of the Derivative Works; within the Source form or + * documentation, if provided along with the Derivative Works; or, + * within a display generated by the Derivative Works, if and + * wherever such third-party notices normally appear. The contents + * of the NOTICE file are for informational purposes only and + * do not modify the License. You may add Your own attribution + * notices within Derivative Works that You distribute, alongside + * or as an addendum to the NOTICE text from the Work, provided + * that such additional attribution notices cannot be construed + * as modifying the License. + * + * You may add Your own copyright statement to Your modifications and + * may provide additional or different license terms and conditions + * for use, reproduction, or distribution of Your modifications, or + * for any such Derivative Works as a whole, provided Your use, + * reproduction, and distribution of the Work otherwise complies with + * the conditions stated in this License. + * + * 5. Submission of Contributions. Unless You explicitly state otherwise, + * any Contribution intentionally submitted for inclusion in the Work + * by You to the Licensor shall be under the terms and conditions of + * this License, without any additional terms or conditions. + * Notwithstanding the above, nothing herein shall supersede or modify + * the terms of any separate license agreement you may have executed + * with Licensor regarding such Contributions. + * + * 6. Trademarks. This License does not grant permission to use the trade + * names, trademarks, service marks, or product names of the Licensor, + * except as required for reasonable and customary use in describing the + * origin of the Work and reproducing the content of the NOTICE file. + * + * 7. Disclaimer of Warranty. Unless required by applicable law or + * agreed to in writing, Licensor provides the Work (and each + * Contributor provides its Contributions) on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied, including, without limitation, any warranties or conditions + * of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + * PARTICULAR PURPOSE. You are solely responsible for determining the + * appropriateness of using or redistributing the Work and assume any + * risks associated with Your exercise of permissions under this License. + * + * 8. Limitation of Liability. In no event and under no legal theory, + * whether in tort (including negligence), contract, or otherwise, + * unless required by applicable law (such as deliberate and grossly + * negligent acts) or agreed to in writing, shall any Contributor be + * liable to You for damages, including any direct, indirect, special, + * incidental, or consequential damages of any character arising as a + * result of this License or out of the use or inability to use the + * Work (including but not limited to damages for loss of goodwill, + * work stoppage, computer failure or malfunction, or any and all + * other commercial damages or losses), even if such Contributor + * has been advised of the possibility of such damages. + * + * 9. Accepting Warranty or Additional Liability. While redistributing + * the Work or Derivative Works thereof, You may choose to offer, + * and charge a fee for, acceptance of support, warranty, indemnity, + * or other liability obligations and/or rights consistent with this + * License. However, in accepting such obligations, You may act only + * on Your own behalf and on Your sole responsibility, not on behalf + * of any other Contributor, and only if You agree to indemnify, + * defend, and hold each Contributor harmless for any liability + * incurred by, or claims asserted against, such Contributor by reason + * of your accepting any such warranty or additional liability. + * + * END OF TERMS AND CONDITIONS + * + * APPENDIX: How to apply the Apache License to your work. + * + * To apply the Apache License to your work, attach the following + * boilerplate notice, with the fields enclosed by brackets "[]" + * replaced with your own identifying information. (Don't include + * the brackets!) The text should be enclosed in the appropriate + * comment syntax for the file format. We also recommend that a + * file or class name and description of purpose be included on the + * same "printed page" as the copyright notice for easier + * identification within third-party archives. + * + * Copyright [yyyy] [name of copyright owner] + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include + +namespace gr { +namespace iqtlabs { + +typedef struct { + uint64_t freq_start; + uint64_t freq_end; + size_t steps; +} tuning_range_t; + +class retuner_impl { +public: + retuner_impl(uint64_t freq_start, uint64_t freq_end, uint64_t tune_step_hz, + uint64_t tune_step_fft, uint64_t skip_tune_step_fft, + const std::string &tuning_ranges); + void add_range_(uint64_t freq_start, uint64_t freq_end); + bool need_retune_(size_t n); + void parse_tuning_ranges_(const std::string &tuning_ranges); + void next_retune_(double host_now); + uint64_t freq_start_; + uint64_t freq_end_; + uint64_t tune_step_hz_; + uint64_t tune_step_fft_; + uint64_t skip_tune_step_fft_; + + uint64_t skip_fft_count_; + uint64_t tune_freq_; + uint64_t last_rx_freq_; + double last_rx_time_; + double last_sweep_start_; + size_t tuning_range_; + size_t last_tuning_range_; + size_t tuning_range_step_; + size_t fft_count_; + size_t pending_retune_; + size_t total_tune_count_; + std::vector tuning_ranges_; +}; +} /* namespace iqtlabs */ +} /* namespace gr */ diff --git a/python/iqtlabs/bindings/CMakeLists.txt b/python/iqtlabs/bindings/CMakeLists.txt index 82079ab7..0c851d90 100644 --- a/python/iqtlabs/bindings/CMakeLists.txt +++ b/python/iqtlabs/bindings/CMakeLists.txt @@ -37,7 +37,7 @@ list(APPEND iqtlabs_python_files image_inference_python.cc vector_to_json_python.cc vector_roll_python.cc - python_bindings.cc) + retune_pre_fft_python.cc python_bindings.cc) GR_PYBIND_MAKE_OOT(iqtlabs ../../.. diff --git a/python/iqtlabs/bindings/docstrings/retune_pre_fft_pydoc_template.h b/python/iqtlabs/bindings/docstrings/retune_pre_fft_pydoc_template.h new file mode 100644 index 00000000..d2a702cb --- /dev/null +++ b/python/iqtlabs/bindings/docstrings/retune_pre_fft_pydoc_template.h @@ -0,0 +1,24 @@ +/* + * 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, iqtlabs, __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_iqtlabs_retune_pre_fft = R"doc()doc"; + + +static const char* __doc_gr_iqtlabs_retune_pre_fft_retune_pre_fft = R"doc()doc"; + + +static const char* __doc_gr_iqtlabs_retune_pre_fft_make = R"doc()doc"; diff --git a/python/iqtlabs/bindings/failed_conversions.txt b/python/iqtlabs/bindings/failed_conversions.txt deleted file mode 100644 index 8bebf39f..00000000 --- a/python/iqtlabs/bindings/failed_conversions.txt +++ /dev/null @@ -1 +0,0 @@ -./include/gnuradio/iqtlabs/vector_roll.hError occurred while running CASTXML xml file does not exist diff --git a/python/iqtlabs/bindings/python_bindings.cc b/python/iqtlabs/bindings/python_bindings.cc index 59675785..9cc665a2 100644 --- a/python/iqtlabs/bindings/python_bindings.cc +++ b/python/iqtlabs/bindings/python_bindings.cc @@ -28,6 +28,7 @@ namespace py = pybind11; void bind_image_inference(py::module& m); void bind_vector_to_json(py::module& m); void bind_vector_roll(py::module& m); + void bind_retune_pre_fft(py::module& m); // ) END BINDING_FUNCTION_PROTOTYPES @@ -66,5 +67,6 @@ PYBIND11_MODULE(iqtlabs_python, m) bind_image_inference(m); bind_vector_to_json(m); bind_vector_roll(m); + bind_retune_pre_fft(m); // ) END BINDING_FUNCTION_CALLS -} +} \ No newline at end of file diff --git a/python/iqtlabs/bindings/retune_fft_python.cc b/python/iqtlabs/bindings/retune_fft_python.cc index 3ada2f60..d15f46f2 100644 --- a/python/iqtlabs/bindings/retune_fft_python.cc +++ b/python/iqtlabs/bindings/retune_fft_python.cc @@ -14,7 +14,7 @@ /* BINDTOOL_GEN_AUTOMATIC(0) */ /* BINDTOOL_USE_PYGCCXML(0) */ /* BINDTOOL_HEADER_FILE(retune_fft.h) */ -/* BINDTOOL_HEADER_FILE_HASH(d77add23a80b141dc6221b222f6af5d7) */ +/* BINDTOOL_HEADER_FILE_HASH(291a634c39f0e6860211913645932d56) */ /***********************************************************************************/ #include @@ -54,6 +54,7 @@ void bind_retune_fft(py::module& m) py::arg("tuning_ranges"), py::arg("description"), py::arg("rotate_secs"), + py::arg("pre_fft"), D(retune_fft, make)) diff --git a/python/iqtlabs/bindings/retune_pre_fft_python.cc b/python/iqtlabs/bindings/retune_pre_fft_python.cc new file mode 100644 index 00000000..2c455099 --- /dev/null +++ b/python/iqtlabs/bindings/retune_pre_fft_python.cc @@ -0,0 +1,53 @@ +/* + * 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(retune_pre_fft.h) */ +/* BINDTOOL_HEADER_FILE_HASH(a9b4051c99f17cef5206780055ededed) */ +/***********************************************************************************/ + +#include +#include +#include + +namespace py = pybind11; + +#include +// pydoc.h is automatically generated in the build directory +#include + +void bind_retune_pre_fft(py::module& m) +{ + + using retune_pre_fft = ::gr::iqtlabs::retune_pre_fft; + + + py::class_>( + m, "retune_pre_fft", D(retune_pre_fft)) + + .def(py::init(&retune_pre_fft::make), + py::arg("nfft"), + py::arg("fft_batch_size"), + py::arg("tag"), + py::arg("freq_start"), + py::arg("freq_end"), + py::arg("tune_step_hz"), + py::arg("tune_step_fft"), + py::arg("skip_tune_step_fft"), + py::arg("tuning_ranges"), + D(retune_pre_fft, make)) + + + ; +} diff --git a/python/iqtlabs/qa_retune_fft.py b/python/iqtlabs/qa_retune_fft.py index 77aabe21..e83eb2d7 100755 --- a/python/iqtlabs/qa_retune_fft.py +++ b/python/iqtlabs/qa_retune_fft.py @@ -220,13 +220,23 @@ from gnuradio.fft import window try: - from gnuradio.iqtlabs import retune_fft, tuneable_test_source, vector_roll + from gnuradio.iqtlabs import ( + retune_fft, + retune_pre_fft, + tuneable_test_source, + vector_roll, + ) except ImportError: import sys dirname, filename = os.path.split(os.path.abspath(__file__)) sys.path.append(os.path.join(dirname, "bindings")) - from gnuradio.iqtlabs import retune_fft, tuneable_test_source + from gnuradio.iqtlabs import ( + retune_fft, + retune_pre_fft, + tuneable_test_source, + vector_roll, + ) class pdu_decoder(gr.sync_block): @@ -259,7 +269,10 @@ def __init__(self): def retune_fft(self, fft_roll): points = int(2048) - samp_rate = points * points + samp_rate = int(points * points) + tune_step_hz = samp_rate + tune_step_fft = int(64) + skip_tune_step_fft = int(2) freq_start = int(1e9 / samp_rate) * samp_rate freq_end = int(1.1e9 / samp_rate) * samp_rate freq_mid = ((freq_end - freq_start) / 2) + freq_start @@ -271,16 +284,29 @@ def retune_fft(self, fft_roll): with tempfile.TemporaryDirectory() as tmpdir: test_file = os.path.join(tmpdir, "samples.csv") iqtlabs_tuneable_test_source_0 = tuneable_test_source(freq_end) + + iqtlabs_retune_pre_fft_0 = retune_pre_fft( + points, + 1, # fft_batch_size + "rx_freq", + int(freq_start), + int(freq_end), + tune_step_hz, + tune_step_fft, + skip_tune_step_fft, + tuning_ranges, + ) + iqtlabs_retune_fft_0 = retune_fft( "rx_freq", points, points, - int(samp_rate), + samp_rate, int(freq_start), int(freq_end), - int(samp_rate), - 64, - 2, + tune_step_hz, + tune_step_fft, + skip_tune_step_fft, fft_min, 1e9, tmpdir, @@ -289,6 +315,7 @@ def retune_fft(self, fft_roll): tuning_ranges, "a text description", 3600, + True, ) pdu_decoder_0 = pdu_decoder() fft_vxx_0 = fft.fft_vcc( @@ -297,9 +324,6 @@ def retune_fft(self, fft_roll): blocks_throttle_0 = blocks.throttle( gr.sizeof_gr_complex * 1, samp_rate, True ) - blocks_stream_to_vector_0 = blocks.stream_to_vector( - gr.sizeof_gr_complex * 1, points - ) blocks_file_sink_0 = blocks.file_sink(gr.sizeof_char * 1, test_file, False) blocks_file_sink_0.set_unbuffered(False) blocks_complex_to_mag_0 = blocks.complex_to_mag(points) @@ -308,15 +332,15 @@ def retune_fft(self, fft_roll): vr2 = vector_roll(points) self.tb.msg_connect( - (iqtlabs_retune_fft_0, "tune"), (iqtlabs_tuneable_test_source_0, "cmd") + (iqtlabs_retune_pre_fft_0, "tune"), + (iqtlabs_tuneable_test_source_0, "cmd"), ) self.tb.msg_connect( - (iqtlabs_retune_fft_0, "json_output"), (pdu_decoder_0, "pdu") + (iqtlabs_retune_pre_fft_0, "tune"), (iqtlabs_retune_fft_0, "cmd") ) + self.tb.msg_connect((iqtlabs_retune_fft_0, "json"), (pdu_decoder_0, "pdu")) self.tb.connect((blocks_complex_to_mag_0, 0), (blocks_nlog10_ff_0, 0)) self.tb.connect((blocks_nlog10_ff_0, 0), (iqtlabs_retune_fft_0, 0)) - self.tb.connect((blocks_stream_to_vector_0, 0), (fft_vxx_0, 0)) - self.tb.connect((blocks_throttle_0, 0), (blocks_stream_to_vector_0, 0)) if fft_roll: # double roll, is a no-op self.tb.connect((fft_vxx_0, 0), (vr1, 0)) @@ -325,6 +349,8 @@ def retune_fft(self, fft_roll): else: self.tb.connect((fft_vxx_0, 0), (blocks_complex_to_mag_0, 0)) self.tb.connect((iqtlabs_retune_fft_0, 0), (blocks_file_sink_0, 0)) + self.tb.connect((iqtlabs_retune_pre_fft_0, 0), (fft_vxx_0, 0)) + self.tb.connect((blocks_throttle_0, 0), (iqtlabs_retune_pre_fft_0, 0)) self.tb.connect((iqtlabs_tuneable_test_source_0, 0), (blocks_throttle_0, 0)) self.tb.start() @@ -363,8 +389,8 @@ def retune_fft(self, fft_roll): ts = record["ts"] self.assertGreater(ts, last_ts) last_ts = ts - config = record["config"] self.assertGreaterEqual(ts, record["sweep_start"]) + config = record["config"] self.assertEqual("a text description", config["description"]), tuning_range_freq_start = config["tuning_range_freq_start"] tuning_range_freq_end = config["tuning_range_freq_end"] @@ -473,7 +499,7 @@ def retune_fft(self, fft_roll): class qa_retune_fft_no_roll(gr_unittest.TestCase, qa_retune_fft_base): def setUp(self): - self.tb = gr.top_block() + self.tb = gr.top_block(catch_exceptions=False) def tearDown(self): self.tb = None @@ -484,7 +510,7 @@ def test_retune_fft_no_roll(self): class qa_retune_fft_roll(gr_unittest.TestCase, qa_retune_fft_base): def setUp(self): - self.tb = gr.top_block() + self.tb = gr.top_block(catch_exceptions=False) def tearDown(self): self.tb = None