Improve 8b10b decoder performance and add the CCSDS RS decoder

This commit is contained in:
Manolis Surligas 2018-01-30 01:44:16 +02:00
parent 699acdf53e
commit 02801c9a3f
14 changed files with 360 additions and 93 deletions

View File

@ -131,6 +131,7 @@ find_package(Volk REQUIRED)
find_package(OggVorbis REQUIRED)
find_package(PNG REQUIRED)
find_package(png++ REQUIRED)
find_package(Fec REQUIRED)
########################################################################
# Include or not into the module blocks for debugging

View File

@ -0,0 +1,25 @@
INCLUDE(FindPkgConfig)
PKG_CHECK_MODULES(PC_FEC fec)
FIND_PATH(
FEC_INCLUDE_DIRS
NAMES fec.h
HINTS $ENV{FEC_DIR}/include
${PC_FEC_INCLUDEDIR}
PATHS /usr/local/include
/usr/include
)
FIND_LIBRARY(
FEC_LIBRARIES
NAMES fec
HINTS $ENV{FEC_DIR}/lib
${PC_FEC_LIBDIR}
PATHS /usr/local/lib
/usr/local/lib64
/usr/lib
/usr/lib64
)
INCLUDE(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(FEC DEFAULT_MSG FEC_LIBRARIES FEC_INCLUDE_DIRS)

View File

@ -53,5 +53,6 @@ endif()
install(FILES
${enabled_blocks}
satnogs_quad_demod_filter_ff.xml
satnogs_decoder_8b10b.xml DESTINATION share/gnuradio/grc/blocks
satnogs_decoder_8b10b.xml
satnogs_ccsds_rs_decoder_mm.xml DESTINATION share/gnuradio/grc/blocks
)

View File

@ -30,4 +30,6 @@
<block>satnogs_ax25_decoder_bm</block>
<block>satnogs_waterfall_sink</block>
<block>satnogs_quad_demod_filter_ff</block>
<block>satnogs_ccsds_rs_decoder_mm</block>
<block>satnogs_decoder_8b10b</block>
</cat>

View File

@ -0,0 +1,17 @@
<?xml version="1.0"?>
<block>
<name>CCSDS (255,223) RS Decoder</name>
<key>satnogs_ccsds_rs_decoder_mm</key>
<import>import satnogs</import>
<make>satnogs.ccsds_rs_decoder_mm()</make>
<sink>
<name>in</name>
<type>message</type>
</sink>
<source>
<name>pdu</name>
<type>message</type>
</source>
</block>

View File

@ -1,35 +1,33 @@
<?xml version="1.0"?>
<block>
<name>8b10b Decoder</name>
<key>satnogs_decoder_8b10b</key>
<category>[SatNOGS]</category>
<import>import satnogs</import>
<make>satnogs.decoder_8b10b($control_symbol, $max_frame_len
)
</make>
<name>8b10b Decoder</name>
<key>satnogs_decoder_8b10b</key>
<import>import satnogs</import>
<make>satnogs.decoder_8b10b($control_symbol, $max_frame_len)
</make>
<param>
<name>Control symbols</name>
<key>control_symbol</key>
<value>0011111010</value>
<type>string</type>
</param>
<param>
<name>Control symbols</name>
<key>control_symbol</key>
<value>0011111010</value>
<type>string</type>
</param>
<param>
<name>Maximum frame length</name>
<key>max_frame_len</key>
<value>960</value>
<type>int</type>
</param>
<param>
<name>Maximum frame length</name>
<key>max_frame_len</key>
<value>960</value>
<type>int</type>
</param>
<sink>
<name>in</name>
<type>byte</type>
</sink>
<sink>
<name>in</name>
<type>byte</type>
</sink>
<source>
<name>pdu</name>
<type>message</type>
</source>
<source>
<name>pdu</name>
<type>message</type>
</source>
</block>

View File

@ -68,5 +68,6 @@ endif()
install(FILES
${HEADER_FILES}
quad_demod_filter_ff.h
decoder_8b10b.h DESTINATION include/satnogs
decoder_8b10b.h
ccsds_rs_decoder_mm.h DESTINATION include/satnogs
)

View File

@ -0,0 +1,56 @@
/* -*- c++ -*- */
/*
* gr-satnogs: SatNOGS GNU Radio Out-Of-Tree Module
*
* Copyright (C) 2018, Libre Space Foundation <http://librespacefoundation.org/>
*
* 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_CCSDS_RS_DECODER_MM_H
#define INCLUDED_SATNOGS_CCSDS_RS_DECODER_MM_H
#include <satnogs/api.h>
#include <gnuradio/block.h>
namespace gr {
namespace satnogs {
/*!
* \brief <+description of block+>
* \ingroup satnogs
*
*/
class SATNOGS_API ccsds_rs_decoder_mm : virtual public gr::block
{
public:
typedef boost::shared_ptr<ccsds_rs_decoder_mm> sptr;
/*!
* \brief Return a shared_ptr to a new instance of satnogs::ccsds_rs_decoder_mm.
*
* To avoid accidental use of raw pointers, satnogs::ccsds_rs_decoder_mm's
* constructor is in a private implementation
* class. satnogs::ccsds_rs_decoder_mm::make is the public interface for
* creating new instances.
*/
static sptr make();
};
} // namespace satnogs
} // namespace gr
#endif /* INCLUDED_SATNOGS_CCSDS_RS_DECODER_MM_H */

View File

@ -29,6 +29,7 @@ include_directories(
${OGG_INCLUDE_DIR}
${PNG_INCLUDE_DIR}
${png++_INCLUDE_DIRS}
${FEC_INCLUDE_DIRS}
)
link_directories(${Boost_LIBRARY_DIRS})
@ -66,7 +67,8 @@ list(APPEND satnogs_sources
frame_file_sink_impl.cc
iq_sink_impl.cc
quad_demod_filter_ff_impl.cc
decoder_8b10b_impl.cc)
decoder_8b10b_impl.cc
ccsds_rs_decoder_mm_impl.cc)
if(${INCLUDE_DEBUG_BLOCKS})
list(APPEND satnogs_sources ${satnogs_debug_sources})
@ -88,6 +90,7 @@ target_link_libraries(gnuradio-satnogs
${OGGVORBIS_LIBRARIES}
${PNG_LIBRARIES}
${png++_LIBRARIES}
${FEC_LIBRARIES}
)
set_target_properties(gnuradio-satnogs PROPERTIES DEFINE_SYMBOL "gnuradio_satnogs_EXPORTS")

View File

@ -0,0 +1,97 @@
/* -*- c++ -*- */
/*
* gr-satnogs: SatNOGS GNU Radio Out-Of-Tree Module
*
* Copyright (C) 2018, Libre Space Foundation <http://librespacefoundation.org/>
*
* 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 "ccsds_rs_decoder_mm_impl.h"
#include <satnogs/log.h>
extern "C" {
#include <fec.h>
}
namespace gr {
namespace satnogs {
ccsds_rs_decoder_mm::sptr
ccsds_rs_decoder_mm::make()
{
return gnuradio::get_initial_sptr
(new ccsds_rs_decoder_mm_impl());
}
/*
* The private constructor
*/
ccsds_rs_decoder_mm_impl::ccsds_rs_decoder_mm_impl()
: gr::block("ccsds_rs_decoder_mm",
gr::io_signature::make(0, 0, 0),
gr::io_signature::make(0, 0, 0))
{
message_port_register_in(pmt::mp("in"));
message_port_register_out(pmt::mp("pdu"));
set_msg_handler (
pmt::mp ("in"),
boost::bind (&ccsds_rs_decoder_mm_impl::message_handler, this, _1));
}
void
ccsds_rs_decoder_mm_impl::message_handler (pmt::pmt_t m)
{
uint8_t data[255];
int erasures[255];
const uint8_t *data_ref;
size_t data_len;
const int *erasures_ref;
size_t erasures_len;
pmt::pmt_t pmt_data = pmt::dict_ref(m, pmt::mp("pdu"), pmt::PMT_NIL);
pmt::pmt_t pmt_erasures = pmt::dict_ref(m, pmt::mp("erasures"),
pmt::PMT_NIL);
if (pmt::equal (pmt::PMT_NIL, pmt_data)
|| pmt::equal (pmt::PMT_NIL, pmt_erasures)) {
LOG_ERROR("Invalid message format.");
}
data_ref = pmt::u8vector_elements(pmt_data, data_len);
memcpy(data, data_ref, data_len);
erasures_len = pmt::blob_length(pmt_erasures);
erasures_ref = pmt::s32vector_elements(pmt_erasures, erasures_len);
memcpy(erasures, erasures_ref, erasures_len * sizeof(int));
decode_rs_ccsds(data, erasures, (int)erasures_len, (int)(255 - data_len));
message_port_pub(pmt::mp("pdu"), pmt::make_blob(data, 223));
}
/*
* Our virtual destructor.
*/
ccsds_rs_decoder_mm_impl::~ccsds_rs_decoder_mm_impl()
{
}
} /* namespace satnogs */
} /* namespace gr */

View File

@ -0,0 +1,47 @@
/* -*- c++ -*- */
/*
* gr-satnogs: SatNOGS GNU Radio Out-Of-Tree Module
*
* Copyright (C) 2018, Libre Space Foundation <http://librespacefoundation.org/>
*
* 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_CCSDS_RS_DECODER_MM_IMPL_H
#define INCLUDED_SATNOGS_CCSDS_RS_DECODER_MM_IMPL_H
#include <satnogs/ccsds_rs_decoder_mm.h>
namespace gr
{
namespace satnogs
{
class ccsds_rs_decoder_mm_impl : public ccsds_rs_decoder_mm
{
private:
void
message_handler(pmt::pmt_t m);
public:
ccsds_rs_decoder_mm_impl ();
~ccsds_rs_decoder_mm_impl ();
};
} // namespace satnogs
} // namespace gr
#endif /* INCLUDED_SATNOGS_CCSDS_RS_DECODER_MM_IMPL_H */

View File

@ -24,6 +24,8 @@
#include <gnuradio/io_signature.h>
#include "decoder_8b10b_impl.h"
#include <satnogs/log.h>
#include <gnuradio/blocks/count_bits.h>
namespace gr
@ -48,6 +50,7 @@ namespace gr
gr::io_signature::make (1, 1, sizeof(char)),
gr::io_signature::make (0, 0, 0)),
d_max_frame_len (max_frame_len),
d_erasure_cnt (0),
d_control_symbol_pos (0),
d_control_symbol_neg (0),
d_data_reg (0),
@ -55,19 +58,19 @@ namespace gr
d_wrong_bits_neg (0),
d_nwrong (0),
d_nwrong_neg (0),
d_10b_cnt (1),
d_word (0),
d_word_cnt (0),
d_state (IN_SYNC)
{
message_port_register_out (pmt::mp ("pdu"));
set_output_multiple(10);
if (!set_access_code (control_symbol)) {
GR_LOG_ERROR(d_logger, "control_symbol is not 10 bits");
throw std::out_of_range ("control_symbol is not 10 bits");
}
d_8b_words = (uint8_t*) malloc (d_max_frame_len / 10);
d_erasures = (uint8_t*) malloc (d_max_frame_len / 10);
d_8b_words = new uint8_t [d_max_frame_len / 10];
d_erasures_indexes = new int [d_max_frame_len / 10];
}
/*
@ -75,6 +78,8 @@ namespace gr
*/
decoder_8b10b_impl::~decoder_8b10b_impl ()
{
delete [] d_8b_words;
delete [] d_erasures_indexes;
}
bool
@ -128,8 +133,22 @@ namespace gr
}
/* report that there is erasure to this 10 bits */
d_8b_words[write_pos - 1] = min_pos;
d_erasures[write_pos - 1] = (min_dist != 0);
d_8b_words[write_pos] = min_pos;
/* If we did not found a perfect match, mark this index as erasure */
if(min_dist != 0) {
d_erasures_indexes[d_erasure_cnt++] = write_pos;
}
}
static inline uint16_t
pack_10b_word(const uint8_t *in)
{
return ((in[0] & 0x1) << 9) | ((in[1] & 0x1) << 8)
| ((in[2] & 0x1) << 7) | ((in[3] & 0x1) << 6)
| ((in[4] & 0x1) << 5) | ((in[5] & 0x1) << 4)
| ((in[6] & 0x1) << 3) | ((in[7] & 0x1) << 2)
| ((in[8] & 0x1) << 1) | (in[9] & 0x1);
}
int
@ -137,64 +156,55 @@ namespace gr
gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items)
{
int i;
const uint8_t *in = (const uint8_t *) input_items[0];
for (int i = 0; i < noutput_items; i++) {
/* Search for the Comma symbol */
if(d_state == IN_SYNC) {
for (i = 0; i < noutput_items; i++) {
d_data_reg = (d_data_reg << 1) | (in[i] & 0x1);
d_wrong_bits = (d_data_reg ^ d_control_symbol_pos) & 0x3FF;
d_wrong_bits_neg = (d_data_reg ^ d_control_symbol_neg) & 0x3FF;
d_nwrong = gr::blocks::count_bits16 (d_wrong_bits);
d_nwrong_neg = gr::blocks::count_bits16 (d_wrong_bits_neg);
d_data_reg = (d_data_reg << 1) | (in[i] & 0x1);
switch (d_state)
{
case IN_SYNC:
d_wrong_bits = (d_data_reg ^ d_control_symbol_pos) & 0x3FF;
d_wrong_bits_neg = (d_data_reg ^ d_control_symbol_neg) & 0x3FF;
d_nwrong = gr::blocks::count_bits16 (d_wrong_bits);
d_nwrong_neg = gr::blocks::count_bits16 (d_wrong_bits_neg);
/* we found the controls symbol */
if ((d_nwrong == 0) || (d_nwrong_neg == 0)) {
d_state = DECODING;
}
break;
case DECODING:
if (d_10b_cnt <= d_max_frame_len) {
if ((d_10b_cnt % 10 == 0) && (d_10b_cnt < d_max_frame_len)) {
d_word = (d_data_reg & 0x3FF);
/* Revert 10b to 8b and accumulate! */
process_10b (d_10b_cnt / 10);
}
if (d_10b_cnt == d_max_frame_len) {
d_state = IN_SYNC;
d_10b_cnt = 0; // one is added after the if
d_word = 0; // zero it after you use it to prepare for next round
pmt::pmt_t data = pmt::init_u8vector (d_max_frame_len / 10,
d_8b_words);
pmt::pmt_t erasures = pmt::init_u8vector (d_max_frame_len / 10,
d_erasures);
pmt::pmt_t out = pmt::cons (data, erasures);
message_port_pub (pmt::mp ("pdu"), out);
}
d_10b_cnt++;
}
break;
default:
GR_LOG_ERROR(d_logger, "Invalid state");
/* we found the controls symbol */
if ((d_nwrong == 0) || (d_nwrong_neg == 0)) {
d_erasure_cnt = 0;
d_word_cnt = 0;
d_state = DECODING;
return i + 1;
}
}
return noutput_items;
}
// Tell runtime system how many output items we produced.
/*
* From now one, we have a SYNC so we process the data
* in chunks of 10 bits
*/
for(i = 0; i < noutput_items / 10; i++) {
d_word = pack_10b_word(&in[i * 10]);
/* Revert 10b to 8b and accumulate! */
process_10b (d_word_cnt);
d_word_cnt++;
if(d_word_cnt == d_max_frame_len) {
d_state = IN_SYNC;
pmt::pmt_t data = pmt::init_u8vector (d_max_frame_len / 10,
d_8b_words);
pmt::pmt_t erasures = pmt::init_s32vector (d_erasure_cnt,
d_erasures_indexes);
pmt::pmt_t out = pmt::make_dict();
pmt::dict_add(out, pmt::mp("pdu"), data);
pmt::dict_add(out, pmt::mp("erasures"), erasures);
message_port_pub (pmt::mp ("pdu"), out);
return (i+1) * 10;
}
}
return noutput_items;
}

View File

@ -31,17 +31,20 @@ namespace gr
class decoder_8b10b_impl : public decoder_8b10b
{
private:
size_t d_max_frame_len;
const size_t d_max_frame_len;
size_t d_erasure_cnt;
uint16_t d_control_symbol_pos;
uint16_t d_control_symbol_neg;
uint16_t d_data_reg;
uint16_t d_wrong_bits, d_wrong_bits_neg;
uint8_t d_nwrong, d_nwrong_neg;
uint16_t d_10b_cnt;
uint16_t d_wrong_bits;
uint16_t d_wrong_bits_neg;
uint8_t d_nwrong;
uint8_t d_nwrong_neg;
uint16_t d_word;
size_t d_word_cnt;
uint8_t *d_8b_words;
uint8_t *d_erasures;
int *d_erasures_indexes;
int d_lookup_8b10b[2][256] =
{

View File

@ -33,6 +33,7 @@
#include "satnogs/iq_sink.h"
#include "satnogs/quad_demod_filter_ff.h"
#include "satnogs/decoder_8b10b.h"
#include "satnogs/ccsds_rs_decoder_mm.h"
%}
@ -99,7 +100,12 @@ GR_SWIG_BLOCK_MAGIC2(satnogs, frame_file_sink);
%include "satnogs/iq_sink.h"
GR_SWIG_BLOCK_MAGIC2(satnogs, iq_sink);
%include "satnogs/quad_demod_filter_ff.h"
GR_SWIG_BLOCK_MAGIC2(satnogs, quad_demod_filter_ff);
%include "satnogs/decoder_8b10b.h"
GR_SWIG_BLOCK_MAGIC2(satnogs, decoder_8b10b);
%include "satnogs/ccsds_rs_decoder_mm.h"
GR_SWIG_BLOCK_MAGIC2(satnogs, ccsds_rs_decoder_mm);