diff --git a/CMakeLists.txt b/CMakeLists.txt
index d05085e..4be403f 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -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
diff --git a/cmake/Modules/FindFec.cmake b/cmake/Modules/FindFec.cmake
new file mode 100644
index 0000000..d1197a8
--- /dev/null
+++ b/cmake/Modules/FindFec.cmake
@@ -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)
\ No newline at end of file
diff --git a/grc/CMakeLists.txt b/grc/CMakeLists.txt
index 1991aa8..81549ec 100644
--- a/grc/CMakeLists.txt
+++ b/grc/CMakeLists.txt
@@ -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
)
diff --git a/grc/satnogs_block_tree.xml b/grc/satnogs_block_tree.xml
index 17f5742..d80bfc0 100644
--- a/grc/satnogs_block_tree.xml
+++ b/grc/satnogs_block_tree.xml
@@ -30,4 +30,6 @@
satnogs_ax25_decoder_bm
satnogs_waterfall_sink
satnogs_quad_demod_filter_ff
+ satnogs_ccsds_rs_decoder_mm
+ satnogs_decoder_8b10b
\ No newline at end of file
diff --git a/grc/satnogs_ccsds_rs_decoder_mm.xml b/grc/satnogs_ccsds_rs_decoder_mm.xml
new file mode 100644
index 0000000..6b1a6c2
--- /dev/null
+++ b/grc/satnogs_ccsds_rs_decoder_mm.xml
@@ -0,0 +1,17 @@
+
+
+ CCSDS (255,223) RS Decoder
+ satnogs_ccsds_rs_decoder_mm
+ import satnogs
+ satnogs.ccsds_rs_decoder_mm()
+
+
+ in
+ message
+
+
+
+
diff --git a/grc/satnogs_decoder_8b10b.xml b/grc/satnogs_decoder_8b10b.xml
index 03c9b95..70c593c 100644
--- a/grc/satnogs_decoder_8b10b.xml
+++ b/grc/satnogs_decoder_8b10b.xml
@@ -1,35 +1,33 @@
- 8b10b Decoder
- satnogs_decoder_8b10b
- [SatNOGS]
- import satnogs
- satnogs.decoder_8b10b($control_symbol, $max_frame_len
- )
-
+ 8b10b Decoder
+ satnogs_decoder_8b10b
+ import satnogs
+ satnogs.decoder_8b10b($control_symbol, $max_frame_len)
+
-
- Control symbols
- control_symbol
- 0011111010
- string
-
+
+ Control symbols
+ control_symbol
+ 0011111010
+ string
+
-
- Maximum frame length
- max_frame_len
- 960
- int
-
+
+ Maximum frame length
+ max_frame_len
+ 960
+ int
+
-
- in
- byte
-
+
+ in
+ byte
+
-
+
diff --git a/include/satnogs/CMakeLists.txt b/include/satnogs/CMakeLists.txt
index d66a61a..b2c22de 100644
--- a/include/satnogs/CMakeLists.txt
+++ b/include/satnogs/CMakeLists.txt
@@ -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
)
\ No newline at end of file
diff --git a/include/satnogs/ccsds_rs_decoder_mm.h b/include/satnogs/ccsds_rs_decoder_mm.h
new file mode 100644
index 0000000..1efafd4
--- /dev/null
+++ b/include/satnogs/ccsds_rs_decoder_mm.h
@@ -0,0 +1,56 @@
+/* -*- c++ -*- */
+/*
+ * gr-satnogs: SatNOGS GNU Radio Out-Of-Tree Module
+ *
+ * Copyright (C) 2018, Libre Space Foundation
+ *
+ * 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 .
+ */
+
+
+#ifndef INCLUDED_SATNOGS_CCSDS_RS_DECODER_MM_H
+#define INCLUDED_SATNOGS_CCSDS_RS_DECODER_MM_H
+
+#include
+#include
+
+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 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 */
+
diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt
index 99857af..8bf9a01 100644
--- a/lib/CMakeLists.txt
+++ b/lib/CMakeLists.txt
@@ -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")
diff --git a/lib/ccsds_rs_decoder_mm_impl.cc b/lib/ccsds_rs_decoder_mm_impl.cc
new file mode 100644
index 0000000..1f94b09
--- /dev/null
+++ b/lib/ccsds_rs_decoder_mm_impl.cc
@@ -0,0 +1,97 @@
+/* -*- c++ -*- */
+/*
+ * gr-satnogs: SatNOGS GNU Radio Out-Of-Tree Module
+ *
+ * Copyright (C) 2018, Libre Space Foundation
+ *
+ * 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 .
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include
+#include "ccsds_rs_decoder_mm_impl.h"
+
+#include
+extern "C" {
+ #include
+}
+
+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 */
+
diff --git a/lib/ccsds_rs_decoder_mm_impl.h b/lib/ccsds_rs_decoder_mm_impl.h
new file mode 100644
index 0000000..0524218
--- /dev/null
+++ b/lib/ccsds_rs_decoder_mm_impl.h
@@ -0,0 +1,47 @@
+/* -*- c++ -*- */
+/*
+ * gr-satnogs: SatNOGS GNU Radio Out-Of-Tree Module
+ *
+ * Copyright (C) 2018, Libre Space Foundation
+ *
+ * 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 .
+ */
+
+#ifndef INCLUDED_SATNOGS_CCSDS_RS_DECODER_MM_IMPL_H
+#define INCLUDED_SATNOGS_CCSDS_RS_DECODER_MM_IMPL_H
+
+#include
+
+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 */
+
diff --git a/lib/decoder_8b10b_impl.cc b/lib/decoder_8b10b_impl.cc
index d555bd7..dcaa8b6 100644
--- a/lib/decoder_8b10b_impl.cc
+++ b/lib/decoder_8b10b_impl.cc
@@ -24,6 +24,8 @@
#include
#include "decoder_8b10b_impl.h"
+#include
+
#include
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;
}
diff --git a/lib/decoder_8b10b_impl.h b/lib/decoder_8b10b_impl.h
index 4bcf91a..a389042 100644
--- a/lib/decoder_8b10b_impl.h
+++ b/lib/decoder_8b10b_impl.h
@@ -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] =
{
diff --git a/swig/satnogs_swig0.i b/swig/satnogs_swig0.i
index 04654af..a374178 100644
--- a/swig/satnogs_swig0.i
+++ b/swig/satnogs_swig0.i
@@ -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);