update TX rate conversion logic
This commit is contained in:
parent
53dbfb4347
commit
d3719bd11c
|
@ -84,7 +84,7 @@ class my_top_block(gr.top_block):
|
||||||
parser.add_option("-f", "--file1", type="string", default=None, help="specify the input file slot 1")
|
parser.add_option("-f", "--file1", type="string", default=None, help="specify the input file slot 1")
|
||||||
parser.add_option("-F", "--file2", type="string", default=None, help="specify the input file slot 2 (DMR)")
|
parser.add_option("-F", "--file2", type="string", default=None, help="specify the input file slot 2 (DMR)")
|
||||||
parser.add_option("-g", "--gain", type="float", default=1.0, help="input gain")
|
parser.add_option("-g", "--gain", type="float", default=1.0, help="input gain")
|
||||||
parser.add_option("-i", "--if-rate", type="float", default=960000, help="output rate to sdr")
|
parser.add_option("-i", "--if-rate", type="int", default=960000, help="output rate to sdr")
|
||||||
parser.add_option("-I", "--audio-input", type="string", default="", help="pcm input device name. E.g., hw:0,0 or /dev/dsp")
|
parser.add_option("-I", "--audio-input", type="string", default="", help="pcm input device name. E.g., hw:0,0 or /dev/dsp")
|
||||||
parser.add_option("-N", "--gains", type="string", default=None, help="gain settings")
|
parser.add_option("-N", "--gains", type="string", default=None, help="gain settings")
|
||||||
parser.add_option("-O", "--audio-output", type="string", default="default", help="pcm output device name. E.g., hw:0,0 or /dev/dsp")
|
parser.add_option("-O", "--audio-output", type="string", default="default", help="pcm output device name. E.g., hw:0,0 or /dev/dsp")
|
||||||
|
@ -94,7 +94,8 @@ class my_top_block(gr.top_block):
|
||||||
parser.add_option("-Q", "--frequency", type="float", default=0.0, help="Hz")
|
parser.add_option("-Q", "--frequency", type="float", default=0.0, help="Hz")
|
||||||
parser.add_option("-r", "--repeat", action="store_true", default=False, help="input file repeat")
|
parser.add_option("-r", "--repeat", action="store_true", default=False, help="input file repeat")
|
||||||
parser.add_option("-R", "--fullrate-mode", action="store_true", default=False, help="ysf fullrate")
|
parser.add_option("-R", "--fullrate-mode", action="store_true", default=False, help="ysf fullrate")
|
||||||
parser.add_option("-s", "--sample-rate", type="int", default=48000, help="output sample rate")
|
parser.add_option("-s", "--modulator-rate", type="int", default=48000, help="must be submultiple of IF rate")
|
||||||
|
parser.add_option("-S", "--alsa-rate", type="int", default=48000, help="sound source/sink sample rate")
|
||||||
parser.add_option("-t", "--test", type="string", default=None, help="test pattern symbol file")
|
parser.add_option("-t", "--test", type="string", default=None, help="test pattern symbol file")
|
||||||
parser.add_option("-v", "--verbose", type="int", default=0, help="additional output")
|
parser.add_option("-v", "--verbose", type="int", default=0, help="additional output")
|
||||||
(options, args) = parser.parse_args()
|
(options, args) = parser.parse_args()
|
||||||
|
@ -145,10 +146,10 @@ class my_top_block(gr.top_block):
|
||||||
if options.file2 and options.protocol == 'dmr':
|
if options.file2 and options.protocol == 'dmr':
|
||||||
nfiles += 1
|
nfiles += 1
|
||||||
if nfiles < max_inputs and not options.test:
|
if nfiles < max_inputs and not options.test:
|
||||||
AUDIO = audio.source(options.sample_rate, options.audio_input)
|
AUDIO = audio.source(options.alsa_rate, options.audio_input)
|
||||||
lpf_taps = filter.firdes.low_pass(1.0, options.sample_rate, 3400.0, 3400 * 0.1, filter.firdes.WIN_HANN)
|
lpf_taps = filter.firdes.low_pass(1.0, options.alsa_rate, 3400.0, 3400 * 0.1, filter.firdes.WIN_HANN)
|
||||||
audio_rate = 8000
|
audio_rate = 8000
|
||||||
AUDIO_DECIM = filter.fir_filter_fff (int(options.sample_rate / audio_rate), lpf_taps)
|
AUDIO_DECIM = filter.fir_filter_fff (int(options.alsa_rate / audio_rate), lpf_taps)
|
||||||
AUDIO_SCALE = blocks.multiply_const_ff(32767.0 * options.gain)
|
AUDIO_SCALE = blocks.multiply_const_ff(32767.0 * options.gain)
|
||||||
AUDIO_F2S = blocks.float_to_short()
|
AUDIO_F2S = blocks.float_to_short()
|
||||||
self.connect(AUDIO, AUDIO_DECIM, AUDIO_SCALE, AUDIO_F2S)
|
self.connect(AUDIO, AUDIO_DECIM, AUDIO_SCALE, AUDIO_F2S)
|
||||||
|
@ -172,13 +173,13 @@ class my_top_block(gr.top_block):
|
||||||
else:
|
else:
|
||||||
self.connect(AUDIO_F2S, ENCODER2)
|
self.connect(AUDIO_F2S, ENCODER2)
|
||||||
|
|
||||||
MOD = p25_mod_bf(output_sample_rate = options.sample_rate, dstar = (options.protocol == 'dstar'), bt = options.bt, rc = RC_FILTER[options.protocol])
|
MOD = p25_mod_bf(output_sample_rate = options.modulator_rate, dstar = (options.protocol == 'dstar'), bt = options.bt, rc = RC_FILTER[options.protocol])
|
||||||
AMP = blocks.multiply_const_ff(output_gain)
|
AMP = blocks.multiply_const_ff(output_gain)
|
||||||
|
|
||||||
if options.output_file:
|
if options.output_file:
|
||||||
OUT = blocks.file_sink(gr.sizeof_float, options.output_file)
|
OUT = blocks.file_sink(gr.sizeof_float, options.output_file)
|
||||||
elif not options.args:
|
elif not options.args:
|
||||||
OUT = audio.sink(options.sample_rate, options.audio_output)
|
OUT = audio.sink(options.alsa_rate, options.audio_output)
|
||||||
|
|
||||||
if options.protocol == 'dmr' and not options.test:
|
if options.protocol == 'dmr' and not options.test:
|
||||||
self.connect(DMR, MOD)
|
self.connect(DMR, MOD)
|
||||||
|
@ -186,8 +187,13 @@ class my_top_block(gr.top_block):
|
||||||
self.connect(ENCODER, MOD)
|
self.connect(ENCODER, MOD)
|
||||||
|
|
||||||
if options.args:
|
if options.args:
|
||||||
|
f1 = float(options.if_rate) / options.modulator_rate
|
||||||
|
i1 = int(options.if_rate / options.modulator_rate)
|
||||||
|
if f1 - i1 > 1e-3:
|
||||||
|
print '*** Error, sdr rate %d not an integer multiple of modulator rate %d - ratio=%f' % (options.if_rate, options.modulator_rate, f1)
|
||||||
|
sys.exit(1)
|
||||||
self.setup_sdr_output(options, mod_adjust[options.protocol])
|
self.setup_sdr_output(options, mod_adjust[options.protocol])
|
||||||
interp = filter.rational_resampler_fff(options.if_rate / options.sample_rate, 1)
|
interp = filter.rational_resampler_fff(options.if_rate / options.modulator_rate, 1)
|
||||||
self.attn = blocks.multiply_const_cc(0.25)
|
self.attn = blocks.multiply_const_cc(0.25)
|
||||||
self.connect(MOD, AMP, interp, self.fm_modulator, self.attn, self.u)
|
self.connect(MOD, AMP, interp, self.fm_modulator, self.attn, self.u)
|
||||||
else:
|
else:
|
||||||
|
@ -212,7 +218,6 @@ class my_top_block(gr.top_block):
|
||||||
print "setting gain %s to %d" % (name, gain)
|
print "setting gain %s to %d" % (name, gain)
|
||||||
self.u.set_gain(gain, name)
|
self.u.set_gain(gain, name)
|
||||||
|
|
||||||
print 'setting sample rate'
|
|
||||||
self.u.set_sample_rate(options.if_rate)
|
self.u.set_sample_rate(options.if_rate)
|
||||||
self.u.set_center_freq(options.frequency)
|
self.u.set_center_freq(options.frequency)
|
||||||
self.u.set_freq_corr(options.frequency_correction)
|
self.u.set_freq_corr(options.frequency_correction)
|
||||||
|
|
|
@ -107,7 +107,7 @@ class my_top_block(gr.top_block):
|
||||||
parser.add_option("-b", "--bt", type="float", default=0.5, help="specify bt value")
|
parser.add_option("-b", "--bt", type="float", default=0.5, help="specify bt value")
|
||||||
parser.add_option("-f", "--file", type="string", default=None, help="specify the input file (mono 8000 sps S16_LE)")
|
parser.add_option("-f", "--file", type="string", default=None, help="specify the input file (mono 8000 sps S16_LE)")
|
||||||
parser.add_option("-g", "--gain", type="float", default=1.0, help="input gain")
|
parser.add_option("-g", "--gain", type="float", default=1.0, help="input gain")
|
||||||
parser.add_option("-i", "--if-rate", type="float", default=960000, help="output rate to sdr")
|
parser.add_option("-i", "--if-rate", type="int", default=960000, help="output rate to sdr")
|
||||||
parser.add_option("-I", "--audio-input", type="string", default="", help="pcm input device name. E.g., hw:0,0 or /dev/dsp")
|
parser.add_option("-I", "--audio-input", type="string", default="", help="pcm input device name. E.g., hw:0,0 or /dev/dsp")
|
||||||
parser.add_option("-N", "--gains", type="string", default=None, help="gain settings")
|
parser.add_option("-N", "--gains", type="string", default=None, help="gain settings")
|
||||||
parser.add_option("-o", "--if-offset", type="float", default=100000, help="channel spacing (Hz)")
|
parser.add_option("-o", "--if-offset", type="float", default=100000, help="channel spacing (Hz)")
|
||||||
|
@ -115,21 +115,36 @@ class my_top_block(gr.top_block):
|
||||||
parser.add_option("-Q", "--frequency", type="float", default=0.0, help="Hz")
|
parser.add_option("-Q", "--frequency", type="float", default=0.0, help="Hz")
|
||||||
parser.add_option("-r", "--repeat", action="store_true", default=False, help="input file repeat")
|
parser.add_option("-r", "--repeat", action="store_true", default=False, help="input file repeat")
|
||||||
parser.add_option("-R", "--fullrate-mode", action="store_true", default=False, help="ysf fullrate")
|
parser.add_option("-R", "--fullrate-mode", action="store_true", default=False, help="ysf fullrate")
|
||||||
parser.add_option("-s", "--sample-rate", type="int", default=48000, help="output sample rate")
|
parser.add_option("-s", "--modulator-rate", type="int", default=48000, help="must be submultiple of IF rate")
|
||||||
|
parser.add_option("-S", "--alsa-rate", type="int", default=48000, help="sound source/sink sample rate")
|
||||||
parser.add_option("-v", "--verbose", type="int", default=0, help="additional output")
|
parser.add_option("-v", "--verbose", type="int", default=0, help="additional output")
|
||||||
(options, args) = parser.parse_args()
|
(options, args) = parser.parse_args()
|
||||||
|
|
||||||
assert options.file # input file name (-f filename) required
|
assert options.file # input file name (-f filename) required
|
||||||
|
|
||||||
|
f1 = float(options.if_rate) / options.modulator_rate
|
||||||
|
i1 = int(options.if_rate / options.modulator_rate)
|
||||||
|
if f1 - i1 > 1e-3:
|
||||||
|
print '*** Error, sdr rate %d not an integer multiple of modulator rate %d - ratio=%f' % (options.if_rate, options.modulator_rate, f1)
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
protocols = 'dmr p25 dstar ysf'.split()
|
||||||
|
bw = options.if_offset * len(protocols) + 50000
|
||||||
|
if bw > options.if_rate:
|
||||||
|
print '*** Error, a %d Hz band is required for %d channels and guardband.' % (bw, len(protocols))
|
||||||
|
print '*** Either reduce channel spacing using -o (current value is %d Hz),' % (options.if_offset)
|
||||||
|
print '*** or increase SDR output sample rate using -i (current rate is %d Hz)' % (options.if_rate)
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
max_inputs = 1
|
max_inputs = 1
|
||||||
|
|
||||||
from dv_tx import output_gains, gain_adjust, gain_adjust_fullrate, mod_adjust
|
from dv_tx import output_gains, gain_adjust, gain_adjust_fullrate, mod_adjust
|
||||||
|
|
||||||
if options.do_audio:
|
if options.do_audio:
|
||||||
AUDIO = audio.source(options.sample_rate, options.audio_input)
|
AUDIO = audio.source(options.alsa_rate, options.audio_input)
|
||||||
lpf_taps = filter.firdes.low_pass(1.0, options.sample_rate, 3400.0, 3400 * 0.1, filter.firdes.WIN_HANN)
|
lpf_taps = filter.firdes.low_pass(1.0, options.alsa_rate, 3400.0, 3400 * 0.1, filter.firdes.WIN_HANN)
|
||||||
audio_rate = 8000
|
audio_rate = 8000
|
||||||
AUDIO_DECIM = filter.fir_filter_fff (int(options.sample_rate / audio_rate), lpf_taps)
|
AUDIO_DECIM = filter.fir_filter_fff (int(options.alsa_rate / audio_rate), lpf_taps)
|
||||||
AUDIO_SCALE = blocks.multiply_const_ff(32767.0 * options.gain)
|
AUDIO_SCALE = blocks.multiply_const_ff(32767.0 * options.gain)
|
||||||
AUDIO_F2S = blocks.float_to_short()
|
AUDIO_F2S = blocks.float_to_short()
|
||||||
self.connect(AUDIO, AUDIO_DECIM, AUDIO_SCALE, AUDIO_F2S)
|
self.connect(AUDIO, AUDIO_DECIM, AUDIO_SCALE, AUDIO_F2S)
|
||||||
|
@ -138,7 +153,6 @@ class my_top_block(gr.top_block):
|
||||||
alt_input = None
|
alt_input = None
|
||||||
|
|
||||||
SUM = blocks.add_cc()
|
SUM = blocks.add_cc()
|
||||||
protocols = 'dmr p25 dstar ysf'.split()
|
|
||||||
input_repeat = True
|
input_repeat = True
|
||||||
for i in xrange(len(protocols)):
|
for i in xrange(len(protocols)):
|
||||||
SOURCE = blocks.file_source(gr.sizeof_short, options.file, input_repeat)
|
SOURCE = blocks.file_source(gr.sizeof_short, options.file, input_repeat)
|
||||||
|
@ -159,9 +173,9 @@ class my_top_block(gr.top_block):
|
||||||
output_gain = output_gains[protocols[i]],
|
output_gain = output_gains[protocols[i]],
|
||||||
gain_adjust = gain_adj,
|
gain_adjust = gain_adj,
|
||||||
mod_adjust = mod_adjust[protocols[i]],
|
mod_adjust = mod_adjust[protocols[i]],
|
||||||
if_freq = i * options.if_offset,
|
if_freq = (i - len(protocols)/2) * options.if_offset,
|
||||||
if_rate = options.if_rate,
|
if_rate = options.if_rate,
|
||||||
sample_rate = options.sample_rate,
|
sample_rate = options.modulator_rate,
|
||||||
bt = options.bt,
|
bt = options.bt,
|
||||||
fullrate_mode = options.fullrate_mode,
|
fullrate_mode = options.fullrate_mode,
|
||||||
alt_input = alt_input,
|
alt_input = alt_input,
|
||||||
|
|
|
@ -180,9 +180,8 @@ class p25_mod_bf(gr.hier_block2):
|
||||||
gr.io_signature(1, 1, gr.sizeof_float)) # Output signature
|
gr.io_signature(1, 1, gr.sizeof_float)) # Output signature
|
||||||
|
|
||||||
input_sample_rate = 4800 # P25 baseband symbol rate
|
input_sample_rate = 4800 # P25 baseband symbol rate
|
||||||
lcm = gru.lcm(input_sample_rate, output_sample_rate)
|
intermediate_rate = 48000
|
||||||
self._interp_factor = int(lcm // input_sample_rate)
|
self._interp_factor = intermediate_rate / input_sample_rate
|
||||||
self._decimation = int(lcm // output_sample_rate)
|
|
||||||
|
|
||||||
self.dstar = dstar
|
self.dstar = dstar
|
||||||
self.bt = bt
|
self.bt = bt
|
||||||
|
@ -201,13 +200,13 @@ class p25_mod_bf(gr.hier_block2):
|
||||||
|
|
||||||
assert rc is None or rc == 'rc' or rc == 'rrc'
|
assert rc is None or rc == 'rc' or rc == 'rrc'
|
||||||
if rc:
|
if rc:
|
||||||
coeffs = filter.firdes.root_raised_cosine(1.0, output_sample_rate, input_sample_rate, 0.2, 91)
|
coeffs = filter.firdes.root_raised_cosine(1.0, intermediate_rate, input_sample_rate, 0.2, 91)
|
||||||
if rc == 'rc':
|
if rc == 'rc':
|
||||||
coeffs = c4fm_taps(sample_rate=output_sample_rate).generate()
|
coeffs = c4fm_taps(sample_rate=intermediate_rate).generate()
|
||||||
elif self.dstar:
|
elif self.dstar:
|
||||||
coeffs = gmsk_taps(sample_rate=output_sample_rate, bt=self.bt).generate()
|
coeffs = gmsk_taps(sample_rate=intermediate_rate, bt=self.bt).generate()
|
||||||
elif not rc:
|
elif not rc:
|
||||||
coeffs = c4fm_taps(sample_rate=output_sample_rate, generator=self.generator).generate()
|
coeffs = c4fm_taps(sample_rate=intermediate_rate, generator=self.generator).generate()
|
||||||
self.filter = filter.interp_fir_filter_fff(self._interp_factor, coeffs)
|
self.filter = filter.interp_fir_filter_fff(self._interp_factor, coeffs)
|
||||||
|
|
||||||
if verbose:
|
if verbose:
|
||||||
|
@ -217,9 +216,9 @@ class p25_mod_bf(gr.hier_block2):
|
||||||
self._setup_logging()
|
self._setup_logging()
|
||||||
|
|
||||||
self.connect(self, self.C2S, self.polarity, self.filter)
|
self.connect(self, self.C2S, self.polarity, self.filter)
|
||||||
if (self._decimation > 1):
|
if intermediate_rate != output_sample_rate:
|
||||||
self.decimator = filter.rational_resampler_fff(1, self._decimation)
|
self.arb_resamp = filter.pfb.arb_resampler_fff(float(output_sample_rate)/intermediate_rate)
|
||||||
self.connect(self.filter, self.decimator, self)
|
self.connect(self.filter, self.arb_resamp, self)
|
||||||
else:
|
else:
|
||||||
self.connect(self.filter, self)
|
self.connect(self.filter, self)
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue