CW signal to Morse Symbol decoding block
The CW symbol decoder block takes as input the power of the processed signal and tries to identify the dot and dash symbols. It produces asynchronous messages containing the decoded symbols. The output messages can be directly used by the Morse code decoder block, in order to retrieve the clear text message. There are some few thing that need to be done for the block to be fully operational.
This commit is contained in:
parent
5d4884cf0d
commit
f8b847077e
File diff suppressed because it is too large
Load Diff
|
@ -1,5 +1,5 @@
|
|||
<?xml version='1.0' encoding='utf-8'?>
|
||||
<?grc format='1' created='3.7.8'?>
|
||||
<?grc format='1' created='3.7.10'?>
|
||||
<flow_graph>
|
||||
<timestamp>Sun Jan 17 23:03:00 2016</timestamp>
|
||||
<block>
|
||||
|
@ -40,6 +40,10 @@
|
|||
<key>generate_options</key>
|
||||
<value>qt_gui</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>hier_block_src_path</key>
|
||||
<value>.:</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>id</key>
|
||||
<value>test_matched_filter</value>
|
||||
|
@ -48,10 +52,18 @@
|
|||
<key>max_nouts</key>
|
||||
<value>0</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>qt_qss_theme</key>
|
||||
<value></value>
|
||||
</param>
|
||||
<param>
|
||||
<key>realtime_scheduling</key>
|
||||
<value></value>
|
||||
</param>
|
||||
<param>
|
||||
<key>run_command</key>
|
||||
<value>{python} -u {filename}</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>run_options</key>
|
||||
<value>prompt</value>
|
||||
|
|
|
@ -128,7 +128,7 @@
|
|||
</param>
|
||||
<param>
|
||||
<key>_coordinate</key>
|
||||
<value>(944, 184)</value>
|
||||
<value>(960, 168)</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>_rotation</key>
|
||||
|
@ -159,11 +159,11 @@
|
|||
</param>
|
||||
<param>
|
||||
<key>p</key>
|
||||
<value>0.1</value>
|
||||
<value>0.01</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>_coordinate</key>
|
||||
<value>(240, 196)</value>
|
||||
<value>(200, 150)</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>_rotation</key>
|
||||
|
@ -210,7 +210,7 @@
|
|||
</param>
|
||||
<param>
|
||||
<key>_coordinate</key>
|
||||
<value>(672, 180)</value>
|
||||
<value>(632, 164)</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>_rotation</key>
|
||||
|
|
|
@ -20,5 +20,6 @@ install(FILES
|
|||
satnogs_cw_matched_filter_ff.xml
|
||||
satnogs_morse_decoder.xml
|
||||
satnogs_morse_debug_source.xml
|
||||
satnogs_clear_text_msg_sink.xml DESTINATION share/gnuradio/grc/blocks
|
||||
satnogs_clear_text_msg_sink.xml
|
||||
satnogs_cw_to_symbol.xml DESTINATION share/gnuradio/grc/blocks
|
||||
)
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
<?xml version="1.0"?>
|
||||
<block>
|
||||
<name>CW to Symbols</name>
|
||||
<key>satnogs_cw_to_symbol</key>
|
||||
<category>satnogs</category>
|
||||
<import>import satnogs</import>
|
||||
<make>satnogs.cw_to_symbol($sampling_rate, $threshold, $wpm)</make>
|
||||
|
||||
<param>
|
||||
<name>Sampling Rate</name>
|
||||
<key>sampling_rate</key>
|
||||
<value>samp_rate</value>
|
||||
<type>real</type>
|
||||
</param>
|
||||
|
||||
<param>
|
||||
<name>Activation Threshold</name>
|
||||
<key>threshold</key>
|
||||
<type>real</type>
|
||||
</param>
|
||||
|
||||
<param>
|
||||
<name>Words per Minute</name>
|
||||
<key>wpm</key>
|
||||
<value>20</value>
|
||||
<type>int</type>
|
||||
</param>
|
||||
|
||||
<sink>
|
||||
<name>in</name>
|
||||
<type>float</type>
|
||||
</sink>
|
||||
|
||||
<source>
|
||||
<name>out</name>
|
||||
<type>message</type>
|
||||
</source>
|
||||
</block>
|
|
@ -29,5 +29,6 @@ install(FILES
|
|||
morse.h
|
||||
morse_decoder.h
|
||||
morse_debug_source.h
|
||||
clear_text_msg_sink.h DESTINATION include/satnogs
|
||||
clear_text_msg_sink.h
|
||||
cw_to_symbol.h DESTINATION include/satnogs
|
||||
)
|
||||
|
|
|
@ -0,0 +1,63 @@
|
|||
/* -*- c++ -*- */
|
||||
/*
|
||||
* gr-satnogs: SatNOGS GNU Radio Out-Of-Tree Module
|
||||
*
|
||||
* Copyright (C) 2016, 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_CW_TO_SYMBOL_H
|
||||
#define INCLUDED_SATNOGS_CW_TO_SYMBOL_H
|
||||
|
||||
#include <satnogs/api.h>
|
||||
#include <gnuradio/sync_block.h>
|
||||
|
||||
namespace gr {
|
||||
namespace satnogs {
|
||||
|
||||
/*!
|
||||
* \brief The CW to Symbol block tries to translate the received signal
|
||||
* power time-series into Morse symbols.
|
||||
* \ingroup satnogs
|
||||
*/
|
||||
class SATNOGS_API cw_to_symbol : virtual public gr::sync_block
|
||||
{
|
||||
public:
|
||||
typedef boost::shared_ptr<cw_to_symbol> sptr;
|
||||
|
||||
/*!
|
||||
* The CW to Symbol block tries to translate the received signal
|
||||
* power time-series into Morse symbols.
|
||||
*
|
||||
* The input stream is the energy of the signal in the time domain.
|
||||
* For best results, a proper moving average filter should be applied
|
||||
* before.
|
||||
*
|
||||
* Upon a successful recovery of a symbol it produces an appropriate
|
||||
* asynchronous message that can directly be used by the Morse decoder
|
||||
* block.
|
||||
*
|
||||
* @param sampling_rate the sampling rate of the signal
|
||||
* @param threshold the activation threshold
|
||||
* @param wpm Morse code Words per Minute
|
||||
*/
|
||||
static sptr make(double sampling_rate, float threshold, size_t wpm = 20);
|
||||
};
|
||||
|
||||
} // namespace satnogs
|
||||
} // namespace gr
|
||||
|
||||
#endif /* INCLUDED_SATNOGS_CW_TO_SYMBOL_H */
|
||||
|
|
@ -29,7 +29,8 @@ list(APPEND satnogs_sources
|
|||
morse_tree.cc
|
||||
morse_decoder_impl.cc
|
||||
morse_debug_source_impl.cc
|
||||
clear_text_msg_sink_impl.cc )
|
||||
clear_text_msg_sink_impl.cc
|
||||
cw_to_symbol_impl.cc )
|
||||
|
||||
set(satnogs_sources "${satnogs_sources}" PARENT_SCOPE)
|
||||
if(NOT satnogs_sources)
|
||||
|
|
|
@ -0,0 +1,211 @@
|
|||
/* -*- c++ -*- */
|
||||
/*
|
||||
* gr-satnogs: SatNOGS GNU Radio Out-Of-Tree Module
|
||||
*
|
||||
* Copyright (C) 2016, 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 <satnogs/log.h>
|
||||
#include <satnogs/morse.h>
|
||||
#include "cw_to_symbol_impl.h"
|
||||
|
||||
namespace gr
|
||||
{
|
||||
namespace satnogs
|
||||
{
|
||||
|
||||
cw_to_symbol::sptr
|
||||
cw_to_symbol::make (double sampling_rate, float threshold, size_t wpm)
|
||||
{
|
||||
return gnuradio::get_initial_sptr (
|
||||
new cw_to_symbol_impl (sampling_rate, threshold, wpm));
|
||||
}
|
||||
|
||||
/*
|
||||
* The private constructor
|
||||
*/
|
||||
cw_to_symbol_impl::cw_to_symbol_impl (double sampling_rate, float threshold,
|
||||
size_t wpm) :
|
||||
gr::sync_block ("cw_to_symbol",
|
||||
gr::io_signature::make (1, 1, sizeof(float)),
|
||||
gr::io_signature::make (0, 0, 0)),
|
||||
d_sampling_rate(sampling_rate),
|
||||
d_act_thrshld(threshold),
|
||||
d_confidence_level(0.90),
|
||||
d_dot_samples((1.2/wpm) / (1.0 / sampling_rate)),
|
||||
d_dash_samples(3 * d_dot_samples),
|
||||
d_short_pause_samples(3 * d_dot_samples),
|
||||
d_long_pause_samples(7 * d_dot_samples),
|
||||
d_state(IDLE),
|
||||
d_state_cnt(0),
|
||||
d_pause_cnt(0)
|
||||
{
|
||||
message_port_register_out(pmt::mp("out"));
|
||||
}
|
||||
|
||||
/*
|
||||
* Our virtual destructor.
|
||||
*/
|
||||
cw_to_symbol_impl::~cw_to_symbol_impl ()
|
||||
{
|
||||
}
|
||||
|
||||
inline void
|
||||
cw_to_symbol_impl::set_idle ()
|
||||
{
|
||||
d_state = IDLE;
|
||||
d_state_cnt = 0;
|
||||
d_pause_cnt = 0;
|
||||
}
|
||||
|
||||
inline void
|
||||
cw_to_symbol_impl::set_short_on ()
|
||||
{
|
||||
d_state = SHORT_ON_PERIOD;
|
||||
d_state_cnt = 1;
|
||||
}
|
||||
|
||||
inline void
|
||||
cw_to_symbol_impl::set_long_on ()
|
||||
{
|
||||
d_state = LONG_ON_PERIOD;
|
||||
d_pause_cnt = 0;
|
||||
}
|
||||
|
||||
inline void
|
||||
cw_to_symbol_impl::set_short_off (size_t borrow_cnt)
|
||||
{
|
||||
d_state = SHORT_OFF_PERIOD;
|
||||
d_state_cnt = 0;
|
||||
d_pause_cnt += borrow_cnt;
|
||||
|
||||
/* Due to time-slots borrowing we may be already at the Long pause */
|
||||
if(d_pause_cnt > d_short_pause_samples) {
|
||||
d_state = LONG_OFF_PERIOD;
|
||||
}
|
||||
}
|
||||
|
||||
inline void
|
||||
cw_to_symbol_impl::set_long_off ()
|
||||
{
|
||||
d_state = LONG_OFF_PERIOD;
|
||||
}
|
||||
|
||||
int
|
||||
cw_to_symbol_impl::work (int noutput_items,
|
||||
gr_vector_const_void_star &input_items,
|
||||
gr_vector_void_star &output_items)
|
||||
{
|
||||
int i;
|
||||
float conf_lvl;
|
||||
const float *in = (const float *) input_items[0];
|
||||
|
||||
for(i = 0; i < noutput_items; i++) {
|
||||
switch(d_state){
|
||||
case IDLE:
|
||||
if(in[i] > d_act_thrshld) {
|
||||
set_short_on();
|
||||
}
|
||||
// TODO Avoid unnecessary pause messages
|
||||
break;
|
||||
|
||||
case SHORT_ON_PERIOD:
|
||||
if( in[i] > d_act_thrshld ) {
|
||||
d_state_cnt++;
|
||||
|
||||
if(d_state_cnt > d_dot_samples){
|
||||
set_long_on();
|
||||
}
|
||||
}
|
||||
else{
|
||||
/*
|
||||
* Before going to short pause, check the confidence level.
|
||||
* Perhaps a short symbol should be produced.
|
||||
*
|
||||
* Otherwise, it was a false alarm. So the time-slots counted
|
||||
* so far should be assigned as pause time-slots.
|
||||
*/
|
||||
conf_lvl = ((float) d_state_cnt) / d_dot_samples;
|
||||
if(conf_lvl > d_confidence_level){
|
||||
message_port_pub(pmt::mp("out"), pmt::from_long(MORSE_DOT));
|
||||
set_short_off(0);
|
||||
}
|
||||
else{
|
||||
set_short_off(d_state_cnt);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case LONG_ON_PERIOD:
|
||||
if( in[i] > d_act_thrshld ) {
|
||||
d_state_cnt++;
|
||||
}
|
||||
else{
|
||||
/*
|
||||
* In this case the FSM should continue at the SHORT_OFF state.
|
||||
* Before this depending the confidence for a long pulse, produce
|
||||
* a short or long pulse message
|
||||
*/
|
||||
conf_lvl = ((float) d_state_cnt) / d_dash_samples;
|
||||
if(conf_lvl > d_confidence_level){
|
||||
message_port_pub(pmt::mp("out"), pmt::from_long(MORSE_DASH));
|
||||
}
|
||||
else{
|
||||
message_port_pub(pmt::mp("out"), pmt::from_long(MORSE_DOT));
|
||||
}
|
||||
set_short_off(0);
|
||||
}
|
||||
break;
|
||||
|
||||
case SHORT_OFF_PERIOD:
|
||||
if(in[i] > d_act_thrshld) {
|
||||
set_short_on();
|
||||
}
|
||||
else {
|
||||
d_pause_cnt++;
|
||||
if(d_pause_cnt > d_short_pause_samples) {
|
||||
set_long_off();
|
||||
}
|
||||
}
|
||||
break;
|
||||
case LONG_OFF_PERIOD:
|
||||
if(in[i] > d_act_thrshld) {
|
||||
set_short_on();
|
||||
}
|
||||
else {
|
||||
d_pause_cnt++;
|
||||
if(d_pause_cnt > d_long_pause_samples) {
|
||||
message_port_pub(pmt::mp("out"), pmt::from_long(MORSE_L_SPACE));
|
||||
set_idle();
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
LOG_ERROR("Invalid State.");
|
||||
d_state = IDLE;
|
||||
}
|
||||
}
|
||||
return noutput_items;
|
||||
}
|
||||
|
||||
} /* namespace satnogs */
|
||||
} /* namespace gr */
|
||||
|
|
@ -0,0 +1,81 @@
|
|||
/* -*- c++ -*- */
|
||||
/*
|
||||
* gr-satnogs: SatNOGS GNU Radio Out-Of-Tree Module
|
||||
*
|
||||
* Copyright (C) 2016, 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_CW_TO_SYMBOL_IMPL_H
|
||||
#define INCLUDED_SATNOGS_CW_TO_SYMBOL_IMPL_H
|
||||
|
||||
#include <satnogs/cw_to_symbol.h>
|
||||
|
||||
namespace gr
|
||||
{
|
||||
namespace satnogs
|
||||
{
|
||||
|
||||
class cw_to_symbol_impl : public cw_to_symbol
|
||||
{
|
||||
typedef enum {
|
||||
IDLE,
|
||||
SHORT_ON_PERIOD,
|
||||
LONG_ON_PERIOD,
|
||||
SHORT_OFF_PERIOD,
|
||||
LONG_OFF_PERIOD
|
||||
} cw_state_t;
|
||||
private:
|
||||
const double d_sampling_rate;
|
||||
const float d_act_thrshld;
|
||||
const float d_confidence_level;
|
||||
const size_t d_dot_samples;
|
||||
const size_t d_dash_samples;
|
||||
const size_t d_short_pause_samples;
|
||||
const size_t d_long_pause_samples;
|
||||
cw_state_t d_state;
|
||||
size_t d_state_cnt;
|
||||
size_t d_pause_cnt;
|
||||
|
||||
inline void
|
||||
set_idle ();
|
||||
|
||||
inline void
|
||||
set_short_on ();
|
||||
|
||||
inline void
|
||||
set_long_on ();
|
||||
|
||||
inline void
|
||||
set_short_off (size_t borrow_cnt);
|
||||
|
||||
inline void
|
||||
set_long_off ();
|
||||
|
||||
public:
|
||||
cw_to_symbol_impl (double sampling_rate, float threshold, size_t wpm);
|
||||
~cw_to_symbol_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);
|
||||
};
|
||||
|
||||
} // namespace satnogs
|
||||
} // namespace gr
|
||||
|
||||
#endif /* INCLUDED_SATNOGS_CW_TO_SYMBOL_IMPL_H */
|
||||
|
|
@ -13,6 +13,7 @@
|
|||
#include "satnogs/morse_decoder.h"
|
||||
#include "satnogs/morse_debug_source.h"
|
||||
#include "satnogs/clear_text_msg_sink.h"
|
||||
#include "satnogs/cw_to_symbol.h"
|
||||
%}
|
||||
|
||||
%include "satnogs/cw_matched_filter_ff.h"
|
||||
|
@ -24,3 +25,5 @@ GR_SWIG_BLOCK_MAGIC2(satnogs, morse_decoder);
|
|||
GR_SWIG_BLOCK_MAGIC2(satnogs, morse_debug_source);
|
||||
%include "satnogs/clear_text_msg_sink.h"
|
||||
GR_SWIG_BLOCK_MAGIC2(satnogs, clear_text_msg_sink);
|
||||
%include "satnogs/cw_to_symbol.h"
|
||||
GR_SWIG_BLOCK_MAGIC2(satnogs, cw_to_symbol);
|
||||
|
|
Loading…
Reference in New Issue