From 5d4884cf0d9d1ee04f026c553d041f0eb8c45440 Mon Sep 17 00:00:00 2001 From: Manolis Surligas Date: Sun, 24 Jan 2016 21:43:17 +0200 Subject: [PATCH] Add a generic clear text message sink. For now the generic clear text message sink just prints the decoded clear text messages in the stdout. In the future and depending the needs of the project, the clear text messages can be forwarded at other services on the same host or via the network. Also the debug message source block now supports injection of artificial errors, for more robust decoding of the Morse decoder block. --- .gitignore | 1 + README.md | 6 +-- examples/test_morse_decoder.grc | 59 +++++++++++++++++++++++-- grc/CMakeLists.txt | 3 +- grc/satnogs_clear_text_msg_sink.xml | 13 ++++++ grc/satnogs_cw_matched_filter_ff.xml | 63 ++++++++++++++------------- grc/satnogs_morse_debug_source.xml | 57 +++++++++++++++--------- grc/satnogs_morse_decoder.xml | 35 ++++++++------- include/satnogs/CMakeLists.txt | 3 +- include/satnogs/clear_text_msg_sink.h | 59 +++++++++++++++++++++++++ include/satnogs/morse_debug_source.h | 12 ++++- lib/CMakeLists.txt | 3 +- lib/clear_text_msg_sink_impl.cc | 61 ++++++++++++++++++++++++++ lib/clear_text_msg_sink_impl.h | 46 +++++++++++++++++++ lib/morse_debug_source_impl.cc | 39 ++++++++++++++--- lib/morse_debug_source_impl.h | 5 ++- lib/morse_decoder_impl.cc | 7 +-- swig/satnogs_swig.i | 3 ++ 18 files changed, 387 insertions(+), 88 deletions(-) create mode 100644 grc/satnogs_clear_text_msg_sink.xml create mode 100644 include/satnogs/clear_text_msg_sink.h create mode 100644 lib/clear_text_msg_sink_impl.cc create mode 100644 lib/clear_text_msg_sink_impl.h diff --git a/.gitignore b/.gitignore index f2f50e3..4e2c807 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,4 @@ apps/*.py .cproject .pyproject .pydevproject +nbproject/ \ No newline at end of file diff --git a/README.md b/README.md index ec25485..cab3341 100644 --- a/README.md +++ b/README.md @@ -5,9 +5,9 @@ for decoding signals from various scientific and academic sattelites. ## Install ### Requirements -1. GNU Radio -2. CMake -3. G++ +1. GNU Radio ( > 3.7.2 ) +2. CMake ( > 3.1) +3. G++ (with C++11 support) 4. VOLK 5. git diff --git a/examples/test_morse_decoder.grc b/examples/test_morse_decoder.grc index 23d9000..2338e06 100644 --- a/examples/test_morse_decoder.grc +++ b/examples/test_morse_decoder.grc @@ -109,7 +109,7 @@ - satnogs_morse_debug_source + satnogs_clear_text_msg_sink alias @@ -126,6 +126,41 @@ _enabled True + + _coordinate + (944, 184) + + + _rotation + 0 + + + id + satnogs_clear_text_msg_sink_0 + + + + satnogs_morse_debug_source + + alias + + + + comment + + + + affinity + + + + _enabled + True + + + p + 0.1 + _coordinate (240, 196) @@ -138,6 +173,10 @@ id satnogs_morse_debug_source_0 + + errors + True + maxoutbuf 0 @@ -148,7 +187,7 @@ debug_seq - "HELLO EARTH WORLD" + "HELLO EARTH WORLD 123456789" @@ -171,7 +210,7 @@ _coordinate - (752, 276) + (672, 180) _rotation @@ -181,6 +220,14 @@ id satnogs_morse_decoder_0 + + maxoutbuf + 0 + + + minoutbuf + 0 + unrecognized_char ord('#') @@ -192,4 +239,10 @@ out in + + satnogs_morse_decoder_0 + satnogs_clear_text_msg_sink_0 + out + in + diff --git a/grc/CMakeLists.txt b/grc/CMakeLists.txt index e7f9f22..5564406 100644 --- a/grc/CMakeLists.txt +++ b/grc/CMakeLists.txt @@ -19,5 +19,6 @@ install(FILES satnogs_cw_matched_filter_ff.xml satnogs_morse_decoder.xml - satnogs_morse_debug_source.xml DESTINATION share/gnuradio/grc/blocks + satnogs_morse_debug_source.xml + satnogs_clear_text_msg_sink.xml DESTINATION share/gnuradio/grc/blocks ) diff --git a/grc/satnogs_clear_text_msg_sink.xml b/grc/satnogs_clear_text_msg_sink.xml new file mode 100644 index 0000000..497c8f5 --- /dev/null +++ b/grc/satnogs_clear_text_msg_sink.xml @@ -0,0 +1,13 @@ + + + Clear Text Message Sink + satnogs_clear_text_msg_sink + satnogs + import satnogs + satnogs.clear_text_msg_sink() + + + in + message + + diff --git a/grc/satnogs_cw_matched_filter_ff.xml b/grc/satnogs_cw_matched_filter_ff.xml index 6143b75..7888e22 100644 --- a/grc/satnogs_cw_matched_filter_ff.xml +++ b/grc/satnogs_cw_matched_filter_ff.xml @@ -1,37 +1,38 @@ - CW Matched Filter - satnogs_cw_matched_filter_ff - satnogs - import satnogs - satnogs.cw_matched_filter_ff($sampling_rate, $carrier_freq, $wpm) + CW Matched Filter + satnogs_cw_matched_filter_ff + satnogs + import satnogs + satnogs.cw_matched_filter_ff($sampling_rate, $carrier_freq, $wpm) + - - Sampling Rate - sampling_rate - real - - - - Audio Frequency (Hz) - carrier_freq - real - - - - Words per Minute - wpm - 20 - int - + + Sampling Rate + sampling_rate + real + - - in - float - + + Audio Frequency (Hz) + carrier_freq + real + - - out - float - + + Words per Minute + wpm + 20 + int + + + + in + float + + + + out + float + diff --git a/grc/satnogs_morse_debug_source.xml b/grc/satnogs_morse_debug_source.xml index 1993acd..cdc01c9 100644 --- a/grc/satnogs_morse_debug_source.xml +++ b/grc/satnogs_morse_debug_source.xml @@ -1,24 +1,41 @@ - Morse code Debug Source - satnogs_morse_debug_source - satnogs - import satnogs - satnogs.morse_debug_source($debug_seq) - - - Sentence - debug_seq - "HELLO WORLD" - string - + Morse code Debug Source + satnogs_morse_debug_source + satnogs + import satnogs + satnogs.morse_debug_source($debug_seq, $errors, $p) - - out - message - + + Sentence + debug_seq + "HELLO WORLD" + string + + + + Inject Errors + errors + enum + + + + + + Error probability + p + 0.1 + real + + + + out + message + diff --git a/grc/satnogs_morse_decoder.xml b/grc/satnogs_morse_decoder.xml index 9eb7a32..52b41e6 100644 --- a/grc/satnogs_morse_decoder.xml +++ b/grc/satnogs_morse_decoder.xml @@ -1,21 +1,26 @@ - Morse Decoder - satnogs_morse_decoder - satnogs - import satnogs - satnogs.morse_decoder($unrecognized_char) + Morse Decoder + satnogs_morse_decoder + satnogs + import satnogs + satnogs.morse_decoder($unrecognized_char) - - Unrecognized character - unrecognized_char - ord('#') - int - + + Unrecognized character + unrecognized_char + ord('#') + int + - - in - message - + + in + message + + + + out + message + diff --git a/include/satnogs/CMakeLists.txt b/include/satnogs/CMakeLists.txt index ee0b40b..c512fa6 100644 --- a/include/satnogs/CMakeLists.txt +++ b/include/satnogs/CMakeLists.txt @@ -28,5 +28,6 @@ install(FILES morse_tree.h morse.h morse_decoder.h - morse_debug_source.h DESTINATION include/satnogs + morse_debug_source.h + clear_text_msg_sink.h DESTINATION include/satnogs ) diff --git a/include/satnogs/clear_text_msg_sink.h b/include/satnogs/clear_text_msg_sink.h new file mode 100644 index 0000000..4164581 --- /dev/null +++ b/include/satnogs/clear_text_msg_sink.h @@ -0,0 +1,59 @@ +/* -*- c++ -*- */ +/* + * gr-satnogs: SatNOGS GNU Radio Out-Of-Tree Module + * + * Copyright (C) 2016, 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_CLEAR_TEXT_MSG_SINK_H +#define INCLUDED_SATNOGS_CLEAR_TEXT_MSG_SINK_H + +#include +#include + +namespace gr +{ + namespace satnogs + { + + /*! + * \brief Block accepting clear text messages from various decoders. + * Its purpose is to forward these messages at other services, programs, + * stdout, etc, + * + * \ingroup satnogs + * + */ + class SATNOGS_API clear_text_msg_sink : virtual public gr::block + { + public: + typedef boost::shared_ptr sptr; + + /*! + * \brief Block accepting clear text messages from various decoders. + * Its purpose is to forward these messages at other services, programs, + * stdout, etc, + * + */ + static sptr + make (); + }; + + } // namespace satnogs +} // namespace gr + +#endif /* INCLUDED_SATNOGS_CLEAR_TEXT_MSG_SINK_H */ + diff --git a/include/satnogs/morse_debug_source.h b/include/satnogs/morse_debug_source.h index c2939c1..a972d6b 100644 --- a/include/satnogs/morse_debug_source.h +++ b/include/satnogs/morse_debug_source.h @@ -28,7 +28,9 @@ namespace gr { namespace satnogs { /*! - * \brief A Morse debug source block + * \brief A Morse debug source block that supports injection of random + * errors based on a Bernulli distribution with probability p. + * * \ingroup satnogs * */ @@ -40,10 +42,16 @@ namespace gr { /*! * \brief A Morse debug source block that produces messages corresponding * to Morse symbols, based on the given debug_seq string. + * This block can also inject random errors, based on a Bernoulli + * distribution. * * @param debug_seq A string containing the debug sentence + * @param inject_errors if set the debug source block will produce + * errors that follow a Bernoulli distribution + * @param error_prob the probability p of error for the Bernulli distribution */ - static sptr make(const std::string& debug_seq); + static sptr make(const std::string& debug_seq, bool inject_errors = false, + float error_prob = 0.1); }; } // namespace satnogs diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index 61851b1..d7c46cb 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -28,7 +28,8 @@ list(APPEND satnogs_sources cw_matched_filter_ff_impl.cc morse_tree.cc morse_decoder_impl.cc - morse_debug_source_impl.cc ) + morse_debug_source_impl.cc + clear_text_msg_sink_impl.cc ) set(satnogs_sources "${satnogs_sources}" PARENT_SCOPE) if(NOT satnogs_sources) diff --git a/lib/clear_text_msg_sink_impl.cc b/lib/clear_text_msg_sink_impl.cc new file mode 100644 index 0000000..cc633a6 --- /dev/null +++ b/lib/clear_text_msg_sink_impl.cc @@ -0,0 +1,61 @@ +/* -*- c++ -*- */ +/* + * gr-satnogs: SatNOGS GNU Radio Out-Of-Tree Module + * + * Copyright (C) 2016, 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 "clear_text_msg_sink_impl.h" + +namespace gr { + namespace satnogs { + + clear_text_msg_sink::sptr + clear_text_msg_sink::make() + { + return gnuradio::get_initial_sptr + (new clear_text_msg_sink_impl()); + } + + void + clear_text_msg_sink_impl::msg_handler (pmt::pmt_t msg) + { + std::string s((const char *)pmt::blob_data(msg), pmt::blob_length(msg)); + std::cout << s << " " << std::endl; + } + + /* + * The private constructor + */ + clear_text_msg_sink_impl::clear_text_msg_sink_impl() + : gr::block("clear_text_msg_sink", + gr::io_signature::make(0, 0, 0), + gr::io_signature::make(0, 0, 0)) + { + message_port_register_in(pmt::mp("in")); + set_msg_handler ( + pmt::mp ("in"), + boost::bind (&clear_text_msg_sink_impl::msg_handler, this, _1)); + } + + } /* namespace satnogs */ +} /* namespace gr */ + diff --git a/lib/clear_text_msg_sink_impl.h b/lib/clear_text_msg_sink_impl.h new file mode 100644 index 0000000..51c6364 --- /dev/null +++ b/lib/clear_text_msg_sink_impl.h @@ -0,0 +1,46 @@ +/* -*- c++ -*- */ +/* + * gr-satnogs: SatNOGS GNU Radio Out-Of-Tree Module + * + * Copyright (C) 2016, 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_CLEAR_TEXT_MSG_SINK_IMPL_H +#define INCLUDED_SATNOGS_CLEAR_TEXT_MSG_SINK_IMPL_H + +#include + +namespace gr +{ + namespace satnogs + { + + class clear_text_msg_sink_impl : public clear_text_msg_sink + { + private: + void + msg_handler(pmt::pmt_t msg); + + public: + clear_text_msg_sink_impl (); + + }; + + } // namespace satnogs +} // namespace gr + +#endif /* INCLUDED_SATNOGS_CLEAR_TEXT_MSG_SINK_IMPL_H */ + diff --git a/lib/morse_debug_source_impl.cc b/lib/morse_debug_source_impl.cc index 1808b48..7fd4425 100644 --- a/lib/morse_debug_source_impl.cc +++ b/lib/morse_debug_source_impl.cc @@ -25,24 +25,31 @@ #include #include "morse_debug_source_impl.h" #include +#include namespace gr { namespace satnogs { morse_debug_source::sptr - morse_debug_source::make(const std::string& debug_seq) + morse_debug_source::make(const std::string& debug_seq, + bool inject_errors, + float error_prob) { return gnuradio::get_initial_sptr - (new morse_debug_source_impl(debug_seq)); + (new morse_debug_source_impl(debug_seq, inject_errors, error_prob)); } /* * The private constructor */ - morse_debug_source_impl::morse_debug_source_impl(std::string debug_seq) + morse_debug_source_impl::morse_debug_source_impl(std::string debug_seq, + bool inject_errors, + float error_prob) : gr::block("morse_debug_source", gr::io_signature::make(0, 0, 0), gr::io_signature::make(0, 0, 0)), + d_inject_errors(inject_errors), + d_p(error_prob), d_run(true), d_chars { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', @@ -81,12 +88,17 @@ namespace gr { size_t idx; std::string s; char c; + std::random_device rd; + std::mt19937 gen(rd()); + std::bernoulli_distribution error_distr(d_p); + bool inject_error; size_t len = sentence.length(); pmt::pmt_t port = pmt::mp("out"); - std::this_thread::sleep_for(std::chrono::milliseconds(2000)); + std::this_thread::sleep_for(std::chrono::milliseconds(1000)); + while(d_run) { - /* Not the best approach, but hey, this is only for debug */ + /* Not the best approach, but hey, this is only for debug */ for(i = 0; i < len; i++){ c = std::toupper(sentence[i]); if(c == ' '){ @@ -95,13 +107,26 @@ namespace gr { idx = find_char_idx(d_chars, sizeof(d_chars), c); if(idx != sizeof(d_chars)){ + s = d_symbols[idx]; + /* Get from the random distribution if an error should be injected */ + inject_error = d_inject_errors && error_distr(gen); for(j = 0; j < s.length(); j++) { if(s[j] == '.'){ - message_port_pub(port, pmt::from_long(MORSE_DOT)); + if(inject_error){ + message_port_pub(port, pmt::from_long(MORSE_DASH)); + } + else{ + message_port_pub(port, pmt::from_long(MORSE_DOT)); + } } else{ - message_port_pub(port, pmt::from_long(MORSE_DASH)); + if(inject_error){ + message_port_pub(port, pmt::from_long(MORSE_DOT)); + } + else{ + message_port_pub(port, pmt::from_long(MORSE_DASH)); + } } std::this_thread::sleep_for(std::chrono::milliseconds(100)); } diff --git a/lib/morse_debug_source_impl.h b/lib/morse_debug_source_impl.h index 5c1f7e2..c88d70a 100644 --- a/lib/morse_debug_source_impl.h +++ b/lib/morse_debug_source_impl.h @@ -32,6 +32,8 @@ namespace gr { class morse_debug_source_impl : public morse_debug_source { private: + const bool d_inject_errors; + const float d_p; bool d_run; const char d_chars[36]; const std::vector d_symbols; @@ -41,7 +43,8 @@ namespace gr { send_debug_msg(std::string sentence); public: - morse_debug_source_impl(std::string debug_seq); + morse_debug_source_impl(std::string debug_seq, bool inject_errors, + float error_prob); ~morse_debug_source_impl(); }; diff --git a/lib/morse_decoder_impl.cc b/lib/morse_decoder_impl.cc index fc014b5..f1a90b6 100644 --- a/lib/morse_decoder_impl.cc +++ b/lib/morse_decoder_impl.cc @@ -49,7 +49,6 @@ namespace gr case MORSE_DOT: case MORSE_DASH: case MORSE_S_SPACE: - LOG_DEBUG("Received %d", s); res = d_morse_tree.received_symbol(s); break; /* @@ -59,7 +58,8 @@ namespace gr case MORSE_L_SPACE: str = d_morse_tree.get_word(); d_morse_tree.reset(); - std::cout << "Received word: " << str << std::endl; + message_port_pub(pmt::mp("out"), pmt::make_blob(str.c_str(), + str.length())); break; default: LOG_ERROR("Unknown Morse symbol"); @@ -91,8 +91,9 @@ namespace gr gr::io_signature::make (0, 0, 0)), d_morse_tree (unrecognized_char) { - /* Register the input msg handler */ + /* Register the input and output msg handler */ message_port_register_in (pmt::mp ("in")); + message_port_register_out(pmt::mp("out")); set_msg_handler ( pmt::mp ("in"), boost::bind (&morse_decoder_impl::symbol_msg_handler, this, _1)); diff --git a/swig/satnogs_swig.i b/swig/satnogs_swig.i index ad58389..240d84f 100644 --- a/swig/satnogs_swig.i +++ b/swig/satnogs_swig.i @@ -12,6 +12,7 @@ #include "satnogs/morse_tree.h" #include "satnogs/morse_decoder.h" #include "satnogs/morse_debug_source.h" +#include "satnogs/clear_text_msg_sink.h" %} %include "satnogs/cw_matched_filter_ff.h" @@ -21,3 +22,5 @@ GR_SWIG_BLOCK_MAGIC2(satnogs, cw_matched_filter_ff); GR_SWIG_BLOCK_MAGIC2(satnogs, morse_decoder); %include "satnogs/morse_debug_source.h" GR_SWIG_BLOCK_MAGIC2(satnogs, morse_debug_source); +%include "satnogs/clear_text_msg_sink.h" +GR_SWIG_BLOCK_MAGIC2(satnogs, clear_text_msg_sink);