diff --git a/grc/CMakeLists.txt b/grc/CMakeLists.txt
index 07917f9..e1fbdf7 100644
--- a/grc/CMakeLists.txt
+++ b/grc/CMakeLists.txt
@@ -24,6 +24,7 @@ list(APPEND debug_blocks
satnogs_debug_msg_source.xml
satnogs_debug_msg_source_raw.xml
satnogs_leo_channel.xml
+ satnogs_cw_encoder.xml
)
list(APPEND enabled_blocks
@@ -50,7 +51,6 @@ install(FILES
${enabled_blocks}
satnogs_ogg_source.xml
satnogs_noaa_apt_sink.xml
- satnogs_frame_file_sink.xml
+ satnogs_frame_file_sink.xml DESTINATION share/gnuradio/grc/blocks
satnogs_iq_sink.xml
- satnogs_cw_encoder.xml DESTINATION share/gnuradio/grc/blocks
)
diff --git a/grc/satnogs_cw_encoder.xml b/grc/satnogs_cw_encoder.xml
index c3d5288..6ac5c15 100644
--- a/grc/satnogs_cw_encoder.xml
+++ b/grc/satnogs_cw_encoder.xml
@@ -1,38 +1,39 @@
- cw_encoder
+ CW Encoder
satnogs_cw_encoder
- [satnogs]
+ [SatNOGS]/Debug
import satnogs
satnogs.cw_encoder($samp_rate, $cw_freq, $wpm)
-
+
- ...
- ...
- ...
+ Sample Rate
+ samp_rate
+ samp_rate
+ real
+
+
+
+ CW Frequency
+ cw_freq
+ 700
+ real
+
+
+
+ Words per minute
+ wpm
+ 20
+ int
-
- in
-
+ symbol
+ message
-
out
-
+ complex
diff --git a/include/satnogs/CMakeLists.txt b/include/satnogs/CMakeLists.txt
index 63b6843..d8e1ee5 100644
--- a/include/satnogs/CMakeLists.txt
+++ b/include/satnogs/CMakeLists.txt
@@ -21,10 +21,11 @@
# Install public header files
########################################################################
list(APPEND DEBUG_HEADER_FILES
- morse_debug_source.h
- debug_msg_source_raw.h
- debug_msg_source.h
- leo_channel.h
+ morse_debug_source.h
+ debug_msg_source_raw.h
+ debug_msg_source.h
+ leo_channel.h
+ cw_encoder.h
)
list(APPEND HEADER_FILES
@@ -64,7 +65,6 @@ install(FILES
${HEADER_FILES}
ogg_source.h
noaa_apt_sink.h
- frame_file_sink.h
+ frame_file_sink.h DESTINATION include/satnogs
iq_sink.h DESTINATION
- cw_encoder.h DESTINATION include/satnogs
)
\ No newline at end of file
diff --git a/include/satnogs/morse.h b/include/satnogs/morse.h
index e5e3044..af643b5 100644
--- a/include/satnogs/morse.h
+++ b/include/satnogs/morse.h
@@ -2,7 +2,8 @@
/*
* gr-satnogs: SatNOGS GNU Radio Out-Of-Tree Module
*
- * Copyright (C) 2016, Libre Space Foundation
+ * Copyright (C) 2016,2017
+ * 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
@@ -27,10 +28,11 @@
* The different Morse symbols
*/
typedef enum {
- MORSE_DOT = 0,//!< MORSE_DOT Morse dot (.) symbol
- MORSE_DASH, //!< MORSE_DASH Morse dash (-) symbol
- MORSE_S_SPACE,//!< MORSE_S_SPACE Morse short space between characters
- MORSE_L_SPACE //!< MORSE_L_SPACE Morse long space between words
+ MORSE_DOT = 0, //!< Morse dot (.) symbol
+ MORSE_DASH, //!< Morse dash (-) symbol
+ MORSE_INTRA_SPACE, //!< Space between dot and dash symbols
+ MORSE_S_SPACE, //!< Morse short space between characters
+ MORSE_L_SPACE //!
+#include
#include "cw_encoder_impl.h"
namespace gr {
namespace satnogs {
- const std::vector cw_encoder_impl::cw_chars (
- { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N',
- 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '1', '2',
- '3', '4', '5', '6', '7', '8', '9', '0' });
- const std::vector cw_encoder_impl::cw_symbols (
- { ".-", "-...", "-.-.", "-..", ".", "..-.", "--.", "....", "..",
- ".---", "-.-", ".-..", "--", "-.", "---", ".--.", "--.-", ".-.",
- "...", "-", "..-", "...-", ".--", "-..-", "-.--", "--..", ".----",
- "..---", "...--", "....-", ".....", "-....", "--...", "---..",
- "----.", "-----" });
-
cw_encoder::sptr
cw_encoder::make(double samp_rate, double cw_freq, size_t wpm)
{
@@ -60,11 +50,11 @@ namespace gr {
d_wpm (wpm),
d_dot_samples ((1.2 / wpm) / (1.0 / samp_rate)),
d_window_size (0),
- d_nco (),
- d_word (new uint8_t[2048]),
- d_remaining (0)
+ d_windows_remaining (0),
+ d_cw_symbol (MORSE_L_SPACE),
+ d_nco ()
{
- message_port_register_in(pmt::mp("word"));
+ message_port_register_in(pmt::mp("symbol"));
/*
* Try to split the CW pulses in smaller windows for dealing efficiently
@@ -82,6 +72,7 @@ namespace gr {
d_window_size++;
}
+ set_output_multiple(d_window_size);
d_nco.set_freq ((2 * M_PI * cw_freq) / samp_rate);
}
@@ -90,31 +81,6 @@ namespace gr {
*/
cw_encoder_impl::~cw_encoder_impl()
{
- delete [] d_word;
- }
-
- static inline size_t
- find_char_idx(const char* characters, size_t len, char c)
- {
- size_t i;
- for(i = 0; i < len; i++) {
- if(characters[i] == c){
- return i;
- }
- }
- return len;
- }
-
- std::string
- cw_encoder_impl::get_cw_symbol (char c)
- {
- size_t i;
- for(i = 0; i < cw_chars.size(); i++) {
- if(cw_chars[i] == c) {
- return cw_symbols[i];
- }
- }
- return "";
}
int
@@ -122,19 +88,56 @@ namespace gr {
gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items)
{
- gr_complex *out = (gr_complex *) output_items[0];
size_t available;
+ size_t i;
+ gr_complex *out = (gr_complex *) output_items[0];
- if(d_remaining == 0) {
- pmt::pmt_t w = delete_head_blocking(pmt::mp("word"));
- if(pmt::blob_length(w) > 2048) {
- return 0;
- }
- d_word = (uint8_t *) pmt::blob_data(w);
- d_remaining = pmt::blob_length(w);
+ if(noutput_items < 0) {
+ return noutput_items;
}
- return noutput_items;
+ if(d_windows_remaining == 0) {
+ pmt::pmt_t symbol = delete_head_blocking(pmt::mp("symbol"));
+ d_cw_symbol = (morse_symbol_t) pmt::to_long(symbol);
+ /* Reset NCO so the amplitude starts from zero */
+ d_nco.set_freq ((2 * M_PI * d_cw_freq) / d_samp_rate);
+ switch(d_cw_symbol) {
+ case MORSE_DOT:
+ case MORSE_INTRA_SPACE:
+ d_windows_remaining = d_dot_samples / d_window_size;
+ break;
+ case MORSE_DASH:
+ case MORSE_S_SPACE:
+ d_windows_remaining = (d_dot_samples / d_window_size) * 3;
+ break;
+ case MORSE_L_SPACE:
+ d_windows_remaining = (d_dot_samples / d_window_size) * 7;
+ break;
+ default:
+ LOG_WARN("Unrecognized CW symbol");
+ return 0;
+ }
+ }
+
+ for(i = 0; i < (size_t)noutput_items / d_window_size; i++) {
+ switch(d_cw_symbol){
+ case MORSE_S_SPACE:
+ case MORSE_L_SPACE:
+ case MORSE_INTRA_SPACE:
+ memset (out + i * d_window_size, 0,
+ d_window_size * sizeof(gr_complex));
+ break;
+ case MORSE_DOT:
+ case MORSE_DASH:
+ d_nco.sincos(out + i * d_window_size, d_window_size, 1.0);
+ break;
+ }
+ d_windows_remaining--;
+ if(d_windows_remaining == 0) {
+ return (i + 1) * d_window_size;
+ }
+ }
+ return i * d_window_size;
}
} /* namespace satnogs */
diff --git a/lib/cw_encoder_impl.h b/lib/cw_encoder_impl.h
index bc92e9d..747cf8d 100644
--- a/lib/cw_encoder_impl.h
+++ b/lib/cw_encoder_impl.h
@@ -25,6 +25,7 @@
#include
#include
#include
+#include
#include
namespace gr
@@ -40,16 +41,16 @@ namespace gr
const size_t d_wpm;
const size_t d_dot_samples;
size_t d_window_size;
+ size_t d_windows_remaining;
+ morse_symbol_t d_cw_symbol;
gr::fxpt_nco d_nco;
- uint8_t *d_word;
- size_t d_remaining;
+
+
std::string
get_cw_symbol(char c);
public:
- static const std::vector cw_chars;
- static const std::vector cw_symbols;
cw_encoder_impl (double samp_rate, double cw_freq, size_t wpm);
~cw_encoder_impl ();
diff --git a/lib/morse_debug_source_impl.cc b/lib/morse_debug_source_impl.cc
index 7fd4425..448fe09 100644
--- a/lib/morse_debug_source_impl.cc
+++ b/lib/morse_debug_source_impl.cc
@@ -2,7 +2,8 @@
/*
* gr-satnogs: SatNOGS GNU Radio Out-Of-Tree Module
*
- * Copyright (C) 2016, Libre Space Foundation
+ * Copyright (C) 2016, 2017
+ * 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
@@ -27,55 +28,55 @@
#include
#include
-namespace gr {
- namespace satnogs {
+namespace gr
+{
+ namespace satnogs
+ {
morse_debug_source::sptr
- morse_debug_source::make(const std::string& debug_seq,
- bool inject_errors,
- float error_prob)
+ 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, inject_errors, error_prob));
+ return gnuradio::get_initial_sptr (
+ 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,
- 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',
- 'W', 'X', 'Y', 'Z', '1', '2', '3', '4', '5', '6', '7',
- '8', '9', '0' },
- d_symbols { ".-", "-...", "-.-.", "-..", ".", "..-.", "--.",
- "....", "..", ".---", "-.-", ".-..", "--", "-.",
- "---", ".--.", "--.-", ".-.", "...", "-", "..-",
- "...-", ".--", "-..-", "-.--", "--..", ".----",
- "..---", "...--", "....-", ".....", "-....", "--...",
- "---..", "----.", "-----"}
+ 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', 'W', 'X', 'Y',
+ 'Z', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0' },
+ d_symbols
+ { ".-", "-...", "-.-.", "-..", ".", "..-.", "--.", "....", "..",
+ ".---", "-.-", ".-..", "--", "-.", "---", ".--.", "--.-",
+ ".-.", "...", "-", "..-", "...-", ".--", "-..-", "-.--",
+ "--..", ".----", "..---", "...--", "....-", ".....", "-....",
+ "--...", "---..", "----.", "-----" }
{
- message_port_register_out(pmt::mp("out"));
- d_thread = std::thread(&morse_debug_source_impl::send_debug_msg,
- this,
- debug_seq);
+ message_port_register_out (pmt::mp ("out"));
+ d_thread = std::thread (&morse_debug_source_impl::send_debug_msg, this,
+ debug_seq);
}
static inline size_t
- find_char_idx(const char* characters, size_t len, char c)
+ find_char_idx (const char* characters, size_t len, char c)
{
size_t i;
- for(i = 0; i < len; i++) {
- if(characters[i] == c){
- return i;
- }
+ for (i = 0; i < len; i++) {
+ if (characters[i] == c) {
+ return i;
+ }
}
return len;
}
@@ -89,65 +90,69 @@ namespace gr {
std::string s;
char c;
std::random_device rd;
- std::mt19937 gen(rd());
- std::bernoulli_distribution error_distr(d_p);
+ 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");
+ size_t len = sentence.length ();
+ pmt::pmt_t port = pmt::mp ("out");
- std::this_thread::sleep_for(std::chrono::milliseconds(1000));
-
- while(d_run) {
+ std::this_thread::sleep_for (std::chrono::milliseconds (1000));
+
+ while (d_run) {
/* Not the best approach, but hey, this is only for debug */
- for(i = 0; i < len; i++){
- c = std::toupper(sentence[i]);
- if(c == ' '){
- message_port_pub(port, pmt::from_long(MORSE_L_SPACE));
- }
+ for (i = 0; i < len; i++) {
+ c = std::toupper (sentence[i]);
+ if (c == ' ') {
+ message_port_pub (port, pmt::from_long (MORSE_L_SPACE));
+ }
- idx = find_char_idx(d_chars, sizeof(d_chars), c);
- if(idx != sizeof(d_chars)){
+ 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] == '.'){
- if(inject_error){
- message_port_pub(port, pmt::from_long(MORSE_DASH));
- }
- else{
- message_port_pub(port, pmt::from_long(MORSE_DOT));
- }
- }
- else{
- 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));
- }
+ 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] == '.') {
+ if (inject_error) {
+ message_port_pub (port, pmt::from_long (MORSE_DASH));
+ message_port_pub (port, pmt::from_long (MORSE_INTRA_SPACE));
- /* Send also a character delimiter after waiting a little */
- std::this_thread::sleep_for(std::chrono::milliseconds(200));
- message_port_pub(port, pmt::from_long(MORSE_S_SPACE));
- }
- }
- message_port_pub(port, pmt::from_long(MORSE_L_SPACE));
- std::this_thread::sleep_for(std::chrono::milliseconds(1000));
+ }
+ else {
+ message_port_pub (port, pmt::from_long (MORSE_DOT));
+ message_port_pub (port, pmt::from_long (MORSE_INTRA_SPACE));
+ }
+ }
+ else {
+ if (inject_error) {
+ message_port_pub (port, pmt::from_long (MORSE_DOT));
+ message_port_pub (port, pmt::from_long (MORSE_INTRA_SPACE));
+ }
+ else {
+ message_port_pub (port, pmt::from_long (MORSE_DASH));
+ message_port_pub (port, pmt::from_long (MORSE_INTRA_SPACE));
+ }
+ }
+ std::this_thread::sleep_for (std::chrono::milliseconds (100));
+ }
+
+ /* Send also a character delimiter */
+ message_port_pub (port, pmt::from_long (MORSE_S_SPACE));
+ }
+ }
+ message_port_pub (port, pmt::from_long (MORSE_L_SPACE));
+ std::this_thread::sleep_for (std::chrono::milliseconds (1000));
}
}
/*
* Our virtual destructor.
*/
- morse_debug_source_impl::~morse_debug_source_impl()
+ morse_debug_source_impl::~morse_debug_source_impl ()
{
d_run = false;
- d_thread.join();
+ d_thread.join ();
}
} /* namespace satnogs */
diff --git a/lib/morse_decoder_impl.cc b/lib/morse_decoder_impl.cc
index 221156e..0e4e543 100644
--- a/lib/morse_decoder_impl.cc
+++ b/lib/morse_decoder_impl.cc
@@ -2,7 +2,8 @@
/*
* gr-satnogs: SatNOGS GNU Radio Out-Of-Tree Module
*
- * Copyright (C) 2016, Libre Space Foundation
+ * Copyright (C) 2016, 2017
+ * 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
@@ -34,7 +35,7 @@ namespace gr
morse_decoder::make (char unrecognized_char)
{
return gnuradio::get_initial_sptr (
- new morse_decoder_impl (unrecognized_char));
+ new morse_decoder_impl (unrecognized_char));
}
void
@@ -45,50 +46,54 @@ namespace gr
morse_symbol_t s;
s = (morse_symbol_t) pmt::to_long (msg);
- switch(s) {
- case MORSE_DOT:
- case MORSE_DASH:
- case MORSE_S_SPACE:
- res = d_morse_tree.received_symbol(s);
- break;
- /*
- * If a word separator occurs it is a good time to retrieve the decoded
- * word
- */
- case MORSE_L_SPACE:
- /*
- * Inject a character separator, for the morse decoder to commit
- * the outstanding character
- */
- res = d_morse_tree.received_symbol(MORSE_S_SPACE);
- /* Just ignore the word separator if no word is yet decoded */
- if (d_morse_tree.get_word_len() == 0) {
- res = true;
- break;
- }
- str = d_morse_tree.get_word();
- d_morse_tree.reset();
- message_port_pub(pmt::mp("out"), pmt::make_blob(str.c_str(),
- str.length()));
- break;
- default:
- LOG_ERROR("Unknown Morse symbol");
- return;
- }
+ switch (s)
+ {
+ case MORSE_DOT:
+ case MORSE_DASH:
+ case MORSE_S_SPACE:
+ res = d_morse_tree.received_symbol (s);
+ break;
+ /*
+ * If a word separator occurs it is a good time to retrieve the decoded
+ * word
+ */
+ case MORSE_L_SPACE:
+ /*
+ * Inject a character separator, for the morse decoder to commit
+ * the outstanding character
+ */
+ res = d_morse_tree.received_symbol (MORSE_S_SPACE);
+ /* Just ignore the word separator if no word is yet decoded */
+ if (d_morse_tree.get_word_len () == 0) {
+ res = true;
+ break;
+ }
+ str = d_morse_tree.get_word ();
+ d_morse_tree.reset ();
+ message_port_pub (pmt::mp ("out"),
+ pmt::make_blob (str.c_str (), str.length ()));
+ break;
+ case MORSE_INTRA_SPACE:
+ /*Ignore it */
+ break;
+ default:
+ LOG_ERROR("Unknown Morse symbol");
+ return;
+ }
/*
* If the decoding return false, it means that either an non decode-able
* character situation occurred or the maximum word limit reached
*/
if (!s) {
- if(d_morse_tree.get_max_word_len() == d_morse_tree.get_word_len()){
- str = d_morse_tree.get_word();
- d_morse_tree.reset();
- std::cout << "Received word: " << str << std::endl;
- }
+ if (d_morse_tree.get_max_word_len () == d_morse_tree.get_word_len ()) {
+ str = d_morse_tree.get_word ();
+ d_morse_tree.reset ();
+ std::cout << "Received word: " << str << std::endl;
+ }
}
- else{
- LOG_DEBUG("Something went wrong");
+ else {
+ LOG_DEBUG("Something went wrong");
}
}
@@ -96,17 +101,16 @@ namespace gr
* The private constructor
*/
morse_decoder_impl::morse_decoder_impl (char unrecognized_char) :
- gr::block ("morse_decoder",
- gr::io_signature::make (0, 0, 0),
- gr::io_signature::make (0, 0, 0)),
- d_morse_tree (unrecognized_char)
+ gr::block ("morse_decoder", gr::io_signature::make (0, 0, 0),
+ gr::io_signature::make (0, 0, 0)),
+ d_morse_tree (unrecognized_char)
{
/* Register the input and output msg handler */
message_port_register_in (pmt::mp ("in"));
- message_port_register_out(pmt::mp("out"));
+ message_port_register_out (pmt::mp ("out"));
set_msg_handler (
- pmt::mp ("in"),
- boost::bind (&morse_decoder_impl::symbol_msg_handler, this, _1));
+ pmt::mp ("in"),
+ boost::bind (&morse_decoder_impl::symbol_msg_handler, this, _1));
}
} /* namespace satnogs */