Merge branch 'cw' into 'master'
CW decoder See merge request librespacefoundation/satnogs/gr-satnogs!117
This commit is contained in:
commit
05eacd4eec
|
@ -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
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,426 @@
|
|||
#!/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: Wed Nov 1 21:56:56 2017
|
||||
##################################################
|
||||
|
||||
if __name__ == '__main__':
|
||||
import ctypes
|
||||
import sys
|
||||
if sys.platform.startswith('linux'):
|
||||
try:
|
||||
x11 = ctypes.cdll.LoadLibrary('libX11.so')
|
||||
x11.XInitThreads()
|
||||
except:
|
||||
print "Warning: failed to XInitThreads()"
|
||||
|
||||
from PyQt4 import Qt
|
||||
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 sys
|
||||
import time
|
||||
from gnuradio import qtgui
|
||||
|
||||
|
||||
class satnogs_cw_decoder(gr.top_block, Qt.QWidget):
|
||||
|
||||
def __init__(self, antenna=satnogs.not_set_antenna, bb_gain=satnogs.not_set_rx_bb_gain, cw_offset=700, decoded_data_file_path='/tmp/.satnogs/data/data', dev_args=satnogs.not_set_dev_args, doppler_correction_per_sec=1000, enable_iq_dump=0, file_path='test.txt', if_gain=satnogs.not_set_rx_if_gain, iq_file_path='/tmp/iq.dat', lo_offset=100e3, ppm=0, rf_gain=satnogs.not_set_rx_rf_gain, rigctl_port=4532, rx_freq=100e6, rx_sdr_device='usrpb200', waterfall_file_path='/tmp/waterfall.dat', wpm=20):
|
||||
gr.top_block.__init__(self, "CW Decoder")
|
||||
Qt.QWidget.__init__(self)
|
||||
self.setWindowTitle("CW Decoder")
|
||||
qtgui.util.check_set_qss()
|
||||
try:
|
||||
self.setWindowIcon(Qt.QIcon.fromTheme('gnuradio-grc'))
|
||||
except:
|
||||
pass
|
||||
self.top_scroll_layout = Qt.QVBoxLayout()
|
||||
self.setLayout(self.top_scroll_layout)
|
||||
self.top_scroll = Qt.QScrollArea()
|
||||
self.top_scroll.setFrameStyle(Qt.QFrame.NoFrame)
|
||||
self.top_scroll_layout.addWidget(self.top_scroll)
|
||||
self.top_scroll.setWidgetResizable(True)
|
||||
self.top_widget = Qt.QWidget()
|
||||
self.top_scroll.setWidget(self.top_widget)
|
||||
self.top_layout = Qt.QVBoxLayout(self.top_widget)
|
||||
self.top_grid_layout = Qt.QGridLayout()
|
||||
self.top_layout.addLayout(self.top_grid_layout)
|
||||
|
||||
self.settings = Qt.QSettings("GNU Radio", "satnogs_cw_decoder")
|
||||
self.restoreGeometry(self.settings.value("geometry").toByteArray())
|
||||
|
||||
##################################################
|
||||
# Parameters
|
||||
##################################################
|
||||
self.antenna = antenna
|
||||
self.bb_gain = bb_gain
|
||||
self.cw_offset = cw_offset
|
||||
self.decoded_data_file_path = decoded_data_file_path
|
||||
self.dev_args = dev_args
|
||||
self.doppler_correction_per_sec = doppler_correction_per_sec
|
||||
self.enable_iq_dump = enable_iq_dump
|
||||
self.file_path = file_path
|
||||
self.if_gain = if_gain
|
||||
self.iq_file_path = iq_file_path
|
||||
self.lo_offset = lo_offset
|
||||
self.ppm = ppm
|
||||
self.rf_gain = rf_gain
|
||||
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.xlating_decimation = xlating_decimation = 5
|
||||
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 = 250
|
||||
self.lpf_decimation = lpf_decimation = 5
|
||||
self.audio_samp_rate = audio_samp_rate = 48000
|
||||
|
||||
##################################################
|
||||
# Blocks
|
||||
##################################################
|
||||
self.satnogs_waterfall_sink_0 = satnogs.waterfall_sink((samp_rate_rx/xlating_decimation), 0.0, 10, 1024, waterfall_file_path, 1)
|
||||
self.satnogs_tcp_rigctl_msg_source_0 = satnogs.tcp_rigctl_msg_source("127.0.0.1", rigctl_port, False, 1000, 1500)
|
||||
self.satnogs_ogg_encoder_0 = satnogs.ogg_encoder(file_path, audio_samp_rate, 1.0)
|
||||
self.satnogs_morse_decoder_0 = satnogs.morse_decoder(ord('#'))
|
||||
self.satnogs_iq_sink_0 = satnogs.iq_sink(16768, iq_file_path, False, enable_iq_dump)
|
||||
self.satnogs_frame_file_sink_0_0 = satnogs.frame_file_sink(decoded_data_file_path, 0)
|
||||
self.satnogs_cw_to_symbol_0 = satnogs.cw_to_symbol(int((samp_rate_rx/xlating_decimation)/lpf_decimation), 300000, 0.9, wpm)
|
||||
self.satnogs_coarse_doppler_correction_cc_0 = satnogs.coarse_doppler_correction_cc(rx_freq, samp_rate_rx)
|
||||
self.rational_resampler_xxx_0 = filter.rational_resampler_ccc(
|
||||
interpolation=audio_samp_rate,
|
||||
decimation=int((samp_rate_rx/xlating_decimation)/lpf_decimation),
|
||||
taps=None,
|
||||
fractional_bw=None,
|
||||
)
|
||||
self.osmosdr_source_0 = osmosdr.source( args="numchan=" + str(1) + " " + satnogs.handle_rx_dev_args(rx_sdr_device, dev_args) )
|
||||
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.handle_rx_rf_gain(rx_sdr_device, rf_gain), 0)
|
||||
self.osmosdr_source_0.set_if_gain(satnogs.handle_rx_if_gain(rx_sdr_device, if_gain), 0)
|
||||
self.osmosdr_source_0.set_bb_gain(satnogs.handle_rx_bb_gain(rx_sdr_device, bb_gain), 0)
|
||||
self.osmosdr_source_0.set_antenna(satnogs.handle_rx_antenna(rx_sdr_device, antenna), 0)
|
||||
self.osmosdr_source_0.set_bandwidth(samp_rate_rx, 0)
|
||||
|
||||
self.low_pass_filter_0 = filter.fir_filter_ccf(lpf_decimation, firdes.low_pass(
|
||||
1, samp_rate_rx/xlating_decimation, 2e3, 500, firdes.WIN_HAMMING, 6.76))
|
||||
self.freq_xlating_fir_filter_xxx_0 = filter.freq_xlating_fir_filter_ccc(xlating_decimation, (xlate_filter_taps), lo_offset - cw_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, 40)
|
||||
self.blocks_delay_0 = blocks.delay(gr.sizeof_gr_complex*1, ndelay)
|
||||
self.blocks_complex_to_real_0 = blocks.complex_to_real(1)
|
||||
self.blocks_complex_to_mag_squared_0 = blocks.complex_to_mag_squared(1)
|
||||
self.analog_agc2_xx_0 = analog.agc2_cc(0.1, 0.8, 0.6, 0.0)
|
||||
self.analog_agc2_xx_0.set_max_gain(1e3)
|
||||
|
||||
##################################################
|
||||
# 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_frame_file_sink_0_0, 'frame'))
|
||||
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_complex_to_real_0, 0), (self.satnogs_ogg_encoder_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.low_pass_filter_0, 0), (self.rational_resampler_xxx_0, 0))
|
||||
self.connect((self.osmosdr_source_0, 0), (self.satnogs_coarse_doppler_correction_cc_0, 0))
|
||||
self.connect((self.rational_resampler_xxx_0, 0), (self.blocks_complex_to_real_0, 0))
|
||||
self.connect((self.rational_resampler_xxx_0, 0), (self.satnogs_iq_sink_0, 0))
|
||||
self.connect((self.rational_resampler_xxx_0, 0), (self.satnogs_waterfall_sink_0, 0))
|
||||
self.connect((self.satnogs_coarse_doppler_correction_cc_0, 0), (self.freq_xlating_fir_filter_xxx_0, 0))
|
||||
|
||||
def closeEvent(self, event):
|
||||
self.settings = Qt.QSettings("GNU Radio", "satnogs_cw_decoder")
|
||||
self.settings.setValue("geometry", self.saveGeometry())
|
||||
event.accept()
|
||||
|
||||
def get_antenna(self):
|
||||
return self.antenna
|
||||
|
||||
def set_antenna(self, antenna):
|
||||
self.antenna = antenna
|
||||
self.osmosdr_source_0.set_antenna(satnogs.handle_rx_antenna(self.rx_sdr_device, self.antenna), 0)
|
||||
|
||||
def get_bb_gain(self):
|
||||
return self.bb_gain
|
||||
|
||||
def set_bb_gain(self, bb_gain):
|
||||
self.bb_gain = bb_gain
|
||||
self.osmosdr_source_0.set_bb_gain(satnogs.handle_rx_bb_gain(self.rx_sdr_device, self.bb_gain), 0)
|
||||
|
||||
def get_cw_offset(self):
|
||||
return self.cw_offset
|
||||
|
||||
def set_cw_offset(self, cw_offset):
|
||||
self.cw_offset = cw_offset
|
||||
self.freq_xlating_fir_filter_xxx_0.set_center_freq(self.lo_offset - self.cw_offset)
|
||||
|
||||
def get_decoded_data_file_path(self):
|
||||
return self.decoded_data_file_path
|
||||
|
||||
def set_decoded_data_file_path(self, decoded_data_file_path):
|
||||
self.decoded_data_file_path = decoded_data_file_path
|
||||
|
||||
def get_dev_args(self):
|
||||
return self.dev_args
|
||||
|
||||
def set_dev_args(self, dev_args):
|
||||
self.dev_args = dev_args
|
||||
|
||||
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_enable_iq_dump(self):
|
||||
return self.enable_iq_dump
|
||||
|
||||
def set_enable_iq_dump(self, enable_iq_dump):
|
||||
self.enable_iq_dump = enable_iq_dump
|
||||
|
||||
def get_file_path(self):
|
||||
return self.file_path
|
||||
|
||||
def set_file_path(self, file_path):
|
||||
self.file_path = file_path
|
||||
|
||||
def get_if_gain(self):
|
||||
return self.if_gain
|
||||
|
||||
def set_if_gain(self, if_gain):
|
||||
self.if_gain = if_gain
|
||||
self.osmosdr_source_0.set_if_gain(satnogs.handle_rx_if_gain(self.rx_sdr_device, self.if_gain), 0)
|
||||
|
||||
def get_iq_file_path(self):
|
||||
return self.iq_file_path
|
||||
|
||||
def set_iq_file_path(self, iq_file_path):
|
||||
self.iq_file_path = iq_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 - self.cw_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_rf_gain(self):
|
||||
return self.rf_gain
|
||||
|
||||
def set_rf_gain(self, rf_gain):
|
||||
self.rf_gain = rf_gain
|
||||
self.osmosdr_source_0.set_gain(satnogs.handle_rx_rf_gain(self.rx_sdr_device, self.rf_gain), 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.handle_rx_rf_gain(self.rx_sdr_device, self.rf_gain), 0)
|
||||
self.osmosdr_source_0.set_if_gain(satnogs.handle_rx_if_gain(self.rx_sdr_device, self.if_gain), 0)
|
||||
self.osmosdr_source_0.set_bb_gain(satnogs.handle_rx_bb_gain(self.rx_sdr_device, self.bb_gain), 0)
|
||||
self.osmosdr_source_0.set_antenna(satnogs.handle_rx_antenna(self.rx_sdr_device, self.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, self.samp_rate_rx/self.xlating_decimation, 2e3, 500, firdes.WIN_HAMMING, 6.76))
|
||||
|
||||
def get_xlating_decimation(self):
|
||||
return self.xlating_decimation
|
||||
|
||||
def set_xlating_decimation(self, xlating_decimation):
|
||||
self.xlating_decimation = xlating_decimation
|
||||
self.low_pass_filter_0.set_taps(firdes.low_pass(1, self.samp_rate_rx/self.xlating_decimation, 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_lpf_decimation(self):
|
||||
return self.lpf_decimation
|
||||
|
||||
def set_lpf_decimation(self, lpf_decimation):
|
||||
self.lpf_decimation = lpf_decimation
|
||||
|
||||
def get_audio_samp_rate(self):
|
||||
return self.audio_samp_rate
|
||||
|
||||
def set_audio_samp_rate(self, audio_samp_rate):
|
||||
self.audio_samp_rate = audio_samp_rate
|
||||
|
||||
|
||||
def argument_parser():
|
||||
description = 'A CW (Morse) Decoder'
|
||||
parser = OptionParser(usage="%prog: [options]", option_class=eng_option, description=description)
|
||||
parser.add_option(
|
||||
"", "--antenna", dest="antenna", type="string", default=satnogs.not_set_antenna,
|
||||
help="Set antenna [default=%default]")
|
||||
parser.add_option(
|
||||
"", "--bb-gain", dest="bb_gain", type="eng_float", default=eng_notation.num_to_str(satnogs.not_set_rx_bb_gain),
|
||||
help="Set bb_gain [default=%default]")
|
||||
parser.add_option(
|
||||
"", "--cw-offset", dest="cw_offset", type="eng_float", default=eng_notation.num_to_str(700),
|
||||
help="Set cw_offset [default=%default]")
|
||||
parser.add_option(
|
||||
"", "--decoded-data-file-path", dest="decoded_data_file_path", type="string", default='/tmp/.satnogs/data/data',
|
||||
help="Set decoded_data_file_path [default=%default]")
|
||||
parser.add_option(
|
||||
"", "--dev-args", dest="dev_args", type="string", default=satnogs.not_set_dev_args,
|
||||
help="Set dev_args [default=%default]")
|
||||
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(
|
||||
"", "--enable-iq-dump", dest="enable_iq_dump", type="intx", default=0,
|
||||
help="Set enable_iq_dump [default=%default]")
|
||||
parser.add_option(
|
||||
"", "--file-path", dest="file_path", type="string", default='test.txt',
|
||||
help="Set file_path [default=%default]")
|
||||
parser.add_option(
|
||||
"", "--if-gain", dest="if_gain", type="eng_float", default=eng_notation.num_to_str(satnogs.not_set_rx_if_gain),
|
||||
help="Set if_gain [default=%default]")
|
||||
parser.add_option(
|
||||
"", "--iq-file-path", dest="iq_file_path", type="string", default='/tmp/iq.dat',
|
||||
help="Set iq_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(
|
||||
"", "--rf-gain", dest="rf_gain", type="eng_float", default=eng_notation.num_to_str(satnogs.not_set_rx_rf_gain),
|
||||
help="Set rf_gain [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=20,
|
||||
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()
|
||||
|
||||
from distutils.version import StrictVersion
|
||||
if StrictVersion(Qt.qVersion()) >= StrictVersion("4.5.0"):
|
||||
style = gr.prefs().get_string('qtgui', 'style', 'raster')
|
||||
Qt.QApplication.setGraphicsSystem(style)
|
||||
qapp = Qt.QApplication(sys.argv)
|
||||
|
||||
tb = top_block_cls(antenna=options.antenna, bb_gain=options.bb_gain, cw_offset=options.cw_offset, decoded_data_file_path=options.decoded_data_file_path, dev_args=options.dev_args, doppler_correction_per_sec=options.doppler_correction_per_sec, enable_iq_dump=options.enable_iq_dump, file_path=options.file_path, if_gain=options.if_gain, iq_file_path=options.iq_file_path, lo_offset=options.lo_offset, ppm=options.ppm, rf_gain=options.rf_gain, 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.show()
|
||||
|
||||
def quitting():
|
||||
tb.stop()
|
||||
tb.wait()
|
||||
qapp.connect(qapp, Qt.SIGNAL("aboutToQuit()"), quitting)
|
||||
qapp.exec_()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
|
@ -1,5 +1,5 @@
|
|||
<?xml version='1.0' encoding='utf-8'?>
|
||||
<?grc format='1' created='3.7.9'?>
|
||||
<?grc format='1' created='3.7.11'?>
|
||||
<flow_graph>
|
||||
<timestamp>Sun Jan 17 23:03:00 2016</timestamp>
|
||||
<block>
|
||||
|
@ -10,7 +10,7 @@
|
|||
</param>
|
||||
<param>
|
||||
<key>window_size</key>
|
||||
<value></value>
|
||||
<value>2048,1080</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>category</key>
|
||||
|
@ -148,15 +148,16 @@
|
|||
<key>variable</key>
|
||||
<param>
|
||||
<key>comment</key>
|
||||
<value>The frequency of the CW signal</value>
|
||||
<value>The number of taps depends on the number of samples
|
||||
of a full period of the CW signal with frequency freq.</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>_enabled</key>
|
||||
<value>True</value>
|
||||
<value>1</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>_coordinate</key>
|
||||
<value>(840, 13)</value>
|
||||
<value>(552, 13)</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>_rotation</key>
|
||||
|
@ -164,11 +165,11 @@
|
|||
</param>
|
||||
<param>
|
||||
<key>id</key>
|
||||
<value>freq</value>
|
||||
<value>ndelay</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>value</key>
|
||||
<value>700.0</value>
|
||||
<value>100</value>
|
||||
</param>
|
||||
</block>
|
||||
<block>
|
||||
|
@ -261,34 +262,6 @@
|
|||
<value>8000</value>
|
||||
</param>
|
||||
</block>
|
||||
<block>
|
||||
<key>variable</key>
|
||||
<param>
|
||||
<key>comment</key>
|
||||
<value>The number of taps depends on the number of samples
|
||||
of a full period of the CW signal with frequency freq.</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>_enabled</key>
|
||||
<value>True</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>_coordinate</key>
|
||||
<value>(552, 13)</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>_rotation</key>
|
||||
<value>0</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>id</key>
|
||||
<value>taps</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>value</key>
|
||||
<value>int(math.ceil(samp_rate/freq))</value>
|
||||
</param>
|
||||
</block>
|
||||
<block>
|
||||
<key>variable</key>
|
||||
<param>
|
||||
|
@ -320,7 +293,7 @@ of a full period of the CW signal with frequency freq.</value>
|
|||
<key>analog_agc2_xx</key>
|
||||
<param>
|
||||
<key>attack_rate</key>
|
||||
<value>6.25e-3</value>
|
||||
<value>0.01</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>alias</key>
|
||||
|
@ -336,7 +309,7 @@ of a full period of the CW signal with frequency freq.</value>
|
|||
</param>
|
||||
<param>
|
||||
<key>decay_rate</key>
|
||||
<value>6.25e-3</value>
|
||||
<value>0.001</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>_enabled</key>
|
||||
|
@ -344,7 +317,7 @@ of a full period of the CW signal with frequency freq.</value>
|
|||
</param>
|
||||
<param>
|
||||
<key>_coordinate</key>
|
||||
<value>(608, 336)</value>
|
||||
<value>(736, 376)</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>_rotation</key>
|
||||
|
@ -462,7 +435,7 @@ of a full period of the CW signal with frequency freq.</value>
|
|||
</param>
|
||||
<param>
|
||||
<key>_coordinate</key>
|
||||
<value>(960, 188)</value>
|
||||
<value>(711, 291)</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>_rotation</key>
|
||||
|
@ -485,6 +458,85 @@ of a full period of the CW signal with frequency freq.</value>
|
|||
<value>samp_rate</value>
|
||||
</param>
|
||||
</block>
|
||||
<block>
|
||||
<key>band_pass_filter</key>
|
||||
<param>
|
||||
<key>beta</key>
|
||||
<value>6.76</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>alias</key>
|
||||
<value></value>
|
||||
</param>
|
||||
<param>
|
||||
<key>comment</key>
|
||||
<value></value>
|
||||
</param>
|
||||
<param>
|
||||
<key>affinity</key>
|
||||
<value></value>
|
||||
</param>
|
||||
<param>
|
||||
<key>decim</key>
|
||||
<value>1</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>_enabled</key>
|
||||
<value>True</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>type</key>
|
||||
<value>fir_filter_fff</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>_coordinate</key>
|
||||
<value>(511, 355)</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>_rotation</key>
|
||||
<value>0</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>gain</key>
|
||||
<value>1</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>high_cutoff_freq</key>
|
||||
<value>1000</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>id</key>
|
||||
<value>band_pass_filter_0</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>interp</key>
|
||||
<value>1</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>low_cutoff_freq</key>
|
||||
<value>200</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>maxoutbuf</key>
|
||||
<value>0</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>minoutbuf</key>
|
||||
<value>0</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>samp_rate</key>
|
||||
<value>samp_rate</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>width</key>
|
||||
<value>100</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>win</key>
|
||||
<value>firdes.WIN_HAMMING</value>
|
||||
</param>
|
||||
</block>
|
||||
<block>
|
||||
<key>blocks_add_xx</key>
|
||||
<param>
|
||||
|
@ -536,6 +588,61 @@ of a full period of the CW signal with frequency freq.</value>
|
|||
<value>1</value>
|
||||
</param>
|
||||
</block>
|
||||
<block>
|
||||
<key>blocks_delay</key>
|
||||
<param>
|
||||
<key>alias</key>
|
||||
<value></value>
|
||||
</param>
|
||||
<param>
|
||||
<key>comment</key>
|
||||
<value></value>
|
||||
</param>
|
||||
<param>
|
||||
<key>affinity</key>
|
||||
<value></value>
|
||||
</param>
|
||||
<param>
|
||||
<key>delay</key>
|
||||
<value>ndelay</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>_enabled</key>
|
||||
<value>True</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>_coordinate</key>
|
||||
<value>(1000, 428)</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>_rotation</key>
|
||||
<value>0</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>id</key>
|
||||
<value>blocks_delay_0</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>maxoutbuf</key>
|
||||
<value>0</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>minoutbuf</key>
|
||||
<value>0</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>num_ports</key>
|
||||
<value>1</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>type</key>
|
||||
<value>float</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>vlen</key>
|
||||
<value>1</value>
|
||||
</param>
|
||||
</block>
|
||||
<block>
|
||||
<key>blocks_moving_average_xx</key>
|
||||
<param>
|
||||
|
@ -556,7 +663,7 @@ of a full period of the CW signal with frequency freq.</value>
|
|||
</param>
|
||||
<param>
|
||||
<key>_coordinate</key>
|
||||
<value>(1000, 438)</value>
|
||||
<value>(1304, 556)</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>_rotation</key>
|
||||
|
@ -568,7 +675,7 @@ of a full period of the CW signal with frequency freq.</value>
|
|||
</param>
|
||||
<param>
|
||||
<key>length</key>
|
||||
<value>taps</value>
|
||||
<value>ndelay</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>max_iter</key>
|
||||
|
@ -615,7 +722,7 @@ of a full period of the CW signal with frequency freq.</value>
|
|||
</param>
|
||||
<param>
|
||||
<key>_coordinate</key>
|
||||
<value>(304, 364)</value>
|
||||
<value>(296, 268)</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>_rotation</key>
|
||||
|
@ -666,7 +773,7 @@ of a full period of the CW signal with frequency freq.</value>
|
|||
</param>
|
||||
<param>
|
||||
<key>_coordinate</key>
|
||||
<value>(336, 220)</value>
|
||||
<value>(296, 212)</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>_rotation</key>
|
||||
|
@ -693,6 +800,108 @@ of a full period of the CW signal with frequency freq.</value>
|
|||
<value>1</value>
|
||||
</param>
|
||||
</block>
|
||||
<block>
|
||||
<key>blocks_multiply_xx</key>
|
||||
<param>
|
||||
<key>alias</key>
|
||||
<value></value>
|
||||
</param>
|
||||
<param>
|
||||
<key>comment</key>
|
||||
<value></value>
|
||||
</param>
|
||||
<param>
|
||||
<key>affinity</key>
|
||||
<value></value>
|
||||
</param>
|
||||
<param>
|
||||
<key>_enabled</key>
|
||||
<value>True</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>_coordinate</key>
|
||||
<value>(1152, 408)</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>_rotation</key>
|
||||
<value>0</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>id</key>
|
||||
<value>blocks_multiply_xx_0</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>type</key>
|
||||
<value>float</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>maxoutbuf</key>
|
||||
<value>0</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>minoutbuf</key>
|
||||
<value>0</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>num_inputs</key>
|
||||
<value>2</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>vlen</key>
|
||||
<value>1</value>
|
||||
</param>
|
||||
</block>
|
||||
<block>
|
||||
<key>blocks_multiply_xx</key>
|
||||
<param>
|
||||
<key>alias</key>
|
||||
<value></value>
|
||||
</param>
|
||||
<param>
|
||||
<key>comment</key>
|
||||
<value></value>
|
||||
</param>
|
||||
<param>
|
||||
<key>affinity</key>
|
||||
<value></value>
|
||||
</param>
|
||||
<param>
|
||||
<key>_enabled</key>
|
||||
<value>True</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>_coordinate</key>
|
||||
<value>(1502, 407)</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>_rotation</key>
|
||||
<value>0</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>id</key>
|
||||
<value>blocks_multiply_xx_0_0</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>type</key>
|
||||
<value>float</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>maxoutbuf</key>
|
||||
<value>0</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>minoutbuf</key>
|
||||
<value>0</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>num_inputs</key>
|
||||
<value>2</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>vlen</key>
|
||||
<value>1</value>
|
||||
</param>
|
||||
</block>
|
||||
<block>
|
||||
<key>blocks_throttle</key>
|
||||
<param>
|
||||
|
@ -713,7 +922,7 @@ of a full period of the CW signal with frequency freq.</value>
|
|||
</param>
|
||||
<param>
|
||||
<key>_coordinate</key>
|
||||
<value>(456, 364)</value>
|
||||
<value>(335, 403)</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>_rotation</key>
|
||||
|
@ -768,7 +977,7 @@ of a full period of the CW signal with frequency freq.</value>
|
|||
</param>
|
||||
<param>
|
||||
<key>file</key>
|
||||
<value>/home/surligas/workspace/gr-satnogs/examples/morse_ref.wav</value>
|
||||
<value>./morse_ref.wav</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>_coordinate</key>
|
||||
|
@ -799,6 +1008,61 @@ of a full period of the CW signal with frequency freq.</value>
|
|||
<value>True</value>
|
||||
</param>
|
||||
</block>
|
||||
<block>
|
||||
<key>fir_filter_xxx</key>
|
||||
<param>
|
||||
<key>alias</key>
|
||||
<value></value>
|
||||
</param>
|
||||
<param>
|
||||
<key>comment</key>
|
||||
<value></value>
|
||||
</param>
|
||||
<param>
|
||||
<key>affinity</key>
|
||||
<value></value>
|
||||
</param>
|
||||
<param>
|
||||
<key>decim</key>
|
||||
<value>1</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>_enabled</key>
|
||||
<value>True</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>_coordinate</key>
|
||||
<value>(1296, 412)</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>_rotation</key>
|
||||
<value>0</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>id</key>
|
||||
<value>fir_filter_xxx_0</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>maxoutbuf</key>
|
||||
<value>0</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>minoutbuf</key>
|
||||
<value>0</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>samp_delay</key>
|
||||
<value>0</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>taps</key>
|
||||
<value>[1.0,]*ndelay</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>type</key>
|
||||
<value>fff</value>
|
||||
</param>
|
||||
</block>
|
||||
<block>
|
||||
<key>import</key>
|
||||
<param>
|
||||
|
@ -836,6 +1100,10 @@ of a full period of the CW signal with frequency freq.</value>
|
|||
<key>autoscale</key>
|
||||
<value>False</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>axislabels</key>
|
||||
<value>True</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>alias</key>
|
||||
<value></value>
|
||||
|
@ -862,7 +1130,7 @@ of a full period of the CW signal with frequency freq.</value>
|
|||
</param>
|
||||
<param>
|
||||
<key>_coordinate</key>
|
||||
<value>(704, 486)</value>
|
||||
<value>(1032, 612)</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>gui_hint</key>
|
||||
|
@ -1134,7 +1402,7 @@ of a full period of the CW signal with frequency freq.</value>
|
|||
</param>
|
||||
<param>
|
||||
<key>size</key>
|
||||
<value>1024</value>
|
||||
<value>samp_rate</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>srate</key>
|
||||
|
@ -1182,7 +1450,7 @@ of a full period of the CW signal with frequency freq.</value>
|
|||
</param>
|
||||
<param>
|
||||
<key>ymax</key>
|
||||
<value>150000</value>
|
||||
<value>1</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>ymin</key>
|
||||
|
@ -1195,6 +1463,10 @@ of a full period of the CW signal with frequency freq.</value>
|
|||
<key>autoscale</key>
|
||||
<value>False</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>axislabels</key>
|
||||
<value>True</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>alias</key>
|
||||
<value></value>
|
||||
|
@ -1221,7 +1493,7 @@ of a full period of the CW signal with frequency freq.</value>
|
|||
</param>
|
||||
<param>
|
||||
<key>_coordinate</key>
|
||||
<value>(512, 222)</value>
|
||||
<value>(936, 216)</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>gui_hint</key>
|
||||
|
@ -1548,70 +1820,15 @@ of a full period of the CW signal with frequency freq.</value>
|
|||
<value>-10</value>
|
||||
</param>
|
||||
</block>
|
||||
<block>
|
||||
<key>satnogs_cw_matched_filter_ff</key>
|
||||
<param>
|
||||
<key>carrier_freq</key>
|
||||
<value>freq</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>alias</key>
|
||||
<value></value>
|
||||
</param>
|
||||
<param>
|
||||
<key>comment</key>
|
||||
<value></value>
|
||||
</param>
|
||||
<param>
|
||||
<key>energy</key>
|
||||
<value>True</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>affinity</key>
|
||||
<value></value>
|
||||
</param>
|
||||
<param>
|
||||
<key>_enabled</key>
|
||||
<value>1</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>_coordinate</key>
|
||||
<value>(808, 351)</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>_rotation</key>
|
||||
<value>0</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>id</key>
|
||||
<value>satnogs_cw_matched_filter_ff_0</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>maxoutbuf</key>
|
||||
<value>0</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>minoutbuf</key>
|
||||
<value>0</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>sampling_rate</key>
|
||||
<value>samp_rate</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>wpm</key>
|
||||
<value>wpm</value>
|
||||
</param>
|
||||
</block>
|
||||
<block>
|
||||
<key>satnogs_cw_to_symbol</key>
|
||||
<param>
|
||||
<key>threshold</key>
|
||||
<value>20e3</value>
|
||||
<value>2.0</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>auto_config</key>
|
||||
<value>True</value>
|
||||
<value>False</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>alias</key>
|
||||
|
@ -1635,11 +1852,11 @@ of a full period of the CW signal with frequency freq.</value>
|
|||
</param>
|
||||
<param>
|
||||
<key>_coordinate</key>
|
||||
<value>(272, 559)</value>
|
||||
<value>(816, 576)</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>_rotation</key>
|
||||
<value>0</value>
|
||||
<value>180</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>id</key>
|
||||
|
@ -1682,11 +1899,11 @@ of a full period of the CW signal with frequency freq.</value>
|
|||
</param>
|
||||
<param>
|
||||
<key>_coordinate</key>
|
||||
<value>(664, 580)</value>
|
||||
<value>(551, 603)</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>_rotation</key>
|
||||
<value>0</value>
|
||||
<value>180</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>id</key>
|
||||
|
@ -1723,18 +1940,30 @@ of a full period of the CW signal with frequency freq.</value>
|
|||
<key>_enabled</key>
|
||||
<value>True</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>filename</key>
|
||||
<value></value>
|
||||
</param>
|
||||
<param>
|
||||
<key>_coordinate</key>
|
||||
<value>(864, 580)</value>
|
||||
<value>(191, 587)</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>_rotation</key>
|
||||
<value>0</value>
|
||||
<value>180</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>id</key>
|
||||
<value>satnogs_multi_format_msg_sink_0</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>outstream</key>
|
||||
<value>True</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>timestamp</key>
|
||||
<value>False</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>format</key>
|
||||
<value>0</value>
|
||||
|
@ -1742,28 +1971,52 @@ of a full period of the CW signal with frequency freq.</value>
|
|||
</block>
|
||||
<connection>
|
||||
<source_block_id>analog_agc2_xx_0_0</source_block_id>
|
||||
<sink_block_id>qtgui_time_sink_x_0_0</sink_block_id>
|
||||
<sink_block_id>blocks_delay_0</sink_block_id>
|
||||
<source_key>0</source_key>
|
||||
<sink_key>2</sink_key>
|
||||
<sink_key>0</sink_key>
|
||||
</connection>
|
||||
<connection>
|
||||
<source_block_id>analog_agc2_xx_0_0</source_block_id>
|
||||
<sink_block_id>satnogs_cw_matched_filter_ff_0</sink_block_id>
|
||||
<sink_block_id>blocks_multiply_xx_0</sink_block_id>
|
||||
<source_key>0</source_key>
|
||||
<sink_key>0</sink_key>
|
||||
</connection>
|
||||
<connection>
|
||||
<source_block_id>analog_agc2_xx_0_0</source_block_id>
|
||||
<sink_block_id>qtgui_time_sink_x_0_0</sink_block_id>
|
||||
<source_key>0</source_key>
|
||||
<sink_key>2</sink_key>
|
||||
</connection>
|
||||
<connection>
|
||||
<source_block_id>analog_fastnoise_source_x_0</source_block_id>
|
||||
<sink_block_id>blocks_add_xx_0</sink_block_id>
|
||||
<source_key>0</source_key>
|
||||
<sink_key>1</sink_key>
|
||||
</connection>
|
||||
<connection>
|
||||
<source_block_id>band_pass_filter_0</source_block_id>
|
||||
<sink_block_id>analog_agc2_xx_0_0</sink_block_id>
|
||||
<source_key>0</source_key>
|
||||
<sink_key>0</sink_key>
|
||||
</connection>
|
||||
<connection>
|
||||
<source_block_id>band_pass_filter_0</source_block_id>
|
||||
<sink_block_id>audio_sink_0</sink_block_id>
|
||||
<source_key>0</source_key>
|
||||
<sink_key>0</sink_key>
|
||||
</connection>
|
||||
<connection>
|
||||
<source_block_id>blocks_add_xx_0</source_block_id>
|
||||
<sink_block_id>blocks_multiply_const_vxx_0</sink_block_id>
|
||||
<source_key>0</source_key>
|
||||
<sink_key>0</sink_key>
|
||||
</connection>
|
||||
<connection>
|
||||
<source_block_id>blocks_delay_0</source_block_id>
|
||||
<sink_block_id>blocks_multiply_xx_0</sink_block_id>
|
||||
<source_key>0</source_key>
|
||||
<sink_key>1</sink_key>
|
||||
</connection>
|
||||
<connection>
|
||||
<source_block_id>blocks_moving_average_xx_0</source_block_id>
|
||||
<sink_block_id>qtgui_time_sink_x_0</sink_block_id>
|
||||
|
@ -1776,12 +2029,6 @@ of a full period of the CW signal with frequency freq.</value>
|
|||
<source_key>0</source_key>
|
||||
<sink_key>0</sink_key>
|
||||
</connection>
|
||||
<connection>
|
||||
<source_block_id>blocks_multiply_const_vxx_0</source_block_id>
|
||||
<sink_block_id>audio_sink_0</sink_block_id>
|
||||
<source_key>0</source_key>
|
||||
<sink_key>0</sink_key>
|
||||
</connection>
|
||||
<connection>
|
||||
<source_block_id>blocks_multiply_const_vxx_0</source_block_id>
|
||||
<sink_block_id>blocks_throttle_0</sink_block_id>
|
||||
|
@ -1800,9 +2047,21 @@ of a full period of the CW signal with frequency freq.</value>
|
|||
<source_key>0</source_key>
|
||||
<sink_key>0</sink_key>
|
||||
</connection>
|
||||
<connection>
|
||||
<source_block_id>blocks_multiply_xx_0</source_block_id>
|
||||
<sink_block_id>fir_filter_xxx_0</sink_block_id>
|
||||
<source_key>0</source_key>
|
||||
<sink_key>0</sink_key>
|
||||
</connection>
|
||||
<connection>
|
||||
<source_block_id>blocks_multiply_xx_0_0</source_block_id>
|
||||
<sink_block_id>blocks_moving_average_xx_0</sink_block_id>
|
||||
<source_key>0</source_key>
|
||||
<sink_key>0</sink_key>
|
||||
</connection>
|
||||
<connection>
|
||||
<source_block_id>blocks_throttle_0</source_block_id>
|
||||
<sink_block_id>analog_agc2_xx_0_0</sink_block_id>
|
||||
<sink_block_id>band_pass_filter_0</sink_block_id>
|
||||
<source_key>0</source_key>
|
||||
<sink_key>0</sink_key>
|
||||
</connection>
|
||||
|
@ -1819,11 +2078,17 @@ of a full period of the CW signal with frequency freq.</value>
|
|||
<sink_key>0</sink_key>
|
||||
</connection>
|
||||
<connection>
|
||||
<source_block_id>satnogs_cw_matched_filter_ff_0</source_block_id>
|
||||
<sink_block_id>blocks_moving_average_xx_0</sink_block_id>
|
||||
<source_block_id>fir_filter_xxx_0</source_block_id>
|
||||
<sink_block_id>blocks_multiply_xx_0_0</sink_block_id>
|
||||
<source_key>0</source_key>
|
||||
<sink_key>0</sink_key>
|
||||
</connection>
|
||||
<connection>
|
||||
<source_block_id>fir_filter_xxx_0</source_block_id>
|
||||
<sink_block_id>blocks_multiply_xx_0_0</sink_block_id>
|
||||
<source_key>0</source_key>
|
||||
<sink_key>1</sink_key>
|
||||
</connection>
|
||||
<connection>
|
||||
<source_block_id>satnogs_cw_to_symbol_0</source_block_id>
|
||||
<sink_block_id>satnogs_morse_decoder_0</sink_block_id>
|
||||
|
|
|
@ -78,65 +78,7 @@
|
|||
</param>
|
||||
<param>
|
||||
<key>title</key>
|
||||
<value></value>
|
||||
</param>
|
||||
</block>
|
||||
<block>
|
||||
<key>variable</key>
|
||||
<param>
|
||||
<key>comment</key>
|
||||
<value></value>
|
||||
</param>
|
||||
<param>
|
||||
<key>_enabled</key>
|
||||
<value>True</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>_coordinate</key>
|
||||
<value>(8, 160)</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>_rotation</key>
|
||||
<value>0</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>id</key>
|
||||
<value>samp_rate</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>value</key>
|
||||
<value>32000</value>
|
||||
</param>
|
||||
</block>
|
||||
<block>
|
||||
<key>satnogs_clear_text_msg_sink</key>
|
||||
<param>
|
||||
<key>alias</key>
|
||||
<value></value>
|
||||
</param>
|
||||
<param>
|
||||
<key>comment</key>
|
||||
<value></value>
|
||||
</param>
|
||||
<param>
|
||||
<key>affinity</key>
|
||||
<value></value>
|
||||
</param>
|
||||
<param>
|
||||
<key>_enabled</key>
|
||||
<value>True</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>_coordinate</key>
|
||||
<value>(960, 168)</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>_rotation</key>
|
||||
<value>0</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>id</key>
|
||||
<value>satnogs_clear_text_msg_sink_0</value>
|
||||
<value>Morse Decoder Simple Example</value>
|
||||
</param>
|
||||
</block>
|
||||
<block>
|
||||
|
@ -187,7 +129,7 @@
|
|||
</param>
|
||||
<param>
|
||||
<key>debug_seq</key>
|
||||
<value>"XPGOLIAT HELLO EARTH WORLD 123456789"</value>
|
||||
<value>"SATNOGS HELLO EARTH WORLD 123456789"</value>
|
||||
</param>
|
||||
</block>
|
||||
<block>
|
||||
|
@ -233,6 +175,53 @@
|
|||
<value>ord('#')</value>
|
||||
</param>
|
||||
</block>
|
||||
<block>
|
||||
<key>satnogs_multi_format_msg_sink</key>
|
||||
<param>
|
||||
<key>alias</key>
|
||||
<value></value>
|
||||
</param>
|
||||
<param>
|
||||
<key>comment</key>
|
||||
<value></value>
|
||||
</param>
|
||||
<param>
|
||||
<key>affinity</key>
|
||||
<value></value>
|
||||
</param>
|
||||
<param>
|
||||
<key>_enabled</key>
|
||||
<value>True</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>filename</key>
|
||||
<value></value>
|
||||
</param>
|
||||
<param>
|
||||
<key>_coordinate</key>
|
||||
<value>(968, 148)</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>_rotation</key>
|
||||
<value>0</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>id</key>
|
||||
<value>satnogs_multi_format_msg_sink_0</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>outstream</key>
|
||||
<value>True</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>timestamp</key>
|
||||
<value>False</value>
|
||||
</param>
|
||||
<param>
|
||||
<key>format</key>
|
||||
<value>0</value>
|
||||
</param>
|
||||
</block>
|
||||
<connection>
|
||||
<source_block_id>satnogs_morse_debug_source_0</source_block_id>
|
||||
<sink_block_id>satnogs_morse_decoder_0</sink_block_id>
|
||||
|
@ -241,7 +230,7 @@
|
|||
</connection>
|
||||
<connection>
|
||||
<source_block_id>satnogs_morse_decoder_0</source_block_id>
|
||||
<sink_block_id>satnogs_clear_text_msg_sink_0</sink_block_id>
|
||||
<sink_block_id>satnogs_multi_format_msg_sink_0</sink_block_id>
|
||||
<source_key>out</source_key>
|
||||
<sink_key>in</sink_key>
|
||||
</connection>
|
||||
|
|
|
@ -24,11 +24,11 @@ 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
|
||||
satnogs_block_tree.xml
|
||||
satnogs_cw_matched_filter_ff.xml
|
||||
satnogs_morse_decoder.xml
|
||||
satnogs_multi_format_msg_sink.xml
|
||||
satnogs_ogg_encoder.xml
|
||||
|
@ -41,16 +41,17 @@ list(APPEND enabled_blocks
|
|||
satnogs_coarse_doppler_correction_cc.xml
|
||||
satnogs_ax25_encoder_mb.xml
|
||||
satnogs_ax25_decoder_bm.xml
|
||||
satnogs_waterfall_sink.xml
|
||||
satnogs_waterfall_sink.xml
|
||||
satnogs_ogg_source.xml
|
||||
satnogs_noaa_apt_sink.xml
|
||||
satnogs_frame_file_sink.xml
|
||||
satnogs_iq_sink.xml
|
||||
)
|
||||
|
||||
if(${INCLUDE_DEBUG_BLOCKS})
|
||||
list(APPEND enabled_blocks ${debug_blocks})
|
||||
endif()
|
||||
install(FILES
|
||||
${enabled_blocks}
|
||||
satnogs_ogg_source.xml
|
||||
satnogs_noaa_apt_sink.xml
|
||||
satnogs_frame_file_sink.xml
|
||||
satnogs_iq_sink.xml DESTINATION share/gnuradio/grc/blocks
|
||||
${enabled_blocks}
|
||||
DESTINATION share/gnuradio/grc/blocks
|
||||
)
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
<?xml version="1.0"?>
|
||||
<block>
|
||||
<name>CW Encoder</name>
|
||||
<key>satnogs_cw_encoder</key>
|
||||
<category>[SatNOGS]/Debug</category>
|
||||
<import>import satnogs</import>
|
||||
<make>satnogs.cw_encoder($samp_rate, $cw_freq, $wpm)</make>
|
||||
|
||||
<param>
|
||||
<name>Sample Rate</name>
|
||||
<key>samp_rate</key>
|
||||
<value>samp_rate</value>
|
||||
<type>real</type>
|
||||
</param>
|
||||
|
||||
<param>
|
||||
<name>CW Frequency</name>
|
||||
<key>cw_freq</key>
|
||||
<value>700</value>
|
||||
<type>real</type>
|
||||
</param>
|
||||
|
||||
<param>
|
||||
<name>Words per minute</name>
|
||||
<key>wpm</key>
|
||||
<value>20</value>
|
||||
<type>int</type>
|
||||
</param>
|
||||
|
||||
<sink>
|
||||
<name>symbol</name>
|
||||
<type>message</type>
|
||||
</sink>
|
||||
|
||||
<source>
|
||||
<name>out</name>
|
||||
<type>complex</type>
|
||||
</source>
|
||||
</block>
|
|
@ -1,57 +0,0 @@
|
|||
<?xml version="1.0"?>
|
||||
<block>
|
||||
<name>CW Matched Filter</name>
|
||||
<key>satnogs_cw_matched_filter_ff</key>
|
||||
<import>import satnogs</import>
|
||||
<make>satnogs.cw_matched_filter_ff($sampling_rate, $carrier_freq, $wpm, $energy)</make>
|
||||
<callback>set_new_freq_locked($carrier_freq)</callback>
|
||||
|
||||
<param>
|
||||
<name>Sampling Rate</name>
|
||||
<key>sampling_rate</key>
|
||||
<type>real</type>
|
||||
</param>
|
||||
|
||||
<param>
|
||||
<name>Audio Frequency (Hz)</name>
|
||||
<key>carrier_freq</key>
|
||||
<type>real</type>
|
||||
</param>
|
||||
|
||||
<param>
|
||||
<name>Words per Minute</name>
|
||||
<key>wpm</key>
|
||||
<value>20</value>
|
||||
<type>int</type>
|
||||
</param>
|
||||
|
||||
<param>
|
||||
<name>Compute Energy</name>
|
||||
<key>energy</key>
|
||||
<type>enum</type>
|
||||
<option>
|
||||
<name>No</name>
|
||||
<key>False</key>
|
||||
</option>
|
||||
<option>
|
||||
<name>Yes</name>
|
||||
<key>True</key>
|
||||
</option>
|
||||
</param>
|
||||
|
||||
<sink>
|
||||
<name>freq</name>
|
||||
<type>message</type>
|
||||
<optional>1</optional>
|
||||
</sink>
|
||||
|
||||
<sink>
|
||||
<name>in</name>
|
||||
<type>float</type>
|
||||
</sink>
|
||||
|
||||
<source>
|
||||
<name>out</name>
|
||||
<type>float</type>
|
||||
</source>
|
||||
</block>
|
|
@ -3,7 +3,7 @@
|
|||
<name>CW to Symbols</name>
|
||||
<key>satnogs_cw_to_symbol</key>
|
||||
<import>import satnogs</import>
|
||||
<make>satnogs.cw_to_symbol($sampling_rate, $threshold, $conf_level, $wpm, $auto_config)</make>
|
||||
<make>satnogs.cw_to_symbol($sampling_rate, $threshold, $conf_level, $wpm)</make>
|
||||
<callback>set_act_threshold($threshold)</callback>
|
||||
|
||||
<param>
|
||||
|
@ -32,20 +32,6 @@
|
|||
<value>20</value>
|
||||
<type>int</type>
|
||||
</param>
|
||||
|
||||
<param>
|
||||
<name>Automatic timing recovery</name>
|
||||
<key>auto_config</key>
|
||||
<type>enum</type>
|
||||
<option>
|
||||
<name>No</name>
|
||||
<key>False</key>
|
||||
</option>
|
||||
<option>
|
||||
<name>Yes</name>
|
||||
<key>True</key>
|
||||
</option>
|
||||
</param>
|
||||
|
||||
<sink>
|
||||
<name>act_threshold</name>
|
||||
|
@ -53,12 +39,6 @@
|
|||
<optional>1</optional>
|
||||
</sink>
|
||||
|
||||
<sink>
|
||||
<name>sync</name>
|
||||
<type>message</type>
|
||||
<optional>1</optional>
|
||||
</sink>
|
||||
|
||||
<sink>
|
||||
<name>in</name>
|
||||
<type>float</type>
|
||||
|
|
|
@ -4,7 +4,14 @@
|
|||
<key>satnogs_morse_debug_source</key>
|
||||
<category>[SatNOGS]/Debug</category>
|
||||
<import>import satnogs</import>
|
||||
<make>satnogs.morse_debug_source($debug_seq, $errors, $p)</make>
|
||||
<make>satnogs.morse_debug_source($wpm, $debug_seq, $errors, $p, $seq_pause_ms)</make>
|
||||
|
||||
<param>
|
||||
<name>WPM</name>
|
||||
<key>wpm</key>
|
||||
<value>20</value>
|
||||
<type>int</type>
|
||||
</param>
|
||||
|
||||
<param>
|
||||
<name>Sentence</name>
|
||||
|
@ -33,6 +40,13 @@
|
|||
<value>0.1</value>
|
||||
<type>real</type>
|
||||
</param>
|
||||
|
||||
<param>
|
||||
<name>Sequence Pause (millis)</name>
|
||||
<key>seq_pause_ms</key>
|
||||
<value>1000</value>
|
||||
<type>int</type>
|
||||
</param>
|
||||
|
||||
<source>
|
||||
<name>out</name>
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
<name>Multi Format Message Sink</name>
|
||||
<key>satnogs_multi_format_msg_sink</key>
|
||||
<import>import satnogs</import>
|
||||
<make>satnogs.multi_format_msg_sink($format)</make>
|
||||
<make>satnogs.multi_format_msg_sink($format, $timestamp, $outstream, $filename)</make>
|
||||
|
||||
<param>
|
||||
<name>Output format</name>
|
||||
|
@ -22,6 +22,41 @@
|
|||
<key>2</key>
|
||||
</option>
|
||||
|
||||
</param>
|
||||
<param>
|
||||
<name>Output Timestamp</name>
|
||||
<key>timestamp</key>
|
||||
<type>enum</type>
|
||||
<option>
|
||||
<name>No</name>
|
||||
<key>False</key>
|
||||
</option>
|
||||
<option>
|
||||
<name>Yes</name>
|
||||
<key>True</key>
|
||||
</option>
|
||||
</param>
|
||||
<param>
|
||||
<name>Output Result</name>
|
||||
<key>outstream</key>
|
||||
<type>enum</type>
|
||||
<option>
|
||||
<name>STDOUT</name>
|
||||
<key>True</key>
|
||||
<opt>t:stdout</opt>
|
||||
</option>
|
||||
<option>
|
||||
<name>File</name>
|
||||
<key>False</key>
|
||||
<opt>t:file</opt>
|
||||
</option>
|
||||
</param>
|
||||
<param>
|
||||
<name>File</name>
|
||||
<key>filename</key>
|
||||
<value></value>
|
||||
<type>file_save</type>
|
||||
<hide>#if $outstream.t == "file" then 'none' else 'all'#</hide>
|
||||
</param>
|
||||
<sink>
|
||||
<name>in</name>
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
<key>satnogs_ogg_source</key>
|
||||
<category>[satnogs]</category>
|
||||
<import>import satnogs</import>
|
||||
<make>satnogs.ogg_source($filename, $channels)</make>
|
||||
<make>satnogs.ogg_source($filename, $channels, $repeat)</make>
|
||||
|
||||
<param>
|
||||
<name>File</name>
|
||||
|
@ -19,6 +19,20 @@
|
|||
<value>1</value>
|
||||
<type>int</type>
|
||||
</param>
|
||||
|
||||
<param>
|
||||
<name>Repeat</name>
|
||||
<key>repeat</key>
|
||||
<type>enum</type>
|
||||
<option>
|
||||
<name>No</name>
|
||||
<key>False</key>
|
||||
</option>
|
||||
<option>
|
||||
<name>Yes</name>
|
||||
<key>True</key>
|
||||
</option>
|
||||
</param>
|
||||
|
||||
<source>
|
||||
<name>out</name>
|
||||
|
|
|
@ -21,17 +21,17 @@
|
|||
# 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
|
||||
api.h
|
||||
ax25.h
|
||||
config.h
|
||||
cw_matched_filter_ff.h
|
||||
log.h
|
||||
morse_tree.h
|
||||
morse.h
|
||||
|
@ -55,16 +55,18 @@ list(APPEND HEADER_FILES
|
|||
ax25_encoder_mb.h
|
||||
ax25_decoder_bm.h
|
||||
qb50_deframer.h
|
||||
waterfall_sink.h
|
||||
waterfall_sink.h
|
||||
ogg_source.h
|
||||
noaa_apt_sink.h
|
||||
frame_file_sink.h
|
||||
iq_sink.h
|
||||
)
|
||||
|
||||
if(${INCLUDE_DEBUG_BLOCKS})
|
||||
list(APPEND HEADER_FILES ${DEBUG_HEADER_FILES})
|
||||
endif()
|
||||
|
||||
install(FILES
|
||||
${HEADER_FILES}
|
||||
ogg_source.h
|
||||
noaa_apt_sink.h
|
||||
frame_file_sink.h
|
||||
iq_sink.h DESTINATION include/satnogs
|
||||
DESTINATION include/satnogs
|
||||
)
|
|
@ -0,0 +1,59 @@
|
|||
/* -*- c++ -*- */
|
||||
/*
|
||||
* gr-satnogs: SatNOGS GNU Radio Out-Of-Tree Module
|
||||
*
|
||||
* Copyright (C) 2017
|
||||
* 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_ENCODER_H
|
||||
#define INCLUDED_SATNOGS_CW_ENCODER_H
|
||||
|
||||
#include <satnogs/api.h>
|
||||
#include <gnuradio/sync_block.h>
|
||||
|
||||
namespace gr
|
||||
{
|
||||
namespace satnogs
|
||||
{
|
||||
|
||||
/*!
|
||||
* \brief CW encoder block, mainly for debugging and testing purposes.
|
||||
* It accepts a CW word via a message source port and transmits the
|
||||
* corresponding CW symbols.
|
||||
* \ingroup satnogs
|
||||
*
|
||||
*/
|
||||
class SATNOGS_API cw_encoder : virtual public gr::sync_block
|
||||
{
|
||||
public:
|
||||
typedef boost::shared_ptr<cw_encoder> sptr;
|
||||
|
||||
/*!
|
||||
* \brief Return a shared_ptr to a new instance of satnogs::cw_encoder.
|
||||
* @param samp_rate the sampling rate
|
||||
* @param cw_freq the CW tone frequency
|
||||
* @param wpm words per minute (WPM)
|
||||
*/
|
||||
static sptr
|
||||
make (double samp_rate, double cw_freq = 700, size_t wpm = 20);
|
||||
};
|
||||
|
||||
} // namespace satnogs
|
||||
} // namespace gr
|
||||
|
||||
#endif /* INCLUDED_SATNOGS_CW_ENCODER_H */
|
||||
|
|
@ -1,65 +0,0 @@
|
|||
/* -*- 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_MATCHED_FILTER_FF_H
|
||||
#define INCLUDED_SATNOGS_CW_MATCHED_FILTER_FF_H
|
||||
|
||||
#include <satnogs/api.h>
|
||||
#include <gnuradio/sync_block.h>
|
||||
|
||||
namespace gr {
|
||||
namespace satnogs {
|
||||
|
||||
/*!
|
||||
* \brief This block implements a matched filter to reduce the noise
|
||||
* level of the received CW signal.
|
||||
*
|
||||
* \ingroup satnogs
|
||||
*
|
||||
*/
|
||||
class SATNOGS_API cw_matched_filter_ff : virtual public gr::sync_block
|
||||
{
|
||||
public:
|
||||
typedef boost::shared_ptr<cw_matched_filter_ff> sptr;
|
||||
|
||||
/*!
|
||||
* \brief Matched filter for CW noise reduction
|
||||
*
|
||||
* @param sampling_rate the sampling rate of the signal
|
||||
* @param carrier_freq the audio frequency of the CW signal
|
||||
* @param wpm Morse code Words per Minute
|
||||
* @param energy_out if true, the filter produces the energy of the
|
||||
* resulting filtered samples, otherwise the raw filter samples are
|
||||
* produced. This is handy, in order to save the flowgraph from
|
||||
* am additional signal energy block.
|
||||
*/
|
||||
static sptr make(double sampling_rate, double carrier_freq = 500,
|
||||
size_t wpm = 20,
|
||||
bool energy_out = false);
|
||||
|
||||
virtual void set_new_freq_locked(double freq) = 0;
|
||||
virtual void set_new_freq(double freq) = 0;
|
||||
};
|
||||
|
||||
} // namespace satnogs
|
||||
} // namespace gr
|
||||
|
||||
#endif /* INCLUDED_SATNOGS_CW_MATCHED_FILTER_FF_H */
|
||||
|
|
@ -24,17 +24,24 @@
|
|||
#include <satnogs/api.h>
|
||||
#include <gnuradio/sync_block.h>
|
||||
|
||||
namespace gr {
|
||||
namespace satnogs {
|
||||
namespace gr
|
||||
{
|
||||
namespace satnogs
|
||||
{
|
||||
|
||||
/*!
|
||||
* \brief The CW to Symbol block tries to translate the received signal
|
||||
* power time-series into Morse symbols.
|
||||
* \brief The CW to Symbol block tries to translate the input signal
|
||||
* into Morse symbols. The input signal should have been already properly
|
||||
* filtered and processed. A possible DSP on the input signal may be the
|
||||
* squared magnitude or the amplitude of the autocorrelation. Proper filtering
|
||||
* that take cares possible spikes may drastically increase the performance
|
||||
* of this block.
|
||||
*
|
||||
* \ingroup satnogs
|
||||
*/
|
||||
class SATNOGS_API cw_to_symbol : virtual public gr::sync_block
|
||||
{
|
||||
public:
|
||||
public:
|
||||
typedef boost::shared_ptr<cw_to_symbol> sptr;
|
||||
|
||||
/*!
|
||||
|
@ -58,18 +65,13 @@ namespace gr {
|
|||
* symbols
|
||||
*
|
||||
* @param wpm Morse code Words per Minute
|
||||
*
|
||||
* @param auto_config if set to true, the block will try first to
|
||||
* automatically adjust the WPM in order to extract the dot and dash
|
||||
* durations. If set to false, the given WPM is used.
|
||||
*/
|
||||
static cw_to_symbol::sptr
|
||||
make (double sampling_rate, float threshold, float conf_level = 0.9,
|
||||
size_t wpm = 20, bool auto_config = false);
|
||||
size_t wpm = 20);
|
||||
|
||||
virtual void set_act_threshold(float thrld) = 0;
|
||||
|
||||
virtual void start_timing_recovery() = 0;
|
||||
virtual void
|
||||
set_act_threshold (float thrld) = 0;
|
||||
};
|
||||
|
||||
} // namespace satnogs
|
||||
|
|
|
@ -2,7 +2,8 @@
|
|||
/*
|
||||
* gr-satnogs: SatNOGS GNU Radio Out-Of-Tree Module
|
||||
*
|
||||
* Copyright (C) 2016, Libre Space Foundation <http://librespacefoundation.org/>
|
||||
* Copyright (C) 2016,2017
|
||||
* 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
|
||||
|
@ -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 //!<Morse long space between words
|
||||
} morse_symbol_t;
|
||||
|
||||
|
||||
|
|
|
@ -2,7 +2,8 @@
|
|||
/*
|
||||
* gr-satnogs: SatNOGS GNU Radio Out-Of-Tree Module
|
||||
*
|
||||
* Copyright (C) 2016, Libre Space Foundation <http://librespacefoundation.org/>
|
||||
* Copyright (C) 2016,2017
|
||||
* 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
|
||||
|
@ -24,8 +25,10 @@
|
|||
#include <satnogs/api.h>
|
||||
#include <gnuradio/block.h>
|
||||
|
||||
namespace gr {
|
||||
namespace satnogs {
|
||||
namespace gr
|
||||
{
|
||||
namespace satnogs
|
||||
{
|
||||
|
||||
/*!
|
||||
* \brief A Morse debug source block that supports injection of random
|
||||
|
@ -36,7 +39,7 @@ namespace gr {
|
|||
*/
|
||||
class SATNOGS_API morse_debug_source : virtual public gr::block
|
||||
{
|
||||
public:
|
||||
public:
|
||||
typedef boost::shared_ptr<morse_debug_source> sptr;
|
||||
|
||||
/*!
|
||||
|
@ -45,13 +48,21 @@ namespace gr {
|
|||
* This block can also inject random errors, based on a Bernoulli
|
||||
* distribution.
|
||||
*
|
||||
* @param wpm words per minute
|
||||
* @param debug_seq A string containing the debug sentence
|
||||
* @param inject_errors if set the debug source block will produce
|
||||
* errors that follow a Bernoulli distribution
|
||||
* @param error_prob the probability p of error for the Bernulli distribution
|
||||
* @param seq_pause_ms pause in milliseconds between concecutive debug
|
||||
* sequences. For simplicity the pause duration will be scaled to multiple
|
||||
* dot durations.
|
||||
*/
|
||||
static sptr make(const std::string& debug_seq, bool inject_errors = false,
|
||||
float error_prob = 0.1);
|
||||
static sptr
|
||||
make (const size_t wpm,
|
||||
const std::string& debug_seq,
|
||||
bool inject_errors = false,
|
||||
float error_prob = 0.1,
|
||||
size_t seq_pause_ms = 1000);
|
||||
};
|
||||
|
||||
} // namespace satnogs
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
/*
|
||||
* gr-satnogs: SatNOGS GNU Radio Out-Of-Tree Module
|
||||
*
|
||||
* Copyright (C) 2016, Libre Space Foundation <http://librespacefoundation.org/>
|
||||
* Copyright (C) 2016,2017, 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
|
||||
|
@ -44,12 +44,24 @@ namespace gr
|
|||
|
||||
/*!
|
||||
* \brief Block accepting clear text messages from various decoders.
|
||||
* Its purpose is to forward these messages at other services, programs,
|
||||
* stdout, etc,
|
||||
* Its purpose is to either print these messages to stdout or save them
|
||||
* in text format in a file.
|
||||
*
|
||||
* Depending on format parameter, the contents of each message are
|
||||
* converted to hexademical, binary or ASCII format.
|
||||
*
|
||||
* @param format the format that will used to display the messages.
|
||||
* 0: Clear Text 1: Hexademical 2: Binary
|
||||
* @param timestamp if set, a ISO 8601 timestamp is inserted in front of
|
||||
* each message
|
||||
* @param out_stdout if set, the messages are displayed in the stdout.
|
||||
* Otherwise messages are saved in a text file
|
||||
* @param filepath specifies the file path of the text file
|
||||
*/
|
||||
static sptr
|
||||
make (size_t format);
|
||||
make (size_t format, bool timestamp = true,
|
||||
bool out_stdout = true,
|
||||
const std::string& filepath = "");
|
||||
};
|
||||
|
||||
} // namespace satnogs
|
||||
|
|
|
@ -47,9 +47,12 @@ namespace gr
|
|||
* @param number of channels of the OGG stream. If the actual OGG stream
|
||||
* contains a different number of channels than specified an exception
|
||||
* is raised
|
||||
* @param repeat if set to true, when EOF is reached the block
|
||||
* will continue to output samples from the beginning of the OGG file.
|
||||
*/
|
||||
static sptr
|
||||
make (const std::string& filename, size_t channels = 1);
|
||||
make (const std::string& filename, size_t channels = 1,
|
||||
bool repeat = false);
|
||||
};
|
||||
|
||||
} // namespace satnogs
|
||||
|
|
|
@ -33,13 +33,13 @@ include_directories(
|
|||
link_directories(${Boost_LIBRARY_DIRS})
|
||||
|
||||
list(APPEND satnogs_debug_sources
|
||||
morse_debug_source_impl.cc
|
||||
debug_msg_source_impl.cc
|
||||
debug_msg_source_raw_impl.cc
|
||||
leo_channel_impl.cc
|
||||
morse_debug_source_impl.cc
|
||||
debug_msg_source_impl.cc
|
||||
debug_msg_source_raw_impl.cc
|
||||
leo_channel_impl.cc
|
||||
cw_encoder_impl.cc
|
||||
)
|
||||
list(APPEND satnogs_sources
|
||||
cw_matched_filter_ff_impl.cc
|
||||
morse_tree.cc
|
||||
morse_decoder_impl.cc
|
||||
multi_format_msg_sink_impl.cc
|
||||
|
|
|
@ -0,0 +1,145 @@
|
|||
/* -*- c++ -*- */
|
||||
/*
|
||||
* gr-satnogs: SatNOGS GNU Radio Out-Of-Tree Module
|
||||
*
|
||||
* Copyright (C) 2017
|
||||
* 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 "cw_encoder_impl.h"
|
||||
|
||||
namespace gr {
|
||||
namespace satnogs {
|
||||
|
||||
cw_encoder::sptr
|
||||
cw_encoder::make(double samp_rate, double cw_freq, size_t wpm)
|
||||
{
|
||||
return gnuradio::get_initial_sptr
|
||||
(new cw_encoder_impl(samp_rate, cw_freq, wpm));
|
||||
}
|
||||
|
||||
/*
|
||||
* The private constructor
|
||||
*/
|
||||
cw_encoder_impl::cw_encoder_impl(double samp_rate, double cw_freq,
|
||||
size_t wpm)
|
||||
: gr::sync_block("cw_encoder",
|
||||
gr::io_signature::make(0, 0, 0),
|
||||
gr::io_signature::make(1, 1, sizeof(gr_complex))),
|
||||
d_samp_rate (samp_rate),
|
||||
d_cw_freq (cw_freq),
|
||||
d_wpm (wpm),
|
||||
d_dot_samples ((1.2 / wpm) / (1.0 / samp_rate)),
|
||||
d_window_size (0),
|
||||
d_windows_remaining (0),
|
||||
d_cw_symbol (MORSE_L_SPACE),
|
||||
d_nco ()
|
||||
{
|
||||
message_port_register_in(pmt::mp("symbol"));
|
||||
|
||||
/*
|
||||
* Try to split the CW pulses in smaller windows for dealing efficiently
|
||||
* with the available buffer size
|
||||
*/
|
||||
size_t i = 10;
|
||||
d_window_size = d_dot_samples / i;
|
||||
while(d_window_size > 200) {
|
||||
i += 10;
|
||||
d_window_size = d_dot_samples / i;
|
||||
}
|
||||
|
||||
/* NOTE: The dot duration should be a perfect multiple of the window */
|
||||
while(d_dot_samples % d_window_size != 0) {
|
||||
d_window_size++;
|
||||
}
|
||||
|
||||
set_output_multiple(d_window_size);
|
||||
d_nco.set_freq ((2 * M_PI * cw_freq) / samp_rate);
|
||||
}
|
||||
|
||||
/*
|
||||
* Our virtual destructor.
|
||||
*/
|
||||
cw_encoder_impl::~cw_encoder_impl()
|
||||
{
|
||||
}
|
||||
|
||||
int
|
||||
cw_encoder_impl::work(int noutput_items,
|
||||
gr_vector_const_void_star &input_items,
|
||||
gr_vector_void_star &output_items)
|
||||
{
|
||||
size_t available;
|
||||
size_t i;
|
||||
gr_complex *out = (gr_complex *) output_items[0];
|
||||
|
||||
if(noutput_items < 0) {
|
||||
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 */
|
||||
} /* namespace gr */
|
||||
|
|
@ -0,0 +1,67 @@
|
|||
/* -*- c++ -*- */
|
||||
/*
|
||||
* gr-satnogs: SatNOGS GNU Radio Out-Of-Tree Module
|
||||
*
|
||||
* Copyright (C) 2017
|
||||
* 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_ENCODER_IMPL_H
|
||||
#define INCLUDED_SATNOGS_CW_ENCODER_IMPL_H
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <satnogs/cw_encoder.h>
|
||||
#include <satnogs/morse.h>
|
||||
#include <gnuradio/fxpt_nco.h>
|
||||
|
||||
namespace gr
|
||||
{
|
||||
namespace satnogs
|
||||
{
|
||||
|
||||
class cw_encoder_impl : public cw_encoder
|
||||
{
|
||||
private:
|
||||
const double d_samp_rate;
|
||||
const double d_cw_freq;
|
||||
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;
|
||||
|
||||
|
||||
|
||||
std::string
|
||||
get_cw_symbol(char c);
|
||||
|
||||
public:
|
||||
cw_encoder_impl (double samp_rate, double cw_freq, size_t wpm);
|
||||
~cw_encoder_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_ENCODER_IMPL_H */
|
||||
|
|
@ -1,131 +0,0 @@
|
|||
/* -*- 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 "cw_matched_filter_ff_impl.h"
|
||||
|
||||
#include <volk/volk.h>
|
||||
#include <gnuradio/fxpt_nco.h>
|
||||
|
||||
namespace gr {
|
||||
namespace satnogs {
|
||||
|
||||
cw_matched_filter_ff::sptr
|
||||
cw_matched_filter_ff::make(double sampling_rate, double carrier_freq,
|
||||
size_t wpm, bool energy_out)
|
||||
{
|
||||
return gnuradio::get_initial_sptr
|
||||
(new cw_matched_filter_ff_impl(sampling_rate, carrier_freq,
|
||||
wpm, energy_out));
|
||||
}
|
||||
|
||||
/*
|
||||
* The private constructor
|
||||
*/
|
||||
cw_matched_filter_ff_impl::cw_matched_filter_ff_impl (double sampling_rate,
|
||||
double carrier_freq,
|
||||
size_t wpm,
|
||||
bool energy_out) :
|
||||
gr::sync_block ("cw_matched_filter_ff",
|
||||
gr::io_signature::make (1, 1, sizeof(float)),
|
||||
gr::io_signature::make (1, 1, sizeof(float))),
|
||||
d_samp_rate(sampling_rate),
|
||||
d_dot_duration(1.2/wpm),
|
||||
d_produce_enrg(energy_out),
|
||||
d_dot_samples(d_dot_duration / (1.0 / sampling_rate))
|
||||
{
|
||||
const int alignment_multiple = volk_get_alignment() / sizeof(float);
|
||||
set_alignment(std::max(1,alignment_multiple));
|
||||
set_history(d_dot_samples);
|
||||
|
||||
d_sin_wave = (float *)volk_malloc(d_dot_samples * sizeof(float), 32);
|
||||
if(!d_sin_wave){
|
||||
throw std::runtime_error("Could not allocate sine wave buffer");
|
||||
}
|
||||
|
||||
/* Register the input port for frequency change messages */
|
||||
message_port_register_in(pmt::mp("freq"));
|
||||
set_msg_handler(pmt::mp("freq"),
|
||||
boost::bind(&cw_matched_filter_ff_impl::new_freq_msg_handler,
|
||||
this, _1));
|
||||
|
||||
/* Now fill the buffer with the appropriate sine wave */
|
||||
gr::fxpt_nco nco;
|
||||
nco.set_freq(2 * M_PI * carrier_freq / sampling_rate);
|
||||
nco.sin(d_sin_wave, d_dot_samples, 1.0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Our virtual destructor.
|
||||
*/
|
||||
cw_matched_filter_ff_impl::~cw_matched_filter_ff_impl()
|
||||
{
|
||||
volk_free(d_sin_wave);
|
||||
}
|
||||
|
||||
void
|
||||
cw_matched_filter_ff_impl::new_freq_msg_handler (pmt::pmt_t msg)
|
||||
{
|
||||
if(pmt::is_pair(msg)){
|
||||
set_new_freq(pmt::to_double(pmt::cdr(msg)));
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
cw_matched_filter_ff_impl::work (int noutput_items,
|
||||
gr_vector_const_void_star &input_items,
|
||||
gr_vector_void_star &output_items)
|
||||
{
|
||||
boost::mutex::scoped_lock lock (d_mutex);
|
||||
const float *in = (const float *) input_items[0];
|
||||
float *out = (float *) output_items[0];
|
||||
|
||||
for (int i = 0; i < noutput_items; i++) {
|
||||
volk_32f_x2_dot_prod_32f (out + i, in + i, d_sin_wave, d_dot_samples);
|
||||
}
|
||||
if (d_produce_enrg) {
|
||||
volk_32f_s32f_power_32f (out, out, 2, noutput_items);
|
||||
}
|
||||
|
||||
return noutput_items;
|
||||
}
|
||||
|
||||
void
|
||||
cw_matched_filter_ff_impl::set_new_freq (double freq)
|
||||
{
|
||||
gr::fxpt_nco nco;
|
||||
nco.set_freq(2 * M_PI * freq / d_samp_rate);
|
||||
nco.sin(d_sin_wave, d_dot_samples, 1.0);
|
||||
}
|
||||
|
||||
void
|
||||
cw_matched_filter_ff_impl::set_new_freq_locked(double freq)
|
||||
{
|
||||
boost::mutex::scoped_lock lock(d_mutex);
|
||||
set_new_freq(freq);
|
||||
}
|
||||
|
||||
} /* namespace satnogs */
|
||||
} /* namespace gr */
|
||||
|
|
@ -1,82 +0,0 @@
|
|||
/* -*- 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_MATCHED_FILTER_FF_IMPL_H
|
||||
#define INCLUDED_SATNOGS_CW_MATCHED_FILTER_FF_IMPL_H
|
||||
|
||||
#include <satnogs/cw_matched_filter_ff.h>
|
||||
#include <boost/thread/mutex.hpp>
|
||||
|
||||
namespace gr
|
||||
{
|
||||
namespace satnogs
|
||||
{
|
||||
|
||||
class cw_matched_filter_ff_impl : public cw_matched_filter_ff
|
||||
{
|
||||
private:
|
||||
/**
|
||||
* The sampling rate of the signal
|
||||
*/
|
||||
const double d_samp_rate;
|
||||
|
||||
/**
|
||||
* The duration of the dot in seconds
|
||||
*/
|
||||
const double d_dot_duration;
|
||||
/**
|
||||
* If set to true, this block produces the energy of the filtered
|
||||
* samples, rather the samples themselves
|
||||
*/
|
||||
const bool d_produce_enrg;
|
||||
/**
|
||||
* The duration of the dot in number of samples
|
||||
*/
|
||||
const size_t d_dot_samples;
|
||||
|
||||
float *d_sin_wave;
|
||||
|
||||
boost::mutex d_mutex;
|
||||
|
||||
void
|
||||
new_freq_msg_handler(pmt::pmt_t msg);
|
||||
|
||||
public:
|
||||
cw_matched_filter_ff_impl (double sampling_rate, double carrier_freq,
|
||||
size_t wpm, bool energy_out);
|
||||
~cw_matched_filter_ff_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);
|
||||
|
||||
void
|
||||
set_new_freq(double freq);
|
||||
|
||||
void
|
||||
set_new_freq_locked(double freq);
|
||||
};
|
||||
|
||||
} // namespace satnogs
|
||||
} // namespace gr
|
||||
|
||||
#endif /* INCLUDED_SATNOGS_CW_MATCHED_FILTER_FF_IMPL_H */
|
||||
|
|
@ -2,7 +2,8 @@
|
|||
/*
|
||||
* gr-satnogs: SatNOGS GNU Radio Out-Of-Tree Module
|
||||
*
|
||||
* Copyright (C) 2016, Libre Space Foundation <http://librespacefoundation.org/>
|
||||
* Copyright (C) 2016,2017
|
||||
* 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
|
||||
|
@ -26,7 +27,9 @@
|
|||
#include <gnuradio/io_signature.h>
|
||||
#include <satnogs/log.h>
|
||||
#include <satnogs/utils.h>
|
||||
#include <boost/math/common_factor.hpp>
|
||||
#include "cw_to_symbol_impl.h"
|
||||
#include <volk/volk.h>
|
||||
|
||||
namespace gr
|
||||
{
|
||||
|
@ -34,62 +37,118 @@ 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)
|
||||
{
|
||||
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));
|
||||
}
|
||||
|
||||
/*
|
||||
* 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) :
|
||||
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_dot_samples ((1.2 / wpm) * sampling_rate),
|
||||
d_window_size(0),
|
||||
d_window_cnt(0),
|
||||
d_dot_windows_num(0),
|
||||
d_dec_state (NO_SYNC),
|
||||
d_prev_space_symbol (true)
|
||||
{
|
||||
message_port_register_in(pmt::mp("act_threshold"));
|
||||
message_port_register_in(pmt::mp("sync"));
|
||||
message_port_register_out(pmt::mp("out"));
|
||||
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 (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_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));
|
||||
|
||||
if( auto_config ){
|
||||
d_dot_samples = (1.2/MIN_WPM) / (1.0 / d_sampling_rate);
|
||||
/*
|
||||
* Try to split the CW pulses in smaller windows for detecting faster
|
||||
* a false alarm. As we use the window size for setting the history
|
||||
* it should have a reasonably size.
|
||||
*/
|
||||
size_t i = 1;
|
||||
d_window_size = d_dot_samples / i;
|
||||
while(d_window_size > 64) {
|
||||
i++;
|
||||
d_window_size = d_dot_samples / i;
|
||||
}
|
||||
|
||||
/* NOTE: The dot duration should be a perfect multiple of the window */
|
||||
while(d_dot_samples % d_window_size != 0) {
|
||||
d_window_size++;
|
||||
}
|
||||
|
||||
LOG_WARN("Dot symbol samples: %lu", d_dot_samples);
|
||||
LOG_WARN("Window size: %lu", d_window_size);
|
||||
|
||||
/* Set the duration of each symbol in multiples of the window size */
|
||||
d_dot_windows_num = d_dot_samples / d_window_size;
|
||||
d_dash_windows_num = 3 * d_dot_windows_num;
|
||||
d_short_pause_windows_num = d_dash_windows_num;
|
||||
d_long_pause_windows_num = 7 * d_dot_windows_num;
|
||||
|
||||
const int alignment_multiple = volk_get_alignment ()
|
||||
/ (d_window_size * sizeof(float));
|
||||
set_alignment (std::max (1, alignment_multiple));
|
||||
|
||||
d_const_val = (float *) volk_malloc(d_window_size * sizeof(float),
|
||||
volk_get_alignment ());
|
||||
d_tmp = (float *) volk_malloc(d_window_size * sizeof(float),
|
||||
volk_get_alignment ());
|
||||
d_out = (int32_t *) volk_malloc (d_window_size * sizeof(int32_t),
|
||||
volk_get_alignment ());
|
||||
|
||||
if(!d_const_val || !d_tmp || !d_out) {
|
||||
throw std::runtime_error("cw_to_symbol: Could not allocate memory");
|
||||
}
|
||||
|
||||
for(i = 0; i < d_window_size; i++) {
|
||||
d_const_val[i] = threshold;
|
||||
}
|
||||
set_history(d_window_size);
|
||||
}
|
||||
|
||||
inline void
|
||||
cw_to_symbol_impl::send_symbol_msg (morse_symbol_t s)
|
||||
{
|
||||
message_port_pub(pmt::mp("out"), pmt::from_long(s));
|
||||
if(s == MORSE_S_SPACE || s == MORSE_L_SPACE) {
|
||||
d_prev_space_symbol = true;
|
||||
}
|
||||
else{
|
||||
d_prev_space_symbol = false;
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -97,322 +156,189 @@ namespace gr
|
|||
*/
|
||||
cw_to_symbol_impl::~cw_to_symbol_impl ()
|
||||
{
|
||||
volk_free (d_const_val);
|
||||
volk_free (d_tmp);
|
||||
volk_free (d_out);
|
||||
}
|
||||
|
||||
inline void
|
||||
cw_to_symbol_impl::set_idle ()
|
||||
{
|
||||
d_state = IDLE;
|
||||
d_state_cnt = 0;
|
||||
d_pause_cnt = 0;
|
||||
d_dec_state = NO_SYNC;
|
||||
d_window_cnt = 0;
|
||||
}
|
||||
|
||||
inline void
|
||||
cw_to_symbol_impl::set_short_on ()
|
||||
{
|
||||
d_state = SHORT_ON_PERIOD;
|
||||
d_state_cnt = 1;
|
||||
d_pause_cnt = 0;
|
||||
d_dec_state = SEARCH_DOT;
|
||||
d_window_cnt = 1;
|
||||
}
|
||||
|
||||
inline void
|
||||
cw_to_symbol_impl::set_long_on ()
|
||||
{
|
||||
d_state = LONG_ON_PERIOD;
|
||||
d_dec_state = SEARCH_DASH;
|
||||
}
|
||||
|
||||
inline void
|
||||
cw_to_symbol_impl::set_short_off ()
|
||||
cw_to_symbol_impl::set_search_space ()
|
||||
{
|
||||
d_state = SHORT_OFF_PERIOD;
|
||||
d_state_cnt = 0;
|
||||
d_pause_cnt = 1;
|
||||
}
|
||||
|
||||
inline void
|
||||
cw_to_symbol_impl::set_long_off ()
|
||||
{
|
||||
d_state = LONG_OFF_PERIOD;
|
||||
d_dec_state = SEARCH_SPACE;
|
||||
d_window_cnt = 1;
|
||||
}
|
||||
|
||||
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)));
|
||||
}
|
||||
}
|
||||
|
||||
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)) {
|
||||
set_act_threshold (pmt::to_double (pmt::cdr (msg)));
|
||||
}
|
||||
}
|
||||
|
||||
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];
|
||||
bool triggered;
|
||||
size_t i;
|
||||
const float *in_old = (const float *) input_items[0];
|
||||
const float *in = in_old + history() - 1;
|
||||
|
||||
/* 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 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;
|
||||
if(noutput_items < 0) {
|
||||
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;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
return noutput_items;
|
||||
}
|
||||
|
||||
void
|
||||
cw_to_symbol_impl::estimate_dot_duration (size_t estimate)
|
||||
{
|
||||
/*
|
||||
* 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;
|
||||
/* During idle state search for a possible trigger */
|
||||
if(d_dec_state == NO_SYNC) {
|
||||
for(i = 0; i < (size_t)noutput_items; i++) {
|
||||
/*
|
||||
* Clamp the input so the window mean is not affected by strong spikes
|
||||
* Good luck understanding this black magic shit!
|
||||
*/
|
||||
triggered = is_triggered(in_old + i, d_window_size);
|
||||
if(triggered) {
|
||||
LOG_DEBUG("Triggered!");
|
||||
set_short_on();
|
||||
return i+1;
|
||||
}
|
||||
}
|
||||
return noutput_items;
|
||||
}
|
||||
|
||||
/*
|
||||
* Keep the minimum dot duration. This is only for the sync process.
|
||||
* 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++;
|
||||
}
|
||||
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++;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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;
|
||||
/* From now one, we handle the input in multiples of a window */
|
||||
for (i = 0; i < (size_t)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();
|
||||
LOG_DEBUG("Going to search for long sequence");
|
||||
}
|
||||
}
|
||||
else {
|
||||
if(check_conf_level(d_window_cnt, d_dot_windows_num)) {
|
||||
LOG_DEBUG("DOT");
|
||||
send_symbol_msg(MORSE_DOT);
|
||||
}
|
||||
LOG_DEBUG("Going to search for space: win cnt %lu", d_window_cnt);
|
||||
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 ();
|
||||
LOG_DEBUG("Going to search for 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();
|
||||
LOG_DEBUG("Going to search for dot");
|
||||
}
|
||||
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();
|
||||
LOG_DEBUG("Going to idle");
|
||||
return (i + 1) * d_window_size;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
LOG_ERROR("Invalid decoder state");
|
||||
}
|
||||
}
|
||||
return i * d_window_size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the dash, short and long pause durations based on the dot estimated
|
||||
* duration.
|
||||
*/
|
||||
void
|
||||
cw_to_symbol_impl::set_symbols_duration ()
|
||||
{
|
||||
d_dash_samples = 3 * d_dot_samples;
|
||||
d_short_pause_samples = d_dash_samples;
|
||||
d_long_pause_samples = 7 * d_dot_samples;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the estimated dot duration. After the call of this method
|
||||
* the caller MUST initiate a timing recovery procedure.
|
||||
*/
|
||||
void
|
||||
cw_to_symbol_impl::reset_sync ()
|
||||
{
|
||||
d_sync_state = SYNC_TRIGGER_OFF;
|
||||
d_est_cnt = 0;
|
||||
set_idle ();
|
||||
d_have_sync = false;
|
||||
d_dot_samples = (1.2 / MIN_WPM) / (1.0 / d_sampling_rate);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a new activation threshold. If auto timing recovery is enabled,
|
||||
* the process of finding automatically the WPM is initiated after the
|
||||
* configuration of the new threshold.
|
||||
* Sets a new activation threshold.
|
||||
* @param thrhld the new threshold.
|
||||
*/
|
||||
void
|
||||
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
|
||||
*/
|
||||
if(d_auto_sync) {
|
||||
reset_sync();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts the timing recovery process fro automatically retrieving the best
|
||||
* WPM estimation.
|
||||
* Clamps the input and performs at the same time binary slicing.
|
||||
* With this way, a decision based on moving average is not affected
|
||||
* by strong peaks.
|
||||
* @param out the output buffer with the binary sliced output
|
||||
* @param in the input signal
|
||||
* @param len number of samples to process
|
||||
*/
|
||||
void
|
||||
cw_to_symbol_impl::start_timing_recovery ()
|
||||
inline void
|
||||
cw_to_symbol_impl::clamp_input (int32_t* out, const float* in, size_t len)
|
||||
{
|
||||
reset_sync();
|
||||
volk_32f_x2_subtract_32f(d_tmp, in, d_const_val, len);
|
||||
volk_32f_binary_slicer_32i(d_out, d_tmp, len);
|
||||
}
|
||||
|
||||
static inline int32_t
|
||||
hadd (const int32_t* in, size_t len)
|
||||
{
|
||||
size_t i;
|
||||
int32_t cnt = 0;
|
||||
for(i = 0; i < len; i++) {
|
||||
cnt += in[i];
|
||||
}
|
||||
return cnt;
|
||||
}
|
||||
|
||||
inline bool
|
||||
cw_to_symbol_impl::is_triggered (const float* in, size_t len)
|
||||
{
|
||||
int32_t cnt;
|
||||
clamp_input(d_out, in, len);
|
||||
cnt = hadd(d_out, len);
|
||||
return (cnt >= (int32_t)(d_window_size * d_confidence_level)) ? true : false;
|
||||
}
|
||||
|
||||
} /* namespace satnogs */
|
||||
|
|
|
@ -2,7 +2,8 @@
|
|||
/*
|
||||
* gr-satnogs: SatNOGS GNU Radio Out-Of-Tree Module
|
||||
*
|
||||
* Copyright (C) 2016, Libre Space Foundation <http://librespacefoundation.org/>
|
||||
* Copyright (C) 2016,2017
|
||||
* 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
|
||||
|
@ -31,40 +32,28 @@ namespace gr
|
|||
|
||||
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;
|
||||
|
||||
/**
|
||||
* 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;
|
||||
typedef enum
|
||||
{
|
||||
NO_SYNC, SEARCH_DOT, SEARCH_DASH, SEARCH_SPACE
|
||||
} cw_dec_state_t;
|
||||
|
||||
private:
|
||||
const double d_sampling_rate;
|
||||
float d_act_thrshld;
|
||||
const float d_confidence_level;
|
||||
const size_t d_sync_limit;
|
||||
const bool d_auto_sync;
|
||||
size_t d_dot_samples;
|
||||
size_t d_dash_samples;
|
||||
size_t d_short_pause_samples;
|
||||
size_t d_long_pause_samples;
|
||||
cw_state_t d_state;
|
||||
size_t d_state_cnt;
|
||||
size_t d_pause_cnt;
|
||||
size_t d_est_cnt;
|
||||
size_t d_mean_cnt;
|
||||
bool d_have_sync;
|
||||
bool d_seq_started;
|
||||
sync_state_t d_sync_state;
|
||||
size_t d_window_size;
|
||||
size_t d_window_cnt;
|
||||
size_t d_dot_windows_num;
|
||||
size_t d_dash_windows_num;
|
||||
size_t d_short_pause_windows_num;
|
||||
size_t d_long_pause_windows_num;
|
||||
cw_dec_state_t d_dec_state;
|
||||
bool d_prev_space_symbol;
|
||||
float *d_const_val;
|
||||
float *d_tmp;
|
||||
int32_t *d_out;
|
||||
|
||||
inline void
|
||||
set_idle ();
|
||||
|
@ -76,37 +65,35 @@ namespace gr
|
|||
set_long_on ();
|
||||
|
||||
inline void
|
||||
set_short_off ();
|
||||
set_search_space ();
|
||||
|
||||
inline void
|
||||
set_long_off ();
|
||||
clamp_input (int32_t *out, const float *in, size_t len);
|
||||
|
||||
inline bool
|
||||
is_triggered (const float *in, size_t len);
|
||||
|
||||
inline void
|
||||
send_symbol_msg (morse_symbol_t s);
|
||||
|
||||
void set_act_threshold_msg_handler(pmt::pmt_t msg);
|
||||
inline bool
|
||||
check_conf_level(size_t cnt, size_t target);
|
||||
|
||||
void sync_msg_handler(pmt::pmt_t msg);
|
||||
|
||||
void estimate_dot_duration(size_t estimate);
|
||||
|
||||
void set_symbols_duration();
|
||||
|
||||
void reset_sync();
|
||||
void
|
||||
set_act_threshold_msg_handler (pmt::pmt_t msg);
|
||||
|
||||
public:
|
||||
cw_to_symbol_impl (double sampling_rate, float threshold,
|
||||
float conf_level, size_t wpm, bool auto_config);
|
||||
float conf_level, 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);
|
||||
gr_vector_void_star &output_items);
|
||||
|
||||
void set_act_threshold(float thrhld);
|
||||
|
||||
void start_timing_recovery();
|
||||
void
|
||||
set_act_threshold (float thrhld);
|
||||
};
|
||||
|
||||
} // namespace satnogs
|
||||
|
|
|
@ -2,7 +2,8 @@
|
|||
/*
|
||||
* gr-satnogs: SatNOGS GNU Radio Out-Of-Tree Module
|
||||
*
|
||||
* Copyright (C) 2016, Libre Space Foundation <http://librespacefoundation.org/>
|
||||
* Copyright (C) 2016, 2017
|
||||
* 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
|
||||
|
@ -27,55 +28,62 @@
|
|||
#include <satnogs/morse.h>
|
||||
#include <random>
|
||||
|
||||
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 size_t wpm,
|
||||
const std::string& debug_seq, bool inject_errors,
|
||||
float error_prob,
|
||||
size_t seq_pause_ms)
|
||||
{
|
||||
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 (wpm, debug_seq, inject_errors,
|
||||
error_prob, seq_pause_ms));
|
||||
}
|
||||
|
||||
/*
|
||||
* 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 (const size_t wpm,
|
||||
std::string debug_seq,
|
||||
bool inject_errors,
|
||||
float error_prob,
|
||||
size_t seq_pause_ms) :
|
||||
gr::block ("morse_debug_source",
|
||||
gr::io_signature::make (0, 0, 0),
|
||||
gr::io_signature::make (0, 0, 0)),
|
||||
d_wpm (wpm),
|
||||
d_inject_errors (inject_errors),
|
||||
d_p (error_prob),
|
||||
d_seq_pause_ms (seq_pause_ms),
|
||||
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 +97,75 @@ 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));
|
||||
|
||||
for(i = 0; i < d_seq_pause_ms / (1200/d_wpm); i++) {
|
||||
message_port_pub (port, pmt::from_long (MORSE_INTRA_SPACE));
|
||||
}
|
||||
|
||||
/* Perform a true sleep, to avoid message overload */
|
||||
std::this_thread::sleep_for (std::chrono::milliseconds (d_seq_pause_ms));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* 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 */
|
||||
|
|
|
@ -2,7 +2,8 @@
|
|||
/*
|
||||
* gr-satnogs: SatNOGS GNU Radio Out-Of-Tree Module
|
||||
*
|
||||
* Copyright (C) 2016, Libre Space Foundation <http://librespacefoundation.org/>
|
||||
* Copyright (C) 2016, 2017
|
||||
* 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
|
||||
|
@ -26,26 +27,31 @@
|
|||
#include <algorithm>
|
||||
#include <vector>
|
||||
|
||||
namespace gr {
|
||||
namespace satnogs {
|
||||
namespace gr
|
||||
{
|
||||
namespace satnogs
|
||||
{
|
||||
|
||||
class morse_debug_source_impl : public morse_debug_source
|
||||
{
|
||||
private:
|
||||
private:
|
||||
const size_t d_wpm;
|
||||
const bool d_inject_errors;
|
||||
const float d_p;
|
||||
const size_t d_seq_pause_ms;
|
||||
bool d_run;
|
||||
const char d_chars[36];
|
||||
const std::vector<std::string> d_symbols;
|
||||
std::thread d_thread;
|
||||
|
||||
void
|
||||
send_debug_msg(std::string sentence);
|
||||
send_debug_msg (std::string sentence);
|
||||
|
||||
public:
|
||||
morse_debug_source_impl(std::string debug_seq, bool inject_errors,
|
||||
float error_prob);
|
||||
~morse_debug_source_impl();
|
||||
public:
|
||||
morse_debug_source_impl (const size_t wpm, std::string debug_seq,
|
||||
bool inject_errors,
|
||||
float error_prob, size_t seq_pause_ms);
|
||||
~morse_debug_source_impl ();
|
||||
};
|
||||
|
||||
} // namespace satnogs
|
||||
|
|
|
@ -2,7 +2,8 @@
|
|||
/*
|
||||
* gr-satnogs: SatNOGS GNU Radio Out-Of-Tree Module
|
||||
*
|
||||
* Copyright (C) 2016, Libre Space Foundation <http://librespacefoundation.org/>
|
||||
* Copyright (C) 2016, 2017
|
||||
* 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
|
||||
|
@ -34,61 +35,63 @@ 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
|
||||
morse_decoder_impl::symbol_msg_handler (pmt::pmt_t msg)
|
||||
{
|
||||
bool res;
|
||||
bool res = false;
|
||||
std::string str;
|
||||
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;
|
||||
}
|
||||
}
|
||||
else{
|
||||
LOG_DEBUG("Something went wrong");
|
||||
if (!res) {
|
||||
if (d_morse_tree.get_max_word_len () == d_morse_tree.get_word_len ()) {
|
||||
str = d_morse_tree.get_word ();
|
||||
d_morse_tree.reset ();
|
||||
message_port_pub (pmt::mp ("out"),
|
||||
pmt::make_blob (str.c_str (), str.length ()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -96,17 +99,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 */
|
||||
|
|
|
@ -2,7 +2,8 @@
|
|||
/*
|
||||
* gr-satnogs: SatNOGS GNU Radio Out-Of-Tree Module
|
||||
*
|
||||
* Copyright (C) 2016, Libre Space Foundation <http://librespacefoundation.org/>
|
||||
* Copyright (C) 2016,2017
|
||||
* 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
|
||||
|
@ -36,12 +37,12 @@ namespace gr
|
|||
* Constructs a Morse code tree for Morse code decoding
|
||||
*/
|
||||
morse_tree::morse_tree () :
|
||||
d_unrecognized_symbol('#'),
|
||||
d_root (new tree_node(0)),
|
||||
d_current (d_root),
|
||||
d_buff_len(4096),
|
||||
d_word_len(0),
|
||||
d_word_buffer(new char[d_buff_len])
|
||||
d_unrecognized_symbol ('#'),
|
||||
d_root (new tree_node (0)),
|
||||
d_current (d_root),
|
||||
d_buff_len (4096),
|
||||
d_word_len (0),
|
||||
d_word_buffer (new char[d_buff_len])
|
||||
{
|
||||
construct_tree ();
|
||||
}
|
||||
|
@ -52,12 +53,12 @@ namespace gr
|
|||
* in the place of unrecognized symbols
|
||||
*/
|
||||
morse_tree::morse_tree (char unrecognized) :
|
||||
d_unrecognized_symbol(unrecognized),
|
||||
d_root (new tree_node(0)),
|
||||
d_current (d_root),
|
||||
d_buff_len(4096),
|
||||
d_word_len(0),
|
||||
d_word_buffer(new char[d_buff_len])
|
||||
d_unrecognized_symbol (unrecognized),
|
||||
d_root (new tree_node (0)),
|
||||
d_current (d_root),
|
||||
d_buff_len (4096),
|
||||
d_word_len (0),
|
||||
d_word_buffer (new char[d_buff_len])
|
||||
{
|
||||
construct_tree ();
|
||||
}
|
||||
|
@ -200,46 +201,46 @@ namespace gr
|
|||
bool ret = false;
|
||||
/* Check for overflow */
|
||||
if (d_word_len == d_buff_len) {
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
switch (s)
|
||||
{
|
||||
case MORSE_DOT:
|
||||
if (d_current->get_left_child ()) {
|
||||
d_current = d_current->get_left_child ();
|
||||
ret = true;
|
||||
}
|
||||
break;
|
||||
case MORSE_DASH:
|
||||
if (d_current->get_right_child ()) {
|
||||
d_current = d_current->get_right_child ();
|
||||
ret = true;
|
||||
}
|
||||
break;
|
||||
case MORSE_S_SPACE:
|
||||
/*
|
||||
* A short space received, but the decoder is still at the root.
|
||||
* This is not in general an error so we return true
|
||||
*/
|
||||
if(d_current == d_root){
|
||||
return true;
|
||||
}
|
||||
c = d_current->get_char ();
|
||||
d_current = d_root;
|
||||
/*
|
||||
* Some nodes are null transitions and do not correspond to
|
||||
* a specific character
|
||||
*/
|
||||
if (c != 0) {
|
||||
d_word_buffer[d_word_len] = c;
|
||||
d_word_len++;
|
||||
ret = true;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
LOG_ERROR("Unsupported Morse symbol");
|
||||
return false;
|
||||
}
|
||||
{
|
||||
case MORSE_DOT:
|
||||
if (d_current->get_left_child ()) {
|
||||
d_current = d_current->get_left_child ();
|
||||
ret = true;
|
||||
}
|
||||
break;
|
||||
case MORSE_DASH:
|
||||
if (d_current->get_right_child ()) {
|
||||
d_current = d_current->get_right_child ();
|
||||
ret = true;
|
||||
}
|
||||
break;
|
||||
case MORSE_S_SPACE:
|
||||
/*
|
||||
* A short space received, but the decoder is still at the root.
|
||||
* This is not in general an error so we return true
|
||||
*/
|
||||
if (d_current == d_root) {
|
||||
return true;
|
||||
}
|
||||
c = d_current->get_char ();
|
||||
d_current = d_root;
|
||||
/*
|
||||
* Some nodes are null transitions and do not correspond to
|
||||
* a specific character
|
||||
*/
|
||||
if (c != 0) {
|
||||
d_word_buffer[d_word_len] = c;
|
||||
d_word_len++;
|
||||
ret = true;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
LOG_ERROR("Unsupported Morse symbol");
|
||||
return false;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -265,7 +266,7 @@ namespace gr
|
|||
morse_tree::delete_tree (tree_node *node)
|
||||
{
|
||||
if (!node) {
|
||||
return;
|
||||
return;
|
||||
}
|
||||
delete_tree (node->get_left_child ());
|
||||
delete_tree (node->get_right_child ());
|
||||
|
@ -273,7 +274,9 @@ namespace gr
|
|||
}
|
||||
|
||||
tree_node::tree_node (char c) :
|
||||
d_char (c), d_left (NULL), d_right (NULL)
|
||||
d_char (c),
|
||||
d_left (NULL),
|
||||
d_right (NULL)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
/*
|
||||
* gr-satnogs: SatNOGS GNU Radio Out-Of-Tree Module
|
||||
*
|
||||
* Copyright (C) 2016, Libre Space Foundation <http://librespacefoundation.org/>
|
||||
* Copyright (C) 2016,2017 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
|
||||
|
@ -24,58 +24,136 @@
|
|||
|
||||
#include <gnuradio/io_signature.h>
|
||||
#include "multi_format_msg_sink_impl.h"
|
||||
#include <ctime>
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
|
||||
namespace gr {
|
||||
namespace satnogs {
|
||||
namespace gr
|
||||
{
|
||||
namespace satnogs
|
||||
{
|
||||
|
||||
multi_format_msg_sink::sptr
|
||||
multi_format_msg_sink::make(size_t format)
|
||||
multi_format_msg_sink::make (size_t format,
|
||||
bool timestamp,
|
||||
bool out_stdout,
|
||||
const std::string& filepath)
|
||||
{
|
||||
return gnuradio::get_initial_sptr
|
||||
(new multi_format_msg_sink_impl(format));
|
||||
return gnuradio::get_initial_sptr (
|
||||
new multi_format_msg_sink_impl (format, timestamp,
|
||||
out_stdout, filepath));
|
||||
}
|
||||
|
||||
void
|
||||
multi_format_msg_sink_impl::msg_handler (pmt::pmt_t msg)
|
||||
multi_format_msg_sink_impl::msg_handler_file (pmt::pmt_t msg)
|
||||
{
|
||||
uint8_t *su;
|
||||
std::string s((const char *)pmt::blob_data(msg), pmt::blob_length(msg));
|
||||
switch(d_format){
|
||||
std::string s ((const char *) pmt::blob_data (msg),
|
||||
pmt::blob_length (msg));
|
||||
|
||||
if(d_timestamp) {
|
||||
std::time_t t = std::time(nullptr);
|
||||
std::tm tm = *std::localtime(&t);
|
||||
d_fos << "[" << std::put_time(&tm, "%F %T %z") << "] ";
|
||||
}
|
||||
|
||||
switch (d_format)
|
||||
{
|
||||
case 0:
|
||||
std::cout << "Received text sequence:" << s << " " << std::endl;
|
||||
d_fos << s << std::endl;
|
||||
break;
|
||||
case 1:
|
||||
su = (uint8_t *)pmt::blob_data(msg);
|
||||
for (size_t i = 0; i < pmt::blob_length (msg); i++) {
|
||||
printf ("0x%02x ", su[i]);
|
||||
}
|
||||
std::cout << std::endl;
|
||||
su = (uint8_t *) pmt::blob_data (msg);
|
||||
for (size_t i = 0; i < pmt::blob_length (msg); i++) {
|
||||
d_fos << std::hex << std::showbase << std::setw (4)
|
||||
<< (uint32_t) su[i] << " ";
|
||||
}
|
||||
d_fos << std::endl;
|
||||
break;
|
||||
case 2:
|
||||
su = (uint8_t *)pmt::blob_data(msg);
|
||||
for (size_t i = 0; i < pmt::blob_length (msg); i++) {
|
||||
std::cout << "0b" << std::bitset<8> (su[i]) << " ";
|
||||
}
|
||||
std::cout << std::endl;
|
||||
su = (uint8_t *) pmt::blob_data (msg);
|
||||
for (size_t i = 0; i < pmt::blob_length (msg); i++) {
|
||||
d_fos << "0b" << std::bitset<8> (su[i]) << " ";
|
||||
}
|
||||
d_fos << std::endl;
|
||||
break;
|
||||
default:
|
||||
printf("Invalid format");
|
||||
throw std::invalid_argument("Invalid format");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
multi_format_msg_sink_impl::msg_handler_stdout (pmt::pmt_t msg)
|
||||
{
|
||||
uint8_t *su;
|
||||
std::string s ((const char *) pmt::blob_data (msg),
|
||||
pmt::blob_length (msg));
|
||||
|
||||
if(d_timestamp) {
|
||||
std::time_t t = std::time(nullptr);
|
||||
std::tm tm = *std::localtime(&t);
|
||||
std::cout << "[" << std::put_time(&tm, "%F %T %z") << "] ";
|
||||
}
|
||||
|
||||
switch (d_format)
|
||||
{
|
||||
case 0:
|
||||
std::cout << s << std::endl;
|
||||
break;
|
||||
case 1:
|
||||
su = (uint8_t *) pmt::blob_data (msg);
|
||||
for (size_t i = 0; i < pmt::blob_length (msg); i++) {
|
||||
std::cout << std::hex << std::showbase << std::setw (4)
|
||||
<< (uint32_t) su[i] << " ";
|
||||
}
|
||||
std::cout << std::endl;
|
||||
break;
|
||||
case 2:
|
||||
su = (uint8_t *) pmt::blob_data (msg);
|
||||
for (size_t i = 0; i < pmt::blob_length (msg); i++) {
|
||||
std::cout << "0b" << std::bitset<8> (su[i]) << " ";
|
||||
}
|
||||
std::cout << std::endl;
|
||||
break;
|
||||
default:
|
||||
throw std::invalid_argument("Invalid format");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* The private constructor
|
||||
*/
|
||||
multi_format_msg_sink_impl::multi_format_msg_sink_impl(size_t format)
|
||||
: gr::block("multi_format_msg_sink",
|
||||
gr::io_signature::make(0, 0, 0),
|
||||
gr::io_signature::make(0, 0, 0)),
|
||||
d_format(format)
|
||||
multi_format_msg_sink_impl::multi_format_msg_sink_impl (
|
||||
size_t format, bool timestamp, bool out_stdout,
|
||||
const std::string& filepath) :
|
||||
gr::block ("multi_format_msg_sink",
|
||||
gr::io_signature::make (0, 0, 0),
|
||||
gr::io_signature::make (0, 0, 0)),
|
||||
d_format (format),
|
||||
d_timestamp (timestamp),
|
||||
d_stdout (out_stdout)
|
||||
{
|
||||
message_port_register_in(pmt::mp("in"));
|
||||
set_msg_handler (
|
||||
pmt::mp ("in"),
|
||||
boost::bind (&multi_format_msg_sink_impl::msg_handler, this, _1));
|
||||
message_port_register_in (pmt::mp ("in"));
|
||||
if(out_stdout) {
|
||||
set_msg_handler (
|
||||
pmt::mp ("in"),
|
||||
boost::bind (&multi_format_msg_sink_impl::msg_handler_stdout,
|
||||
this, _1));
|
||||
}
|
||||
else{
|
||||
d_fos.open(filepath);
|
||||
set_msg_handler (
|
||||
pmt::mp ("in"),
|
||||
boost::bind (&multi_format_msg_sink_impl::msg_handler_file,
|
||||
this, _1));
|
||||
}
|
||||
}
|
||||
|
||||
multi_format_msg_sink_impl::~multi_format_msg_sink_impl ()
|
||||
{
|
||||
if(!d_stdout) {
|
||||
d_fos.close();
|
||||
}
|
||||
}
|
||||
|
||||
} /* namespace satnogs */
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
/*
|
||||
* gr-satnogs: SatNOGS GNU Radio Out-Of-Tree Module
|
||||
*
|
||||
* Copyright (C) 2016, Libre Space Foundation <http://librespacefoundation.org/>
|
||||
* Copyright (C) 2016,2017, 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
|
||||
|
@ -22,6 +22,7 @@
|
|||
#define INCLUDED_SATNOGS_MULTI_FORMAT_MSG_SINK_IMPL_H
|
||||
|
||||
#include <satnogs/multi_format_msg_sink.h>
|
||||
#include <fstream>
|
||||
|
||||
namespace gr
|
||||
{
|
||||
|
@ -32,12 +33,20 @@ namespace gr
|
|||
{
|
||||
private:
|
||||
void
|
||||
msg_handler(pmt::pmt_t msg);
|
||||
msg_handler_stdout (pmt::pmt_t msg);
|
||||
void
|
||||
msg_handler_file (pmt::pmt_t msg);
|
||||
|
||||
size_t d_format;
|
||||
const size_t d_format;
|
||||
const bool d_timestamp;
|
||||
const bool d_stdout;
|
||||
std::ofstream d_fos;
|
||||
|
||||
public:
|
||||
multi_format_msg_sink_impl (size_t format);
|
||||
multi_format_msg_sink_impl (size_t format, bool timestamp,
|
||||
bool out_stdout, const std::string& filepath);
|
||||
|
||||
~multi_format_msg_sink_impl ();
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include <vorbis/vorbisfile.h>
|
||||
#include <volk/volk.h>
|
||||
|
||||
#include <satnogs/log.h>
|
||||
#include "ogg_source_impl.h"
|
||||
|
||||
#define PCM_BUF_SIZE 4096
|
||||
|
@ -35,21 +36,22 @@ namespace gr {
|
|||
namespace satnogs {
|
||||
|
||||
ogg_source::sptr
|
||||
ogg_source::make(const std::string& filename, size_t channels)
|
||||
ogg_source::make (const std::string& filename, size_t channels, bool repeat)
|
||||
{
|
||||
return gnuradio::get_initial_sptr
|
||||
(new ogg_source_impl(filename, channels));
|
||||
return gnuradio::get_initial_sptr (
|
||||
new ogg_source_impl (filename, channels, repeat));
|
||||
}
|
||||
|
||||
/*
|
||||
* The private constructor
|
||||
*/
|
||||
ogg_source_impl::ogg_source_impl (const std::string& filename,
|
||||
size_t channels) :
|
||||
size_t channels, bool repeat) :
|
||||
gr::sync_block (
|
||||
"ogg_source", gr::io_signature::make (0, 0, 0),
|
||||
gr::io_signature::make (channels, channels, sizeof(float))),
|
||||
d_channels (channels)
|
||||
d_channels (channels),
|
||||
d_repeat (repeat)
|
||||
{
|
||||
if (channels < 1) {
|
||||
throw std::invalid_argument ("At least one output channels should"
|
||||
|
@ -60,8 +62,8 @@ namespace gr {
|
|||
throw std::invalid_argument ("Invalid .ogg file");
|
||||
}
|
||||
|
||||
vorbis_info *vi = ov_info(&d_ogvorb_f,-1);
|
||||
if(vi->channels != (int) channels) {
|
||||
vorbis_info *vi = ov_info (&d_ogvorb_f, -1);
|
||||
if (vi->channels != (int) channels) {
|
||||
throw std::invalid_argument (
|
||||
std::string ("Channels number specified (")
|
||||
+ std::to_string (channels)
|
||||
|
@ -69,14 +71,17 @@ namespace gr {
|
|||
"the ogg stream (" + std::to_string (vi->channels) + ")");
|
||||
}
|
||||
|
||||
const int alignment_multiple = volk_get_alignment() / sizeof(float);
|
||||
set_alignment(std::max(1,alignment_multiple));
|
||||
set_max_noutput_items(PCM_BUF_SIZE);
|
||||
const int alignment_multiple = volk_get_alignment () / sizeof(float);
|
||||
set_alignment (std::max (1, alignment_multiple));
|
||||
set_max_noutput_items (PCM_BUF_SIZE);
|
||||
|
||||
d_in_buffer = (int16_t *)volk_malloc(PCM_BUF_SIZE * sizeof(int16_t),
|
||||
volk_get_alignment());
|
||||
d_out_buffer = (float *)volk_malloc(PCM_BUF_SIZE * sizeof(float),
|
||||
volk_get_alignment());
|
||||
d_in_buffer = (int16_t *) volk_malloc (PCM_BUF_SIZE * sizeof(int16_t),
|
||||
volk_get_alignment ());
|
||||
d_out_buffer = (float *) volk_malloc (PCM_BUF_SIZE * sizeof(float),
|
||||
volk_get_alignment ());
|
||||
if(!d_in_buffer || !d_out_buffer) {
|
||||
throw std::runtime_error("Could not allocate memory");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -103,6 +108,17 @@ namespace gr {
|
|||
available * sizeof(int16_t),
|
||||
0, sizeof(int16_t), 1, §ion);
|
||||
if(ret < sizeof(int16_t)) {
|
||||
/*
|
||||
* If return value is EOF and the repeat mode is set seek back to the
|
||||
* start of the ogg stream
|
||||
*/
|
||||
if(ret == 0 && d_repeat) {
|
||||
if(ov_seekable(&d_ogvorb_f)){
|
||||
ov_time_seek(&d_ogvorb_f, 0);
|
||||
return 0;
|
||||
}
|
||||
LOG_WARN("File is not seakable.");
|
||||
}
|
||||
return WORK_DONE;
|
||||
}
|
||||
|
||||
|
|
|
@ -33,14 +33,16 @@ namespace gr
|
|||
class ogg_source_impl : public ogg_source
|
||||
{
|
||||
private:
|
||||
const size_t d_channels;
|
||||
OggVorbis_File d_ogvorb_f;
|
||||
const size_t d_channels;
|
||||
const bool d_repeat;
|
||||
OggVorbis_File d_ogvorb_f;
|
||||
|
||||
int16_t *d_in_buffer;
|
||||
float *d_out_buffer;
|
||||
int16_t *d_in_buffer;
|
||||
float *d_out_buffer;
|
||||
|
||||
public:
|
||||
ogg_source_impl (const std::string& filename, size_t channels);
|
||||
ogg_source_impl (const std::string& filename, size_t channels,
|
||||
bool repeat);
|
||||
~ogg_source_impl ();
|
||||
|
||||
// Where all the action really happens
|
||||
|
|
|
@ -9,7 +9,6 @@
|
|||
%include "satnogs_swig_doc.i"
|
||||
|
||||
%{
|
||||
#include "satnogs/cw_matched_filter_ff.h"
|
||||
#include "satnogs/morse_tree.h"
|
||||
#include "satnogs/morse_decoder.h"
|
||||
#include "satnogs/morse_debug_source.h"
|
||||
|
@ -36,12 +35,10 @@
|
|||
#include "satnogs/noaa_apt_sink.h"
|
||||
#include "satnogs/frame_file_sink.h"
|
||||
#include "satnogs/iq_sink.h"
|
||||
#include "satnogs/cw_encoder.h"
|
||||
%}
|
||||
|
||||
|
||||
%include "satnogs/cw_matched_filter_ff.h"
|
||||
GR_SWIG_BLOCK_MAGIC2(satnogs, cw_matched_filter_ff);
|
||||
|
||||
%include "satnogs/morse_tree.h"
|
||||
|
||||
%include "satnogs/morse_decoder.h"
|
||||
|
@ -112,3 +109,5 @@ GR_SWIG_BLOCK_MAGIC2(satnogs, noaa_apt_sink);
|
|||
GR_SWIG_BLOCK_MAGIC2(satnogs, frame_file_sink);
|
||||
%include "satnogs/iq_sink.h"
|
||||
GR_SWIG_BLOCK_MAGIC2(satnogs, iq_sink);
|
||||
%include "satnogs/cw_encoder.h"
|
||||
GR_SWIG_BLOCK_MAGIC2(satnogs, cw_encoder);
|
||||
|
|
Loading…
Reference in New Issue