SSB_HighSpeed_Modem/modem/rx_8psk.py

211 lines
9.1 KiB
Python
Executable File

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#
# SPDX-License-Identifier: GPL-3.0
#
# GNU Radio Python Flow Graph
# Title: 8PSK Modem DJ0ABR
# Author: kurt
# Description: requires GNU Radio 3.8xxx
# GNU Radio version: 3.8.2.0
from gnuradio import analog
from gnuradio import audio
from gnuradio import blocks
from gnuradio import digital
from gnuradio import filter
from gnuradio.filter import firdes
from gnuradio import gr
import sys
import signal
from argparse import ArgumentParser
from gnuradio.eng_arg import eng_float, intx
from gnuradio import eng_notation
class rx_8psk(gr.top_block):
def __init__(self, resamp=6, samp_rate=48000):
gr.top_block.__init__(self, "8PSK Modem DJ0ABR")
##################################################
# Parameters
##################################################
self.resamp = resamp
self.samp_rate = samp_rate
##################################################
# Variables
##################################################
self.sps = sps = 4
self.nfilts = nfilts = 32
self.rrc_taps = rrc_taps = firdes.root_raised_cosine(nfilts, nfilts, 1.1/float(sps), 0.2, 11*sps*nfilts)
self.outputsps = outputsps = 7
self.mixf = mixf = 1500
##################################################
# Blocks
##################################################
self.mmse_resampler_xx_0_0 = filter.mmse_resampler_ff(0, samp_rate / 8000)
self.mmse_resampler_xx_0 = filter.mmse_resampler_cc(0, resamp)
self.low_pass_filter_0 = filter.fir_filter_fff(
1,
firdes.low_pass(
12,
samp_rate,
3900,
3300,
firdes.WIN_HAMMING,
6.76))
self.digital_pfb_clock_sync_xxx_0 = digital.pfb_clock_sync_ccf(sps, 0.06, rrc_taps, nfilts, nfilts/16, 2, outputsps)
self.digital_lms_dd_equalizer_cc_0 = digital.lms_dd_equalizer_cc(15, 0.01, outputsps, digital.constellation_8psk_natural().base())
self.digital_diff_decoder_bb_0 = digital.diff_decoder_bb(8)
self.digital_costas_loop_cc_0 = digital.costas_loop_cc(0.15, 8, False)
self.digital_constellation_decoder_cb_0 = digital.constellation_decoder_cb(digital.constellation_8psk_natural().base())
self.blocks_udp_sink_0_0_0 = blocks.udp_sink(gr.sizeof_int*1, '127.0.0.1', 40137, 120, False)
self.blocks_udp_sink_0_0 = blocks.udp_sink(gr.sizeof_int*1, '127.0.0.1', 40136, 120, False)
self.blocks_udp_sink_0 = blocks.udp_sink(gr.sizeof_char*1, '127.0.0.1', 40135, 344, False)
self.blocks_multiply_xx_0_1_0 = blocks.multiply_vff(1)
self.blocks_multiply_xx_0_1 = blocks.multiply_vff(1)
self.blocks_multiply_xx_0_0_0 = blocks.multiply_vff(1)
self.blocks_interleave_0_0 = blocks.interleave(gr.sizeof_int*1, 1)
self.blocks_interleave_0 = blocks.interleave(gr.sizeof_int*1, 1)
self.blocks_float_to_int_0_1 = blocks.float_to_int(1, 1)
self.blocks_float_to_int_0_0 = blocks.float_to_int(1, 16777216)
self.blocks_float_to_int_0 = blocks.float_to_int(1, 16777216)
self.blocks_float_to_complex_0 = blocks.float_to_complex(1)
self.blocks_complex_to_float_1 = blocks.complex_to_float(1)
self.blocks_complex_to_float_0 = blocks.complex_to_float(1)
self.audio_source_0 = audio.source(samp_rate, '', True)
self.analog_sig_source_x_0_0_0 = analog.sig_source_c(samp_rate, analog.GR_COS_WAVE, mixf, 1, 0, 0)
self.analog_const_source_x_0_1 = analog.sig_source_f(0, analog.GR_CONST_WAVE, 0, 0, 16777216)
self.analog_const_source_x_0_0 = analog.sig_source_i(0, analog.GR_CONST_WAVE, 0, 0, 1000)
self.analog_const_source_x_0 = analog.sig_source_i(0, analog.GR_CONST_WAVE, 0, 0, 1000)
self.analog_agc2_xx_0_0 = analog.agc2_cc(1e-2, 0.2, 1, 2)
self.analog_agc2_xx_0_0.set_max_gain(3)
##################################################
# Connections
##################################################
self.connect((self.analog_agc2_xx_0_0, 0), (self.digital_costas_loop_cc_0, 0))
self.connect((self.analog_const_source_x_0, 0), (self.blocks_interleave_0, 0))
self.connect((self.analog_const_source_x_0_0, 0), (self.blocks_interleave_0_0, 0))
self.connect((self.analog_const_source_x_0_1, 0), (self.blocks_multiply_xx_0_1_0, 1))
self.connect((self.analog_sig_source_x_0_0_0, 0), (self.blocks_complex_to_float_1, 0))
self.connect((self.audio_source_0, 0), (self.low_pass_filter_0, 0))
self.connect((self.audio_source_0, 0), (self.mmse_resampler_xx_0_0, 0))
self.connect((self.blocks_complex_to_float_0, 0), (self.blocks_float_to_int_0, 0))
self.connect((self.blocks_complex_to_float_0, 1), (self.blocks_float_to_int_0_0, 0))
self.connect((self.blocks_complex_to_float_1, 1), (self.blocks_multiply_xx_0_0_0, 1))
self.connect((self.blocks_complex_to_float_1, 0), (self.blocks_multiply_xx_0_1, 1))
self.connect((self.blocks_float_to_complex_0, 0), (self.mmse_resampler_xx_0, 0))
self.connect((self.blocks_float_to_int_0, 0), (self.blocks_interleave_0_0, 1))
self.connect((self.blocks_float_to_int_0_0, 0), (self.blocks_interleave_0_0, 2))
self.connect((self.blocks_float_to_int_0_1, 0), (self.blocks_interleave_0, 1))
self.connect((self.blocks_interleave_0, 0), (self.blocks_udp_sink_0_0, 0))
self.connect((self.blocks_interleave_0_0, 0), (self.blocks_udp_sink_0_0_0, 0))
self.connect((self.blocks_multiply_xx_0_0_0, 0), (self.blocks_float_to_complex_0, 0))
self.connect((self.blocks_multiply_xx_0_1, 0), (self.blocks_float_to_complex_0, 1))
self.connect((self.blocks_multiply_xx_0_1_0, 0), (self.blocks_float_to_int_0_1, 0))
self.connect((self.digital_constellation_decoder_cb_0, 0), (self.digital_diff_decoder_bb_0, 0))
self.connect((self.digital_costas_loop_cc_0, 0), (self.blocks_complex_to_float_0, 0))
self.connect((self.digital_costas_loop_cc_0, 0), (self.digital_constellation_decoder_cb_0, 0))
self.connect((self.digital_diff_decoder_bb_0, 0), (self.blocks_udp_sink_0, 0))
self.connect((self.digital_lms_dd_equalizer_cc_0, 0), (self.analog_agc2_xx_0_0, 0))
self.connect((self.digital_pfb_clock_sync_xxx_0, 0), (self.digital_lms_dd_equalizer_cc_0, 0))
self.connect((self.low_pass_filter_0, 0), (self.blocks_multiply_xx_0_0_0, 0))
self.connect((self.low_pass_filter_0, 0), (self.blocks_multiply_xx_0_1, 0))
self.connect((self.mmse_resampler_xx_0, 0), (self.digital_pfb_clock_sync_xxx_0, 0))
self.connect((self.mmse_resampler_xx_0_0, 0), (self.blocks_multiply_xx_0_1_0, 0))
def get_resamp(self):
return self.resamp
def set_resamp(self, resamp):
self.resamp = resamp
self.mmse_resampler_xx_0.set_resamp_ratio(self.resamp)
def get_samp_rate(self):
return self.samp_rate
def set_samp_rate(self, samp_rate):
self.samp_rate = samp_rate
self.analog_sig_source_x_0_0_0.set_sampling_freq(self.samp_rate)
self.low_pass_filter_0.set_taps(firdes.low_pass(12, self.samp_rate, 3900, 3300, firdes.WIN_HAMMING, 6.76))
self.mmse_resampler_xx_0_0.set_resamp_ratio(self.samp_rate / 8000)
def get_sps(self):
return self.sps
def set_sps(self, sps):
self.sps = sps
self.set_rrc_taps(firdes.root_raised_cosine(self.nfilts, self.nfilts, 1.1/float(self.sps), 0.2, 11*self.sps*self.nfilts))
def get_nfilts(self):
return self.nfilts
def set_nfilts(self, nfilts):
self.nfilts = nfilts
self.set_rrc_taps(firdes.root_raised_cosine(self.nfilts, self.nfilts, 1.1/float(self.sps), 0.2, 11*self.sps*self.nfilts))
def get_rrc_taps(self):
return self.rrc_taps
def set_rrc_taps(self, rrc_taps):
self.rrc_taps = rrc_taps
self.digital_pfb_clock_sync_xxx_0.update_taps(self.rrc_taps)
def get_outputsps(self):
return self.outputsps
def set_outputsps(self, outputsps):
self.outputsps = outputsps
def get_mixf(self):
return self.mixf
def set_mixf(self, mixf):
self.mixf = mixf
self.analog_sig_source_x_0_0_0.set_frequency(self.mixf)
def argument_parser():
description = 'requires GNU Radio 3.8xxx'
parser = ArgumentParser(description=description)
parser.add_argument(
"-r", "--resamp", dest="resamp", type=intx, default=6,
help="Set resamp [default=%(default)r]")
parser.add_argument(
"-s", "--samp-rate", dest="samp_rate", type=intx, default=48000,
help="Set samp_rate [default=%(default)r]")
return parser
def main(top_block_cls=rx_8psk, options=None):
if options is None:
options = argument_parser().parse_args()
tb = top_block_cls(resamp=options.resamp, samp_rate=options.samp_rate)
def sig_handler(sig=None, frame=None):
tb.stop()
tb.wait()
sys.exit(0)
signal.signal(signal.SIGINT, sig_handler)
signal.signal(signal.SIGTERM, sig_handler)
tb.start()
tb.wait()
if __name__ == '__main__':
main()