Esempio n. 1
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)
Esempio n. 2
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)
Esempio n. 3
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 = filter.rational_resampler_ccc(cr_interp, cr_decim)
            #here we take a different tack and use A.A.'s CPM decomposition technique
            self.clockrec = digital.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 = digital.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 = blocks.streams_to_stream(int(gr.sizeof_gr_complex*1), int(N))
            self.mf0 = filter.fir_filter_ccc(samples_per_symbol_viterbi, MF[0].conjugate()) #two matched filters for decomposition
            self.mf1 = filter.fir_filter_ccc(samples_per_symbol_viterbi, MF[1].conjugate())
            self.fo = analog.sig_source_c(samples_per_symbol_viterbi, gr.GR_COS_WAVE, -f0T, 1, 0) #the memoryless modulation component of the decomposition
            self.fomult = blocks.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 = filter.firdes.root_raised_cosine(10, #gain
                                                      self._samplerate*16, #sample rate
                                                      self._bits_per_sec, #symbol rate
                                                      0.4, #alpha, same as BT?
                                                      50*16) #no. of taps

            sensitivity = (math.pi / 2) / self._samples_per_symbol
            self.demod = analog.quadrature_demod_cf(sensitivity) #param is gain

            self.clockrec = digital.pfb_clock_sync_ccf(self._samples_per_symbol,
                                                       0.04,
                                                       self.datafiltertaps, 16, 0, 1.15)
            self.tcslicer = digital.digital.binary_slicer_fb()
            self.slicer = digital.binary_slicer_fb()

        self.diff = digital.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)

        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)