Skip to content

Instantly share code, notes, and snippets.

@rtucker
Last active November 23, 2022 13:43
Show Gist options
  • Save rtucker/8641650 to your computer and use it in GitHub Desktop.
Save rtucker/8641650 to your computer and use it in GitHub Desktop.
#!/usr/bin/env /usr/bin/python
# Copyright 2013 Clayton Smith (argilo@gmail.com)
# Copyright 2014 Ryan Tucker (rtucker@gmail.com)
# (Add UDP streaming support, tweak RRC filter)
#
# 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/>.
from gnuradio import gr, atsc, blocks, analog, filter
from gnuradio.filter import firdes
from grc_gnuradio import blks2 as grc_blks2
import sys, os
import osmosdr
UDP_HOST="0.0.0.0"
UDP_PORT=1234
TAPS=100
def main(args):
nargs = len(args)
if nargs == 1:
infile = args[0]
outfile = None
print("Transmitting pre-encoded content: %s" % infile)
elif nargs == 2:
infile = args[0]
outfile = args[1]
print("Converting pre-encoded content to complex baseband: %s -> %s" % (infile, outfile))
else:
infile = None
outfile = None
print("Listening on %s port %d/udp" % (UDP_HOST, UDP_PORT))
symbol_rate = 4500000.0 / 286 * 684
pilot_freq = 309441
center_freq = 473000000
txvga1_gain = -6
txvga2_gain = 12
tb = gr.top_block()
if infile is not None:
src = blocks.file_source(gr.sizeof_char, infile, False if outfile else True)
else:
src = blocks.udp_source(gr.sizeof_char, UDP_HOST, UDP_PORT)
pad = atsc.pad()
rand = atsc.randomizer()
rs_enc = atsc.rs_encoder()
inter = atsc.interleaver()
trell = atsc.trellis_encoder()
fsm = atsc.field_sync_mux()
v2s = blocks.vector_to_stream(gr.sizeof_char, 1024)
minn = blocks.keep_m_in_n(gr.sizeof_char, 832, 1024, 4)
b2f = blocks.uchar_to_float()
mul = blocks.multiply_const_vff((2, ))
add = blocks.add_const_vff((-7 + 1.25, ))
zero = analog.sig_source_f(0, analog.GR_CONST_WAVE, 0, 0, 0)
#rrc = filter.fir_filter_ccf(1, firdes.root_raised_cosine(0.1, symbol_rate, symbol_rate/2, 0.1152, TAPS))
rrc = filter.fft_filter_ccc(1, firdes.root_raised_cosine(0.1, symbol_rate, symbol_rate/2, 0.1152, TAPS))
offset = analog.sig_source_c(symbol_rate, analog.GR_COS_WAVE, -3000000 + pilot_freq, 0.9, 0)
mix = blocks.multiply_vcc(1)
f2c = blocks.float_to_complex(1)
tb.connect(src, pad, rand, rs_enc, inter, trell, fsm, v2s, minn, b2f, mul, add)
tb.connect((add, 0), (f2c, 0))
tb.connect((zero, 0), (f2c, 1))
tb.connect((f2c, 0), (mix, 0))
tb.connect((offset, 0), (mix, 1))
if outfile:
dst = blocks.file_sink(gr.sizeof_gr_complex, outfile)
tb.connect(mix, rrc, dst)
else:
out = osmosdr.sink(args="bladerf=0,buffers=128,buflen=16384")
out.set_sample_rate(symbol_rate)
out.set_center_freq(center_freq, 0)
out.set_freq_corr(0, 0)
out.set_gain(txvga2_gain, 0)
out.set_bb_gain(txvga1_gain, 0)
out.set_bandwidth(6000000, 0)
tb.connect(mix, rrc, out)
tb.run()
if __name__ == '__main__':
main(sys.argv[1:])
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment