Implement the generic decoder API

To simplify the logic and allow an easy and more efficient way to add
new decoders, the new architecture uses only one decoder block.

This block takes as input a void* stream and produces PDUs with their
metadata. To do so, the block accepts a decoder object. Every decoder
should implement the virtual class decoder(). This class provides the
necessary API and an arbitrary number of decoders can be supported. The
decoding status is reported to the frame_decoder block through the
decoder_status_t structure.
This commit is contained in:
Manolis Surligas 2019-09-01 12:41:27 +03:00
parent 9fe6b6f274
commit ad590174e0
11 changed files with 503 additions and 1 deletions

View File

@ -34,6 +34,7 @@ list(APPEND enabled_blocks
satnogs_ccsds_rs_decoder_mm.xml
satnogs_decoder_8b10b.xml
satnogs_fox_telem_mm.xml
satnogs_frame_decoder.xml
satnogs_frame_file_sink.xml
satnogs_iq_sink.xml
satnogs_lrpt_decoder.xml

View File

@ -43,4 +43,5 @@
<block>satnogs_decoder_8b10b</block>
<block>variable_whitening</block>
<block>satnogs_frame_acquisition</block>
<block>satnogs_frame_decoder</block>
</cat>

View File

@ -0,0 +1,63 @@
<?xml version="1.0"?>
<block>
<name>Frame Decoder</name>
<key>satnogs_frame_decoder</key>
<import>import satnogs</import>
<make>satnogs.frame_decoder($decoder_object, $itype.size)</make>
<param>
<name>Input Type</name>
<key>itype</key>
<value></value>
<type>enum</type>
<option>
<name>Complex</name>
<key>complex</key>
<opt>size:gr.sizeof_gr_complex</opt>
</option>
<option>
<name>Float</name>
<key>float</key>
<opt>size:gr.sizeof_float</opt>
</option>
<option>
<name>Int</name>
<key>int</key>
<opt>size:gr.sizeof_int</opt>
</option>
<option>
<name>Short</name>
<key>short</key>
<opt>size:gr.sizeof_short</opt>
</option>
<option>
<name>Byte</name>
<key>byte</key>
<opt>size:gr.sizeof_char</opt>
</option>
</param>
<param>
<name>Decoder object</name>
<key>decoder_object</key>
<value>None</value>
<type>raw</type>
</param>
<sink>
<name>in</name>
<type>$itype</type>
</sink>
<sink>
<name>reset</name>
<type>message</type>
<optional>1</optional>
</sink>
<source>
<name>out</name>
<type>message</type>
</source>
</block>

View File

@ -42,6 +42,8 @@ list(APPEND HEADER_FILES
utils.h
udp_msg_source.h
tcp_rigctl_msg_source.h
decoder.h
frame_decoder.h
frame_encoder.h
doppler_correction_cc.h
doppler_fit.h

126
include/satnogs/decoder.h Normal file
View File

@ -0,0 +1,126 @@
/* -*- c++ -*- */
/*
* gr-satnogs: SatNOGS GNU Radio Out-Of-Tree Module
*
* Copyright (C) 2019, Libre Space Foundation <http://libre.space>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef INCLUDED_SATNOGS_DECODER_H
#define INCLUDED_SATNOGS_DECODER_H
#include <satnogs/api.h>
#include <cstdint>
#include <cstdlib>
#include <pmt/pmt.h>
namespace gr
{
namespace satnogs
{
/**
* The status of the decoder
*/
class decoder_status
{
public:
bool packed; /**< Indicates if the output is packed bits or unpacked */
int consumed; /**< The number of input items consumed */
ssize_t decoded_bits; /**< The number of the decoded bits. */
pmt::pmt_t metadata; /**< Metadata for the decoded frame */
decoder_status () :
packed(false),
consumed(0),
decoded_bits(-1),
metadata(pmt::PMT_NIL)
{
}
};
typedef class decoder_status decoder_status_t;
/**
* \brief Abstract class that provided the API for the c decoders
*
* This is an abstract class providing the API for the SatNOGS decoders.
*
* The gr-satnogs module tries to provide a unified decoding framework,
* for various satellites.
* Specialization is performed by passing to the generic decoding block the
* appropriate decoder class that implements this abstract class API.
*
*/
class SATNOGS_API decoder
{
public:
typedef boost::shared_ptr<decoder> decoder_sptr;
static int base_unique_id;
int
unique_id ();
decoder (int input_item_size, size_t max_frame_len = 8192);
virtual ~decoder ();
/**
* Decodes a buffer. The difference with the decoder::decode_once() is that
* this method does not reset the internal state of the decoder.
* Therefore, it can be called again and continue the decoding when
* data are available.
*
* @param out the output buffer that will hold the decoded data
*
* @param in the input items
*
* @param len the length of the input buffer in <b>bits</b>
*
* @return the number of decoded <b>bits</b>. Due to the fact that
* some coding schemes may not produce an output that is a multiple of
* 8 bits, it is necessary to count in a per bit basis. If the result
* is not a multiple of 8 bits, the LS bits are padded with zeros.
* If an error occurred an appropriate negative error code is returned
*/
virtual decoder_status_t
decode (uint8_t *out, const void *in, int len) = 0;
/**
* Resets the internal state of the decoder to the initial defaults
*
*/
virtual void
reset () = 0;
size_t
max_frame_len() const;
int
sizeof_input_item() const;
private:
const int d_sizeof_in;
const size_t d_max_frame_len;
int d_id;
};
} // namespace satnogs
} // namespace gr
#endif /* INCLUDED_SATNOGS_DECODER_H */

View File

@ -0,0 +1,60 @@
/* -*- c++ -*- */
/*
* gr-satnogs: SatNOGS GNU Radio Out-Of-Tree Module
*
* Copyright (C) 2019, Libre Space Foundation <http://libre.space>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef INCLUDED_SATNOGS_FRAME_DECODER_H
#define INCLUDED_SATNOGS_FRAME_DECODER_H
#include <satnogs/api.h>
#include <gnuradio/sync_block.h>
#include <satnogs/decoder.h>
namespace gr {
namespace satnogs {
/*!
* \brief This is a generic frame decoder block. It takes as input a
* bit stream and produces decoded frames and their metadata.
*
* The decoding is performed by using a proper decoder object.
* Each decoder implements the virtual class ::decoder()
*
* The frame and metadata are produced in a pmt dictionary, with the
* keys "pdu" and "metadata".
*
* \ingroup satnogs
*
*/
class SATNOGS_API frame_decoder : virtual public gr::sync_block
{
public:
typedef boost::shared_ptr<frame_decoder> sptr;
/*!
* \brief Return a shared_ptr to a new instance of satnogs::frame_decoder.
* @param decoder_object the decoder object to use
*/
static sptr make(decoder::decoder_sptr decoder_object, int input_size);
};
} // namespace satnogs
} // namespace gr
#endif /* INCLUDED_SATNOGS_FRAME_DECODER_H */

View File

@ -48,7 +48,9 @@ list(APPEND satnogs_sources
cw_to_symbol_impl.cc
udp_msg_source_impl.cc
tcp_rigctl_msg_source_impl.cc
decoder.cc
doppler_correction_cc_impl.cc
frame_decoder_impl.cc
frame_encoder_impl.cc
doppler_fit.cc
freq_drift.cc

78
lib/decoder.cc Normal file
View File

@ -0,0 +1,78 @@
/* -*- c++ -*- */
/*
* gr-satnogs: SatNOGS GNU Radio Out-Of-Tree Module
*
* Copyright (C) 2019, Libre Space Foundation <http://libre.space>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <gnuradio/io_signature.h>
#include <satnogs/decoder.h>
namespace gr
{
namespace satnogs
{
int decoder::base_unique_id = 1;
/**
* @note: For internal GNU Radio companion usage. DO NOT EDIT!
* @return the unique id of the decoder object
*/
int
decoder::unique_id ()
{
return d_id;
}
/**
* Creates a generic decoder object
* @param max_frame_len the maximum allowed frame size in bytes
*/
decoder::decoder(int input_item_size, size_t max_frame_len)
: d_sizeof_in(input_item_size),
d_max_frame_len(max_frame_len),
d_id(base_unique_id++)
{
}
decoder::~decoder()
{
}
/**
*
* @return the maximum allowed frame length
*/
size_t
decoder::max_frame_len() const
{
return d_max_frame_len;
}
int
decoder::sizeof_input_item () const
{
return d_sizeof_in;
}
} /* namespace satnogs */
} /* namespace gr */

106
lib/frame_decoder_impl.cc Normal file
View File

@ -0,0 +1,106 @@
/* -*- c++ -*- */
/*
* gr-satnogs: SatNOGS GNU Radio Out-Of-Tree Module
*
* Copyright (C) 2019, Libre Space Foundation <http://libre.space>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <gnuradio/io_signature.h>
#include "frame_decoder_impl.h"
namespace gr
{
namespace satnogs
{
frame_decoder::sptr
frame_decoder::make (decoder::decoder_sptr decoder_object, int input_size)
{
return gnuradio::get_initial_sptr (new frame_decoder_impl (decoder_object,
input_size));
}
/*
* The private constructor
*/
frame_decoder_impl::frame_decoder_impl (decoder::decoder_sptr decoder_object,
int input_size) :
gr::sync_block ("frame_decoder",
gr::io_signature::make (1, 1, input_size),
gr::io_signature::make (0, 0, 0)),
d_decoder (decoder_object)
{
if (input_size != decoder_object->sizeof_input_item ()) {
throw std::invalid_argument (
"Size mismatch between the block input and the decoder");
}
message_port_register_in (pmt::mp ("reset"));
message_port_register_out (pmt::mp ("out"));
d_frame = new uint8_t[decoder_object->max_frame_len () * 8];
set_msg_handler (pmt::mp ("reset"),
boost::bind (&frame_decoder_impl::reset, this, _1));
}
/*
* Our virtual destructor.
*/
frame_decoder_impl::~frame_decoder_impl ()
{
}
void
frame_decoder_impl::reset (pmt::pmt_t m)
{
d_decoder->reset();
}
int
frame_decoder_impl::work (int noutput_items,
gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items)
{
const void *in = input_items[0];
pmt::pmt_t res = pmt::make_dict();
decoder_status_t status = d_decoder->decode (d_frame, in, noutput_items);
if (status.decoded_bits > 0) {
if (status.packed) {
res = pmt::dict_add(res, pmt::mp("pdu"),
pmt::make_blob (d_frame, (size_t)status.decoded_bits / 8));
}
else {
res = pmt::dict_add (
res, pmt::mp ("pdu"),
pmt::make_blob (d_frame, (size_t) status.decoded_bits));
}
res = pmt::dict_add (res, pmt::mp ("metadata"), status.metadata);
message_port_pub (pmt::mp ("out"), res);
}
// Tell runtime system how many output items we produced.
return status.consumed;
}
} /* namespace satnogs */
} /* namespace gr */

56
lib/frame_decoder_impl.h Normal file
View File

@ -0,0 +1,56 @@
/* -*- c++ -*- */
/*
* gr-satnogs: SatNOGS GNU Radio Out-Of-Tree Module
*
* Copyright (C) 2019, Libre Space Foundation <http://libre.space>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef INCLUDED_SATNOGS_FRAME_DECODER_IMPL_H
#define INCLUDED_SATNOGS_FRAME_DECODER_IMPL_H
#include <satnogs/frame_decoder.h>
namespace gr
{
namespace satnogs
{
class frame_decoder_impl : public frame_decoder
{
public:
frame_decoder_impl (decoder::decoder_sptr decoder_object, int input_size);
~frame_decoder_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);
private:
decoder::decoder_sptr d_decoder;
uint8_t *d_frame;
void
reset(pmt::pmt_t m);
};
} // namespace satnogs
} // namespace gr
#endif /* INCLUDED_SATNOGS_FRAME_DECODER_IMPL_H */

View File

@ -10,7 +10,8 @@
%template(whitening_sptr) boost::shared_ptr<gr::satnogs::whitening>;
%nodefaultctor gr::satnogs::decoder;
%template(decoder_sptr) boost::shared_ptr<gr::satnogs::decoder>;
%{
#include "satnogs/morse_tree.h"
@ -19,7 +20,9 @@
#include "satnogs/cw_to_symbol.h"
#include "satnogs/udp_msg_source.h"
#include "satnogs/tcp_rigctl_msg_source.h"
#include "satnogs/decoder.h"
#include "satnogs/doppler_correction_cc.h"
#include "satnogs/frame_decoder.h"
#include "satnogs/frame_encoder.h"
#include "satnogs/upsat_fsk_frame_acquisition.h"
#include "satnogs/upsat_fsk_frame_encoder.h"
@ -46,6 +49,7 @@
%include "satnogs/morse_tree.h"
%include "satnogs/decoder.h"
%include "satnogs/morse_decoder.h"
GR_SWIG_BLOCK_MAGIC2(satnogs, morse_decoder);
@ -62,6 +66,9 @@ GR_SWIG_BLOCK_MAGIC2(satnogs, udp_msg_source);
%include "satnogs/tcp_rigctl_msg_source.h"
GR_SWIG_BLOCK_MAGIC2(satnogs, tcp_rigctl_msg_source);
%include "satnogs/frame_decoder.h"
GR_SWIG_BLOCK_MAGIC2(satnogs, frame_decoder);
%include "satnogs/frame_encoder.h"
GR_SWIG_BLOCK_MAGIC2(satnogs, frame_encoder);