1# 2# Copyright 2005,2012 Free Software Foundation, Inc. 3# 4# This file is part of GNU Radio 5# 6# GNU Radio is free software; you can redistribute it and/or modify 7# it under the terms of the GNU General Public License as published by 8# the Free Software Foundation; either version 3, or (at your option) 9# any later version. 10# 11# GNU Radio is distributed in the hope that it will be useful, 12# but WITHOUT ANY WARRANTY; without even the implied warranty of 13# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14# GNU General Public License for more details. 15# 16# You should have received a copy of the GNU General Public License 17# along with GNU Radio; see the file COPYING. If not, write to 18# the Free Software Foundation, Inc., 51 Franklin Street, 19# Boston, MA 02110-1301, USA. 20# 21 22from __future__ import print_function 23from __future__ import absolute_import 24from __future__ import division 25from __future__ import unicode_literals 26 27import math 28 29from gnuradio import gr, filter 30from .fm_emph import fm_preemph 31 32from . import analog_swig as analog 33 34 35class nbfm_tx(gr.hier_block2): 36 """ 37 Narrow Band FM Transmitter. 38 39 Takes a single float input stream of audio samples in the range [-1,+1] 40 and produces a single FM modulated complex baseband output. 41 42 Args: 43 audio_rate: sample rate of audio stream, >= 16k (integer) 44 quad_rate: sample rate of output stream (integer) 45 tau: preemphasis time constant (default 75e-6) (float) 46 max_dev: maximum deviation in Hz (default 5e3) (float) 47 fh: high frequency at which to flatten preemphasis; < 0 means default of 0.925*quad_rate/2.0 (float) 48 49 quad_rate must be an integer multiple of audio_rate. 50 """ 51 def __init__(self, audio_rate, quad_rate, tau=75e-6, max_dev=5e3, fh=-1.0): 52 gr.hier_block2.__init__(self, "nbfm_tx", 53 gr.io_signature(1, 1, gr.sizeof_float), # Input signature 54 gr.io_signature(1, 1, gr.sizeof_gr_complex)) # Output signature 55 56 # FIXME audio_rate and quad_rate ought to be exact rationals 57 self._audio_rate = audio_rate = int(audio_rate) 58 self._quad_rate = quad_rate = int(quad_rate) 59 60 if quad_rate % audio_rate != 0: 61 raise ValueError("quad_rate is not an integer multiple of audio_rate") 62 63 64 do_interp = audio_rate != quad_rate 65 66 if do_interp: 67 interp_factor = quad_rate / audio_rate 68 interp_taps = filter.optfir.low_pass(interp_factor, # gain 69 quad_rate, # Fs 70 4500, # passband cutoff 71 7000, # stopband cutoff 72 0.1, # passband ripple dB 73 40) # stopband atten dB 74 75 #print("len(interp_taps) =", len(interp_taps)) 76 self.interpolator = filter.interp_fir_filter_fff (interp_factor, interp_taps) 77 78 self.preemph = fm_preemph(quad_rate, tau=tau, fh=fh) 79 80 k = 2 * math.pi * max_dev / quad_rate 81 self.modulator = analog.frequency_modulator_fc(k) 82 83 if do_interp: 84 self.connect(self, self.interpolator, self.preemph, self.modulator, self) 85 else: 86 self.connect(self, self.preemph, self.modulator, self) 87 88 def set_max_deviation(self, max_dev): 89 k = 2 * math.pi * max_dev / self._quad_rate 90 self.modulator.set_sensitivity(k) 91 92 93 94class ctcss_gen_f(gr.hier_block2): 95 def __init__(self, sample_rate, tone_freq): 96 gr.hier_block2.__init__(self, "ctcss_gen_f", 97 gr.io_signature(0, 0, 0), # Input signature 98 gr.io_signature(1, 1, gr.sizeof_float)) # Output signature 99 100 self.plgen = analog.sig_source_f(sample_rate, analog.GR_SIN_WAVE, 101 tone_freq, 0.1, 0.0) 102 self.connect(self.plgen, self) 103