def test_ccf_000(self):
        N = 1000         # number of samples to use
        fs = 1000        # baseband sampling rate
        rrate = 1.123    # resampling rate

        nfilts = 32
        taps = filter.firdes.low_pass_2(nfilts, nfilts*fs, fs/2, fs/10,
                                        attenuation_dB=80,
                                        window=filter.firdes.WIN_BLACKMAN_hARRIS)

        freq = 100
        data = sig_source_c(fs, freq, 1, N)
        signal = blocks.vector_source_c(data)
        pfb = filter.pfb_arb_resampler_ccf(rrate, taps)
        snk = blocks.vector_sink_c()

        self.tb.connect(signal, pfb, snk)
        self.tb.run() 

        Ntest = 50
        L = len(snk.data())
        t = map(lambda x: float(x)/(fs*rrate), xrange(L))

        phase = 0.53013
        expected_data = map(lambda x: math.cos(2.*math.pi*freq*x+phase) + \
                                1j*math.sin(2.*math.pi*freq*x+phase), t)

        dst_data = snk.data()
        self.assertComplexTuplesAlmostEqual(expected_data[-Ntest:], dst_data[-Ntest:], 3)
예제 #2
0
    def test_ccf_000(self):
        N = 1000  # number of samples to use
        fs = 1000  # baseband sampling rate
        rrate = 1.123  # resampling rate

        nfilts = 32
        taps = filter.firdes.low_pass_2(
            nfilts,
            nfilts * fs,
            fs / 2,
            fs / 10,
            attenuation_dB=80,
            window=filter.firdes.WIN_BLACKMAN_hARRIS)

        freq = 100
        data = sig_source_c(fs, freq, 1, N)
        signal = blocks.vector_source_c(data)
        pfb = filter.pfb_arb_resampler_ccf(rrate, taps)
        snk = blocks.vector_sink_c()

        self.tb.connect(signal, pfb, snk)
        self.tb.run()

        Ntest = 50
        L = len(snk.data())
        t = map(lambda x: float(x) / (fs * rrate), xrange(L))

        phase = 0.53013
        expected_data = map(lambda x: math.cos(2.*math.pi*freq*x+phase) + \
                                1j*math.sin(2.*math.pi*freq*x+phase), t)

        dst_data = snk.data()
        self.assertComplexTuplesAlmostEqual(expected_data[-Ntest:],
                                            dst_data[-Ntest:], 3)
예제 #3
0
    def __init__(self, input_rate, sps):
        gr.hier_block2.__init__(
            self,
            "atsc_rx_filter",
            gr.io_signature(1, 1, gr.sizeof_gr_complex),  # Input signature
            gr.io_signature(1, 1, gr.sizeof_gr_complex))  # Output signature

        # Create matched RX filter with RRC response for fractional
        # interpolator.
        nfilts = 16
        output_rate = ATSC_SYMBOL_RATE * sps  # Desired oversampled sample rate
        filter_rate = input_rate * nfilts
        symbol_rate = ATSC_SYMBOL_RATE / 2.0  # One-sided bandwidth of sideband
        excess_bw = 0.1152  #1.0-(0.5*ATSC_SYMBOL_RATE/ATSC_CHANNEL_BW) # ~10.3%
        ntaps = int((2 * ATSC_RRC_SYMS + 1) * sps * nfilts)
        interp = output_rate / input_rate
        gain = nfilts * symbol_rate / filter_rate
        rrc_taps = filter.firdes.root_raised_cosine(
            gain,  # Filter gain
            filter_rate,  # PFB filter prototype rate
            symbol_rate,  # ATSC symbol rate
            excess_bw,  # ATSC RRC excess bandwidth
            ntaps)  # Length of filter

        pfb = filter.pfb_arb_resampler_ccf(interp, rrc_taps, nfilts)

        # Connect pipeline
        self.connect(self, pfb, self)
예제 #4
0
    def __init__(self):
        gr.top_block.__init__(self)
        parser = OptionParser(option_class=eng_option)

        parser.add_option("-c", "--calibration", type="eng_float", default=0, help="freq offset")
        parser.add_option("-g", "--gain", type="eng_float", default=1)
        parser.add_option("-i", "--input-file", type="string", default="in.dat", help="specify the input file")
        parser.add_option("-o", "--output-file", type="string", default="out.dat", help="specify the output file")
        parser.add_option("-r", "--new-sample-rate", type="int", default=96000, help="output sample rate")
        parser.add_option("-s", "--sample-rate", type="int", default=48000, help="input sample rate")
        (options, args) = parser.parse_args()
 
        sample_rate = options.sample_rate
        new_sample_rate = options.new_sample_rate

        IN = blocks.file_source(gr.sizeof_gr_complex, options.input_file)
        OUT = blocks.file_sink(gr.sizeof_gr_complex, options.output_file)

        LO = analog.sig_source_c(sample_rate, analog.GR_COS_WAVE, options.calibration, 1.0, 0)
        MIXER = blocks.multiply_cc()

        AMP = blocks.multiply_const_cc(options.gain)

        nphases = 32
        frac_bw = 0.05
        p1 = frac_bw
        p2 = frac_bw
        rs_taps = filter.firdes.low_pass(nphases, nphases, p1, p2)
        RESAMP = filter.pfb_arb_resampler_ccf(float(new_sample_rate) / float(sample_rate), (rs_taps), nphases, )

        self.connect(IN, (MIXER, 0))
        self.connect(LO, (MIXER, 1))

        self.connect(MIXER, AMP, RESAMP, OUT)
예제 #5
0
    def __init__(self, input_rate, sps):
        gr.hier_block2.__init__(self, "atsc_rx_filter",
                                gr.io_signature(1, 1, gr.sizeof_gr_complex), # Input signature
                                gr.io_signature(1, 1, gr.sizeof_gr_complex)) # Output signature

        # Create matched RX filter with RRC response for fractional
        # interpolator.
        nfilts = 16
        output_rate = ATSC_SYMBOL_RATE*sps # Desired oversampled sample rate
        filter_rate = input_rate*nfilts
        symbol_rate = ATSC_SYMBOL_RATE / 2.0 # One-sided bandwidth of sideband
        excess_bw = 0.1152 #1.0-(0.5*ATSC_SYMBOL_RATE/ATSC_CHANNEL_BW) # ~10.3%
        ntaps = int((2*ATSC_RRC_SYMS+1)*sps*nfilts)
        interp = output_rate / input_rate
        gain = nfilts*symbol_rate/filter_rate
        rrc_taps = filter.firdes.root_raised_cosine(gain,             # Filter gain
                                                    filter_rate,      # PFB filter prototype rate
                                                    symbol_rate,      # ATSC symbol rate
                                                    excess_bw,        # ATSC RRC excess bandwidth
                                                    ntaps)            # Length of filter

        pfb = filter.pfb_arb_resampler_ccf(interp, rrc_taps, nfilts)

        # Connect pipeline
        self.connect(self, pfb, self)
예제 #6
0
    def test02(self):
        # Test QPSK sync
        M = 4
        theta = 0
        loop_bw = cmath.pi / 100.0
        fmin = -0.5
        fmax = 0.5
        mu = 0.5
        gain_mu = 0.01
        omega = 2
        gain_omega = 0.001
        omega_rel = 0.001

        self.test = digital.mpsk_receiver_cc(M, theta, loop_bw, fmin, fmax, mu,
                                             gain_mu, omega, gain_omega,
                                             omega_rel)

        data = 10000 * [
            complex(0.707, 0.707),
            complex(-0.707, 0.707),
            complex(-0.707, -0.707),
            complex(0.707, -0.707)
        ]
        data = [0.5 * d for d in data]
        self.src = blocks.vector_source_c(data, False)
        self.snk = blocks.vector_sink_c()

        # pulse shaping interpolation filter
        nfilts = 32
        excess_bw = 0.35
        ntaps = 11 * int(omega * nfilts)
        rrc_taps0 = filter.firdes.root_raised_cosine(nfilts, nfilts, 1.0,
                                                     excess_bw, ntaps)
        rrc_taps1 = filter.firdes.root_raised_cosine(1, omega, 1.0, excess_bw,
                                                     11 * omega)
        self.rrc0 = filter.pfb_arb_resampler_ccf(omega, rrc_taps0)
        self.rrc1 = filter.fir_filter_ccf(1, rrc_taps1)

        self.tb.connect(self.src, self.rrc0, self.rrc1, self.test, self.snk)
        self.tb.run()

        expected_result = 10000 * [
            complex(-0.5, +0.0),
            complex(+0.0, -0.5),
            complex(+0.5, +0.0),
            complex(+0.0, +0.5)
        ]

        dst_data = self.snk.data()

        # Only compare last Ncmp samples
        Nstrt = 30000
        Ncmp = 1000
        expected_result = expected_result[Nstrt:Nstrt + Ncmp]
        dst_data = dst_data[Nstrt:Nstrt + Ncmp]

        #for e,d in zip(expected_result, dst_data):
        #    print "{0:+.02f}  {1:+.02f}".format(e, d)

        self.assertComplexTuplesAlmostEqual(expected_result, dst_data, 1)
    def test_001(self):
        # We're using a really simple preamble so that the correlation
        # is straight forward.
        preamble = [0, 0, 0, 1, 0, 0, 0]
        # Our pulse shape has this width (in units of symbols).
        pulse_width = 1.5
        # The number of filters to use for resampling.
        n_filters = 12
        sps = 3
        data = [0]*10 + preamble + [0]*40
        src = blocks.vector_source_c(data)

        # We want to generate taps with a sampling rate of sps=n_filters for resampling
        # purposes.
        pulse_shape = make_parabolic_pulse_shape(sps=n_filters, N=0.5, scale=35)

        # Create our resampling filter to generate the data for the correlator.
        shape = filter.pfb_arb_resampler_ccf(sps, pulse_shape, n_filters)
        # Generate the correlator block itself.
        correlator = digital.correlate_and_sync_cc(preamble, pulse_shape, sps, n_filters)

        # Connect it all up and go.
        snk = blocks.vector_sink_c()
        null = blocks.null_sink(gr.sizeof_gr_complex)
        tb = gr.top_block()
        tb.connect(src, shape, correlator, snk)
        tb.connect((correlator, 1), null)
        tb.run()

        # Look at the tags.  Retrieve the timing offset.
        data = snk.data()
        offset = None
        timing_error = None
        for tag in snk.tags():
            key = pmt.symbol_to_string(tag.key)
            if key == "time_est":
                offset = tag.offset
                timing_error = pmt.to_double(tag.value)
        if offset is None:
            raise ValueError("No tags found.")
        # Detect where the middle of the preamble is.
        # Assume we have only one peak and that it is symmetric.
        sum_id = 0
        sum_d = 0
        for i, d in enumerate(data):
            sum_id += i*abs(d)
            sum_d += abs(d)
        data_i = sum_id/sum_d
        if offset is not None:
            diff = data_i-offset
            remainder = -(diff%sps)
            if remainder < -sps/2.0:
                remainder += sps
        tol = 0.2
        difference = timing_error - remainder
        difference = difference % sps
        if abs(difference) >= tol:
            print("Tag gives timing estimate of {0}. QA calculates it as {1}.  Tolerance is {2}".format(timing_error, remainder, tol))
        self.assertTrue(abs(difference) < tol)
예제 #8
0
    def test02(self):
        # Test QPSK sync
        M = 4
        theta = 0
        loop_bw = cmath.pi/100.0
        fmin = -0.5
        fmax = 0.5
        mu = 0.5
        gain_mu = 0.01
        omega = 2
        gain_omega = 0.001
        omega_rel = 0.001

        self.test = digital.mpsk_receiver_cc(M, theta, loop_bw,
                                             fmin, fmax, mu, gain_mu,
                                             omega, gain_omega,
                                             omega_rel)

        data = 10000*[complex( 0.707,  0.707),
                     complex(-0.707,  0.707), 
                     complex(-0.707, -0.707), 
                     complex( 0.707, -0.707)]
        data = [0.5*d for d in data]
        self.src = blocks.vector_source_c(data, False)
        self.snk = blocks.vector_sink_c()

        # pulse shaping interpolation filter
        nfilts = 32
        excess_bw = 0.35
        ntaps = 11 * int(omega*nfilts)
        rrc_taps0 = filter.firdes.root_raised_cosine(
            nfilts, nfilts, 1.0, excess_bw, ntaps)
        rrc_taps1 = filter.firdes.root_raised_cosine(
            1, omega, 1.0, excess_bw, 11*omega)
        self.rrc0 = filter.pfb_arb_resampler_ccf(omega, rrc_taps0)
        self.rrc1 = filter.fir_filter_ccf(1, rrc_taps1)

        self.tb.connect(self.src, self.rrc0, self.rrc1, self.test, self.snk)
        self.tb.run()
        
        expected_result = 10000*[complex(-0.5, +0.0), complex(+0.0, -0.5),
                                 complex(+0.5, +0.0), complex(+0.0, +0.5)]

        # get data after a settling period
        dst_data = self.snk.data()[200:]

        # Only compare last Ncmp samples
        Ncmp = 1000
        len_e = len(expected_result)
        len_d = len(dst_data)
        expected_result = expected_result[len_e - Ncmp - 1:-1]
        dst_data = dst_data[len_d - Ncmp:]

        #for e,d in zip(expected_result, dst_data):
        #    print "{0:+.02f}  {1:+.02f}".format(e, d)

        self.assertComplexTuplesAlmostEqual(expected_result, dst_data, 1)
    def test01(self):
        # Test BPSK sync
        excess_bw = 0.35

        sps = 4
        loop_bw = cmath.pi/100.0
        nfilts = 32
        init_phase = nfilts/2
        max_rate_deviation = 0.5
        osps = 1
        
        ntaps = 11 * int(sps*nfilts)
        taps = filter.firdes.root_raised_cosine(nfilts, nfilts*sps,
                                                1.0, excess_bw, ntaps)

        self.test = digital.pfb_clock_sync_ccf(sps, loop_bw, taps,
                                               nfilts, init_phase,
                                               max_rate_deviation,
                                               osps)
        
        data = 10000*[complex(1,0), complex(-1,0)]
        self.src = blocks.vector_source_c(data, False)

        # pulse shaping interpolation filter
        rrc_taps = filter.firdes.root_raised_cosine(
            nfilts,          # gain
            nfilts,          # sampling rate based on 32 filters in resampler
            1.0,             # symbol rate
            excess_bw,       # excess bandwidth (roll-off factor)
            ntaps)
        self.rrc_filter = filter.pfb_arb_resampler_ccf(sps, rrc_taps)

        self.snk = blocks.vector_sink_c()

        self.tb.connect(self.src, self.rrc_filter, self.test, self.snk)
        self.tb.run()
        
        expected_result = 10000*[complex(1,0), complex(-1,0)]
        dst_data = self.snk.data()

        # Only compare last Ncmp samples
        Ncmp = 1000
        len_e = len(expected_result)
        len_d = len(dst_data)
        expected_result = expected_result[len_e - Ncmp:]
        dst_data = dst_data[len_d - Ncmp:]

        #for e,d in zip(expected_result, dst_data):
        #    print e, d
        
        self.assertComplexTuplesAlmostEqual(expected_result, dst_data, 1)
예제 #10
0
    def test01(self):
        # Test BPSK sync
        excess_bw = 0.35

        sps = 4
        loop_bw = cmath.pi/100.0
        nfilts = 32
        init_phase = nfilts/2
        max_rate_deviation = 0.5
        osps = 1

        ntaps = 11 * int(sps*nfilts)
        taps = filter.firdes.root_raised_cosine(nfilts, nfilts*sps,
                                                1.0, excess_bw, ntaps)

        self.test = digital.pfb_clock_sync_ccf(sps, loop_bw, taps,
                                               nfilts, init_phase,
                                               max_rate_deviation,
                                               osps)

        data = 10000*[complex(1,0), complex(-1,0)]
        self.src = blocks.vector_source_c(data, False)

        # pulse shaping interpolation filter
        rrc_taps = filter.firdes.root_raised_cosine(
            nfilts,          # gain
            nfilts,          # sampling rate based on 32 filters in resampler
            1.0,             # symbol rate
            excess_bw,       # excess bandwidth (roll-off factor)
            ntaps)
        self.rrc_filter = filter.pfb_arb_resampler_ccf(sps, rrc_taps)

        self.snk = blocks.vector_sink_c()

        self.tb.connect(self.src, self.rrc_filter, self.test, self.snk)
        self.tb.run()

        expected_result = 10000*[complex(1,0), complex(-1,0)]
        dst_data = self.snk.data()

        # Only compare last Ncmp samples
        Ncmp = 1000
        len_e = len(expected_result)
        len_d = len(dst_data)
        expected_result = expected_result[len_e - Ncmp:]
        dst_data = dst_data[len_d - Ncmp:]

        #for e,d in zip(expected_result, dst_data):
        #    print e, d

        self.assertComplexTuplesAlmostEqual(expected_result, dst_data, 1)
예제 #11
0
    def test01(self):
        # Test BPSK sync
        M = 2
        theta = 0
        loop_bw = cmath.pi / 100.0
        fmin = -0.5
        fmax = 0.5
        mu = 0.5
        gain_mu = 0.01
        omega = 2
        gain_omega = 0.001
        omega_rel = 0.001

        self.test = digital.mpsk_receiver_cc(M, theta, loop_bw, fmin, fmax, mu,
                                             gain_mu, omega, gain_omega,
                                             omega_rel)

        data = 10000 * [complex(1, 0), complex(-1, 0)]
        #data = [2*random.randint(0,1)-1 for x in xrange(10000)]
        self.src = blocks.vector_source_c(data, False)
        self.snk = blocks.vector_sink_c()

        # pulse shaping interpolation filter
        nfilts = 32
        excess_bw = 0.35
        ntaps = 11 * int(omega * nfilts)
        rrc_taps0 = filter.firdes.root_raised_cosine(nfilts, nfilts, 1.0,
                                                     excess_bw, ntaps)
        rrc_taps1 = filter.firdes.root_raised_cosine(1, omega, 1.0, excess_bw,
                                                     11 * omega)
        self.rrc0 = filter.pfb_arb_resampler_ccf(omega, rrc_taps0)
        self.rrc1 = filter.fir_filter_ccf(1, rrc_taps1)

        self.tb.connect(self.src, self.rrc0, self.rrc1, self.test, self.snk)
        self.tb.run()

        expected_result = [0.5 * d for d in data]
        dst_data = self.snk.data()

        # Only compare last Ncmp samples
        Ncmp = 1000
        len_e = len(expected_result)
        len_d = len(dst_data)
        expected_result = expected_result[len_e - Ncmp:]
        dst_data = dst_data[len_d - Ncmp:]

        #for e,d in zip(expected_result, dst_data):
        #    print "{0:+.02f}  {1:+.02f}".format(e, d)

        self.assertComplexTuplesAlmostEqual(expected_result, dst_data, 1)
예제 #12
0
    def test01(self):
        # Test BPSK sync
        M = 2
        theta = 0
        loop_bw = cmath.pi/100.0
        fmin = -0.5
        fmax = 0.5
        mu = 0.5
        gain_mu = 0.01
        omega = 2
        gain_omega = 0.001
        omega_rel = 0.001

        self.test = digital.mpsk_receiver_cc(M, theta, loop_bw,
                                             fmin, fmax, mu, gain_mu,
                                             omega, gain_omega,
                                             omega_rel)
        
        data = 10000*[complex(1,0), complex(-1,0)]
        #data = [2*random.randint(0,1)-1 for x in xrange(10000)]
        self.src = blocks.vector_source_c(data, False)
        self.snk = blocks.vector_sink_c()

        # pulse shaping interpolation filter
        nfilts = 32
        excess_bw = 0.35
        ntaps = 11 * int(omega*nfilts)
        rrc_taps0 = filter.firdes.root_raised_cosine(
            nfilts, nfilts, 1.0, excess_bw, ntaps)
        rrc_taps1 = filter.firdes.root_raised_cosine(
            1, omega, 1.0, excess_bw, 11*omega)
        self.rrc0 = filter.pfb_arb_resampler_ccf(omega, rrc_taps0)
        self.rrc1 = filter.fir_filter_ccf(1, rrc_taps1)

        self.tb.connect(self.src, self.rrc0, self.rrc1, self.test, self.snk)
        self.tb.run()
        
        expected_result = [-0.5*d for d in data]
        dst_data = self.snk.data()

        # Only Ncmp samples after Nstrt samples
        Nstrt = 9000
        Ncmp = 1000
        expected_result = expected_result[Nstrt:Nstrt+Ncmp]
        dst_data = dst_data[Nstrt:Nstrt+Ncmp]
        
        #for e,d in zip(expected_result, dst_data):
        #    print "{0:+.02f}  {1:+.02f}".format(e, d)
        
        self.assertComplexTuplesAlmostEqual(expected_result, dst_data, 1)
예제 #13
0
    def __init__(self,byte_size,mod_type,samples_per_symbol,blk_num=-1):

	gr.hier_block2.__init__(self, "transmit_path",
				gr.io_signature(0,0,0),
				gr.io_signature(1,1,gr.sizeof_gr_complex))

	self.mod_type = mod_type	# bpsk or qpsk
	if(self.mod_type == "bpsk"):
		self.block_size = (byte_size+9)*8
	else:
		self.block_size = (byte_size+9)*4
	
	self.cp_size = 32
	
	self.db_num = 1
	self.eb_num = 1
	
	self.samples_per_symbol = samples_per_symbol
	self.excess_bw = 0.35
	
	self.amp = 2.0
	
	self.src = scfde.modulate_message_c(block_size=self.block_size,
						mod_type=self.mod_type,
						msgq_limit=4,
						block_num=blk_num)
	self.insert_esti = scfde.insert_esti_block_ccb( block_size=self.block_size,
							    db_num=self.db_num,
							    eb_num=self.eb_num)
	self.insert_sync = scfde.insert_sync_block_cbc(block_size=self.block_size)
	self.insert_cp = scfde.insert_cp_cc(block_size=self.block_size,
						cp_size=self.cp_size)
	self.p_to_s = scfde.parallel_to_serial_cc(ratio=self.block_size+self.cp_size)
	#pulse shaping
	nfilts = 32
	ntaps = nfilts*11*int(self.samples_per_symbol)
	self.rrc_taps = filter.firdes.root_raised_cosine(
			nfilts,nfilts,1.0,self.excess_bw,ntaps)
	self.rrc_filter = filter.pfb_arb_resampler_ccf(self.samples_per_symbol,
								self.rrc_taps)
	self.amplifier = blocks.multiply_const_cc(self.amp)
	
	self.connect(self.src,self.insert_esti)
	self.connect((self.insert_esti,0),(self.insert_sync,0))
	self.connect((self.insert_esti,1),(self.insert_sync,1))
	self.connect(self.insert_sync,self.insert_cp)
	self.connect(self.insert_cp,self.p_to_s,self.rrc_filter,self.amplifier,self)
예제 #14
0
    def __init__(self, mod_name="", samp_per_sym=2, excess_bw=.35):
        gr.hier_block2.__init__(self, mod_name, gr.io_signature(0, 0, 0),
                                gr.io_signature(1, 1, gr.sizeof_gr_complex))
        self.random_source = \
            blocks.vector_source_b(
                map(int, np.random.randint(0, 255, int(1e6))), True
            )
        num_filters = 32
        num_taps = num_filters * 11 * int(
            samp_per_sym)  # make nfilts filters of ntaps each
        rrc_taps = filter.firdes.root_raised_cosine(
            num_filters,  # gain
            num_filters,  # sampling rate based on 32 filters in resampler
            1.0,  # symbol rate
            excess_bw,  # excess bandwidth (roll-off factor)
            num_taps)

        self.rrc_filter = filter.pfb_arb_resampler_ccf(samp_per_sym, rrc_taps)
        self.rrc_filter.declare_sample_delay(0)
예제 #15
0
    def test_ccf_000(self):
        N = 5000         # number of samples to use
        fs = 5000.0      # baseband sampling rate
        rrate = 2.4321   # resampling rate

        nfilts = 32
        taps = filter.firdes.low_pass_2(nfilts, nfilts*fs, fs/2, fs/10,
                                        attenuation_dB=80,
                                        window=filter.firdes.WIN_BLACKMAN_hARRIS)

        freq = 211.123
        data = sig_source_c(fs, freq, 1, N)
        signal = blocks.vector_source_c(data)
        pfb = filter.pfb_arb_resampler_ccf(rrate, taps, nfilts)
        snk = blocks.vector_sink_c()
        
        self.tb.connect(signal, pfb, snk)
        self.tb.run() 

        Ntest = 50
        L = len(snk.data())

        # Get group delay and estimate of phase offset from the filter itself.
        delay = pfb.group_delay()
        phase = pfb.phase_offset(freq, fs)
        
        # Create a timeline offset by the filter's group delay
        t = map(lambda x: float(x)/(fs*rrate), xrange(delay, L+delay))

        # Data of the sinusoid at frequency freq with the delay and phase offset.
        expected_data = map(lambda x: math.cos(2.*math.pi*freq*x+phase) + \
                                1j*math.sin(2.*math.pi*freq*x+phase), t)

        dst_data = snk.data()

        self.assertComplexTuplesAlmostEqual(expected_data[-Ntest:], dst_data[-Ntest:], 2)
    def __init__(self,
                 frame_preamble,
                 sync_word,
                 append_crc,
                 whitening,
                 manchester,
                 msb_first,
                 ax25_format,
                 dest_addr,
                 dest_ssid,
                 src_addr,
                 src_ssid,
                 settling_samples,
                 samps_per_symbol,
                 interpolation_taps,
                 samp_rate,
                 lo_offset,
                 deviation,
                 baud_rate):
        gr.hier_block2.__init__(self, "satnogs_upsat_transmitter",
                                gr.io_signature(0 , 0 , 0),
                                # Output 0: The complex TX signal for the SDR device
                                # Output 1: The constellation output for the vector analyzer
                                gr.io_signature(1, 1, sizeof_gr_complex)) 
        self.frame_preamble = frame_preamble
        self.sync_word = sync_word
        self.append_crc = append_crc
        self.whitening = whitening
        self.manchester = manchester
        self.msb_first = msb_first
        self.ax25_format = ax25_format
        self.dest_addr = dest_addr
        self.dest_ssid = dest_ssid
        self.src_addr = src_addr
        self.src_ssid = src_ssid
        self.settling_samples = settling_samples
        self.samps_per_symbol = samps_per_symbol
        self.interpolation_taps = interpolation_taps
        self.samp_rate = samp_rate
        self.lo_offset = lo_offset   
        self.deviation=deviation
        self.baud_rate=baud_rate
        self.message_port_register_hier_out("in")
        
        
        self.modulation_index = self.deviation/(self.baud_rate / 2.0)
        self.sensitivity = (math.pi*self.modulation_index) / self.samps_per_symbol
        self.resampling_rate = self.samp_rate / (self.baud_rate*self.samps_per_symbol )
        self.par_taps = filter.firdes.low_pass_2(32, 32, 0.8, 0.1, 60)
        self.num_filters = 32
 
#=================================================================
# TX Related blocks
#=================================================================

        self.fsk_frame_encoder = satnogs_swig.upsat_fsk_frame_encoder(self.frame_preamble,
                                                                  self.sync_word,
                                                                  self.append_crc,
                                                                  self.whitening,
                                                                  self.manchester,
                                                                  self.msb_first,
                                                                  self.ax25_format,
                                                                  self.dest_addr,
                                                                  self.dest_ssid,
                                                                  self.src_addr,
                                                                  self.src_ssid,
                                                                  self.settling_samples
                                                                  )
    
        self.interp_fir_filter = filter.interp_fir_filter_fff(self.samps_per_symbol,
                                                                 self.interpolation_taps
                                                                 )
    
        self.frequency_modulator = analog.frequency_modulator_fc(self.sensitivity)
        self.signal_source = analog.sig_source_c(self.samp_rate,
                                             102,
                                             self.lo_offset,
                                             1,
                                             0)
        self.polyphase_arbitrary_resampler = filter.pfb_arb_resampler_ccf(self.resampling_rate,
                                                                      self.par_taps,
                                                                      self.num_filters)
        self.multiply = blocks.multiply_cc(1)
    
#=================================================================
# Connections
#=================================================================  
        self.msg_connect((self, "in"), (self.fsk_frame_encoder, "pdu"))
        self.connect((self.fsk_frame_encoder, 0), (self.interp_fir_filter, 0))
        self.connect((self.interp_fir_filter, 0), (self.frequency_modulator, 0))
        self.connect((self.frequency_modulator, 0), (self.polyphase_arbitrary_resampler, 0))
        self.connect((self.signal_source, 0) , (self.multiply, 0))
        self.connect((self.polyphase_arbitrary_resampler, 0) , (self.multiply, 1))
        self.connect((self.multiply, 0), self)
예제 #17
0
    def __init__(self, frame_preamble, sync_word, append_crc, whitening,
                 manchester, msb_first, ax25_format, dest_addr, dest_ssid,
                 src_addr, src_ssid, settling_samples, samps_per_symbol,
                 interpolation_taps, samp_rate, lo_offset, deviation,
                 baud_rate):
        gr.hier_block2.__init__(
            self,
            "satnogs_upsat_transmitter",
            gr.io_signature(0, 0, 0),
            # Output 0: The complex TX signal for the SDR device
            # Output 1: The constellation output for the vector analyzer
            gr.io_signature(1, 1, sizeof_gr_complex))
        self.frame_preamble = frame_preamble
        self.sync_word = sync_word
        self.append_crc = append_crc
        self.whitening = whitening
        self.manchester = manchester
        self.msb_first = msb_first
        self.ax25_format = ax25_format
        self.dest_addr = dest_addr
        self.dest_ssid = dest_ssid
        self.src_addr = src_addr
        self.src_ssid = src_ssid
        self.settling_samples = settling_samples
        self.samps_per_symbol = samps_per_symbol
        self.interpolation_taps = interpolation_taps
        self.samp_rate = samp_rate
        self.lo_offset = lo_offset
        self.deviation = deviation
        self.baud_rate = baud_rate
        self.message_port_register_hier_out("in")

        self.modulation_index = self.deviation / (self.baud_rate / 2.0)
        self.sensitivity = (math.pi *
                            self.modulation_index) / self.samps_per_symbol
        self.resampling_rate = self.samp_rate / (self.baud_rate *
                                                 self.samps_per_symbol)
        self.par_taps = filter.firdes.low_pass_2(32, 32, 0.8, 0.1, 60)
        self.num_filters = 32

        #=================================================================
        # TX Related blocks
        #=================================================================

        self.fsk_frame_encoder = satnogs_swig.upsat_fsk_frame_encoder(
            self.frame_preamble, self.sync_word, self.append_crc,
            self.whitening, self.manchester, self.msb_first, self.ax25_format,
            self.dest_addr, self.dest_ssid, self.src_addr, self.src_ssid,
            self.settling_samples)

        self.interp_fir_filter = filter.interp_fir_filter_fff(
            self.samps_per_symbol, self.interpolation_taps)

        self.frequency_modulator = analog.frequency_modulator_fc(
            self.sensitivity)
        self.signal_source = analog.sig_source_c(self.samp_rate, 102,
                                                 self.lo_offset, 1, 0)
        self.polyphase_arbitrary_resampler = filter.pfb_arb_resampler_ccf(
            self.resampling_rate, self.par_taps, self.num_filters)
        self.multiply = blocks.multiply_cc(1)

        #=================================================================
        # Connections
        #=================================================================
        self.msg_connect((self, "in"), (self.fsk_frame_encoder, "pdu"))
        self.connect((self.fsk_frame_encoder, 0), (self.interp_fir_filter, 0))
        self.connect((self.interp_fir_filter, 0),
                     (self.frequency_modulator, 0))
        self.connect((self.frequency_modulator, 0),
                     (self.polyphase_arbitrary_resampler, 0))
        self.connect((self.signal_source, 0), (self.multiply, 0))
        self.connect((self.polyphase_arbitrary_resampler, 0),
                     (self.multiply, 1))
        self.connect((self.multiply, 0), self)
예제 #18
0
    def test_001(self):
        # We're using a really simple preamble so that the correlation
        # is straight forward.
        preamble = [0, 0, 0, 1, 0, 0, 0]
        # Our pulse shape has this width (in units of symbols).
        pulse_width = 1.5
        # The number of filters to use for resampling.
        n_filters = 12
        sps = 3
        data = [0] * 10 + preamble + [0] * 40
        src = blocks.vector_source_c(data)

        # We want to generate taps with a sampling rate of sps=n_filters for resampling
        # purposes.
        pulse_shape = make_parabolic_pulse_shape(sps=n_filters,
                                                 N=0.5,
                                                 scale=35)

        # Create our resampling filter to generate the data for the correlator.
        shape = filter.pfb_arb_resampler_ccf(sps, pulse_shape, n_filters)
        # Generate the correlator block itself.
        correlator = digital.correlate_and_sync_cc(preamble, pulse_shape, sps,
                                                   n_filters)

        # Connect it all up and go.
        snk = blocks.vector_sink_c()
        null = blocks.null_sink(gr.sizeof_gr_complex)
        tb = gr.top_block()
        tb.connect(src, shape, correlator, snk)
        tb.connect((correlator, 1), null)
        tb.run()

        # Look at the tags.  Retrieve the timing offset.
        data = snk.data()
        offset = None
        timing_error = None
        for tag in snk.tags():
            key = pmt.symbol_to_string(tag.key)
            if key == "time_est":
                offset = tag.offset
                timing_error = pmt.to_double(tag.value)
        if offset is None:
            raise ValueError("No tags found.")
        # Detect where the middle of the preamble is.
        # Assume we have only one peak and that it is symmetric.
        sum_id = 0
        sum_d = 0
        for i, d in enumerate(data):
            sum_id += i * abs(d)
            sum_d += abs(d)
        data_i = sum_id / sum_d
        if offset is not None:
            diff = data_i - offset
            remainder = -(diff % sps)
            if remainder < -sps / 2.0:
                remainder += sps
        tol = 0.2
        difference = timing_error - remainder
        difference = difference % sps
        if abs(difference) >= tol:
            print(
                "Tag gives timing estimate of {0}. QA calculates it as {1}.  Tolerance is {2}"
                .format(timing_error, remainder, tol))
        self.assertTrue(abs(difference) < tol)
예제 #19
0
    def __init__(self, constellation,
                 differential=_def_differential,
                 samples_per_symbol=_def_samples_per_symbol,
                 pre_diff_code=True,
                 excess_bw=_def_excess_bw,
                 verbose=_def_verbose,
                 log=_def_log):

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

        self._constellation = constellation
        self._samples_per_symbol = samples_per_symbol
        self._excess_bw = excess_bw
        self._differential = differential
        # Only apply a predifferential coding if the constellation also supports it.
        self.pre_diff_code = pre_diff_code and self._constellation.apply_pre_diff_code()

        if self._samples_per_symbol < 2:
            raise TypeError, ("sbp must be >= 2, is %f" % self._samples_per_symbol)
        
        arity = pow(2,self.bits_per_symbol())
        
        # turn bytes into k-bit vectors
        self.bytes2chunks = \
            blocks.packed_to_unpacked_bb(self.bits_per_symbol(), gr.GR_MSB_FIRST)

        if self.pre_diff_code:
            self.symbol_mapper = digital.map_bb(self._constellation.pre_diff_code())

        if differential:
            self.diffenc = digital.diff_encoder_bb(arity)

        self.chunks2symbols = digital.chunks_to_symbols_bc(self._constellation.points())

        # pulse shaping filter
        nfilts = 32
        ntaps = nfilts * 11 * int(self._samples_per_symbol)    # make nfilts filters of ntaps each
        self.rrc_taps = filter.firdes.root_raised_cosine(
            nfilts,          # gain
            nfilts,          # sampling rate based on 32 filters in resampler
            1.0,             # symbol rate
            self._excess_bw, # excess bandwidth (roll-off factor)
            ntaps)
        self.rrc_filter = filter.pfb_arb_resampler_ccf(self._samples_per_symbol,
                                                       self.rrc_taps)

	# Connect
        self._blocks = [self, self.bytes2chunks]
        if self.pre_diff_code:
            self._blocks.append(self.symbol_mapper)
        if differential:
            self._blocks.append(self.diffenc)
        self._blocks += [self.chunks2symbols, self.rrc_filter, self]
        self.connect(*self._blocks)

        if verbose:
            self._print_verbage()
            
        if log:
            self._setup_logging()
예제 #20
0
    def __init__(self,
                 constellation,
                 differential=_def_differential,
                 samples_per_symbol=_def_samples_per_symbol,
                 pre_diff_code=True,
                 excess_bw=_def_excess_bw,
                 verbose=_def_verbose,
                 log=_def_log,
                 truncate=_def_truncate):

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

        self._constellation = constellation
        self._samples_per_symbol = samples_per_symbol
        self._excess_bw = excess_bw
        self._differential = differential
        # Only apply a predifferential coding if the constellation also supports it.
        self.pre_diff_code = pre_diff_code and self._constellation.apply_pre_diff_code(
        )

        if self._samples_per_symbol < 2:
            raise TypeError("sps must be >= 2, is %f" %
                            self._samples_per_symbol)

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

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

        if self.pre_diff_code:
            self.symbol_mapper = digital.map_bb(
                self._constellation.pre_diff_code())

        if differential:
            self.diffenc = digital.diff_encoder_bb(arity)

        self.chunks2symbols = digital.chunks_to_symbols_bc(
            self._constellation.points())

        # pulse shaping filter
        nfilts = 32
        ntaps_per_filt = 11
        # make nfilts filters of ntaps each
        ntaps = nfilts * ntaps_per_filt * int(self._samples_per_symbol)
        self.rrc_taps = filter.firdes.root_raised_cosine(
            nfilts,  # gain
            nfilts,  # sampling rate based on 32 filters in resampler
            1.0,  # symbol rate
            self._excess_bw,  # excess bandwidth (roll-off factor)
            ntaps)
        self.rrc_filter = filter.pfb_arb_resampler_ccf(
            self._samples_per_symbol, self.rrc_taps)

        # Remove the filter transient at the beginning of the transmission
        if truncate:
            fsps = float(self._samples_per_symbol)
            # Length of delay through rrc filter
            len_filt_delay = int((ntaps_per_filt * fsps * fsps - fsps) / 2.0)
            self.skiphead = blocks.skiphead(gr.sizeof_gr_complex * 1,
                                            len_filt_delay)

        # Connect
        self._blocks = [self, self.bytes2chunks]
        if self.pre_diff_code:
            self._blocks.append(self.symbol_mapper)
        if differential:
            self._blocks.append(self.diffenc)
        self._blocks += [self.chunks2symbols, self.rrc_filter]

        if truncate:
            self._blocks.append(self.skiphead)
        self._blocks.append(self)
        self.connect(*self._blocks)

        if verbose:
            self._print_verbage()

        if log:
            self._setup_logging()
예제 #21
0
  def __init__(self):
    grc_wxgui.top_block_gui.__init__(self, title="Top Block")

    options = get_options()

    self.ifreq = options.frequency
    self.rfgain = options.gain

    self.src = osmosdr.source(options.args)
    self.src.set_center_freq(self.ifreq)
    self.src.set_sample_rate(int(options.sample_rate))

    if self.rfgain is None:
        self.src.set_gain_mode(1)
        self.iagc = 1
        self.rfgain = 0
    else:
        self.iagc = 0
        self.src.set_gain_mode(0)
        self.src.set_gain(self.rfgain)

    # may differ from the requested rate
    sample_rate = self.src.get_sample_rate()
    sys.stderr.write("sample rate: %d\n" % (sample_rate))

    symbol_rate = 18000
    sps = 2 # output rate will be 36,000
    out_sample_rate = symbol_rate * sps

    options.low_pass = options.low_pass / 2.0

    if sample_rate == 96000: # FunCube Dongle
        first_decim = 2
    else:
        first_decim = 10

    self.offset = 0

    taps = firdes.low_pass(1.0, sample_rate, options.low_pass, options.low_pass * 0.2, firdes.WIN_HANN)
    self.tuner = filter.freq_xlating_fir_filter_ccf(first_decim, taps, self.offset, sample_rate)

    self.demod = cqpsk.cqpsk_demod(
        samples_per_symbol = sps,
        excess_bw=0.35,
        costas_alpha=0.03,
        gain_mu=0.05,
        mu=0.05,
        omega_relative_limit=0.05,
        log=options.log,
        verbose=options.verbose)

    self.output = blocks.file_sink(gr.sizeof_float, options.output_file)

    rerate = float(sample_rate / float(first_decim)) / float(out_sample_rate)
    sys.stderr.write("resampling factor: %f\n" % rerate)

    if rerate.is_integer():
        sys.stderr.write("using pfb decimator\n")
        self.resamp = filter.pfb.decimator_ccf(int(rerate), None, 0, 110)
        #self.resamp = filter.pfb_decimator_ccf(int(rerate), taps, 0, 110)
    else:
        sys.stderr.write("using pfb resampler\n")
        self.resamp = filter.pfb_arb_resampler_ccf(1 / rerate)

    self.connect(self.src, self.tuner, self.resamp, self.demod, self.output)

    self.Main = wx.Notebook(self.GetWin(), style=wx.NB_TOP)
    self.Main.AddPage(grc_wxgui.Panel(self.Main), "Wideband Spectrum")
    self.Main.AddPage(grc_wxgui.Panel(self.Main), "Channel Spectrum")
    self.Main.AddPage(grc_wxgui.Panel(self.Main), "Soft Bits")

    def set_ifreq(ifreq):
        self.ifreq = ifreq
        self._ifreq_text_box.set_value(self.ifreq)
        self.src.set_center_freq(self.ifreq)

    self._ifreq_text_box = forms.text_box(
        parent=self.GetWin(),
        value=self.ifreq,
        callback=set_ifreq,
        label="Center Frequency",
        converter=forms.float_converter(),
    )
    self.Add(self._ifreq_text_box)

    def set_iagc(iagc):
        self.iagc = iagc
        self._agc_check_box.set_value(self.iagc)
        self.src.set_gain_mode(self.iagc, 0)
        self.src.set_gain(0 if self.iagc == 1 else self.rfgain, 0)

    self._agc_check_box = forms.check_box(
        parent=self.GetWin(),
        value=self.iagc,
        callback=set_iagc,
        label="Automatic Gain",
        true=1,
        false=0,
    )

    self.Add(self._agc_check_box)

    def set_rfgain(rfgain):
        self.rfgain = rfgain
        self._rfgain_slider.set_value(self.rfgain)
        self._rfgain_text_box.set_value(self.rfgain)
        self.src.set_gain(0 if self.iagc == 1 else self.rfgain, 0)

    _rfgain_sizer = wx.BoxSizer(wx.VERTICAL)
    self._rfgain_text_box = forms.text_box(
        parent=self.GetWin(),
        sizer=_rfgain_sizer,
        value=self.rfgain,
        callback=set_rfgain,
        label="RF Gain",
        converter=forms.float_converter(),
        proportion=0,
    )
    self._rfgain_slider = forms.slider(
        parent=self.GetWin(),
        sizer=_rfgain_sizer,
        value=self.rfgain,
        callback=set_rfgain,
        minimum=0,
        maximum=50,
        num_steps=200,
        style=wx.SL_HORIZONTAL,
        cast=float,
        proportion=1,
    )

    self.Add(_rfgain_sizer)

    self.Add(self.Main)

    def fftsink2_callback(x, y):
        if abs(x / (sample_rate / 2)) > 0.9:
            set_ifreq(self.ifreq + x / 2)
        else:
            sys.stderr.write("coarse tuned to: %d Hz\n" % x)
            self.offset = -x
            self.tuner.set_center_freq(self.offset)

    self.scope = fftsink2.fft_sink_c(self.Main.GetPage(0).GetWin(),
        title="Wideband Spectrum (click to coarse tune)",
        fft_size=1024,
        sample_rate=sample_rate,
        ref_scale=2.0,
        ref_level=0,
        y_divs=10,
        fft_rate=10,
        average=False,
        avg_alpha=0.6)

    self.Main.GetPage(0).Add(self.scope.win)
    self.scope.set_callback(fftsink2_callback)

    self.connect(self.src, self.scope)

    def fftsink2_callback2(x, y):
        self.offset = self.offset - (x / 10)
        sys.stderr.write("fine tuned to: %d Hz\n" % self.offset)
        self.tuner.set_center_freq(self.offset)

    self.scope2 = fftsink2.fft_sink_c(self.Main.GetPage(1).GetWin(),
        title="Channel Spectrum (click to fine tune)",
        fft_size=1024,
        sample_rate=out_sample_rate,
        ref_scale=2.0,
        ref_level=-20,
        y_divs=10,
        fft_rate=10,
        average=False,
        avg_alpha=0.6)

    self.Main.GetPage(1).Add(self.scope2.win)
    self.scope2.set_callback(fftsink2_callback2)

    self.connect(self.resamp, self.scope2)

    self.scope3 = scopesink2.scope_sink_f(
        self.Main.GetPage(2).GetWin(),
        title="Soft Bits",
        sample_rate=out_sample_rate,
        v_scale=0,
        v_offset=0,
        t_scale=0.001,
        ac_couple=False,
        xy_mode=False,
        num_inputs=1,
        trig_mode=wxgui.TRIG_MODE_AUTO,
        y_axis_label="Counts",
	)
    self.Main.GetPage(2).Add(self.scope3.win)

    self.connect(self.demod, self.scope3)