1# 2# Copyright 2005,2007,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 30from gnuradio import filter 31 32from . import analog_swig as analog 33from .fm_emph import fm_preemph 34 35 36class wfm_tx(gr.hier_block2): 37 def __init__(self, audio_rate, quad_rate, tau=75e-6, max_dev=75e3, fh=-1.0): 38 """ 39 Wide Band FM Transmitter. 40 41 Takes a single float input stream of audio samples in the range [-1,+1] 42 and produces a single FM modulated complex baseband output. 43 44 Args: 45 audio_rate: sample rate of audio stream, >= 16k (integer) 46 quad_rate: sample rate of output stream (integer) 47 tau: preemphasis time constant (default 75e-6) (float) 48 max_dev: maximum deviation in Hz (default 75e3) (float) 49 fh: high frequency at which to flatten preemphasis; < 0 means default of 0.925*quad_rate/2.0 (float) 50 51 quad_rate must be an integer multiple of audio_rate. 52 """ 53 gr.hier_block2.__init__(self, "wfm_tx", 54 gr.io_signature(1, 1, gr.sizeof_float), # Input signature 55 gr.io_signature(1, 1, gr.sizeof_gr_complex)) # Output signature 56 57 # FIXME audio_rate and quad_rate ought to be exact rationals 58 audio_rate = int(audio_rate) 59 quad_rate = int(quad_rate) 60 61 if quad_rate % audio_rate != 0: 62 raise ValueError("quad_rate is not an integer multiple of audio_rate") 63 64 65 do_interp = audio_rate != quad_rate 66 67 if do_interp: 68 interp_factor = quad_rate / audio_rate 69 interp_taps = filter.optfir.low_pass(interp_factor, # gain 70 quad_rate, # Fs 71 16000, # passband cutoff 72 18000, # stopband cutoff 73 0.1, # passband ripple dB 74 40) # stopband atten dB 75 76 print("len(interp_taps) =", len(interp_taps)) 77 self.interpolator = filter.interp_fir_filter_fff (interp_factor, interp_taps) 78 79 self.preemph = fm_preemph(quad_rate, tau=tau, fh=fh) 80 81 k = 2 * math.pi * max_dev / quad_rate 82 self.modulator = analog.frequency_modulator_fc (k) 83 84 if do_interp: 85 self.connect(self, self.interpolator, self.preemph, self.modulator, self) 86 else: 87 self.connect(self, self.preemph, self.modulator, self) 88