diff options
19 files changed, 157 insertions, 96 deletions
diff --git a/gr-blocks/grc/blocks_complex_to_interleaved_char.block.yml b/gr-blocks/grc/blocks_complex_to_interleaved_char.block.yml index 78a1da6e8b..84b85579a2 100644 --- a/gr-blocks/grc/blocks_complex_to_interleaved_char.block.yml +++ b/gr-blocks/grc/blocks_complex_to_interleaved_char.block.yml @@ -3,6 +3,10 @@ label: Complex To IChar flags: [ python, cpp ] parameters: +- id: scale_factor + label: Scale Factor + dtype: float + default: '1.0' - id: vector_output label: Vector Output dtype: enum @@ -23,7 +27,7 @@ outputs: templates: imports: from gnuradio import blocks - make: blocks.complex_to_interleaved_char(${vector_output}) + make: blocks.complex_to_interleaved_char(${vector_output}, ${scale_factor}) cpp_templates: includes: ['#include <gnuradio/blocks/complex_to_interleaved_char.h>'] @@ -33,4 +37,16 @@ cpp_templates: 'True': 'true' 'False': 'false' +documentation: |- + This block converts a complex sample to interleaved IQ bytes. + The default scale factor is 1.0 for backward compatibility, however if + the outputs should be signed voltage style bytes (-127 to 127) the scale factor + should be set to 127.0 (SCHAR_MAX). + + Also note that this block can inherently cause a loss of precision as it + maps the scaled inputs to integer outputs using an lrintf function. So + if you overlay a complex-to-ichar into a ichar-to-complex and overlay it + on the original signal, you can notice variation due to the integer + rounding. + file_format: 1 diff --git a/gr-blocks/grc/blocks_complex_to_interleaved_short.block.yml b/gr-blocks/grc/blocks_complex_to_interleaved_short.block.yml index bd4a588aca..89739e8245 100644 --- a/gr-blocks/grc/blocks_complex_to_interleaved_short.block.yml +++ b/gr-blocks/grc/blocks_complex_to_interleaved_short.block.yml @@ -3,6 +3,10 @@ label: Complex To IShort flags: [ python, cpp ] parameters: +- id: scale_factor + label: Scale Factor + dtype: float + default: '1.0' - id: vector_output label: Vector Output dtype: enum @@ -23,14 +27,32 @@ outputs: templates: imports: from gnuradio import blocks - make: blocks.complex_to_interleaved_short(${vector_output}) + make: blocks.complex_to_interleaved_short(${vector_output},${scale_factor}) + callbacks: + - set_scale_factor(${scale_factor}) cpp_templates: includes: ['#include <gnuradio/blocks/complex_to_interleaved_short.h>'] declarations: 'blocks::complex_to_interleaved_short::sptr ${id};' make: 'this->${id} = blocks::complex_to_interleaved_short::make(${vector_output});' + callbacks: + - set_scale_factor(${scale_factor}) translations: 'True': 'true' 'False': 'false' +documentation: |- + This block converts a complex sample to interleaved IQ 16-bit values. + The default scale factor is 1.0 for backward compatibility, however if + the outputs should be signed voltage style, some care needs to be taken + with the scale factor. For a 12-bit output (-2047 to 2047), the + scale factor should be 2047.0. For a full 16-bit output, the + scale factor should be 32767.0. + + Also note that this block can inherently cause a loss of precision as it + maps the scaled inputs to integer outputs using an lrintf function. So + if you overlay a complex-to-ishort into a ishort-to-complex and overlay it + on the original signal, you can notice variation due to the integer + rounding. + file_format: 1 diff --git a/gr-blocks/grc/blocks_interleaved_char_to_complex.block.yml b/gr-blocks/grc/blocks_interleaved_char_to_complex.block.yml index 39f747a981..46d01b79c3 100644 --- a/gr-blocks/grc/blocks_interleaved_char_to_complex.block.yml +++ b/gr-blocks/grc/blocks_interleaved_char_to_complex.block.yml @@ -3,6 +3,10 @@ label: IChar To Complex flags: [ python, cpp ] parameters: +- id: scale_factor + label: Scale Factor + dtype: float + default: '1.0' - id: vector_input label: Vector Input dtype: enum @@ -23,14 +27,24 @@ outputs: templates: imports: from gnuradio import blocks - make: blocks.interleaved_char_to_complex(${vector_input}) + make: blocks.interleaved_char_to_complex(${vector_input},${scale_factor}) + callbacks: + - set_scale_factor(${scale_factor}) cpp_templates: includes: ['#include <gnuradio/blocks/interleaved_char_to_complex.h>'] declarations: 'blocks::interleaved_char_to_complex::sptr ${id};' make: 'this->${id} = blocks::interleaved_char_to_complex::make(${vector_input});' + callbacks: + - set_scale_factor(${scale_factor}) translations: 'True': 'true' 'False': 'false' +documentation: |- + This block converts interleaved IQ bytes to a float complex data type. + The default scale factor is 1.0 for backward compatibility, however if + the inputs are signed voltage style bytes (-127 to 127) the scale factor + should be set to 127.0 (SCHAR_MAX). + file_format: 1 diff --git a/gr-blocks/grc/blocks_interleaved_short_to_complex.block.yml b/gr-blocks/grc/blocks_interleaved_short_to_complex.block.yml index f96960ad56..5904ed76b1 100644 --- a/gr-blocks/grc/blocks_interleaved_short_to_complex.block.yml +++ b/gr-blocks/grc/blocks_interleaved_short_to_complex.block.yml @@ -3,6 +3,10 @@ label: IShort To Complex flags: [ python, cpp ] parameters: +- id: scale_factor + label: Scale Factor + dtype: float + default: '1.0' - id: vector_input label: Vector Input dtype: enum @@ -30,9 +34,10 @@ outputs: templates: imports: from gnuradio import blocks - make: blocks.interleaved_short_to_complex(${vector_input}, ${swap}) + make: blocks.interleaved_short_to_complex(${vector_input}, ${swap},${scale_factor}) callbacks: - set_swap(${swap}) + - set_scale_factor(${scale_factor}) cpp_templates: includes: ['#include <gnuradio/blocks/interleaved_short_to_complex.h>'] @@ -40,8 +45,18 @@ cpp_templates: make: 'this->${id} = blocks::interleaved_short_to_complex::make(${vector_input}, ${swap});' callbacks: - set_swap(${swap}) + - set_scale_factor(${scale_factor}) translations: 'True': 'true' 'False': 'false' +documentation: |- + This block converts interleaved 12/16-bit IQ samples to a float complex data + type. The default scale factor is 1.0 for backward compatibility, however if + the inputs are signed voltage style, some attention needs to be + paid to the scale factor to get the correct scaling. If the input is + 12-bit represented in a 16-bit number (-2047 to 2047), the scale factor + should be 2047.0. If the input is a full 16-bit sample (-32767 to 32767) + the scale factor should be set to 32767.0 (SHRT_MAX). + file_format: 1 diff --git a/gr-blocks/include/gnuradio/blocks/complex_to_interleaved_char.h b/gr-blocks/include/gnuradio/blocks/complex_to_interleaved_char.h index ce2270ff93..38f6a4042b 100644 --- a/gr-blocks/include/gnuradio/blocks/complex_to_interleaved_char.h +++ b/gr-blocks/include/gnuradio/blocks/complex_to_interleaved_char.h @@ -39,7 +39,9 @@ public: /*! * Build a complex to interleaved chars block. */ - static sptr make(bool vector = false); + static sptr make(bool vector = false, float scale_factor = 1.0f); + + virtual void set_scale_factor(float new_value) = 0; }; } /* namespace blocks */ diff --git a/gr-blocks/include/gnuradio/blocks/complex_to_interleaved_short.h b/gr-blocks/include/gnuradio/blocks/complex_to_interleaved_short.h index def7b1a25a..81c49e3357 100644 --- a/gr-blocks/include/gnuradio/blocks/complex_to_interleaved_short.h +++ b/gr-blocks/include/gnuradio/blocks/complex_to_interleaved_short.h @@ -39,7 +39,9 @@ public: /*! * Build a complex to interleaved shorts block. */ - static sptr make(bool vector = false); + static sptr make(bool vector = false, float scale_factor = 1.0f); + + virtual void set_scale_factor(float new_value) = 0; }; } /* namespace blocks */ diff --git a/gr-blocks/include/gnuradio/blocks/interleaved_char_to_complex.h b/gr-blocks/include/gnuradio/blocks/interleaved_char_to_complex.h index ef93e00063..6d6c4fce52 100644 --- a/gr-blocks/include/gnuradio/blocks/interleaved_char_to_complex.h +++ b/gr-blocks/include/gnuradio/blocks/interleaved_char_to_complex.h @@ -30,7 +30,9 @@ public: /*! * Build an interleaved char to complex block. */ - static sptr make(bool vector_input = false); + static sptr make(bool vector_input = false, float scale_factor = 1.0f); + + virtual void set_scale_factor(float new_value) = 0; }; } /* namespace blocks */ diff --git a/gr-blocks/include/gnuradio/blocks/interleaved_short_to_complex.h b/gr-blocks/include/gnuradio/blocks/interleaved_short_to_complex.h index ad49bb4f7b..8ddfaa6c1a 100644 --- a/gr-blocks/include/gnuradio/blocks/interleaved_short_to_complex.h +++ b/gr-blocks/include/gnuradio/blocks/interleaved_short_to_complex.h @@ -30,9 +30,12 @@ public: /*! * Build an interleaved short to complex block. */ - static sptr make(bool vector_input = false, bool swap = false); + static sptr + make(bool vector_input = false, bool swap = false, float scale_factor = 1.0f); virtual void set_swap(bool swap) = 0; + + virtual void set_scale_factor(float new_value) = 0; }; } /* namespace blocks */ diff --git a/gr-blocks/lib/CMakeLists.txt b/gr-blocks/lib/CMakeLists.txt index 233a4e068d..2f27e22f5e 100644 --- a/gr-blocks/lib/CMakeLists.txt +++ b/gr-blocks/lib/CMakeLists.txt @@ -98,7 +98,6 @@ add_library(gnuradio-blocks head_impl.cc int_to_float_impl.cc interleave_impl.cc - interleaved_short_array_to_complex.cc interleaved_short_to_complex_impl.cc interleaved_char_to_complex_impl.cc keep_m_in_n_impl.cc diff --git a/gr-blocks/lib/complex_to_interleaved_char_impl.cc b/gr-blocks/lib/complex_to_interleaved_char_impl.cc index d875ce9772..a60a3d9675 100644 --- a/gr-blocks/lib/complex_to_interleaved_char_impl.cc +++ b/gr-blocks/lib/complex_to_interleaved_char_impl.cc @@ -14,21 +14,26 @@ #include "complex_to_interleaved_char_impl.h" #include <gnuradio/io_signature.h> +#include <volk/volk.h> namespace gr { namespace blocks { -complex_to_interleaved_char::sptr complex_to_interleaved_char::make(bool vector) +complex_to_interleaved_char::sptr complex_to_interleaved_char::make(bool vector, + float scale_factor) { - return gnuradio::get_initial_sptr(new complex_to_interleaved_char_impl(vector)); + return gnuradio::get_initial_sptr( + new complex_to_interleaved_char_impl(vector, scale_factor)); } -complex_to_interleaved_char_impl::complex_to_interleaved_char_impl(bool vector) +complex_to_interleaved_char_impl::complex_to_interleaved_char_impl(bool vector, + float scale_factor) : sync_interpolator( "complex_to_interleaved_char", io_signature::make(1, 1, sizeof(gr_complex)), io_signature::make(1, 1, vector ? 2 * sizeof(char) : sizeof(char)), vector ? 1 : 2), + d_scalar(scale_factor), d_vector(vector) { } @@ -37,14 +42,11 @@ int complex_to_interleaved_char_impl::work(int noutput_items, gr_vector_const_void_star& input_items, gr_vector_void_star& output_items) { - const gr_complex* in = (const gr_complex*)input_items[0]; - char* out = (char*)output_items[0]; - - int npairs = (d_vector ? noutput_items : noutput_items / 2); - for (int i = 0; i < npairs; i++) { - *out++ = (char)lrintf(in[i].real()); // FIXME saturate? - *out++ = (char)lrintf(in[i].imag()); - } + const float* in = (const float*)input_items[0]; + int8_t* out = (int8_t*)output_items[0]; + + volk_32f_s32f_convert_8i( + out, in, d_scalar, d_vector ? noutput_items * 2 : noutput_items); return noutput_items; } diff --git a/gr-blocks/lib/complex_to_interleaved_char_impl.h b/gr-blocks/lib/complex_to_interleaved_char_impl.h index 3070d3fb9c..2e7e3c68bd 100644 --- a/gr-blocks/lib/complex_to_interleaved_char_impl.h +++ b/gr-blocks/lib/complex_to_interleaved_char_impl.h @@ -19,10 +19,13 @@ namespace blocks { class BLOCKS_API complex_to_interleaved_char_impl : public complex_to_interleaved_char { private: + float d_scalar; bool d_vector; public: - complex_to_interleaved_char_impl(bool vector); + complex_to_interleaved_char_impl(bool vector, float scale_factor); + + virtual void set_scale_factor(float new_value) { d_scalar = new_value; }; int work(int noutput_items, gr_vector_const_void_star& input_items, diff --git a/gr-blocks/lib/complex_to_interleaved_short_impl.cc b/gr-blocks/lib/complex_to_interleaved_short_impl.cc index 2e8e8d047d..6a20e0b59f 100644 --- a/gr-blocks/lib/complex_to_interleaved_short_impl.cc +++ b/gr-blocks/lib/complex_to_interleaved_short_impl.cc @@ -14,21 +14,26 @@ #include "complex_to_interleaved_short_impl.h" #include <gnuradio/io_signature.h> +#include <volk/volk.h> namespace gr { namespace blocks { -complex_to_interleaved_short::sptr complex_to_interleaved_short::make(bool vector) +complex_to_interleaved_short::sptr complex_to_interleaved_short::make(bool vector, + float scale_factor) { - return gnuradio::get_initial_sptr(new complex_to_interleaved_short_impl(vector)); + return gnuradio::get_initial_sptr( + new complex_to_interleaved_short_impl(vector, scale_factor)); } -complex_to_interleaved_short_impl::complex_to_interleaved_short_impl(bool vector) +complex_to_interleaved_short_impl::complex_to_interleaved_short_impl(bool vector, + float scale_factor) : sync_interpolator( "complex_to_interleaved_short", io_signature::make(1, 1, sizeof(gr_complex)), io_signature::make(1, 1, vector ? 2 * sizeof(short) : sizeof(short)), vector ? 1 : 2), + d_scalar(scale_factor), d_vector(vector) { } @@ -37,14 +42,11 @@ int complex_to_interleaved_short_impl::work(int noutput_items, gr_vector_const_void_star& input_items, gr_vector_void_star& output_items) { - const gr_complex* in = (const gr_complex*)input_items[0]; + const float* in = (const float*)input_items[0]; short* out = (short*)output_items[0]; - int npairs = (d_vector ? noutput_items : noutput_items / 2); - for (int i = 0; i < npairs; i++) { - *out++ = (short)lrintf(in[i].real()); // FIXME saturate? - *out++ = (short)lrintf(in[i].imag()); - } + volk_32f_s32f_convert_16i( + out, in, d_scalar, d_vector ? noutput_items * 2 : noutput_items); return noutput_items; } diff --git a/gr-blocks/lib/complex_to_interleaved_short_impl.h b/gr-blocks/lib/complex_to_interleaved_short_impl.h index abed74b3df..1b1b294438 100644 --- a/gr-blocks/lib/complex_to_interleaved_short_impl.h +++ b/gr-blocks/lib/complex_to_interleaved_short_impl.h @@ -19,10 +19,13 @@ namespace blocks { class BLOCKS_API complex_to_interleaved_short_impl : public complex_to_interleaved_short { private: + float d_scalar; bool d_vector; public: - complex_to_interleaved_short_impl(bool vector); + complex_to_interleaved_short_impl(bool vector, float scale_factor); + + virtual void set_scale_factor(float new_value) { d_scalar = new_value; }; int work(int noutput_items, gr_vector_const_void_star& input_items, diff --git a/gr-blocks/lib/interleaved_char_to_complex_impl.cc b/gr-blocks/lib/interleaved_char_to_complex_impl.cc index 31ed942485..1b1ace671f 100644 --- a/gr-blocks/lib/interleaved_char_to_complex_impl.cc +++ b/gr-blocks/lib/interleaved_char_to_complex_impl.cc @@ -19,16 +19,21 @@ namespace gr { namespace blocks { -interleaved_char_to_complex::sptr interleaved_char_to_complex::make(bool vector_input) +interleaved_char_to_complex::sptr interleaved_char_to_complex::make(bool vector_input, + float scale_factor) { - return gnuradio::get_initial_sptr(new interleaved_char_to_complex_impl(vector_input)); + return gnuradio::get_initial_sptr( + new interleaved_char_to_complex_impl(vector_input, scale_factor)); } -interleaved_char_to_complex_impl::interleaved_char_to_complex_impl(bool vector_input) +interleaved_char_to_complex_impl::interleaved_char_to_complex_impl(bool vector_input, + float scale_factor) : sync_decimator("interleaved_char_to_complex", gr::io_signature::make(1, 1, (vector_input ? 2 : 1) * sizeof(char)), gr::io_signature::make(1, 1, sizeof(gr_complex)), - vector_input ? 1 : 2) + vector_input ? 1 : 2), + d_scalar(scale_factor), + d_vector(vector_input) { const int alignment_multiple = volk_get_alignment() / sizeof(gr_complex); set_alignment(std::max(1, alignment_multiple)); @@ -38,10 +43,11 @@ int interleaved_char_to_complex_impl::work(int noutput_items, gr_vector_const_void_star& input_items, gr_vector_void_star& output_items) { - const int8_t* in = (const int8_t*)input_items[0]; float* out = (float*)output_items[0]; + const int8_t* in = (const int8_t*)input_items[0]; - volk_8i_s32f_convert_32f_u(out, in, 1.0, 2 * noutput_items); + // This calculates in[] * 1.0 / d_scalar + volk_8i_s32f_convert_32f(out, in, d_scalar, 2 * noutput_items); return noutput_items; } diff --git a/gr-blocks/lib/interleaved_char_to_complex_impl.h b/gr-blocks/lib/interleaved_char_to_complex_impl.h index 85406d50a5..211c684943 100644 --- a/gr-blocks/lib/interleaved_char_to_complex_impl.h +++ b/gr-blocks/lib/interleaved_char_to_complex_impl.h @@ -19,8 +19,14 @@ namespace blocks { class BLOCKS_API interleaved_char_to_complex_impl : public interleaved_char_to_complex { private: + float d_scalar; + bool d_vector; + public: - interleaved_char_to_complex_impl(bool vector_input = false); + interleaved_char_to_complex_impl(bool vector_input = false, + float scale_factor = 1.0f); + + virtual void set_scale_factor(float new_value) { d_scalar = new_value; }; int work(int noutput_items, gr_vector_const_void_star& input_items, diff --git a/gr-blocks/lib/interleaved_short_array_to_complex.cc b/gr-blocks/lib/interleaved_short_array_to_complex.cc deleted file mode 100644 index 1033abdbdc..0000000000 --- a/gr-blocks/lib/interleaved_short_array_to_complex.cc +++ /dev/null @@ -1,23 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2002,2012 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "interleaved_short_array_to_complex.h" -#include <assert.h> -#include <volk/volk.h> - -void interleaved_short_array_to_complex(const short* in, gr_complex* out, int nsamples) -{ - assert(nsamples % 2 == 0); - volk_16i_s32f_convert_32f_u((float*)out, (const int16_t*)in, 1, nsamples); -} diff --git a/gr-blocks/lib/interleaved_short_array_to_complex.h b/gr-blocks/lib/interleaved_short_array_to_complex.h deleted file mode 100644 index 30aee57026..0000000000 --- a/gr-blocks/lib/interleaved_short_array_to_complex.h +++ /dev/null @@ -1,25 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2012 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - */ - -#ifndef INCLUDED_INTERLEAVED_SHORT_ARRAY_TO_COMPLEX_H -#define INCLUDED_INTERLEAVED_SHORT_ARRAY_TO_COMPLEX_H - -#include <gnuradio/blocks/api.h> -#include <gnuradio/gr_complex.h> - -/* - * convert array of interleaved shorts to complex. - * the shorts contains real, imaginary, real, imaginary... - * nsamples is the number of shorts; it must be even. - */ -BLOCKS_API void -interleaved_short_array_to_complex(const short* in, gr_complex* out, int nsamples); - -#endif /* INCLUDED_INTERLEAVED_SHORT_ARRAY_TO_COMPLEX_H */ diff --git a/gr-blocks/lib/interleaved_short_to_complex_impl.cc b/gr-blocks/lib/interleaved_short_to_complex_impl.cc index 654eb1573a..f32bf28fcb 100644 --- a/gr-blocks/lib/interleaved_short_to_complex_impl.cc +++ b/gr-blocks/lib/interleaved_short_to_complex_impl.cc @@ -12,28 +12,33 @@ #include "config.h" #endif -#include "interleaved_short_array_to_complex.h" #include "interleaved_short_to_complex_impl.h" #include <gnuradio/io_signature.h> +#include <volk/volk.h> namespace gr { namespace blocks { -interleaved_short_to_complex::sptr interleaved_short_to_complex::make(bool vector_input, - bool swap) +interleaved_short_to_complex::sptr +interleaved_short_to_complex::make(bool vector_input, bool swap, float scale_factor) { return gnuradio::get_initial_sptr( - new interleaved_short_to_complex_impl(vector_input, swap)); + new interleaved_short_to_complex_impl(vector_input, swap, scale_factor)); } interleaved_short_to_complex_impl::interleaved_short_to_complex_impl(bool vector_input, - bool swap) + bool swap, + float scale_factor) : sync_decimator("interleaved_short_to_complex", gr::io_signature::make(1, 1, (vector_input ? 2 : 1) * sizeof(short)), gr::io_signature::make(1, 1, sizeof(gr_complex)), vector_input ? 1 : 2), + d_scalar(scale_factor), + d_vector(vector_input), d_swap(swap) { + const int alignment_multiple = volk_get_alignment() / sizeof(gr_complex); + set_alignment(std::max(1, alignment_multiple)); } void interleaved_short_to_complex_impl::set_swap(bool swap) { d_swap = swap; } @@ -43,16 +48,17 @@ int interleaved_short_to_complex_impl::work(int noutput_items, gr_vector_void_star& output_items) { const short* in = (const short*)input_items[0]; - gr_complex* out = (gr_complex*)output_items[0]; + float* out = (float*)output_items[0]; - interleaved_short_array_to_complex(in, out, 2 * noutput_items); + // This calculates in[] * 1.0 / d_scalar + volk_16i_s32f_convert_32f(out, in, d_scalar, 2 * noutput_items); if (d_swap) { float* p = (float*)output_items[0]; for (int i = 0; i < noutput_items; ++i) { float f = p[2 * i + 1]; - p[2 * i + 1] = p[2 * i + 0]; - p[2 * i + 0] = f; + p[2 * i + 1] = p[2 * i]; + p[2 * i] = f; } } diff --git a/gr-blocks/lib/interleaved_short_to_complex_impl.h b/gr-blocks/lib/interleaved_short_to_complex_impl.h index ef616bfbf7..698ac8d7bf 100644 --- a/gr-blocks/lib/interleaved_short_to_complex_impl.h +++ b/gr-blocks/lib/interleaved_short_to_complex_impl.h @@ -19,13 +19,19 @@ namespace blocks { class BLOCKS_API interleaved_short_to_complex_impl : public interleaved_short_to_complex { private: + float d_scalar; + bool d_vector; bool d_swap; public: - interleaved_short_to_complex_impl(bool vector_input = false, bool swap = false); + interleaved_short_to_complex_impl(bool vector_input = false, + bool swap = false, + float scale_factor = 1.0f); void set_swap(bool swap); + virtual void set_scale_factor(float new_value) { d_scalar = new_value; }; + int work(int noutput_items, gr_vector_const_void_star& input_items, gr_vector_void_star& output_items); |