def __init__(self): gr.top_block.__init__(self) parser = OptionParser(option_class=eng_option) parser.add_option("-a", "--audio-input", type="string", default="") parser.add_option("-A", "--audio-output", type="string", default="") parser.add_option("-f", "--factor", type="eng_float", default=1) parser.add_option("-i", "--do-interp", action="store_true", default=False, help="enable output interpolator") parser.add_option("-s", "--sample-rate", type="int", default=48000, help="input sample rate") parser.add_option("-S", "--stretch", type="int", default=0, help="flex amt") parser.add_option("-y", "--symbol-rate", type="int", default=4800, help="input symbol rate") parser.add_option("-v", "--verbose", action="store_true", default=False, help="dump demodulation data") (options, args) = parser.parse_args() sample_rate = options.sample_rate symbol_rate = options.symbol_rate IN = audio.source(sample_rate, options.audio_input) audio_output_rate = 8000 if options.do_interp: audio_output_rate = 48000 OUT = audio.sink(audio_output_rate, options.audio_output) symbol_decim = 1 symbol_coeffs = gr.firdes.root_raised_cosine(1.0, # gain sample_rate , # sampling rate symbol_rate, # symbol rate 0.2, # width of trans. band 500) # filter type SYMBOL_FILTER = gr.fir_filter_fff (symbol_decim, symbol_coeffs) AMP = gr.multiply_const_ff(options.factor) msgq = gr.msg_queue(2) FSK4 = op25.fsk4_demod_ff(msgq, sample_rate, symbol_rate) levels = levels = [-2.0, 0.0, 2.0, 4.0] SLICER = repeater.fsk4_slicer_fb(levels) framer_msgq = gr.msg_queue(2) DECODE = repeater.p25_frame_assembler('', # udp hostname 0, # udp port no. options.verbose, #debug True, # do_imbe True, # do_output False, # do_msgq framer_msgq) IMBE = repeater.vocoder(False, # 0=Decode,True=Encode options.verbose, # Verbose flag options.stretch, # flex amount "", # udp ip address 0, # udp port False) # dump raw u vectors CVT = gr.short_to_float() if options.do_interp: interp_taps = gr.firdes.low_pass(1.0, 48000, 4000, 4000 * 0.1, gr.firdes.WIN_HANN) INTERP = gr.interp_fir_filter_fff(48000 // 8000, interp_taps) AMP2 = gr.multiply_const_ff(1.0 / 32767.0) self.connect(IN, AMP, SYMBOL_FILTER, FSK4, SLICER, DECODE, IMBE, CVT, AMP2) if options.do_interp: self.connect(AMP2, INTERP, OUT) else: self.connect(AMP2, OUT)
def __init__(self): gr.top_block.__init__(self) parser = OptionParser(option_class=eng_option) parser.add_option("-i", "--input-file", type="string", default="in.dat", help="specify the input file") parser.add_option("-g", "--gain", type="eng_float", default=1.0) parser.add_option("-L", "--low-pass", type="eng_float", default=15e3, help="low pass cut-off", metavar="Hz") parser.add_option("-o", "--output-file", type="string", default="out.dat", help="specify the output file") parser.add_option("-s", "--sample-rate", type="int", default=48000, help="input sample rate") parser.add_option("-v", "--verbose", action="store_true", default=False, help="dump demodulation data") (options, args) = parser.parse_args() sample_rate = options.sample_rate sps = 10 symbol_rate = 4800 # output rate will be 48,000 ntaps = 11 * sps channel_taps = gr.firdes.low_pass(1.0, sample_rate, options.low_pass, options.low_pass * 0.1, gr.firdes.WIN_HANN) IN = gr.file_source(gr.sizeof_short, options.input_file) OUT = gr.file_sink(gr.sizeof_char, options.output_file) CVT = gr.short_to_float() AMP = gr.multiply_const_ff(options.gain / 32767.0) symbol_decim = 1 symbol_coeffs = gr.firdes.root_raised_cosine (1.0, # gain sample_rate , # sampling rate symbol_rate, # symbol rate 0.20, # width of trans. band 500) # filter type SYMBOL_FILTER = gr.fir_filter_fff (symbol_decim, symbol_coeffs) self.msgq = gr.msg_queue(2) FSK4 = op25.fsk4_demod_ff(self.msgq, sample_rate, symbol_rate) levels = [ -2.0, 0.0, 2.0, 4.0 ] SLICER = repeater.fsk4_slicer_fb(levels) hostname = "127.0.0.1" port = 23456 debug = 255 do_imbe = False do_output = True do_msgq = False msgqd = gr.msg_queue(2) DECODER = repeater.p25_frame_assembler(hostname, port, debug, do_imbe, do_output, do_msgq, msgqd) self.connect(IN, CVT, AMP, SYMBOL_FILTER, FSK4, SLICER, DECODER, OUT)
def __init__(self): gr.top_block.__init__(self) parser=OptionParser(option_class=eng_option) parser.add_option("-R", "--rx-subdev-spec", type="subdev", default=None, help="select USRP Rx side A or B (default=A)") parser.add_option("-C", "--costas-alpha", type="eng_float", default=0.125, help="offset frequency", metavar="Hz") parser.add_option("-c", "--calibration", type="int", default=0, help="USRP calibration offset", metavar="FREQ") parser.add_option("-d","--debug", type="int", default=0, help="debug level") parser.add_option("-G", "--gain-mu", type="eng_float", default=0.05, help="Gardner gain") parser.add_option("-H", "--hostname", type="string", default="127.0.0.1", help="IP address of asterisk (or wireshark) host") parser.add_option("-g", "--gain", type="eng_float", default=None, help="set gain in dB (default is midpoint)") parser.add_option("-p", "--port", type="int", default=32001, help="starting port number for chan_usrp") parser.add_option("-w", "--wireshark", action="store_true", default=False, help="write data to wireshark") (options, args) = parser.parse_args() if len(args) != 0: parser.print_help() sys.exit(1) if options.debug > 10: print 'Ready for GDB to attach (pid = %d)' % (os.getpid(),) raw_input("Press 'Enter' to continue...") # build graph self.u = usrp.source_c() # usrp is data source adc_rate = self.u.adc_rate() # 64 MS/s usrp_decim = 60 self.u.set_decim_rate(usrp_decim) usrp_rate = adc_rate / usrp_decim # 1.0667 M channel_decim = 50.0 channel_rate = usrp_rate / channel_decim # 8K sps rate sps = channel_rate / 4800.0 print "channel rate %f sps %f" % (channel_rate, sps) low_pass = 15e3 channel_taps = gr.firdes.low_pass(1.0, usrp_rate, low_pass, low_pass * 0.1, gr.firdes.WIN_HANN) low_pass_nfm = 7.5e3 channel_taps_nfm = gr.firdes.low_pass(1.0, usrp_rate, low_pass_nfm, low_pass_nfm * 0.1, gr.firdes.WIN_HANN) if options.rx_subdev_spec is None: options.rx_subdev_spec = pick_subdevice(self.u) self.u.set_mux(usrp.determine_rx_mux_value(self.u, options.rx_subdev_spec)) self.subdev = usrp.selected_subdev(self.u, options.rx_subdev_spec) print "Using RX d'board %s" % (self.subdev.side_and_name(),) for i in xrange(len(channels)): freq = channels[i]['freq'] mode = channels[i]['mode'] port = channels[i]['port'] ctcss = 0.0 if 'ctcss' in channels[i]: ctcss = channels[i]['ctcss'] wireshark = False if 'wireshark' in channels[i]: wireshark = True lo_freq = center_freq - freq if mode == 'c4fm': channel = rx_channel_c4fm(sps, channel_decim, channel_taps, options, usrp_rate, channel_rate, lo_freq) elif mode == 'cqpsk': channel = rx_channel_cqpsk(sps, channel_decim, channel_taps, options, usrp_rate, channel_rate, lo_freq) elif mode == 'fm': channel = rx_channel_nfm(sps, channel_decim, channel_taps, options, usrp_rate, channel_rate, lo_freq, low_pass, ctcss) elif mode == 'nfm': channel = rx_channel_nfm(sps, channel_decim, channel_taps_nfm, options, usrp_rate, channel_rate, lo_freq, low_pass_nfm, ctcss) # reduce float symbols to binary dibits levels = [ -2.0, 0.0, 2.0, 4.0 ] slicer = repeater.fsk4_slicer_fb(levels) if wireshark: # build p25 frames from raw dibits and write to wireshark msgq = gr.msg_queue(2) decoder = repeater.p25_frame_assembler(options.hostname, WIRESHARK_PORT, options.debug, False, False, False, msgq) self.connect (self.u, channel, slicer, decoder) sinks = gr.file_sink(gr.sizeof_char, "sym-%d.dat" % i) self.connect (slicer, sinks) else: # build p25 frames from raw dibits and extract IMBE speech codewords msgq = gr.msg_queue(2) decoder = repeater.p25_frame_assembler('', 0, options.debug, True, True, False, msgq) # decode the IMBE codewords - outputs speech at 8k rate imbe = repeater.vocoder(False, False, 0, "", 0, False) # write the audio (8k, signed int16) to asterisk app_rpt via UDP chan_rpt = repeater.chan_usrp_rx(options.hostname, port, options.debug) self.connect (self.u, channel, slicer, decoder, imbe, chan_rpt) fsink = gr.file_sink(gr.sizeof_float, 'fm-sink-%d.dat' % port) self.connect (channel, fsink) sfn = "chan-%d.bin" % port ssink = gr.file_sink(gr.sizeof_char, sfn) self.connect (slicer, ssink) print "attached channel %d freq %f port %d" % (i+1, lo_freq, port) if options.gain is None: # if no gain was specified, use the mid-point in dB g = self.subdev.gain_range() options.gain = float(g[0]+g[1])/2 usrp_freq = center_freq + options.calibration # set initial values self.set_gain(options.gain) if not(self.set_freq(usrp_freq)): self._set_status_msg("Failed to set initial frequency")
def __init__(self): gr.top_block.__init__(self) parser = OptionParser(option_class=eng_option) parser.add_option("-1", "--one-channel", action="store_true", default=False, help="software synthesized Q channel") parser.add_option("-a", "--agc", action="store_true", default=False, help="automatic gain control (overrides --gain)") parser.add_option("-c", "--calibration", type="eng_float", default=0, help="freq offset") parser.add_option("-d", "--debug", action="store_true", default=False, help="allow time at init to attach gdb") parser.add_option("-C", "--costas-alpha", type="eng_float", default=0.125, help="Costas alpha") parser.add_option("-g", "--gain", type="eng_float", default=1.0) parser.add_option("-i", "--input-file", type="string", default="in.dat", help="specify the input file") parser.add_option("-I", "--imbe", action="store_true", default=False, help="output IMBE codewords") parser.add_option("-L", "--low-pass", type="eng_float", default=6.5e3, help="low pass cut-off", metavar="Hz") parser.add_option("-o", "--output-file", type="string", default="out.dat", help="specify the output file") parser.add_option("-p", "--polarity", action="store_true", default=False, help="use reversed polarity") parser.add_option("-r", "--raw-symbols", type="string", default=None, help="dump decoded symbols to file") parser.add_option("-s", "--sample-rate", type="int", default=96000, help="input sample rate") parser.add_option("-t", "--tone-detect", action="store_true", default=False, help="use experimental tone detect algorithm") parser.add_option("-v", "--verbose", action="store_true", default=False, help="additional output") parser.add_option("-6", "--k6k", action="store_true", default=False, help="use 6K symbol rate") (options, args) = parser.parse_args() sample_rate = options.sample_rate if options.k6k: symbol_rate = 6000 else: symbol_rate = 4800 samples_per_symbol = sample_rate // symbol_rate IN = gr.file_source(gr.sizeof_gr_complex, options.input_file) if options.one_channel: C2F = gr.complex_to_float() F2C = gr.float_to_complex() # osc./mixer for mixing signal down to approx. zero IF LO = gr.sig_source_c(sample_rate, gr.GR_COS_WAVE, options.calibration, 1.0, 0) MIXER = gr.multiply_cc() # get signal into normalized range (-1.0 - +1.0) if options.agc: AMP = gr.feedforward_agc_cc(16, 1.0) else: AMP = gr.multiply_const_cc(options.gain) lpf_taps = gr.firdes.low_pass(1.0, sample_rate, options.low_pass, options.low_pass * 0.1, gr.firdes.WIN_HANN) decim_amt = 1 if options.tone_detect: if sample_rate != 96000: print "warning, only 96K has been tested." print "other rates may require theta to be reviewed/adjusted." step_size = 7.5e-8 theta = -4 # optimum timing sampling point cic_length = 48 DEMOD = repeater.tdetect_cc(samples_per_symbol, step_size, theta, cic_length) else: # decim by 2 to get 48k rate samples_per_symbol /= 2 # for DECIM sample_rate /= 2 # for DECIM decim_amt = 2 # create Gardner/Costas loop # the loop will not work if the sample levels aren't normalized (above) timing_error_gain = 0.025 # loop error gain gain_omega = 0.25 * timing_error_gain * timing_error_gain alpha = options.costas_alpha beta = 0.125 * alpha * alpha fmin = -0.025 # fmin and fmax are in radians/s fmax = 0.025 DEMOD = repeater.gardner_costas_cc(samples_per_symbol, timing_error_gain, gain_omega, alpha, beta, fmax, fmin) DECIM = gr.fir_filter_ccf(decim_amt, lpf_taps) # probably too much phase noise etc to attempt coherent demodulation # so we use differential DIFF = gr.diff_phasor_cc() # take angle of the phase difference (in radians) TOFLOAT = gr.complex_to_arg() # convert from radians such that signal is in [-3, -1, +1, +3] RESCALE = gr.multiply_const_ff(1 / (pi / 4.0)) # optional polarity reversal (should be unnec. - now autodetected) p = 1.0 if options.polarity: p = -1.0 POLARITY = gr.multiply_const_ff(p) # hard decision at specified points levels = [-2.0, 0.0, 2.0, 4.0] SLICER = repeater.fsk4_slicer_fb(levels) # assemble received frames and route to Wireshark via UDP hostname = "127.0.0.1" port = 23456 debug = 0 if options.verbose: debug = 255 do_imbe = False if options.imbe: do_imbe = True do_output = True # enable block's output stream do_msgq = False # msgq output not yet implemented msgq = gr.msg_queue(2) DECODER = repeater.p25_frame_assembler(hostname, port, debug, do_imbe, do_output, do_msgq, msgq) OUT = gr.file_sink(gr.sizeof_char, options.output_file) if options.one_channel: self.connect(IN, C2F, F2C, (MIXER, 0)) else: self.connect(IN, (MIXER, 0)) self.connect(LO, (MIXER, 1)) self.connect(MIXER, AMP, DECIM, DEMOD, DIFF, TOFLOAT, RESCALE, POLARITY, SLICER, DECODER, OUT) if options.raw_symbols: SINKC = gr.file_sink(gr.sizeof_char, options.raw_symbols) self.connect(SLICER, SINKC) if options.debug: print 'Ready for GDB to attach (pid = %d)' % (os.getpid(), ) raw_input("Press 'Enter' to continue...")
def __init__(self): gr.top_block.__init__(self) parser = OptionParser(option_class=eng_option) parser.add_option("-a", "--audio-input", type="string", default="") parser.add_option("-A", "--analog-gain", type="float", default=1.0, help="output gain for analog channel") parser.add_option("-c", "--ctcss-freq", type="float", default=0.0, help="CTCSS tone frequency") parser.add_option("-d", "--debug", type="int", default=0, help="debug level") parser.add_option("-g", "--gain", type="eng_float", default=1, help="adjusts input level for standard data levels") parser.add_option("-H", "--hostname", type="string", default="127.0.0.1", help="asterisk host IP") parser.add_option("-p", "--port", type="int", default=32001, help="chan_usrp UDP port") parser.add_option("-s", "--sample-rate", type="int", default=48000, help="input sample rate") parser.add_option("-S", "--stretch", type="int", default=0) (options, args) = parser.parse_args() sample_rate = options.sample_rate symbol_rate = 4800 symbol_decim = 1 IN = audio.source(sample_rate, options.audio_input) symbol_coeffs = gr.firdes.root_raised_cosine( 1.0, # gain sample_rate, # sampling rate symbol_rate, # symbol rate 0.2, # width of trans. band 500) # filter type SYMBOL_FILTER = gr.fir_filter_fff(symbol_decim, symbol_coeffs) AMP = gr.multiply_const_ff(options.gain) msgq = gr.msg_queue(2) FSK4 = op25.fsk4_demod_ff(msgq, sample_rate, symbol_rate) levels = levels = [-2.0, 0.0, 2.0, 4.0] SLICER = repeater.fsk4_slicer_fb(levels) framer_msgq = gr.msg_queue(2) DECODE = repeater.p25_frame_assembler( '', # udp hostname 0, # udp port no. options.debug, #debug True, # do_imbe True, # do_output False, # do_msgq framer_msgq) IMBE = repeater.vocoder( False, # 0=Decode,True=Encode options.debug, # Verbose flag options.stretch, # flex amount "", # udp ip address 0, # udp port False) # dump raw u vectors CHAN_RPT = repeater.chan_usrp_rx(options.hostname, options.port, options.debug) self.connect(IN, AMP, SYMBOL_FILTER, FSK4, SLICER, DECODE, IMBE, CHAN_RPT) # blocks for second channel (fm rx) output_sample_rate = 8000 decim_amt = sample_rate / output_sample_rate RESAMP = blks2.rational_resampler_fff(1, decim_amt) if options.ctcss_freq > 0: level = 5.0 len = 0 ramp = 0 gate = True CTCSS = repeater.ctcss_squelch_ff(output_sample_rate, options.ctcss_freq, level, len, ramp, gate) AMP2 = gr.multiply_const_ff(32767.0 * options.analog_gain) CVT = gr.float_to_short() CHAN_RPT2 = repeater.chan_usrp_rx(options.hostname, options.port + 1, options.debug) if options.ctcss_freq > 0: self.connect(IN, RESAMP, CTCSS, AMP2, CVT, CHAN_RPT2) else: self.connect(IN, RESAMP, AMP2, CVT, CHAN_RPT2)
def __init__(self): gr.top_block.__init__(self) parser = OptionParser(option_class=eng_option) parser.add_option("-R", "--rx-subdev-spec", type="subdev", default=None, help="select USRP Rx side A or B (default=A)") parser.add_option("-C", "--costas-alpha", type="eng_float", default=0.125, help="offset frequency", metavar="Hz") parser.add_option("-c", "--calibration", type="int", default=0, help="USRP calibration offset", metavar="FREQ") parser.add_option("-d", "--debug", type="int", default=0, help="debug level") parser.add_option("-G", "--gain-mu", type="eng_float", default=0.05, help="Gardner gain") parser.add_option("-H", "--hostname", type="string", default="127.0.0.1", help="IP address of asterisk (or wireshark) host") parser.add_option("-g", "--gain", type="eng_float", default=None, help="set gain in dB (default is midpoint)") parser.add_option("-p", "--port", type="int", default=32001, help="starting port number for chan_usrp") parser.add_option("-w", "--wireshark", action="store_true", default=False, help="write data to wireshark") (options, args) = parser.parse_args() if len(args) != 0: parser.print_help() sys.exit(1) if options.debug > 10: print 'Ready for GDB to attach (pid = %d)' % (os.getpid(), ) raw_input("Press 'Enter' to continue...") # build graph self.u = usrp.source_c() # usrp is data source adc_rate = self.u.adc_rate() # 64 MS/s usrp_decim = 60 self.u.set_decim_rate(usrp_decim) usrp_rate = adc_rate / usrp_decim # 1.0667 M channel_decim = 50.0 channel_rate = usrp_rate / channel_decim # 8K sps rate sps = channel_rate / 4800.0 print "channel rate %f sps %f" % (channel_rate, sps) low_pass = 15e3 channel_taps = gr.firdes.low_pass(1.0, usrp_rate, low_pass, low_pass * 0.1, gr.firdes.WIN_HANN) low_pass_nfm = 7.5e3 channel_taps_nfm = gr.firdes.low_pass(1.0, usrp_rate, low_pass_nfm, low_pass_nfm * 0.1, gr.firdes.WIN_HANN) if options.rx_subdev_spec is None: options.rx_subdev_spec = pick_subdevice(self.u) self.u.set_mux( usrp.determine_rx_mux_value(self.u, options.rx_subdev_spec)) self.subdev = usrp.selected_subdev(self.u, options.rx_subdev_spec) print "Using RX d'board %s" % (self.subdev.side_and_name(), ) for i in xrange(len(channels)): freq = channels[i]['freq'] mode = channels[i]['mode'] port = channels[i]['port'] ctcss = 0.0 if 'ctcss' in channels[i]: ctcss = channels[i]['ctcss'] wireshark = False if 'wireshark' in channels[i]: wireshark = True lo_freq = center_freq - freq if mode == 'c4fm': channel = rx_channel_c4fm(sps, channel_decim, channel_taps, options, usrp_rate, channel_rate, lo_freq) elif mode == 'cqpsk': channel = rx_channel_cqpsk(sps, channel_decim, channel_taps, options, usrp_rate, channel_rate, lo_freq) elif mode == 'fm': channel = rx_channel_nfm(sps, channel_decim, channel_taps, options, usrp_rate, channel_rate, lo_freq, low_pass, ctcss) elif mode == 'nfm': channel = rx_channel_nfm(sps, channel_decim, channel_taps_nfm, options, usrp_rate, channel_rate, lo_freq, low_pass_nfm, ctcss) # reduce float symbols to binary dibits levels = [-2.0, 0.0, 2.0, 4.0] slicer = repeater.fsk4_slicer_fb(levels) if wireshark: # build p25 frames from raw dibits and write to wireshark msgq = gr.msg_queue(2) decoder = repeater.p25_frame_assembler(options.hostname, WIRESHARK_PORT, options.debug, False, False, False, msgq) self.connect(self.u, channel, slicer, decoder) sinks = gr.file_sink(gr.sizeof_char, "sym-%d.dat" % i) self.connect(slicer, sinks) else: # build p25 frames from raw dibits and extract IMBE speech codewords msgq = gr.msg_queue(2) decoder = repeater.p25_frame_assembler('', 0, options.debug, True, True, False, msgq) # decode the IMBE codewords - outputs speech at 8k rate imbe = repeater.vocoder(False, False, 0, "", 0, False) # write the audio (8k, signed int16) to asterisk app_rpt via UDP chan_rpt = repeater.chan_usrp_rx(options.hostname, port, options.debug) self.connect(self.u, channel, slicer, decoder, imbe, chan_rpt) fsink = gr.file_sink(gr.sizeof_float, 'fm-sink-%d.dat' % port) self.connect(channel, fsink) sfn = "chan-%d.bin" % port ssink = gr.file_sink(gr.sizeof_char, sfn) self.connect(slicer, ssink) print "attached channel %d freq %f port %d" % (i + 1, lo_freq, port) if options.gain is None: # if no gain was specified, use the mid-point in dB g = self.subdev.gain_range() options.gain = float(g[0] + g[1]) / 2 usrp_freq = center_freq + options.calibration # set initial values self.set_gain(options.gain) if not (self.set_freq(usrp_freq)): self._set_status_msg("Failed to set initial frequency")
def __init__(self): gr.top_block.__init__(self) parser = OptionParser(option_class=eng_option) parser.add_option("-a", "--audio-input", type="string", default="") parser.add_option("-A", "--analog-gain", type="float", default=1.0, help="output gain for analog channel") parser.add_option("-c", "--ctcss-freq", type="float", default=0.0, help="CTCSS tone frequency") parser.add_option("-d", "--debug", type="int", default=0, help="debug level") parser.add_option("-g", "--gain", type="eng_float", default=1, help="adjusts input level for standard data levels") parser.add_option("-H", "--hostname", type="string", default="127.0.0.1", help="asterisk host IP") parser.add_option("-p", "--port", type="int", default=32001, help="chan_usrp UDP port") parser.add_option("-s", "--sample-rate", type="int", default=48000, help="input sample rate") parser.add_option("-S", "--stretch", type="int", default=0) (options, args) = parser.parse_args() sample_rate = options.sample_rate symbol_rate = 4800 symbol_decim = 1 IN = audio.source(sample_rate, options.audio_input) symbol_coeffs = gr.firdes.root_raised_cosine(1.0, # gain sample_rate , # sampling rate symbol_rate, # symbol rate 0.2, # width of trans. band 500) # filter type SYMBOL_FILTER = gr.fir_filter_fff (symbol_decim, symbol_coeffs) AMP = gr.multiply_const_ff(options.gain) msgq = gr.msg_queue(2) FSK4 = fsk4.demod_ff(msgq, sample_rate, symbol_rate) levels = levels = [-2.0, 0.0, 2.0, 4.0] SLICER = repeater.fsk4_slicer_fb(levels) framer_msgq = gr.msg_queue(2) DECODE = repeater.p25_frame_assembler('', # udp hostname 0, # udp port no. options.debug, #debug True, # do_imbe True, # do_output False, # do_msgq framer_msgq) IMBE = repeater.vocoder(False, # 0=Decode,True=Encode options.debug, # Verbose flag options.stretch, # flex amount "", # udp ip address 0, # udp port False) # dump raw u vectors CHAN_RPT = repeater.chan_usrp_rx(options.hostname, options.port, options.debug) self.connect(IN, AMP, SYMBOL_FILTER, FSK4, SLICER, DECODE, IMBE, CHAN_RPT) # blocks for second channel (fm rx) output_sample_rate = 8000 decim_amt = sample_rate / output_sample_rate RESAMP = blks2.rational_resampler_fff(1, decim_amt) if options.ctcss_freq > 0: level = 5.0 len = 0 ramp = 0 gate = True CTCSS = repeater.ctcss_squelch_ff(output_sample_rate, options.ctcss_freq, level, len, ramp, gate) AMP2 = gr.multiply_const_ff(32767.0 * options.analog_gain) CVT = gr.float_to_short() CHAN_RPT2 = repeater.chan_usrp_rx(options.hostname, options.port+1, options.debug) if options.ctcss_freq > 0: self.connect(IN, RESAMP, CTCSS, AMP2, CVT, CHAN_RPT2) else: self.connect(IN, RESAMP, AMP2, CVT, CHAN_RPT2)
def __init__(self): gr.top_block.__init__(self) parser = OptionParser(option_class=eng_option) parser.add_option("-1", "--one-channel", action="store_true", default=False, help="software synthesized Q channel") parser.add_option("-c", "--calibration", type="eng_float", default=0, help="freq offset") parser.add_option("-d", "--debug", action="store_true", default=False, help="allow time at init to attach gdb") parser.add_option("-C", "--costas-alpha", type="eng_float", default=0.125, help="Costas alpha") parser.add_option("-g", "--gain", type="eng_float", default=1.0) parser.add_option("-i", "--input-file", type="string", default="in.dat", help="specify the input file") parser.add_option("-I", "--imbe", action="store_true", default=False, help="output IMBE codewords") parser.add_option("-L", "--low-pass", type="eng_float", default=6.5e3, help="low pass cut-off", metavar="Hz") parser.add_option("-o", "--output-file", type="string", default="out.dat", help="specify the output file") parser.add_option("-p", "--polarity", action="store_true", default=False, help="use reversed polarity") parser.add_option("-s", "--sample-rate", type="int", default=96000, help="input sample rate") parser.add_option("-t", "--tone-detect", action="store_true", default=False, help="use experimental tone detect algorithm") parser.add_option("-v", "--verbose", action="store_true", default=False, help="additional output") (options, args) = parser.parse_args() sample_rate = options.sample_rate symbol_rate = 4800 samples_per_symbol = sample_rate // symbol_rate IN = gr.file_source(gr.sizeof_gr_complex, options.input_file) if options.one_channel: C2F = gr.complex_to_float() F2C = gr.float_to_complex() # osc./mixer for mixing signal down to approx. zero IF LO = gr.sig_source_c (sample_rate, gr.GR_COS_WAVE, options.calibration, 1.0, 0) MIXER = gr.multiply_cc() # get signal into normalized range (-1.0 - +1.0) # FIXME: add AGC AMP = gr.multiply_const_cc(options.gain) lpf_taps = gr.firdes.low_pass(1.0, sample_rate, options.low_pass, options.low_pass * 0.1, gr.firdes.WIN_HANN) decim_amt = 1 if options.tone_detect: if sample_rate != 96000: print "warning, only 96K has been tested." print "other rates may require theta to be reviewed/adjusted." step_size = 7.5e-8 theta = -4 # optimum timing sampling point cic_length = 48 DEMOD = repeater.tdetect_cc(samples_per_symbol, step_size, theta, cic_length) else: # decim by 2 to get 48k rate samples_per_symbol /= 2 # for DECIM sample_rate /= 2 # for DECIM decim_amt = 2 # create Gardner/Costas loop # the loop will not work if the sample levels aren't normalized (above) timing_error_gain = 0.025 # loop error gain gain_omega = 0.25 * timing_error_gain * timing_error_gain alpha = options.costas_alpha beta = 0.125 * alpha * alpha fmin = -0.025 # fmin and fmax are in radians/s fmax = 0.025 DEMOD = repeater.gardner_costas_cc(samples_per_symbol, timing_error_gain, gain_omega, alpha, beta, fmax, fmin) DECIM = gr.fir_filter_ccf (decim_amt, lpf_taps) # probably too much phase noise etc to attempt coherent demodulation # so we use differential DIFF = gr.diff_phasor_cc() # take angle of the phase difference (in radians) TOFLOAT = gr.complex_to_arg() # convert from radians such that signal is in [-3, -1, +1, +3] RESCALE = gr.multiply_const_ff(1 / (pi / 4.0)) # optional polarity reversal (should be unnec. - now autodetected) p = 1.0 if options.polarity: p = -1.0 POLARITY = gr.multiply_const_ff(p) # hard decision at specified points levels = [-2.0, 0.0, 2.0, 4.0 ] SLICER = repeater.fsk4_slicer_fb(levels) # assemble received frames and route to Wireshark via UDP hostname = "127.0.0.1" port = 23456 debug = 0 if options.verbose: debug = 255 do_imbe = False if options.imbe: do_imbe = True do_output = True # enable block's output stream do_msgq = False # msgq output not yet implemented msgq = gr.msg_queue(2) DECODER = repeater.p25_frame_assembler(hostname, port, debug, do_imbe, do_output, do_msgq, msgq) OUT = gr.file_sink(gr.sizeof_char, options.output_file) if options.one_channel: self.connect(IN, C2F, F2C, (MIXER, 0)) else: self.connect(IN, (MIXER, 0)) self.connect(LO, (MIXER, 1)) self.connect(MIXER, AMP, DECIM, DEMOD, DIFF, TOFLOAT, RESCALE, POLARITY, SLICER, DECODER, OUT) if options.debug: print 'Ready for GDB to attach (pid = %d)' % (os.getpid(),) raw_input("Press 'Enter' to continue...")
def __init__(self): gr.top_block.__init__(self) parser = OptionParser(option_class=eng_option) parser.add_option("-a", "--audio-input", type="string", default="") parser.add_option("-A", "--audio-output", type="string", default="") parser.add_option("-f", "--factor", type="eng_float", default=1) parser.add_option("-i", "--do-interp", action="store_true", default=False, help="enable output interpolator") parser.add_option("-s", "--sample-rate", type="int", default=48000, help="input sample rate") parser.add_option("-S", "--stretch", type="int", default=0, help="flex amt") parser.add_option("-y", "--symbol-rate", type="int", default=4800, help="input symbol rate") parser.add_option("-v", "--verbose", action="store_true", default=False, help="dump demodulation data") (options, args) = parser.parse_args() sample_rate = options.sample_rate symbol_rate = options.symbol_rate IN = audio.source(sample_rate, options.audio_input) audio_output_rate = 8000 if options.do_interp: audio_output_rate = 48000 OUT = audio.sink(audio_output_rate, options.audio_output) symbol_decim = 1 symbol_coeffs = gr.firdes.root_raised_cosine( 1.0, # gain sample_rate, # sampling rate symbol_rate, # symbol rate 0.2, # width of trans. band 500) # filter type SYMBOL_FILTER = gr.fir_filter_fff(symbol_decim, symbol_coeffs) AMP = gr.multiply_const_ff(options.factor) msgq = gr.msg_queue(2) FSK4 = op25.fsk4_demod_ff(msgq, sample_rate, symbol_rate) levels = levels = [-2.0, 0.0, 2.0, 4.0] SLICER = repeater.fsk4_slicer_fb(levels) framer_msgq = gr.msg_queue(2) DECODE = repeater.p25_frame_assembler( '', # udp hostname 0, # udp port no. options.verbose, #debug True, # do_imbe True, # do_output False, # do_msgq framer_msgq) IMBE = repeater.vocoder( False, # 0=Decode,True=Encode options.verbose, # Verbose flag options.stretch, # flex amount "", # udp ip address 0, # udp port False) # dump raw u vectors CVT = gr.short_to_float() if options.do_interp: interp_taps = gr.firdes.low_pass(1.0, 48000, 4000, 4000 * 0.1, gr.firdes.WIN_HANN) INTERP = gr.interp_fir_filter_fff(48000 // 8000, interp_taps) AMP2 = gr.multiply_const_ff(1.0 / 32767.0) self.connect(IN, AMP, SYMBOL_FILTER, FSK4, SLICER, DECODE, IMBE, CVT, AMP2) if options.do_interp: self.connect(AMP2, INTERP, OUT) else: self.connect(AMP2, OUT)
def __init__(self): gr.top_block.__init__(self) parser = OptionParser(option_class=eng_option) parser.add_option("-i", "--input-file", type="string", default="in.dat", help="specify the input file") parser.add_option("-g", "--gain", type="eng_float", default=1.0) parser.add_option("-L", "--low-pass", type="eng_float", default=15e3, help="low pass cut-off", metavar="Hz") parser.add_option("-o", "--output-file", type="string", default="out.dat", help="specify the output file") parser.add_option("-s", "--sample-rate", type="int", default=48000, help="input sample rate") parser.add_option("-v", "--verbose", action="store_true", default=False, help="dump demodulation data") (options, args) = parser.parse_args() sample_rate = options.sample_rate sps = 10 symbol_rate = 4800 # output rate will be 48,000 ntaps = 11 * sps channel_taps = gr.firdes.low_pass(1.0, sample_rate, options.low_pass, options.low_pass * 0.1, gr.firdes.WIN_HANN) IN = gr.file_source(gr.sizeof_short, options.input_file) OUT = gr.file_sink(gr.sizeof_char, options.output_file) CVT = gr.short_to_float() AMP = gr.multiply_const_ff(options.gain / 32767.0) symbol_decim = 1 symbol_coeffs = gr.firdes.root_raised_cosine( 1.0, # gain sample_rate, # sampling rate symbol_rate, # symbol rate 0.20, # width of trans. band 500) # filter type SYMBOL_FILTER = gr.fir_filter_fff(symbol_decim, symbol_coeffs) self.msgq = gr.msg_queue(2) FSK4 = op25.fsk4_demod_ff(self.msgq, sample_rate, symbol_rate) levels = [-2.0, 0.0, 2.0, 4.0] SLICER = repeater.fsk4_slicer_fb(levels) hostname = "127.0.0.1" port = 23456 debug = 255 do_imbe = False do_output = True do_msgq = False msgqd = gr.msg_queue(2) DECODER = repeater.p25_frame_assembler(hostname, port, debug, do_imbe, do_output, do_msgq, msgqd) self.connect(IN, CVT, AMP, SYMBOL_FILTER, FSK4, SLICER, DECODER, OUT)