Add CW decoder

* Filtering and decimation stages tested for USRP
* TODO: Test filtering for the rest of the SDR devices
This commit is contained in:
Manolis Surligas 2017-04-08 22:18:40 +03:00
parent ca1b8b1242
commit ea5a5632f5
3 changed files with 458 additions and 203 deletions

View File

@ -28,6 +28,7 @@ GR_PYTHON_INSTALL(
flowgraphs/satnogs_cw_demod.py
flowgraphs/satnogs_generic_iq_receiver.py
flowgraphs/satnogs_bpsk_demod.py
flowgraphs/satnogs_cw_decoder.py
flowgraphs/satnogs_apt_demod.py
flowgraphs/satnogs_fsk9600_ax25.py
flowgraphs/satnogs_fsk9600_g3ruh_ax25.py

View File

@ -0,0 +1,251 @@
#!/usr/bin/env python2
# -*- coding: utf-8 -*-
##################################################
# GNU Radio Python Flow Graph
# Title: CW Decoder
# Author: Manolis Surligas (surligas@gmail.com)
# Description: A CW (Morse) Decoder
# Generated: Sat Apr 8 22:15:03 2017
##################################################
from gnuradio import analog
from gnuradio import blocks
from gnuradio import eng_notation
from gnuradio import filter
from gnuradio import gr
from gnuradio.eng_option import eng_option
from gnuradio.filter import firdes
from optparse import OptionParser
import osmosdr
import satnogs
import time
class satnogs_cw_decoder(gr.top_block):
def __init__(self, doppler_correction_per_sec=1000, file_path='test.txt', lo_offset=100e3, ppm=0, rigctl_port=4532, rx_freq=100e6, rx_sdr_device='usrpb200', waterfall_file_path='/tmp/waterfall.dat', wpm=22):
gr.top_block.__init__(self, "CW Decoder")
##################################################
# Parameters
##################################################
self.doppler_correction_per_sec = doppler_correction_per_sec
self.file_path = file_path
self.lo_offset = lo_offset
self.ppm = ppm
self.rigctl_port = rigctl_port
self.rx_freq = rx_freq
self.rx_sdr_device = rx_sdr_device
self.waterfall_file_path = waterfall_file_path
self.wpm = wpm
##################################################
# Variables
##################################################
self.samp_rate_rx = samp_rate_rx = satnogs.hw_rx_settings[rx_sdr_device]['samp_rate']
self.xlate_filter_taps = xlate_filter_taps = firdes.low_pass(1, samp_rate_rx, 125000, 25000, firdes.WIN_HAMMING, 6.76)
self.taps = taps = firdes.low_pass(12.0, samp_rate_rx, 100e3, 60000, firdes.WIN_HAMMING, 6.76)
self.ndelay = ndelay = 100
self.filter_rate = filter_rate = 100000
##################################################
# Blocks
##################################################
self.satnogs_tcp_rigctl_msg_source_0 = satnogs.tcp_rigctl_msg_source("127.0.0.1", rigctl_port, False, 1000, 1500)
self.satnogs_multi_format_msg_sink_0 = satnogs.multi_format_msg_sink(0, True, False, 'test.txt')
self.satnogs_morse_decoder_0 = satnogs.morse_decoder(ord('#'))
self.satnogs_cw_to_symbol_0 = satnogs.cw_to_symbol(int(samp_rate_rx/filter_rate) / 5, 2e6, 0.9, wpm, False)
self.satnogs_coarse_doppler_correction_cc_0 = satnogs.coarse_doppler_correction_cc(rx_freq, samp_rate_rx)
self.osmosdr_source_0 = osmosdr.source( args="numchan=" + str(1) + " " + satnogs.hw_rx_settings[rx_sdr_device]['dev_arg'] )
self.osmosdr_source_0.set_sample_rate(samp_rate_rx)
self.osmosdr_source_0.set_center_freq(rx_freq - lo_offset, 0)
self.osmosdr_source_0.set_freq_corr(ppm, 0)
self.osmosdr_source_0.set_dc_offset_mode(2, 0)
self.osmosdr_source_0.set_iq_balance_mode(0, 0)
self.osmosdr_source_0.set_gain_mode(False, 0)
self.osmosdr_source_0.set_gain(satnogs.hw_rx_settings[rx_sdr_device]['rf_gain'], 0)
self.osmosdr_source_0.set_if_gain(satnogs.hw_rx_settings[rx_sdr_device]['if_gain'], 0)
self.osmosdr_source_0.set_bb_gain(satnogs.hw_rx_settings[rx_sdr_device]['bb_gain'], 0)
self.osmosdr_source_0.set_antenna(satnogs.hw_rx_settings[rx_sdr_device]['antenna'], 0)
self.osmosdr_source_0.set_bandwidth(samp_rate_rx, 0)
self.low_pass_filter_0 = filter.fir_filter_ccf(5, firdes.low_pass(
1, int(samp_rate_rx/filter_rate), 2e3, 500, firdes.WIN_HAMMING, 6.76))
self.freq_xlating_fir_filter_xxx_0 = filter.freq_xlating_fir_filter_ccc(int(samp_rate_rx/filter_rate), (xlate_filter_taps), lo_offset, samp_rate_rx)
self.fir_filter_xxx_0 = filter.fir_filter_ccc(1, ([1,] * ndelay))
self.fir_filter_xxx_0.declare_sample_delay(0)
self.blocks_multiply_conjugate_cc_0 = blocks.multiply_conjugate_cc(1)
self.blocks_moving_average_xx_0 = blocks.moving_average_ff(ndelay, 1, 4000)
self.blocks_delay_0 = blocks.delay(gr.sizeof_gr_complex*1, ndelay)
self.blocks_complex_to_mag_squared_0 = blocks.complex_to_mag_squared(1)
self.analog_agc2_xx_0 = analog.agc2_cc(0.01, 0.001, 1.0, 1.0)
self.analog_agc2_xx_0.set_max_gain(65536)
##################################################
# Connections
##################################################
self.msg_connect((self.satnogs_cw_to_symbol_0, 'out'), (self.satnogs_morse_decoder_0, 'in'))
self.msg_connect((self.satnogs_morse_decoder_0, 'out'), (self.satnogs_multi_format_msg_sink_0, 'in'))
self.msg_connect((self.satnogs_tcp_rigctl_msg_source_0, 'freq'), (self.satnogs_coarse_doppler_correction_cc_0, 'freq'))
self.connect((self.analog_agc2_xx_0, 0), (self.blocks_delay_0, 0))
self.connect((self.analog_agc2_xx_0, 0), (self.blocks_multiply_conjugate_cc_0, 0))
self.connect((self.blocks_complex_to_mag_squared_0, 0), (self.blocks_moving_average_xx_0, 0))
self.connect((self.blocks_delay_0, 0), (self.blocks_multiply_conjugate_cc_0, 1))
self.connect((self.blocks_moving_average_xx_0, 0), (self.satnogs_cw_to_symbol_0, 0))
self.connect((self.blocks_multiply_conjugate_cc_0, 0), (self.fir_filter_xxx_0, 0))
self.connect((self.fir_filter_xxx_0, 0), (self.blocks_complex_to_mag_squared_0, 0))
self.connect((self.freq_xlating_fir_filter_xxx_0, 0), (self.low_pass_filter_0, 0))
self.connect((self.low_pass_filter_0, 0), (self.analog_agc2_xx_0, 0))
self.connect((self.osmosdr_source_0, 0), (self.satnogs_coarse_doppler_correction_cc_0, 0))
self.connect((self.satnogs_coarse_doppler_correction_cc_0, 0), (self.freq_xlating_fir_filter_xxx_0, 0))
def get_doppler_correction_per_sec(self):
return self.doppler_correction_per_sec
def set_doppler_correction_per_sec(self, doppler_correction_per_sec):
self.doppler_correction_per_sec = doppler_correction_per_sec
def get_file_path(self):
return self.file_path
def set_file_path(self, file_path):
self.file_path = file_path
def get_lo_offset(self):
return self.lo_offset
def set_lo_offset(self, lo_offset):
self.lo_offset = lo_offset
self.osmosdr_source_0.set_center_freq(self.rx_freq - self.lo_offset, 0)
self.freq_xlating_fir_filter_xxx_0.set_center_freq(self.lo_offset)
def get_ppm(self):
return self.ppm
def set_ppm(self, ppm):
self.ppm = ppm
self.osmosdr_source_0.set_freq_corr(self.ppm, 0)
def get_rigctl_port(self):
return self.rigctl_port
def set_rigctl_port(self, rigctl_port):
self.rigctl_port = rigctl_port
def get_rx_freq(self):
return self.rx_freq
def set_rx_freq(self, rx_freq):
self.rx_freq = rx_freq
self.satnogs_coarse_doppler_correction_cc_0.set_new_freq_locked(self.rx_freq)
self.osmosdr_source_0.set_center_freq(self.rx_freq - self.lo_offset, 0)
def get_rx_sdr_device(self):
return self.rx_sdr_device
def set_rx_sdr_device(self, rx_sdr_device):
self.rx_sdr_device = rx_sdr_device
self.set_samp_rate_rx(satnogs.hw_rx_settings[self.rx_sdr_device]['samp_rate'])
self.osmosdr_source_0.set_gain(satnogs.hw_rx_settings[self.rx_sdr_device]['rf_gain'], 0)
self.osmosdr_source_0.set_if_gain(satnogs.hw_rx_settings[self.rx_sdr_device]['if_gain'], 0)
self.osmosdr_source_0.set_bb_gain(satnogs.hw_rx_settings[self.rx_sdr_device]['bb_gain'], 0)
self.osmosdr_source_0.set_antenna(satnogs.hw_rx_settings[self.rx_sdr_device]['antenna'], 0)
def get_waterfall_file_path(self):
return self.waterfall_file_path
def set_waterfall_file_path(self, waterfall_file_path):
self.waterfall_file_path = waterfall_file_path
def get_wpm(self):
return self.wpm
def set_wpm(self, wpm):
self.wpm = wpm
def get_samp_rate_rx(self):
return self.samp_rate_rx
def set_samp_rate_rx(self, samp_rate_rx):
self.samp_rate_rx = samp_rate_rx
self.set_xlate_filter_taps(firdes.low_pass(1, self.samp_rate_rx, 125000, 25000, firdes.WIN_HAMMING, 6.76))
self.osmosdr_source_0.set_sample_rate(self.samp_rate_rx)
self.osmosdr_source_0.set_bandwidth(self.samp_rate_rx, 0)
self.low_pass_filter_0.set_taps(firdes.low_pass(1, int(self.samp_rate_rx/self.filter_rate), 2e3, 500, firdes.WIN_HAMMING, 6.76))
def get_xlate_filter_taps(self):
return self.xlate_filter_taps
def set_xlate_filter_taps(self, xlate_filter_taps):
self.xlate_filter_taps = xlate_filter_taps
self.freq_xlating_fir_filter_xxx_0.set_taps((self.xlate_filter_taps))
def get_taps(self):
return self.taps
def set_taps(self, taps):
self.taps = taps
def get_ndelay(self):
return self.ndelay
def set_ndelay(self, ndelay):
self.ndelay = ndelay
self.fir_filter_xxx_0.set_taps(([1,] * self.ndelay))
self.blocks_moving_average_xx_0.set_length_and_scale(self.ndelay, 1)
self.blocks_delay_0.set_dly(self.ndelay)
def get_filter_rate(self):
return self.filter_rate
def set_filter_rate(self, filter_rate):
self.filter_rate = filter_rate
self.low_pass_filter_0.set_taps(firdes.low_pass(1, int(self.samp_rate_rx/self.filter_rate), 2e3, 500, firdes.WIN_HAMMING, 6.76))
def argument_parser():
description = 'A CW (Morse) Decoder'
parser = OptionParser(usage="%prog: [options]", option_class=eng_option, description=description)
parser.add_option(
"", "--doppler-correction-per-sec", dest="doppler_correction_per_sec", type="intx", default=1000,
help="Set doppler_correction_per_sec [default=%default]")
parser.add_option(
"", "--file-path", dest="file_path", type="string", default='test.txt',
help="Set file_path [default=%default]")
parser.add_option(
"", "--lo-offset", dest="lo_offset", type="eng_float", default=eng_notation.num_to_str(100e3),
help="Set lo_offset [default=%default]")
parser.add_option(
"", "--ppm", dest="ppm", type="intx", default=0,
help="Set ppm [default=%default]")
parser.add_option(
"", "--rigctl-port", dest="rigctl_port", type="intx", default=4532,
help="Set rigctl_port [default=%default]")
parser.add_option(
"", "--rx-freq", dest="rx_freq", type="eng_float", default=eng_notation.num_to_str(100e6),
help="Set rx_freq [default=%default]")
parser.add_option(
"", "--rx-sdr-device", dest="rx_sdr_device", type="string", default='usrpb200',
help="Set rx_sdr_device [default=%default]")
parser.add_option(
"", "--waterfall-file-path", dest="waterfall_file_path", type="string", default='/tmp/waterfall.dat',
help="Set waterfall_file_path [default=%default]")
parser.add_option(
"", "--wpm", dest="wpm", type="intx", default=22,
help="Set wpm [default=%default]")
return parser
def main(top_block_cls=satnogs_cw_decoder, options=None):
if options is None:
options, _ = argument_parser().parse_args()
tb = top_block_cls(doppler_correction_per_sec=options.doppler_correction_per_sec, file_path=options.file_path, lo_offset=options.lo_offset, ppm=options.ppm, rigctl_port=options.rigctl_port, rx_freq=options.rx_freq, rx_sdr_device=options.rx_sdr_device, waterfall_file_path=options.waterfall_file_path, wpm=options.wpm)
tb.start()
tb.wait()
if __name__ == '__main__':
main()

View File

@ -34,62 +34,63 @@ namespace gr
{
cw_to_symbol::sptr
cw_to_symbol::make (double sampling_rate, float threshold,
float conf_level, size_t wpm, bool auto_config)
cw_to_symbol::make (double sampling_rate, float threshold, float conf_level,
size_t wpm, bool auto_config)
{
return gnuradio::get_initial_sptr (
new cw_to_symbol_impl (sampling_rate, threshold, conf_level,
wpm, auto_config));
new cw_to_symbol_impl (sampling_rate, threshold, conf_level, wpm,
auto_config));
}
/*
* The private constructor
*/
cw_to_symbol_impl::cw_to_symbol_impl (double sampling_rate, float threshold,
float conf_level, size_t wpm,
bool auto_config) :
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(conf_level),
d_sync_limit(15),
d_auto_sync(auto_config),
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),
d_est_cnt(0),
d_mean_cnt(0),
d_have_sync(!auto_config),
d_seq_started(false),
d_sync_state(SYNC_TRIGGER_OFF)
float conf_level, size_t wpm,
bool auto_config) :
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 (conf_level),
d_sync_limit (15),
d_auto_sync (auto_config),
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),
d_est_cnt (0),
d_mean_cnt (0),
d_have_sync (!auto_config),
d_seq_started (false),
d_sync_state (SYNC_TRIGGER_OFF)
{
message_port_register_in(pmt::mp("act_threshold"));
message_port_register_in(pmt::mp("sync"));
message_port_register_out(pmt::mp("out"));
message_port_register_in (pmt::mp ("act_threshold"));
message_port_register_in (pmt::mp ("sync"));
message_port_register_out (pmt::mp ("out"));
/* Register the message handlers */
set_msg_handler(pmt::mp("act_threshold"),
boost::bind(&cw_to_symbol_impl::set_act_threshold_msg_handler,
this, _1));
set_msg_handler(pmt::mp("sync"),
boost::bind(&cw_to_symbol_impl::sync_msg_handler,
this, _1));
set_msg_handler (
pmt::mp ("act_threshold"),
boost::bind (&cw_to_symbol_impl::set_act_threshold_msg_handler, this,
_1));
set_msg_handler (
pmt::mp ("sync"),
boost::bind (&cw_to_symbol_impl::sync_msg_handler, this, _1));
if( auto_config ){
d_dot_samples = (1.2/MIN_WPM) / (1.0 / d_sampling_rate);
if (auto_config) {
d_dot_samples = (1.2 / MIN_WPM) / (1.0 / d_sampling_rate);
}
}
inline void
cw_to_symbol_impl::send_symbol_msg (morse_symbol_t s)
{
message_port_pub(pmt::mp("out"), pmt::from_long(s));
message_port_pub (pmt::mp ("out"), pmt::from_long (s));
}
/*
@ -138,177 +139,179 @@ namespace gr
void
cw_to_symbol_impl::set_act_threshold_msg_handler (pmt::pmt_t msg)
{
if(pmt::is_pair(msg)){
set_act_threshold(pmt::to_double(pmt::cdr(msg)));
if (pmt::is_pair (msg)) {
set_act_threshold (pmt::to_double (pmt::cdr (msg)));
}
}
void
cw_to_symbol_impl::sync_msg_handler (pmt::pmt_t msg)
{
if(pmt::is_pair(msg)){
if(pmt::to_bool(pmt::cdr(msg))){
start_timing_recovery();
}
if (pmt::is_pair (msg)) {
if (pmt::to_bool (pmt::cdr (msg))) {
start_timing_recovery ();
}
}
}
int
cw_to_symbol_impl::work (int noutput_items,
gr_vector_const_void_star &input_items,
gr_vector_void_star &output_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];
/* The estimation for the WPM has not yet been computed */
if(!d_have_sync){
for(i = 0; i < noutput_items; i++) {
switch (d_sync_state) {
case SYNC_TRIGGER_OFF:
if(in[i] > d_act_thrshld) {
d_sync_state = SYNC_TRIGGER_ON;
}
break;
case SYNC_TRIGGER_ON:
if(in[i] > d_act_thrshld) {
d_state_cnt++;
}
else {
/* Trigger is OFF. Extract the best timing information available */
d_sync_state = SYNC_TRIGGER_OFF;
estimate_dot_duration(d_state_cnt);
d_state_cnt = 0;
if (!d_have_sync) {
for (i = 0; i < noutput_items; i++) {
switch (d_sync_state)
{
case SYNC_TRIGGER_OFF:
if (in[i] > d_act_thrshld) {
d_sync_state = SYNC_TRIGGER_ON;
}
break;
case SYNC_TRIGGER_ON:
if (in[i] > d_act_thrshld) {
d_state_cnt++;
}
else {
/* Trigger is OFF. Extract the best timing information available */
d_sync_state = SYNC_TRIGGER_OFF;
estimate_dot_duration (d_state_cnt);
d_state_cnt = 0;
/*
* If the sync process was over set the state to idle and
* return for proper decoding
*/
if(d_have_sync) {
set_idle();
return i+1;
}
}
break;
}
}
/*
* If the sync process was over set the state to idle and
* return for proper decoding
*/
if (d_have_sync) {
set_idle ();
return i + 1;
}
}
break;
}
}
return noutput_items;
return noutput_items;
}
for(i = 0; i < noutput_items; i++) {
switch(d_state){
case IDLE:
if(in[i] > d_act_thrshld) {
set_short_on();
}
break;
for (i = 0; i < noutput_items; i++) {
switch (d_state)
{
case IDLE:
if (in[i] > d_act_thrshld) {
set_short_on ();
}
break;
case SHORT_ON_PERIOD:
if( in[i] > d_act_thrshld ) {
d_state_cnt++;
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.
*/
conf_lvl = ((float) d_state_cnt) / d_dot_samples;
if(conf_lvl > d_confidence_level){
LOG_DEBUG("DOT");
send_symbol_msg(MORSE_DOT);
}
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.
*/
conf_lvl = ((float) d_state_cnt) / d_dot_samples;
if (conf_lvl > d_confidence_level) {
LOG_DEBUG("DOT");
send_symbol_msg (MORSE_DOT);
}
/* Go find a possible short pause symbol */
set_short_off();
}
break;
/* Go find a possible short pause symbol */
set_short_off ();
}
break;
case LONG_ON_PERIOD:
if( in[i] > d_act_thrshld ) {
d_state_cnt++;
}
else {
conf_lvl = ((float) d_state_cnt) / d_dash_samples;
if(conf_lvl > d_confidence_level) {
LOG_DEBUG("DASH");
send_symbol_msg(MORSE_DASH);
set_short_off();
break;
}
case LONG_ON_PERIOD:
if (in[i] > d_act_thrshld) {
d_state_cnt++;
}
else {
conf_lvl = ((float) d_state_cnt) / d_dash_samples;
if (conf_lvl > d_confidence_level) {
LOG_DEBUG("DASH");
send_symbol_msg (MORSE_DASH);
set_short_off ();
break;
}
/* Perhaps this was a short on symbol */
conf_lvl = ((float) d_state_cnt) / d_dot_samples;
if(conf_lvl > d_confidence_level) {
LOG_DEBUG("DOT");
send_symbol_msg(MORSE_DOT);
set_short_off();
}
/* Perhaps this was a short on symbol */
conf_lvl = ((float) d_state_cnt) / d_dot_samples;
if (conf_lvl > d_confidence_level) {
LOG_DEBUG("DOT");
send_symbol_msg (MORSE_DOT);
set_short_off ();
}
}
break;
}
break;
case SHORT_OFF_PERIOD:
if(in[i] > d_act_thrshld) {
/*
* Before going to ON state, again check if a short pause symbol
* should be produced
*/
conf_lvl = ((float) d_pause_cnt) / d_short_pause_samples;
if(conf_lvl > d_confidence_level) {
LOG_DEBUG("Short space");
send_symbol_msg(MORSE_S_SPACE);
}
set_short_on();
}
else {
d_pause_cnt++;
if(d_pause_cnt > d_short_pause_samples) {
set_long_off();
}
}
break;
case SHORT_OFF_PERIOD:
if (in[i] > d_act_thrshld) {
/*
* Before going to ON state, again check if a short pause symbol
* should be produced
*/
conf_lvl = ((float) d_pause_cnt) / d_short_pause_samples;
if (conf_lvl > d_confidence_level) {
LOG_DEBUG("Short space");
send_symbol_msg (MORSE_S_SPACE);
}
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) {
conf_lvl = ((float) d_pause_cnt) / d_long_pause_samples;
if (conf_lvl > d_confidence_level) {
LOG_DEBUG("Long space");
send_symbol_msg (MORSE_L_SPACE);
set_idle();
break;
}
else {
LOG_DEBUG("Short space");
send_symbol_msg (MORSE_S_SPACE);
}
set_short_on();
}
else {
d_pause_cnt++;
/*
* If the pause duration is greater than the long pause symbol,
* definitely a long pause symbol should be produced
*/
if(d_pause_cnt > d_long_pause_samples) {
LOG_DEBUG("Long space");
send_symbol_msg(MORSE_L_SPACE);
d_seq_started = false;
set_idle();
}
}
break;
default:
LOG_ERROR("Invalid State.");
d_state = IDLE;
}
case LONG_OFF_PERIOD:
if (in[i] > d_act_thrshld) {
conf_lvl = ((float) d_pause_cnt) / d_long_pause_samples;
if (conf_lvl > d_confidence_level) {
LOG_DEBUG("Long space");
send_symbol_msg (MORSE_L_SPACE);
set_idle ();
break;
}
else {
LOG_DEBUG("Short space");
send_symbol_msg (MORSE_S_SPACE);
}
set_short_on ();
}
else {
d_pause_cnt++;
/*
* If the pause duration is greater than the long pause symbol,
* definitely a long pause symbol should be produced
*/
if (d_pause_cnt > d_long_pause_samples) {
LOG_DEBUG("Long space");
send_symbol_msg (MORSE_L_SPACE);
d_seq_started = false;
set_idle ();
}
}
break;
default:
LOG_ERROR("Invalid State.");
d_state = IDLE;
}
}
return noutput_items;
}
@ -320,9 +323,9 @@ namespace gr
* The estimations should be in a logical range of
* [MIN_WPM - MAX_WPM] WPM. Otherwise it is considered a false alarm.
*/
if( estimate < (1.2/MAX_WPM) / (1.0 / d_sampling_rate)
|| estimate >= (1.2/MIN_WPM) / (1.0 / d_sampling_rate)) {
return;
if (estimate < (1.2 / MAX_WPM) / (1.0 / d_sampling_rate)
|| estimate >= (1.2 / MIN_WPM) / (1.0 / d_sampling_rate)) {
return;
}
/*
@ -330,34 +333,34 @@ namespace gr
* At the end the resulting dot duration will be a mean value of
* possible dot durations
*/
if(estimate < d_dot_samples) {
d_dot_samples = estimate;
d_mean_cnt += estimate;
d_est_cnt++;
if (estimate < d_dot_samples) {
d_dot_samples = estimate;
d_mean_cnt += estimate;
d_est_cnt++;
}
else if(mape(d_dot_samples, estimate) < 1 - d_confidence_level) {
d_mean_cnt += estimate;
d_est_cnt++;
else if (mape (d_dot_samples, estimate) < 1 - d_confidence_level) {
d_mean_cnt += estimate;
d_est_cnt++;
}
/*
* Perhaps the synchronization process was triggered by a dash.
* Check this possibility and use MAPE and confidence level to
* decide or not to take into consideration the new estimation
*/
else if ( mape(d_dot_samples, estimate / 3.0) < 1 - d_confidence_level ) {
d_mean_cnt += estimate / 3.0;
d_est_cnt++;
else if (mape (d_dot_samples, estimate / 3.0) < 1 - d_confidence_level) {
d_mean_cnt += estimate / 3.0;
d_est_cnt++;
}
/*
* If the synchronization process is over update the dot duration
* with an average estimation
*/
if(d_est_cnt == d_sync_limit) {
d_have_sync = true;
d_dot_samples = d_mean_cnt / d_sync_limit;
set_symbols_duration();
std::cout << "Have sync" << d_dot_samples << std::endl;
if (d_est_cnt == d_sync_limit) {
d_have_sync = true;
d_dot_samples = d_mean_cnt / d_sync_limit;
set_symbols_duration ();
std::cout << "Have sync" << d_dot_samples << std::endl;
}
}
@ -397,11 +400,11 @@ namespace gr
cw_to_symbol_impl::set_act_threshold (float thrhld)
{
d_act_thrshld = thrhld;
/* When a new activation threshold is set,
* if the automatic synchronization is set it should be again performed
/* When a new activation threshold is set and automatic synchronization
* is set, the automatic timing recovery should be again performed
*/
if(d_auto_sync) {
reset_sync();
if (d_auto_sync) {
reset_sync ();
}
}
@ -412,7 +415,7 @@ namespace gr
void
cw_to_symbol_impl::start_timing_recovery ()
{
reset_sync();
reset_sync ();
}
} /* namespace satnogs */