Added decode block

gr-droneid-update-3.10
David Protzman 2022-09-22 21:15:13 -04:00
rodzic 08cd68ab52
commit 94297ff21c
12 zmienionych plików z 399 dodań i 3 usunięć

Wyświetl plik

@ -7,5 +7,5 @@
#
install(FILES
droneid_misc_utils.block.yml DESTINATION share/gnuradio/grc/blocks
droneid_decode.block.yml DESTINATION share/gnuradio/grc/blocks
)

Wyświetl plik

@ -0,0 +1,40 @@
id: droneid_decode
label: decode
category: '[droneid]'
templates:
imports: from gnuradio import droneid
make: droneid.decode(${debug_path})
# Make one 'parameters' list entry for every parameter you want settable from the GUI.
# Keys include:
# * id (makes the value accessible as keyname, e.g. in the make entry)
# * label (label shown in the GUI)
# * dtype (e.g. int, float, complex, byte, short, xxx_vector, ...)
# * default
parameters:
- id: debug_path
label: Debug Path
dtype: string
default: /tmp/bursts
# Make one 'inputs' list entry per input and one 'outputs' list entry per output.
# Keys include:
# * label (an identifier for the GUI)
# * domain (optional - stream or message. Default is stream)
# * dtype (e.g. int, float, complex, byte, short, xxx_vector, ...)
# * vlen (optional - data stream vector length. Default is 1)
# * optional (optional - set to 1 for optional inputs. Default is 0)
inputs:
- label: pdus
domain: message
optional: 0
outputs:
- label: pdus
domain: message
optional: 1
# 'file_format' specifies the version of the GRC yml format used in the file
# and should usually not be changed.
file_format: 1

Wyświetl plik

@ -11,5 +11,6 @@
########################################################################
install(FILES
api.h
misc_utils.h DESTINATION include/gnuradio/droneid
misc_utils.h
decode.h DESTINATION include/gnuradio/droneid
)

Wyświetl plik

@ -0,0 +1,41 @@
/* -*- c++ -*- */
/*
* Copyright 2022 gr-droneid author.
*
* SPDX-License-Identifier: GPL-3.0-or-later
*/
#ifndef INCLUDED_DRONEID_DECODE_H
#define INCLUDED_DRONEID_DECODE_H
#include <gnuradio/droneid/api.h>
#include <gnuradio/sync_block.h>
namespace gr {
namespace droneid {
/*!
* \brief <+description of block+>
* \ingroup droneid
*
*/
class DRONEID_API decode : virtual public gr::sync_block
{
public:
typedef std::shared_ptr<decode> sptr;
/*!
* \brief Return a shared_ptr to a new instance of droneid::decode.
*
* To avoid accidental use of raw pointers, droneid::decode's
* constructor is in a private implementation
* class. droneid::decode::make is the public interface for
* creating new instances.
*/
static sptr make(const std::string & debug_path);
};
} // namespace droneid
} // namespace gr
#endif /* INCLUDED_DRONEID_DECODE_H */

Wyświetl plik

@ -13,6 +13,7 @@ include(GrPlatform) #define LIB_SUFFIX
list(APPEND droneid_sources
misc_utils.cc
decode_impl.cc
)
set(droneid_sources "${droneid_sources}" PARENT_SCOPE)
@ -23,6 +24,7 @@ endif(NOT droneid_sources)
add_library(gnuradio-droneid SHARED ${droneid_sources})
target_link_libraries(gnuradio-droneid gnuradio::gnuradio-runtime gnuradio-fft gnuradio-filter)
target_link_libraries(gnuradio-droneid turbofec boost_filesystem)
target_include_directories(gnuradio-droneid
PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/../include>
PUBLIC $<INSTALL_INTERFACE:include>
@ -56,6 +58,7 @@ include(GrTest)
#include_directories()
# List all files that contain Boost.UTF unit tests here
list(APPEND test_droneid_sources
qa_decode.cc
)
# Anything we need to link to for the unit tests go here
list(APPEND GR_TEST_TARGET_DEPS gnuradio-droneid)

Wyświetl plik

@ -0,0 +1,173 @@
/* -*- c++ -*- */
/*
* Copyright 2022 gr-droneid author.
*
* SPDX-License-Identifier: GPL-3.0-or-later
*/
#include "decode_impl.h"
#include <gnuradio/io_signature.h>
extern "C" {
#include <turbofec/rate_match.h>
#include <turbofec/turbo.h>
}
#include <gnuradio/io_signature.h>
#include "decode_impl.h"
#include <boost/filesystem.hpp>
#include <gnuradio/droneid/misc_utils.h>
#include <chrono>
// This line is required before the include of CRC.h so that it actually loads the CRC_24_LTEA definition
#define CRCPP_INCLUDE_ESOTERIC_CRC_DEFINITIONS
#include <CRC.h>
namespace gr {
namespace droneid {
using path = boost::filesystem::path;
decode::sptr
decode::make(const std::string & debug_path) {
return gnuradio::get_initial_sptr
(new decode_impl(debug_path));
}
/*
* The private constructor
*/
decode_impl::decode_impl(const std::string & debug_path)
: gr::sync_block("decode",
gr::io_signature::make(0, 0, 0),
gr::io_signature::make(0, 0, 0)),
debug_path_(debug_path){
message_port_register_in(pmt::mp(input_pdu_port_name_));
message_port_register_out(pmt::mp(output_pdu_port_name_));
set_msg_handler(pmt::mp(input_pdu_port_name_), [this](const pmt::pmt_t & pdu){
this->handle_pdu(pdu);
});
}
/*
* Our virtual destructor.
*/
decode_impl::~decode_impl() {
}
std::vector<int8_t> decode_impl::qpsk_to_bits(const std::vector<gr_complex> &samples) {
std::vector<int8_t> bits(samples.size() * 2);
auto * bit_vec_ptr = &bits[0];
std::for_each(samples.begin(), samples.end(), [&bit_vec_ptr](const gr_complex & sample) {
if (sample.real() > 0 && sample.imag() > 0) {
*bit_vec_ptr++ = 0;
*bit_vec_ptr++ = 0;
} else if (sample.real() > 0 && sample.imag() < 0) {
*bit_vec_ptr++ = 0;
*bit_vec_ptr++ = 1;
} else if (sample.real() < 0 && sample.imag() > 0) {
*bit_vec_ptr++ = 1;
*bit_vec_ptr++ = 0;
} else {
*bit_vec_ptr++ = 1;
*bit_vec_ptr++ = 1;
}
});
return bits;
}
void decode_impl::handle_pdu(const pmt::pmt_t & pdu) {
const auto start_time = std::chrono::high_resolution_clock::now();
const pmt::pmt_t meta = pmt::car(pdu);
const pmt::pmt_t vec = pmt::cdr(pdu);
const auto samples = pmt::c32vector_elements(vec);
if (samples.size() != 3600) {
std::cout << "Invalid number of samples. Expected 3600, got " << samples.size() << "\n";
return;
}
auto bits = qpsk_to_bits(samples);
if (! debug_path_.empty()) {
misc_utils::write((path(debug_path_) / "bits").string(), &bits[0], sizeof(bits[0]), bits.size());
const auto bit_string = misc_utils::bit_vec_to_string(bits);
misc_utils::write((path(debug_path_) / "bit_string").string(), &bit_string[0], sizeof(bit_string[0]), bit_string.size());
}
// misc_utils::print_bits(bits);
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Setup and run the Turbo decoder
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
const size_t input_file_bit_count = 7200;
const int turbo_iterations = 4;
const int turbo_decoder_bit_count = 1412; // Number of bits that the Turbo decoder will take in
const int expected_payload_bytes = 176; // Number of bytes that the Turbo decoder will output
const int expected_payload_bits = expected_payload_bytes * 8;
// Allocate buffers for the Turbo decoder
std::vector<int8_t> d1(turbo_decoder_bit_count);
std::vector<int8_t> d2(turbo_decoder_bit_count);
std::vector<int8_t> d3(turbo_decoder_bit_count);
std::vector<uint8_t> decoded_bytes(expected_payload_bytes);
// Create the required structures to run the Turbo decoder
struct lte_rate_matcher * rate_matcher = lte_rate_matcher_alloc();
struct tdecoder * turbo_decoder = alloc_tdec();
struct lte_rate_matcher_io rate_matcher_io = {
.D = turbo_decoder_bit_count,
.E = input_file_bit_count,
.d = {&d1[0], &d2[0], &d3[0]},
.e = &bits[0]
};
// Setup the rate matching logic
lte_rate_match_rv(rate_matcher, &rate_matcher_io, 0);
// Run the turbo decoder (will do rate matching as well)
const int decode_status = lte_turbo_decode(turbo_decoder, expected_payload_bits, turbo_iterations,
&decoded_bytes[0], &d1[0], &d2[0], &d3[0]);
if (decode_status != 0) {
std::cerr << "Failed to decode\n";
} else {
for (const auto & b : decoded_bytes) {
fprintf(stdout, "%02x", b);
}
fprintf(stdout, "\n");
const auto crc_out = CRC::Calculate(&decoded_bytes[0], decoded_bytes.size(), CRC::CRC_24_LTEA());
if (crc_out != 0) {
std::cerr << "CRC Check Failed!\n";
}
message_port_pub(pmt::mp(output_pdu_port_name_), pmt::cons(pmt::make_dict(), pmt::init_u8vector(decoded_bytes.size(), decoded_bytes)));
}
free_tdec(turbo_decoder);
lte_rate_matcher_free(rate_matcher);
const auto end_time = std::chrono::high_resolution_clock::now();
std::cout << "Time: " << std::chrono::duration<float>(end_time - start_time).count() << "\n";
}
int
decode_impl::work(int noutput_items,
gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items) {
// Do <+signal processing+>
// Tell runtime system how many output items we produced.
return noutput_items;
}
} /* namespace droneid */
} /* namespace gr */

Wyświetl plik

@ -0,0 +1,44 @@
/* -*- c++ -*- */
/*
* Copyright 2022 gr-droneid author.
*
* SPDX-License-Identifier: GPL-3.0-or-later
*/
#ifndef INCLUDED_DRONEID_DECODE_IMPL_H
#define INCLUDED_DRONEID_DECODE_IMPL_H
#include <gnuradio/droneid/decode.h>
namespace gr {
namespace droneid {
class decode_impl : public decode {
private:
const std::string input_pdu_port_name_ = "pdus";
const std::string output_pdu_port_name_ = "pdus";
const std::string debug_path_;
static std::vector<int8_t> qpsk_to_bits(const std::vector<gr_complex> & samples);
// Nothing to declare in this block.
public:
decode_impl(const std::string & debug_path);
~decode_impl();
// Where all the action really happens
int work(
int noutput_items,
gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items
);
void handle_pdu(const pmt::pmt_t & pdu);
};
} // namespace droneid
} // namespace gr
#endif /* INCLUDED_DRONEID_DECODE_IMPL_H */

Wyświetl plik

@ -0,0 +1,21 @@
/* -*- c++ -*- */
/*
* Copyright 2022 gr-droneid author.
*
* SPDX-License-Identifier: GPL-3.0-or-later
*/
#include <gnuradio/attributes.h>
#include <gnuradio/droneid/decode.h>
#include <boost/test/unit_test.hpp>
namespace gr {
namespace droneid {
BOOST_AUTO_TEST_CASE(test_decode_replace_with_specific_test_name)
{
// Put test here
}
} /* namespace droneid */
} /* namespace gr */

Wyświetl plik

@ -29,7 +29,8 @@ include(GrPybind)
########################################################################
list(APPEND droneid_python_files
misc_utils_python.cc python_bindings.cc)
misc_utils_python.cc
decode_python.cc python_bindings.cc)
GR_PYBIND_MAKE_OOT(droneid
../../..

Wyświetl plik

@ -0,0 +1,46 @@
/*
* Copyright 2022 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(decode.h) */
/* BINDTOOL_HEADER_FILE_HASH(4384f371a0acd77c255acf790ea502c6) */
/***********************************************************************************/
#include <pybind11/complex.h>
#include <pybind11/pybind11.h>
#include <pybind11/stl.h>
namespace py = pybind11;
#include <gnuradio/droneid/decode.h>
// pydoc.h is automatically generated in the build directory
#include <decode_pydoc.h>
void bind_decode(py::module& m)
{
using decode = ::gr::droneid::decode;
py::class_<decode,
gr::sync_block,
gr::block,
gr::basic_block,
std::shared_ptr<decode>>(m, "decode", D(decode))
.def(py::init(&decode::make), py::arg("debug_path"), D(decode, make))
;
}

Wyświetl plik

@ -0,0 +1,24 @@
/*
* Copyright 2022 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, droneid, __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_droneid_decode = R"doc()doc";
static const char* __doc_gr_droneid_decode_decode = R"doc()doc";
static const char* __doc_gr_droneid_decode_make = R"doc()doc";

Wyświetl plik

@ -22,6 +22,7 @@ namespace py = pybind11;
/**************************************/
// BINDING_FUNCTION_PROTOTYPES(
void bind_misc_utils(py::module& m);
void bind_decode(py::module& m);
// ) END BINDING_FUNCTION_PROTOTYPES
@ -53,5 +54,6 @@ PYBIND11_MODULE(droneid_python, m)
/**************************************/
// BINDING_FUNCTION_CALLS(
bind_misc_utils(m);
bind_decode(m);
// ) END BINDING_FUNCTION_CALLS
}