def __init__(self, constellation, differential, rotation): if constellation.arity() > 256: # If this becomes limiting some of the blocks should be generalised so # that they can work with shorts and ints as well as chars. raise ValueError("Constellation cannot contain more than 256 points.") gr.hier_block2.__init__(self, "mod_demod", gr.io_signature(1, 1, gr.sizeof_char), # Input signature gr.io_signature(1, 1, gr.sizeof_char)) # Output signature arity = constellation.arity() # TX self.constellation = constellation self.differential = differential import weakref self.blocks = [weakref.proxy(self)] # We expect a stream of unpacked bits. # First step is to pack them. self.blocks.append( gr.unpacked_to_packed_bb(1, gr.GR_MSB_FIRST)) # Second step we unpack them such that we have k bits in each byte where # each constellation symbol hold k bits. self.blocks.append( gr.packed_to_unpacked_bb(self.constellation.bits_per_symbol(), gr.GR_MSB_FIRST)) # Apply any pre-differential coding # Gray-coding is done here if we're also using differential coding. if self.constellation.apply_pre_diff_code(): self.blocks.append(gr.map_bb(self.constellation.pre_diff_code())) # Differential encoding. if self.differential: self.blocks.append(gr.diff_encoder_bb(arity)) # Convert to constellation symbols. self.blocks.append(gr.chunks_to_symbols_bc(self.constellation.points(), self.constellation.dimensionality())) # CHANNEL # Channel just consists of a rotation to check differential coding. if rotation is not None: self.blocks.append(gr.multiply_const_cc(rotation)) # RX # Convert the constellation symbols back to binary values. self.blocks.append(digital_swig.constellation_decoder_cb(self.constellation.base())) # Differential decoding. if self.differential: self.blocks.append(gr.diff_decoder_bb(arity)) # Decode any pre-differential coding. if self.constellation.apply_pre_diff_code(): self.blocks.append(gr.map_bb( mod_codes.invert_code(self.constellation.pre_diff_code()))) # unpack the k bit vector into a stream of bits self.blocks.append(gr.unpack_k_bits_bb( self.constellation.bits_per_symbol())) # connect to block output check_index = len(self.blocks) self.blocks = self.blocks[:check_index] self.blocks.append(weakref.proxy(self)) self.connect(*self.blocks)
def __init__(self, constellation, differential, rotation): if constellation.arity() > 256: # If this becomes limiting some of the blocks should be generalised so # that they can work with shorts and ints as well as chars. raise ValueError("Constellation cannot contain more than 256 points.") gr.hier_block2.__init__(self, "mod_demod", gr.io_signature(1, 1, gr.sizeof_char), # Input signature gr.io_signature(1, 1, gr.sizeof_char)) # Output signature arity = constellation.arity() # TX self.constellation = constellation self.differential = differential self.blocks = [self] # We expect a stream of unpacked bits. # First step is to pack them. self.blocks.append( gr.unpacked_to_packed_bb(1, gr.GR_MSB_FIRST)) # Second step we unpack them such that we have k bits in each byte where # each constellation symbol hold k bits. self.blocks.append( gr.packed_to_unpacked_bb(self.constellation.bits_per_symbol(), gr.GR_MSB_FIRST)) # Apply any pre-differential coding # Gray-coding is done here if we're also using differential coding. if self.constellation.apply_pre_diff_code(): self.blocks.append(gr.map_bb(self.constellation.pre_diff_code())) # Differential encoding. if self.differential: self.blocks.append(gr.diff_encoder_bb(arity)) # Convert to constellation symbols. self.blocks.append(gr.chunks_to_symbols_bc(self.constellation.points(), self.constellation.dimensionality())) # CHANNEL # Channel just consists of a rotation to check differential coding. if rotation is not None: self.blocks.append(gr.multiply_const_cc(rotation)) # RX # Convert the constellation symbols back to binary values. self.blocks.append(digital_swig.constellation_decoder_cb(self.constellation.base())) # Differential decoding. if self.differential: self.blocks.append(gr.diff_decoder_bb(arity)) # Decode any pre-differential coding. if self.constellation.apply_pre_diff_code(): self.blocks.append(gr.map_bb( mod_codes.invert_code(self.constellation.pre_diff_code()))) # unpack the k bit vector into a stream of bits self.blocks.append(gr.unpack_k_bits_bb( self.constellation.bits_per_symbol())) # connect to block output check_index = len(self.blocks) self.blocks = self.blocks[:check_index] self.blocks.append(self) self.connect(*self.blocks)
def __init__(self, options, args): gr.top_block.__init__(self) self.options = options self.args = args frekvens = options.freq # u = usrp.source_c(0) # u.set_decim_rate(256) # subdev_spec = (1,0) # u.set_mux(usrp.determine_rx_mux_value(u,subdev_spec)) # subdev = usrp.selected_subdev(u,subdev_spec) # subdev.set_auto_tr(True) # subdev.set_gain(57) # usrp.tune(u,0,subdev,frekvens)#106.3e6) # samplerate = 64000000/256 # 250000 self.u = uhd.usrp_source("", uhd.io_type_t.COMPLEX_FLOAT32, 1) self.u.set_subdev_spec("") # default should be good? self.u.set_samp_rate(250e3) samplerate = self.u.get_samp_rate() # Retrieve what it actually does self.u.set_antenna("RX2", 0) if options.gain is None: # set to halfway g = self.u.get_gain_range() options.gain = (g.start() + g.stop()) / 2.0 if not (self.u.set_center_freq(frekvens, 0)): print "Failed to set frequency" sys.exit(1) print "Setting gain to %i" % options.gain self.u.set_gain(options.gain) coeffs = gr.firdes.low_pass(1, samplerate, 10000, 10000) filter = gr.fir_filter_ccf(5, coeffs) gang = gr.multiply_const_ff(10) lpcoeffs = gr.firdes.low_pass(1, samplerate, 8000, 3000) lpfilter = gr.fir_filter_fff(1, lpcoeffs) demod = gr.quadrature_demod_cf(0.5) clockrec = gr.clock_recovery_mm_ff( float(samplerate) / 5 / 9600, 0.25 * 0.175 * 0.175, 0.5, 0.175, 0.005) #datadec = ais.ais_decoder_mysql("localhost","diverse","aisblock","elgelg") self.datadec = ais.ais_decoder_gearth(30003) slicer = gr.binary_slicer_fb() diff = gr.diff_decoder_bb(2) invert = ais.invert10_bb() # print subdev.name() self.connect(self.u, filter, demod, lpfilter, gang, clockrec, slicer, diff, invert, self.datadec)
def __init__(self, options, args): gr.top_block.__init__(self) self.options = options self.args = args frekvens = options.freq # u = usrp.source_c(0) # u.set_decim_rate(256) # subdev_spec = (1,0) # u.set_mux(usrp.determine_rx_mux_value(u,subdev_spec)) # subdev = usrp.selected_subdev(u,subdev_spec) # subdev.set_auto_tr(True) # subdev.set_gain(57) # usrp.tune(u,0,subdev,frekvens)#106.3e6) # samplerate = 64000000/256 # 250000 self.u = uhd.usrp_source("", uhd.io_type_t.COMPLEX_FLOAT32,1) self.u.set_subdev_spec(""); # default should be good? self.u.set_samp_rate(250e3); samplerate = self.u.get_samp_rate() # Retrieve what it actually does self.u.set_antenna("RX2",0) if options.gain is None: # set to halfway g = self.u.get_gain_range() options.gain = (g.start()+g.stop()) / 2.0 if not(self.u.set_center_freq(frekvens, 0)): print "Failed to set frequency" sys.exit(1) print "Setting gain to %i" % options.gain self.u.set_gain(options.gain) coeffs = gr.firdes.low_pass(1,samplerate,10000,10000) filter = gr.fir_filter_ccf(5,coeffs) gang = gr.multiply_const_ff(10) lpcoeffs = gr.firdes.low_pass(1,samplerate,8000,3000) lpfilter = gr.fir_filter_fff(1,lpcoeffs) demod = gr.quadrature_demod_cf(0.5) clockrec = gr.clock_recovery_mm_ff(float(samplerate)/5/9600,0.25*0.175*0.175,0.5,0.175,0.005) #datadec = ais.ais_decoder_mysql("localhost","diverse","aisblock","elgelg") self.datadec = ais.ais_decoder_gearth(30003) slicer = gr.binary_slicer_fb() diff = gr.diff_decoder_bb(2) invert = ais.invert10_bb() # print subdev.name() self.connect(self.u,filter,demod,lpfilter,gang,clockrec, slicer,diff,invert,self.datadec)
def test_diff_encdec_002(self): random.seed(0) modulus = 8 src_data = make_random_int_tuple(40000, 0, modulus-1) expected_result = src_data src = gr.vector_source_b(src_data) enc = gr.diff_encoder_bb(modulus) dec = gr.diff_decoder_bb(modulus) dst = gr.vector_sink_b() self.tb.connect(src, enc, dec, dst) self.tb.run() # run the graph and wait for it to finish actual_result = dst.data() # fetch the contents of the sink self.assertEqual(expected_result, actual_result)
def __init__(self, samp_rate, symbol_rate=31.25): super(psk31_receiver, self).__init__( "psk31_receiver", gr.io_signature(1, 1, gr.sizeof_gr_complex), gr.io_signature(0, 0, 1)) self.symbol_rate = symbol_rate self.costas = digital.costas_loop_cc(2*3.14/100, 4) self.clock_recovery = digital.clock_recovery_mm_cc( 1.0*samp_rate/symbol_rate, 0.25 * 0.1*0.1, 0.05, 0.1, 0.001) self.receiver = digital.constellation_receiver_cb( digital.constellation_bpsk().base(), 2*3.14/100, -0.25, 0.25) self.diff = gr.diff_decoder_bb(2) self.decoder = ham.psk31_decode_bb(True) self.msgq_out = gr.msg_queue() self.snk = gr.message_sink(gr.sizeof_char, self.msgq_out, True) self.connect(self, self.costas, self.clock_recovery, self.receiver, self.diff, self.decoder, self.snk)
def __init__(self, samples_per_symbol=1): gr.hier_block2.__init__(self, 'gsm_modulate_burst', gr.io_signature2(2, 2, 58 * 2, 1), gr.io_signature(1, 1, gr.sizeof_gr_complex)) # take care of the packetizer conf = mlse.make_packet_config_gsm() self.packetbuilder = mlse.packetbuilder_midamble_vbb(conf) self.connect(self, self.packetbuilder) self.connect((self, 1), (self.packetbuilder, 1)) # tsc_index # append 8 1-bits to the packet for the idle-time between bursts. # This is necessary among others to flush the gmsk-modulator which is causal. # (We use 1-bits because that's what the gsm-standard says) # (we also only use 8 bits, because the specified value of 8.25 only works # properly with samplerates that are a multiple of 4.) self.guardbits = gr.vector_source_b((1, ) * 8, True, 8) self.guard_cat = mlse.vector_concat_vv(148, 8) self.connect(self.packetbuilder, self.guard_cat) self.connect(self.guardbits, (self.guard_cat, 1)) # we now have a vector of bits, transform that into a stream self.tostream = gr.vector_to_stream(1, 148 + 8) # do the precoding: self.diffcode = gr.diff_decoder_bb(2) self.nrz = gr.map_bb([1, -1]) self.connect(self.guard_cat, self.tostream, self.diffcode, self.nrz) # modulate self.mod = digital.gmskmod_bc(samples_per_symbol, 0.3, 8) # skip the first gmsk_length*samplerate/2 samples to make this block # acausal. # self.skiphead = gr.skiphead(gr.sizeof_gr_complex, int(samples_per_symbol*4.5)); # self.connect(self.nrz, self.mod, self.skiphead, self) self.connect(self.nrz, self.mod, self) # workaround: we need a negative delay later,
def __init__(self, samples_per_symbol = 1): gr.hier_block2.__init__(self, 'gsm_modulate_burst', gr.io_signature2(2,2,58*2,1), gr.io_signature(1, 1, gr.sizeof_gr_complex)) # take care of the packetizer conf = mlse.make_packet_config_gsm() self.packetbuilder = mlse.packetbuilder_midamble_vbb(conf) self.connect(self, self.packetbuilder) self.connect((self,1), (self.packetbuilder,1)) # tsc_index # append 8 1-bits to the packet for the idle-time between bursts. # This is necessary among others to flush the gmsk-modulator which is causal. # (We use 1-bits because that's what the gsm-standard says) # (we also only use 8 bits, because the specified value of 8.25 only works # properly with samplerates that are a multiple of 4.) self.guardbits = gr.vector_source_b((1,)*8,True,8) self.guard_cat = mlse.vector_concat_vv(148,8) self.connect(self.packetbuilder, self.guard_cat) self.connect(self.guardbits, (self.guard_cat,1)) # we now have a vector of bits, transform that into a stream self.tostream = gr.vector_to_stream(1, 148+8) # do the precoding: self.diffcode = gr.diff_decoder_bb(2); self.nrz = gr.map_bb([1,-1]) self.connect(self.guard_cat, self.tostream, self.diffcode, self.nrz) # modulate self.mod = digital.gmskmod_bc(samples_per_symbol, 0.3, 8) # skip the first gmsk_length*samplerate/2 samples to make this block # acausal. # self.skiphead = gr.skiphead(gr.sizeof_gr_complex, int(samples_per_symbol*4.5)); # self.connect(self.nrz, self.mod, self.skiphead, self) self.connect(self.nrz, self.mod, self) # workaround: we need a negative delay later,
def __init__(self, frame, panel, vbox, argv): stdgui2.std_top_block.__init__(self, frame, panel, vbox, argv) parser = OptionParser(option_class=eng_option) parser.add_option("-V", "--volume", type="eng_float", default=None, help="set volume (default is midpoint)") parser.add_option("-O", "--audio-output", type="string", default="plughw:0,0", help="pcm device name (default is plughw:0,0)") # print help when called with wrong arguments (options, args) = parser.parse_args() if len(args) != 0: parser.print_help() sys.exit(1) self.file_source = gr.file_source(gr.sizeof_gr_complex * 1, offline_samples, True) chan_filter_coeffs = gr.firdes.low_pass( 1.0, # gain usrp_rate, # sampling rate 80e3, # passband cutoff 35e3, # transition width gr.firdes.WIN_HAMMING) self.chan_filter = gr.fir_filter_ccf(1, chan_filter_coeffs) print "# channel filter:", len(chan_filter_coeffs), "taps" # PLL-based WFM demod fm_alpha = 0.25 * 250e3 * math.pi / usrp_rate # 0.767 fm_beta = fm_alpha * fm_alpha / 4.0 # 0.147 fm_max_freq = 2.0 * math.pi * 90e3 / usrp_rate # 2.209 self.fm_demod = gr.pll_freqdet_cf( fm_alpha, # phase gain fm_beta, # freq gain fm_max_freq, # in radians/sample -fm_max_freq) self.connect(self.file_source, self.chan_filter, self.fm_demod) # L+R, pilot, L-R, RDS filters lpr_filter_coeffs = gr.firdes.low_pass( 1.0, # gain usrp_rate, # sampling rate 15e3, # passband cutoff 1e3, # transition width gr.firdes.WIN_HAMMING) self.lpr_filter = gr.fir_filter_fff(audio_decim, lpr_filter_coeffs) pilot_filter_coeffs = gr.firdes.band_pass( 1.0, # gain usrp_rate, # sampling rate 19e3 - 500, # low cutoff 19e3 + 500, # high cutoff 1e3, # transition width gr.firdes.WIN_HAMMING) self.pilot_filter = gr.fir_filter_fff(1, pilot_filter_coeffs) dsbsc_filter_coeffs = gr.firdes.band_pass( 1.0, # gain usrp_rate, # sampling rate 38e3 - 15e3 / 2, # low cutoff 38e3 + 15e3 / 2, # high cutoff 1e3, # transition width gr.firdes.WIN_HAMMING) self.dsbsc_filter = gr.fir_filter_fff(1, dsbsc_filter_coeffs) rds_filter_coeffs = gr.firdes.band_pass( 1.0, # gain usrp_rate, # sampling rate 57e3 - 3e3, # low cutoff 57e3 + 3e3, # high cutoff 3e3, # transition width gr.firdes.WIN_HAMMING) self.rds_filter = gr.fir_filter_fff(1, rds_filter_coeffs) print "# lpr filter:", len(lpr_filter_coeffs), "taps" print "# pilot filter:", len(pilot_filter_coeffs), "taps" print "# dsbsc filter:", len(dsbsc_filter_coeffs), "taps" print "# rds filter:", len(rds_filter_coeffs), "taps" self.connect(self.fm_demod, self.lpr_filter) self.connect(self.fm_demod, self.pilot_filter) self.connect(self.fm_demod, self.dsbsc_filter) self.connect(self.fm_demod, self.rds_filter) # down-convert L-R, RDS self.stereo_baseband = gr.multiply_ff() self.connect(self.pilot_filter, (self.stereo_baseband, 0)) self.connect(self.pilot_filter, (self.stereo_baseband, 1)) self.connect(self.dsbsc_filter, (self.stereo_baseband, 2)) self.rds_baseband = gr.multiply_ff() self.connect(self.pilot_filter, (self.rds_baseband, 0)) self.connect(self.pilot_filter, (self.rds_baseband, 1)) self.connect(self.pilot_filter, (self.rds_baseband, 2)) self.connect(self.rds_filter, (self.rds_baseband, 3)) # low-pass and downsample L-R lmr_filter_coeffs = gr.firdes.low_pass( 1.0, # gain usrp_rate, # sampling rate 15e3, # passband cutoff 1e3, # transition width gr.firdes.WIN_HAMMING) self.lmr_filter = gr.fir_filter_fff(audio_decim, lmr_filter_coeffs) self.connect(self.stereo_baseband, self.lmr_filter) # create L, R from L-R, L+R self.left = gr.add_ff() self.right = gr.sub_ff() self.connect(self.lpr_filter, (self.left, 0)) self.connect(self.lmr_filter, (self.left, 1)) self.connect(self.lpr_filter, (self.right, 0)) self.connect(self.lmr_filter, (self.right, 1)) # send audio to null sink self.null0 = gr.null_sink(gr.sizeof_float) self.null1 = gr.null_sink(gr.sizeof_float) self.connect(self.left, self.null0) self.connect(self.right, self.null1) # low-pass the baseband RDS signal at 1.5kHz rds_bb_filter_coeffs = gr.firdes.low_pass( 1, # gain usrp_rate, # sampling rate 1.5e3, # passband cutoff 2e3, # transition width gr.firdes.WIN_HAMMING) self.rds_bb_filter = gr.fir_filter_fff(audio_decim, rds_bb_filter_coeffs) print "# rds bb filter:", len(rds_bb_filter_coeffs), "taps" self.connect(self.rds_baseband, self.rds_bb_filter) # 1187.5bps = 19kHz/16 self.clock_divider = rds.freq_divider(16) rds_clock_taps = gr.firdes.low_pass( 1, # gain usrp_rate, # sampling rate 1.2e3, # passband cutoff 1.5e3, # transition width gr.firdes.WIN_HAMMING) self.rds_clock = gr.fir_filter_fff(audio_decim, rds_clock_taps) print "# rds clock filter:", len(rds_clock_taps), "taps" self.connect(self.pilot_filter, self.clock_divider, self.rds_clock) # bpsk_demod, diff_decoder, rds_decoder self.bpsk_demod = rds.bpsk_demod(audio_rate) self.differential_decoder = gr.diff_decoder_bb(2) self.msgq = gr.msg_queue() self.rds_decoder = rds.data_decoder(self.msgq) self.connect(self.rds_bb_filter, (self.bpsk_demod, 0)) self.connect(self.rds_clock, (self.bpsk_demod, 1)) self.connect(self.bpsk_demod, self.differential_decoder) self.connect(self.differential_decoder, self.rds_decoder) self.frame = frame self.panel = panel self._build_gui(vbox, usrp_rate, audio_rate)
def __init__(self, constellation, samples_per_symbol=_def_samples_per_symbol, differential=_def_differential, excess_bw=_def_excess_bw, gray_coded=True, freq_bw=_def_freq_bw, timing_bw=_def_timing_bw, phase_bw=_def_phase_bw, verbose=_def_verbose, log=_def_log): """ Hierarchical block for RRC-filtered differential generic demodulation. The input is the complex modulated signal at baseband. The output is a stream of bits packed 1 bit per byte (LSB) @param constellation: determines the modulation type @type constellation: gnuradio.digital.gr_constellation @param samples_per_symbol: samples per symbol >= 2 @type samples_per_symbol: float @param excess_bw: Root-raised cosine filter excess bandwidth @type excess_bw: float @param gray_coded: turn gray coding on/off @type gray_coded: bool @param freq_bw: loop filter lock-in bandwidth @type freq_bw: float @param timing_bw: timing recovery loop lock-in bandwidth @type timing_bw: float @param phase_bw: phase recovery loop bandwidth @type phase_bw: float @param verbose: Print information about modulator? @type verbose: bool @param debug: Print modualtion data to files? @type debug: bool """ gr.hier_block2.__init__(self, "generic_demod", gr.io_signature(1, 1, gr.sizeof_gr_complex), # Input signature gr.io_signature(1, 1, gr.sizeof_char)) # Output signature self._constellation = constellation.base() self._samples_per_symbol = samples_per_symbol self._excess_bw = excess_bw self._phase_bw = phase_bw self._freq_bw = freq_bw self._timing_bw = timing_bw self._timing_max_dev= _def_timing_max_dev self._differential = differential if self._samples_per_symbol < 2: raise TypeError, ("sbp must be >= 2, is %d" % self._samples_per_symbol) arity = pow(2,self.bits_per_symbol()) nfilts = 32 ntaps = 11 * int(self._samples_per_symbol*nfilts) # Automatic gain control self.agc = gr.agc2_cc(0.6e-1, 1e-3, 1, 1, 100) # Frequency correction fll_ntaps = 55 self.freq_recov = digital_swig.fll_band_edge_cc(self._samples_per_symbol, self._excess_bw, fll_ntaps, self._freq_bw) # symbol timing recovery with RRC data filter taps = gr.firdes.root_raised_cosine(nfilts, nfilts*self._samples_per_symbol, 1.0, self._excess_bw, ntaps) self.time_recov = gr.pfb_clock_sync_ccf(self._samples_per_symbol, self._timing_bw, taps, nfilts, nfilts//2, self._timing_max_dev) fmin = -0.25 fmax = 0.25 self.receiver = digital_swig.constellation_receiver_cb( self._constellation, self._phase_bw, fmin, fmax) # Do differential decoding based on phase change of symbols if differential: self.diffdec = gr.diff_decoder_bb(arity) if gray_coded: self.symbol_mapper = gr.map_bb( mod_codes.invert_code(self._constellation.pre_diff_code())) # unpack the k bit vector into a stream of bits self.unpack = gr.unpack_k_bits_bb(self.bits_per_symbol()) if verbose: self._print_verbage() if log: self._setup_logging() # Connect and Initialize base class blocks = [self, self.agc, self.freq_recov, self.time_recov, self.receiver] if differential: blocks.append(self.diffdec) if self._constellation.apply_pre_diff_code(): blocks.append(self.symbol_mapper) blocks += [self.unpack, self] self.connect(*blocks)
alle.append([0,0,0,0,0,1,0,0,0,0,1,1,1,1,0,1,0,1,0,1,1,1,0,1,0,1,0,0,0,0,1,0,0,1,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1,0,0,1,1,1,1,0,0,0,0,0,0,0,1,1,0,0,1,0,1,0,0,0,1,1,0,1,0,1,1,0,1,0,0,0,0,1,0,0,0,0,1,1,0,1,1,0,0,0,1,1,1,1,0,0,0,0,1,0,0,0,0,1,0,0,0,1,0,0,0,0,1,0,0,1,1,1,1,1,1,1,1,1,1,0,1,1,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,1,1,0,0,1,1,0,1,0,1,0]) alle.append([0,0,0,0,0,1,0,0,0,1,0,0,1,0,1,0,0,1,1,0,0,0,0,0,1,0,0,1,0,1,1,0,1,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1,0,1,0,0,1,0,0,0,0,0,0,0,0,1,1,0,0,1,0,1,0,0,0,1,0,1,0,1,1,0,0,0,1,1,0,0,1,0,0,0,0,1,1,0,1,1,0,0,0,1,1,0,1,0,0,0,0,1,0,1,0,1,0,1,1,1,1,0,1,1,0,1,0,0,1,1,1,1,1,1,1,1,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,0,1,1,1,0,0,0]) alle.append([0,0,0,0,0,1,0,0,0,1,0,0,1,0,1,0,0,1,1,0,0,0,0,0,1,0,0,1,0,1,1,0,1,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,1,0,1,0,0,0,0,0,0,0,0,1,0,0,0,1,1,1,0,1,0,0,0,0,1,1,0,1,0,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,0,1,1,1,0,1,0,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,1,1,0,0,1,1,0,0,0,1,1,0,0,0,0]) alle.append([0,0,0,0,0,1,0,0,0,1,0,0,1,0,1,0,0,1,1,0,0,0,0,0,1,0,0,1,0,1,1,0,1,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,1,1,0,0,0,0,0,0,0,1,1,0,0,1,0,0,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,0,1,0,0,0,0,1,1,0,1,0,1,1,1,1,1,0,0,0,0,1,0,0,1,0,1,0,0,1,1,1,0,1,0,1,1,0,1,0,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,0,0,1,0,1,0,0]) alle.append([0,0,0,0,0,1,0,0,0,1,0,0,1,0,1,0,0,1,1,0,0,0,0,0,1,0,0,1,0,1,1,0,1,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,0,0,0,0,0,0,0,0,1,1,0,0,1,0,0,1,1,1,1,1,0,1,0,0,1,1,1,1,1,1,0,1,0,0,0,0,1,1,0,1,0,1,1,1,1,0,1,0,1,1,1,0,0,0,0,0,1,0,1,1,1,0,1,0,1,0,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0,1,1,1,1,1,0,0]) alle.append([0,0,0,0,1,1,0,0,0,0,1,1,1,1,0,1,1,1,0,1,1,1,1,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,1,1,0,1,0,0,1,0,0,1,1,1,0,1,0,0,1,0,0,1,0,0,0,1,0,0,0,0,1,1,0,1,0,1,1,1,1,0,1,1,1,0,0,0,0,0,0,0,0,1,1,0,1,1,1,1,1,1,1,0,0,1,0,1,1,0,0,1,1,0,1,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]) alle.append([0,0,0,0,0,1,0,0,0,0,1,1,1,0,1,0,0,1,1,1,0,0,1,1,0,0,1,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,1,1,1,1,0,0,0,0,0,0,0,1,1,0,0,0,1,1,1,1,0,0,0,1,0,1,0,1,0,1,0,1,0,0,1,0,0,0,0,1,1,0,1,0,1,0,1,1,0,1,1,0,1,1,0,1,0,0,1,0,1,0,0,1,0,1,1,1,0,1,0,0,0,1,1,1,0,1,0,1,1,1,1,0,1,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,1,1,1,1,0,0,0,1,0,1,1]) alle.append([0,0,0,0,0,1,0,0,0,0,1,1,1,1,0,1,0,1,1,1,1,1,0,0,1,0,1,1,0,1,1,1,0,1,1,1,0,0,0,1,0,1,1,0,0,0,0,0,0,1,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,1,1,0,1,0,0,1,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,1,0,0,0,0,1,1,0,1,0,1,1,0,0,1,1,1,1,0,0,0,1,1,0,1,1,1,0,1,0,0,0,0,0,1,0,0,1,0,1,1,0,1,1,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]) alle.append([0,0,0,0,0,1,0,0,0,1,0,0,1,0,1,0,0,1,1,0,0,0,0,0,1,0,0,1,0,1,1,0,1,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,1,1,1,1,0,0,0,0,0,0,0,1,1,0,0,1,0,0,0,1,0,1,0,1,1,1,1,0,0,0,1,0,1,0,1,0,0,0,0,1,1,0,1,0,1,1,0,0,0,0,0,0,0,1,1,0,1,1,1,0,1,0,0,1,0,0,0,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1,0,1,1,1,0]) alle.append([0,0,0,0,0,1,0,0,0,1,0,0,1,0,1,0,0,1,1,0,0,0,0,0,1,0,0,1,0,1,1,0,1,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,1,0,1,0,0,0,0,0,0,0,0,0,1,1,0,0,0,1,1,1,1,1,0,0,1,0,0,0,1,0,0,0,0,1,0,1,0,0,0,0,1,1,0,1,0,1,0,1,0,1,0,0,1,0,1,1,0,0,1,1,0,1,0,0,1,0,0,0,0,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,1,0,1,0,1,1,0]) alle.append([0,0,0,0,0,1,0,0,0,1,0,0,1,0,1,0,0,1,1,0,0,0,0,0,1,0,0,1,0,1,1,0,1,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,1,0,1,0,1,0,0,0,0,0,0,0,1,1,0,0,0,1,1,1,0,0,1,0,0,0,0,1,0,1,1,0,0,1,0,1,0,0,0,0,1,1,0,1,0,1,0,0,1,1,0,0,0,1,0,1,1,0,0,0,1,1,0,0,1,0,0,0,1,1,0,0,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,1,1,1,0,1,1,0,1,1,0,1]) src = ais.ais_source_f(alle[0], 500, True) dst = gr.vector_sink_f() slice = gr.binary_slicer_fb() diffdec = gr.diff_decoder_bb(2) invert = ais.invert10_bb() dst2 = gr.vector_sink_b() gaussian_taps = gr.firdes.gaussian(1,5,0.35,100) sqwave = (1,) * 5 taps = numpy.convolve(numpy.array(gaussian_taps),numpy.array(sqwave)) gaussian_filter = gr.interp_fir_filter_fff(5,taps) gange = gr.multiply_const_ff(0.3) lydut = audio.sink(9600*5,"default") filut = gr.file_sink(gr.sizeof_float,"filut.raw") #fg.connect(src,dst) #fg.connect(src,slice,diffdec,invert,dst2)
def __init__(self, options): gr.hier_block2.__init__( self, "ais_demod", gr.io_signature(1, 1, gr.sizeof_gr_complex), # Input signature gr.io_signature(1, 1, gr.sizeof_char), ) # Output signature self._samples_per_symbol = options.samples_per_symbol self._bits_per_sec = options.bits_per_sec self._samplerate = self._samples_per_symbol * self._bits_per_sec self._gain_mu = options.gain_mu self._mu = options.mu self._omega_relative_limit = options.omega_relative_limit self.fftlen = options.fftlen # right now we are going to hardcode the different options for VA mode here. later on we can use configurable options samples_per_symbol_viterbi = 2 bits_per_symbol = 2 samples_per_symbol = 6 samples_per_symbol_clockrec = samples_per_symbol / bits_per_symbol BT = 0.4 data_rate = 9600.0 samp_rate = options.samp_rate self.gmsk_sync = gmsk_sync.square_and_fft_sync(self._samplerate, self._bits_per_sec, self.fftlen) if options.viterbi is True: # calculate the required decimation and interpolation to achieve the desired samples per symbol denom = gcd(data_rate * samples_per_symbol, samp_rate) cr_interp = int(data_rate * samples_per_symbol / denom) cr_decim = int(samp_rate / denom) self.resample = blks2.rational_resampler_ccc(cr_interp, cr_decim) # here we take a different tack and use A.A.'s CPM decomposition technique self.clockrec = gr.clock_recovery_mm_cc( samples_per_symbol_clockrec, 0.005 * 0.005 * 0.25, 0.5, 0.005, 0.0005 ) # might have to futz with the max. deviation (fsm, constellation, MF, N, f0T) = make_gmsk( samples_per_symbol_viterbi, BT ) # calculate the decomposition required for demodulation self.costas = gr.costas_loop_cc( 0.015, 0.015 * 0.015 * 0.25, 100e-6, -100e-6, 4 ) # does fine freq/phase synchronization. should probably calc the coeffs instead of hardcode them. self.streams2stream = gr.streams_to_stream(int(gr.sizeof_gr_complex * 1), int(N)) self.mf0 = gr.fir_filter_ccc( samples_per_symbol_viterbi, MF[0].conjugate() ) # two matched filters for decomposition self.mf1 = gr.fir_filter_ccc(samples_per_symbol_viterbi, MF[1].conjugate()) self.fo = gr.sig_source_c( samples_per_symbol_viterbi, gr.GR_COS_WAVE, -f0T, 1, 0 ) # the memoryless modulation component of the decomposition self.fomult = gr.multiply_cc(1) self.trellis = trellis.viterbi_combined_cb( fsm, int(data_rate), -1, -1, int(N), constellation, trellis.TRELLIS_EUCLIDEAN ) # the actual Viterbi decoder else: # this is probably not optimal and someone who knows what they're doing should correct me self.datafiltertaps = gr.firdes.root_raised_cosine( 10, # gain self._samplerate * 32, # sample rate self._bits_per_sec, # symbol rate 0.4, # alpha, same as BT? 50 * 32, ) # no. of taps self.datafilter = gr.fir_filter_fff(1, self.datafiltertaps) sensitivity = (math.pi / 2) / self._samples_per_symbol self.demod = gr.quadrature_demod_cf(sensitivity) # param is gain # self.clockrec = digital.clock_recovery_mm_ff(self._samples_per_symbol,0.25*self._gain_mu*self._gain_mu,self._mu,self._gain_mu,self._omega_relative_limit) self.clockrec = gr.pfb_clock_sync_ccf(self._samples_per_symbol, 0.04, self.datafiltertaps, 32, 0, 1.15) self.tcslicer = digital.digital.binary_slicer_fb() # self.dfe = digital.digital.lms_dd_equalizer_cc( # 32, # 0.005, # 1, # digital.digital.constellation_bpsk() # ) # self.delay = gr.delay(gr.sizeof_float, 64 + 16) #the correlator delays 64 bits, and the LMS delays some as well. self.slicer = digital.digital.binary_slicer_fb() # self.training_correlator = digital.correlate_access_code_bb("1100110011001100", 0) # self.cma = digital.cma_equalizer_cc # just a note here: a complex combined quad demod/slicer could be based on if's rather than an actual quad demod, right? # in fact all the constellation decoders up to QPSK could operate on complex data w/o doing the whole atan thing self.diff = gr.diff_decoder_bb(2) self.invert = ais.invert() # NRZI signal diff decoded and inverted should give original signal self.connect(self, self.gmsk_sync) if options.viterbi is False: self.connect(self.gmsk_sync, self.clockrec, self.demod, self.slicer, self.diff, self.invert, self) # self.connect(self.gmsk_sync, self.demod, self.clockrec, self.tcslicer, self.training_correlator) # self.connect(self.clockrec, self.delay, (self.dfe, 0)) # self.connect(self.training_correlator, (self.dfe, 1)) # self.connect(self.dfe, self.slicer, self.diff, self.invert, self) else: self.connect(self.gmsk_sync, self.costas, self.resample, self.clockrec) self.connect(self.clockrec, (self.fomult, 0)) self.connect(self.fo, (self.fomult, 1)) self.connect(self.fomult, self.mf0) self.connect(self.fomult, self.mf1) self.connect(self.mf0, (self.streams2stream, 0)) self.connect(self.mf1, (self.streams2stream, 1)) self.connect(self.streams2stream, self.trellis, self.diff, self.invert, self)
src = audio.source(samplerate, "hw:1") pluss = gr.add_const_ff(0.0) lpcoeffs = gr.firdes.low_pass(1, samplerate, 8000, 3000) lpfilter = gr.fir_filter_fff(1, lpcoeffs) forsterk = gr.multiply_const_ff(5) clockrec = gr.clock_recovery_mm_ff( float(samplerate) / 9600, 0.25 * 0.175 * 0.175, 0.5, 0.175, 0.005) slicer = gr.binary_slicer_fb() # Parameters: ([mysql-server],[database name],[database user],[database password]) datadec = ais.ais_decoder_mysql("localhost", "diverse", "ruben", "elg") # You should use the create_mysql.sql to create the necessary tables # in the database. # See create_mysql.txt for help. Those files can be found in the root folder of # the source tree. diff = gr.diff_decoder_bb(2) invert = ais.invert10_bb() fg.connect(src, pluss, lpfilter, forsterk, clockrec, slicer, diff, invert, datadec) fg.start() raw_input("Receives AIS from soundcard ") fg.stop() print "Received correctly: ", datadec.received() print "Wrong CRC: ", datadec.lost() print "Wrong Size: ", datadec.lost2()
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("-f", "--freq", type="eng_float", default=91.2e6, help="set frequency to FREQ", metavar="FREQ") parser.add_option("-g", "--gain", type="eng_float", default=None, help="set gain in dB") parser.add_option("-s", "--squelch", type="eng_float", default=0, help="set squelch level (default is 0)") parser.add_option("-V", "--volume", type="eng_float", default=None, help="set volume (default is midpoint)") parser.add_option("-O", "--audio-output", type="string", default="plughw:0,0", help="pcm device name (default is plughw:0,0)") (options, args) = parser.parse_args() if len(args) != 0: parser.print_help() sys.exit(1) # connect to USRP usrp_decim = 250 self.u = usrp.source_c(0, usrp_decim) print "USRP Serial: ", self.u.serial_number() demod_rate = self.u.adc_rate() / usrp_decim # 256 kS/s audio_decim = 8 audio_rate = demod_rate / audio_decim # 32 kS/s if options.rx_subdev_spec is None: options.rx_subdev_spec = usrp.pick_subdev(self.u, dblist) 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 d'board", self.subdev.side_and_name() # gain, volume, frequency self.gain = options.gain if options.gain is None: self.gain = self.subdev.gain_range()[1] self.vol = options.volume if self.vol is None: g = self.volume_range() self.vol = float(g[0]+g[1])/2 self.freq = options.freq if abs(self.freq) < 1e6: self.freq *= 1e6 print "Volume:%r, Gain:%r, Freq:%3.1f MHz" % (self.vol, self.gain, self.freq/1e6) # channel filter, wfm_rcv_pll chan_filt_coeffs = optfir.low_pass( 1, # gain demod_rate, # rate 80e3, # passband cutoff 115e3, # stopband cutoff 0.1, # passband ripple 60) # stopband attenuation self.chan_filt = gr.fir_filter_ccf (1, chan_filt_coeffs) self.guts = blks2.wfm_rcv_pll (demod_rate, audio_decim) self.connect(self.u, self.chan_filt, self.guts) # volume control, audio sink self.volume_control_l = gr.multiply_const_ff(self.vol) self.volume_control_r = gr.multiply_const_ff(self.vol) self.audio_sink = audio.sink(int(audio_rate), options.audio_output, False) self.connect ((self.guts, 0), self.volume_control_l, (self.audio_sink, 0)) self.connect ((self.guts, 1), self.volume_control_r, (self.audio_sink, 1)) # pilot channel filter (band-pass, 18.5-19.5kHz) pilot_filter_coeffs = gr.firdes.band_pass( 1, # gain demod_rate, # sampling rate 18.5e3, # low cutoff 19.5e3, # high cutoff 1e3, # transition width gr.firdes.WIN_HAMMING) self.pilot_filter = gr.fir_filter_fff(1, pilot_filter_coeffs) self.connect(self.guts.fm_demod, self.pilot_filter) # RDS channel filter (band-pass, 54-60kHz) rds_filter_coeffs = gr.firdes.band_pass( 1, # gain demod_rate, # sampling rate 54e3, # low cutoff 60e3, # high cutoff 3e3, # transition width gr.firdes.WIN_HAMMING) self.rds_filter = gr.fir_filter_fff(1, rds_filter_coeffs) self.connect(self.guts.fm_demod, self.rds_filter) # create 57kHz subcarrier from 19kHz pilot, downconvert RDS channel self.mixer = gr.multiply_ff() self.connect(self.pilot_filter, (self.mixer, 0)) self.connect(self.pilot_filter, (self.mixer, 1)) self.connect(self.pilot_filter, (self.mixer, 2)) self.connect(self.rds_filter, (self.mixer, 3)) # low-pass the baseband RDS signal at 1.5kHz rds_bb_filter_coeffs = gr.firdes.low_pass( 1, # gain demod_rate, # sampling rate 1.5e3, # passband cutoff 2e3, # transition width gr.firdes.WIN_HAMMING) self.rds_bb_filter = gr.fir_filter_fff(1, rds_bb_filter_coeffs) self.connect(self.mixer, self.rds_bb_filter) # 1187.5bps = 19kHz/16 self.rds_clock = rds.freq_divider(16) clock_taps = gr.firdes.low_pass( 1, # gain demod_rate, # sampling rate 1.2e3, # passband cutoff 1.5e3, # transition width gr.firdes.WIN_HANN) self.clock_filter = gr.fir_filter_fff(1, clock_taps) self.connect(self.pilot_filter, self.rds_clock, self.clock_filter) # bpsk_demod, diff_decoder, rds_decoder self.bpsk_demod = rds.bpsk_demod(demod_rate) self.differential_decoder = gr.diff_decoder_bb(2) self.msgq = gr.msg_queue() self.rds_decoder = rds.data_decoder(self.msgq) self.connect(self.rds_bb_filter, (self.bpsk_demod, 0)) self.connect(self.clock_filter, (self.bpsk_demod, 1)) self.connect(self.bpsk_demod, self.differential_decoder) self.connect(self.differential_decoder, self.rds_decoder) # set initial values self.subdev.set_gain(self.gain) self.set_vol(self.vol) self.set_freq(self.freq)
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("-f", "--freq", type="eng_float", default=91.2e6, help="set frequency to FREQ", metavar="FREQ") parser.add_option("-g", "--gain", type="eng_float", default=None, help="set gain in dB") parser.add_option("-s", "--squelch", type="eng_float", default=0, help="set squelch level (default is 0)") parser.add_option("-V", "--volume", type="eng_float", default=None, help="set volume (default is midpoint)") parser.add_option("-O", "--audio-output", type="string", default="plughw:0,0", help="pcm device name (default is plughw:0,0)") (options, args) = parser.parse_args() if len(args) != 0: parser.print_help() sys.exit(1) # connect to USRP usrp_decim = 250 self.u = usrp.source_c(0, usrp_decim) print "USRP Serial: ", self.u.serial_number() demod_rate = self.u.adc_rate() / usrp_decim # 256 kS/s audio_decim = 8 audio_rate = demod_rate / audio_decim # 32 kS/s if options.rx_subdev_spec is None: options.rx_subdev_spec = usrp.pick_subdev(self.u, dblist) 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 d'board", self.subdev.side_and_name() # gain, volume, frequency self.gain = options.gain if options.gain is None: self.gain = self.subdev.gain_range()[1] self.vol = options.volume if self.vol is None: g = self.volume_range() self.vol = float(g[0] + g[1]) / 2 self.freq = options.freq if abs(self.freq) < 1e6: self.freq *= 1e6 print "Volume:%r, Gain:%r, Freq:%3.1f MHz" % (self.vol, self.gain, self.freq / 1e6) # channel filter, wfm_rcv_pll chan_filt_coeffs = optfir.low_pass( 1, # gain demod_rate, # rate 80e3, # passband cutoff 115e3, # stopband cutoff 0.1, # passband ripple 60) # stopband attenuation self.chan_filt = gr.fir_filter_ccf(1, chan_filt_coeffs) self.guts = blks2.wfm_rcv_pll(demod_rate, audio_decim) self.connect(self.u, self.chan_filt, self.guts) # volume control, audio sink self.volume_control_l = gr.multiply_const_ff(self.vol) self.volume_control_r = gr.multiply_const_ff(self.vol) self.audio_sink = audio.sink(int(audio_rate), options.audio_output, False) self.connect((self.guts, 0), self.volume_control_l, (self.audio_sink, 0)) self.connect((self.guts, 1), self.volume_control_r, (self.audio_sink, 1)) # pilot channel filter (band-pass, 18.5-19.5kHz) pilot_filter_coeffs = gr.firdes.band_pass( 1, # gain demod_rate, # sampling rate 18.5e3, # low cutoff 19.5e3, # high cutoff 1e3, # transition width gr.firdes.WIN_HAMMING) self.pilot_filter = gr.fir_filter_fff(1, pilot_filter_coeffs) self.connect(self.guts.fm_demod, self.pilot_filter) # RDS channel filter (band-pass, 54-60kHz) rds_filter_coeffs = gr.firdes.band_pass( 1, # gain demod_rate, # sampling rate 54e3, # low cutoff 60e3, # high cutoff 3e3, # transition width gr.firdes.WIN_HAMMING) self.rds_filter = gr.fir_filter_fff(1, rds_filter_coeffs) self.connect(self.guts.fm_demod, self.rds_filter) # create 57kHz subcarrier from 19kHz pilot, downconvert RDS channel self.mixer = gr.multiply_ff() self.connect(self.pilot_filter, (self.mixer, 0)) self.connect(self.pilot_filter, (self.mixer, 1)) self.connect(self.pilot_filter, (self.mixer, 2)) self.connect(self.rds_filter, (self.mixer, 3)) # low-pass the baseband RDS signal at 1.5kHz rds_bb_filter_coeffs = gr.firdes.low_pass( 1, # gain demod_rate, # sampling rate 1.5e3, # passband cutoff 2e3, # transition width gr.firdes.WIN_HAMMING) self.rds_bb_filter = gr.fir_filter_fff(1, rds_bb_filter_coeffs) self.connect(self.mixer, self.rds_bb_filter) # 1187.5bps = 19kHz/16 self.rds_clock = rds.freq_divider(16) clock_taps = gr.firdes.low_pass( 1, # gain demod_rate, # sampling rate 1.2e3, # passband cutoff 1.5e3, # transition width gr.firdes.WIN_HANN) self.clock_filter = gr.fir_filter_fff(1, clock_taps) self.connect(self.pilot_filter, self.rds_clock, self.clock_filter) # bpsk_demod, diff_decoder, rds_decoder self.bpsk_demod = rds.bpsk_demod(demod_rate) self.differential_decoder = gr.diff_decoder_bb(2) self.msgq = gr.msg_queue() self.rds_decoder = rds.data_decoder(self.msgq) self.connect(self.rds_bb_filter, (self.bpsk_demod, 0)) self.connect(self.clock_filter, (self.bpsk_demod, 1)) self.connect(self.bpsk_demod, self.differential_decoder) self.connect(self.differential_decoder, self.rds_decoder) # set initial values self.subdev.set_gain(self.gain) self.set_vol(self.vol) self.set_freq(self.freq)
def __init__(self,frame,panel,vbox,argv): stdgui2.std_top_block.__init__ (self,frame,panel,vbox,argv) 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("-f", "--freq", type="eng_float", default=91.2e6, help="set frequency to FREQ", metavar="FREQ") parser.add_option("-g", "--gain", type="eng_float", default=None, help="set gain in dB") # FIXME add squelch parser.add_option("-s", "--squelch", type="eng_float", default=0, help="set squelch level (default is 0)") parser.add_option("-V", "--volume", type="eng_float", default=None, help="set volume (default is midpoint)") parser.add_option("-O", "--audio-output", type="string", default="plughw:0,0", help="pcm device name (default is plughw:0,0)") # print help when called with wrong arguments (options, args) = parser.parse_args() if len(args) != 0: parser.print_help() sys.exit(1) # connect to USRP usrp_decim = 250 self.u = usrp.source_c(0, usrp_decim) print "USRP Serial:", self.u.serial_number() usrp_rate = self.u.adc_rate() / usrp_decim # 256 kS/s print "usrp_rate =", usrp_rate audio_decim = 8 audio_rate = usrp_rate / audio_decim # 32 kS/s print "audio_rate =", audio_rate #if options.rx_subdev_spec is None: # options.rx_subdev_spec = usrp.pick_subdev(self.u, dblist) 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 d'board", self.subdev.side_and_name() # gain, volume, frequency self.gain = options.gain if options.gain is None: g = self.subdev.gain_range() self.gain = float(g[0]+g[1])/2 self.vol = options.volume if self.vol is None: g = self.volume_range() self.vol = float(g[0]+g[1])/2 self.freq = options.freq print "Volume:%r, Gain:%r, Freq:%3.1f MHz" % (self.vol, self.gain, self.freq/1e6) # channel filter chan_filter_coeffs = gr.firdes.low_pass( 1.0, # gain usrp_rate, # sampling rate 80e3, # passband cutoff 35e3, # transition width gr.firdes.WIN_HAMMING) self.chan_filter = gr.fir_filter_ccf(1, chan_filter_coeffs) print "# channel filter:", len(chan_filter_coeffs), "taps" # PLL-based WFM demod fm_alpha = 0.25 * 250e3 * math.pi / usrp_rate # 0.767 fm_beta = fm_alpha * fm_alpha / 4.0 # 0.147 fm_max_freq = 2.0 * math.pi * 90e3 / usrp_rate # 2.209 self.fm_demod = gr.pll_freqdet_cf( #fm_alpha, # phase gain #fm_beta, # freq gain 1.0, # Loop BW fm_max_freq, # in radians/sample -fm_max_freq) self.fm_demod.set_alpha(fm_alpha) self.fm_demod.set_beta(fm_beta) self.connect(self.u, self.chan_filter, self.fm_demod) # L+R, pilot, L-R, RDS filters lpr_filter_coeffs = gr.firdes.low_pass( 1.0, # gain usrp_rate, # sampling rate 15e3, # passband cutoff 1e3, # transition width gr.firdes.WIN_HAMMING) self.lpr_filter = gr.fir_filter_fff(audio_decim, lpr_filter_coeffs) pilot_filter_coeffs = gr.firdes.band_pass( 1.0, # gain usrp_rate, # sampling rate 19e3-500, # low cutoff 19e3+500, # high cutoff 1e3, # transition width gr.firdes.WIN_HAMMING) self.pilot_filter = gr.fir_filter_fff(1, pilot_filter_coeffs) dsbsc_filter_coeffs = gr.firdes.band_pass( 1.0, # gain usrp_rate, # sampling rate 38e3-15e3/2, # low cutoff 38e3+15e3/2, # high cutoff 1e3, # transition width gr.firdes.WIN_HAMMING) self.dsbsc_filter = gr.fir_filter_fff(1, dsbsc_filter_coeffs) rds_filter_coeffs = gr.firdes.band_pass( 1.0, # gain usrp_rate, # sampling rate 57e3-3e3, # low cutoff 57e3+3e3, # high cutoff 3e3, # transition width gr.firdes.WIN_HAMMING) self.rds_filter = gr.fir_filter_fff(1, rds_filter_coeffs) print "# lpr filter:", len(lpr_filter_coeffs), "taps" print "# pilot filter:", len(pilot_filter_coeffs), "taps" print "# dsbsc filter:", len(dsbsc_filter_coeffs), "taps" print "# rds filter:", len(rds_filter_coeffs), "taps" self.connect(self.fm_demod, self.lpr_filter) self.connect(self.fm_demod, self.pilot_filter) self.connect(self.fm_demod, self.dsbsc_filter) self.connect(self.fm_demod, self.rds_filter) # down-convert L-R, RDS self.stereo_baseband = gr.multiply_ff() self.connect(self.pilot_filter, (self.stereo_baseband, 0)) self.connect(self.pilot_filter, (self.stereo_baseband, 1)) self.connect(self.dsbsc_filter, (self.stereo_baseband, 2)) self.rds_baseband = gr.multiply_ff() self.connect(self.pilot_filter, (self.rds_baseband, 0)) self.connect(self.pilot_filter, (self.rds_baseband, 1)) self.connect(self.pilot_filter, (self.rds_baseband, 2)) self.connect(self.rds_filter, (self.rds_baseband, 3)) # low-pass and downsample L-R lmr_filter_coeffs = gr.firdes.low_pass( 1.0, # gain usrp_rate, # sampling rate 15e3, # passband cutoff 1e3, # transition width gr.firdes.WIN_HAMMING) self.lmr_filter = gr.fir_filter_fff(audio_decim, lmr_filter_coeffs) self.connect(self.stereo_baseband, self.lmr_filter) # create L, R from L-R, L+R self.left = gr.add_ff() self.right = gr.sub_ff() self.connect(self.lpr_filter, (self.left, 0)) self.connect(self.lmr_filter, (self.left, 1)) self.connect(self.lpr_filter, (self.right, 0)) self.connect(self.lmr_filter, (self.right, 1)) # volume control, complex2flot, audio sink self.volume_control_l = gr.multiply_const_ff(self.vol) self.volume_control_r = gr.multiply_const_ff(self.vol) output_audio_rate = 48000 self.audio_sink = audio.sink(int(output_audio_rate), options.audio_output, False) #self.connect(self.left, self.volume_control_l, (self.audio_sink, 0)) #self.connect(self.right, self.volume_control_r, (self.audio_sink, 1)) self.resamp_L = blks2.rational_resampler_fff(interpolation=output_audio_rate,decimation=audio_rate,taps=None,fractional_bw=None,) self.resamp_R = blks2.rational_resampler_fff(interpolation=output_audio_rate,decimation=audio_rate,taps=None,fractional_bw=None,) self.connect(self.left, self.volume_control_l, self.resamp_L, (self.audio_sink, 0)) self.connect(self.right, self.volume_control_r, self.resamp_R, (self.audio_sink, 1)) # low-pass the baseband RDS signal at 1.5kHz rds_bb_filter_coeffs = gr.firdes.low_pass( 1, # gain usrp_rate, # sampling rate 1.5e3, # passband cutoff 2e3, # transition width gr.firdes.WIN_HAMMING) self.rds_bb_filter = gr.fir_filter_fff(audio_decim, rds_bb_filter_coeffs) print "# rds bb filter:", len(rds_bb_filter_coeffs), "taps" self.connect(self.rds_baseband, self.rds_bb_filter) # 1187.5bps = 19kHz/16 self.clock_divider = rds.freq_divider(16) rds_clock_taps = gr.firdes.low_pass( 1, # gain usrp_rate, # sampling rate 1.2e3, # passband cutoff 1.5e3, # transition width gr.firdes.WIN_HAMMING) self.rds_clock = gr.fir_filter_fff(audio_decim, rds_clock_taps) print "# rds clock filter:", len(rds_clock_taps), "taps" self.connect(self.pilot_filter, self.clock_divider, self.rds_clock) # bpsk_demod, diff_decoder, rds_decoder self.bpsk_demod = rds.bpsk_demod(audio_rate) self.differential_decoder = gr.diff_decoder_bb(2) self.msgq = gr.msg_queue() self.rds_decoder = rds.data_decoder(self.msgq) self.connect(self.rds_bb_filter, (self.bpsk_demod, 0)) self.connect(self.rds_clock, (self.bpsk_demod, 1)) self.connect(self.bpsk_demod, self.differential_decoder) self.connect(self.differential_decoder, self.rds_decoder) self.frame = frame self.panel = panel self._build_gui(vbox, usrp_rate, audio_rate) self.set_gain(self.gain) self.set_vol(self.vol) if not(self.set_freq(self.freq)): self._set_status_msg("Failed to set initial frequency")
def __init__(self, constellation, samples_per_symbol=_def_samples_per_symbol, differential=_def_differential, excess_bw=_def_excess_bw, gray_coded=True, freq_bw=_def_freq_bw, timing_bw=_def_timing_bw, phase_bw=_def_phase_bw, verbose=_def_verbose, log=_def_log): """ Hierarchical block for RRC-filtered differential generic demodulation. The input is the complex modulated signal at baseband. The output is a stream of bits packed 1 bit per byte (LSB) @param constellation: determines the modulation type @type constellation: gnuradio.digital.gr_constellation @param samples_per_symbol: samples per symbol >= 2 @type samples_per_symbol: float @param excess_bw: Root-raised cosine filter excess bandwidth @type excess_bw: float @param gray_coded: turn gray coding on/off @type gray_coded: bool @param freq_bw: loop filter lock-in bandwidth @type freq_bw: float @param timing_bw: timing recovery loop lock-in bandwidth @type timing_bw: float @param phase_bw: phase recovery loop bandwidth @type phase_bw: float @param verbose: Print information about modulator? @type verbose: bool @param debug: Print modualtion data to files? @type debug: bool """ gr.hier_block2.__init__( self, "generic_demod", gr.io_signature(1, 1, gr.sizeof_gr_complex), # Input signature gr.io_signature(1, 1, gr.sizeof_char)) # Output signature self._constellation = constellation.base() self._samples_per_symbol = samples_per_symbol self._excess_bw = excess_bw self._phase_bw = phase_bw self._freq_bw = freq_bw self._timing_bw = timing_bw self._timing_max_dev = _def_timing_max_dev self._differential = differential if self._samples_per_symbol < 2: raise TypeError, ("sbp must be >= 2, is %d" % self._samples_per_symbol) arity = pow(2, self.bits_per_symbol()) nfilts = 32 ntaps = 11 * int(self._samples_per_symbol * nfilts) # Automatic gain control self.agc = gr.agc2_cc(0.6e-1, 1e-3, 1, 1, 100) # Frequency correction fll_ntaps = 55 self.freq_recov = digital_swig.fll_band_edge_cc( self._samples_per_symbol, self._excess_bw, fll_ntaps, self._freq_bw) # symbol timing recovery with RRC data filter taps = gr.firdes.root_raised_cosine(nfilts, nfilts * self._samples_per_symbol, 1.0, self._excess_bw, ntaps) self.time_recov = gr.pfb_clock_sync_ccf(self._samples_per_symbol, self._timing_bw, taps, nfilts, nfilts // 2, self._timing_max_dev) fmin = -0.25 fmax = 0.25 self.receiver = digital_swig.constellation_receiver_cb( self._constellation, self._phase_bw, fmin, fmax) # Do differential decoding based on phase change of symbols if differential: self.diffdec = gr.diff_decoder_bb(arity) if gray_coded: self.symbol_mapper = gr.map_bb( mod_codes.invert_code(self._constellation.pre_diff_code())) # unpack the k bit vector into a stream of bits self.unpack = gr.unpack_k_bits_bb(self.bits_per_symbol()) if verbose: self._print_verbage() if log: self._setup_logging() # Connect and Initialize base class blocks = [ self, self.agc, self.freq_recov, self.time_recov, self.receiver ] if differential: blocks.append(self.diffdec) if self._constellation.apply_pre_diff_code(): blocks.append(self.symbol_mapper) blocks += [self.unpack, self] self.connect(*blocks)
def __init__(self,frame,panel,vbox,argv): stdgui2.std_top_block.__init__ (self,frame,panel,vbox,argv) parser=OptionParser(option_class=eng_option) parser.add_option("-V", "--volume", type="eng_float", default=None, help="set volume (default is midpoint)") parser.add_option("-O", "--audio-output", type="string", default="plughw:0,0", help="pcm device name (default is plughw:0,0)") # print help when called with wrong arguments (options, args) = parser.parse_args() if len(args) != 0: parser.print_help() sys.exit(1) self.file_source = gr.file_source(gr.sizeof_gr_complex*1, offline_samples, True) chan_filter_coeffs = gr.firdes.low_pass( 1.0, # gain usrp_rate, # sampling rate 80e3, # passband cutoff 35e3, # transition width gr.firdes.WIN_HAMMING) self.chan_filter = gr.fir_filter_ccf(1, chan_filter_coeffs) print "# channel filter:", len(chan_filter_coeffs), "taps" # PLL-based WFM demod fm_alpha = 0.25 * 250e3 * math.pi / usrp_rate # 0.767 fm_beta = fm_alpha * fm_alpha / 4.0 # 0.147 fm_max_freq = 2.0 * math.pi * 90e3 / usrp_rate # 2.209 self.fm_demod = gr.pll_freqdet_cf( fm_alpha, # phase gain fm_beta, # freq gain fm_max_freq, # in radians/sample -fm_max_freq) self.connect(self.file_source, self.chan_filter, self.fm_demod) # L+R, pilot, L-R, RDS filters lpr_filter_coeffs = gr.firdes.low_pass( 1.0, # gain usrp_rate, # sampling rate 15e3, # passband cutoff 1e3, # transition width gr.firdes.WIN_HAMMING) self.lpr_filter = gr.fir_filter_fff(audio_decim, lpr_filter_coeffs) pilot_filter_coeffs = gr.firdes.band_pass( 1.0, # gain usrp_rate, # sampling rate 19e3-500, # low cutoff 19e3+500, # high cutoff 1e3, # transition width gr.firdes.WIN_HAMMING) self.pilot_filter = gr.fir_filter_fff(1, pilot_filter_coeffs) dsbsc_filter_coeffs = gr.firdes.band_pass( 1.0, # gain usrp_rate, # sampling rate 38e3-15e3/2, # low cutoff 38e3+15e3/2, # high cutoff 1e3, # transition width gr.firdes.WIN_HAMMING) self.dsbsc_filter = gr.fir_filter_fff(1, dsbsc_filter_coeffs) rds_filter_coeffs = gr.firdes.band_pass( 1.0, # gain usrp_rate, # sampling rate 57e3-3e3, # low cutoff 57e3+3e3, # high cutoff 3e3, # transition width gr.firdes.WIN_HAMMING) self.rds_filter = gr.fir_filter_fff(1, rds_filter_coeffs) print "# lpr filter:", len(lpr_filter_coeffs), "taps" print "# pilot filter:", len(pilot_filter_coeffs), "taps" print "# dsbsc filter:", len(dsbsc_filter_coeffs), "taps" print "# rds filter:", len(rds_filter_coeffs), "taps" self.connect(self.fm_demod, self.lpr_filter) self.connect(self.fm_demod, self.pilot_filter) self.connect(self.fm_demod, self.dsbsc_filter) self.connect(self.fm_demod, self.rds_filter) # down-convert L-R, RDS self.stereo_baseband = gr.multiply_ff() self.connect(self.pilot_filter, (self.stereo_baseband, 0)) self.connect(self.pilot_filter, (self.stereo_baseband, 1)) self.connect(self.dsbsc_filter, (self.stereo_baseband, 2)) self.rds_baseband = gr.multiply_ff() self.connect(self.pilot_filter, (self.rds_baseband, 0)) self.connect(self.pilot_filter, (self.rds_baseband, 1)) self.connect(self.pilot_filter, (self.rds_baseband, 2)) self.connect(self.rds_filter, (self.rds_baseband, 3)) # low-pass and downsample L-R lmr_filter_coeffs = gr.firdes.low_pass( 1.0, # gain usrp_rate, # sampling rate 15e3, # passband cutoff 1e3, # transition width gr.firdes.WIN_HAMMING) self.lmr_filter = gr.fir_filter_fff(audio_decim, lmr_filter_coeffs) self.connect(self.stereo_baseband, self.lmr_filter) # create L, R from L-R, L+R self.left = gr.add_ff() self.right = gr.sub_ff() self.connect(self.lpr_filter, (self.left, 0)) self.connect(self.lmr_filter, (self.left, 1)) self.connect(self.lpr_filter, (self.right, 0)) self.connect(self.lmr_filter, (self.right, 1)) # send audio to null sink self.null0 = gr.null_sink(gr.sizeof_float) self.null1 = gr.null_sink(gr.sizeof_float) self.connect(self.left, self.null0) self.connect(self.right, self.null1) # low-pass the baseband RDS signal at 1.5kHz rds_bb_filter_coeffs = gr.firdes.low_pass( 1, # gain usrp_rate, # sampling rate 1.5e3, # passband cutoff 2e3, # transition width gr.firdes.WIN_HAMMING) self.rds_bb_filter = gr.fir_filter_fff(audio_decim, rds_bb_filter_coeffs) print "# rds bb filter:", len(rds_bb_filter_coeffs), "taps" self.connect(self.rds_baseband, self.rds_bb_filter) # 1187.5bps = 19kHz/16 self.clock_divider = rds.freq_divider(16) rds_clock_taps = gr.firdes.low_pass( 1, # gain usrp_rate, # sampling rate 1.2e3, # passband cutoff 1.5e3, # transition width gr.firdes.WIN_HAMMING) self.rds_clock = gr.fir_filter_fff(audio_decim, rds_clock_taps) print "# rds clock filter:", len(rds_clock_taps), "taps" self.connect(self.pilot_filter, self.clock_divider, self.rds_clock) # bpsk_demod, diff_decoder, rds_decoder self.bpsk_demod = rds.bpsk_demod(audio_rate) self.differential_decoder = gr.diff_decoder_bb(2) self.msgq = gr.msg_queue() self.rds_decoder = rds.data_decoder(self.msgq) self.connect(self.rds_bb_filter, (self.bpsk_demod, 0)) self.connect(self.rds_clock, (self.bpsk_demod, 1)) self.connect(self.bpsk_demod, self.differential_decoder) self.connect(self.differential_decoder, self.rds_decoder) self.frame = frame self.panel = panel self._build_gui(vbox, usrp_rate, audio_rate)
def __init__(self): gr.top_block.__init__ (self) parser=OptionParser(option_class=eng_option) parser.add_option("-H", "--hostname", type="string", default="localhost", help="set hostname of generic sdr") parser.add_option("-P", "--portnum", type="int", default=None, help="set portnum of generic sdr") parser.add_option("-r", "--sdr_rate", type="eng_float", default=250e3, help="set sample rate of generic sdr") parser.add_option("-V", "--volume", type="eng_float", default=None, help="set volume (default is midpoint)") parser.add_option("-O", "--audio-output", type="string", default="plughw:0,0", help="pcm device name (default is plughw:0,0)") # print help when called with wrong arguments (options, args) = parser.parse_args() if len(args) != 0: parser.print_help() sys.exit(1) self.vol = options.volume if self.vol is None: self.vol = 0.1 # connect to generic SDR sdr_rate = options.sdr_rate audio_decim = 8 audio_rate = int(sdr_rate/audio_decim) print "audio_rate = ", audio_rate self.interleaved_short_to_complex = gr.interleaved_short_to_complex() self.char_to_short = gr.char_to_short(1) self.sdr_source = grc_blks2.tcp_source( itemsize=gr.sizeof_char*1, addr=options.hostname, port=options.portnum, server=False ) # self.sdr_source = gr.file_source(1, 'sdrs_baseband.dat') # self.throttle = gr.throttle(1, 500e3) # self.connect(self.sdr_source, self.file_sink) self.logger = gr.file_sink(1, 'log.out') self.connect(self.sdr_source, self.logger) # channel filter chan_filter_coeffs = gr.firdes.low_pass( 1.0, # gain sdr_rate, # sampling rate 80e3, # passband cutoff 35e3, # transition width gr.firdes.WIN_HAMMING) self.chan_filter = gr.fir_filter_ccf(1, chan_filter_coeffs) # print "# channel filter:", len(chan_filter_coeffs), "taps" # PLL-based WFM demod fm_alpha = 0.25 * 250e3 * math.pi / sdr_rate # 0.767 fm_beta = fm_alpha * fm_alpha / 4.0 # 0.147 fm_max_freq = 2.0 * math.pi * 90e3 / sdr_rate # 2.209 self.fm_demod = gr.pll_freqdet_cf( 1.0, # Loop BW fm_max_freq, # in radians/sample -fm_max_freq) self.fm_demod.set_alpha(fm_alpha) self.fm_demod.set_beta(fm_beta) self.connect(self.sdr_source, self.char_to_short) self.connect(self.char_to_short, self.interleaved_short_to_complex) self.connect(self.interleaved_short_to_complex, self.chan_filter, self.fm_demod) # L+R, pilot, L-R, RDS filters lpr_filter_coeffs = gr.firdes.low_pass( 1.0, # gain sdr_rate, # sampling rate 15e3, # passband cutoff 1e3, # transition width gr.firdes.WIN_HAMMING) self.lpr_filter = gr.fir_filter_fff(audio_decim, lpr_filter_coeffs) pilot_filter_coeffs = gr.firdes.band_pass( 1.0, # gain sdr_rate, # sampling rate 19e3-500, # low cutoff 19e3+500, # high cutoff 1e3, # transition width gr.firdes.WIN_HAMMING) self.pilot_filter = gr.fir_filter_fff(1, pilot_filter_coeffs) dsbsc_filter_coeffs = gr.firdes.band_pass( 1.0, # gain sdr_rate, # sampling rate 38e3-15e3/2, # low cutoff 38e3+15e3/2, # high cutoff 1e3, # transition width gr.firdes.WIN_HAMMING) self.dsbsc_filter = gr.fir_filter_fff(1, dsbsc_filter_coeffs) rds_filter_coeffs = gr.firdes.band_pass( 1.0, # gain sdr_rate, # sampling rate 57e3-3e3, # low cutoff 57e3+3e3, # high cutoff 3e3, # transition width gr.firdes.WIN_HAMMING) self.rds_filter = gr.fir_filter_fff(1, rds_filter_coeffs) # print "# lpr filter:", len(lpr_filter_coeffs), "taps" # print "# pilot filter:", len(pilot_filter_coeffs), "taps" # print "# dsbsc filter:", len(dsbsc_filter_coeffs), "taps" # print "# rds filter:", len(rds_filter_coeffs), "taps" self.connect(self.fm_demod, self.lpr_filter) self.connect(self.fm_demod, self.pilot_filter) self.connect(self.fm_demod, self.dsbsc_filter) self.connect(self.fm_demod, self.rds_filter) # down-convert L-R, RDS self.stereo_baseband = gr.multiply_ff() self.connect(self.pilot_filter, (self.stereo_baseband, 0)) self.connect(self.pilot_filter, (self.stereo_baseband, 1)) self.connect(self.dsbsc_filter, (self.stereo_baseband, 2)) self.rds_baseband = gr.multiply_ff() self.connect(self.pilot_filter, (self.rds_baseband, 0)) self.connect(self.pilot_filter, (self.rds_baseband, 1)) self.connect(self.pilot_filter, (self.rds_baseband, 2)) self.connect(self.rds_filter, (self.rds_baseband, 3)) # low-pass and downsample L-R lmr_filter_coeffs = gr.firdes.low_pass( 1.0, # gain sdr_rate, # sampling rate 15e3, # passband cutoff 1e3, # transition width gr.firdes.WIN_HAMMING) self.lmr_filter = gr.fir_filter_fff(audio_decim, lmr_filter_coeffs) self.connect(self.stereo_baseband, self.lmr_filter) # create L, R from L-R, L+R self.left = gr.add_ff() self.right = gr.sub_ff() self.connect(self.lpr_filter, (self.left, 0)) self.connect(self.lmr_filter, (self.left, 1)) self.connect(self.lpr_filter, (self.right, 0)) self.connect(self.lmr_filter, (self.right, 1)) # volume control, complex2flot, audio sink self.volume_control_l = gr.multiply_const_ff(self.vol) self.volume_control_r = gr.multiply_const_ff(self.vol) output_audio_rate = 48000 self.resamp_L = blks2.rational_resampler_fff(interpolation=output_audio_rate,decimation=audio_rate,taps=None,fractional_bw=None,) self.resamp_R = blks2.rational_resampler_fff(interpolation=output_audio_rate,decimation=audio_rate,taps=None,fractional_bw=None,) self.connect(self.left, self.volume_control_l, self.resamp_L) self.connect(self.right, self.volume_control_r, self.resamp_R) # self.audio_sink = audio.sink(int(output_audio_rate), # options.audio_output, False) # self.connect(self.resamp_L, (self.audio_sink, 0)) # self.connect(self.resamp_R, (self.audio_sink, 1)) self.file_sink1 = gr.file_sink(gr.sizeof_float, 'audioL.dat') self.file_sink2 = gr.file_sink(gr.sizeof_float, 'audioR.dat') self.file_sink3 = gr.file_sink(gr.sizeof_float, 'fmDemod.dat') self.connect(self.resamp_L, self.file_sink1) self.connect(self.resamp_R, self.file_sink2) self.connect(self.fm_demod, self.file_sink3) # low-pass the baseband RDS signal at 1.5kHz rds_bb_filter_coeffs = gr.firdes.low_pass( 1, # gain sdr_rate, # sampling rate 1.5e3, # passband cutoff 2e3, # transition width gr.firdes.WIN_HAMMING) self.rds_bb_filter = gr.fir_filter_fff(audio_decim, rds_bb_filter_coeffs) # print "# rds bb filter:", len(rds_bb_filter_coeffs), "taps" self.connect(self.rds_baseband, self.rds_bb_filter) # 1187.5bps = 19kHz/16 self.clock_divider = rds.freq_divider(16) rds_clock_taps = gr.firdes.low_pass( 1, # gain sdr_rate, # sampling rate 1.2e3, # passband cutoff 1.5e3, # transition width gr.firdes.WIN_HAMMING) self.rds_clock = gr.fir_filter_fff(audio_decim, rds_clock_taps) # print "# rds clock filter:", len(rds_clock_taps), "taps" self.connect(self.pilot_filter, self.clock_divider, self.rds_clock) # bpsk_demod, diff_decoder, rds_decoder self.bpsk_demod = rds.bpsk_demod(audio_rate) self.differential_decoder = gr.diff_decoder_bb(2) self.msgq = gr.msg_queue() self.rds_decoder = rds.data_decoder(self.msgq) self.connect(self.rds_bb_filter, (self.bpsk_demod, 0)) self.connect(self.rds_clock, (self.bpsk_demod, 1)) self.connect(self.bpsk_demod, self.differential_decoder) self.connect(self.differential_decoder, self.rds_decoder)
def __init__(self): gr.top_block.__init__ (self) parser=OptionParser(option_class=eng_option) parser.add_option("-H", "--hostname", type="string", default="localhost", help="set hostname of generic sdr") parser.add_option("-P", "--portnum", type="int", default=None, help="set portnum of generic sdr") parser.add_option("-W", "--wsportnum", type="int", default=None, help="set portnum of audio websocket server") parser.add_option("-r", "--sdr_rate", type="eng_float", default=250e3, help="set sample rate of generic sdr") parser.add_option("-V", "--volume", type="eng_float", default=None, help="set volume (default is midpoint)") parser.add_option("-O", "--audio-output", type="string", default="plughw:0,0", help="pcm device name (default is plughw:0,0)") # print help when called with wrong arguments (options, args) = parser.parse_args() if len(args) != 0: parser.print_help() sys.exit(1) self.vol = options.volume if self.vol is None: self.vol = 0.1 # connect to generic SDR sdr_rate = options.sdr_rate audio_decim = 8 audio_rate = int(sdr_rate/audio_decim) print "audio_rate = ", audio_rate self.interleaved_short_to_complex = gr.interleaved_short_to_complex() self.char_to_short = gr.char_to_short(1) self.sdr_source = grc_blks2.tcp_source( itemsize=gr.sizeof_char*1, addr=options.hostname, port=options.portnum, server=False ) # self.sdr_source = gr.file_source(1, 'sdrs_baseband.dat') # self.throttle = gr.throttle(1, 500e3) # self.connect(self.sdr_source, self.file_sink) self.logger = gr.file_sink(1, 'log.out') self.connect(self.sdr_source, self.logger) # channel filter chan_filter_coeffs = gr.firdes.low_pass( 1.0, # gain sdr_rate, # sampling rate 80e3, # passband cutoff 35e3, # transition width gr.firdes.WIN_HAMMING) self.chan_filter = gr.fir_filter_ccf(1, chan_filter_coeffs) # print "# channel filter:", len(chan_filter_coeffs), "taps" # PLL-based WFM demod fm_alpha = 0.25 * 250e3 * math.pi / sdr_rate # 0.767 fm_beta = fm_alpha * fm_alpha / 4.0 # 0.147 fm_max_freq = 2.0 * math.pi * 90e3 / sdr_rate # 2.209 self.fm_demod = gr.pll_freqdet_cf( 1.0, # Loop BW fm_max_freq, # in radians/sample -fm_max_freq) self.fm_demod.set_alpha(fm_alpha) self.fm_demod.set_beta(fm_beta) self.connect(self.sdr_source, self.char_to_short) self.connect(self.char_to_short, self.interleaved_short_to_complex) self.connect(self.interleaved_short_to_complex, self.chan_filter, self.fm_demod) # L+R, pilot, L-R, RDS filters lpr_filter_coeffs = gr.firdes.low_pass( 1.0, # gain sdr_rate, # sampling rate 15e3, # passband cutoff 1e3, # transition width gr.firdes.WIN_HAMMING) self.lpr_filter = gr.fir_filter_fff(audio_decim, lpr_filter_coeffs) pilot_filter_coeffs = gr.firdes.band_pass( 1.0, # gain sdr_rate, # sampling rate 19e3-500, # low cutoff 19e3+500, # high cutoff 1e3, # transition width gr.firdes.WIN_HAMMING) self.pilot_filter = gr.fir_filter_fff(1, pilot_filter_coeffs) dsbsc_filter_coeffs = gr.firdes.band_pass( 1.0, # gain sdr_rate, # sampling rate 38e3-15e3/2, # low cutoff 38e3+15e3/2, # high cutoff 1e3, # transition width gr.firdes.WIN_HAMMING) self.dsbsc_filter = gr.fir_filter_fff(1, dsbsc_filter_coeffs) rds_filter_coeffs = gr.firdes.band_pass( 1.0, # gain sdr_rate, # sampling rate 57e3-3e3, # low cutoff 57e3+3e3, # high cutoff 3e3, # transition width gr.firdes.WIN_HAMMING) self.rds_filter = gr.fir_filter_fff(1, rds_filter_coeffs) # print "# lpr filter:", len(lpr_filter_coeffs), "taps" # print "# pilot filter:", len(pilot_filter_coeffs), "taps" # print "# dsbsc filter:", len(dsbsc_filter_coeffs), "taps" # print "# rds filter:", len(rds_filter_coeffs), "taps" self.connect(self.fm_demod, self.lpr_filter) self.connect(self.fm_demod, self.pilot_filter) self.connect(self.fm_demod, self.dsbsc_filter) self.connect(self.fm_demod, self.rds_filter) # down-convert L-R, RDS self.stereo_baseband = gr.multiply_ff() self.connect(self.pilot_filter, (self.stereo_baseband, 0)) self.connect(self.pilot_filter, (self.stereo_baseband, 1)) self.connect(self.dsbsc_filter, (self.stereo_baseband, 2)) self.rds_baseband = gr.multiply_ff() self.connect(self.pilot_filter, (self.rds_baseband, 0)) self.connect(self.pilot_filter, (self.rds_baseband, 1)) self.connect(self.pilot_filter, (self.rds_baseband, 2)) self.connect(self.rds_filter, (self.rds_baseband, 3)) # low-pass and downsample L-R lmr_filter_coeffs = gr.firdes.low_pass( 1.0, # gain sdr_rate, # sampling rate 15e3, # passband cutoff 1e3, # transition width gr.firdes.WIN_HAMMING) self.lmr_filter = gr.fir_filter_fff(audio_decim, lmr_filter_coeffs) self.connect(self.stereo_baseband, self.lmr_filter) # create L, R from L-R, L+R self.left = gr.add_ff() self.right = gr.sub_ff() self.connect(self.lpr_filter, (self.left, 0)) self.connect(self.lmr_filter, (self.left, 1)) self.connect(self.lpr_filter, (self.right, 0)) self.connect(self.lmr_filter, (self.right, 1)) # volume control, complex2flot, audio sink self.volume_control_l = gr.multiply_const_ff(self.vol) self.volume_control_r = gr.multiply_const_ff(self.vol) output_audio_rate = 48000 self.resamp_L = blks2.rational_resampler_fff(interpolation=output_audio_rate,decimation=audio_rate,taps=None,fractional_bw=None,) self.resamp_R = blks2.rational_resampler_fff(interpolation=output_audio_rate,decimation=audio_rate,taps=None,fractional_bw=None,) self.connect(self.left, self.volume_control_l, self.resamp_L) self.connect(self.right, self.volume_control_r, self.resamp_R) # self.audio_sink = audio.sink(int(output_audio_rate), # options.audio_output, False) # self.connect(self.resamp_L, (self.audio_sink, 0)) # self.connect(self.resamp_R, (self.audio_sink, 1)) # self.file_sink1 = gr.file_sink(gr.sizeof_float, 'audioL.dat') # self.file_sink2 = gr.file_sink(gr.sizeof_float, 'audioR.dat') # self.file_sink3 = gr.file_sink(gr.sizeof_float, 'fmDemod.dat') # self.connect(self.resamp_L, self.file_sink1) # self.connect(self.resamp_R, self.file_sink2) # self.connect(self.fm_demod, self.file_sink3) # Interleave both channels so that we can push over one websocket connection self.audio_interleaver = gr.float_to_complex(1) self.connect(self.resamp_L, (self.audio_interleaver, 0)) self.connect(self.resamp_R, (self.audio_interleaver, 1)) self.ws_audio_server = sdrportal.ws_sink_c(True, options.wsportnum, "FLOAT") self.connect(self.audio_interleaver, self.ws_audio_server) # low-pass the baseband RDS signal at 1.5kHz rds_bb_filter_coeffs = gr.firdes.low_pass( 1, # gain sdr_rate, # sampling rate 1.5e3, # passband cutoff 2e3, # transition width gr.firdes.WIN_HAMMING) self.rds_bb_filter = gr.fir_filter_fff(audio_decim, rds_bb_filter_coeffs) # print "# rds bb filter:", len(rds_bb_filter_coeffs), "taps" self.connect(self.rds_baseband, self.rds_bb_filter) # 1187.5bps = 19kHz/16 self.clock_divider = rds.freq_divider(16) rds_clock_taps = gr.firdes.low_pass( 1, # gain sdr_rate, # sampling rate 1.2e3, # passband cutoff 1.5e3, # transition width gr.firdes.WIN_HAMMING) self.rds_clock = gr.fir_filter_fff(audio_decim, rds_clock_taps) # print "# rds clock filter:", len(rds_clock_taps), "taps" self.connect(self.pilot_filter, self.clock_divider, self.rds_clock) # bpsk_demod, diff_decoder, rds_decoder self.bpsk_demod = rds.bpsk_demod(audio_rate) self.differential_decoder = gr.diff_decoder_bb(2) self.msgq = gr.msg_queue() self.rds_decoder = rds.data_decoder(self.msgq) self.connect(self.rds_bb_filter, (self.bpsk_demod, 0)) self.connect(self.rds_clock, (self.bpsk_demod, 1)) self.connect(self.bpsk_demod, self.differential_decoder) self.connect(self.differential_decoder, self.rds_decoder)
def __init__(self, options): gr.hier_block2.__init__(self, "ais_demod", gr.io_signature(1, 1, gr.sizeof_gr_complex), # Input signature gr.io_signature(1, 1, gr.sizeof_char)) # Output signature self._samples_per_symbol = options.samples_per_symbol self._bits_per_sec = options.bits_per_sec self._samplerate = self._samples_per_symbol * self._bits_per_sec self._gain_mu = options.gain_mu self._mu = options.mu self._omega_relative_limit = options.omega_relative_limit self.fftlen = options.fftlen #right now we are going to hardcode the different options for VA mode here. later on we can use configurable options samples_per_symbol_viterbi = 2 bits_per_symbol = 2 samples_per_symbol = 6 samples_per_symbol_clockrec = samples_per_symbol / bits_per_symbol BT = 0.4 data_rate = 9600.0 samp_rate = options.samp_rate self.gmsk_sync = gmsk_sync.square_and_fft_sync(self._samplerate, self._bits_per_sec, self.fftlen) if(options.viterbi is True): #calculate the required decimation and interpolation to achieve the desired samples per symbol denom = gcd(data_rate*samples_per_symbol, samp_rate) cr_interp = int(data_rate*samples_per_symbol/denom) cr_decim = int(samp_rate/denom) self.resample = blks2.rational_resampler_ccc(cr_interp, cr_decim) #here we take a different tack and use A.A.'s CPM decomposition technique self.clockrec = gr.clock_recovery_mm_cc(samples_per_symbol_clockrec, 0.005*0.005*0.25, 0.5, 0.005, 0.0005) #might have to futz with the max. deviation (fsm, constellation, MF, N, f0T) = make_gmsk(samples_per_symbol_viterbi, BT) #calculate the decomposition required for demodulation self.costas = gr.costas_loop_cc(0.015, 0.015*0.015*0.25, 100e-6, -100e-6, 4) #does fine freq/phase synchronization. should probably calc the coeffs instead of hardcode them. self.streams2stream = gr.streams_to_stream(int(gr.sizeof_gr_complex*1), int(N)) self.mf0 = gr.fir_filter_ccc(samples_per_symbol_viterbi, MF[0].conjugate()) #two matched filters for decomposition self.mf1 = gr.fir_filter_ccc(samples_per_symbol_viterbi, MF[1].conjugate()) self.fo = gr.sig_source_c(samples_per_symbol_viterbi, gr.GR_COS_WAVE, -f0T, 1, 0) #the memoryless modulation component of the decomposition self.fomult = gr.multiply_cc(1) self.trellis = trellis.viterbi_combined_cb(fsm, int(data_rate), -1, -1, int(N), constellation, trellis.TRELLIS_EUCLIDEAN) #the actual Viterbi decoder else: #this is probably not optimal and someone who knows what they're doing should correct me self.datafiltertaps = gr.firdes.root_raised_cosine(10, #gain self._samplerate*32, #sample rate self._bits_per_sec, #symbol rate 0.4, #alpha, same as BT? 50*32) #no. of taps self.datafilter = gr.fir_filter_fff(1, self.datafiltertaps) sensitivity = (math.pi / 2) / self._samples_per_symbol self.demod = gr.quadrature_demod_cf(sensitivity) #param is gain #self.clockrec = digital.clock_recovery_mm_ff(self._samples_per_symbol,0.25*self._gain_mu*self._gain_mu,self._mu,self._gain_mu,self._omega_relative_limit) self.clockrec = gr.pfb_clock_sync_ccf(self._samples_per_symbol, 0.04, self.datafiltertaps, 32, 0, 1.15) self.tcslicer = digital.digital.binary_slicer_fb() # self.dfe = digital.digital.lms_dd_equalizer_cc( # 32, # 0.005, # 1, # digital.digital.constellation_bpsk() # ) # self.delay = gr.delay(gr.sizeof_float, 64 + 16) #the correlator delays 64 bits, and the LMS delays some as well. self.slicer = digital.digital.binary_slicer_fb() # self.training_correlator = digital.correlate_access_code_bb("1100110011001100", 0) # self.cma = digital.cma_equalizer_cc #just a note here: a complex combined quad demod/slicer could be based on if's rather than an actual quad demod, right? #in fact all the constellation decoders up to QPSK could operate on complex data w/o doing the whole atan thing self.diff = gr.diff_decoder_bb(2) self.invert = ais.invert() #NRZI signal diff decoded and inverted should give original signal self.connect(self, self.gmsk_sync) if(options.viterbi is False): self.connect(self.gmsk_sync, self.clockrec, self.demod, self.slicer, self.diff, self.invert, self) #self.connect(self.gmsk_sync, self.demod, self.clockrec, self.tcslicer, self.training_correlator) #self.connect(self.clockrec, self.delay, (self.dfe, 0)) #self.connect(self.training_correlator, (self.dfe, 1)) #self.connect(self.dfe, self.slicer, self.diff, self.invert, self) else: self.connect(self.gmsk_sync, self.costas, self.resample, self.clockrec) self.connect(self.clockrec, (self.fomult, 0)) self.connect(self.fo, (self.fomult, 1)) self.connect(self.fomult, self.mf0) self.connect(self.fomult, self.mf1) self.connect(self.mf0, (self.streams2stream, 0)) self.connect(self.mf1, (self.streams2stream, 1)) self.connect(self.streams2stream, self.trellis, self.diff, self.invert, self)
samplerate = 48000 src = audio.source(samplerate,"hw:1") pluss = gr.add_const_ff(0.0) lpcoeffs = gr.firdes.low_pass(1,samplerate,8000,3000) lpfilter = gr.fir_filter_fff(1,lpcoeffs) forsterk = gr.multiply_const_ff(5) clockrec = gr.clock_recovery_mm_ff(float(samplerate)/9600,0.25*0.175*0.175,0.5,0.175,0.005) slicer = gr.binary_slicer_fb() # Parameters: ([mysql-server],[database name],[database user],[database password]) datadec = ais.ais_decoder_mysql("localhost","diverse","ruben","elg") # You should use the create_mysql.sql to create the necessary tables # in the database. # See create_mysql.txt for help. Those files can be found in the root folder of # the source tree. diff = gr.diff_decoder_bb(2) invert = ais.invert10_bb() fg.connect(src,pluss,lpfilter,forsterk,clockrec,slicer,diff,invert,datadec) fg.start() raw_input("Receives AIS from soundcard ") fg.stop() print "Received correctly: ",datadec.received() print "Wrong CRC: ",datadec.lost() print "Wrong Size: ",datadec.lost2()