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_cnt(0),
d_dot_windows_num(0),
d_state (IDLE),
d_dec_state (NO_SYNC),
d_prev_space_symbol (true),
d_sync_state (SYNC_TRIGGER_OFF)
d_prev_space_symbol (true)
{
if(wpm < MIN_WPM){
throw std::invalid_argument("Decoder can not handle such low WPM setting");
if (wpm < MIN_WPM) {
throw std::invalid_argument (
"Decoder can not handle such low WPM setting");
}
if(wpm > MAX_WPM) {
throw std::invalid_argument("Decoder can not handle such high WPM setting");
if (wpm > MAX_WPM) {
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"));
@ -137,6 +142,12 @@ namespace gr
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.
*/
@ -150,14 +161,13 @@ namespace gr
inline void
cw_to_symbol_impl::set_idle ()
{
d_state = IDLE;
d_dec_state = NO_SYNC;
d_window_cnt = 0;
}
inline void
cw_to_symbol_impl::set_short_on ()
{
d_state = TRIGGED;
d_dec_state = SEARCH_DOT;
d_window_cnt = 1;
}
@ -169,18 +179,12 @@ namespace gr
}
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;
}
inline void
cw_to_symbol_impl::set_long_off ()
{
d_dec_state = SEARCH_LONG_OFF;
}
void
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_void_star &output_items)
{
int32_t cnt;
bool triggered;
int i;
const float *in_old = (const float *) input_items[0];
const float *in = in_old + history() - 1;
float conf;
/* 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++) {
/*
* 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);
if(triggered) {
LOG_DEBUG("Triggered!");
set_short_on();
return i+1;
}
}
return noutput_items;
}
else{
/* From now one, we handle the input in multiples of a window */
for (i = 0; i < noutput_items / d_window_size; i++) {
triggered = is_triggered(in + i * d_window_size, d_window_size);
/* From now one, we handle the input in multiples of a window */
for (i = 0; i < noutput_items / d_window_size; i++) {
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();
}
}
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 noutput_items;
return i * d_window_size;
}
/**

View File

@ -32,25 +32,12 @@ namespace gr
class cw_to_symbol_impl : public cw_to_symbol
{
typedef enum
{
IDLE, TRIGGED
} cw_state_t;
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;
/**
* 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:
const double d_sampling_rate;
float d_act_thrshld;
@ -62,10 +49,8 @@ namespace gr
size_t d_dash_windows_num;
size_t d_short_pause_windows_num;
size_t d_long_pause_windows_num;
cw_state_t d_state;
cw_dec_state_t d_dec_state;
bool d_prev_space_symbol;
sync_state_t d_sync_state;
float *d_const_val;
float *d_tmp;
int32_t *d_out;
@ -80,10 +65,7 @@ namespace gr
set_long_on ();
inline void
set_short_off ();
inline void
set_long_off ();
set_search_space ();
inline int32_t
hadd (const int32_t *in, size_t len);
@ -97,6 +79,9 @@ namespace gr
inline void
send_symbol_msg (morse_symbol_t s);
inline bool
check_conf_level(size_t cnt, size_t target);
void
set_act_threshold_msg_handler (pmt::pmt_t msg);