Example #1
0
 def test_012_disconnect_input(self):
     hblock = gr.hier_block2("test_block",
                             gr.io_signature(1,1,gr.sizeof_int),
                             gr.io_signature(1,1,gr.sizeof_int))
     nop1 = blocks.nop(gr.sizeof_int)
     hblock.connect(hblock, nop1)
     hblock.disconnect(hblock, nop1)
Example #2
0
    def __init__(self):
        gr.hier_block2.__init__(
            self, "NBFM Chain",
            gr.io_signature(1, 1, gr.sizeof_gr_complex*1),
            gr.io_signature(1, 1, gr.sizeof_float*1),
        )

        ##################################################
        # Blocks
        ##################################################
        self.rational_resampler_xxx_0 = filter.rational_resampler_ccc(
                interpolation=192000,
                decimation=2400000,
                taps=None,
                fractional_bw=None,
        )
        self.low_pass_filter_1 = filter.fir_filter_ccf(1, firdes.low_pass(
        	1, 192000, 5e3, 5e3, firdes.WIN_HAMMING, 6.76))
        self.blocks_multiply_const_vxx_0 = blocks.multiply_const_vff((5, ))
        self.analog_nbfm_rx_0 = analog.nbfm_rx(
        	audio_rate=48000,
        	quad_rate=192000,
        	tau=75e-6,
        	max_dev=2.5e3,
        )

        ##################################################
        # Connections
        ##################################################
        self.connect((self.analog_nbfm_rx_0, 0), (self.blocks_multiply_const_vxx_0, 0))    
        self.connect((self.blocks_multiply_const_vxx_0, 0), (self, 0))    
        self.connect((self.low_pass_filter_1, 0), (self.analog_nbfm_rx_0, 0))    
        self.connect((self, 0), (self.rational_resampler_xxx_0, 0))    
        self.connect((self.rational_resampler_xxx_0, 0), (self.low_pass_filter_1, 0))    
Example #3
0
    def __init__(self, size, factor, itemsize=gr.sizeof_gr_complex):
        """
        size: (int) vector size (FFT size) of next block
        factor: (int) output will have this many more samples than input
        
        If size is not divisible by factor, then the output will necessarily have jitter.
        """
        size = int(size)
        factor = int(factor)
        # assert size % factor == 0
        offset = size // factor

        gr.hier_block2.__init__(
            self, type(self).__name__,
            gr.io_signature(1, 1, itemsize),
            gr.io_signature(1, 1, itemsize),
        )
        
        if factor == 1:
            # No duplication needed; simplify flowgraph
            # GR refused to connect self to self, so insert a dummy block
            self.connect(self, blocks.copy(itemsize), self)
        else:
            interleave = blocks.interleave(itemsize * size)
            self.connect(
                interleave,
                blocks.vector_to_stream(itemsize, size),
                self)
        
            for i in xrange(0, factor):
                self.connect(
                    self,
                    blocks.delay(itemsize, (factor - 1 - i) * offset),
                    blocks.stream_to_vector(itemsize, size),
                    (interleave, i))
Example #4
0
 def test_016_disconnect_output(self):
     hblock = gr.hier_block2("test_block",
                             gr.io_signature(1,1,gr.sizeof_int),
                             gr.io_signature(1,1,gr.sizeof_int))
     nop1 = blocks.nop(gr.sizeof_int)
     hblock.connect(nop1, hblock)
     hblock.disconnect(nop1, hblock)
Example #5
0
    def __init__(self, fft_length, occupied_tones, carrier_map_bin):
        
        """
        Hierarchical block for receiving OFDM symbols.
        """
        gr.hier_block2.__init__(self, "ncofdm_filt",
                                gr.io_signature(1, 1, gr.sizeof_gr_complex),
                                gr.io_signature(1, 1, gr.sizeof_gr_complex)) # Input signature

        # fft length, e.g. 256
        self._fft_length = fft_length
        # the number of used subcarriers, e.g. 240
        self._occupied_tones = occupied_tones
        # a binary array indicates the used subcarriers
        self._carrier_map_bin = carrier_map_bin

        # setup filter banks
        self.chan_filt_low = filter.fft_filter_ccc(1,[1]) 
        self.chan_filt_high1 = filter.fft_filter_ccc(1,[1]) 
        self.chan_filt_high2 = filter.fft_filter_ccc(1,[1])
        self.chan_filt_high3 = filter.fft_filter_ccc(1,[1])
        self.chan_filt_high4 = filter.fft_filter_ccc(1,[1])
        self.chan_filt_high5 = filter.fft_filter_ccc(1,[1])
        
        # calculate the filter taps
        filt_num = self.calc_filter_taps(2, 0)
        

        # signals run into a serial of filters, one lowpass filter and 5 highpass filters
        self.connect(self, self.chan_filt_high1,
                           self.chan_filt_high2, self.chan_filt_high3,
                           self.chan_filt_high4, self.chan_filt_high5,
                           self.chan_filt_low, self) 
	def __init__(self, access_code='', threshold=-1, callback=None, verbose=0):
		"""
		packet_demod constructor.
		@param access_code AKA sync vector
		@param threshold detect access_code with up to threshold bits wrong (0 -> use default)
		@param callback a function of args: ok, payload
		"""
		#access code
		if not access_code: #get access code
			access_code = packet_utils.default_access_code
		if not packet_utils.is_1_0_string(access_code):
			raise ValueError, "Invalid access_code %r. Must be string of 1's and 0's" % (access_code,)
		self._access_code = access_code
		#threshold
		if threshold < 0: threshold = DEFAULT_THRESHOLD
		self._threshold = threshold
		#blocks
		msgq = gr.msg_queue(DEFAULT_MSGQ_LIMIT) #holds packets from the PHY
		correlator = digital.correlate_access_code_bb(self._access_code, self._threshold)
		framer_sink = logitech_27mhz_transceiver.framer_sink(msgq)

		#initialize hier2
		gr.hier_block2.__init__(
			self,
			"packet_decoder",
			gr.io_signature(1, 1, gr.sizeof_char), # Input signature
			gr.io_signature(0, 0, 0) # Output signature
		)
		#connect
		self.connect(self, correlator, framer_sink)
		#start thread
		_packet_decoder_thread(msgq, callback,verbose)
	def __init__(self, samples_per_symbol, bits_per_symbol, access_code='', pad_for_usrp=True, kbid='', verbose=0):
		"""
		packet_mod constructor.
		@param samples_per_symbol number of samples per symbol
		@param bits_per_symbol number of bits per symbol
		@param access_code AKA sync vector
		@param pad_for_usrp If true, packets are padded such that they end up a multiple of 128 samples
		@param payload_length number of bytes in a data-stream slice
		"""
		#setup parameters
		self._samples_per_symbol = samples_per_symbol
		self._bits_per_symbol = bits_per_symbol
		self._kbid = kbid
		self._verbose = verbose
		if not access_code: #get access code
			access_code = packet_utils.default_access_code
		if not packet_utils.is_1_0_string(access_code):
			raise ValueError, "Invalid access_code %r. Must be string of 1's and 0's" % (access_code,)
		self._access_code = access_code
		self._pad_for_usrp = pad_for_usrp
		#create blocks
		msg_source = gr.message_source(gr.sizeof_char, DEFAULT_MSGQ_LIMIT)
		self._msgq_out = msg_source.msgq()
		#initialize hier2
		gr.hier_block2.__init__(
			self,
			"packet_encoder",
			gr.io_signature(0, 0, 0), # Input signature
			gr.io_signature(1, 1, gr.sizeof_char) # Output signature
		)
		#connect
		self.connect(msg_source, self)
Example #8
0
	def __init__(self, sample_rate, symbol_rate):
		gr.hier_block2.__init__(self, "dvb_s_demodulator_cc",
				gr.io_signature(1, 1, gr.sizeof_gr_complex),	# Input signature
				gr.io_signature(1, 1, gr.sizeof_gr_complex))	# Output signature

		omega = sample_rate / symbol_rate
		gain_omega = omega * omega / 4.0
		freq_beta = freq_alpha * freq_alpha / 4.0
		mu = 0.0
		gain_mu = 0.05
		omega_relative_limit = 0.005

		# 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(omega, dvb_swig.RRC_ROLLOFF_FACTOR, 11 * int(omega), freq_bw)
		self.freq_recov.set_alpha(freq_alpha)
		self.freq_recov.set_beta(freq_beta)
		self.receiver = digital.mpsk_receiver_cc(M, 0, freq_bw, fmin, fmax, mu, gain_mu, omega, gain_omega, omega_relative_limit)
		self.receiver.set_alpha(freq_alpha)
		self.receiver.set_beta(freq_beta)
		self.rotate = gr.multiply_const_cc(0.707 + 0.707j)

		self.connect(self, self.agc, self.freq_recov, self.receiver, self.rotate, self)
    def __init__(self, bitrate,
                 constellation, samples_per_symbol,
                 differential, excess_bw, gray_coded,
                 freq_bw, timing_bw, phase_bw,
                 verbose, log):

        gr.hier_block2.__init__(self, "bert_receive",
                                gr.io_signature(1, 1, gr.sizeof_gr_complex), # Input signature
                                gr.io_signature(0, 0, 0))                    # Output signature
        
        self._bitrate = bitrate

        self._demod = digital.generic_demod(constellation, differential, 
                                            samples_per_symbol,
                                            gray_coded, excess_bw,
                                            freq_bw, timing_bw, phase_bw,
                                            verbose, log)

        self._symbol_rate = self._bitrate / self._demod.bits_per_symbol()
        self._sample_rate = self._symbol_rate * samples_per_symbol

        # Add an SNR probe on the demodulated constellation
        self._snr_probe = digital.probe_mpsk_snr_est_c(digital.SNR_EST_M2M4, 1000,
                                                       alpha=10.0/self._symbol_rate)
        self.connect(self._demod.time_recov, self._snr_probe)
        
        # Descramble BERT sequence.  A channel error will create 3 incorrect bits
        self._descrambler = digital.descrambler_bb(0x8A, 0x7F, 7) # CCSDS 7-bit descrambler

        # Measure BER by the density of 0s in the stream
        self._ber = digital.probe_density_b(1.0/self._symbol_rate)
        
        self.connect(self, self._demod, self._descrambler, self._ber)
Example #10
0
    def __init__(self, input_is_real=False, baseband_freq=0, y_per_div=10, ref_level=50,
                 sample_rate=1, fac_size=512,
                 fac_rate=default_fac_rate,
                 average=False, avg_alpha=None, title='', peak_hold=False):

	self._item_size = gr.sizeof_gr_complex
	if input_is_real:
	    self._item_size = gr.sizeof_float

	gr.hier_block2.__init__(
			self,
			"Fast AutoCorrelation",
			gr.io_signature(1, 1, self._item_size),
			gr.io_signature(0, 0, 0),
		)

        # initialize common attributes
        self.baseband_freq = baseband_freq
        self.y_divs = 8
        self.y_per_div=y_per_div
        self.ref_level = ref_level
        self.sample_rate = sample_rate
        self.fac_size = fac_size
        self.fac_rate = fac_rate
        self.average = average
        if (avg_alpha is None) or (avg_alpha <= 0):
            self.avg_alpha = 0.20 / fac_rate	# averaging needed to be slowed down for very slow rates
        else:
            self.avg_alpha = avg_alpha
        self.title = title
        self.peak_hold = peak_hold
        self.input_is_real = input_is_real
        self.msgq = gr.msg_queue(2)         # queue that holds a maximum of 2 messages
Example #11
0
 def __init__(self,
         device_name,
         sample_rate,
         channel_mapping,
         audio_module):
     self.__device_name = device_name
     self.__sample_rate = sample_rate
     
     self.__signal_type = SignalType(
         # TODO: type should be able to be LSB
         kind='IQ' if len(channel_mapping) == 2 else 'USB',
         sample_rate=self.__sample_rate)
     
     gr.hier_block2.__init__(
         self, type(self).__name__,
         gr.io_signature(1, 1, gr.sizeof_gr_complex * 1),
         gr.io_signature(0, 0, 0),
     )
     
     sink = audio_module.sink(
         self.__sample_rate,
         device_name=self.__device_name,
         ok_to_block=True)
     
     # TODO: ignoring channel_mapping parameter, shouldn't be
     split = blocks.complex_to_float(1)
     self.connect(self, split, (sink, 0))
     self.connect((split, 1), (sink, 1))
Example #12
0
    def __init__(self, interp, taps=None, atten=100):
        gr.hier_block2.__init__(self, "pfb_interpolator_ccf",
                                gr.io_signature(1, 1, gr.sizeof_gr_complex),
                                gr.io_signature(1, 1, gr.sizeof_gr_complex))

        self._interp = interp
        self._taps = taps

        if (taps is not None) and (len(taps) > 0):
            self._taps = taps
        else:
            # Create a filter that covers the full bandwidth of the input signal
            bw = 0.4
            tb = 0.2
            ripple = 0.99
            made = False
            while not made:
                try:
                    self._taps = optfir.low_pass(self._interp, self._interp, bw, bw+tb, ripple, atten)
                    made = True
                except RuntimeError:
                    ripple += 0.01
                    made = False
                    print("Warning: set ripple to %.4f dB. If this is a problem, adjust the attenuation or create your own filter taps." % (ripple))

                    # Build in an exit strategy; if we've come this far, it ain't working.
                    if(ripple >= 1.0):
                        raise RuntimeError("optfir could not generate an appropriate filter.")

        self.pfb = filter.pfb_interpolator_ccf(self._interp, self._taps)

        self.connect(self, self.pfb)
        self.connect(self.pfb, self)
Example #13
0
    def __init__(self, mode, input_rate=0, context=None):
        assert input_rate > 0
        self.__input_rate = input_rate
        gr.hier_block2.__init__(
            self, 'RTTY demodulator',
            gr.io_signature(1, 1, gr.sizeof_gr_complex * 1),
            gr.io_signature(1, 1, gr.sizeof_float * 1))
        
        channel_filter = self.__make_channel_filter()

        self.__text = u''
        self.__char_queue = gr.msg_queue(limit=100)
        self.__char_sink = blocks.message_sink(gr.sizeof_char, self.__char_queue, True)

        self.connect(
            self,
            channel_filter,
            self.__make_demodulator(),
            self.__char_sink)
        
        self.connect(
            channel_filter,
            self.__make_audio_filter(),
            blocks.rotator_cc(rotator_inc(self.__demod_rate, 2000 + self.__spacing / 2)),
            blocks.complex_to_real(vlen=1),
            analog.agc2_ff(
                reference=dB(-10),
                attack_rate=8e-1,
                decay_rate=8e-1),
            self)
Example #14
0
    def __init__(self, rate, taps=None, flt_size=32, atten=100):
        gr.hier_block2.__init__(self, "pfb_arb_resampler_ccc",
                                gr.io_signature(1, 1, gr.sizeof_gr_complex), # Input signature
                                gr.io_signature(1, 1, gr.sizeof_gr_complex)) # Output signature

        self._rate = rate
        self._size = flt_size

        if (taps is not None) and (len(taps) > 0):
            self._taps = taps
        else:
            # Create a filter that covers the full bandwidth of the input signal
            bw = 0.4
            tb = 0.2
            ripple = 0.1
            #self._taps = filter.firdes.low_pass_2(self._size, self._size, bw, tb, atten)
            made = False
            while not made:
                try:
                    self._taps = optfir.low_pass(self._size, self._size, bw, bw+tb, ripple, atten)
                    made = True
                except RuntimeError:
                    ripple += 0.01
                    made = False
                    print("Warning: set ripple to %.4f dB. If this is a problem, adjust the attenuation or create your own filter taps." % (ripple))

                    # Build in an exit strategy; if we've come this far, it ain't working.
                    if(ripple >= 1.0):
                        raise RuntimeError("optfir could not generate an appropriate filter.")

        self.pfb = filter.pfb_arb_resampler_ccc(self._rate, self._taps, self._size)
        #print "PFB has %d taps\n" % (len(self._taps),)

        self.connect(self, self.pfb)
        self.connect(self.pfb, self)
Example #15
0
 def __init__(self, n_chans, n_filterbanks=1, taps=None, outchans=None,
              atten=100, bw=1.0, tb=0.2, ripple=0.1):
     if n_filterbanks > n_chans:
         n_filterbanks = n_chans
     if outchans is None:
         outchans = range(n_chans)
     gr.hier_block2.__init__(
         self, "pfb_channelizer_hier_ccf",
         gr.io_signature(1, 1, gr.sizeof_gr_complex),
         gr.io_signature(len(outchans), len(outchans), gr.sizeof_gr_complex))
     if taps is None:
         taps = optfir.low_pass(1, n_chans, bw, bw+tb, ripple, atten)
     taps = list(taps)
     extra_taps = int(math.ceil(1.0*len(taps)/n_chans)*n_chans - len(taps))
     taps = taps + [0] * extra_taps
     # Make taps for each channel
     chantaps = [list(reversed(taps[i: len(taps): n_chans])) for i in range(0, n_chans)]
     # Convert the input stream into a stream of vectors.
     self.s2v = blocks.stream_to_vector(gr.sizeof_gr_complex, n_chans)
     # Create a mapping to separate out each filterbank (a group of channels to be processed together)
     # And a list of sets of taps for each filterbank.
     low_cpp = int(n_chans/n_filterbanks)
     extra = n_chans - low_cpp*n_filterbanks
     cpps = [low_cpp+1]*extra + [low_cpp]*(n_filterbanks-extra)
     splitter_mapping = []
     filterbanktaps = []
     total = 0
     for cpp in cpps:
         splitter_mapping.append([(0, i) for i in range(total, total+cpp)])
         filterbanktaps.append(chantaps[total: total+cpp])
         total += cpp
     assert(total == n_chans)
     # Split the stream of vectors in n_filterbanks streams of vectors.
     self.splitter = blocks.vector_map(gr.sizeof_gr_complex, [n_chans], splitter_mapping)
     # Create the filterbanks
     self.fbs = [filter.filterbank_vcvcf(taps) for taps in filterbanktaps]
     # Combine the streams of vectors back into a single stream of vectors.
     combiner_mapping = [[]]
     for i, cpp in enumerate(cpps):
         for j in range(cpp):
             combiner_mapping[0].append((i, j))
     self.combiner = blocks.vector_map(gr.sizeof_gr_complex, cpps, combiner_mapping)
     # Add the final FFT to the channelizer.
     self.fft = fft.fft_vcc(n_chans, forward=True, window=[1.0]*n_chans)
     # Select the desired channels
     if outchans != range(n_chans):
         selector_mapping = [[(0, i) for i in outchans]]
         self.selector = blocks.vector_map(gr.sizeof_gr_complex, [n_chans], selector_mapping)
     # Convert stream of vectors to a normal stream.
     self.v2ss = blocks.vector_to_streams(gr.sizeof_gr_complex, len(outchans))
     self.connect(self, self.s2v, self.splitter)
     for i in range(0, n_filterbanks):
         self.connect((self.splitter, i), self.fbs[i], (self.combiner, i))
     self.connect(self.combiner, self.fft)
     if outchans != range(n_chans):
         self.connect(self.fft, self.selector, self.v2ss)
     else:
         self.connect(self.fft, self.v2ss)
     for i in range(0, len(outchans)):
         self.connect((self.v2ss, i), (self, i))
Example #16
0
    def __init__(self, sps, channel_decim, channel_taps, options, usrp_rate, channel_rate, lo_freq):
        gr.hier_block2.__init__(self, "rx_channel_cqpsk",
                                gr.io_signature(1, 1, gr.sizeof_gr_complex),
                                gr.io_signature(1, 1, gr.sizeof_float))

        chan = gr.freq_xlating_fir_filter_ccf(int(channel_decim), channel_taps, lo_freq, usrp_rate)

        agc = gr.feedforward_agc_cc(16, 1.0)

        gain_omega = 0.125 * options.gain_mu * options.gain_mu

        alpha = options.costas_alpha
        beta = 0.125 * alpha * alpha
        fmin = -0.025
        fmax =  0.025

        clock = repeater.gardner_costas_cc(sps, options.gain_mu, gain_omega, alpha, beta, fmax, fmin)

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

        # take angle of the difference (in radians)
        to_float = gr.complex_to_arg()

        # convert from radians such that signal is in -3/-1/+1/+3
        rescale = gr.multiply_const_ff( (1 / (pi / 4)) )

        self.connect (self, chan, agc, clock, diffdec, to_float, rescale, self)
Example #17
0
    def __init__(self, sps, channel_decim, channel_taps, options, usrp_rate, channel_rate, lo_freq, max_dev, ctcss):
        gr.hier_block2.__init__(self, "rx_channel_nfm",
                                gr.io_signature(1, 1, gr.sizeof_gr_complex),
#                               gr.io_signature(0, 0, 0))
                                gr.io_signature(1, 1, gr.sizeof_float))

        output_sample_rate = 8000

        chan = gr.freq_xlating_fir_filter_ccf(int(channel_decim), channel_taps, lo_freq, usrp_rate)

        nphases = 32
        frac_bw = 0.45
        rs_taps = gr.firdes.low_pass(nphases, nphases, frac_bw, 0.5-frac_bw)

        resampler = blks2.pfb_arb_resampler_ccf(
           float(output_sample_rate)/channel_rate,
           (rs_taps),
           nphases
        )

        # FM Demodulator  input: complex; output: float
        k = output_sample_rate/(2*math.pi*max_dev)
        fm_demod = gr.quadrature_demod_cf(k)

        self.connect (self, chan, resampler, fm_demod)
        if ctcss > 0:
            level = 5.0
            len = 0
            ramp = 0
            gate = True
            ctcss = repeater.ctcss_squelch_ff(output_sample_rate, ctcss, level, len, ramp, gate)
            self.connect (fm_demod, ctcss, self)
        else:
            self.connect (fm_demod, self)
Example #18
0
 def __init__(self, modulator, audio_rate, rf_rate, freq):
     modulator = IModulator(modulator)
     
     gr.hier_block2.__init__(
         self, 'SimulatedChannel',
         gr.io_signature(1, 1, gr.sizeof_float * 1),
         gr.io_signature(1, 1, gr.sizeof_gr_complex * 1),
     )
     
     self.__freq = freq
     self.__rf_rate = rf_rate
     self.__modulator = modulator
     
     modulator_input_type = modulator.get_input_type()
     if modulator_input_type.get_kind() == 'MONO':
         audio_resampler = make_resampler(audio_rate, modulator_input_type.get_sample_rate())
         self.connect(self, audio_resampler, modulator)
     elif modulator_input_type.get_kind() == 'NONE':
         self.connect(self, blocks.null_sink(gr.sizeof_float))
     else:
         raise Exception('don\'t know how to supply input of type %s' % modulator_input_type)
     
     rf_resampler = rational_resampler.rational_resampler_ccf(
         interpolation=int(rf_rate),
         decimation=int(modulator.get_output_type().get_sample_rate()))
     self.__rotator = blocks.rotator_cc(rotator_inc(rate=rf_rate, shift=freq))
     self.__mult = blocks.multiply_const_cc(dB(-10))
     self.connect(modulator, rf_resampler, self.__rotator, self.__mult, self)
Example #19
0
    def __init__(self, sps, channel_decim, channel_taps, options, usrp_rate, channel_rate, lo_freq):
        gr.hier_block2.__init__(self, "rx_channel_fm",
                                gr.io_signature(1, 1, gr.sizeof_gr_complex),
                                gr.io_signature(1, 1, gr.sizeof_float))

        chan = gr.freq_xlating_fir_filter_ccf(int(channel_decim), channel_taps, lo_freq, usrp_rate)

        symbol_decim = 1
        symbol_rate = 4800

        self.symbol_deviation = 600.0
        fm_demod_gain = channel_rate / (2.0 * pi * self.symbol_deviation)
        fm_demod = gr.quadrature_demod_cf(fm_demod_gain)

        symbol_coeffs = gr.firdes_root_raised_cosine(1.0,
                                                     channel_rate,
                                                     symbol_rate, 
                                                     1.0,
                                                     51)
        symbol_filter = gr.fir_filter_fff(symbol_decim, symbol_coeffs)

        # C4FM demodulator
        autotuneq = gr.msg_queue(2)
        demod_fsk4 = fsk4.demod_ff(autotuneq, channel_rate, symbol_rate)
 
        self.connect (self, chan, fm_demod, symbol_filter, demod_fsk4, self)
Example #20
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._clockrec_gain = options[ "clockrec_gain" ]
        self._omega_relative_limit = options[ "omega_relative_limit" ]
        self.fftlen = options[ "fftlen" ]
        self.freq_sync = gmsk_sync.square_and_fft_sync_cc(self._samplerate, self._bits_per_sec, self.fftlen)
        self.agc = analog.feedforward_agc_cc(512, 2)
        self.preamble = [1,1,0,0]*7
        self.mod = digital.gmsk_mod(self._samples_per_symbol, 0.4)
        self.mod_vector = ais.modulate_vector_bc(self.mod.to_basic_block(), self.preamble, [1])
        self.preamble_detect = ais.corr_est_cc(self.mod_vector,
                                               self._samples_per_symbol,
                                               1, #mark delay
                                               0.9) #threshold
        self.clockrec = ais.msk_timing_recovery_cc(self._samples_per_symbol,
                                                       self._clockrec_gain, #gain
                                                       self._omega_relative_limit, #error lim
                                                       1) #output sps

        sensitivity = (math.pi / 2)
        self.demod = analog.quadrature_demod_cf(sensitivity) #param is gain
        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)

        self.connect(self, self.freq_sync, self.agc, (self.preamble_detect, 0), self.clockrec, self.demod, self.slicer, self.diff, self.invert, self)
Example #21
0
    def __init__(self, mode, input_rate, output_rate, mod_class=None):
        gr.hier_block2.__init__(
            self, type(self).__name__,
            gr.io_signature(1, 1, gr.sizeof_float),
            gr.io_signature(1, 1, gr.sizeof_gr_complex))
        
        if mod_class is None:
            mode_def = lookup_mode(mode)
            if mode_def is None:
                raise Exception('{}: No modulator registered for mode {!r}, only {!r}'.format(
                    type(self).__name__, mode, [md.mode for md in get_modes() if md.mod_class]))
            mod_class = mode_def.mod_class
        
        context = _ModulatorAdapterContext(adapter=self)
        
        modulator = self.__modulator = IModulator(mod_class(
            mode=mode,
            context=context))

        self.__connect_with_resampling(
            self, input_rate,
            modulator, modulator.get_input_type().get_sample_rate(),
            False)
        self.__connect_with_resampling(
            modulator, modulator.get_output_type().get_sample_rate(),
            self, output_rate,
            True)
Example #22
0
	def __init__(self,
			device_name,
			sample_rate,
			quadrature_as_stereo):
		self.__device_name = device_name
		self.__sample_rate = sample_rate
		self.__quadrature_as_stereo = quadrature_as_stereo
		
		if self.__quadrature_as_stereo:
			self.__signal_type = SignalType(
				kind='IQ',
				sample_rate=self.__sample_rate)
		else:
			self.__signal_type = SignalType(
				kind='USB',  # TODO obtain correct type from config (or say hamlib)
				sample_rate=self.__sample_rate)
		
		gr.hier_block2.__init__(
			self, type(self).__name__,
			gr.io_signature(0, 0, 0),
			gr.io_signature(1, 1, gr.sizeof_gr_complex * 1),
		)
		
		self.__source = audio.source(
			self.__sample_rate,
			device_name=self.__device_name,
			ok_to_block=True)
		
		combine = blocks.float_to_complex(1)
		self.connect(self.__source, combine, self)
		if self.__quadrature_as_stereo:
			# if we don't do this, the imaginary component is 0 and the spectrum is symmetric
			self.connect((self.__source, 1), (combine, 1))
Example #23
0
    def __init__(self,
                 sps,               # Samples per symbol
                 excess_bw,         # RRC filter excess bandwidth (typically 0.35-0.5)
                 amplitude,         # DAC output level, 0-32767, typically 2000-8000
                 vector_source,   # Indicate if it's the infinite sequence of 1, or by use the code to change the amplitude
                 ):

            gr.hier_block2.__init__(self, "bpsk_modulator",
                                gr.io_signature(0, 0, 0),                    # Input signature
                                gr.io_signature(1, 1, gr.sizeof_gr_complex)) # Output signature
            
            # Create BERT data bit stream	
            
            self.vector_source = vector_source
            
            self._scrambler = gr.scrambler_bb(0x8A, 0x7F, 31) # CCSDS 7-bit scrambler
            
            # Map to constellation
            self._constellation = [-1+0j, 1+0j]
            self._mapper = gr.chunks_to_symbols_bc(self._constellation)	
            
            # Create RRC with specified excess bandwidth
            taps = gr.firdes.root_raised_cosine(sps,  # Gain
					    sps,	    # Sampling rate
					    1.0,	    # Symbol rate
					    excess_bw,	    # Roll-off factor
					    11*sps)         # Number of taps
            
            self._rrc = gr.interp_fir_filter_ccf(sps,	    # Interpolation rate
					     taps)	    # FIR taps
            
            self.amp = gr.multiply_const_cc(amplitude)
            
            # Wire block inputs and outputs
            self.connect(self.vector_source, self._scrambler, self._mapper, self._rrc, self.amp, self)
Example #24
0
 def test_005_connect_invalid_src_port_exceeds(self):
     hblock = gr.hier_block2("test_block",
                             gr.io_signature(1,1,gr.sizeof_int),
                             gr.io_signature(1,1,gr.sizeof_int))
     nop1 = blocks.nop(gr.sizeof_int)
     self.assertRaises(RuntimeError,
         lambda: hblock.connect((hblock, 1), nop1))
Example #25
0
    def __init__(self, queue, freq=0.0, verbose=False, log=False):
	gr.hier_block2.__init__(self, "flex_demod",
				gr.io_signature(1, 1, gr.sizeof_gr_complex),
				gr.io_signature(0,0,0))

        k = 25000/(2*pi*1600)        # 4800 Hz max deviation
        quad = gr.quadrature_demod_cf(k)
	self.connect(self, quad)
	
        rsamp = blks2.rational_resampler_fff(16, 25)
        self.slicer = pager_swig.slicer_fb(5e-6) # DC removal averaging filter constant
	self.sync = pager_swig.flex_sync()

        self.connect(quad, rsamp, self.slicer, self.sync)

	for i in range(4):
	    self.connect((self.sync, i), pager_swig.flex_deinterleave(), pager_swig.flex_parse(queue, freq))

	if log:
	    suffix = '_'+ "%3.3f" % (freq/1e6,) + '.dat'
	    quad_sink = gr.file_sink(gr.sizeof_float, 'quad'+suffix)
	    rsamp_sink = gr.file_sink(gr.sizeof_float, 'rsamp'+suffix)
	    slicer_sink = gr.file_sink(gr.sizeof_char, 'slicer'+suffix)
	    self.connect(rsamp, rsamp_sink)
	    self.connect(quad, quad_sink)
	    self.connect(self.slicer, slicer_sink)
Example #26
0
 def test_024_disconnect_single(self):
     hblock = gr.top_block("test_block")
     blk = gr.hier_block2("block",
                          gr.io_signature(0, 0, 0),
                          gr.io_signature(0, 0, 0))
     hblock.connect(blk)
     hblock.disconnect(blk)
Example #27
0
 def test_025_disconnect_single_not_connected(self):
     hblock = gr.top_block("test_block")
     blk = gr.hier_block2("block",
                          gr.io_signature(0, 0, 0),
                          gr.io_signature(0, 0, 0))
     self.assertRaises(RuntimeError,
                       lambda: hblock.disconnect(blk))
Example #28
0
 def __init__(self, dest, key):
     gr.hier_block2.__init__(
         self, self.__class__.__name__,
         gr.io_signature(1, 1, gr.sizeof_gr_complex * 1),
         gr.io_signature(1, 1, gr.sizeof_gr_complex * 1))
     self.__dest = dest
     self.__key = key
Example #29
0
 def test_022_connect_single_with_ports(self):
     hblock = gr.top_block("test_block")
     blk = gr.hier_block2("block",
                          gr.io_signature(1, 1, 1),
                          gr.io_signature(1, 1, 1))
     self.assertRaises(RuntimeError,
                       lambda: hblock.connect(blk))
Example #30
0
	def __init__(self,
			device_name,
			sample_rate,
			quadrature_as_stereo):
		self.__device_name = device_name
		self.__sample_rate = sample_rate
		self.__quadrature_as_stereo = quadrature_as_stereo
		
		self.__signal_type = SignalType(
			# TODO: type should be able to be LSB
			kind='IQ' if quadrature_as_stereo else 'USB',
			sample_rate=self.__sample_rate)
		
		gr.hier_block2.__init__(
			self, type(self).__name__,
			gr.io_signature(1, 1, gr.sizeof_gr_complex * 1),
			gr.io_signature(0, 0, 0),
		)
		
		sink = audio.sink(
			self.__sample_rate,
			device_name=self.__device_name,
			ok_to_block=True)
		
		split = blocks.complex_to_float(1)
		self.connect(self, split, (sink, 0))
		self.connect((split, 1), (sink, 1))
Example #31
0
    def __init__(self,
                 samples_per_symbol=_def_samples_per_symbol,
                 excess_bw=_def_excess_bw,
                 gray_code=_def_gray_code,
                 verbose=_def_verbose,
                 log=_def_log):
        """
	Hierarchical block for RRC-filtered QPSK modulation.

	The input is a byte stream (unsigned char) and the
	output is the complex modulated signal at baseband.

	@param samples_per_symbol: samples per symbol >= 2
	@type samples_per_symbol: integer
	@param excess_bw: Root-raised cosine filter excess bandwidth
	@type excess_bw: 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,
            "qam64_mod",
            gr.io_signature(1, 1, gr.sizeof_char),  # Input signature
            gr.io_signature(1, 1, gr.sizeof_gr_complex))  # Output signature
        self._samples_per_symbol = samples_per_symbol
        self._excess_bw = excess_bw
        self._gray_code = gray_code

        if not isinstance(samples_per_symbol, int) or samples_per_symbol < 2:
            raise TypeError, ("sbp must be an integer >= 2, is %d" %
                              samples_per_symbol)

        ntaps = 11 * samples_per_symbol

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

        # turn bytes into k-bit vectors
        self.bytes2chunks = \
          gr.packed_to_unpacked_bb(self.bits_per_symbol(), gr.GR_MSB_FIRST)

        if self._gray_code:
            self.symbol_mapper = gr.map_bb(qam.binary_to_gray[arity])
        else:
            self.symbol_mapper = gr.map_bb(qam.binary_to_ungray[arity])

        self.diffenc = gr.diff_encoder_bb(arity)

        rot = 1.0
        print "constellation with %d arity" % arity
        rotated_const = map(lambda pt: pt * rot, qam.constellation[arity])
        self.chunks2symbols = gr.chunks_to_symbols_bc(rotated_const)

        # pulse shaping filter
        self.rrc_taps = gr.firdes.root_raised_cosine(
            self.
            _samples_per_symbol,  # gain  (sps since we're interpolating by sps)
            self._samples_per_symbol,  # sampling rate
            1.0,  # symbol rate
            self._excess_bw,  # excess bandwidth (roll-off factor)
            ntaps)

        self.rrc_filter = gr.interp_fir_filter_ccf(self._samples_per_symbol,
                                                   self.rrc_taps)

        if verbose:
            self._print_verbage()

        if log:
            self._setup_logging()

# Connect
        self.connect(self, self.bytes2chunks, self.symbol_mapper, self.diffenc,
                     self.chunks2symbols, self.rrc_filter, self)
Example #32
0
    def __init__(self, options, msgq_limit=2, pad_for_usrp=True):
        """
	Hierarchical block for sending packets

        Packets to be sent are enqueued by calling send_pkt.
        The output is the complex modulated signal at baseband.

        Args:
            options: pass modulation options from higher layers (fft length, occupied tones, etc.)
            msgq_limit: maximum number of messages in message queue (int)
            pad_for_usrp: If true, packets are padded such that they end up a multiple of 128 samples
        """

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

        self._pad_for_usrp = pad_for_usrp
        self._modulation = options.modulation
        self._fft_length = options.fft_length
        self._occupied_tones = options.occupied_tones
        self._cp_length = options.cp_length

        win = []  #[1 for i in range(self._fft_length)]

        # Use freq domain to get doubled-up known symbol for correlation in time domain
        zeros_on_left = int(
            math.ceil((self._fft_length - self._occupied_tones) / 2.0))
        ksfreq = known_symbols_4512_3[0:self._occupied_tones]
        for i in range(len(ksfreq)):
            if ((zeros_on_left + i) & 1):
                ksfreq[i] = 0

        # hard-coded known symbols
        preambles = (ksfreq, )

        padded_preambles = list()
        for pre in preambles:
            padded = self._fft_length * [
                0,
            ]
            padded[zeros_on_left:zeros_on_left + self._occupied_tones] = pre
            padded_preambles.append(padded)

        symbol_length = options.fft_length + options.cp_length

        mods = {
            "bpsk": 2,
            "qpsk": 4,
            "8psk": 8,
            "qam8": 8,
            "qam16": 16,
            "qam64": 64,
            "qam256": 256
        }
        arity = mods[self._modulation]

        rot = 1
        if self._modulation == "qpsk":
            rot = (0.707 + 0.707j)

        # FIXME: pass the constellation objects instead of just the points
        if (self._modulation.find("psk") >= 0):
            constel = psk.psk_constellation(arity)
            rotated_const = map(lambda pt: pt * rot, constel.points())
        elif (self._modulation.find("qam") >= 0):
            constel = qam.qam_constellation(arity)
            rotated_const = map(lambda pt: pt * rot, constel.points())
        #print rotated_const
        self._pkt_input = digital.ofdm_mapper_bcv(rotated_const, msgq_limit,
                                                  options.occupied_tones,
                                                  options.fft_length)

        self.preambles = digital.ofdm_insert_preamble(self._fft_length,
                                                      padded_preambles)
        self.ifft = fft.fft_vcc(self._fft_length, False, win, True)
        self.cp_adder = digital.ofdm_cyclic_prefixer(self._fft_length,
                                                     symbol_length)
        self.scale = blocks.multiply_const_cc(1.0 /
                                              math.sqrt(self._fft_length))

        self.connect((self._pkt_input, 0), (self.preambles, 0))
        self.connect((self._pkt_input, 1), (self.preambles, 1))
        self.connect(self.preambles, self.ifft, self.cp_adder, self.scale,
                     self)
Example #33
0
class receiver(gr.hier_block2):
	def __init__(self):
		gr.hier_block2.__init__(self, "ofdm_tx",
					gr.io_signature(1, 1, gr.sizeof_gr_complex),
					gr.io_signature(1, 1, gr.sizeof_char))
Example #34
0
    def __init__(self, mode='433', input_rate=0, context=None):
        assert input_rate > 0
        assert context is not None
        gr.hier_block2.__init__(self,
                                type(self).__name__,
                                gr.io_signature(1, 1, gr.sizeof_gr_complex),
                                gr.io_signature(0, 0, 0))

        # The input bandwidth chosen is not primarily determined by the bandwidth of the input signals, but by the frequency error of the transmitters. Therefore it is not too critical, and we can choose the exact rate to make the filtering easy.
        if input_rate <= upper_preferred_demod_rate:
            # Skip having a filter at all.
            self.__band_filter = None
            demod_rate = input_rate
        else:
            # TODO: This gunk is very similar to the stuff that MultistageChannelFilter does. See if we can share some code.
            lower_rate = input_rate
            lower_rate_prev = None
            while lower_rate > upper_preferred_demod_rate and lower_rate != lower_rate_prev:
                lower_rate_prev = lower_rate
                if lower_rate % 5 == 0 and lower_rate > upper_preferred_demod_rate * 3:
                    lower_rate /= 5
                elif lower_rate % 2 == 0:
                    lower_rate /= 2
                else:
                    # non-integer ratio
                    lower_rate = upper_preferred_demod_rate
                    break
            demod_rate = lower_rate

            self.__band_filter = MultistageChannelFilter(
                input_rate=input_rate,
                output_rate=demod_rate,
                cutoff_freq=demod_rate * 0.4,
                transition_width=demod_rate * 0.2)

        # Subprocess
        # using /usr/bin/env because twisted spawnProcess doesn't support path search
        # pylint: disable=no-member
        self.__process = the_reactor.spawnProcess(
            RTL433ProcessProtocol(context.output_message, self.__log),
            '/usr/bin/env',
            env=None,  # inherit environment
            args=[
                b'env',
                b'rtl_433',
                b'-F',
                b'json',
                b'-r',
                b'-',  # read from stdin
                b'-m',
                b'3',  # complex float input
                b'-s',
                str(demod_rate),
                b'-q'  # quiet mode, suppress "Registering protocol..." stderr flood
            ],
            childFDs={
                0: 'w',
                1: 'r',
                2: 2
            })
        sink = make_sink_to_process_stdin(self.__process,
                                          itemsize=gr.sizeof_gr_complex)

        agc = analog.agc2_cc(reference=dB(-4))
        agc.set_attack_rate(200 / demod_rate)
        agc.set_decay_rate(200 / demod_rate)

        if self.__band_filter:
            self.connect(self, self.__band_filter, agc)
        else:
            self.connect(self, agc)
        self.connect(agc, sink)
Example #35
0
    def __init__(self,
                 input_rate=None,
                 demod_type='cqpsk',
                 filter_type=None,
                 excess_bw=_def_excess_bw,
                 relative_freq=0,
                 offset=0,
                 if_rate=_def_if_rate,
                 gain_mu=_def_gain_mu,
                 costas_alpha=_def_costas_alpha,
                 symbol_rate=_def_symbol_rate):
        """
	Hierarchical block for P25 demodulation.

	The complex input is tuned, decimated and demodulated
        @param input_rate: sample rate of complex input channel
        @type input_rate: int
	"""

        gr.hier_block2.__init__(
            self,
            "p25_demod_cb",
            gr.io_signature(1, 1, gr.sizeof_gr_complex),  # Input signature
            gr.io_signature(1, 1, gr.sizeof_char))  # Output signature
        #				gr.io_signature(0, 0, 0)) # Output signature
        p25_demod_base.__init__(self,
                                if_rate=if_rate,
                                symbol_rate=symbol_rate,
                                filter_type=filter_type)

        self.input_rate = input_rate
        self.if_rate = if_rate
        self.symbol_rate = symbol_rate
        self.connect_state = None
        self.offset = 0
        self.sps = 0.0
        self.lo_freq = 0
        self.float_sink = None
        self.complex_sink = None
        self.if1 = 0
        self.if2 = 0
        self.t_cache = {}
        if filter_type == 'rrc':
            self.set_baseband_gain(0.61)

        self.mixer = blocks.multiply_cc()
        decimator_values = get_decim(input_rate)
        if decimator_values:
            self.decim, self.decim2 = decimator_values
            self.if1 = input_rate / self.decim
            self.if2 = self.if1 / self.decim2
            sys.stderr.write(
                'Using two-stage decimator for speed=%d, decim=%d/%d if1=%d if2=%d\n'
                % (input_rate, self.decim, self.decim2, self.if1, self.if2))
            bpf_coeffs = filter.firdes.complex_band_pass(
                1.0, input_rate, -self.if1 / 2, self.if1 / 2, self.if1 / 2,
                filter.firdes.WIN_HAMMING)
            self.t_cache[0] = bpf_coeffs
            fa = 6250
            fb = self.if2 / 2
            if filter_type == 'nxdn' and self.symbol_rate == 2400:  # nxdn48 6.25 KHz
                fa = 3125
            lpf_coeffs = filter.firdes.low_pass(1.0, self.if1, (fb + fa) / 2,
                                                fb - fa,
                                                filter.firdes.WIN_HAMMING)
            self.bpf = filter.fir_filter_ccc(self.decim, bpf_coeffs)
            self.lpf = filter.fir_filter_ccf(self.decim2, lpf_coeffs)
            resampled_rate = self.if2
            self.relative_limit = (input_rate // 2) - (self.if1 // 2)
            self.bfo = analog.sig_source_c(self.if1, analog.GR_SIN_WAVE, 0,
                                           1.0, 0)
            self.connect(self, self.bpf, (self.mixer, 0))
            self.connect(self.bfo, (self.mixer, 1))
        else:
            sys.stderr.write(
                'Unable to use two-stage decimator for speed=%d\n' %
                (input_rate))
            # local osc
            self.lo = analog.sig_source_c(input_rate, analog.GR_SIN_WAVE, 0,
                                          1.0, 0)
            f1 = 7250
            f2 = 1450
            if filter_type == 'nxdn' and self.symbol_rate == 2400:  # nxdn48 6.25 KHz
                f1 = 3125
                f2 = 625
            lpf_coeffs = filter.firdes.low_pass(1.0, input_rate, f1, f2,
                                                filter.firdes.WIN_HANN)
            decimation = int(input_rate / if_rate)
            self.lpf = filter.fir_filter_ccf(decimation, lpf_coeffs)
            resampled_rate = float(input_rate) / float(
                decimation)  # rate at output of self.lpf
            self.relative_limit = (input_rate // 2) - f1
            self.connect(self, (self.mixer, 0))
            self.connect(self.lo, (self.mixer, 1))
        self.connect(self.mixer, self.lpf)

        if self.if_rate != resampled_rate:
            self.if_out = filter.pfb.arb_resampler_ccf(
                float(self.if_rate) / resampled_rate)
            self.connect(self.lpf, self.if_out)
        else:
            self.if_out = self.lpf

        fa = 6250
        fb = fa + 625
        cutoff_coeffs = filter.firdes.low_pass(1.0, self.if_rate,
                                               (fb + fa) / 2, fb - fa,
                                               filter.firdes.WIN_HANN)
        self.cutoff = filter.fir_filter_ccf(1, cutoff_coeffs)

        omega = float(self.if_rate) / float(self.symbol_rate)
        gain_omega = 0.1 * gain_mu * gain_mu

        alpha = costas_alpha
        beta = 0.125 * alpha * alpha
        fmax = 2400  # Hz
        fmax = 2 * pi * fmax / float(self.if_rate)

        self.clock = op25_repeater.gardner_costas_cc(omega, gain_mu,
                                                     gain_omega, alpha, beta,
                                                     fmax, -fmax)

        self.agc = analog.feedforward_agc_cc(16, 1.0)

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

        # take angle of the difference (in radians)
        self.to_float = blocks.complex_to_arg()

        # convert from radians such that signal is in -3/-1/+1/+3
        self.rescale = blocks.multiply_const_ff((1 / (pi / 4)))

        # fm demodulator (needed in fsk4 case)
        fm_demod_gain = if_rate / (2.0 * pi * _def_symbol_deviation)
        self.fm_demod = analog.quadrature_demod_cf(fm_demod_gain)

        self.connect_chain(demod_type)
        self.connect(self.slicer, self)

        self.set_relative_frequency(relative_freq)
Example #36
0
 def __init__(
     self,
     verbose_mode=True,
     radio_device_name="/dev/ndr47x",
     radio_baud_rate=921600,
     gig_iface_to_use="eth0",
     num_tuners=1,
     tuner1_param_list=[False, 900e6, 0],
     tuner2_param_list=[False, 900e6, 0],
     num_wbddcs=1,
     wbddc1_param_list=[40001, 0, 0, False, 0e6],
     wbddc2_param_list=[40002, 0, 0, False, 0e6],
     tagged=False,
 ):
     gr.hier_block2.__init__(
         self,
         "[CyberRadio] NDR472 Source",
         gr.io_signature(0, 0, 0),
         gr.io_signaturev(num_wbddcs + 1, num_wbddcs + 1,
                          [gr.sizeof_char * 1] +
                          num_wbddcs * [gr.sizeof_gr_complex * 1]),
     )
     self.verbose_mode = verbose_mode
     self.radio_device_name = radio_device_name
     self.radio_baud_rate = radio_baud_rate
     self.gig_iface_to_use = gig_iface_to_use
     self.udp_host_name = CyberRadioDriver.getInterfaceAddresses(
         self.gig_iface_to_use)[1]
     self.num_tuners = num_tuners
     self.tuner1_param_list = tuner1_param_list
     self.tuner2_param_list = tuner2_param_list
     self.num_wbddcs = num_wbddcs
     self.wbddc1_param_list = wbddc1_param_list
     self.wbddc2_param_list = wbddc2_param_list
     self.tagged = tagged
     self.CyberRadio_file_like_object_source_0 = CyberRadio.file_like_object_source(
     )
     self.connect((self.CyberRadio_file_like_object_source_0, 0), (self, 0))
     self.CyberRadio_NDR_driver_interface_0 = CyberRadio.NDR_driver_interface(
         radio_type="ndr472",
         verbose=verbose_mode,
         log_file=self.CyberRadio_file_like_object_source_0,
         connect_mode="tty",
         dev_name=radio_device_name,
         baud_rate=radio_baud_rate,
     )
     self.vita_tail_size = self.CyberRadio_NDR_driver_interface_0.getVitaTailSize(
     )
     self.vita_payload_size = self.CyberRadio_NDR_driver_interface_0.getVitaPayloadSize(
     )
     self.vita_header_size = self.CyberRadio_NDR_driver_interface_0.getVitaHeaderSize(
     )
     self.iq_swapped = self.CyberRadio_NDR_driver_interface_0.isIqSwapped()
     self.byte_swapped = self.CyberRadio_NDR_driver_interface_0.isByteswapped(
     )
     self._set_udp_dest_info()
     if self.num_tuners >= 1:
         self._set_tuner_param_list(1, tuner1_param_list)
     if self.num_tuners >= 2:
         self._set_tuner_param_list(2, tuner2_param_list)
     self.wbddc_sources = {}
     if self.num_wbddcs >= 1:
         self.CyberRadio_vita_iq_source_wbddc_1 = self._get_configured_wbddc(
             1, wbddc1_param_list)
         self.connect((self.CyberRadio_vita_iq_source_wbddc_1, 0),
                      (self, 1))
         self.wbddc_sources[1] = self.CyberRadio_vita_iq_source_wbddc_1
     if self.num_wbddcs >= 2:
         self.CyberRadio_vita_iq_source_wbddc_2 = self._get_configured_wbddc(
             2, wbddc2_param_list)
         self.connect((self.CyberRadio_vita_iq_source_wbddc_2, 0),
                      (self, 2))
         self.wbddc_sources[2] = self.CyberRadio_vita_iq_source_wbddc_2
Example #37
0
    def __init__(self, options, log=False):

        ## Read configuration
        config = station_configuration()

        fft_length = config.fft_length
        #cp_length     = config.cp_length
        block_header = config.training_data
        data_subc = config.data_subcarriers
        virtual_subc = config.virtual_subcarriers
        total_subc = config.subcarriers
        block_length = config.block_length
        frame_length = config.frame_length

        L = block_header.mm_periodic_parts

        cp_length = config.cp_length

        print "data_subc: ", config.data_subcarriers
        print "total_subc: ", config.subcarriers
        print "frame_lengthframe_length: ", frame_length

        ## Set Input/Output signature
        gr.hier_block2.__init__(
            self,
            "fbmc_inner_receiver",
            gr.io_signature(1, 1, gr.sizeof_gr_complex),
            gr.io_signaturev(
                4,
                4,
                [
                    gr.sizeof_float * total_subc,  # Normalized |CTF|^2 
                    gr.sizeof_char,  # Frame start
                    gr.sizeof_gr_complex * total_subc,  # OFDM blocks, SNR est
                    gr.sizeof_float
                ]))  # CFO

        ## Input and output ports
        self.input = rx_input = self

        out_ofdm_blocks = (self, 2)
        out_frame_start = (self, 1)
        out_disp_ctf = (self, 0)
        out_disp_cfo = (self, 3)
        #out_snr_pream    = ( self, 3 )

        ## pre-FFT processing
        '''
    ## Compute autocorrelations for S&C preamble
    ## and cyclic prefix
    
    self._sc_metric = sc_metric = autocorrelator( fft_length/2, fft_length/2 )
    self._gi_metric = gi_metric = autocorrelator( fft_length, cp_length )
    
    self.connect( rx_input, sc_metric )
    self.connect( rx_input, gi_metric )
    terminate_stream(self, gi_metric)
    
    ## Sync. Output contains OFDM blocks
    sync = ofdm.time_sync( fft_length/2, 1)
    self.connect( rx_input, ( sync, 0 ) )
    self.connect( sc_metric, ( sync, 1 ) )
    self.connect( sc_metric, ( sync, 2 ) )
    
    ofdm_blocks = ( sync, 0 )
    frame_start = ( sync, 1 )
    log_to_file( self, ( sync, 1 ), "data/fbmc_peak_detector.char" )
    '''
        if options.ideal is False and options.ideal2 is False:
            #Testing old/new metric
            self.tm = schmidl.recursive_timing_metric(2 * fft_length)
            self.connect(self.input, self.tm)
            #log_to_file( self, self.tm, "data/fbmc_rec_sc_metric_ofdm.float" )

            timingmetric_shift = 0  #-2 #int(-cp_length * 0.8)
            tmfilter = filter.fft_filter_fff(
                1, [2. / fft_length] * (fft_length / 2)
            )  # ofdm.lms_fir_ff( fft_length, 1e-3 ) #; filter.fir_filter_fff(1, [1./fft_length]*fft_length)
            self.connect(self.tm, tmfilter)
            self.tm = tmfilter
            #log_to_file( self, self.tm, "data/fbmc_rec_sc_metric_ofdm2.float" )

            self._pd_thres = 0.6
            self._pd_lookahead = fft_length  # empirically chosen
            peak_detector = ofdm.peak_detector_02_fb(self._pd_lookahead,
                                                     self._pd_thres)
            self.connect(self.tm, peak_detector)
            #log_to_file( self, peak_detector, "data/fbmc_rec_peak_detector.char" )

            #frame_start = [0]*frame_length
            #frame_start[0] = 1
            #frame_start = blocks.vector_source_b(frame_start,True)

            #OLD
            #delayed_timesync = blocks.delay(gr.sizeof_char,
            #                           (frame_length-10)*fft_length/2 - fft_length/4 -1 + timingmetric_shift)
            delayed_timesync = blocks.delay(
                gr.sizeof_char,
                (frame_length - 10) * fft_length / 2 - fft_length / 4 +
                int(2.5 * fft_length) + timingmetric_shift - 1)
            #delayed_timesync = blocks.delay(gr.sizeof_char,
            #(frame_length-10)*fft_length/2 - fft_length/4 + int(3.5*fft_length)  + timingmetric_shift-1)
            self.connect(peak_detector, delayed_timesync)

            self.block_sampler = ofdm.vector_sampler(
                gr.sizeof_gr_complex, fft_length / 2 * frame_length)

            self.connect(self.input, self.block_sampler)
            self.connect(delayed_timesync, (self.block_sampler, 1))
            #log_to_file( self, self.block_sampler, "data/fbmc_block_sampler.compl" )

            vt2s = blocks.vector_to_stream(gr.sizeof_gr_complex * fft_length,
                                           frame_length / 2)
            self.connect(self.block_sampler, vt2s)
            #terminate_stream(self,ofdm_blocks)

            ofdm_blocks = vt2s
            '''
        # TODO: dynamic solution
        vt2s = blocks.vector_to_stream(gr.sizeof_gr_complex*block_length/2,
                                                frame_length)
        self.connect(self.block_sampler,vt2s)
        terminate_stream(self,( sync, 0 ))
        ofdm_blocks = vt2s
        '''

            ##stv_help = blocks.stream_to_vector(gr.sizeof_gr_complex*config.fft_length/2, 1)
            #stv_help = blocks.vector_to_stream(gr.sizeof_gr_complex*config.fft_length/2, 2)
            ##self.connect(ofdm_blocks, stv_help)
            ##ofdm_blocks = stv_help
            #ofdm_blocks = ( sync, 0 )
            #frame_start = ( sync, 1 )
            #log_to_file(self, frame_start, "data/frame_start.compl")

            #log_to_file( self, sc_metric, "data/sc_metric.float" )
            #log_to_file( self, gi_metric, "data/gi_metric.float" )
            #log_to_file( self, (sync,1), "data/sync.float" )

            #    log_to_file(self,ofdm_blocks,"data/ofdm_blocks_original.compl")
            frame_start = [0] * int(frame_length / 2)
            frame_start[0] = 1
            frame_start = blocks.vector_source_b(frame_start, True)

            #frame_start2 = [0]*int(frame_length/2)
            #frame_start2[0] = 1
            #frame_start2 = blocks.vector_source_b(frame_start2,True)

        if options.disable_time_sync or options.ideal or options.ideal2:
            if options.ideal is False and options.ideal2 is False:
                terminate_stream(self, ofdm_blocks)
                terminate_stream(self, frame_start)

            serial_to_parallel = blocks.stream_to_vector(
                gr.sizeof_gr_complex, fft_length)
            #discard_cp = ofdm.vector_mask(block_length,cp_length,fft_length,[])
            #serial_to_parallel = blocks.stream_to_vector(gr.sizeof_gr_complex,block_length)
            #discard_cp = ofdm.vector_mask(block_length,cp_length,fft_length,[])
            #self.connect( rx_input,serial_to_parallel)

            #self.connect( rx_input, blocks.delay(gr.sizeof_gr_complex,0),serial_to_parallel)
            initial_skip = blocks.skiphead(gr.sizeof_gr_complex,
                                           2 * fft_length)
            self.connect(rx_input, initial_skip)
            if options.ideal is False and options.ideal2 is False:
                self.connect(initial_skip, serial_to_parallel)
                ofdm_blocks = serial_to_parallel
            else:
                ofdm_blocks = initial_skip
            #self.connect( rx_input, serial_to_parallel, discard_cp )

            frame_start = [0] * int(frame_length / 2)
            frame_start[0] = 1
            frame_start = blocks.vector_source_b(frame_start, True)

            #frame_start2 = [0]*int(frame_length/2)
            #frame_start2[0] = 1
            #frame_start2 = blocks.vector_source_b(frame_start2,True)

            print "Disabled time synchronization stage"

        print "\t\t\t\t\tframe_length = ", frame_length

        if options.ideal is False and options.ideal2 is False:
            ## Extract preamble, feed to Morelli & Mengali frequency offset estimator
            assert (block_header.mm_preamble_pos == 0)
            morelli_foe = ofdm.mm_frequency_estimator(fft_length, 2, 1,
                                                      config.fbmc)
            sampler_preamble = ofdm.vector_sampler(
                gr.sizeof_gr_complex * fft_length, 1)
            self.connect(ofdm_blocks, (sampler_preamble, 0))
            self.connect(frame_start, blocks.delay(gr.sizeof_char, 1),
                         (sampler_preamble, 1))
            self.connect(sampler_preamble, morelli_foe)
            freq_offset = morelli_foe
            print "FRAME_LENGTH: ", frame_length
            #log_to_file( self, sampler_preamble, "data/sampler_preamble.compl" )
            #log_to_file( self, rx_input, "data/rx_input.compl" )
            #log_to_file( self, ofdm_blocks, "data/rx_input.compl" )

            #Extracting preamble for SNR estimation
            #fft_snr_est = fft_blocks.fft_vcc( fft_length, True, [], True )
            #self.connect( sampler_preamble, blocks.stream_to_vector(gr.sizeof_gr_complex*fft_length/2, 2),  fft_snr_est )

            ## Remove virtual subcarriers
            #if fft_length > data_subc:
            #subcarrier_mask_snr_est = ofdm.vector_mask( fft_length, virtual_subc/2,
            #                       total_subc, [] )
            #self.connect( fft_snr_est, subcarrier_mask_snr_est )
            #fft_snr_est = subcarrier_mask_snr_est
            #log_to_file(self, ofdm_blocks, "data/vec_mask.compl")
            ## Least Squares estimator for channel transfer function (CTF)

            #self.connect( fft_snr_est, out_snr_pream ) # Connecting to output

            ## Adaptive LMS FIR filtering of frequency offset
            lms_fir = ofdm.lms_fir_ff(20,
                                      1e-3)  # TODO: verify parameter choice
            self.connect(freq_offset, lms_fir)
            freq_offset = lms_fir

            self.connect(freq_offset,
                         blocks.keep_one_in_n(gr.sizeof_float,
                                              20), out_disp_cfo)
        else:
            self.connect(blocks.vector_source_f([1]), out_disp_cfo)

        #log_to_file(self, lms_fir, "data/lms_fir.float")

        if options.disable_freq_sync or options.ideal or options.ideal2:
            if options.ideal is False and options.ideal2 is False:
                terminate_stream(self, freq_offset)
                freq_offset = blocks.vector_source_f([0.0], True)
            print "Disabled frequency synchronization stage"

        if options.ideal is False and options.ideal2 is False:
            ## Correct frequency shift, feed-forward structure
            frequency_shift = ofdm.frequency_shift_vcc(fft_length,
                                                       -1.0 / fft_length, 0)

            #freq_shift = blocks.multiply_cc()
            #norm_freq = -0.1 / config.fft_length
            #freq_off = self.freq_off_src = analog.sig_source_c(1.0, analog.GR_SIN_WAVE, norm_freq, 1.0, 0.0 )

            self.connect(ofdm_blocks, (frequency_shift, 0))
            self.connect(freq_offset, (frequency_shift, 1))
            self.connect(frame_start, blocks.delay(gr.sizeof_char, 0),
                         (frequency_shift, 2))

            #self.connect(frequency_shift,s2help)
            #ofdm_blocks = s2help
            ofdm_blocks = frequency_shift
        #terminate_stream(self, frequency_shift)

        #inner_pb_filt = self._inner_pilot_block_filter = fbmc_inner_pilot_block_filter()
        #self.connect(ofdm_blocks,inner_pb_filt)
        #self.connect(frame_start,(inner_pb_filt,1))
        #self.connect((inner_pb_filt,1),blocks.null_sink(gr.sizeof_char))

        #ofdm_blocks = (inner_pb_filt,0)

        overlap_ser_to_par = ofdm.fbmc_overlapping_serial_to_parallel_cvc(
            fft_length)
        self.separate_vcvc = ofdm.fbmc_separate_vcvc(fft_length, 2)
        self.polyphase_network_vcvc_1 = ofdm.fbmc_polyphase_network_vcvc(
            fft_length, 4, 4 * fft_length - 1, True)
        self.polyphase_network_vcvc_2 = ofdm.fbmc_polyphase_network_vcvc(
            fft_length, 4, 4 * fft_length - 1, True)
        self.junction_vcvc = ofdm.fbmc_junction_vcvc(fft_length, 2)
        self.fft_fbmc = fft_blocks.fft_vcc(fft_length, True, [], True)

        print "config.training_data.fbmc_no_preambles: ", config.training_data.fbmc_no_preambles
        #center_preamble = [1, -1j, -1, 1j]

        #self.preamble = preamble = [0]*total_subc + center_preamble*((int)(total_subc/len(center_preamble)))+[0]*total_subc

        self.preamble = preamble = config.training_data.fbmc_pilotsym_fd_list
        #inv_preamble = 1. / numpy.array(self.preamble)
        #print "self.preamble: ", len(self.preamble
        #print "inv_preamble: ", list(inv_preamble)

        #print "self.preamble", self.preamble
        #print "self.preamble2", self.preamble2

        self.multiply_const = ofdm.multiply_const_vcc(
            ([1.0 / (math.sqrt(fft_length * 0.6863))] * total_subc))
        self.beta_multiplier_vcvc = ofdm.fbmc_beta_multiplier_vcvc(
            total_subc, 4, 4 * fft_length - 1, 0)
        #self.skiphead = blocks.skiphead(gr.sizeof_gr_complex*total_subc, 2*4-1-1)
        self.skiphead = blocks.skiphead(gr.sizeof_gr_complex * total_subc, 2)
        self.skiphead_1 = blocks.skiphead(gr.sizeof_gr_complex * total_subc, 0)
        #self.remove_preamble_vcvc = ofdm.fbmc_remove_preamble_vcvc(total_subc, config.frame_data_part/2, config.training_data.fbmc_no_preambles*total_subc/2)
        #self.subchannel_processing_vcvc = ofdm.fbmc_subchannel_processing_vcvc(total_subc, config.frame_data_part, 1, 2, 1, 0)
        self.oqam_postprocessing_vcvc = ofdm.fbmc_oqam_postprocessing_vcvc(
            total_subc, 0, 0)

        #log_to_file( self, ofdm_blocks, "data/PRE_FBMC.compl" )
        #log_to_file( self, self.fft_fbmc, "data/FFT_FBMC.compl" )

        if options.ideal is False and options.ideal2 is False:
            self.subchannel_processing_vcvc = ofdm.fbmc_subchannel_processing_vcvc(
                total_subc, config.frame_data_part, 3, 2, 1, 0)
            help2 = blocks.keep_one_in_n(gr.sizeof_gr_complex * total_subc,
                                         frame_length)
            self.connect((self.subchannel_processing_vcvc, 1), help2)
            #log_to_file( self, self.subchannel_processing_vcvc, "data/fbmc_subc.compl" )

        #terminate_stream(self, help2)

        if options.ideal is False and options.ideal2 is False:
            self.connect(
                ofdm_blocks,
                blocks.vector_to_stream(gr.sizeof_gr_complex, fft_length),
                overlap_ser_to_par)
        else:
            self.connect(ofdm_blocks, overlap_ser_to_par)

        self.connect(overlap_ser_to_par, self.separate_vcvc)
        self.connect((self.separate_vcvc, 1),
                     (self.polyphase_network_vcvc_2, 0))
        self.connect((self.separate_vcvc, 0),
                     (self.polyphase_network_vcvc_1, 0))
        self.connect((self.polyphase_network_vcvc_1, 0),
                     (self.junction_vcvc, 0))
        self.connect((self.polyphase_network_vcvc_2, 0),
                     (self.junction_vcvc, 1))
        self.connect(self.junction_vcvc, self.fft_fbmc)

        ofdm_blocks = self.fft_fbmc
        print "config.dc_null: ", config.dc_null
        if fft_length > data_subc:
            subcarrier_mask_fbmc = ofdm.vector_mask_dc_null(
                fft_length, virtual_subc / 2, total_subc, config.dc_null, [])
            self.connect(ofdm_blocks, subcarrier_mask_fbmc)
            ofdm_blocks = subcarrier_mask_fbmc
            #log_to_file(self, ofdm_blocks, "data/vec_mask.compl")
            ## Least Squares estimator for channel transfer function (CTF)
            #log_to_file( self, subcarrier_mask, "data/OFDM_Blocks.compl" )

        self.connect(ofdm_blocks, self.beta_multiplier_vcvc)

        ofdm_blocks = self.beta_multiplier_vcvc
        #self.connect(ofdm_blocks,self.multiply_const)
        #self.connect(self.multiply_const, (self.skiphead, 0))

        self.connect(ofdm_blocks, (self.skiphead, 0))
        #log_to_file( self, self.skiphead, "data/fbmc_skiphead_4.compl" )

        #self.connect(ofdm_blocks, self.multiply_const)
        #self.connect(self.multiply_const, self.beta_multiplier_vcvc)
        #self.connect((self.beta_multiplier_vcvc, 0), (self.skiphead, 0))
        if options.ideal or options.ideal2:
            self.connect((self.skiphead, 0), (self.skiphead_1, 0))
        else:
            self.connect((self.skiphead, 0),
                         (self.subchannel_processing_vcvc, 0))
            self.connect((self.subchannel_processing_vcvc, 0),
                         (self.skiphead_1, 0))

        #log_to_file( self, self.skiphead, "data/fbmc_subc.compl" )
        #self.connect((self.skiphead_1, 0),(self.remove_preamble_vcvc, 0))
        #self.connect((self.remove_preamble_vcvc, 0),  (self.oqam_postprocessing_vcvc, 0))

        #ofdm_blocks = self.oqam_postprocessing_vcvc
        #log_to_file( self, self.subchannel_processing_vcvc, "data/subc_0.compl" )
        #log_to_file( self, (self.subchannel_processing_vcvc,1), "data/subc_1.compl" )

        self.connect((self.skiphead_1, 0), (self.oqam_postprocessing_vcvc, 0))
        #self.connect((self.oqam_postprocessing_vcvc, 0), (self.remove_preamble_vcvc, 0) )

        ofdm_blocks = (self.oqam_postprocessing_vcvc, 0
                       )  #(self.remove_preamble_vcvc, 0)
        #log_to_file( self, (self.oqam_postprocessing_vcvc, 0), "data/fbmc_before_remove.compl" )

        #log_to_file( self, self.skiphead, "data/SKIP_HEAD_FBMC.compl" )
        #log_to_file( self, self.beta_multiplier_vcvc, "data/BETA_REC_FBMC.compl" )
        #log_to_file( self, self.oqam_postprocessing_vcvc, "data/REC_OUT_FBMC.compl" )
        """ DISABLED OFDM CHANNEL ESTIMATION PREMBLE -> CORRECT LATER to compare FBMC and OFDM channel estimation
    #TAKING THE CHANNEL ESTIMATION PREAMBLE
    chest_pre_trigger = blocks.delay( gr.sizeof_char, 3 )
    sampled_chest_preamble = ofdm.vector_sampler( gr.sizeof_gr_complex * fft_length/2, 2 )
      
    self.connect( frame_start,       chest_pre_trigger )
    self.connect( chest_pre_trigger, ( sampled_chest_preamble, 1 ) )
    self.connect( frequency_shift,       ( sampled_chest_preamble, 0 ) )
    #ofdm_blocks = sampled_chest_preamble
    
        
    ## FFT
    fft = fft_blocks.fft_vcc( fft_length, True, [], True )
    self.connect( sampled_chest_preamble, fft )
    ofdm_blocks_est = fft
    log_to_file( self, sampled_chest_preamble, "data/SAMPLED_EST_PREAMBLE.compl" )
    log_to_file( self, ofdm_blocks_est, "data/FFT.compl" )
    
    
    ## Remove virtual subcarriers
    if fft_length > data_subc:
      subcarrier_mask = ofdm.vector_mask( fft_length, virtual_subc/2,
                                           total_subc, [] )
      self.connect( ofdm_blocks_est, subcarrier_mask )
      ofdm_blocks_est = subcarrier_mask
      #log_to_file(self, ofdm_blocks, "data/vec_mask.compl")
       ## Least Squares estimator for channel transfer function (CTF)
      log_to_file( self, subcarrier_mask, "data/OFDM_Blocks.compl" )
    
          
    ## post-FFT processing
      
    
    
    ## extract channel estimation preamble from frame
    ##chest_pre_trigger = blocks.delay( gr.sizeof_char, 
                                  ##1 )
    ##sampled_chest_preamble = \
     ## ofdm.vector_sampler( gr.sizeof_gr_complex * total_subc, 1 )
    ##self.connect( frame_start,       chest_pre_trigger )
    ##self.connect( chest_pre_trigger, ( sampled_chest_preamble, 1 ) )
    ##self.connect( ofdm_blocks,       ( sampled_chest_preamble, 0 ) )
    

    
    ## Least Squares estimator for channel transfer function (CTF)
    inv_preamble_fd = numpy.array( block_header.pilotsym_fd[ 
        block_header.channel_estimation_pilot[0] ] )
    #print "Channel estimation pilot: ", inv_preamble_fd
    inv_preamble_fd = 1. / inv_preamble_fd
    
    LS_channel_estimator = ofdm.multiply_const_vcc( list( inv_preamble_fd ) )
    self.connect( ofdm_blocks_est, LS_channel_estimator )
    estimated_CTF = LS_channel_estimator
    terminate_stream(self,estimated_CTF)
    """
        if options.ideal is False and options.ideal2 is False:
            if options.logcir:
                log_to_file(self, sampled_chest_preamble, "data/PREAM.compl")

            if not options.disable_ctf_enhancer:

                if options.logcir:
                    ifft1 = fft_blocks.fft_vcc(total_subc, False, [], True)
                    self.connect(
                        estimated_CTF, ifft1,
                        gr.null_sink(gr.sizeof_gr_complex * total_subc))
                    summ1 = ofdm.vector_sum_vcc(total_subc)
                    c2m = gr.complex_to_mag(total_subc)
                    self.connect(estimated_CTF, summ1,
                                 gr.null_sink(gr.sizeof_gr_complex))
                    self.connect(estimated_CTF, c2m,
                                 gr.null_sink(gr.sizeof_float * total_subc))
                    log_to_file(self, ifft1, "data/CIR1.compl")
                    log_to_file(self, summ1, "data/CTFsumm1.compl")
                    log_to_file(self, estimated_CTF, "data/CTF1.compl")
                    log_to_file(self, c2m, "data/CTFmag1.float")

                ## MSE enhancer
                ctf_mse_enhancer = ofdm.CTF_MSE_enhancer(
                    total_subc, cp_length + cp_length)
                self.connect(estimated_CTF, ctf_mse_enhancer)
                #      log_to_file( self, ctf_mse_enhancer, "data/ctf_mse_enhancer_original.compl")
                #ifft3 = fft_blocks.fft_vcc(total_subc,False,[],True)
                #null_noise = ofdm.noise_nulling(total_subc, cp_length + cp_length)
                #ctf_mse_enhancer = fft_blocks.fft_vcc(total_subc,True,[],True)
                #ctf_mse_enhancer = ofdm.vector_mask( fft_length, virtual_subc/2,
                # total_subc, [] )
                #self.connect( estimated_CTF, ifft3,null_noise,ctf_mse_enhancer )

                estimated_CTF = ctf_mse_enhancer
                print "Disabled CTF MSE enhancer"

            if options.logcir:
                ifft2 = fft_blocks.fft_vcc(total_subc, False, [], True)
                self.connect(estimated_CTF, ifft2,
                             gr.null_sink(gr.sizeof_gr_complex * total_subc))
                summ2 = ofdm.vector_sum_vcc(total_subc)
                c2m2 = gr.complex_to_mag(total_subc)
                self.connect(estimated_CTF, summ2,
                             gr.null_sink(gr.sizeof_gr_complex))
                self.connect(estimated_CTF, c2m2,
                             gr.null_sink(gr.sizeof_float * total_subc))
                log_to_file(self, ifft2, "data/CIR2.compl")
                log_to_file(self, summ2, "data/CTFsumm2.compl")
                log_to_file(self, estimated_CTF, "data/CTF2.compl")
                log_to_file(self, c2m2, "data/CTFmag2.float")

            ## Postprocess the CTF estimate
            ## CTF -> inverse CTF (for equalizer)
            ## CTF -> norm |.|^2 (for CTF display)
            ctf_postprocess = ofdm.fbmc_postprocess_CTF_estimate(total_subc)

            self.connect(help2, ctf_postprocess)
            #estimated_SNR = ( ctf_postprocess, 0 )
            disp_CTF = (ctf_postprocess, 0)
            #self.connect(estimated_SNR,out_snr_pream)
            #log_to_file( self, estimated_SNR, "data/fbmc_SNR.float" )

            #Disable measured SNR output
            #terminate_stream(self, estimated_SNR)
            #self.connect(blocks.vector_source_f([10.0],True) ,out_snr_pream)


#     if options.disable_equalization or options.ideal:
#       terminate_stream(self, inv_estimated_CTF)
#       inv_estimated_CTF_vec = blocks.vector_source_c([1.0/fft_length*math.sqrt(total_subc)]*total_subc,True,total_subc)
#       inv_estimated_CTF_str = blocks.vector_to_stream(gr.sizeof_gr_complex, total_subc)
#       self.inv_estimated_CTF_mul = ofdm.multiply_const_ccf( 1.0/config.rms_amplitude )
#       #inv_estimated_CTF_mul.set_k(1.0/config.rms_amplitude)
#       inv_estimated_CTF = blocks.stream_to_vector(gr.sizeof_gr_complex, total_subc)
#       self.connect( inv_estimated_CTF_vec, inv_estimated_CTF_str, self.inv_estimated_CTF_mul, inv_estimated_CTF)
#       print "Disabled equalization stage"
        '''
    ## LMS Phase tracking
    ## Track residual frequency offset and sampling clock frequency offset

    nondata_blocks = []
    for i in range(config.frame_length):
      if i in config.training_data.pilotsym_pos:
        nondata_blocks.append(i)
        
    print"\t\t\t\t\tnondata_blocks=",nondata_blocks
    pilot_subc = block_header.pilot_tones
    pilot_subcarriers = block_header.pilot_subc_sym
    print "PILOT SUBCARRIERS: ", pilot_subcarriers
        
    phase_tracking = ofdm.lms_phase_tracking_03( total_subc, pilot_subc,
                                               nondata_blocks, pilot_subcarriers,0 )
    self.connect( ofdm_blocks, ( phase_tracking, 0 ) )
    self.connect( inv_estimated_CTF, ( phase_tracking, 1 ) )
    self.connect( frame_start, ( phase_tracking, 2 ) ) ##
    
    if options.scatter_plot_before_phase_tracking:
      self.before_phase_tracking = equalizer
      
    
    if options.disable_phase_tracking or options.ideal:
      terminate_stream(self, phase_tracking)
      print "Disabled phase tracking stage"
    else:
      ofdm_blocks = phase_tracking
    '''
        ## Channel Equalizer
        ##equalizer = ofdm.channel_equalizer( total_subc )
        ##self.connect( ofdm_blocks,       ( equalizer, 0 ) )
        ##self.connect( inv_estimated_CTF, ( equalizer, 1 ) )
        ##self.connect( frame_start,       ( equalizer, 2 ) )
        ##ofdm_blocks = equalizer
        #log_to_file(self, equalizer,"data/equalizer_siso.compl")

        #log_to_file(self, ofdm_blocks, "data/equalizer.compl")

        ## LMS Phase tracking
        ## Track residual frequency offset and sampling clock frequency offset

        nondata_blocks = []
        for i in range(config.frame_length):
            if i in config.training_data.pilotsym_pos:
                nondata_blocks.append(i)

        print "\t\t\t\t\tnondata_blocks=", nondata_blocks
        pilot_subc = block_header.pilot_tones
        pilot_subcarriers = block_header.pilot_subc_sym
        print "PILOT SUBCARRIERS: ", pilot_subcarriers

        if options.scatter_plot_before_phase_tracking:
            self.before_phase_tracking = equalizer

        ## Output connections

        self.connect(ofdm_blocks, out_ofdm_blocks)
        self.connect(frame_start, out_frame_start)
        if options.ideal is False and options.ideal2 is False:
            self.connect(disp_CTF, out_disp_ctf)
        else:
            self.connect(blocks.vector_source_f([1.0] * total_subc),
                         blocks.stream_to_vector(gr.sizeof_float, total_subc),
                         out_disp_ctf)

        if log:
            log_to_file(self, sc_metric, "data/sc_metric.float")
            log_to_file(self, gi_metric, "data/gi_metric.float")
            log_to_file(self, morelli_foe, "data/morelli_foe.float")
            log_to_file(self, lms_fir, "data/lms_fir.float")
            log_to_file(self, sampler_preamble, "data/preamble.compl")
            log_to_file(self, sync, "data/sync.compl")
            log_to_file(self, frequency_shift, "data/frequency_shift.compl")
            log_to_file(self, fft, "data/fft.compl")
            log_to_file(self, fft, "data/fft.float", mag=True)

            if vars().has_key('subcarrier_mask'):
                log_to_file(self, subcarrier_mask,
                            "data/subcarrier_mask.compl")

            log_to_file(self, ofdm_blocks, "data/ofdm_blocks_out.compl")
            log_to_file(self,
                        frame_start,
                        "data/frame_start.float",
                        char_to_float=True)

            log_to_file(self, sampled_chest_preamble,
                        "data/sampled_chest_preamble.compl")
            log_to_file(self, LS_channel_estimator,
                        "data/ls_channel_estimator.compl")
            log_to_file(self,
                        LS_channel_estimator,
                        "data/ls_channel_estimator.float",
                        mag=True)

            if "ctf_mse_enhancer" in locals():
                log_to_file(self, ctf_mse_enhancer,
                            "data/ctf_mse_enhancer.compl")
                log_to_file(self,
                            ctf_mse_enhancer,
                            "data/ctf_mse_enhancer.float",
                            mag=True)

            log_to_file(self, (ctf_postprocess, 0),
                        "data/inc_estimated_ctf.compl")
            log_to_file(self, (ctf_postprocess, 1), "data/disp_ctf.float")

            log_to_file(self, equalizer, "data/equalizer.compl")
            log_to_file(self, equalizer, "data/equalizer.float", mag=True)

            log_to_file(self, phase_tracking, "data/phase_tracking.compl")
Example #38
0
    def __init__(self, vlen):
        gr.hier_block2.__init__(
            self, "snr_estimator",
            gr.io_signature2(2, 2, gr.sizeof_gr_complex, gr.sizeof_char),
            gr.io_signature(1, 1, gr.sizeof_float))

        data_in = (self, 0)
        trig_in = (self, 1)
        snr_out = (self, 0)

        ## Preamble Extraction
        sampler = vector_sampler(gr.sizeof_gr_complex, vlen)
        self.connect(data_in, sampler)
        self.connect(trig_in, (sampler, 1))

        ## Algorithm implementation
        estim = sc_snr_estimator(vlen)
        self.connect(sampler, estim)
        self.connect(estim, snr_out)

        return

        ## Split block into two parts
        splitter = gr.vector_to_streams(gr.sizeof_gr_complex * vlen / 2, 2)
        self.connect(sampler, splitter)

        ## Conjugate first half block
        conj = gr.conjugate_cc(vlen / 2)
        self.connect(splitter, conj)

        ## Vector multiplication of both half blocks
        vmult = gr.multiply_vcc(vlen / 2)
        self.connect(conj, vmult)
        self.connect((splitter, 1), (vmult, 1))

        ## Sum of Products
        psum = vector_sum_vcc(vlen / 2)
        self.connect(vmult, psum)

        ## Magnitude of P(d)
        p_mag = gr.complex_to_mag()
        self.connect(psum, p_mag)

        ## Squared Magnitude of block
        r_magsqrd = gr.complex_to_mag_squared(vlen)
        self.connect(sampler, r_magsqrd)

        ## Sum of squared second half block
        r_sum = vector_sum_vff(vlen)
        self.connect(r_magsqrd, r_sum)

        ## Square Root of Metric
        m_sqrt = gr.divide_ff()
        self.connect(p_mag, (m_sqrt, 0))
        self.connect(r_sum, gr.multiply_const_ff(0.5), (m_sqrt, 1))

        ## Denominator of SNR estimate
        denom = gr.add_const_ff(1)
        neg_m_sqrt = gr.multiply_const_ff(-1.0)
        self.connect(m_sqrt, limit_vff(1, 1 - 2e-5, -1000), neg_m_sqrt, denom)

        ## SNR estimate
        snr_est = gr.divide_ff()
        self.connect(m_sqrt, (snr_est, 0))
        self.connect(denom, (snr_est, 1))

        ## Setup Output Connections
        self.connect(snr_est, self)
Example #39
0
    def __init__(self, options, callback=None):
        """
	Hierarchical block for demodulating and deframing packets.

	The input is the complex modulated signal at baseband.
        Demodulated packets are sent to the handler.

        Args:
            options: pass modulation options from higher layers (fft length, occupied tones, etc.)
            callback: function of two args: ok, payload (ok: bool; payload: string)
	"""
	gr.hier_block2.__init__(self, "ofdm_demod",
				gr.io_signature(1, 1, gr.sizeof_gr_complex), # Input signature
				gr.io_signature(1, 1, gr.sizeof_gr_complex)) # Output signature


        self._rcvd_pktq = gr.msg_queue()          # holds packets from the PHY

        self._modulation = options.modulation
        self._fft_length = options.fft_length
        self._occupied_tones = options.occupied_tones
        self._cp_length = options.cp_length
        self._snr = options.snr

        # Use freq domain to get doubled-up known symbol for correlation in time domain
        zeros_on_left = int(math.ceil((self._fft_length - self._occupied_tones)/2.0))
        ksfreq = known_symbols_4512_3[0:self._occupied_tones]
        for i in range(len(ksfreq)):
            if((zeros_on_left + i) & 1):
                ksfreq[i] = 0

        # hard-coded known symbols
        preambles = (ksfreq,)

        symbol_length = self._fft_length + self._cp_length
        self.ofdm_recv = ofdm_receiver(self._fft_length,
                                       self._cp_length,
                                       self._occupied_tones,
                                       self._snr, preambles,
                                       options.log)

        mods = {"bpsk": 2, "qpsk": 4, "8psk": 8, "qam8": 8, "qam16": 16, "qam64": 64, "qam256": 256}
        arity = mods[self._modulation]
        
        rot = 1
        if self._modulation == "qpsk":
            rot = (0.707+0.707j)

        # FIXME: pass the constellation objects instead of just the points
        if(self._modulation.find("psk") >= 0):
            constel = psk.psk_constellation(arity)
            rotated_const = map(lambda pt: pt * rot, constel.points())
        elif(self._modulation.find("qam") >= 0):
            constel = qam.qam_constellation(arity)
            rotated_const = map(lambda pt: pt * rot, constel.points())
        #print rotated_const

        phgain = 0.25
        frgain = phgain*phgain / 4.0
        self.ofdm_demod = digital.ofdm_frame_sink(rotated_const, range(arity),
                                                  self._rcvd_pktq,
                                                  self._occupied_tones,
                                                  phgain, frgain)

        self.connect(self, self.ofdm_recv)
        self.connect((self.ofdm_recv, 0), (self.ofdm_demod, 0))
        self.connect((self.ofdm_recv, 1), (self.ofdm_demod, 1))

        # added output signature to work around bug, though it might not be a bad
        # thing to export, anyway
        self.connect(self.ofdm_recv.chan_filt, self)

        if options.log:
            self.connect(self.ofdm_demod,
                         blocks.file_sink(gr.sizeof_gr_complex*self._occupied_tones,
                                      "ofdm_frame_sink_c.dat"))
        else:
            self.connect(self.ofdm_demod,
                         blocks.null_sink(gr.sizeof_gr_complex*self._occupied_tones))

        if options.verbose:
            self._print_verbage()
            
        self._watcher = _queue_watcher_thread(self._rcvd_pktq, callback)
Example #40
0
    def __init__(
            self,
            n_bursts, n_channels,
            freq_delta, base_freq,
            burst_length, base_time, hop_time,
            post_tuning=True,
            tx_gain=30,
            verbose=False
        ):
        gr.hier_block2.__init__(self,
            "FrequencyHopperSrc",
            gr.io_signature(1, 1, gr.sizeof_gr_complex),
            gr.io_signature(1, 1, gr.sizeof_gr_complex),
        )
        n_samples_total = n_bursts * burst_length
        self.hop_sequence = numpy.arange(base_freq, base_freq + n_channels * freq_delta, freq_delta)
        #   self.hop_sequence = 2410000000, 2415000000, 2425000000, 2430000000, 2435000000, 2440000000, 2455000000 
        #   numpy.random.shuffle(self.hop_sequence)  #this randomly shuffels frequencies in the specified range
        #   self.hop_sequence = [self.hop_sequence[x % n_channels] for x in xrange(n_bursts)]
        self.hop_sequence = [self.hop_sequence[x % 7]for x in xrange(n_bursts)]
        if verbose:
            print "Hop Frequencies  | Hop Pattern"
            print "=================|================================"
            for f in self.hop_sequence:
                print "{:6.3f} MHz      |  ".format(f/1e6),
                if n_channels < 50:
                    print " " * int((f - base_freq) / freq_delta) + "#"
                else:
                    print "\n"
            print "=================|================================"

        gain_tag = gr.tag_t()
        gain_tag.offset = 0
        gain_tag.key = pmt.string_to_symbol('tx_command')
        gain_tag.value = pmt.cons(
                pmt.intern("gain"),
                # These are both valid:
                #pmt.from_double(tx_gain)
                pmt.cons(pmt.to_pmt(0), pmt.to_pmt(tx_gain))
        )
        tag_list = [gain_tag,]
        for i in xrange(n_bursts):
            tune_tag = gr.tag_t()
            tune_tag.offset = i * burst_length
            if i > 0 and post_tuning:
                tune_tag.offset -= 1 # Move it to last sample of previous burst
            tune_tag.key = pmt.string_to_symbol('tx_freq')
            tune_tag.value = pmt.to_pmt(self.hop_sequence[i])
            tag_list.append(tune_tag)
            length_tag = gr.tag_t()
            length_tag.offset = i * burst_length
            length_tag.key = pmt.string_to_symbol('packet_len')
            length_tag.value = pmt.from_long(burst_length)
            tag_list.append(length_tag)
            time_tag = gr.tag_t()
            time_tag.offset = i * burst_length
            time_tag.key = pmt.string_to_symbol('tx_time')
            time_tag.value = pmt.make_tuple(
                    pmt.from_uint64(int(base_time + i * hop_time)),
                    pmt.from_double((base_time + i * hop_time) % 1),
            )
            tag_list.append(time_tag)
        tag_source = blocks.vector_source_c((1.0,) * n_samples_total, repeat=False, tags=tag_list)
        mult = blocks.multiply_cc()
        self.connect(self, mult, self)
        self.connect(tag_source, (mult, 1))
Example #41
0
    def __init__(self,
                 sign_freq,
                 audio_freq,
                 signal_low_pass_cutoff=10000,
                 signal_low_pass_trans=1000,
                 audio_low_pass_cutoff=3000,
                 audio_low_pass_trans=20,
                 use_dc_blocker=True,
                 audio_gain=1):
        ##################################################
        # Variables
        ##################################################
        self.sign_freq = sign_freq
        self.audio_freq = audio_freq
        self.signal_low_pass_cutoff = signal_low_pass_cutoff
        self.signal_low_pass_trans = signal_low_pass_trans
        self.audio_low_pass_cutoff = audio_low_pass_cutoff
        self.audio_low_pass_trans = audio_low_pass_trans
        self.use_dc_blocker = use_dc_blocker
        self.audio_gain = audio_gain

        # hyper parameter
        self.low_pass_ampl_bound = 0.1
        self.low_pass_window = firdes.WIN_HAMMING
        self.low_pass_beta = 6.76

        ##################################################
        # Submodule
        ##################################################
        self.input_resample = filter.rational_resampler_ccf(
            interpolation=2000000,
            decimation=sign_freq,
            taps=None,
            fractional_bw=None)

        self.signal_low_pass_filter = eewls.auto_gain_low_pass_filter(
            filter.fir_filter_ccf, 8, self.low_pass_ampl_bound, 2000000,
            self.signal_low_pass_cutoff, self.signal_low_pass_trans,
            self.low_pass_window, self.low_pass_beta, str(complex))

        self.am_demod = analog.am_demod_cf(channel_rate=50000,
                                           audio_decim=5,
                                           audio_pass=5000,
                                           audio_stop=5500)
        self.resampler = filter.rational_resampler_fff(
            interpolation=48 * self.audio_freq * 2 / 96000,
            decimation=50,
            taps=None,
            fractional_bw=None)
        self.audio_filter = filter.interp_fir_filter_fff(
            1,
            firdes.low_pass(self.audio_gain, self.audio_freq * 2,
                            self.audio_low_pass_cutoff,
                            self.audio_low_pass_trans, self.low_pass_window,
                            self.low_pass_beta))

        gr.hier_block2.__init__(
            self, "fm_audio_decoder",
            gr.io_signature(
                1, 1,
                self.input_resample.input_signature().sizeof_stream_item(0)),
            gr.io_signature(
                1, 1,
                self.audio_filter.output_signature().sizeof_stream_item(0)))

        if self.use_dc_blocker:
            self.dc_blocker = filter.dc_blocker_cc(256, True)
        ##################################################
        # Connections
        ##################################################
        self.connect((self, 0), (self.input_resample, 0))
        self.connect((self.input_resample, 0),
                     (self.signal_low_pass_filter, 0))
        if self.use_dc_blocker:
            self.connect((self.signal_low_pass_filter, 0),
                         (self.dc_blocker, 0))
            self.connect((self.dc_blocker, 0), (self.am_demod, 0))
        else:
            self.connect((self.signal_low_pass_filter, 0), (self.am_demod, 0))
        self.connect((self.am_demod, 0), (self.resampler, 0))
        self.connect((self.resampler, 0), (self.audio_filter, 0))
        self.connect((self.audio_filter, 0), (self, 0))
Example #42
0
    def __init__(self, magnitude=0, phase=0, mode=0):
        '''
        This block implements the single branch IQ imbalance
        transmitter and receiver models.

        Developed from source (2014):
        "In-Phase and Quadrature Imbalance:
          Modeling, Estimation, and Compensation"

        TX Impairment:

                                  {R}--|Multiply: 10**(mag/20)|--+--|Multiply: cos(pi*degree/180)|--X1
        Input ---|Complex2Float|---|                             +--|Multiply: sin(pi*degree/180)|--X2
                                  {I}--|  Adder  |
                                   X2--|   (+)   |--X3

                          X1--{R}--| Float 2 |--- Output
                          X3--{I}--| Complex |

        RX Impairment:

                                  {R}--|Multiply: cos(pi*degree/180)|-------|       |
        Input ---|Complex2Float|---|                                        | Adder |--X1
                                  {I}--+--|Multiply: sin(pi*degree/180)|----|  (+)  |
                                       |
                                       +--X2

                        X1--|Multiply: 10**(mag/20)|--{R}--| Float 2 |--- Output
                        X2---------------------------{I}--| Complex |

        (ASCII ART monospace viewing)
        '''
        gr.hier_block2.__init__(
            self,
            "IQ Imbalance Generator",
            gr.io_signature(1, 1, gr.sizeof_gr_complex * 1),
            gr.io_signature(1, 1, gr.sizeof_gr_complex * 1),
        )

        ##################################################
        # Parameters
        ##################################################
        self.magnitude = magnitude
        self.phase = phase
        self.mode = mode

        ##################################################
        # Blocks
        ##################################################
        # Same blocks for Transmitter and Receiver
        self.mag = blocks.multiply_const_vff((math.pow(10,
                                                       magnitude / 20.0), ))
        self.sin_phase = blocks.multiply_const_vff(
            (math.sin(phase * math.pi / 180.0), ))
        self.cos_phase = blocks.multiply_const_vff(
            (math.cos(phase * math.pi / 180.0), ))
        self.f2c = blocks.float_to_complex(1)
        self.c2f = blocks.complex_to_float(1)
        self.adder = blocks.add_vff(1)

        ##################################################
        # Connections
        ##################################################
        if (self.mode):
            # Receiver Mode
            self.connect((self, 0), (self.c2f, 0))
            self.connect((self.c2f, 0), (self.cos_phase, 0))
            self.connect((self.cos_phase, 0), (self.adder, 0))
            self.connect((self.c2f, 1), (self.sin_phase, 0))
            self.connect((self.sin_phase, 0), (self.adder, 1))
            self.connect((self.adder, 0), (self.mag, 0))
            self.connect((self.mag, 0), (self.f2c, 0))
            self.connect((self.c2f, 1), (self.f2c, 1))
            self.connect((self.f2c, 0), (self, 0))
        else:
            # Transmitter Mode
            self.connect((self, 0), (self.c2f, 0))
            self.connect((self.c2f, 0), (self.mag, 0))
            self.connect((self.mag, 0), (self.cos_phase, 0))
            self.connect((self.cos_phase, 0), (self.f2c, 0))
            self.connect((self.mag, 0), (self.sin_phase, 0))
            self.connect((self.sin_phase, 0), (self.adder, 0))
            self.connect((self.c2f, 1), (self.adder, 1))
            self.connect((self.adder, 0), (self.f2c, 1))
            self.connect((self.f2c, 0), (self, 0))
Example #43
0
    def __init__(self,
                 samples_per_symbol=_def_samples_per_symbol,
                 excess_bw=_def_excess_bw,
                 verbose=_def_verbose,
                 log=_def_log):
        """
	Hierarchical block for RRC-filtered QPSK modulation.

	The input is a byte stream (unsigned char) and the
	output is the complex modulated signal at baseband.

	@param samples_per_symbol: samples per symbol >= 2
	@type samples_per_symbol: integer
	@param excess_bw: Root-raised cosine filter excess bandwidth
	@type excess_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,
            "cqpsk_mod",
            gr.io_signature(1, 1, gr.sizeof_char),  # Input signature
            gr.io_signature(1, 1, gr.sizeof_gr_complex))  # Output signature

        self._samples_per_symbol = samples_per_symbol
        self._excess_bw = excess_bw

        if not isinstance(samples_per_symbol, int) or samples_per_symbol < 2:
            raise TypeError, ("sbp must be an integer >= 2, is %d" %
                              samples_per_symbol)

        ntaps = 11 * samples_per_symbol

        arity = 8

        # turn bytes into k-bit vectors
        self.bytes2chunks = \
          blocks.packed_to_unpacked_bb(self.bits_per_symbol(), gr.GR_MSB_FIRST)

        #	0	+45	1	[+1]
        #	1	+135	3	[+3]
        #	2	-45	7	[-1]
        #	3	-135	5	[-3]
        self.pi4map = [1, 3, 7, 5]
        self.symbol_mapper = digital.map_bb(self.pi4map)
        self.diffenc = digital.diff_encoder_bb(arity)
        self.chunks2symbols = digital.chunks_to_symbols_bc(
            psk.constellation[arity])

        # pulse shaping filter
        self.rrc_taps = filter.firdes.root_raised_cosine(
            self.
            _samples_per_symbol,  # gain  (sps since we're interpolating by sps)
            self._samples_per_symbol,  # sampling rate
            1.0,  # symbol rate
            self._excess_bw,  # excess bandwidth (roll-off factor)
            ntaps)

        self.rrc_filter = filter.interp_fir_filter_ccf(
            self._samples_per_symbol, self.rrc_taps)

        if verbose:
            self._print_verbage()

        if log:
            self._setup_logging()

# Connect & Initialize base class
        self.connect(self, self.bytes2chunks, self.symbol_mapper, self.diffenc,
                     self.chunks2symbols, self.rrc_filter, self)
Example #44
0
    def __init__(self):
        gr.hier_block2.__init__(
            self,
            "bch_viterbi_vfvb",
            gr.io_signature(1, 1, gr.sizeof_float * 120),  # Input signature
            gr.io_signature(1, 1, gr.sizeof_char * 40))  # Output signature

        # Define blocks and connect them
        # Repeat input vector one time to get viterbi decoder state right (tail-biting stuff)
        #self.rpt = blocks.repeat(gr.sizeof_float * 120, 2)
        # viterbi decoder requires stream as input
        #self.vtos = blocks.vector_to_stream(1 * gr.sizeof_float, 120)

        # self.vtss = blocks.vector_to_streams(1* gr.sizeof_float, 120, "bch_viterbi_vector_to_streams_0")
        self.vtss = blocks.vector_to_streams(1 * gr.sizeof_float, 120)
        #self.app = blocks.streams_to_stream(1* gr.sizeof_float, 138, "bch_viterbi_streams_to_stream_0")
        self.app = blocks.streams_to_stream(1 * gr.sizeof_float, 138)
        self.connect(self, self.vtss)
        for i in range(18):
            self.connect((self.vtss, 120 - 18 + i), (self.app, i))
        for i in range(120):
            self.connect((self.vtss, i), (self.app, i + 18))

        # Correct FSM instantiation: k=num_input_bits, n=num_output_bits, Tuple[dim(k*n)] (decimal notation)
        self.fsm = trellis.fsm(1, 3, [91, 121, 117])

        # Values for viterbi decoder
        K = 46  # steps for one coding block
        SO = 0  # initial state
        SK = -1  # final state (in this case unknown, therefore -1)
        D = 3  # dimensionality
        # D = 3 follows from the fact that 1 {0,1} input symbol of the encoder produces 3 {0,1} output symbols.
        # (packed into one byte {0,1,...,7} )
        # with NRZ coding follows:
        # 0 -->  1
        # 1 --> -1
        # This leads to the following constellation input
        #               |  0  |  1   | 2    | 3     |  4   |  5    |  6    |  7     |
        constellation = [
            1, 1, 1, 1, 1, -1, 1, -1, 1, 1, -1, -1, -1, 1, 1, -1, 1, -1, -1,
            -1, 1, -1, -1, -1
        ]
        # print "len(constellation)/D = " + str(len(constellation)/D) + "\tfsm.O = " + str(self.fsm.O())
        # Viterbi_combined input: FSM, K, SO, SK, D, TABLE, TYPE
        # FSM    = Finite State Machine
        # K      = number of output symbols produced by the FSM
        # SO     = initial state of the FSM
        # SK     = final state of the FSM (unknown in this example)
        # D      = dimensionality
        # TABLE  = constellation of the input symbols
        # self.vit = trellis.viterbi_combined_fb(self.fsm, K, SO, SK, D, constellation, 200, "bch_viterbi_combined_fb_0")
        self.vit = trellis.viterbi_combined_fb(self.fsm, K, SO, SK, D,
                                               constellation, 200)
        self.connect(self.app, self.vit)
        # connect all streams which are crated yet
        #self.connect(self,self.rpt,self.vtos,self.vit)
        # self.keep = blocks.keep_m_in_n(gr.sizeof_char, 40, 46, 6, "bch_viterbi_keep_m_in_n_0")
        self.keep = blocks.keep_m_in_n(gr.sizeof_char, 40, 46, 6)
        # self.tovec = blocks.stream_to_vector(1, 40, "bch_viterbi_stream_to_vector_0")
        self.tovec = blocks.stream_to_vector(1, 40)
        self.connect(self.vit, self.keep, self.tovec, self)
    def __init__(self,
                 baudrate,
                 samp_rate,
                 iq,
                 deviation=None,
                 subaudio=False,
                 dc_block=True,
                 dump_path=None,
                 options=None):
        gr.hier_block2.__init__(
            self, "fsk_demodulator",
            gr.io_signature(1, 1,
                            gr.sizeof_gr_complex if iq else gr.sizeof_float),
            gr.io_signature(1, 1, gr.sizeof_float))
        options_block.__init__(self, options)

        use_agc = self.options.use_agc or not iq

        if dump_path is not None:
            dump_path = pathlib.Path(dump_path)

        if deviation is not None:
            _deviation = deviation
        else:
            _deviation = self.options.deviation
        if iq:
            self.demod = analog.quadrature_demod_cf(samp_rate /
                                                    (2 * pi * _deviation))
            self.connect(self, self.demod)
        else:
            self.demod = self

        sps = samp_rate / baudrate
        max_sps = 10
        if sps > max_sps:
            decimation = ceil(sps / max_sps)
        else:
            decimation = 1
        sps /= decimation

        if subaudio:
            # some not-so-bad filter parameters for subaudio processing
            subaudio_cutoff = 2.0 / 3.0 * baudrate
            subaudio_transition = subaudio_cutoff / 4.0
            subaudio_taps = firdes.low_pass(1, samp_rate, subaudio_cutoff,
                                            subaudio_transition)
            self.subaudio_lowpass = filter.fir_filter_fff(1, subaudio_taps)

        # square pulse filter
        sqfilter_len = int(samp_rate / baudrate)
        taps = np.ones(sqfilter_len) / sqfilter_len
        self.lowpass = filter.fir_filter_fff(decimation, taps)

        if dc_block:
            self.dcblock = filter.dc_blocker_ff(ceil(sps * 32), True)
        else:
            self.dcblock = self.lowpass  # to simplify connections below

        if use_agc:
            agc_constant = 2e-2 / sps  # This gives a time constant of 50 symbols
            self.agc = rms_agc_f(agc_constant, 1)

        if dump_path is not None:
            self.waveform = blocks.file_sink(gr.sizeof_float,
                                             str(dump_path / 'waveform.f32'))

        ted_gain = 1.47  # "empiric" formula for TED gain of Gardner detector 1.47 symbol^{-1}
        damping = 1.0
        self.clock_recovery = digital.symbol_sync_ff(
            digital.TED_GARDNER, sps, self.options.clk_bw, damping, ted_gain,
            self.options.clk_limit * sps, 1,
            digital.constellation_bpsk().base(), digital.IR_PFB_NO_MF)

        if dump_path is not None:
            self.clock_recovery_out = blocks.file_sink(
                gr.sizeof_float, str(dump_path / 'clock_recovery_out.f32'),
                False)
            self.clock_recovery_err = blocks.file_sink(
                gr.sizeof_float, str(dump_path / 'clock_recovery_err.f32'),
                False)
            self.clock_recovery_T_inst = blocks.file_sink(
                gr.sizeof_float, str(dump_path / 'clock_recovery_T_inst.f32'),
                False)
            self.clock_recovery_T_avg = blocks.file_sink(
                gr.sizeof_float, str(dump_path / 'clock_recovery_T_avg.f32'),
                False)
            self.connect(self.clock_recovery, self.clock_recovery_out)
            self.connect((self.clock_recovery, 1), self.clock_recovery_err)
            self.connect((self.clock_recovery, 2), self.clock_recovery_T_inst)
            self.connect((self.clock_recovery, 3), self.clock_recovery_T_avg)

        conns = [self.demod]
        if subaudio:
            conns.append(self.subaudio_lowpass)
        conns.append(self.lowpass)
        if dc_block:
            conns.append(self.dcblock)
        self.connect(*conns)
        if use_agc:
            self.connect(self.dcblock, self.agc, self.clock_recovery)
            if dump_path is not None:
                self.connect(self.agc, self.waveform)
        else:
            self.connect(self.dcblock, self.clock_recovery)
            if dump_path is not None:
                self.connect(self.dcblock, self.waveform)
        self.connect(self.clock_recovery, self)
Example #46
0
    def __init__(self, fft_length, cp_length, carrier_num, logging=False):
        """
        OFDM synchronization using PN Correlation:
        T. M. Schmidl and D. C. Cox, "Robust Frequency and Timing
        Synchonization for OFDM," IEEE Trans. Communications, vol. 45,
        no. 12, 1997.
        """
        
	gr.hier_block2.__init__(self, "ofdm_sync_pn",
				gr.io_signature(1, 1, gr.sizeof_gr_complex), # Input signature
                                gr.io_signature2(2, 2, gr.sizeof_float, gr.sizeof_char)) # Output signature

        self.input = blocks.add_const_cc(0)

        # PN Sync

        # Create a delay line
        self.delay = blocks.delay(gr.sizeof_gr_complex, fft_length/2)

        # Correlation from ML Sync
        self.conjg = blocks.conjugate_cc();
        self.corr = blocks.multiply_cc();

        # Create a moving sum filter for the corr output
        if 1:
            moving_sum_taps = [1.0 for i in range(fft_length//2)]
            self.moving_sum_filter = filter.fir_filter_ccf(1,moving_sum_taps)
        else:
            moving_sum_taps = [complex(1.0,0.0) for i in range(fft_length//2)]
            self.moving_sum_filter = filter.fft_filter_ccc(1,moving_sum_taps)

        # Create a moving sum filter for the input
        self.inputmag2 = blocks.complex_to_mag_squared()
        movingsum2_taps = [1.0 for i in range(fft_length//2)]

        if 1:
            self.inputmovingsum = filter.fir_filter_fff(1,movingsum2_taps)
        else:
            self.inputmovingsum = filter.fft_filter_fff(1,movingsum2_taps)

        self.square = blocks.multiply_ff()
        self.normalize = blocks.divide_ff()
     
        # Get magnitude (peaks) and angle (phase/freq error)
        self.c2mag = blocks.complex_to_mag_squared()
        self.angle = blocks.complex_to_arg()

        self.sample_and_hold = gr_papyrus.sample_and_hold_ff()

        #ML measurements input to sampler block and detect
        self.sub1 = blocks.add_const_ff(-1)
        # linklab, change peak detector parameters: use higher threshold to detect rise/fall of peak
        #self.pk_detect = gr.peak_detector_fb(0.20, 0.20, 30, 0.001)
        self.pk_detect = gr_papyrus.peak_detector_fb(0.50, 0.60, 30, 0.001, carrier_num) # linklab
        #self.pk_detect = gr.peak_detector2_fb(9)

        self.connect(self, self.input)
        
        # Calculate the frequency offset from the correlation of the preamble
        self.connect(self.input, self.delay)
        self.connect(self.input, (self.corr,0))
        self.connect(self.delay, self.conjg)
        self.connect(self.conjg, (self.corr,1))
        self.connect(self.corr, self.moving_sum_filter)
        self.connect(self.moving_sum_filter, self.c2mag)
        self.connect(self.moving_sum_filter, self.angle)
        self.connect(self.angle, (self.sample_and_hold,0))

        # Get the power of the input signal to normalize the output of the correlation
        self.connect(self.input, self.inputmag2, self.inputmovingsum)
        self.connect(self.inputmovingsum, (self.square,0))
        self.connect(self.inputmovingsum, (self.square,1))
        self.connect(self.square, (self.normalize,1))
        self.connect(self.c2mag, (self.normalize,0))

        # Create a moving sum filter for the corr output
        matched_filter_taps = [1.0/cp_length for i in range(cp_length)]
        self.matched_filter = filter.fir_filter_fff(1,matched_filter_taps)
        self.connect(self.normalize, self.matched_filter)
       
        # linklab, provide the signal power into peak detector, linklab
        self.connect(self.square, (self.pk_detect,1))

        #self.connect(self.matched_filter, self.sub1, self.pk_detect)
        self.connect(self.matched_filter, self.sub1, (self.pk_detect, 0))
        #self.connect(self.matched_filter, self.pk_detect)
        self.connect(self.pk_detect, (self.sample_and_hold,1))

        # Set output signals
        #    Output 0: fine frequency correction value
        #    Output 1: timing signal
        self.connect(self.sample_and_hold, (self,0))
        self.connect(self.pk_detect, (self,1))

        if logging:
            self.connect(self.matched_filter, gr.file_sink(gr.sizeof_float, "ofdm_sync_pn-mf_f.dat"))
            self.connect(self.normalize, gr.file_sink(gr.sizeof_float, "ofdm_sync_pn-theta_f.dat"))
            self.connect(self.angle, gr.file_sink(gr.sizeof_float, "ofdm_sync_pn-epsilon_f.dat"))
            self.connect(self.pk_detect, gr.file_sink(gr.sizeof_char, "ofdm_sync_pn-peaks_b.dat"))
            self.connect(self.sample_and_hold, gr.file_sink(gr.sizeof_float, "ofdm_sync_pn-sample_and_hold_f.dat"))
            self.connect(self.input, gr.file_sink(gr.sizeof_gr_complex, "ofdm_sync_pn-input_c.dat"))
Example #47
0
    def __init__(self, k, cl_loop_bandwidth, cl_order, cl_freq_sub, ss_sps,
                 ss_loop_bandwidth, ss_ted_gain, ss_damping, ss_max_dev,
                 ss_out_ss, ss_interpolation, ss_ted_type, ss_constellation,
                 ss_nfilter, ss_pfb_mf_taps, sel_costas, sel_spl, samp_rate):
        gr.hier_block2.__init__(
            self,
            "demodulator",
            gr.io_signature(1, 1, gr.sizeof_float),  # Input signature
            gr.io_signature(1, 1, gr.sizeof_char))  # Output signature

        ##################################################
        # Variables
        ##################################################
        self.k = k
        self.cl_loop_bandwidth = cl_loop_bandwidth
        self.cl_order = cl_order
        self.cl_freq_sub = cl_freq_sub

        self.ss_sps = ss_sps
        self.ss_loop_bandwidth = ss_loop_bandwidth
        self.ss_ted_gain = ss_ted_gain
        self.ss_damping = ss_damping
        self.ss_max_dev = ss_max_dev
        self.ss_out_ss = ss_out_ss
        self.ss_interpolation = ss_interpolation
        self.ss_ted_type = ss_ted_type
        self.ss_constellation = ss_constellation
        self.ss_nfilter = ss_nfilter
        self.ss_pfb_mf_taps = ss_pfb_mf_taps

        self.sel_costas = sel_costas
        self.sel_spl = sel_spl
        self.samp_rate = samp_rate

        ##################################################
        # Blocks
        ##################################################

        self.digital_sync = digital.symbol_sync_ff(
            self.ss_ted_type, self.ss_sps, self.ss_loop_bandwidth,
            self.ss_damping, self.ss_ted_gain, self.ss_max_dev, self.ss_out_ss,
            self.ss_constellation, self.ss_interpolation, self.ss_nfilter,
            (self.ss_pfb_mf_taps))

        self.spl_decoder = ecss.spl_decoder()

        self.costas_loop_cc = digital.costas_loop_cc(self.cl_loop_bandwidth,
                                                     self.cl_order, False)
        self.signal_gen = analog.sig_source_c(samp_rate, analog.GR_SIN_WAVE,
                                              self.cl_freq_sub, 1, 0)
        self.multiply = blocks.multiply_vcc(1)

        self.hilbert = filter.hilbert_fc(65, firdes.WIN_HAMMING, 6.76)
        self.null_complex = blocks.null_sink(gr.sizeof_gr_complex * 1)
        self.null_float = blocks.null_sink(gr.sizeof_float * 1)
        self.to_char = blocks.float_to_uchar()
        self.unpack = blocks.unpack_k_bits_bb(k)

        ##################################################
        # Connections
        ##################################################

        if (sel_costas == 0):
            # if (type == 0):
            #     self.connect(self, (self.multiply, 0))
            # else:
            self.connect(self, self.hilbert, (self.multiply, 0))

            self.connect(self.signal_gen, (self.multiply, 1))
            self.connect(self.multiply, self.costas_loop_cc)
            self.connect((self.costas_loop_cc, 0), self.null_complex)
            self.connect((self.costas_loop_cc, 1), self.null_float)
            self.connect((self.costas_loop_cc, 2), self.digital_sync)
        else:
            self.connect(self, self.digital_sync)

        if (sel_spl == 0):
            self.connect(self.digital_sync, self.spl_decoder, self.unpack,
                         self)
        else:
            self.connect(self.digital_sync, self.to_char, self.unpack, self)
Example #48
0
    def __init__(self,
                 samples_per_symbol=_def_samples_per_symbol,
                 excess_bw=_def_excess_bw,
                 costas_alpha=_def_costas_alpha,
                 gain_mu=_def_gain_mu,
                 mu=_def_mu,
                 omega_relative_limit=_def_omega_relative_limit,
                 gray_code=_def_gray_code,
                 verbose=_def_verbose,
                 log=_def_log):
        """
	Hierarchical block for RRC-filtered CQPSK demodulation

	The input is the complex modulated signal at baseband.
	The output is a stream of floats in [ -3 / -1 / +1 / +3 ]

	@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 gain_mu: for M&M block
        @type gain_mu: float
        @param mu: for M&M block
        @type mu: float
        @param omega_relative_limit: for M&M block
        @type omega_relative_limit: 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,
            "cqpsk_demod",
            gr.io_signature(1, 1, gr.sizeof_gr_complex),  # Input signature
            gr.io_signature(1, 1, gr.sizeof_float))  # Output signature

        self._samples_per_symbol = samples_per_symbol
        self._excess_bw = excess_bw
        self._costas_alpha = costas_alpha
        self._mm_gain_mu = gain_mu
        self._mm_mu = mu
        self._mm_omega_relative_limit = omega_relative_limit
        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
        scale = (1.0 / 16384.0)
        self.pre_scaler = blocks.multiply_const_cc(
            scale)  # scale the signal from full-range to +-1
        #self.agc = gr.agc2_cc(0.6e-1, 1e-3, 1, 1, 100)
        self.agc = analog.feedforward_agc_cc(16, 2.0)

        # RRC data filter
        ntaps = 11 * samples_per_symbol
        self.rrc_taps = filter.firdes.root_raised_cosine(
            1.0,  # gain
            self._samples_per_symbol,  # sampling rate
            1.0,  # symbol rate
            self._excess_bw,  # excess bandwidth (roll-off factor)
            ntaps)
        self.rrc_filter = filter.interp_fir_filter_ccf(1, self.rrc_taps)

        if not self._mm_gain_mu:
            sbs_to_mm = {
                2: 0.050,
                3: 0.075,
                4: 0.11,
                5: 0.125,
                6: 0.15,
                7: 0.15
            }
            self._mm_gain_mu = sbs_to_mm[samples_per_symbol]

        self._mm_omega = self._samples_per_symbol
        self._mm_gain_omega = .25 * self._mm_gain_mu * self._mm_gain_mu
        self._costas_beta = 0.25 * self._costas_alpha * self._costas_alpha
        fmin = -0.025
        fmax = 0.025

        self.receiver = digital.mpsk_receiver_cc(arity, pi / 4.0, 2 * pi / 150,
                                                 fmin, fmax, self._mm_mu,
                                                 self._mm_gain_mu,
                                                 self._mm_omega,
                                                 self._mm_gain_omega,
                                                 self._mm_omega_relative_limit)

        self.receiver.set_alpha(self._costas_alpha)
        self.receiver.set_beta(self._costas_beta)

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

        # take angle of the difference (in radians)
        self.to_float = blocks.complex_to_arg()

        # convert from radians such that signal is in -3/-1/+1/+3
        self.rescale = blocks.multiply_const_ff(1 / (pi / 4))

        if verbose:
            self._print_verbage()

        if log:
            self._setup_logging()

        # Connect & Initialize base class
        self.connect(self, self.pre_scaler, self.agc, self.rrc_filter,
                     self.receiver, self.diffdec, self.to_float, self.rescale,
                     self)
    def __init__(self,
                 dab_params,
                 bit_rate,
                 address,
                 subch_size,
                 protection,
                 output_float,
                 verbose=False,
                 debug=False):
        if output_float:  # map short samples to the range [-1,1] in floats
            gr.hier_block2.__init__(
                self,
                "dabplus_audio_decoder_ff",
                # Input signature
                gr.io_signature(1, 1,
                                gr.sizeof_float * dab_params.num_carriers * 2),
                # Output signature
                gr.io_signature2(2, 2, gr.sizeof_float, gr.sizeof_float))
        else:  # output signed 16 bit integers (directly from decoder)
            gr.hier_block2.__init__(
                self,
                "dabplus_audio_decoder_ff",
                # Input signature
                gr.io_signature(1, 1,
                                gr.sizeof_float * dab_params.num_carriers * 2),
                # Output signature
                gr.io_signature2(2, 2, gr.sizeof_short, gr.sizeof_short))
        self.dp = dab_params
        self.bit_rate_n = bit_rate / 8
        self.address = address
        self.size = subch_size
        self.protection = protection
        self.output_float = output_float
        self.verbose = verbose
        self.debug = debug

        # sanity check
        # if self.bit_rate_n*6 != self.size:
        #     log = gr.logger("log")
        #     log.debug("bit rate and subchannel size are not fitting")
        #     log.set_level("ERROR")
        #     raise ValueError

        # MSC decoder extracts logical frames out of transmission frame and decodes it
        self.msc_decoder = grdab.msc_decode(self.dp, self.address, self.size,
                                            self.protection, self.verbose,
                                            self.debug)
        # firecode synchronizes to superframes and checks
        self.firecode = grdab.firecode_check_bb_make(self.bit_rate_n)
        # Reed-Solomon error repair
        self.rs = grdab.reed_solomon_decode_bb_make(self.bit_rate_n)
        # mp4 decoder
        self.mp4 = grdab.mp4_decode_bs_make(self.bit_rate_n)

        self.connect((self, 0), self.msc_decoder, self.firecode, self.rs,
                     self.mp4)

        if self.output_float:
            # map short samples to the range [-1,1] in floats
            self.s2f_left = blocks.short_to_float_make(1, 32767)
            self.s2f_right = blocks.short_to_float_make(1, 32767)
            self.gain_left = blocks.multiply_const_ff(1, 1)
            self.gain_right = blocks.multiply_const_ff(1, 1)
            self.connect((self.mp4, 0), self.s2f_left, self.gain_left,
                         (self, 0))
            self.connect((self.mp4, 1), self.s2f_right, self.gain_right,
                         (self, 1))
        else:
            # output signed 16 bit integers (directly from decoder)
            self.connect((self.mp4, 0), (self, 0))
            self.connect((self.mp4, 1), (self, 1))
Example #50
0
    def __init__(self, options, payload='', msgq_limit=2, pad_for_usrp=False):
        """
	Hierarchical block for sending packets

        Packets to be sent are enqueued by calling send_pkt.
        The output is the complex modulated signal at baseband.

        @param options: pass modulation options from higher layers (fft length, occupied tones, etc.)
        @param msgq_limit: maximum number of messages in message queue
        @type msgq_limit: int
        @param pad_for_usrp: If true, packets are padded such that they end up a multiple of 128 samples
        """

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

        self._fft_length = 64
        self._total_sub_carriers = 53
        self._data_subcarriers = 48
        self._cp_length = 16
        self._regime = options.regime
        self._symbol_length = self._fft_length + self._cp_length
        self._role = options.role

        # assuming we have 100Ms/s going to the USRP2 and 80 samples per symbol
        # we can calculate the OFDM symboltime (in microseconds)
        # depending on the interpolation factor
        self._symbol_time = options.interp * (self._fft_length +
                                              self._cp_length) / 100

        win = []

        if (self._regime == "1" or self._regime == "2"):
            rotated_const = ofdm_packet_utils.bpsk(self)

        elif (self._regime == "3" or self._regime == "4"):
            rotated_const = ofdm_packet_utils.qpsk(self)

        elif (self._regime == "5" or self._regime == "6"):
            rotated_const = ofdm_packet_utils.qam16(self)

        elif (self._regime == "7" or self._regime == "8"):
            rotated_const = ofdm_packet_utils.qam64(self)

        # map groups of bits to complex symbols
        self._pkt_input = ftw.ofdm_mapper(rotated_const, msgq_limit,
                                          self._data_subcarriers,
                                          self._fft_length)

        # insert pilot symbols (use pnc block * by lzyou)
        if self._role == 'A':
            print " >>> [FPNC]: *A* Insert Pilot"
            self.pilot = ftw.pnc_ofdm_pilot_cc(self._data_subcarriers, 1)
        elif self._role == 'B':
            print " >>> [FPNC]: *B* Insert Pilot"
            self.pilot = ftw.pnc_ofdm_pilot_cc(self._data_subcarriers, 2)
        else:
            print " >>> [FTW ]: Insert Pilot"
            self.pilot = ftw.ofdm_pilot_cc(self._data_subcarriers)
        # just for test
        #self.pilot = ftw.pnc_ofdm_pilot_cc(self._data_subcarriers, 1)
        #self.pilot = ftw.pnc_ofdm_pilot_cc(self._data_subcarriers, 2)

        # move subcarriers to their designated place and insert DC
        self.cmap = ftw.ofdm_cmap_cc(self._fft_length,
                                     self._total_sub_carriers)

        # inverse fast fourier transform
        self.ifft = gr.fft_vcc(self._fft_length, False, win, False)

        # add cyclic prefix
        from gnuradio import digital
        self.cp_adder = digital.ofdm_cyclic_prefixer(self._fft_length,
                                                     self._symbol_length)
        self.connect(
            gr.null_source(gr.sizeof_char),
            (self.cp_adder,
             1))  # Note: dirty modification to accomdate the API change

        # scale accordingly
        self.scale = gr.multiply_const_cc(1.0 / math.sqrt(self._fft_length))

        # we need to know the number of OFDM data symbols for preamble and zerogap
        info = ofdm_packet_utils.get_info(payload, options.regime,
                                          self._symbol_time)
        N_sym = info["N_sym"]

        # add training sequence (modify by lzyou)
        if self._role == 'A':
            print " >>> [FPNC]: *A* Insert Preamble"
            self.preamble = ofdm_packet_utils.insert_preamble(
                self._symbol_length, N_sym, 'A')
        elif self._role == 'B':
            print " >>> [FPNC]: *B* Insert Preamble"
            self.preamble = ofdm_packet_utils.insert_preamble(
                self._symbol_length, N_sym, 'B')
        else:
            print " >>> [FTW ]: Insert Preamble"
            self.preamble = ofdm_packet_utils.insert_preamble(
                self._symbol_length, N_sym)

        # append zero samples at the end (receiver needs that to decode)
        if self._role == None:
            print " >>> [FTW ]: Insert Zerogap"
            self.zerogap = ofdm_packet_utils.insert_zerogap(
                self._symbol_length, N_sym)
        else:
            print " >>> [FPNC]: Insert Zerogap"
            self.zerogap = ofdm_packet_utils.insert_zerogap(
                self._symbol_length, N_sym, 'FPNC')

        self.s2v = gr.stream_to_vector(gr.sizeof_gr_complex,
                                       self._symbol_length)
        self.v2s = gr.vector_to_stream(gr.sizeof_gr_complex,
                                       self._symbol_length)

        # swap real and immaginary component before sending (GNURadio/USRP2 bug!)
        if options.swapIQ == True:
            self.gr_complex_to_imag_0 = gr.complex_to_imag(1)
            self.gr_complex_to_real_0 = gr.complex_to_real(1)
            self.gr_float_to_complex_0 = gr.float_to_complex(1)
            self.connect((self.v2s, 0), (self.gr_complex_to_imag_0, 0))
            self.connect((self.v2s, 0), (self.gr_complex_to_real_0, 0))
            self.connect((self.gr_complex_to_real_0, 0),
                         (self.gr_float_to_complex_0, 1))
            self.connect((self.gr_complex_to_imag_0, 0),
                         (self.gr_float_to_complex_0, 0))
            self.connect((self.gr_float_to_complex_0, 0), (self))
        elif options.swapIQ == False:
            self.gr_complex_to_imag_0 = gr.complex_to_imag(1)
            self.gr_complex_to_real_0 = gr.complex_to_real(1)
            self.gr_float_to_complex_0 = gr.float_to_complex(1)
            self.connect((self.v2s, 0), (self.gr_complex_to_imag_0, 0))
            self.connect((self.v2s, 0), (self.gr_complex_to_real_0, 0))
            self.connect((self.gr_complex_to_imag_0, 0),
                         (self.gr_float_to_complex_0, 1))
            self.connect((self.gr_complex_to_real_0, 0),
                         (self.gr_float_to_complex_0, 0))
            self.connect((self.gr_float_to_complex_0, 0), (self))

        # connect the blocks
        self.connect((self._pkt_input, 0), (self.pilot, 0))
        self.connect((self._pkt_input, 1), (self.preamble, 1))
        self.connect((self.preamble, 1), (self.zerogap, 1))

        self.connect(self.pilot, self.cmap, self.ifft, self.cp_adder,
                     self.scale, self.s2v, self.preamble, self.zerogap,
                     self.v2s)

        if options.log:
            self.connect(
                (self._pkt_input),
                gr.file_sink(gr.sizeof_gr_complex * self._data_subcarriers,
                             "ofdm_mapper.dat"))
            self.connect(
                self.pilot,
                gr.file_sink(
                    gr.sizeof_gr_complex * (5 + self._data_subcarriers),
                    "ofdm_pilot.dat"))
            self.connect(
                self.cmap,
                gr.file_sink(gr.sizeof_gr_complex * self._fft_length,
                             "ofdm_cmap.dat"))
            self.connect(
                self.ifft,
                gr.file_sink(gr.sizeof_gr_complex * self._fft_length,
                             "ofdm_ifft.dat"))
            self.connect(
                self.cp_adder,
                gr.file_sink(gr.sizeof_gr_complex, "ofdm_cp_adder.dat"))
            self.connect(self.scale,
                         gr.file_sink(gr.sizeof_gr_complex, "ofdm_scale.dat"))
            self.connect(
                self.preamble,
                gr.file_sink(gr.sizeof_gr_complex * self._symbol_length,
                             "ofdm_preamble.dat"))
            self.connect(
                self.zerogap,
                gr.file_sink(gr.sizeof_gr_complex * self._symbol_length,
                             "ofdm_zerogap.dat"))
Example #51
0
    def __init__(
            self,
            parent,
            x_offset=0,
            ref_level=50,
            #sample_rate=1,
            data_len=512 * 2,
            #fft_rate=waterfall_window.DEFAULT_FRAME_RATE,
            #average=False,
            #avg_alpha=None,
            title='',
            size=waterfall_window.DEFAULT_WIN_SIZE,
            ref_scale=2.0,
            dynamic_range=80,
            num_lines=256,
            win=None,
            always_run=False,
            **kwargs  #do not end with a comma
    ):
        #ensure avg alpha
        #if avg_alpha is None: avg_alpha = 2.0/fft_rate
        #init
        gr.hier_block2.__init__(
            self,
            "waterfall_sink",
            gr.io_signature(1, 1, gr.sizeof_float * data_len),
            gr.io_signature(0, 0, 0),
        )
        #blocks
        msgq = gr.msg_queue(2)
        sink = blocks.message_sink(gr.sizeof_float * data_len, msgq, True)
        #controller
        self.controller = pubsub()
        #start input watcher
        common.input_watcher(msgq, self.controller, MSG_KEY)
        #create window
        self.win = waterfall_window.waterfall_window(
            parent=parent,
            controller=self.controller,
            size=size,
            title=title,
            data_len=data_len,
            num_lines=num_lines,
            x_offset=x_offset,
            #decimation_key=DECIMATION_KEY,
            #sample_rate_key=SAMPLE_RATE_KEY,
            #frame_rate_key=FRAME_RATE_KEY,
            dynamic_range=dynamic_range,
            ref_level=ref_level,
            #average_key=AVERAGE_KEY,
            #avg_alpha_key=AVG_ALPHA_KEY,
            msg_key=MSG_KEY,
        )
        common.register_access_methods(self, self.win)
        setattr(self.win, 'set_baseband_freq',
                getattr(self, 'set_baseband_freq'))  #BACKWARDS	# FIXME
        #connect
        if always_run:
            connect_fn = self.connect
        else:
            connect_fn = self.wxgui_connect

        connect_fn(self, sink)
Example #52
0
    def __init__(self, demod_rate, audio_decimation):
        """
        Hierarchical block for demodulating a broadcast FM signal.

        The input is the downconverted complex baseband signal
        (gr_complex).  The output is two streams of the demodulated
        audio (float) 0=Left, 1=Right.

        Args:
            demod_rate: input sample rate of complex baseband input. (float)
            audio_decimation: how much to decimate demod_rate to get to audio. (integer)
        """
        gr.hier_block2.__init__(
            self,
            "wfm_rcv_fmdet",
            gr.io_signature(1, 1, gr.sizeof_gr_complex),  # Input signature
            gr.io_signature(2, 2, gr.sizeof_float))  # Output signature
        lowfreq = -125e3 / demod_rate
        highfreq = 125e3 / demod_rate
        audio_rate = demod_rate / audio_decimation

        # We assign to self so that outsiders can grab the demodulator
        # if they need to.  E.g., to plot its output.
        #
        # input: complex; output: float

        self.fm_demod = analog.fmdet_cf(demod_rate, lowfreq, highfreq, 0.05)

        # input: float; output: float
        self.deemph_Left = fm_deemph(audio_rate)
        self.deemph_Right = fm_deemph(audio_rate)

        # compute FIR filter taps for audio filter
        width_of_transition_band = audio_rate / 32
        audio_coeffs = filter.firdes.low_pass(
            1.0,  # gain
            demod_rate,  # sampling rate
            15000,
            width_of_transition_band,
            filter.firdes.WIN_HAMMING)

        # input: float; output: float
        self.audio_filter = filter.fir_filter_fff(audio_decimation,
                                                  audio_coeffs)
        if 1:
            # Pick off the stereo carrier/2 with this filter. It
            # attenuated 10 dB so apply 10 dB gain We pick off the
            # negative frequency half because we want to base band by
            # it!
            ##  NOTE THIS WAS HACKED TO OFFSET INSERTION LOSS DUE TO
            ##  DEEMPHASIS

            stereo_carrier_filter_coeffs = \
                filter.firdes.complex_band_pass(10.0,
                                                demod_rate,
                                                -19020,
                                                -18980,
                                                width_of_transition_band,
                                                filter.firdes.WIN_HAMMING)

            #print "len stereo carrier filter = ",len(stereo_carrier_filter_coeffs)
            #print "stereo carrier filter ", stereo_carrier_filter_coeffs
            #print "width of transition band = ",width_of_transition_band, " audio rate = ", audio_rate

            # Pick off the double side band suppressed carrier
            # Left-Right audio. It is attenuated 10 dB so apply 10 dB
            # gain

            stereo_dsbsc_filter_coeffs = \
                filter.firdes.complex_band_pass(20.0,
                                                demod_rate,
                                                38000-15000 / 2,
                                                38000+15000 / 2,
                                                width_of_transition_band,
                                                filter.firdes.WIN_HAMMING)
            #print "len stereo dsbsc filter = ",len(stereo_dsbsc_filter_coeffs)
            #print "stereo dsbsc filter ", stereo_dsbsc_filter_coeffs

            # construct overlap add filter system from coefficients
            # for stereo carrier
            self.stereo_carrier_filter = \
                filter.fir_filter_fcc(audio_decimation,
                                      stereo_carrier_filter_coeffs)

            # carrier is twice the picked off carrier so arrange to do
            # a complex multiply
            self.stereo_carrier_generator = blocks.multiply_cc()

            # Pick off the rds signal
            stereo_rds_filter_coeffs = \
                filter.firdes.complex_band_pass(30.0,
                                                demod_rate,
                                                57000 - 1500,
                                                57000 + 1500,
                                                width_of_transition_band,
                                                filter.firdes.WIN_HAMMING)
            #print "len stereo dsbsc filter = ",len(stereo_dsbsc_filter_coeffs)
            #print "stereo dsbsc filter ", stereo_dsbsc_filter_coeffs
            # construct overlap add filter system from coefficients for stereo carrier

            self.rds_signal_filter = \
                filter.fir_filter_fcc(audio_decimation,
                                      stereo_rds_filter_coeffs)
            self.rds_carrier_generator = blocks.multiply_cc()
            self.rds_signal_generator = blocks.multiply_cc()
            self_rds_signal_processor = blocks.null_sink(gr.sizeof_gr_complex)

            loop_bw = 2 * math.pi / 100.0
            max_freq = -2.0 * math.pi * 18990 / audio_rate
            min_freq = -2.0 * math.pi * 19010 / audio_rate
            self.stereo_carrier_pll_recovery = analog.pll_refout_cc(
                loop_bw, max_freq, min_freq)

            #self.stereo_carrier_pll_recovery.squelch_enable(False)
            ##pll_refout does not have squelch yet, so disabled for
            #now

            # set up mixer (multiplier) to get the L-R signal at
            # baseband

            self.stereo_basebander = blocks.multiply_cc()

            # pick off the real component of the basebanded L-R
            # signal.  The imaginary SHOULD be zero

            self.LmR_real = blocks.complex_to_real()
            self.Make_Left = blocks.add_ff()
            self.Make_Right = blocks.sub_ff()

            self.stereo_dsbsc_filter = \
                filter.fir_filter_fcc(audio_decimation,
                                      stereo_dsbsc_filter_coeffs)

        if 1:

            # send the real signal to complex filter to pick off the
            # carrier and then to one side of a multiplier
            self.connect(self, self.fm_demod, self.stereo_carrier_filter,
                         self.stereo_carrier_pll_recovery,
                         (self.stereo_carrier_generator, 0))

            # send the already filtered carrier to the otherside of the carrier
            # the resulting signal from this multiplier is the carrier
            # with correct phase but at -38000 Hz.
            self.connect(self.stereo_carrier_pll_recovery,
                         (self.stereo_carrier_generator, 1))

            # send the new carrier to one side of the mixer (multiplier)
            self.connect(self.stereo_carrier_generator,
                         (self.stereo_basebander, 0))

            # send the demphasized audio to the DSBSC pick off filter,  the complex
            # DSBSC signal at +38000 Hz is sent to the other side of the mixer/multiplier
            # the result is BASEBANDED DSBSC with phase zero!
            self.connect(self.fm_demod, self.stereo_dsbsc_filter,
                         (self.stereo_basebander, 1))

            # Pick off the real part since the imaginary is
            # theoretically zero and then to one side of a summer
            self.connect(self.stereo_basebander, self.LmR_real,
                         (self.Make_Left, 0))

            #take the same real part of the DSBSC baseband signal and
            #send it to negative side of a subtracter
            self.connect(self.LmR_real, (self.Make_Right, 1))

            # Make rds carrier by taking the squared pilot tone and
            # multiplying by pilot tone
            self.connect(self.stereo_basebander,
                         (self.rds_carrier_generator, 0))
            self.connect(self.stereo_carrier_pll_recovery,
                         (self.rds_carrier_generator, 1))

            # take signal, filter off rds, send into mixer 0 channel
            self.connect(self.fm_demod, self.rds_signal_filter,
                         (self.rds_signal_generator, 0))

            # take rds_carrier_generator output and send into mixer 1
            # channel
            self.connect(self.rds_carrier_generator,
                         (self.rds_signal_generator, 1))

            # send basebanded rds signal and send into "processor"
            # which for now is a null sink
            self.connect(self.rds_signal_generator, self_rds_signal_processor)

        if 1:
            # pick off the audio, L+R that is what we used to have and
            # send it to the summer
            self.connect(self.fm_demod, self.audio_filter, (self.Make_Left, 1))

            # take the picked off L+R audio and send it to the PLUS
            # side of the subtractor
            self.connect(self.audio_filter, (self.Make_Right, 0))

            # The result of  Make_Left  gets    (L+R) +  (L-R) and results in 2*L
            # The result of Make_Right gets  (L+R) - (L-R) and results in 2*R
            self.connect(self.Make_Left, self.deemph_Left, (self, 0))
            self.connect(self.Make_Right, self.deemph_Right, (self, 1))
Example #53
0
    def __init__(self,
                 samples_per_symbol=_def_samples_per_symbol,
                 sensitivity=_def_sensitivity,
                 gain_mu=_def_gain_mu,
                 mu=_def_mu,
                 omega_relative_limit=_def_omega_relative_limit,
                 freq_error=_def_freq_error,
                 verbose=_def_verbose,
                 log=_def_log):
        """
        Hierarchical block for Gaussian Minimum Shift Key (GFSK)
        demodulation.

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

        Args:
            samples_per_symbol: samples per baud (integer)
            verbose: Print information about modulator? (bool)
            log: Print modualtion data to files? (bool)

        Clock recovery parameters.  These all have reasonable defaults.

        Args:
            gain_mu: controls rate of mu adjustment (float)
            mu: fractional delay [0.0, 1.0] (float)
            omega_relative_limit: sets max variation in omega (float, typically 0.000200 (200 ppm))
            freq_error: bit rate error as a fraction
            float:
        """

        gr.hier_block2.__init__(
            self,
            "gfsk_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._gain_mu = gain_mu
        self._mu = mu
        self._omega_relative_limit = omega_relative_limit
        self._freq_error = freq_error
        self._differential = False

        if samples_per_symbol < 2:
            raise TypeError("samples_per_symbol >= 2, is %f" %
                            samples_per_symbol)

        self._omega = samples_per_symbol * (1 + self._freq_error)

        if not self._gain_mu:
            self._gain_mu = 0.175

        self._gain_omega = .25 * self._gain_mu * self._gain_mu  # critically damped

        # Demodulate FM
        #sensitivity = (pi / 2) / samples_per_symbol
        self.fmdemod = analog.quadrature_demod_cf(1.0 / sensitivity)

        # the clock recovery block tracks the symbol clock and resamples as needed.
        # the output of the block is a stream of soft symbols (float)
        self.clock_recovery = digital.clock_recovery_mm_ff(
            self._omega, self._gain_omega, self._mu, self._gain_mu,
            self._omega_relative_limit)

        # slice the floats at 0, outputting 1 bit (the LSB of the output byte) per sample
        self.slicer = digital.binary_slicer_fb()

        if verbose:
            self._print_verbage()

        if log:
            self._setup_logging()

        # Connect & Initialize base class
        self.connect(self, self.fmdemod, self.clock_recovery, self.slicer,
                     self)
Example #54
0
    def __init__(self,
                 dest=_def_dest,
                 do_imbe=_def_do_imbe,
                 num_ambe=_def_num_ambe,
                 wireshark_host=_def_wireshark_host,
                 udp_port=_def_udp_port,
                 do_msgq=False,
                 msgq=None,
                 audio_output=_def_audio_output,
                 debug=_def_debug):
        """
	Hierarchical block for P25 decoding.

        @param debug: debug level
        @type debug: int
	"""

        gr.hier_block2.__init__(
            self,
            "p25_demod_c",
            gr.io_signature(1, 1, gr.sizeof_char),  # Input signature
            gr.io_signature(0, 0, 0))  # Output signature

        assert 0 <= num_ambe <= _def_max_tdma_timeslots
        assert not (num_ambe > 1 and dest != 'wav')

        self.debug = debug
        self.dest = dest
        do_output = 1
        do_audio_output = True

        if msgq is None:
            msgq = gr.msg_queue(1)

        self.p25_decoders = []
        self.audio_s2f = []
        self.scaler = []
        self.audio_sink = []
        self.xorhash = []
        num_decoders = 1
        if num_ambe > 1:
            num_decoders += num_ambe - 1
        for slot in xrange(num_decoders):
            self.p25_decoders.append(
                op25_repeater.p25_frame_assembler(wireshark_host, udp_port,
                                                  debug, do_imbe, do_output,
                                                  do_msgq, msgq,
                                                  do_audio_output, True))
            self.p25_decoders[slot].set_slotid(slot)

            self.audio_s2f.append(
                blocks.short_to_float())  # another ridiculous conversion
            self.scaler.append(blocks.multiply_const_ff(1 / 32768.0))
            self.xorhash.append('')

            if dest == 'wav':
                filename = 'default-%f-%d.wav' % (time.time(), slot)
                n_channels = 1
                sample_rate = 8000
                bits_per_sample = 16
                self.audio_sink.append(
                    blocks.wavfile_sink(filename, n_channels, sample_rate,
                                        bits_per_sample))
            elif dest == 'audio':
                self.audio_sink.append(
                    audio.sink(_def_audio_rate, audio_output, True))

            self.connect(self, self.p25_decoders[slot], self.audio_s2f[slot],
                         self.scaler[slot], self.audio_sink[slot])
Example #55
0
    def __init__(
            self,
            parent,
            baseband_freq=0,
            ref_scale=2.0,
            y_per_div=10,
            y_divs=8,
            ref_level=50,
            sample_rate=1,
            pspectrum_len=512,
            specest_rate=specest_window.DEFAULT_FRAME_RATE,
            average=False,
            avg_alpha=None,
            title='',
            size=specest_window.DEFAULT_WIN_SIZE,
            peak_hold=False,
            use_persistence=False,
            persist_alpha=None,
            n=1,
            m=150,
            nsamples=256,
            estimator='esprit',
            **kwargs  #do not end with a comma
    ):
        #ensure avg alpha
        if avg_alpha is None: avg_alpha = 2.0 / specest_rate
        #ensure analog alpha
        if persist_alpha is None:
            actual_specest_rate = float(sample_rate / pspectrum_len) / float(
                max(1, int(float(
                    (sample_rate / pspectrum_len) / specest_rate))))
            #print "requested_specest_rate ",specest_rate
            #print "actual_specest_rate    ",actual_specest_rate
            analog_cutoff_freq = 0.5  # Hertz
            #calculate alpha from wanted cutoff freq
            persist_alpha = 1.0 - math.exp(
                -2.0 * math.pi * analog_cutoff_freq / actual_specest_rate)

        #init
        gr.hier_block2.__init__(
            self,
            "spectrum_sink",
            gr.io_signature(1, 1, self._item_size),
            gr.io_signature(0, 0, 0),
        )
        #blocks
        fft = self._specest_chain(sample_rate=sample_rate,
                                  pspectrum_len=pspectrum_len,
                                  frame_rate=specest_rate,
                                  ref_scale=ref_scale,
                                  avg_alpha=avg_alpha,
                                  average=average,
                                  n=n,
                                  m=m,
                                  nsamples=nsamples,
                                  estimator=estimator)
        msgq = gr.msg_queue(2)
        sink = blocks.message_sink(gr.sizeof_float * pspectrum_len, msgq, True)

        #controller
        self.controller = pubsub()
        self.controller.subscribe(AVERAGE_KEY, fft.set_average)
        self.controller.publish(AVERAGE_KEY, fft.average)
        self.controller.subscribe(AVG_ALPHA_KEY, fft.set_avg_alpha)
        self.controller.publish(AVG_ALPHA_KEY, fft.avg_alpha)
        self.controller.subscribe(SAMPLE_RATE_KEY, fft.set_sample_rate)
        self.controller.publish(SAMPLE_RATE_KEY, fft.sample_rate)
        #start input watcher
        common.input_watcher(msgq, self.controller, MSG_KEY)
        #create window
        self.win = specest_window.specest_window(
            parent=parent,
            controller=self.controller,
            size=size,
            title=title,
            real=self._real,
            spectrum_len=pspectrum_len,
            baseband_freq=baseband_freq,
            sample_rate_key=SAMPLE_RATE_KEY,
            y_per_div=y_per_div,
            y_divs=y_divs,
            ref_level=ref_level,
            average_key=AVERAGE_KEY,
            avg_alpha_key=AVG_ALPHA_KEY,
            peak_hold=peak_hold,
            msg_key=MSG_KEY,
            use_persistence=use_persistence,
            persist_alpha=persist_alpha,
        )
        common.register_access_methods(self, self.win)
        setattr(self.win, 'set_baseband_freq',
                getattr(self, 'set_baseband_freq'))  #BACKWARDS
        setattr(self.win, 'set_peak_hold',
                getattr(self, 'set_peak_hold'))  #BACKWARDS
        #connect
        self.wxgui_connect(self, fft, sink)
Example #56
0
    def __init__(self,
                 samples_per_symbol=_def_samples_per_symbol,
                 sensitivity=_def_sensitivity,
                 bt=_def_bt,
                 verbose=_def_verbose,
                 log=_def_log):
        """
        Hierarchical block for Gaussian Frequency Shift Key (GFSK)
        modulation.

        The input is a byte stream (unsigned char) and the
        output is the complex modulated signal at baseband.

        Args:
            samples_per_symbol: samples per baud >= 2 (integer)
            bt: Gaussian filter bandwidth * symbol time (float)
            verbose: Print information about modulator? (bool)
            debug: Print modualtion data to files? (bool)
        """

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

        samples_per_symbol = int(samples_per_symbol)
        self._samples_per_symbol = samples_per_symbol
        self._bt = bt
        self._differential = False

        if not isinstance(samples_per_symbol, int) or samples_per_symbol < 2:
            raise TypeError(
                "samples_per_symbol must be an integer >= 2, is %r" %
                (samples_per_symbol, ))

        ntaps = 4 * samples_per_symbol  # up to 3 bits in filter at once
        #sensitivity = (pi / 2) / samples_per_symbol	# phase change per bit = pi / 2

        # Turn it into NRZ data.
        #self.nrz = digital.bytes_to_syms()
        self.unpack = blocks.packed_to_unpacked_bb(1, gr.GR_MSB_FIRST)
        self.nrz = digital.chunks_to_symbols_bf([-1, 1])

        # Form Gaussian filter
        # Generate Gaussian response (Needs to be convolved with window below).
        self.gaussian_taps = filter.firdes.gaussian(
            1.0,  # gain
            samples_per_symbol,  # symbol_rate
            bt,  # bandwidth * symbol time
            ntaps  # number of taps
        )

        self.sqwave = (1, ) * samples_per_symbol  # rectangular window
        self.taps = numpy.convolve(numpy.array(self.gaussian_taps),
                                   numpy.array(self.sqwave))
        self.gaussian_filter = filter.interp_fir_filter_fff(
            samples_per_symbol, self.taps)

        # FM modulation
        self.fmmod = analog.frequency_modulator_fc(sensitivity)

        # small amount of output attenuation to prevent clipping USRP sink
        self.amp = blocks.multiply_const_cc(0.999)

        if verbose:
            self._print_verbage()

        if log:
            self._setup_logging()

        # Connect & Initialize base class
        self.connect(self, self.unpack, self.nrz, self.gaussian_filter,
                     self.fmmod, self.amp, self)
Example #57
0
 def __init__(self, *args, **kwds):
     gr.hier_block2.__init__(self, "horizons", gr.io_signature(0, 0, 0),
                             gr.io_signature(0, 0, 0))
     self.thread = h.horizons_thread(*args, auto_start=False, **kwds)
Example #58
0
    def __init__(self,
                 phase_noise_mag=0,
                 magbal=0,
                 phasebal=0,
                 q_ofs=0,
                 i_ofs=0,
                 freq_offset=0,
                 gamma=0,
                 beta=0):
        gr.hier_block2.__init__(
            self,
            "Radio Impairments Model",
            gr.io_signature(1, 1, gr.sizeof_gr_complex * 1),
            gr.io_signature(1, 1, gr.sizeof_gr_complex * 1),
        )

        ##################################################
        # Parameters
        ##################################################
        self.phase_noise_mag = phase_noise_mag
        self.magbal = magbal
        self.phasebal = phasebal
        self.q_ofs = q_ofs
        self.i_ofs = i_ofs
        self.freq_offset = freq_offset
        self.gamma = gamma
        self.beta = beta

        ##################################################
        # Blocks
        ##################################################
        self.phase_noise = phase_noise_gen(10.0**(phase_noise_mag / 20.0), .01)
        self.iq_imbalance = iqbal_gen(magbal, phasebal)
        self.channels_distortion_3_gen_0 = distortion_3_gen(beta)
        self.channels_distortion_2_gen_0 = distortion_2_gen(gamma)
        self.freq_modulator = blocks.multiply_cc()
        self.freq_offset_gen = analog.sig_source_c(1.0, analog.GR_COS_WAVE,
                                                   freq_offset, 1, 0)
        self.freq_modulator_dcoffs = blocks.multiply_cc()
        self.freq_offset_conj = blocks.conjugate_cc()
        self.dc_offset = blocks.add_const_vcc((i_ofs + q_ofs * 1j, ))

        ##################################################
        # Frequency offset
        self.connect((self, 0), (self.freq_modulator, 1))
        self.connect((self.freq_offset_gen, 0), (self.freq_offset_conj, 0))
        self.connect((self.freq_offset_conj, 0), (self.freq_modulator, 0))
        # Most distortions can be strung in a row
        self.connect(
            (self.freq_modulator, 0),
            (self.phase_noise, 0),
            (self.channels_distortion_3_gen_0, 0),
            (self.channels_distortion_2_gen_0, 0),
            (self.iq_imbalance, 0),
            (self.dc_offset, 0),
        )
        # Frequency offset again
        self.connect((self.freq_offset_gen, 0),
                     (self.freq_modulator_dcoffs, 0))
        self.connect((self.dc_offset, 0), (self.freq_modulator_dcoffs, 1))
        self.connect((self.freq_modulator_dcoffs, 0), (self, 0))
Example #59
0
 def __init__(self):
     gr.hier_block2.__init__(self,
                             type(self).__name__,
                             gr.io_signature(1, 1, gr.sizeof_gr_complex),
                             gr.io_signature(0, 0, 0))
     self.connect(self, blocks.null_sink(gr.sizeof_gr_complex))
Example #60
0
    def __init__(
        self, top_level_dir, channels=None, start=None, end=None,
        repeat=False, throttle=False,
    ):
        """Initialize source to directory containing Digital RF channels.

        Parameters
        ----------

        top_level_dir : string
            Either a single top level directory containing Digital RF channel
            directories, or a list of such. A directory can be a file system
            path or a url, where the url points to a top level directory. Each
            must be a local path, or start with 'http://'', 'file://'', or
            'ftp://''.


        Other Parameters
        ----------------

        channels : None | string | int | iterable of previous
            If None, use all available channels in alphabetical order.
            Otherwise, use the channels in the order specified in the given
            iterable (a string or int is taken as a single-element iterable).
            A string is used to specify the channel name, while an int is used
            to specify the channel index in the sorted list of available
            channel names.

        start : None | string | long | iterable of previous
            Can be a single value or an iterable of values corresponding to
            `channels` giving the start of the channel's playback.
            If None or '', the start of the channel's available data is used.
            If an integer, it is interpreted as a sample index given in the
            number of samples since the epoch (time_since_epoch*sample_rate).
            If a float, it is interpreted as a timestamp (seconds since epoch).
            If a string, three forms are permitted:
                1) a string which can be evaluated to an integer/float and
                    interpreted as above,
                2) a string beginning with '+' and followed by an integer
                    (float) expression, interpreted as samples (seconds) from
                    the start of the data, and
                3) a time in ISO8601 format, e.g. '2016-01-01T16:24:00Z'

        end : None | string | long | iterable of previous
            Can be a single value or an iterable of values corresponding to
            `channels` giving the end of the channel's playback.
            If None or '', the end of the channel's available data is used.
            See `start` for a description of how this value is interpreted.

        repeat : bool
            If True, loop the data continuously from the start after the end
            is reached. If False, stop after the data is read once.

        throttle : bool
            If True, playback the samples at their recorded sample rate. If
            False, read samples as quickly as possible.

        Notes
        -----

        A top level directory must contain files in the format:
            <channel>/<YYYY-MM-DDTHH-MM-SS/rf@<seconds>.<%03i milliseconds>.h5

        If more than one top level directory contains the same channel_name
        subdirectory, this is considered the same channel. An error is raised
        if their sample rates differ, or if their time periods overlap.

        """
        Reader = DigitalRFReader(top_level_dir)
        available_channel_names = Reader.get_channels()
        self._channel_names = self._get_channel_names(
            channels, available_channel_names,
        )

        if start is None:
            start = [None]*len(self._channel_names)
        try:
            s_iter = iter(start)
        except TypeError:
            s_iter = iter([start])
        if end is None:
            end = [None]*len(self._channel_names)
        try:
            e_iter = iter(end)
        except TypeError:
            e_iter = iter([end])

        # make sources for each channel
        self._channels = []
        for ch, s, e in zip(self._channel_names, s_iter, e_iter):
            chsrc = digital_rf_channel_source(
                os.path.join(top_level_dir, ch), start=s, end=e, repeat=repeat,
            )
            self._channels.append(chsrc)

        out_sig_dtypes = [src.out_sig()[0] for src in self._channels]
        out_sig = gr.io_signaturev(
            len(out_sig_dtypes), len(out_sig_dtypes),
            [s.itemsize for s in out_sig_dtypes],
        )
        in_sig = gr.io_signature(0, 0, 0)

        gr.hier_block2.__init__(
            self,
            name="digital_rf_source",
            input_signature=in_sig,
            output_signature=out_sig,
        )

        msg_port_name = pmt.intern('metadata')
        self.message_port_register_hier_out('metadata')

        for k, src in enumerate(self._channels):
            if throttle:
                throt = gnuradio.blocks.throttle(
                    src.out_sig()[0].itemsize, src._sample_rate,
                    ignore_tags=True,
                )
                self.connect(src, throt, (self, k))
            else:
                self.connect(src, (self, k))
            self.msg_connect(src, msg_port_name, self, msg_port_name)