Пример #1
0
    def __init__(self,
                 N,
                 sps,
                 rolloff,
                 ntaps,
                 bw,
                 noise,
                 foffset,
                 toffset,
                 poffset,
                 mode=0):
        gr.top_block.__init__(self)

        rrc_taps = gr.firdes.root_raised_cosine(sps, sps, 1.0, rolloff, ntaps)

        gain = 2 * scipy.pi / 100.0
        nfilts = 32
        rrc_taps_rx = gr.firdes.root_raised_cosine(nfilts, sps * nfilts, 1.0,
                                                   rolloff, ntaps * nfilts)

        data = 2.0 * scipy.random.randint(0, 2, N) - 1.0
        data = scipy.exp(1j * poffset) * data

        self.src = gr.vector_source_c(data.tolist(), False)
        self.rrc = gr.interp_fir_filter_ccf(sps, rrc_taps)
        self.chn = gr.channel_model(noise, foffset, toffset)
        self.off = gr.fractional_interpolator_cc(0.20, 1.0)

        if mode == 0:
            self.clk = gr.pfb_clock_sync_ccf(sps, gain, rrc_taps_rx, nfilts,
                                             nfilts // 2, 3.5)
            self.taps = self.clk.get_taps()
            self.dtaps = self.clk.get_diff_taps()

            self.vsnk_err = gr.vector_sink_f()
            self.vsnk_rat = gr.vector_sink_f()
            self.vsnk_phs = gr.vector_sink_f()

            self.connect((self.clk, 1), self.vsnk_err)
            self.connect((self.clk, 2), self.vsnk_rat)
            self.connect((self.clk, 3), self.vsnk_phs)

        else:  # mode == 1
            mu = 0.5
            gain_mu = 0.1
            gain_omega = 0.25 * gain_mu * gain_mu
            omega_rel_lim = 0.02
            self.clk = digital.clock_recovery_mm_cc(sps, gain_omega, mu,
                                                    gain_mu, omega_rel_lim)

            self.vsnk_err = gr.vector_sink_f()

            self.connect((self.clk, 1), self.vsnk_err)

        self.vsnk_src = gr.vector_sink_c()
        self.vsnk_clk = gr.vector_sink_c()

        self.connect(self.src, self.rrc, self.chn, self.off, self.clk,
                     self.vsnk_clk)
        self.connect(self.off, self.vsnk_src)
Пример #2
0
    def __init__(self, N, sps, rolloff, ntaps, bw, noise,
                 foffset, toffset, poffset, mode=0):
        gr.top_block.__init__(self)

        rrc_taps = gr.firdes.root_raised_cosine(
            sps, sps, 1.0, rolloff, ntaps)

        gain = 2*scipy.pi/100.0
        nfilts = 32
        rrc_taps_rx = gr.firdes.root_raised_cosine(
            nfilts, sps*nfilts, 1.0, rolloff, ntaps*nfilts)
            
        data = 2.0*scipy.random.randint(0, 2, N) - 1.0
        data = scipy.exp(1j*poffset) * data

        self.src = gr.vector_source_c(data.tolist(), False)
        self.rrc = gr.interp_fir_filter_ccf(sps, rrc_taps)
        self.chn = gr.channel_model(noise, foffset, toffset)
        self.off = gr.fractional_interpolator_cc(0.20, 1.0)

        if mode == 0:
            self.clk = gr.pfb_clock_sync_ccf(sps, gain, rrc_taps_rx,
                                             nfilts, nfilts//2, 3.5)
            self.taps = self.clk.get_taps()
            self.dtaps = self.clk.get_diff_taps()

            self.vsnk_err = gr.vector_sink_f()
            self.vsnk_rat = gr.vector_sink_f()
            self.vsnk_phs = gr.vector_sink_f()

            self.connect((self.clk,1), self.vsnk_err)
            self.connect((self.clk,2), self.vsnk_rat)
            self.connect((self.clk,3), self.vsnk_phs)
            
        else: # mode == 1
            mu = 0.5
            gain_mu = 0.1
            gain_omega = 0.25*gain_mu*gain_mu
            omega_rel_lim = 0.02
            self.clk = digital.clock_recovery_mm_cc(sps, gain_omega,
                                                    mu, gain_mu,
                                                    omega_rel_lim)

            self.vsnk_err = gr.vector_sink_f()

            self.connect((self.clk,1), self.vsnk_err)

        self.vsnk_src = gr.vector_sink_c()
        self.vsnk_clk = gr.vector_sink_c()

        self.connect(self.src, self.rrc, self.chn, self.off, self.clk, self.vsnk_clk)
        self.connect(self.off, self.vsnk_src)
Пример #3
0
    def __init__(self, sample_rate, symbol_rate):
        gr.hier_block2.__init__(
            self,
            "dvb_s_demodulator2_cc",
            gr.io_signature(1, 1, gr.sizeof_gr_complex),  # Input signature
            gr.io_signature(1, 1, gr.sizeof_gr_complex))  # Output signature

        samples_per_symbol = sample_rate / symbol_rate

        # Automatic gain control
        self.agc = gr.agc2_cc(
            0.06,  # Attack rate
            0.001,  # Decay rate
            1,  # Reference
            1,  # Initial gain
            100)  # Max gain

        # Frequency correction with band-edge filters FLL
        freq_beta = freq_alpha * freq_alpha / 4
        self.freq_recov = digital.fll_band_edge_cc(
            samples_per_symbol,
            dvb_swig.RRC_ROLLOFF_FACTOR,
            11 * int(samples_per_symbol),  # Size of the filter in taps
            freq_bw)
        self.freq_recov.set_alpha(freq_alpha)
        self.freq_recov.set_beta(freq_beta)

        # Symbol timing recovery with RRC data filter
        ntaps = 11 * int(samples_per_symbol * nfilts)
        rrc_taps = gr.firdes.root_raised_cosine(nfilts, nfilts,
                                                1.0 / samples_per_symbol,
                                                dvb_swig.RRC_ROLLOFF_FACTOR,
                                                ntaps)
        self.time_recov = gr.pfb_clock_sync_ccf(
            samples_per_symbol,  # Samples per second in the incoming signal
            timing_alpha,  # Alpha gain of control loop
            rrc_taps,  # The filter taps
            nfilts,  # Number of filters in the filter bank
            nfilts /
            2)  # Initial phase to look at (or which filter to start with)
        self.time_recov.set_beta(timing_beta)

        # Perform phase / fine frequency correction using Costas PLL
        phase_beta = phase_alpha * phase_alpha / 4
        self.phase_recov = digital.costas_loop_cc(phase_bw, M)
        self.phase_recov.set_alpha(phase_alpha)
        self.phase_recov.set_beta(phase_beta)

        self.connect(self, self.agc, self.freq_recov, self.time_recov,
                     self.phase_recov, self)
Пример #4
0
	def __init__(self, sample_rate, symbol_rate):
		gr.hier_block2.__init__(self, "dvb_s_demodulator2_cc",
				gr.io_signature(1, 1, gr.sizeof_gr_complex),	# Input signature
				gr.io_signature(1, 1, gr.sizeof_gr_complex))	# Output signature

		samples_per_symbol = sample_rate / symbol_rate

		# Automatic gain control
		self.agc = gr.agc2_cc(
				0.06,				# Attack rate
				0.001,				# Decay rate
				1,					# Reference
				1,					# Initial gain
				100)				# Max gain

		# Frequency correction with band-edge filters FLL
		freq_beta = freq_alpha * freq_alpha / 4
		self.freq_recov = digital.fll_band_edge_cc(
				samples_per_symbol,
				dvb_swig.RRC_ROLLOFF_FACTOR,
				11 * int(samples_per_symbol),	# Size of the filter in taps
				freq_bw)
		self.freq_recov.set_alpha(freq_alpha)
		self.freq_recov.set_beta(freq_beta)


		# Symbol timing recovery with RRC data filter
		ntaps = 11 * int(samples_per_symbol * nfilts)
		rrc_taps = gr.firdes.root_raised_cosine(nfilts, nfilts,
				1.0 / samples_per_symbol, dvb_swig.RRC_ROLLOFF_FACTOR, ntaps)
		self.time_recov = gr.pfb_clock_sync_ccf(
				samples_per_symbol,				# Samples per second in the incoming signal
				timing_alpha,					# Alpha gain of control loop
				rrc_taps,						# The filter taps
				nfilts,							# Number of filters in the filter bank
				nfilts / 2)						# Initial phase to look at (or which filter to start with)
		self.time_recov.set_beta(timing_beta)

		# Perform phase / fine frequency correction using Costas PLL
		phase_beta  = phase_alpha * phase_alpha / 4
		self.phase_recov = digital.costas_loop_cc(phase_bw, M)
		self.phase_recov.set_alpha(phase_alpha)
		self.phase_recov.set_beta(phase_beta)

		self.connect(self, self.agc, self.freq_recov, self.time_recov, self.phase_recov, self)
    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)
Пример #6
0
    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)
Пример #7
0
    def __init__(self, 
                 samples_per_symbol=_def_samples_per_symbol,
                 excess_bw=_def_excess_bw,
                 costas_alpha=_def_costas_alpha,
                 timing_alpha=_def_timing_alpha,
                 timing_max_dev=_def_timing_max_dev,
                 gray_code=_def_gray_code,
                 verbose=_def_verbose,
                 log=_def_log):
        """
	Hierarchical block for RRC-filtered DQPSK demodulation

	The input is the complex modulated signal at baseband.
	The output is a stream of bits packed 1 bit per byte (LSB)

	@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 costas_alpha: loop filter gain
        @type costas_alphas: float
        @param timing_alpha: timing loop alpha gain
        @type timing_alpha: float
        @param timing_max: timing loop maximum rate deviations
        @type timing_max: float
        @param gray_code: Tell modulator to Gray code the bits
        @type gray_code: bool
        @param verbose: Print information about modulator?
        @type verbose: bool
        @param debug: Print modualtion data to files?
        @type debug: bool
	"""

	gr.hier_block2.__init__(self, "dqpsk2_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 = samples_per_symbol
        self._excess_bw = excess_bw
        self._costas_alpha = costas_alpha
        self._timing_alpha = timing_alpha
        self._timing_beta = _def_timing_beta
        self._timing_max_dev=timing_max_dev
        self._gray_code = gray_code

        if samples_per_symbol < 2:
            raise TypeError, "sbp must be >= 2, is %d" % samples_per_symbol

        arity = pow(2,self.bits_per_symbol())
 
        # Automatic gain control
        self.agc = gr.agc2_cc(0.6e-1, 1e-3, 1, 1, 100)
        #self.agc = gr.feedforward_agc_cc(16, 2.0)

        self._costas_beta  = 0.25 * self._costas_alpha * self._costas_alpha
        # Allow a frequency swing of +/- half of the sample rate
        fmin = -0.5
        fmax = 0.5

        self.clock_recov = gr.costas_loop_cc(self._costas_alpha,
                                             self._costas_beta,
                                             fmax, fmin, arity)

        # symbol timing recovery with RRC data filter
        nfilts = 32
        ntaps = 11 * samples_per_symbol*nfilts
        taps = gr.firdes.root_raised_cosine(nfilts, nfilts, 1.0/float(self._samples_per_symbol), self._excess_bw, ntaps)
        self.time_recov = gr.pfb_clock_sync_ccf(self._samples_per_symbol,
                                                self._timing_alpha,
                                                taps, nfilts, nfilts/2, self._timing_max_dev)
        self.time_recov.set_beta(self._timing_beta)
        
        # Perform Differential decoding on the constellation
        self.diffdec = gr.diff_phasor_cc()
        
        # find closest constellation point
        rot = 1
        rotated_const = map(lambda pt: pt * rot, psk.constellation[arity])
        self.slicer = gr.constellation_decoder_cb(rotated_const, range(arity))

        if self._gray_code:
            self.symbol_mapper = gr.map_bb(psk.gray_to_binary[arity])
        else:
            self.symbol_mapper = gr.map_bb(psk.ungray_to_binary[arity])
        
        # 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
        self.connect(self, self.agc, 
                     self.clock_recov,
                     self.time_recov,
                     self.diffdec, self.slicer, self.symbol_mapper, self.unpack, self)
Пример #8
0
    def __init__(self,
                 samples_per_symbol=_def_samples_per_symbol,
                 excess_bw=_def_excess_bw,
                 freq_alpha=_def_freq_alpha,
                 phase_alpha=_def_phase_alpha,
                 timing_alpha=_def_timing_alpha,
                 timing_max_dev=_def_timing_max_dev,
                 gray_code=_def_gray_code,
                 verbose=_def_verbose,
                 log=_def_log,
                 sync_out=False):
        """
	Hierarchical block for RRC-filtered DQPSK demodulation

	The input is the complex modulated signal at baseband.
	The output is a stream of bits packed 1 bit per byte (LSB)

	@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 freq_alpha: loop filter gain for frequency recovery
        @type freq_alpha: float
        @param phase_alpha: loop filter gain
        @type phase_alphas: float
        @param timing_alpha: timing loop alpha gain
        @type timing_alpha: float
        @param timing_max: timing loop maximum rate deviations
        @type timing_max: float
        @param gray_code: Tell modulator to Gray code the bits
        @type gray_code: bool
        @param verbose: Print information about modulator?
        @type verbose: bool
        @param log: Print modualtion data to files?
        @type log: bool
        @param sync_out: Output a sync signal on :1?
        @type sync_out: bool
	"""
        if sync_out:
            io_sig_out = gr.io_signaturev(
                2, 2, (gr.sizeof_char, gr.sizeof_gr_complex))
        else:
            io_sig_out = gr.io_signature(1, 1, gr.sizeof_char)

        gr.hier_block2.__init__(
            self,
            "dqpsk2_demod",
            gr.io_signature(1, 1, gr.sizeof_gr_complex),  # Input signature
            io_sig_out)  # Output signature

        self._samples_per_symbol = samples_per_symbol
        self._excess_bw = excess_bw
        self._freq_alpha = freq_alpha
        self._freq_beta = 0.25 * self._freq_alpha**2
        self._phase_alpha = phase_alpha
        self._timing_alpha = timing_alpha
        self._timing_beta = _def_timing_beta
        self._timing_max_dev = timing_max_dev
        self._gray_code = gray_code

        if samples_per_symbol < 2:
            raise TypeError, "sbp must be >= 2, is %d" % samples_per_symbol

        arity = pow(2, self.bits_per_symbol())

        # Automatic gain control
        self.agc = gr.agc2_cc(0.6e-1, 1e-3, 1, 1, 100)
        #self.agc = gr.feedforward_agc_cc(16, 2.0)

        # Frequency correction
        self.freq_recov = gr.fll_band_edge_cc(
            self._samples_per_symbol, self._excess_bw,
            11 * int(self._samples_per_symbol), self._freq_alpha,
            self._freq_beta)

        # symbol timing recovery with RRC data filter
        nfilts = 32
        ntaps = 11 * int(samples_per_symbol * nfilts)
        taps = gr.firdes.root_raised_cosine(
            nfilts, nfilts, 1.0 / float(self._samples_per_symbol),
            self._excess_bw, ntaps)
        self.time_recov = gr.pfb_clock_sync_ccf(self._samples_per_symbol,
                                                self._timing_alpha, taps,
                                                nfilts, nfilts / 2,
                                                self._timing_max_dev)
        self.time_recov.set_beta(self._timing_beta)

        # Perform phase / fine frequency correction
        self._phase_beta = 0.25 * self._phase_alpha * self._phase_alpha
        # Allow a frequency swing of +/- half of the sample rate
        fmin = -0.5
        fmax = 0.5

        self.phase_recov = gr.costas_loop_cc(self._phase_alpha,
                                             self._phase_beta, fmax, fmin,
                                             arity)

        # Perform Differential decoding on the constellation
        self.diffdec = gr.diff_phasor_cc()

        # find closest constellation point
        rot = 1
        rotated_const = map(lambda pt: pt * rot, psk.constellation[arity])
        self.slicer = gr.constellation_decoder_cb(rotated_const, range(arity))

        if self._gray_code:
            self.symbol_mapper = gr.map_bb(psk.gray_to_binary[arity])
        else:
            self.symbol_mapper = gr.map_bb(psk.ungray_to_binary[arity])

        # 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
        self.connect(self, self.agc, self.freq_recov, self.time_recov,
                     self.phase_recov, self.diffdec, self.slicer,
                     self.symbol_mapper, self.unpack, self)
        if sync_out: self.connect(self.time_recov, (self, 1))
Пример #9
0
    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)
Пример #10
0
    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)