From 2b51b756a09a563c6fa5d22b931bafc4aecf3d82 Mon Sep 17 00:00:00 2001 From: Igor Freire Date: Wed, 25 Oct 2023 20:10:30 +0000 Subject: [PATCH] Use DVB-S2-specific AFF3CT codec on benchmarking - Replace the standard AFF3CT BCH codec with the DVB-S2 specific versions from the aff3ct/dvbs2 repository. - Organize the AFF3CT BCH encoder and decoder into a static library, to which the bench_bch executable links. - Move the GR-based BCH encoders and decoders to another static library and link the bench_bch executable to it. - Since the AFF3CT DVB-S2-specific BCH decoder only supports hiho decoding (hard-in/hard-out), now all decoders effectively rely on hard decisions on the input. Hence, use a common slicing function to convert the LLRs output by the BPSK demodulator into hard decisions. Remove the slicing function from the GR BCH decoding functions and apply it before calling decode(). With this change, the AFF3CT-based BCH decoder becomes DVB-S2-compliant and, hence, interoperable with the other encoder and decoder implementations. --- bench/fec/CMakeLists.txt | 19 +++-- bench/fec/src/CMakeLists.txt | 9 +- bench/fec/src/aff3ct_bch/CMakeLists.txt | 4 + .../fec/src/aff3ct_bch/Decoder_BCH_DVBS2.cpp | 84 +++++++++++++++++++ .../fec/src/aff3ct_bch/Decoder_BCH_DVBS2.hpp | 29 +++++++ .../fec/src/aff3ct_bch/Encoder_BCH_DVBS2.cpp | 56 +++++++++++++ .../fec/src/aff3ct_bch/Encoder_BCH_DVBS2.hpp | 29 +++++++ bench/fec/src/bench_bch.cc | 25 ++++-- bench/fec/src/bitman.hh | 36 -------- bench/fec/src/gr_bch/CMakeLists.txt | 5 ++ bench/fec/src/gr_bch/api.h | 6 ++ bench/fec/src/gr_bch/bitman.hh | 46 ++++++++++ .../bose_chaudhuri_hocquenghem_decoder.hh | 0 bench/fec/src/{ => gr_bch}/galois_field.hh | 2 +- bench/fec/src/{ => gr_bch}/gr_bch.cc | 36 +++----- bench/fec/src/{ => gr_bch}/gr_bch.h | 27 +++--- 16 files changed, 314 insertions(+), 99 deletions(-) create mode 100644 bench/fec/src/aff3ct_bch/CMakeLists.txt create mode 100644 bench/fec/src/aff3ct_bch/Decoder_BCH_DVBS2.cpp create mode 100644 bench/fec/src/aff3ct_bch/Decoder_BCH_DVBS2.hpp create mode 100644 bench/fec/src/aff3ct_bch/Encoder_BCH_DVBS2.cpp create mode 100644 bench/fec/src/aff3ct_bch/Encoder_BCH_DVBS2.hpp delete mode 100644 bench/fec/src/bitman.hh create mode 100644 bench/fec/src/gr_bch/CMakeLists.txt create mode 100644 bench/fec/src/gr_bch/api.h create mode 100644 bench/fec/src/gr_bch/bitman.hh rename bench/fec/src/{ => gr_bch}/bose_chaudhuri_hocquenghem_decoder.hh (100%) rename bench/fec/src/{ => gr_bch}/galois_field.hh (99%) rename bench/fec/src/{ => gr_bch}/gr_bch.cc (89%) rename bench/fec/src/{ => gr_bch}/gr_bch.h (77%) diff --git a/bench/fec/CMakeLists.txt b/bench/fec/CMakeLists.txt index 1fda8eb..e3a9b05 100644 --- a/bench/fec/CMakeLists.txt +++ b/bench/fec/CMakeLists.txt @@ -5,11 +5,16 @@ find_package(Threads REQUIRED) add_subdirectory(src) -list(APPEND bench_apps bench_plsc bench_bch) +add_executable(bench_plsc ${CMAKE_CURRENT_SOURCE_DIR}/src/bench_plsc.cc) +target_link_libraries(bench_plsc PRIVATE aff3ct::aff3ct-static-lib + boost_program_options gnuradio-dvbs2rx) +target_include_directories(bench_plsc + PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/../../lib/) -foreach(app IN LISTS bench_apps) - add_executable(${app} ${CMAKE_CURRENT_SOURCE_DIR}/src/${app}.cc) - target_link_libraries( - ${app} PRIVATE aff3ct::aff3ct-static-lib boost_program_options - gnuradio-dvbs2rx gnuradio-dvbs2rx-bench) -endforeach(app IN LISTS bench_apps) +add_executable(bench_bch ${CMAKE_CURRENT_SOURCE_DIR}/src/bench_bch.cc) +target_link_libraries( + bench_bch PRIVATE aff3ct::aff3ct-static-lib boost_program_options + gnuradio-dvbs2rx gnuradio-bch-bench aff3ct-bch) +target_include_directories( + bench_bch PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src/aff3ct_bch + ${CMAKE_CURRENT_SOURCE_DIR}/src/gr_bch) diff --git a/bench/fec/src/CMakeLists.txt b/bench/fec/src/CMakeLists.txt index 6f102ee..a8ff291 100644 --- a/bench/fec/src/CMakeLists.txt +++ b/bench/fec/src/CMakeLists.txt @@ -1,7 +1,2 @@ -list(APPEND bench_lib_sources gr_bch.cc) - -add_library(gnuradio-dvbs2rx-bench SHARED ${bench_lib_sources}) -target_include_directories( - gnuradio-dvbs2rx-bench - PUBLIC $) -target_link_libraries(gnuradio-dvbs2rx-bench PRIVATE gnuradio-dvbs2rx) +add_subdirectory(aff3ct_bch) +add_subdirectory(gr_bch) diff --git a/bench/fec/src/aff3ct_bch/CMakeLists.txt b/bench/fec/src/aff3ct_bch/CMakeLists.txt new file mode 100644 index 0000000..e3f4dc2 --- /dev/null +++ b/bench/fec/src/aff3ct_bch/CMakeLists.txt @@ -0,0 +1,4 @@ +file(GLOB_RECURSE SRC_FILES_CO ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/*.hpp) +add_library(aff3ct-bch STATIC ${SRC_FILES_CO}) +target_link_libraries(aff3ct-bch PRIVATE aff3ct::aff3ct-static-lib) diff --git a/bench/fec/src/aff3ct_bch/Decoder_BCH_DVBS2.cpp b/bench/fec/src/aff3ct_bch/Decoder_BCH_DVBS2.cpp new file mode 100644 index 0000000..7f1d9bc --- /dev/null +++ b/bench/fec/src/aff3ct_bch/Decoder_BCH_DVBS2.cpp @@ -0,0 +1,84 @@ +#include +#include +#include + +#include "Decoder_BCH_DVBS2.hpp" + +using namespace aff3ct; +using namespace aff3ct::module; + +template +Decoder_BCH_DVBS2::Decoder_BCH_DVBS2( + const int& K, const int& N, const tools::BCH_polynomial_generator& GF_poly) + : Decoder_BCH_std(K, N, GF_poly) +{ + const std::string name = "Decoder_BCH_DVBS2"; + this->set_name(name); +} + +template +Decoder_BCH_DVBS2* Decoder_BCH_DVBS2::clone() const +{ + auto m = new Decoder_BCH_DVBS2(*this); + m->deep_copy(*this); + return m; +} + +template +int Decoder_BCH_DVBS2::_decode_hiho(const B* Y_N, + int8_t* CWD, + B* V_K, + const size_t frame_id) +{ + std::reverse_copy(Y_N, Y_N + this->N, this->YH_N.begin()); + + auto status = this->_decode(this->YH_N.data(), frame_id); + + std::reverse_copy( + this->YH_N.data() + this->N - this->K, this->YH_N.data() + this->N, V_K); + + CWD[0] = !status; + return status; +} + +template +int Decoder_BCH_DVBS2::_decode_hiho_cw(const B* Y_N, + int8_t* CWD, + B* V_N, + const size_t frame_id) +{ + throw tools::unimplemented_error(__FILE__, __LINE__, __func__); +} + +template +int Decoder_BCH_DVBS2::_decode_siho(const R* Y_N, + int8_t* CWD, + B* V_K, + const size_t frame_id) +{ + throw tools::unimplemented_error(__FILE__, __LINE__, __func__); +} + +template +int Decoder_BCH_DVBS2::_decode_siho_cw(const R* Y_N, + int8_t* CWD, + B* V_N, + const size_t frame_id) +{ + throw tools::unimplemented_error(__FILE__, __LINE__, __func__); +} + + +// ==================================================================================== +// explicit template instantiation +#include "Tools/types.h" +#ifdef AFF3CT_MULTI_PREC +template class aff3ct::module::Decoder_BCH_DVBS2; +template class aff3ct::module::Decoder_BCH_DVBS2; +template class aff3ct::module::Decoder_BCH_DVBS2; +template class aff3ct::module::Decoder_BCH_DVBS2; +#else +template class aff3ct::module::Decoder_BCH_DVBS2; +#endif +// ==================================================================================== +// explicit template instantiation diff --git a/bench/fec/src/aff3ct_bch/Decoder_BCH_DVBS2.hpp b/bench/fec/src/aff3ct_bch/Decoder_BCH_DVBS2.hpp new file mode 100644 index 0000000..37435dc --- /dev/null +++ b/bench/fec/src/aff3ct_bch/Decoder_BCH_DVBS2.hpp @@ -0,0 +1,29 @@ +#ifndef DECODER_BCH_DVBS2_HPP_ +#define DECODER_BCH_DVBS2_HPP_ + +#include + +namespace aff3ct { +namespace module { +template +class Decoder_BCH_DVBS2 : public Decoder_BCH_std +{ +public: + Decoder_BCH_DVBS2(const int& K, + const int& N, + const tools::BCH_polynomial_generator& GF); + + virtual ~Decoder_BCH_DVBS2() = default; + + virtual Decoder_BCH_DVBS2* clone() const; + +protected: + virtual int _decode_hiho(const B* Y_N, int8_t* CWD, B* V_K, const size_t frame_id); + virtual int _decode_hiho_cw(const B* Y_N, int8_t* CWD, B* V_N, const size_t frame_id); + virtual int _decode_siho(const R* Y_N, int8_t* CWD, B* V_K, const size_t frame_id); + virtual int _decode_siho_cw(const R* Y_N, int8_t* CWD, B* V_N, const size_t frame_id); +}; +} // namespace module +} // namespace aff3ct + +#endif // DECODER_BCH_DVBS2_HPP_ diff --git a/bench/fec/src/aff3ct_bch/Encoder_BCH_DVBS2.cpp b/bench/fec/src/aff3ct_bch/Encoder_BCH_DVBS2.cpp new file mode 100644 index 0000000..aaf2ac4 --- /dev/null +++ b/bench/fec/src/aff3ct_bch/Encoder_BCH_DVBS2.cpp @@ -0,0 +1,56 @@ +#include +#include +#include + +#include "Encoder_BCH_DVBS2.hpp" + +using namespace aff3ct; +using namespace aff3ct::module; + +template +Encoder_BCH_DVBS2::Encoder_BCH_DVBS2(const int& K, + const int& N, + const tools::BCH_polynomial_generator& GF_poly) + : Encoder_BCH(K, N, GF_poly), U_K_rev(K) +{ + const std::string name = "Encoder_BCH_DVBS2"; + this->set_name(name); +} + +template +Encoder_BCH_DVBS2* Encoder_BCH_DVBS2::clone() const +{ + auto m = new Encoder_BCH_DVBS2(*this); + m->deep_copy(*this); + return m; +} + +template +void Encoder_BCH_DVBS2::_encode(const B* U_K, B* X_N, const size_t frame_id) +{ + // reverse bits for DVBS2 standard to aff3ct compliance + std::reverse_copy(U_K, U_K + this->K, U_K_rev.begin()); + + // generate the parity bits + this->__encode(U_K_rev.data(), X_N); + + // copy sys bits + std::copy(U_K_rev.data(), U_K_rev.data() + this->K, X_N + this->n_rdncy); + + // reverse bits for DVBS2 standard to aff3ct compliance + std::reverse(X_N, X_N + this->K + this->n_rdncy); +} + +// ==================================================================================== +// explicit template instantiation +#include "Tools/types.h" +#ifdef AFF3CT_MULTI_PREC +template class aff3ct::module::Encoder_BCH_DVBS2; +template class aff3ct::module::Encoder_BCH_DVBS2; +template class aff3ct::module::Encoder_BCH_DVBS2; +template class aff3ct::module::Encoder_BCH_DVBS2; +#else +template class aff3ct::module::Encoder_BCH_DVBS2; +#endif +// ==================================================================================== +// explicit template instantiation diff --git a/bench/fec/src/aff3ct_bch/Encoder_BCH_DVBS2.hpp b/bench/fec/src/aff3ct_bch/Encoder_BCH_DVBS2.hpp new file mode 100644 index 0000000..238c969 --- /dev/null +++ b/bench/fec/src/aff3ct_bch/Encoder_BCH_DVBS2.hpp @@ -0,0 +1,29 @@ +#ifndef ENCODER_BCH_DVBS2_HPP_ +#define ENCODER_BCH_DVBS2_HPP_ + +#include + +namespace aff3ct { +namespace module { +template +class Encoder_BCH_DVBS2 : public Encoder_BCH +{ +protected: + std::vector U_K_rev; + +public: + Encoder_BCH_DVBS2(const int& K, + const int& N, + const tools::BCH_polynomial_generator& GF); + + virtual ~Encoder_BCH_DVBS2() = default; + + virtual Encoder_BCH_DVBS2* clone() const; + +protected: + virtual void _encode(const B* U_K, B* X_N, const size_t frame_id); +}; +} // namespace module +} // namespace aff3ct + +#endif // ENCODER_BCH_DVBS2_HPP_ diff --git a/bench/fec/src/bench_bch.cc b/bench/fec/src/bench_bch.cc index b03e519..a06bf40 100644 --- a/bench/fec/src/bench_bch.cc +++ b/bench/fec/src/bench_bch.cc @@ -1,3 +1,5 @@ +#include "Decoder_BCH_DVBS2.hpp" +#include "Encoder_BCH_DVBS2.hpp" #include "gr_bch.h" #include #include @@ -43,7 +45,7 @@ struct BchEncoder { int m_impl; // Decoder implementation std::unique_ptr m_new_encoder; std::unique_ptr m_gr_encoder; - std::unique_ptr> m_aff3ct_encoder; + std::unique_ptr> m_aff3ct_encoder; std::unique_ptr> m_aff3ct_gen_poly; public: @@ -62,7 +64,7 @@ struct BchEncoder { if (m_impl == AFF3CT_IMPL) { set_aff3ct_gen_poly(N, t, m_aff3ct_gen_poly); m_aff3ct_encoder.reset( - new module::Encoder_BCH<>(K, N, *m_aff3ct_gen_poly.get())); + new module::Encoder_BCH_DVBS2<>(K, N, *m_aff3ct_gen_poly.get())); } else if (m_impl == GR_DVBS2RX_IMPL) { m_gr_encoder.reset(new gr::dvbs2::GrBchEncoder(K, N, t)); } else if (m_impl == NEW_IMPL) { @@ -89,8 +91,9 @@ struct BchDecoder { int m_impl; // Decoder implementation std::unique_ptr m_new_encoder; std::unique_ptr m_gr_decoder; - std::unique_ptr> m_aff3ct_std_decoder; + std::unique_ptr> m_aff3ct_std_decoder; std::unique_ptr> m_aff3ct_gen_poly; + std::vector m_hard_dec; public: /** @@ -101,12 +104,13 @@ struct BchDecoder { * @param N Codeword length in bits. * @param t Error correction capability. */ - BchDecoder(int impl, int K, int N, int t) : m_impl(impl), m_K(K), m_N(N) + BchDecoder(int impl, int K, int N, int t) + : m_impl(impl), m_K(K), m_N(N), m_hard_dec(N) { if (m_impl == AFF3CT_IMPL) { set_aff3ct_gen_poly(N, t, m_aff3ct_gen_poly); m_aff3ct_std_decoder.reset( - new module::Decoder_BCH_std<>(K, N, *m_aff3ct_gen_poly.get())); + new module::Decoder_BCH_DVBS2<>(K, N, *m_aff3ct_gen_poly.get())); } else if (m_impl == GR_DVBS2RX_IMPL) { m_gr_decoder.reset(new gr::dvbs2::GrBchDecoder(K, N, t)); } else if (m_impl == NEW_IMPL) { @@ -116,12 +120,17 @@ struct BchDecoder { void decode(const std::vector& llr_vec, std::vector& dec_bits) { + // Convert the LLR vector into hard decisions. Assume the BCH decoder would take + // hard decisions output by the LDPC decoder even though there is no LDPC block in + // this setup. Importantly, make the same assumption for all implementations. + tools::hard_decide(llr_vec.data(), m_hard_dec.data(), m_N); + if (m_impl == AFF3CT_IMPL) { - m_aff3ct_std_decoder->decode_siho(llr_vec, dec_bits); + m_aff3ct_std_decoder->decode_hiho(m_hard_dec, dec_bits); } else if (m_impl == GR_DVBS2RX_IMPL) { - m_gr_decoder->decode(llr_vec, dec_bits); + m_gr_decoder->decode(m_hard_dec, dec_bits); } else if (m_impl == NEW_IMPL) { - m_new_encoder->decode(llr_vec, dec_bits); + m_new_encoder->decode(m_hard_dec, dec_bits); } } }; diff --git a/bench/fec/src/bitman.hh b/bench/fec/src/bitman.hh deleted file mode 100644 index ea683af..0000000 --- a/bench/fec/src/bitman.hh +++ /dev/null @@ -1,36 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2018 Ahmet Inan, Ron Economos. - * - * This file is part of gr-dvbs2rx. - * - * SPDX-License-Identifier: GPL-3.0-or-later - */ - -#ifndef BITMAN_HH -#define BITMAN_HH - -#include - -namespace CODE { - -void xor_be_bit(uint8_t* buf, int pos, bool val) { buf[pos / 8] ^= val << (7 - pos % 8); } - -void xor_le_bit(uint8_t* buf, int pos, bool val) { buf[pos / 8] ^= val << (pos % 8); } - -void set_be_bit(uint8_t* buf, int pos, bool val) -{ - buf[pos / 8] = (~(1 << (7 - pos % 8)) & buf[pos / 8]) | (val << (7 - pos % 8)); -} - -void set_le_bit(uint8_t* buf, int pos, bool val) -{ - buf[pos / 8] = (~(1 << (pos % 8)) & buf[pos / 8]) | (val << (pos % 8)); -} - -bool get_be_bit(uint8_t* buf, int pos) { return (buf[pos / 8] >> (7 - pos % 8)) & 1; } - -bool get_le_bit(uint8_t* buf, int pos) { return (buf[pos / 8] >> (pos % 8)) & 1; } -} // namespace CODE - -#endif diff --git a/bench/fec/src/gr_bch/CMakeLists.txt b/bench/fec/src/gr_bch/CMakeLists.txt new file mode 100644 index 0000000..d8923cc --- /dev/null +++ b/bench/fec/src/gr_bch/CMakeLists.txt @@ -0,0 +1,5 @@ +list(APPEND gr_bch_sources gr_bch.cc) +add_library(gnuradio-bch-bench STATIC ${gr_bch_sources}) +target_include_directories(gnuradio-bch-bench + PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/../../../../lib) +target_link_libraries(gnuradio-bch-bench PRIVATE gnuradio-dvbs2rx) diff --git a/bench/fec/src/gr_bch/api.h b/bench/fec/src/gr_bch/api.h new file mode 100644 index 0000000..949064b --- /dev/null +++ b/bench/fec/src/gr_bch/api.h @@ -0,0 +1,6 @@ +#ifndef INCLUDED_DVBS2_GR_BCH_BENCH_API_H +#define INCLUDED_DVBS2_GR_BCH_BENCH_API_H + +#define DVBS2_GR_BCH_BENCH_API __attribute__((visibility("default"))) + +#endif /* INCLUDED_DVBS2_GR_BCH_BENCH_API_H */ diff --git a/bench/fec/src/gr_bch/bitman.hh b/bench/fec/src/gr_bch/bitman.hh new file mode 100644 index 0000000..0685fa1 --- /dev/null +++ b/bench/fec/src/gr_bch/bitman.hh @@ -0,0 +1,46 @@ +/* -*- c++ -*- */ +/* + * Copyright 2018 Ahmet Inan, Ron Economos. + * + * This file is part of gr-dvbs2rx. + * + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +#ifndef BITMAN_HH +#define BITMAN_HH + +#include + +namespace CODE { + +void inline xor_be_bit(uint8_t* buf, int pos, bool val) +{ + buf[pos / 8] ^= val << (7 - pos % 8); +} + +void inline xor_le_bit(uint8_t* buf, int pos, bool val) +{ + buf[pos / 8] ^= val << (pos % 8); +} + +void inline set_be_bit(uint8_t* buf, int pos, bool val) +{ + buf[pos / 8] = (~(1 << (7 - pos % 8)) & buf[pos / 8]) | (val << (7 - pos % 8)); +} + +void inline set_le_bit(uint8_t* buf, int pos, bool val) +{ + buf[pos / 8] = (~(1 << (pos % 8)) & buf[pos / 8]) | (val << (pos % 8)); +} + +bool inline get_be_bit(uint8_t* buf, int pos) +{ + return (buf[pos / 8] >> (7 - pos % 8)) & 1; +} + +bool inline get_le_bit(uint8_t* buf, int pos) { return (buf[pos / 8] >> (pos % 8)) & 1; } + +} // namespace CODE + +#endif diff --git a/bench/fec/src/bose_chaudhuri_hocquenghem_decoder.hh b/bench/fec/src/gr_bch/bose_chaudhuri_hocquenghem_decoder.hh similarity index 100% rename from bench/fec/src/bose_chaudhuri_hocquenghem_decoder.hh rename to bench/fec/src/gr_bch/bose_chaudhuri_hocquenghem_decoder.hh diff --git a/bench/fec/src/galois_field.hh b/bench/fec/src/gr_bch/galois_field.hh similarity index 99% rename from bench/fec/src/galois_field.hh rename to bench/fec/src/gr_bch/galois_field.hh index 580f7ee..a71cda9 100644 --- a/bench/fec/src/galois_field.hh +++ b/bench/fec/src/gr_bch/galois_field.hh @@ -293,4 +293,4 @@ private: GF::Tables Tables; }; } // namespace CODE -#endif +#endif \ No newline at end of file diff --git a/bench/fec/src/gr_bch.cc b/bench/fec/src/gr_bch/gr_bch.cc similarity index 89% rename from bench/fec/src/gr_bch.cc rename to bench/fec/src/gr_bch/gr_bch.cc index cb3a9e3..a05666f 100644 --- a/bench/fec/src/gr_bch.cc +++ b/bench/fec/src/gr_bch/gr_bch.cc @@ -50,20 +50,6 @@ void unpacked_to_packed(const std::vector& in_bits, std::vector& o } } -void unpacked_to_packed(const std::vector& in_llrs, - std::vector& out_bytes) -{ - if (in_llrs.size() % 8 != 0) - throw std::runtime_error("Input LLRs must be a multiple of 8"); - if (in_llrs.size() / 8 != out_bytes.size()) - throw std::runtime_error("Input and output sizes do not match"); - memset(out_bytes.data(), 0, out_bytes.size()); - for (unsigned int j = 0; j < in_llrs.size(); j++) { - // Slice and pack - out_bytes[j / 8] |= (in_llrs[j] < 0) << (7 - (j % 8)); - } -} - void packed_to_unpacked(const std::vector& in_bytes, std::vector& out_bits) { if (in_bytes.size() * 8 != out_bits.size()) @@ -215,18 +201,18 @@ GrBchDecoder::GrBchDecoder(int k, int n, int t) } } -void GrBchDecoder::slice_and_pack(const std::vector& llr_vec) +void GrBchDecoder::pack_bits(const std::vector& in_bits) { - assert(llr_vec.size() == m_N); + assert(in_bits.size() == m_N); for (unsigned int j = 0; j < m_K; j++) { - CODE::set_be_bit(m_packed_code.data(), j, llr_vec[j] < 0); + CODE::set_be_bit(m_packed_code.data(), j, in_bits[j]); } for (unsigned int j = 0; j < m_N - m_K; j++) { - CODE::set_be_bit(m_packed_parity.data(), j, llr_vec[j + m_K] < 0); + CODE::set_be_bit(m_packed_parity.data(), j, in_bits[j + m_K]); } } -void GrBchDecoder::unpack(std::vector& dec_bits) +void GrBchDecoder::unpack_bits(std::vector& dec_bits) { assert(dec_bits.size() == m_K); for (unsigned int j = 0; j < m_K; j++) { @@ -234,9 +220,9 @@ void GrBchDecoder::unpack(std::vector& dec_bits) } } -void GrBchDecoder::decode(const std::vector& llr_vec, std::vector& dec_bits) +void GrBchDecoder::decode(const std::vector& in_bits, std::vector& dec_bits) { - slice_and_pack(llr_vec); + pack_bits(in_bits); if (m_N >= 16200) { if (m_t == 12) { (*m_dvbs2rx_decoder_n12)( @@ -251,7 +237,7 @@ void GrBchDecoder::decode(const std::vector& llr_vec, std::vector& d } else { (*m_dvbs2rx_decoder_s12)(m_packed_code.data(), m_packed_parity.data(), 0, 0, m_K); } - unpack(dec_bits); + unpack_bits(dec_bits); } @@ -274,13 +260,13 @@ void NewBchCodec::encode(const std::vector& ref_bits, std::vector& enc packed_to_unpacked(m_packed_codeword, enc_bits); } -void NewBchCodec::decode(const std::vector& llr_vec, std::vector& dec_bits) +void NewBchCodec::decode(const std::vector& in_bits, std::vector& dec_bits) { - if (llr_vec.size() != m_bch.get_n()) + if (in_bits.size() != m_bch.get_n()) throw std::runtime_error("Input size does not match"); if (dec_bits.size() != m_bch.get_k()) throw std::runtime_error("Output size does not match"); - unpacked_to_packed(llr_vec, m_packed_codeword); + unpacked_to_packed(in_bits, m_packed_codeword); m_bch.decode(m_packed_codeword.data(), m_packed_msg.data()); packed_to_unpacked(m_packed_msg, dec_bits); } diff --git a/bench/fec/src/gr_bch.h b/bench/fec/src/gr_bch/gr_bch.h similarity index 77% rename from bench/fec/src/gr_bch.h rename to bench/fec/src/gr_bch/gr_bch.h index fcce9f8..fb7ceb3 100644 --- a/bench/fec/src/gr_bch.h +++ b/bench/fec/src/gr_bch/gr_bch.h @@ -9,6 +9,7 @@ #ifndef INCLUDED_GR_BCH_H #define INCLUDED_GR_BCH_H +#include "api.h" #include "bch.h" #include "bose_chaudhuri_hocquenghem_decoder.hh" #include "galois_field.hh" @@ -16,7 +17,6 @@ #include #include -#define DVBS2_BENCH_API __attribute__((visibility("default"))) #define MAX_BCH_PARITY_BITS 192 namespace gr { @@ -36,7 +36,7 @@ typedef CODE::BoseChaudhuriHocquenghemDecoder<24, 1, 16215, GF_SHORT> BCH_SHORT_ * * Based on gr-dtv/lib/dvb/dvb_bch_bb_impl.cc from the GR sources. */ -class DVBS2_BENCH_API GrBchEncoder +class DVBS2_GR_BCH_BENCH_API GrBchEncoder { private: int m_K; // Message length in bits. @@ -58,7 +58,7 @@ class DVBS2_BENCH_API GrBchEncoder * @brief Wrapper for gr-dvbs2rx's original BCH Decoder * */ -class DVBS2_BENCH_API GrBchDecoder +class DVBS2_GR_BCH_BENCH_API GrBchDecoder { private: int m_K; // Message length in bits. @@ -75,32 +75,29 @@ class DVBS2_BENCH_API GrBchDecoder /** - * @brief Compute the hard decisions and pack them into bytes. + * @brief Pack bits into bytes. * - * Each LLR is converted to a hard decision by comparison to 0. The decision mapping - * is bit=1 for llr < 0 and bit=0 for llr >= 0. - * - * @param llr_vec Vector with log likelihood ratios (LLRs). + * @param in_bits Vector with the input bits. */ - void slice_and_pack(const std::vector& llr_vec); + void pack_bits(const std::vector& in_bits); /** - * @brief Unpack the BCH decoder result. + * @brief Unpack bits from bytes. * - * @param dec_bits Resulting (unpacked) vector of decoded bits. + * @param dec_bits Vector to hold the resulting (unpacked) decoded bits. */ - void unpack(std::vector& dec_bits); + void unpack_bits(std::vector& dec_bits); public: GrBchDecoder(int k, int n, int t); - void decode(const std::vector& llr_vec, std::vector& dec_bits); + void decode(const std::vector& in_bits, std::vector& dec_bits); }; /** * @brief Wrapper for the new BCH Codec implementation * */ -class DVBS2_BENCH_API NewBchCodec +class DVBS2_GR_BCH_BENCH_API NewBchCodec { private: gr::dvbs2rx::galois_field m_gf; @@ -111,7 +108,7 @@ class DVBS2_BENCH_API NewBchCodec public: NewBchCodec(int N, int t); void encode(const std::vector& ref_bits, std::vector& enc_bits); - void decode(const std::vector& llr_vec, std::vector& dec_bits); + void decode(const std::vector& in_bits, std::vector& dec_bits); }; } // namespace dvbs2