Improve CW decoding performance and complexity

This commit is contained in:
Manolis Surligas 2017-08-06 23:48:34 +03:00
parent 5d9fc19e3b
commit 94eef1463c
2 changed files with 89 additions and 45 deletions

View File

@ -59,17 +59,22 @@ namespace gr
d_window_size(0), d_window_size(0),
d_window_cnt(0), d_window_cnt(0),
d_dot_windows_num(0), d_dot_windows_num(0),
d_state (IDLE),
d_dec_state (NO_SYNC), d_dec_state (NO_SYNC),
d_prev_space_symbol (true), d_prev_space_symbol (true)
d_sync_state (SYNC_TRIGGER_OFF)
{ {
if(wpm < MIN_WPM){ if (wpm < MIN_WPM) {
throw std::invalid_argument("Decoder can not handle such low WPM setting"); throw std::invalid_argument (
"Decoder can not handle such low WPM setting");
} }
if(wpm > MAX_WPM) { if (wpm > MAX_WPM) {
throw std::invalid_argument("Decoder can not handle such high WPM setting"); throw std::invalid_argument (
"Decoder can not handle such high WPM setting");
}
if (conf_level > 1.0 || conf_level < 0.5) {
throw std::invalid_argument (
"Confidence level should be in the range [0.5, 1.0]");
} }
message_port_register_in (pmt::mp ("act_threshold")); message_port_register_in (pmt::mp ("act_threshold"));
@ -137,6 +142,12 @@ namespace gr
message_port_pub (pmt::mp ("out"), pmt::from_long (s)); message_port_pub (pmt::mp ("out"), pmt::from_long (s));
} }
inline bool
cw_to_symbol_impl::check_conf_level(size_t cnt, size_t target)
{
return ((float)cnt > target * d_confidence_level);
}
/* /*
* Our virtual destructor. * Our virtual destructor.
*/ */
@ -150,14 +161,13 @@ namespace gr
inline void inline void
cw_to_symbol_impl::set_idle () cw_to_symbol_impl::set_idle ()
{ {
d_state = IDLE; d_dec_state = NO_SYNC;
d_window_cnt = 0; d_window_cnt = 0;
} }
inline void inline void
cw_to_symbol_impl::set_short_on () cw_to_symbol_impl::set_short_on ()
{ {
d_state = TRIGGED;
d_dec_state = SEARCH_DOT; d_dec_state = SEARCH_DOT;
d_window_cnt = 1; d_window_cnt = 1;
} }
@ -169,18 +179,12 @@ namespace gr
} }
inline void inline void
cw_to_symbol_impl::set_short_off () cw_to_symbol_impl::set_search_space ()
{ {
d_dec_state = SEARCH_SHORT_OFF; d_dec_state = SEARCH_SPACE;
d_window_cnt = 1; d_window_cnt = 1;
} }
inline void
cw_to_symbol_impl::set_long_off ()
{
d_dec_state = SEARCH_LONG_OFF;
}
void void
cw_to_symbol_impl::set_act_threshold_msg_handler (pmt::pmt_t msg) cw_to_symbol_impl::set_act_threshold_msg_handler (pmt::pmt_t msg)
{ {
@ -194,15 +198,13 @@ namespace gr
gr_vector_const_void_star &input_items, gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items) gr_vector_void_star &output_items)
{ {
int32_t cnt;
bool triggered; bool triggered;
int i; int i;
const float *in_old = (const float *) input_items[0]; const float *in_old = (const float *) input_items[0];
const float *in = in_old + history() - 1; const float *in = in_old + history() - 1;
float conf;
/* During idle state search for a possible trigger */ /* During idle state search for a possible trigger */
if(d_state == IDLE) { if(d_dec_state == NO_SYNC) {
for(i = 0; i < noutput_items; i++) { for(i = 0; i < noutput_items; i++) {
/* /*
* Clamp the input so the window mean is not affected by strong spikes * Clamp the input so the window mean is not affected by strong spikes
@ -210,19 +212,76 @@ namespace gr
*/ */
triggered = is_triggered(in_old + i, d_window_size); triggered = is_triggered(in_old + i, d_window_size);
if(triggered) { if(triggered) {
LOG_DEBUG("Triggered!");
set_short_on(); set_short_on();
return i+1; return i+1;
} }
} }
return noutput_items; return noutput_items;
} }
else{
/* From now one, we handle the input in multiples of a window */ /* From now one, we handle the input in multiples of a window */
for (i = 0; i < noutput_items / d_window_size; i++) { for (i = 0; i < noutput_items / d_window_size; i++) {
triggered = is_triggered(in + i * d_window_size, d_window_size); triggered = is_triggered(in + i * d_window_size, d_window_size);
switch(d_dec_state) {
case SEARCH_DOT:
if(triggered) {
d_window_cnt++;
if(d_window_cnt > d_dot_windows_num) {
set_long_on();
} }
} }
return noutput_items; else {
if(check_conf_level(d_window_cnt, d_dot_windows_num)) {
LOG_DEBUG("DOT");
send_symbol_msg(MORSE_DOT);
}
set_search_space ();
}
break;
case SEARCH_DASH:
if(triggered) {
d_window_cnt++;
}
else{
if(check_conf_level(d_window_cnt, d_dash_windows_num)) {
LOG_DEBUG("DASH");
send_symbol_msg(MORSE_DASH);
}
else{
LOG_DEBUG("DOT");
send_symbol_msg(MORSE_DOT);
}
set_search_space ();
}
break;
case SEARCH_SPACE:
if (triggered) {
if(check_conf_level(d_window_cnt, d_long_pause_windows_num)) {
LOG_DEBUG("LONG SPACE");
send_symbol_msg(MORSE_L_SPACE);
}
else if(check_conf_level(d_window_cnt, d_short_pause_windows_num)){
LOG_DEBUG("SHORT SPACE");
send_symbol_msg(MORSE_S_SPACE);
}
set_short_on();
}
else{
d_window_cnt++;
if(d_window_cnt > d_long_pause_windows_num) {
LOG_DEBUG("LONG SPACE");
send_symbol_msg(MORSE_L_SPACE);
set_idle();
return (i + 1) * d_window_size;
}
}
break;
default:
LOG_ERROR("Invalid decoder state");
}
}
return i * d_window_size;
} }
/** /**

View File

@ -32,25 +32,12 @@ namespace gr
class cw_to_symbol_impl : public cw_to_symbol class cw_to_symbol_impl : public cw_to_symbol
{ {
typedef enum
{
IDLE, TRIGGED
} cw_state_t;
typedef enum typedef enum
{ {
NO_SYNC, SEARCH_DOT, SEARCH_DASH, SEARCH_SHORT_OFF, SEARCH_LONG_OFF, NO_SYNC, SEARCH_DOT, SEARCH_DASH, SEARCH_SPACE
} cw_dec_state_t; } cw_dec_state_t;
/**
* Different states during the WPM auto synchronization
*/
typedef enum
{
SYNC_TRIGGER_OFF, //!< SYNC_TRIGGER_OFF Signal is below threshold
SYNC_TRIGGER_ON //!< SYNC_TRIGGER_ON Signal is above threshold
} sync_state_t;
private: private:
const double d_sampling_rate; const double d_sampling_rate;
float d_act_thrshld; float d_act_thrshld;
@ -62,10 +49,8 @@ namespace gr
size_t d_dash_windows_num; size_t d_dash_windows_num;
size_t d_short_pause_windows_num; size_t d_short_pause_windows_num;
size_t d_long_pause_windows_num; size_t d_long_pause_windows_num;
cw_state_t d_state;
cw_dec_state_t d_dec_state; cw_dec_state_t d_dec_state;
bool d_prev_space_symbol; bool d_prev_space_symbol;
sync_state_t d_sync_state;
float *d_const_val; float *d_const_val;
float *d_tmp; float *d_tmp;
int32_t *d_out; int32_t *d_out;
@ -80,10 +65,7 @@ namespace gr
set_long_on (); set_long_on ();
inline void inline void
set_short_off (); set_search_space ();
inline void
set_long_off ();
inline int32_t inline int32_t
hadd (const int32_t *in, size_t len); hadd (const int32_t *in, size_t len);
@ -97,6 +79,9 @@ namespace gr
inline void inline void
send_symbol_msg (morse_symbol_t s); send_symbol_msg (morse_symbol_t s);
inline bool
check_conf_level(size_t cnt, size_t target);
void void
set_act_threshold_msg_handler (pmt::pmt_t msg); set_act_threshold_msg_handler (pmt::pmt_t msg);