diff options
author | Eduardo Sánchez Muñoz <esm@eduardosm.net> | 2020-12-18 12:30:26 +0100 |
---|---|---|
committer | Marcus Müller <marcus@hostalia.de> | 2020-12-18 13:54:10 +0100 |
commit | 947800c52f2fcb2b149cfd2809148afcfdb8b79a (patch) | |
tree | ffc11b527f2f95606da621185a8e4c8c5d048ff7 /gr-digital | |
parent | 00fd051dff4a73081c40f4ccfc3b4ac8c62d74f1 (diff) |
Allow to choose whether to normalize constellation average magnitude, average power or to not normalize at all.
Signed-off-by: Eduardo Sánchez Muñoz <esm@eduardosm.net>
Diffstat (limited to 'gr-digital')
-rw-r--r-- | gr-digital/grc/digital_constellation.block.yml | 9 | ||||
-rw-r--r-- | gr-digital/include/gnuradio/digital/constellation.h | 42 | ||||
-rw-r--r-- | gr-digital/lib/constellation.cc | 60 | ||||
-rw-r--r-- | gr-digital/python/digital/bindings/constellation_python.cc | 17 |
4 files changed, 92 insertions, 36 deletions
diff --git a/gr-digital/grc/digital_constellation.block.yml b/gr-digital/grc/digital_constellation.block.yml index 7a1f4654c0..943b578d80 100644 --- a/gr-digital/grc/digital_constellation.block.yml +++ b/gr-digital/grc/digital_constellation.block.yml @@ -29,6 +29,13 @@ parameters: dtype: int default: '1' hide: ${ ( 'none' if str(type) == "calcdist" else 'all') } +- id: normalization + label: Normalization Type + dtype: int + default: digital.constellation.AMPLITUDE_NORMALIZATION + options: [digital.constellation.NO_NORMALIZATION, digital.constellation.POWER_NORMALIZATION, digital.constellation.AMPLITUDE_NORMALIZATION] + option_labels: [None, Power, Amplitude] + hide: ${ ( 'none' if str(type) == "calcdist" else 'all') } - id: precision label: Soft Decisions Precision dtype: int @@ -39,7 +46,7 @@ parameters: dtype: raw default: None hide: ${ ('part' if str(soft_dec_lut) == 'None' else 'none') } -value: ${ digital.constellation_calcdist(const_points, sym_map, rot_sym, dims) if (str(type) == "calcdist") else getattr(digital,'constellation_'+str(type))() } +value: ${ digital.constellation_calcdist(const_points, sym_map, rot_sym, dims, normalization) if (str(type) == "calcdist") else getattr(digital,'constellation_'+str(type))() } templates: diff --git a/gr-digital/include/gnuradio/digital/constellation.h b/gr-digital/include/gnuradio/digital/constellation.h index a8fffe111e..ebe37088b7 100644 --- a/gr-digital/include/gnuradio/digital/constellation.h +++ b/gr-digital/include/gnuradio/digital/constellation.h @@ -49,11 +49,17 @@ typedef std::shared_ptr<constellation> constellation_sptr; class DIGITAL_API constellation : public std::enable_shared_from_this<constellation> { public: + enum normalization_t { + NO_NORMALIZATION, + POWER_NORMALIZATION, + AMPLITUDE_NORMALIZATION, + }; + constellation(std::vector<gr_complex> constell, std::vector<int> pre_diff_code, unsigned int rotational_symmetry, unsigned int dimensionality, - bool normalize_points = true); + normalization_t normalization = AMPLITUDE_NORMALIZATION); constellation(); virtual ~constellation(); @@ -233,15 +239,17 @@ public: * \param pre_diff_code List of alphabet symbols (before applying any differential * coding) (order of list matches constell) * \param rotational_symmetry Number of rotations around unit circle that have the - * same representation. \param dimensionality Number of dimensions to the - * constellation. \param normalize_points Normalize constellation points to - * mean(abs(points))=1 (default is true) + * same representation. + * \param dimensionality Number of dimensions to the constellation. + * \param normalization Use AMPLITUDE_NORMALIZATION to normalize points to + * mean(abs(points))=1 (default), POWER_NORMALIZATION to normalize points + * to mean(abs(points)^2)=1 or NO_NORMALIZATION to keep the original amplitude. */ static sptr make(std::vector<gr_complex> constell, std::vector<int> pre_diff_code, unsigned int rotational_symmetry, unsigned int dimensionality, - bool normalize_points = true); + normalization_t normalization = AMPLITUDE_NORMALIZATION); unsigned int decision_maker(const gr_complex* sample) override; // void calc_metric(gr_complex *sample, float *metric, trellis_metric_type_t type); @@ -253,7 +261,7 @@ protected: std::vector<int> pre_diff_code, unsigned int rotational_symmetry, unsigned int dimensionality, - bool nomalize_points = true); + normalization_t normalization = AMPLITUDE_NORMALIZATION); }; @@ -286,7 +294,8 @@ public: std::vector<int> pre_diff_code, unsigned int rotational_symmetry, unsigned int dimensionality, - unsigned int n_sectors); + unsigned int n_sectors, + normalization_t normalization = AMPLITUDE_NORMALIZATION); ~constellation_sector() override; @@ -339,13 +348,15 @@ public: * \param width_imag_sectors width of each imag sector to calculate decision * boundaries. */ - static constellation_rect::sptr make(std::vector<gr_complex> constell, - std::vector<int> pre_diff_code, - unsigned int rotational_symmetry, - unsigned int real_sectors, - unsigned int imag_sectors, - float width_real_sectors, - float width_imag_sectors); + static constellation_rect::sptr + make(std::vector<gr_complex> constell, + std::vector<int> pre_diff_code, + unsigned int rotational_symmetry, + unsigned int real_sectors, + unsigned int imag_sectors, + float width_real_sectors, + float width_imag_sectors, + normalization_t normalization = AMPLITUDE_NORMALIZATION); ~constellation_rect() override; protected: @@ -355,7 +366,8 @@ protected: unsigned int real_sectors, unsigned int imag_sectors, float width_real_sectors, - float width_imag_sectors); + float width_imag_sectors, + normalization_t normalization = AMPLITUDE_NORMALIZATION); unsigned int get_sector(const gr_complex* sample) override; gr_complex calc_sector_center(unsigned int sector); diff --git a/gr-digital/lib/constellation.cc b/gr-digital/lib/constellation.cc index 0aff0aaecc..e9d3239503 100644 --- a/gr-digital/lib/constellation.cc +++ b/gr-digital/lib/constellation.cc @@ -32,7 +32,7 @@ constellation::constellation(std::vector<gr_complex> constell, std::vector<int> pre_diff_code, unsigned int rotational_symmetry, unsigned int dimensionality, - bool normalize_points) + normalization_t normalization) : d_constellation(constell), d_pre_diff_code(pre_diff_code), d_rotational_symmetry(rotational_symmetry), @@ -46,18 +46,39 @@ constellation::constellation(std::vector<gr_complex> constell, d_lut_scale(0) { unsigned int constsize = d_constellation.size(); - if (normalize_points) { + float summed_mag = 0; + switch (normalization) { + case NO_NORMALIZATION: + break; + + case POWER_NORMALIZATION: + // Scale constellation points so that average power is 1. + for (unsigned int i = 0; i < constsize; i++) { + gr_complex c = d_constellation[i]; + summed_mag += std::norm(c); + } + d_scalefactor = constsize / sqrt(summed_mag); + for (unsigned int i = 0; i < constsize; i++) { + d_constellation[i] = d_constellation[i] * d_scalefactor; + } + break; + + case AMPLITUDE_NORMALIZATION: // Scale constellation points so that average magnitude is 1. - float summed_mag = 0; for (unsigned int i = 0; i < constsize; i++) { gr_complex c = d_constellation[i]; - summed_mag += sqrt(c.real() * c.real() + c.imag() * c.imag()); + summed_mag += std::abs(c); } d_scalefactor = constsize / summed_mag; for (unsigned int i = 0; i < constsize; i++) { d_constellation[i] = d_constellation[i] * d_scalefactor; } + break; + + default: + throw std::runtime_error("Invalid constellation normalization type."); } + if (pre_diff_code.empty()) d_apply_pre_diff_code = false; else if (pre_diff_code.size() != constsize) @@ -370,19 +391,19 @@ constellation_calcdist::make(std::vector<gr_complex> constell, std::vector<int> pre_diff_code, unsigned int rotational_symmetry, unsigned int dimensionality, - bool normalize_points) + normalization_t normalization) { return constellation_calcdist::sptr(new constellation_calcdist( - constell, pre_diff_code, rotational_symmetry, dimensionality, normalize_points)); + constell, pre_diff_code, rotational_symmetry, dimensionality, normalization)); } constellation_calcdist::constellation_calcdist(std::vector<gr_complex> constell, std::vector<int> pre_diff_code, unsigned int rotational_symmetry, unsigned int dimensionality, - bool normalize_points) + normalization_t normalization) : constellation( - constell, pre_diff_code, rotational_symmetry, dimensionality, normalize_points) + constell, pre_diff_code, rotational_symmetry, dimensionality, normalization) { } @@ -401,8 +422,10 @@ constellation_sector::constellation_sector(std::vector<gr_complex> constell, std::vector<int> pre_diff_code, unsigned int rotational_symmetry, unsigned int dimensionality, - unsigned int n_sectors) - : constellation(constell, pre_diff_code, rotational_symmetry, dimensionality), + unsigned int n_sectors, + normalization_t normalization) + : constellation( + constell, pre_diff_code, rotational_symmetry, dimensionality, normalization), n_sectors(n_sectors) { } @@ -435,7 +458,8 @@ constellation_rect::sptr constellation_rect::make(std::vector<gr_complex> conste unsigned int real_sectors, unsigned int imag_sectors, float width_real_sectors, - float width_imag_sectors) + float width_imag_sectors, + normalization_t normalization) { return constellation_rect::sptr(new constellation_rect(constell, pre_diff_code, @@ -443,7 +467,8 @@ constellation_rect::sptr constellation_rect::make(std::vector<gr_complex> conste real_sectors, imag_sectors, width_real_sectors, - width_imag_sectors)); + width_imag_sectors, + normalization)); } constellation_rect::constellation_rect(std::vector<gr_complex> constell, @@ -452,9 +477,14 @@ constellation_rect::constellation_rect(std::vector<gr_complex> constell, unsigned int real_sectors, unsigned int imag_sectors, float width_real_sectors, - float width_imag_sectors) - : constellation_sector( - constell, pre_diff_code, rotational_symmetry, 1, real_sectors * imag_sectors), + float width_imag_sectors, + normalization_t normalization) + : constellation_sector(constell, + pre_diff_code, + rotational_symmetry, + 1, + real_sectors * imag_sectors, + normalization), n_real_sectors(real_sectors), n_imag_sectors(imag_sectors), d_width_real_sectors(width_real_sectors), diff --git a/gr-digital/python/digital/bindings/constellation_python.cc b/gr-digital/python/digital/bindings/constellation_python.cc index 77a252c42c..8944e666c9 100644 --- a/gr-digital/python/digital/bindings/constellation_python.cc +++ b/gr-digital/python/digital/bindings/constellation_python.cc @@ -14,7 +14,7 @@ /* BINDTOOL_GEN_AUTOMATIC(0) */ /* BINDTOOL_USE_PYGCCXML(0) */ /* BINDTOOL_HEADER_FILE(constellation.h) */ -/* BINDTOOL_HEADER_FILE_HASH(5f7cb544c3d7104e228f713f28b385ee) */ +/* BINDTOOL_HEADER_FILE_HASH(7830b0b770b8e3ae0fa213f34ead29b7) */ /***********************************************************************************/ #include <pybind11/complex.h> @@ -43,17 +43,23 @@ void bind_constellation(py::module& m) using constellation_8psk_natural = ::gr::digital::constellation_8psk_natural; using constellation_16qam = ::gr::digital::constellation_16qam; + py::class_<constellation, std::shared_ptr<constellation>> constellation_class( + m, "constellation", D(constellation)); - py::class_<constellation, std::shared_ptr<constellation>>( - m, "constellation", D(constellation)) + py::enum_<constellation::normalization_t>(constellation_class, "normalization") + .value("NO_NORMALIZATION", constellation::NO_NORMALIZATION) + .value("POWER_NORMALIZATION", constellation::POWER_NORMALIZATION) + .value("AMPLITUDE_NORMALIZATION", constellation::AMPLITUDE_NORMALIZATION) + .export_values(); + constellation_class // .def(py::init<std::vector<std::complex<float>, // std::allocator<std::complex<float> > >,std::vector<int, std::allocator<int> // >,unsigned int,unsigned int,bool>(), py::arg("constell"), // py::arg("pre_diff_code"), // py::arg("rotational_symmetry"), // py::arg("dimensionality"), - // py::arg("normalize_points") = true, + // py::arg("normalization") = constellation::AMPLITUDE_NORMALIZATION, // D(constellation,constellation,0) // ) // .def(py::init<>(),D(constellation,constellation,1)) @@ -212,7 +218,7 @@ void bind_constellation(py::module& m) py::arg("pre_diff_code"), py::arg("rotational_symmetry"), py::arg("dimensionality"), - py::arg("normalize_points") = true, + py::arg("normalization") = constellation::AMPLITUDE_NORMALIZATION, D(constellation_calcdist, make)) @@ -264,6 +270,7 @@ void bind_constellation(py::module& m) py::arg("imag_sectors"), py::arg("width_real_sectors"), py::arg("width_imag_sectors"), + py::arg("normalization") = constellation::AMPLITUDE_NORMALIZATION, D(constellation_rect, make)) |