def __init__(self, samplerate, bits_per_sec, fftlen): gr.hier_block2.__init__( self, "square_and_fft_sync_cc", gr.io_signature(1, 1, gr.sizeof_gr_complex), # Input signature gr.io_signature(1, 1, gr.sizeof_gr_complex)) # Output signature #this is just the old square-and-fft method #ais.freqest is simply looking for peaks spaced bits-per-sec apart self.square = blocks.multiply_cc(1) self.fftvect = blocks.stream_to_vector(gr.sizeof_gr_complex, fftlen) self.fft = fft.fft_vcc(fftlen, True, window.rectangular(fftlen), True) self.freqest = ais.freqest(int(samplerate), int(bits_per_sec), fftlen) self.repeat = blocks.repeat(gr.sizeof_float, fftlen) self.fm = analog.frequency_modulator_fc(-1.0 / (float(samplerate) / (2 * pi))) self.mix = blocks.multiply_cc(1) self.connect(self, (self.square, 0)) self.connect(self, (self.square, 1)) #this is the feedforward branch self.connect(self, (self.mix, 0)) #this is the feedback branch self.connect(self.square, self.fftvect, self.fft, self.freqest, self.repeat, self.fm, (self.mix, 1)) #and this is the output self.connect(self.mix, self)
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))
def connect_audio_stage(self, input_port): stereo_rate = self.demod_rate normalizer = TWO_PI / stereo_rate pilot_tone = 19000 pilot_low = pilot_tone * 0.98 pilot_high = pilot_tone * 1.02 def make_audio_filter(): return grfilter.fir_filter_fff( stereo_rate // self.__audio_int_rate, # decimation firdes.low_pass(1.0, stereo_rate, 15000, 5000, firdes.WIN_HAMMING)) stereo_pilot_filter = grfilter.fir_filter_fcc( 1, # decimation firdes.complex_band_pass(1.0, stereo_rate, pilot_low, pilot_high, 300)) # TODO magic number from gqrx stereo_pilot_pll = analog.pll_refout_cc( loop_bw=0.001, max_freq=normalizer * pilot_high, min_freq=normalizer * pilot_low) stereo_pilot_doubler = blocks.multiply_cc() stereo_pilot_out = blocks.complex_to_real() difference_channel_mixer = blocks.multiply_ff() difference_channel_filter = make_audio_filter() mono_channel_filter = make_audio_filter() mixL = blocks.add_ff(1) mixR = blocks.sub_ff(1) # connections self.connect(input_port, mono_channel_filter) if self.__decode_stereo: # stereo pilot tone tracker self.connect(input_port, stereo_pilot_filter, stereo_pilot_pll) self.connect(stereo_pilot_pll, (stereo_pilot_doubler, 0)) self.connect(stereo_pilot_pll, (stereo_pilot_doubler, 1)) self.connect(stereo_pilot_doubler, stereo_pilot_out) # pick out stereo left-right difference channel (at stereo_rate) self.connect(input_port, (difference_channel_mixer, 0)) self.connect(stereo_pilot_out, (difference_channel_mixer, 1)) self.connect( difference_channel_mixer, blocks.multiply_const_ff( 50 ), # TODO: Completely empirical fudge factor. This should not be necessary. We're losing signal somewhere? difference_channel_filter) # recover left/right channels (at self.__audio_int_rate) self.connect(difference_channel_filter, (mixL, 1)) self.connect(difference_channel_filter, (mixR, 1)) resamplerL = self._make_resampler((mixL, 0), self.__audio_int_rate) resamplerR = self._make_resampler((mixR, 0), self.__audio_int_rate) self.connect(mono_channel_filter, (mixL, 0)) self.connect(mono_channel_filter, (mixR, 0)) self.connect_audio_output(resamplerL, resamplerR) else: resampler = self._make_resampler(mono_channel_filter, self.__audio_int_rate) self.connect_audio_output(resampler, resampler)
def __init__(self, protocol=None, mod_adjust=None, output_gain=None, if_freq=0, if_rate=0, verbose=0, sample_rate=0, bt=0): from dv_tx import RC_FILTER gr.hier_block2.__init__( self, "dv_modulator", gr.io_signature(1, 1, gr.sizeof_char), # Input signature gr.io_signature(1, 1, gr.sizeof_gr_complex)) # Output signature MOD = p25_mod_bf(output_sample_rate=sample_rate, dstar=(protocol == 'dstar'), bt=bt, rc=RC_FILTER[protocol]) AMP = blocks.multiply_const_ff(output_gain) max_dev = 12.5e3 k = 2 * math.pi * max_dev / if_rate FM_MOD = analog.frequency_modulator_fc(k * mod_adjust) INTERP = filter.rational_resampler_fff(if_rate // sample_rate, 1) MIXER = blocks.multiply_cc() LO = analog.sig_source_c(if_rate, analog.GR_SIN_WAVE, if_freq, 1.0, 0) self.connect(self, MOD, AMP, INTERP, FM_MOD, (MIXER, 0)) self.connect(LO, (MIXER, 1)) self.connect(MIXER, self)
def __init__(self, vocoder, lo_freq, audio_rate, if_rate): gr.hier_block2.__init__(self, "pipeline", gr.io_signature(0, 0, 0), # Input signature gr.io_signature(1, 1, gr.sizeof_gr_complex)) # Output signature c4fm = op25_c4fm_mod.p25_mod_bf(output_sample_rate=audio_rate, log=False, verbose=True) interp_factor = if_rate / audio_rate low_pass = 2.88e3 interp_taps = filter.firdes.low_pass(1.0, if_rate, low_pass, low_pass * 0.1, filter.firdes.WIN_HANN) interpolator = filter.interp_fir_filter_fff (int(interp_factor), interp_taps) max_dev = 12.5e3 k = 2 * math.pi * max_dev / if_rate adjustment = 1.5 # adjust for proper c4fm deviation level modulator = analog.frequency_modulator_fc (k * adjustment) # Local oscillator lo = analog.sig_source_c (if_rate, # sample rate analog.GR_SIN_WAVE, # waveform type lo_freq, #frequency 1.0, # amplitude 0) # DC Offset mixer = blocks.multiply_cc () self.connect (vocoder, c4fm, interpolator, modulator, (mixer, 0)) self.connect (lo, (mixer, 1)) self.connect (mixer, self)
def __init__(self, fft_len, cp_len, nofdm_symbols): gr.hier_block2.__init__( self, "ofdm_basebandsignal_to_frames_cvc", gr.io_signature(1, 1, gr.sizeof_gr_complex), gr.io_signature(1, 1, fft_len * gr.sizeof_gr_complex)) self.fft_len = fft_len self.cp_len = cp_len self.nofdm_symbols = nofdm_symbols sync_detect = digital.ofdm_sync_sc_cfb(fft_len=fft_len, cp_len=cp_len) delay = blocks.delay(gr.sizeof_gr_complex, self.fft_len + self.cp_len) oscillator = analog.frequency_modulator_fc(-2.0 / self.fft_len) mixer = blocks.multiply_cc() frames = mimoots.ofdm_extract_frame_cvc( fft_len=self.fft_len, cp_len=self.cp_len, nsymbols_per_ofdmframe=self.nofdm_symbols + 2 # +2 Sync-Words ) self.connect(self, sync_detect) self.connect((sync_detect, 0), oscillator, (mixer, 0)) self.connect((self, 0), delay, (mixer, 1)) self.connect((sync_detect, 1), (frames, 1)) self.connect(mixer, (frames, 0)) self.connect(frames, self)
def __init__(self, filename, lo_freq, audio_rate, if_rate): gr.hier_block2.__init__(self, "pipeline", gr.io_signature(0, 0, 0), gr.io_signature(1, 1, gr.sizeof_gr_complex)) try: src = blocks.file_source(gr.sizeof_float, filename, True) except RuntimeError: sys.stderr.write(("\nError: Could not open file '%s'\n\n" % \ filename)) sys.exit(1) print audio_rate, if_rate fmtx = analog.nbfm_tx(audio_rate, if_rate, max_dev=5e3, tau=75e-6, fh=0.925 * if_rate / 2.0) # Local oscillator lo = analog.sig_source_c( if_rate, # sample rate analog.GR_SIN_WAVE, # waveform type lo_freq, # frequency 1.0, # amplitude 0) # DC Offset mixer = blocks.multiply_cc() self.connect(src, fmtx, (mixer, 0)) self.connect(lo, (mixer, 1)) self.connect(mixer, self)
def __init__(self, filename, lo_freq, audio_rate, if_rate): gr.hier_block2.__init__(self, "pipeline", gr.io_signature(0, 0, 0), gr.io_signature(1, 1, gr.sizeof_gr_complex)) try: src = blocks.file_source (gr.sizeof_float, filename, True) except RuntimeError: sys.stderr.write(("\nError: Could not open file '%s'\n\n" % \ filename)) sys.exit(1) print audio_rate, if_rate fmtx = analog.nbfm_tx(audio_rate, if_rate, max_dev=5e3, tau=75e-6, fh=0.925*if_rate/2.0) # Local oscillator lo = analog.sig_source_c(if_rate, # sample rate analog.GR_SIN_WAVE, # waveform type lo_freq, # frequency 1.0, # amplitude 0) # DC Offset mixer = blocks.multiply_cc() self.connect(src, fmtx, (mixer, 0)) self.connect(lo, (mixer, 1)) self.connect(mixer, self)
def test_multiply_vcc_one(self): src1_data = (1.0 + 2.0j, ) src2_data = (3.0 + 4.0j, ) src3_data = (5.0 + 6.0j, ) expected_result = (-85 + 20j, ) op = blocks.multiply_cc(1) self.help_cc(1, (src1_data, src2_data, src3_data), expected_result, op)
def test_multiply_cc(self): src1_data = (1+1j, 2+2j, 3+3j, 4+4j, 5+5j) src2_data = (8, -3, 4, 8, 2) expected_result = (8+8j, -6-6j, 12+12j, 32+32j, 10+10j) op = blocks.multiply_cc() self.help_cc((src1_data, src2_data), expected_result, op)
def test_multiply_cc(self): src1_data = [1+1j, 2+2j, 3+3j, 4+4j, 5+5j] src2_data = [8, -3, 4, 8, 2] expected_result = [8+8j, -6-6j, 12+12j, 32+32j, 10+10j] op = blocks.multiply_cc() self.help_cc((src1_data, src2_data), expected_result, op)
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)
def test_multiply_vcc_five(self): src1_data = (1.0+2.0j, 3.0+4.0j, 5.0+6.0j, 7.0+8.0j, 9.0+10.0j) src2_data = (11.0+12.0j, 13.0+14.0j, 15.0+16.0j, 17.0+18.0j, 19.0+20.0j) src3_data = (21.0+22.0j, 23.0+24.0j, 25.0+26.0j, 27.0+28.0j, 29.0+30.0j) expected_result = (-1021.0+428.0j, -2647.0+1754.0j, -4945.0+3704.0j, -8011.0+6374.0j, -11941.0+9860.0j) op = blocks.multiply_cc(5) self.help_cc(5, (src1_data, src2_data, src3_data), expected_result, op)
def test_multiply_vcc_one(self): src1_data = (1.0+2.0j,) src2_data = (3.0+4.0j,) src3_data = (5.0+6.0j,) expected_result = (-85+20j,) op = blocks.multiply_cc(1) self.help_cc(1, (src1_data, src2_data, src3_data), expected_result, op)
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)) symbol_settings = para.ofdm_symbol() self.constellationP = helpers.get_constellation(settings.PAYLOAD_BPS) self.constellationH = helpers.get_constellation(settings.HEADER_BPS) detector = digital.ofdm_sync_sc_cfb(symbol_settings.get_fft_length(), symbol_settings.get_cp_length()) delayer = blocks.delay(gr.sizeof_gr_complex, symbol_settings.get_time_length_of_symbol) oscillator = analog.frequency_modulator_fc(-2.0 / symbol_settings.get_fft_length()) splitter = digital.header_payload_demux( 3, symbol_settings.get_fft_length(), symbol_settings.get_cp_length(), settings.LENGTH_TAG_KEY, "", True ) mixer = blocks.multiply_cc() header_fft = fft.fft_vcc(symbol_settings.get_fft_length(),, True, (), True) chanest = digital.ofdm_chanest_vcvc(symbol_settings._generate_sync_word_one(),symbol_settings._generate_sync_word_two(), 1) header_equalizer = digital.ofdm_equalizer_simpledfe( symbol_settings.get_fft_length(),, self.constellationH.base(), symbol_settings.get_carrier_tones(), symbol_settings.get_pilot_tones(), symbol_settings._generate_pilot_symbols(), symbols_skipped=0, ) self.connect(self,detector) self.connect(self,delay, (mixer,0), (splitter,0)) self.connect((detector,0), oscillator, (mixer,1)) self.connect((detector,1),(splitter,1))
def test_001_t (self): # set up fg fft_len = 256 cp_len = 32 samp_rate = 32000 data = np.random.choice([-1, 1], [100, fft_len]) timefreq = np.fft.ifft(data, axis=0) #add cp timefreq = np.hstack((timefreq[:, -cp_len:], timefreq)) # msg (only 4th and 5th tuples are needed) id1 = pmt.make_tuple(pmt.intern("Signal"), pmt.from_uint64(0)) name = pmt.make_tuple(pmt.intern("OFDM"), pmt.from_float(1.0)); id2 = pmt.make_tuple(pmt.intern("xxx"), pmt.from_float(0.0)) id3 = pmt.make_tuple(pmt.intern("xxx"), pmt.from_float(0.0)) id4 = pmt.make_tuple(pmt.intern("xxx"), pmt.from_float(256)) id5 = pmt.make_tuple(pmt.intern("xxx"), pmt.from_float(32)) msg = pmt.make_tuple(id1, name, id2, id3, id4, id5) tx = np.reshape(timefreq, (1, -1)) # GR time! src = blocks.vector_source_c(tx[0].tolist(), True, 1, []) freq_offset = analog.sig_source_c(1, analog.GR_SIN_WAVE, 50.0/samp_rate, 1.0, 0.0) mixer = blocks.multiply_cc() sync = inspector.ofdm_synchronizer_cc(4096) dst = blocks.vector_sink_c() dst2 = blocks.vector_sink_c() msg_src = blocks.message_strobe(msg, 0) # connect self.tb.connect(src, (mixer, 0)) self.tb.connect(freq_offset, (mixer, 1)) self.tb.connect(mixer, sync) self.tb.msg_connect((msg_src, 'strobe'), (sync, 'ofdm_in')) self.tb.connect(sync, dst) self.tb.connect(src, dst2) self.tb.start() time.sleep(0.1) self.tb.stop() self.tb.wait() # check data output = dst.data() expect = dst2.data() # block outputs 0j until it has enough OFDM symbols to perform estimations k = (k for k in range(len(output)) if output[k] != 0j).next() # use 10,000 samples for comparison since block fails sometimes # for one work function output = output[k:k+10000] expect = expect[k:k+10000] self.assertComplexTuplesAlmostEqual2(expect, output, abs_eps = 0.001, rel_eps=10)
def __init__(self): analog_source.__init__(self, mod_name="am-dsb", audio_rate=44.1e3) self.interp = filter.fractional_resampler_ff( 0.0, self.audio_rate * 2 / 200e3) self.cnv = blocks.float_to_complex() self.add = blocks.add_const_cc(1.0) self.mod = blocks.multiply_cc() self.connect(self.random_source, self.interp, self.cnv, self.add, self)
def __init__(self): gr.hier_block2.__init__(self, "s", gr.io_signature(2, 2, gr.sizeof_gr_complex), gr.io_signature(1, 1, gr.sizeof_gr_complex)) conj = blocks.conjugate_cc() mult = blocks.multiply_cc() self.connect((self,0), (mult,0)) self.connect((self,1), conj, (mult,1)) self.connect(mult, self)
def test_001_t(self): # set up fg test_len = 1024 packet_len = test_len samp_rate = 2000 center_freq = 1e9 velocity = (5, 15, 20) src = radar.signal_generator_cw_c(packet_len, samp_rate, (0, 0), 1) head = blocks.head(8, test_len) sim = radar.static_target_simulator_cc( (10, 10, 10), velocity, (1e12, 1e12, 1e12), (0, 0, 0), (0, ), samp_rate, center_freq, 1, True, False) mult = blocks.multiply_cc() fft = radar.ts_fft_cc(packet_len) cfar = radar.os_cfar_c(samp_rate, 5, 0, 0.78, 10, True) est = radar.estimator_cw(center_freq) res1 = radar.print_results() res2 = radar.print_results() gate = radar.msg_gate(('velocity', 'bla'), (8, 8), (17, 17)) debug1 = blocks.message_debug() debug2 = blocks.message_debug() self.tb.connect(src, head, (mult, 1)) self.tb.connect(head, sim, (mult, 0)) self.tb.connect(mult, fft, cfar) self.tb.msg_connect(cfar, 'Msg out', est, 'Msg in') self.tb.msg_connect(est, 'Msg out', res1, 'Msg in') self.tb.msg_connect(est, 'Msg out', debug1, 'store') self.tb.msg_connect(est, 'Msg out', gate, 'Msg in') self.tb.msg_connect(gate, 'Msg out', debug2, 'store') self.tb.msg_connect(gate, 'Msg out', res2, 'Msg in') self.tb.start() sleep(0.5) self.tb.stop() self.tb.wait() # check data msg1 = debug1.get_message(0) # msg without gate msg2 = debug2.get_message(0) # msg with gate self.assertEqual( "velocity", pmt.symbol_to_string(pmt.nth(0, (pmt.nth( 1, msg1))))) # check velocity message part (symbol), 1 self.assertEqual( "velocity", pmt.symbol_to_string(pmt.nth(0, (pmt.nth( 1, msg2))))) # check velocity message part (symbol), 2 self.assertEqual(pmt.length(pmt.nth(1, pmt.nth(1, msg1))), 3) # check number of targets without gate self.assertEqual(pmt.length(pmt.nth(1, pmt.nth(1, msg2))), 1) # check nubmer of targets with gate self.assertAlmostEqual( 1, velocity[1] / pmt.f32vector_ref(pmt.nth(1, (pmt.nth(1, msg2))), 0), 1) # check velocity value
def __init__(self): gr.hier_block2.__init__( self, "s", gr.io_signature(2, 2, gr.sizeof_gr_complex), gr.io_signature(1, 1, gr.sizeof_gr_complex)) conj = blocks.conjugate_cc() mult = blocks.multiply_cc() self.connect((self, 0), (mult, 0)) self.connect((self, 1), conj, (mult, 1)) self.connect(mult, self)
def __init__(self, context, mode, angle=0.0): gr.hier_block2.__init__( self, type(self).__name__, gr.io_signature(1, 1, gr.sizeof_float * 1), gr.io_signature(1, 1, gr.sizeof_gr_complex * 1), ) self.__angle = 0.0 # dummy statically visible value will be overwritten # TODO: My signal level parameters are probably wrong because this signal doesn't look like a real VOR signal vor_30 = analog.sig_source_f(self.__audio_rate, analog.GR_COS_WAVE, self.__vor_sig_freq, 1, 0) vor_add = blocks.add_cc(1) vor_audio = blocks.add_ff(1) # Audio/AM signal self.connect( vor_30, blocks.multiply_const_ff(0.3), # M_n (vor_audio, 0)) self.connect( self, blocks.multiply_const_ff(audio_modulation_index), # M_i (vor_audio, 1)) # Carrier component self.connect(analog.sig_source_c(0, analog.GR_CONST_WAVE, 0, 0, 1), (vor_add, 0)) # AM component self.__delay = blocks.delay(gr.sizeof_gr_complex, 0) # configured by set_angle self.connect( vor_audio, make_resampler(self.__audio_rate, self.__rf_rate ), # TODO make a complex version and do this last blocks.float_to_complex(1), self.__delay, (vor_add, 1)) # FM component vor_fm_mult = blocks.multiply_cc(1) self.connect( # carrier generation analog.sig_source_f(self.__rf_rate, analog.GR_COS_WAVE, fm_subcarrier, 1, 0), blocks.float_to_complex(1), (vor_fm_mult, 1)) self.connect( # modulation vor_30, make_resampler(self.__audio_rate, self.__rf_rate), analog.frequency_modulator_fc(2 * math.pi * fm_deviation / self.__rf_rate), blocks.multiply_const_cc(0.3), # M_d vor_fm_mult, (vor_add, 2)) self.connect(vor_add, self) # calculate and initialize delay self.set_angle(angle)
def test_multiply_cc(): top = gr.top_block() src = blocks.null_source(gr.sizeof_gr_complex) mul = blocks.multiply_cc() probe = blocks.probe_rate(gr.sizeof_gr_complex) top.connect((src, 0), (mul, 0)) top.connect((src, 0), (mul, 1)) top.connect(mul, probe) return top, probe
def connect_audio_stage(self, input_port): stereo_rate = self.demod_rate normalizer = TWO_PI / stereo_rate pilot_tone = 19000 pilot_low = pilot_tone * 0.9 pilot_high = pilot_tone * 1.1 def make_audio_filter(): return grfilter.fir_filter_fff( stereo_rate // self.__audio_int_rate, # decimation firdes.low_pass(1.0, stereo_rate, 15000, 5000, firdes.WIN_HAMMING)) stereo_pilot_filter = grfilter.fir_filter_fcc( 1, # decimation firdes.complex_band_pass(1.0, stereo_rate, pilot_low, pilot_high, 300)) # TODO magic number from gqrx stereo_pilot_pll = analog.pll_refout_cc( 0.001, # TODO magic number from gqrx normalizer * pilot_high, normalizer * pilot_low) stereo_pilot_doubler = blocks.multiply_cc() stereo_pilot_out = blocks.complex_to_imag() difference_channel_mixer = blocks.multiply_ff() difference_channel_filter = make_audio_filter() mono_channel_filter = make_audio_filter() mixL = blocks.add_ff(1) mixR = blocks.sub_ff(1) # connections self.connect(input_port, mono_channel_filter) if self.stereo: # stereo pilot tone tracker self.connect(input_port, stereo_pilot_filter, stereo_pilot_pll) self.connect(stereo_pilot_pll, (stereo_pilot_doubler, 0)) self.connect(stereo_pilot_pll, (stereo_pilot_doubler, 1)) self.connect(stereo_pilot_doubler, stereo_pilot_out) # pick out stereo left-right difference channel (at stereo_rate) self.connect(input_port, (difference_channel_mixer, 0)) self.connect(stereo_pilot_out, (difference_channel_mixer, 1)) self.connect(difference_channel_mixer, difference_channel_filter) # recover left/right channels (at self.__audio_int_rate) self.connect(difference_channel_filter, (mixL, 1)) self.connect(difference_channel_filter, (mixR, 1)) resamplerL = self._make_resampler((mixL, 0), self.__audio_int_rate) resamplerR = self._make_resampler((mixR, 0), self.__audio_int_rate) self.connect(mono_channel_filter, (mixL, 0)) self.connect(mono_channel_filter, (mixR, 0)) self.connect_audio_output(resamplerL, resamplerR) else: resampler = self._make_resampler(mono_channel_filter, self.__audio_int_rate) self.connect_audio_output(resampler, resampler)
def __init__(self, context, mode, angle=0.0): gr.hier_block2.__init__( self, 'SimulatedDevice VOR modulator', gr.io_signature(1, 1, gr.sizeof_float * 1), gr.io_signature(1, 1, gr.sizeof_gr_complex * 1), ) self.__angle = 0.0 # dummy statically visible value will be overwritten # TODO: My signal level parameters are probably wrong because this signal doesn't look like a real VOR signal vor_30 = analog.sig_source_f(self.__audio_rate, analog.GR_COS_WAVE, self.__vor_sig_freq, 1, 0) vor_add = blocks.add_cc(1) vor_audio = blocks.add_ff(1) # Audio/AM signal self.connect( vor_30, blocks.multiply_const_ff(0.3), # M_n (vor_audio, 0)) self.connect( self, blocks.multiply_const_ff(audio_modulation_index), # M_i (vor_audio, 1)) # Carrier component self.connect( analog.sig_source_c(0, analog.GR_CONST_WAVE, 0, 0, 1), (vor_add, 0)) # AM component self.__delay = blocks.delay(gr.sizeof_gr_complex, 0) # configured by set_angle self.connect( vor_audio, make_resampler(self.__audio_rate, self.__rf_rate), # TODO make a complex version and do this last blocks.float_to_complex(1), self.__delay, (vor_add, 1)) # FM component vor_fm_mult = blocks.multiply_cc(1) self.connect( # carrier generation analog.sig_source_f(self.__rf_rate, analog.GR_COS_WAVE, fm_subcarrier, 1, 0), blocks.float_to_complex(1), (vor_fm_mult, 1)) self.connect( # modulation vor_30, make_resampler(self.__audio_rate, self.__rf_rate), analog.frequency_modulator_fc(2 * math.pi * fm_deviation / self.__rf_rate), blocks.multiply_const_cc(0.3), # M_d vor_fm_mult, (vor_add, 2)) self.connect( vor_add, self) # calculate and initialize delay self.set_angle(angle)
def test_001_t(self): # set up fg test_len = 1024 packet_len = test_len samp_rate = 2000 center_freq = 1e9 velocity = (5, 15, 20) src = radar.signal_generator_cw_c(packet_len, samp_rate, (0, 0), 1) head = blocks.head(8, test_len) sim = radar.static_target_simulator_cc( (10, 10, 10), velocity, (1e12, 1e12, 1e12), (0, 0, 0), (0,), samp_rate, center_freq, 1, True, False ) mult = blocks.multiply_cc() fft = radar.ts_fft_cc(packet_len) cfar = radar.os_cfar_c(samp_rate, 5, 0, 0.78, 10, True) est = radar.estimator_cw(center_freq) res1 = radar.print_results() res2 = radar.print_results() gate = radar.msg_gate(("velocity", "bla"), (8, 8), (17, 17)) debug1 = blocks.message_debug() debug2 = blocks.message_debug() self.tb.connect(src, head, (mult, 1)) self.tb.connect(head, sim, (mult, 0)) self.tb.connect(mult, fft, cfar) self.tb.msg_connect(cfar, "Msg out", est, "Msg in") self.tb.msg_connect(est, "Msg out", res1, "Msg in") self.tb.msg_connect(est, "Msg out", debug1, "store") self.tb.msg_connect(est, "Msg out", gate, "Msg in") self.tb.msg_connect(gate, "Msg out", debug2, "store") self.tb.msg_connect(gate, "Msg out", res2, "Msg in") self.tb.start() sleep(0.5) self.tb.stop() self.tb.wait() # check data msg1 = debug1.get_message(0) # msg without gate msg2 = debug2.get_message(0) # msg with gate self.assertEqual( "velocity", pmt.symbol_to_string(pmt.nth(0, (pmt.nth(1, msg1)))) ) # check velocity message part (symbol), 1 self.assertEqual( "velocity", pmt.symbol_to_string(pmt.nth(0, (pmt.nth(1, msg2)))) ) # check velocity message part (symbol), 2 self.assertEqual(pmt.length(pmt.nth(1, pmt.nth(1, msg1))), 3) # check number of targets without gate self.assertEqual(pmt.length(pmt.nth(1, pmt.nth(1, msg2))), 1) # check nubmer of targets with gate self.assertAlmostEqual( 1, velocity[1] / pmt.f32vector_ref(pmt.nth(1, (pmt.nth(1, msg2))), 0), 1 ) # check velocity value
def test_001_t(self): # set up fg test_len = 1024 packet_len = test_len samp_rate = 2000 center_freq = 1e9 velocity = 15 src = radar.signal_generator_cw_c(packet_len, samp_rate, (0, 0), 1) head = blocks.head(8, test_len) sim = radar.static_target_simulator_cc( (10, 10), (velocity, velocity), (1e9, 1e9), (0, 0), (0, ), samp_rate, center_freq, 1, True, False) mult = blocks.multiply_cc() fft = radar.ts_fft_cc(packet_len) cfar = radar.os_cfar_c(samp_rate, 5, 0, 0.78, 10, True) est = radar.estimator_cw(center_freq) res = radar.print_results() debug = blocks.message_debug() self.tb.connect(src, head, (mult, 1)) self.tb.connect(head, sim, (mult, 0)) self.tb.connect(mult, fft, cfar) self.tb.msg_connect(cfar, 'Msg out', est, 'Msg in') self.tb.msg_connect(est, 'Msg out', res, 'Msg in') self.tb.msg_connect(est, 'Msg out', debug, 'store') #self.tb.msg_connect(est,'Msg out',debug,'print') self.tb.start() sleep(0.5) self.tb.stop() self.tb.wait() # check data msg = debug.get_message(0) self.assertEqual("rx_time", pmt.symbol_to_string(pmt.nth(0, (pmt.nth( 0, msg))))) # check rx_time message part (symbol) self.assertEqual(0, pmt.to_uint64( pmt.tuple_ref(pmt.nth(1, (pmt.nth(0, msg))), 0))) # check rx_time value self.assertEqual( 0.0, pmt.to_double(pmt.tuple_ref(pmt.nth(1, (pmt.nth(0, msg))), 1))) self.assertEqual( "velocity", pmt.symbol_to_string(pmt.nth( 0, (pmt.nth(1, msg))))) # check velocity message part (symbol) self.assertAlmostEqual( 1, velocity / pmt.f32vector_ref(pmt.nth(1, (pmt.nth(1, msg))), 0), 2) # check velocity value
def connect_audio_stage(self, input_port): stereo_rate = self.demod_rate normalizer = TWO_PI / stereo_rate pilot_tone = 19000 pilot_low = pilot_tone * 0.9 pilot_high = pilot_tone * 1.1 def make_audio_filter(): return grfilter.fir_filter_fff( stereo_rate // self.__audio_int_rate, # decimation firdes.low_pass(1.0, stereo_rate, 15000, 5000, firdes.WIN_HAMMING), ) stereo_pilot_filter = grfilter.fir_filter_fcc( 1, firdes.complex_band_pass(1.0, stereo_rate, pilot_low, pilot_high, 300) # decimation ) # TODO magic number from gqrx stereo_pilot_pll = analog.pll_refout_cc( 0.001, normalizer * pilot_high, normalizer * pilot_low # TODO magic number from gqrx ) stereo_pilot_doubler = blocks.multiply_cc() stereo_pilot_out = blocks.complex_to_imag() difference_channel_mixer = blocks.multiply_ff() difference_channel_filter = make_audio_filter() mono_channel_filter = make_audio_filter() mixL = blocks.add_ff(1) mixR = blocks.sub_ff(1) # connections self.connect(input_port, mono_channel_filter) if self.stereo: # stereo pilot tone tracker self.connect(input_port, stereo_pilot_filter, stereo_pilot_pll) self.connect(stereo_pilot_pll, (stereo_pilot_doubler, 0)) self.connect(stereo_pilot_pll, (stereo_pilot_doubler, 1)) self.connect(stereo_pilot_doubler, stereo_pilot_out) # pick out stereo left-right difference channel (at stereo_rate) self.connect(input_port, (difference_channel_mixer, 0)) self.connect(stereo_pilot_out, (difference_channel_mixer, 1)) self.connect(difference_channel_mixer, difference_channel_filter) # recover left/right channels (at self.__audio_int_rate) self.connect(difference_channel_filter, (mixL, 1)) self.connect(difference_channel_filter, (mixR, 1)) resamplerL = self._make_resampler((mixL, 0), self.__audio_int_rate) resamplerR = self._make_resampler((mixR, 0), self.__audio_int_rate) self.connect(mono_channel_filter, (mixL, 0)) self.connect(mono_channel_filter, (mixR, 0)) self.connect_audio_output(resamplerL, resamplerR) else: resampler = self._make_resampler(mono_channel_filter, self.__audio_int_rate) self.connect_audio_output(resampler, resampler)
def test_004_connect (self): """ Advanced test: - Allocator -> IFFT -> Frequency offset -> FFT -> Serializer - FFT does shift (moves DC to middle) - Make sure input == output - Frequency offset is -2 carriers """ fft_len = 8 n_syms = 1 carr_offset = -2 freq_offset = 1.0 / fft_len * carr_offset # Normalized frequency occupied_carriers = ((-2, -1, 1, 2),) pilot_carriers = ((-3,),(3,)) pilot_symbols = ((1j,),(-1j,)) tx_data = (1, 2, 3, 4) tag_name = "len" tag = gr.tag_t() tag.offset = 0 tag.key = pmt.string_to_symbol(tag_name) tag.value = pmt.from_long(len(tx_data)) offsettag = gr.tag_t() offsettag.offset = 0 offsettag.key = pmt.string_to_symbol("ofdm_sync_carr_offset") offsettag.value = pmt.from_long(carr_offset) src = blocks.vector_source_c(tx_data, False, 1, (tag, offsettag)) alloc = digital.ofdm_carrier_allocator_cvc(fft_len, occupied_carriers, pilot_carriers, pilot_symbols, (), tag_name) tx_ifft = fft.fft_vcc(fft_len, False, (1.0/fft_len,)*fft_len, True) oscillator = analog.sig_source_c(1.0, analog.GR_COS_WAVE, freq_offset, 1.0) mixer = blocks.multiply_cc() rx_fft = fft.fft_vcc(fft_len, True, (), True) sink2 = blocks.vector_sink_c(fft_len) self.tb.connect(rx_fft, sink2) serializer = digital.ofdm_serializer_vcc( alloc, "", 0, "ofdm_sync_carr_offset", True ) sink = blocks.vector_sink_c() self.tb.connect( src, alloc, tx_ifft, blocks.vector_to_stream(gr.sizeof_gr_complex, fft_len), (mixer, 0), blocks.stream_to_vector(gr.sizeof_gr_complex, fft_len), rx_fft, serializer, sink ) self.tb.connect(oscillator, (mixer, 1)) self.tb.run () self.assertComplexTuplesAlmostEqual(sink.data()[-len(occupied_carriers[0]):], tx_data, places=4)
def test_sine(self, param): """this function run the defined test, for easier understanding""" tb = self.tb data_agc = namedtuple('data_agc', 'src out') src_sine = analog.sig_source_c(param.samp_rate, analog.GR_SIN_WAVE, param.freq_sine, 1) src_square = analog.sig_source_f( param.samp_rate, analog.GR_SQR_WAVE, param.freq_square, ((param.input_amplitude_max - param.input_amplitude_min) / math.sqrt(2)), (param.input_amplitude_min / math.sqrt(2))) src_noise = analog.noise_source_c(analog.GR_GAUSSIAN, param.noise, 0) adder = blocks.add_vcc(1) multiply_const = blocks.multiply_const_ff(-1) multiply_complex = blocks.multiply_cc() dst_agc = blocks.vector_sink_c() dst_source = blocks.vector_sink_c() float_to_complex = blocks.float_to_complex() head = blocks.head(gr.sizeof_gr_complex, int(param.N)) agc = ecss.agc_cc(param.settling_time, param.reference, 1.0, 65536.0, param.samp_rate) tb.connect(src_square, (float_to_complex, 0)) tb.connect(src_square, multiply_const) tb.connect(multiply_const, (float_to_complex, 1)) tb.connect(src_sine, (adder, 0)) tb.connect(src_noise, (adder, 1)) tb.connect(adder, (multiply_complex, 0)) tb.connect(float_to_complex, (multiply_complex, 1)) tb.connect(multiply_complex, head) tb.connect(head, agc) tb.connect(agc, dst_agc) tb.connect(head, dst_source) self.tb.run() data_agc.src = dst_source.data() data_agc.out = dst_agc.data() return data_agc
def __init__(self): gr.top_block.__init__(self) usage = "%prog: [options] samples_file" parser = OptionParser(option_class=eng_option, usage=usage) parser.add_option("-m", "--dab-mode", type="int", default=1, help="DAB mode [default=%default]") parser.add_option("-F", "--filter-input", action="store_true", default=False, help="Enable FFT filter at input") parser.add_option("-s", "--resample-fixed", type="float", default=1, help="resample by a fixed factor (fractional interpolation)") parser.add_option("-S", "--autocorrect-sample-rate", action="store_true", default=False, help="Estimate sample rate offset and resample (dynamic fractional interpolation)") parser.add_option('-r', '--sample-rate', type="int", default=2048000, help="Use non-standard sample rate (default=%default)") parser.add_option('-e', '--equalize-magnitude', action="store_true", default=False, help="Enable individual carrier magnitude equalizer") parser.add_option('-d', '--debug', action="store_true", default=False, help="Write output to files") parser.add_option('-v', '--verbose', action="store_true", default=False, help="Print status messages") (options, args) = parser.parse_args () dp = parameters.dab_parameters(options.dab_mode, verbose=options.verbose, sample_rate=options.sample_rate) rp = parameters.receiver_parameters(options.dab_mode, input_fft_filter=options.filter_input, autocorrect_sample_rate=options.autocorrect_sample_rate, sample_rate_correction_factor=options.resample_fixed, equalize_magnitude=options.equalize_magnitude, verbose=options.verbose) if len(args)<1: if options.verbose: print "-> using repeating random vector as source" self.sigsrc = blocks.vector_source_c([10e6*(random.random() + 1j*random.random()) for i in range(0,100000)],True) self.ns_simulate = blocks.vector_source_c([0.01]*dp.ns_length+[1]*dp.symbols_per_frame*dp.symbol_length,1) self.mult = blocks.multiply_cc() # simulate null symbols ... self.src = blocks.throttle( gr.sizeof_gr_complex,2048000) self.connect(self.sigsrc, (self.mult, 0)) self.connect(self.ns_simulate, (self.mult, 1)) self.connect(self.mult, self.src) else: filename = args[0] if options.verbose: print "-> using samples from file " + filename self.src = blocks.file_source(gr.sizeof_gr_complex, filename, False) self.dab_demod = ofdm.ofdm_demod(dp, rp, debug=options.debug, verbose=options.verbose) self.connect(self.src, self.dab_demod) # sink output to nowhere self.nop0 = blocks.nop(gr.sizeof_char*dp.num_carriers/4) self.nop1 = blocks.nop(gr.sizeof_char) self.connect((self.dab_demod,0),self.nop0) self.connect((self.dab_demod,1),self.nop1)
def test_004_connect(self): """ Advanced test: - Allocator -> IFFT -> Frequency offset -> FFT -> Serializer - FFT does shift (moves DC to middle) - Make sure input == output - Frequency offset is -2 carriers """ fft_len = 8 n_syms = 1 carr_offset = -2 freq_offset = 1.0 / fft_len * carr_offset # Normalized frequency occupied_carriers = ((-2, -1, 1, 2),) pilot_carriers = ((-3,), (3,)) pilot_symbols = ((1j,), (-1j,)) tx_data = (1, 2, 3, 4) tag_name = "len" tag = gr.tag_t() tag.offset = 0 tag.key = pmt.string_to_symbol(tag_name) tag.value = pmt.from_long(len(tx_data)) offsettag = gr.tag_t() offsettag.offset = 0 offsettag.key = pmt.string_to_symbol("ofdm_sync_carr_offset") offsettag.value = pmt.from_long(carr_offset) src = blocks.vector_source_c(tx_data, False, 1, (tag, offsettag)) alloc = digital.ofdm_carrier_allocator_cvc( fft_len, occupied_carriers, pilot_carriers, pilot_symbols, (), tag_name ) tx_ifft = fft.fft_vcc(fft_len, False, (1.0 / fft_len,) * fft_len, True) oscillator = analog.sig_source_c(1.0, analog.GR_COS_WAVE, freq_offset, 1.0 / fft_len) mixer = blocks.multiply_cc() rx_fft = fft.fft_vcc(fft_len, True, (), True) sink2 = blocks.vector_sink_c(fft_len) self.tb.connect(rx_fft, sink2) serializer = digital.ofdm_serializer_vcc(alloc, "", 0, "ofdm_sync_carr_offset", True) sink = blocks.vector_sink_c() self.tb.connect( src, alloc, tx_ifft, blocks.vector_to_stream(gr.sizeof_gr_complex, fft_len), (mixer, 0), blocks.stream_to_vector(gr.sizeof_gr_complex, fft_len), rx_fft, serializer, sink, ) self.tb.connect(oscillator, (mixer, 1)) self.tb.run() self.assertComplexTuplesAlmostEqual(sink.data()[-len(occupied_carriers[0]) :], tx_data, places=4)
def __init__(self, samplerate, bits_per_sec, fftlen): gr.hier_block2.__init__(self, "square_and_fft_sync_cc", gr.io_signature(1, 1, gr.sizeof_gr_complex), # Input signature gr.io_signature(1, 1, gr.sizeof_gr_complex)) # Output signature #this is just the old square-and-fft method #ais.freqest is simply looking for peaks spaced bits-per-sec apart self.square = blocks.multiply_cc(1) self.fftvect = blocks.stream_to_vector(gr.sizeof_gr_complex, fftlen) self.fft = fft.fft_vcc(fftlen, True, window.rectangular(fftlen), True) self.freqest = ais.freqest(int(samplerate), int(bits_per_sec), fftlen) self.repeat = blocks.repeat(gr.sizeof_float, fftlen) self.fm = analog.frequency_modulator_fc(-1.0/(float(samplerate)/(2*pi))) self.mix = blocks.multiply_cc(1) self.connect(self, (self.square, 0)) self.connect(self, (self.square, 1)) #this is the feedforward branch self.connect(self, (self.mix, 0)) #this is the feedback branch self.connect(self.square, self.fftvect, self.fft, self.freqest, self.repeat, self.fm, (self.mix, 1)) #and this is the output self.connect(self.mix, self)
def __init__(self): gr.hier_block2.__init__(self, "transmitter_am", gr.io_signature(1, 1, gr.sizeof_float), gr.io_signature(1, 1, gr.sizeof_gr_complex)) self.rate = 44.1e3 / 200e3 self.interp = filter.fractional_interpolator_ff(0.0, self.rate) self.cnv = blocks.float_to_complex() self.mul = blocks.multiply_const_cc(1.0) self.add = blocks.add_const_cc(1.0) self.src = analog.sig_source_c(200e3, analog.GR_SIN_WAVE, 0e3, 1.0) self.mod = blocks.multiply_cc() self.connect(self, self.interp, self.cnv, self.mul, self.add, self.mod, self) self.connect(self.src, (self.mod, 1))
def test01(self): sps = 4 rolloff = 0.35 bw = 2 * math.pi / 100.0 ntaps = 45 # Create pulse shape filter rrc_taps = filter.firdes.root_raised_cosine(sps, sps, 1.0, rolloff, ntaps) # The frequency offset to correct foffset = 0.2 / (2.0 * math.pi) # Create a set of 1's and -1's, pulse shape and interpolate to sps random.seed(0) data = [2.0 * random.randint(0, 2) - 1.0 for i in range(200)] self.src = blocks.vector_source_c(data, False) self.rrc = filter.interp_fir_filter_ccf(sps, rrc_taps) # Mix symbols with a complex sinusoid to spin them self.nco = analog.sig_source_c(1, analog.GR_SIN_WAVE, foffset, 1) self.mix = blocks.multiply_cc() # FLL will despin the symbols to an arbitrary phase self.fll = digital.fll_band_edge_cc(sps, rolloff, ntaps, bw) # Create sinks for all outputs of the FLL # we will only care about the freq and error outputs self.vsnk_frq = blocks.vector_sink_f() self.nsnk_fll = blocks.null_sink(gr.sizeof_gr_complex) self.nsnk_phs = blocks.null_sink(gr.sizeof_float) self.nsnk_err = blocks.null_sink(gr.sizeof_float) # Connect the blocks self.tb.connect(self.nco, (self.mix, 1)) self.tb.connect(self.src, self.rrc, (self.mix, 0)) self.tb.connect(self.mix, self.fll, self.nsnk_fll) self.tb.connect((self.fll, 1), self.vsnk_frq) self.tb.connect((self.fll, 2), self.nsnk_phs) self.tb.connect((self.fll, 3), self.nsnk_err) self.tb.run() N = 700 dst_data = self.vsnk_frq.data()[N:] expected_result = len(dst_data) * [ -0.20, ] self.assertFloatTuplesAlmostEqual(expected_result, dst_data, 4)
def test_multiply_vcc_one(self): src1_data = [ 1.0 + 2.0j, ] src2_data = [ 3.0 + 4.0j, ] src3_data = [ 5.0 + 6.0j, ] expected_result = [ -85 + 20j, ] op = blocks.multiply_cc(1) self.help_cc(1, (src1_data, src2_data, src3_data), expected_result, op)
def __init__(self, freq_off): gr.hier_block2.__init__(self, "freq_offset", gr.io_signature(1,1,gr.sizeof_gr_complex), gr.io_signature(1,1,gr.sizeof_gr_complex)) freqoff = freq_off config = self.config = station_configuration() print "Artificial Frequency Offset: ",freqoff freq_shift = blocks.multiply_cc() norm_freq = freqoff / config.fft_length freq_off_src = self.freq_off_src = analog.sig_source_c(1.0, analog.GR_SIN_WAVE, norm_freq, 1.0, 0.0 ) self.connect( self,( freq_shift, 0 ) ) self.connect( freq_off_src, ( freq_shift, 1 ) ) self.connect( freq_shift, self )
def test_001_t(self): # check doppler freq (frequency shifting) # set up fg test_len = 1000 packet_len = test_len samp_rate = 2000 frequency = (0, ) amplitude = 1 Range = (10, ) velocity = (15, ) rcs = (1e9, ) azimuth = (0, ) position_rx = (0, ) center_freq = 1e9 rndm_phase = True self_coupling = False self_coupling_db = -10 src = radar.signal_generator_cw_c(packet_len, samp_rate, frequency, amplitude) head = blocks.head(8, test_len) sim = radar.static_target_simulator_cc(Range, velocity, rcs, azimuth, position_rx, samp_rate, center_freq, self_coupling_db, rndm_phase, self_coupling) mult = blocks.multiply_cc() snk = blocks.vector_sink_c() self.tb.connect(src, head, sim) self.tb.connect((sim, 0), (mult, 0)) self.tb.connect((head, 0), (mult, 1)) self.tb.connect(mult, snk) self.tb.run() # check data data = snk.data() doppler_freq = 2 * velocity[ 0] * center_freq / 3e8 # peak estimation, calc with doppler formula fft = numpy.fft.fft(data) # get fft num = np.argmax(abs(fft)) # index of max sample fft_freq = samp_rate * num / len( fft ) # calc freq out of max sample index, works only for frequencies < samp_rate/2! self.assertAlmostEqual(fft_freq, doppler_freq, 2) # check if peak in data is doppler peak
def __init__(self, freq_off): gr.hier_block2.__init__(self, "freq_offset", gr.io_signature(1, 1, gr.sizeof_gr_complex), gr.io_signature(1, 1, gr.sizeof_gr_complex)) freqoff = freq_off config = self.config = station_configuration() print "Artificial Frequency Offset: ", freqoff freq_shift = blocks.multiply_cc() norm_freq = freqoff / config.fft_length freq_off_src = self.freq_off_src = analog.sig_source_c( 1.0, analog.GR_SIN_WAVE, norm_freq, 1.0, 0.0) self.connect(self, (freq_shift, 0)) self.connect(freq_off_src, (freq_shift, 1)) self.connect(freq_shift, self)
def update(self, rxcenter, txcenter, rxsps, txsps, fast=False): """ Updates the module by its parameters. Supports a full reconfiguration and a fast reconfiguration for only simple changes such as volume, squelch, frequency, and audiosps which can be changed without much computational expense. """ self.rxsps = rxsps self.txsps = txsps # self.freq, self.bw, self.bwdrop, self.gain, self.vol, self.isps, self.sq freq = self.freq.get_value() bw = self.bw.get_value() bwdrop = self.bwdrop.get_value() gain = self.gain.get_value() vol = self.vol.get_value() sq = self.sq.get_value() dev = self.dev.get_value() taps = filter.firdes.low_pass(gain, sps, bw, bwdrop, filter.firdes.WIN_BLACKMAN) # Turn it off to disconnect them before the variable contents # below are replaced. was_active = self.active self.off() self.shiftsrc = analog.sig_source_c(sps, analog.GR_COS_WAVE, -freq, 0.1, 0) self.shifter = blocks.multiply_cc() self.decfilter = filter.fir_filter_ccf(1, taps) self.fmdemod = analog.nbfm_rx( audio_rate=16000, quad_rate=sps, tau=float(tau) * 0.000000001, max_dev=dev, ) self.sqblock = analog.standard_squelch(isps) self.sqblock.set_threshold(float(sq) / 100.0) self.volblock = blocks.multiply_const_ff(float(vol) / 70.0) if was_active: self.on() else: self.off()
def add_vor(freq, angle): compensation = math.pi / 180 * -6.5 # empirical, calibrated against VOR receiver (and therefore probably wrong) angle = angle + compensation angle = angle % (2 * math.pi) vor_sig_freq = 30 phase_shift = int(rf_rate / vor_sig_freq * (angle / (2 * math.pi))) vor_dev = 480 vor_channel = make_channel(freq) vor_30 = analog.sig_source_f(audio_rate, analog.GR_COS_WAVE, vor_sig_freq, 1, 0) vor_add = blocks.add_cc(1) vor_audio = blocks.add_ff(1) # Audio/AM signal self.connect( vor_30, blocks.multiply_const_ff(0.3), # M_n (vor_audio, 0)) self.connect(audio_signal, blocks.multiply_const_ff(0.07), # M_i (vor_audio, 1)) # Carrier component self.connect( analog.sig_source_c(0, analog.GR_CONST_WAVE, 0, 0, 1), (vor_add, 0)) # AM component self.connect( vor_audio, blocks.float_to_complex(1), make_interpolator(), blocks.delay(gr.sizeof_gr_complex, phase_shift), (vor_add, 1)) # FM component vor_fm_mult = blocks.multiply_cc(1) self.connect( # carrier generation analog.sig_source_f(rf_rate, analog.GR_COS_WAVE, 9960, 1, 0), blocks.float_to_complex(1), (vor_fm_mult, 1)) self.connect( # modulation vor_30, filter.interp_fir_filter_fff(interp, interp_taps), # float not complex analog.frequency_modulator_fc(2 * math.pi * vor_dev / rf_rate), blocks.multiply_const_cc(0.3), # M_d vor_fm_mult, (vor_add, 2)) self.connect( vor_add, vor_channel) signals.append(vor_channel)
def test01(self): sps = 4 rolloff = 0.35 bw = 2*math.pi/100.0 ntaps = 45 # Create pulse shape filter rrc_taps = filter.firdes.root_raised_cosine( sps, sps, 1.0, rolloff, ntaps) # The frequency offset to correct foffset = 0.2 / (2.0*math.pi) # Create a set of 1's and -1's, pulse shape and interpolate to sps random.seed(0) data = [2.0*random.randint(0, 2) - 1.0 for i in range(200)] self.src = blocks.vector_source_c(data, False) self.rrc = filter.interp_fir_filter_ccf(sps, rrc_taps) # Mix symbols with a complex sinusoid to spin them self.nco = analog.sig_source_c(1, analog.GR_SIN_WAVE, foffset, 1) self.mix = blocks.multiply_cc() # FLL will despin the symbols to an arbitrary phase self.fll = digital.fll_band_edge_cc(sps, rolloff, ntaps, bw) # Create sinks for all outputs of the FLL # we will only care about the freq and error outputs self.vsnk_frq = blocks.vector_sink_f() self.nsnk_fll = blocks.null_sink(gr.sizeof_gr_complex) self.nsnk_phs = blocks.null_sink(gr.sizeof_float) self.nsnk_err = blocks.null_sink(gr.sizeof_float) # Connect the blocks self.tb.connect(self.nco, (self.mix,1)) self.tb.connect(self.src, self.rrc, (self.mix,0)) self.tb.connect(self.mix, self.fll, self.nsnk_fll) self.tb.connect((self.fll,1), self.vsnk_frq) self.tb.connect((self.fll,2), self.nsnk_phs) self.tb.connect((self.fll,3), self.nsnk_err) self.tb.run() N = 700 dst_data = self.vsnk_frq.data()[N:] expected_result = len(dst_data)* [-0.20,] self.assertFloatTuplesAlmostEqual(expected_result, dst_data, 4)
def __init__(self, lo_freq, audio_rate, if_rate): gr.hier_block2.__init__( self, "build_fm", gr.io_signature(1, 1, gr.sizeof_float), gr.io_signature(1, 1, gr.sizeof_gr_complex) ) fmtx = analog.nbfm_tx(audio_rate, if_rate, max_dev=5e3, tau=75e-6) # Local oscillator lo = analog.sig_source_c( if_rate, analog.GR_SIN_WAVE, lo_freq, 1.0, 0 # sample rate # waveform type # frequency # amplitude ) # DC Offset mixer = blocks.multiply_cc() self.connect(self, fmtx, (mixer, 0)) self.connect(lo, (mixer, 1)) self.connect(mixer, self)
def __init__(self): gr.hier_block2.__init__(self, "transmitter_am", gr.io_signature(1, 1, gr.sizeof_float), gr.io_signature(1, 1, gr.sizeof_gr_complex)) self.rate = 44.1e3 / 200e3 # self.rate = 200e3/44.1e3 # Build the resampling MMSE filter (float input, float output) self.interp = filter.mmse_resampler_ff(0.0, self.rate) self.cnv = blocks.float_to_complex() self.mul = blocks.multiply_const_cc(1.0) self.add = blocks.add_const_cc(1.0) self.src = analog.sig_source_c(200e3, analog.GR_SIN_WAVE, 0e3, 1.0) # self.src = analog.sig_source_c(200e3, analog.GR_SIN_WAVE, 50e3, 1.0) self.mod = blocks.multiply_cc() self.connect(self, self.interp, self.cnv, self.mul, self.add, self.mod, self) self.connect(self.src, (self.mod, 1))
def __init__(self, noise_voltage, freq, timing): gr.hier_block2.__init__(self, "channel_model", gr.io_signature(1, 1, gr.sizeof_gr_complex), gr.io_signature(1, 1, gr.sizeof_gr_complex)) timing_offset = filter.fractional_resampler_cc(0, timing) noise_adder = blocks.add_cc() noise = analog.noise_source_c(analog.GR_GAUSSIAN, noise_voltage, 0) freq_offset = analog.sig_source_c(1, analog.GR_SIN_WAVE, freq, 1.0, 0.0) mixer_offset = blocks.multiply_cc() self.connect(self, timing_offset) self.connect(timing_offset, (mixer_offset, 0)) self.connect(freq_offset, (mixer_offset, 1)) self.connect(mixer_offset, (noise_adder, 1)) self.connect(noise, (noise_adder, 0)) self.connect(noise_adder, self)
def __init__(self, lo_freq, if_rate, input_file): gr.hier_block2.__init__(self, "file_pipeline", gr.io_signature(0, 0, 0), # Input signature gr.io_signature(1, 1, gr.sizeof_gr_complex)) # Output signature fs = blocks.file_source(gr.sizeof_gr_complex, input_file, True) agc = analog.feedforward_agc_cc(160, 1.0) # Local oscillator lo = analog.sig_source_c (if_rate, # sample rate analog.GR_SIN_WAVE, # waveform type lo_freq, #frequency 1.0, # amplitude 0) # DC Offset mixer = blocks.multiply_cc () self.connect (fs, agc, (mixer, 0)) self.connect (lo, (mixer, 1)) self.connect (mixer, self)
def __init__(self, noise_voltage, freq, timing): gr.hier_block2.__init__(self, "channel_model", gr.io_signature(1, 1, gr.sizeof_gr_complex), gr.io_signature(1, 1, gr.sizeof_gr_complex)) timing_offset = filter.mmse_resampler_cc(0, timing) noise_adder = blocks.add_cc() noise = analog.noise_source_c(analog.GR_GAUSSIAN, noise_voltage, 0) freq_offset = analog.sig_source_c(1, analog.GR_SIN_WAVE, freq, 1.0, 0.0) mixer_offset = blocks.multiply_cc(); self.connect(self, timing_offset) self.connect(timing_offset, (mixer_offset,0)) self.connect(freq_offset, (mixer_offset,1)) self.connect(mixer_offset, (noise_adder,1)) self.connect(noise, (noise_adder,0)) self.connect(noise_adder, self)
def __init__(self, mode, input_rate=0, input_center_freq=0, audio_rate=0, rec_freq=100.0, audio_gain=-6, audio_pan=0, context=None): assert input_rate > 0 assert audio_rate > 0 gr.hier_block2.__init__( # str() because insists on non-unicode self, str('%s receiver' % (mode,)), gr.io_signature(1, 1, gr.sizeof_gr_complex * 1), gr.io_signature(2, 2, gr.sizeof_float * 1), ) # Provided by caller self.input_rate = input_rate self.input_center_freq = input_center_freq self.audio_rate = audio_rate self.context = context # Simple state self.mode = mode self.rec_freq = rec_freq self.audio_gain = audio_gain self.audio_pan = min(1, max(-1, audio_pan)) # Blocks self.oscillator = analog.sig_source_c(input_rate, analog.GR_COS_WAVE, -rec_freq, 1, 0) self.mixer = blocks.multiply_cc(1) self.demodulator = self.__make_demodulator(mode, {}) self.__demod_tunable = ITunableDemodulator.providedBy(self.demodulator) self.audio_gain_l_block = blocks.multiply_const_ff(0.0) self.audio_gain_r_block = blocks.multiply_const_ff(0.0) self.probe_audio = analog.probe_avg_mag_sqrd_f(0, alpha=10.0 / audio_rate) self.__update_oscillator() # in case of __demod_tunable self.__update_audio_gain() self.__do_connect()
def test_001_t (self): # set up fg test_len = 1024 packet_len = test_len samp_rate = 2000 center_freq = 1e9 velocity = 15 src = radar.signal_generator_cw_c(packet_len,samp_rate,(0,0),1) head = blocks.head(8,test_len) sim = radar.static_target_simulator_cc((10,10),(velocity,velocity),(1e9,1e9),(0,0),(0,),samp_rate,center_freq,1,True,False) mult = blocks.multiply_cc() fft = radar.ts_fft_cc(packet_len) cfar = radar.os_cfar_c(samp_rate, 5, 0, 0.78, 10, True) est = radar.estimator_cw(center_freq) res = radar.print_results() debug = blocks.message_debug() self.tb.connect(src,head,(mult,1)) self.tb.connect(head,sim,(mult,0)) self.tb.connect(mult,fft,cfar) self.tb.msg_connect(cfar,'Msg out',est,'Msg in') self.tb.msg_connect(est,'Msg out',res,'Msg in') self.tb.msg_connect(est,'Msg out',debug,'store') #self.tb.msg_connect(est,'Msg out',debug,'print') self.tb.start() sleep(0.5) self.tb.stop() self.tb.wait() # check data msg = debug.get_message(0) self.assertEqual( "rx_time", pmt.symbol_to_string(pmt.nth(0,(pmt.nth(0,msg)))) ) # check rx_time message part (symbol) self.assertEqual( 0, pmt.to_uint64(pmt.tuple_ref(pmt.nth(1,(pmt.nth(0,msg))),0)) ) # check rx_time value self.assertEqual( 0.0, pmt.to_double(pmt.tuple_ref(pmt.nth(1,(pmt.nth(0,msg))),1)) ) self.assertEqual( "velocity", pmt.symbol_to_string(pmt.nth(0,(pmt.nth(1,msg)))) ) # check velocity message part (symbol) self.assertAlmostEqual( 1, velocity/pmt.f32vector_ref(pmt.nth(1,(pmt.nth(1,msg))),0), 2 ) # check velocity value
def test_001_t (self): # check doppler freq (frequency shifting) # set up fg test_len = 1000 packet_len = test_len samp_rate = 2000 frequency = (0,) amplitude = 1 Range = (10,) velocity = (15,) rcs = (1e9,) azimuth = (0,) position_rx = (0,) center_freq = 1e9 rndm_phase = True self_coupling = False self_coupling_db = -10; src = radar.signal_generator_cw_c(packet_len,samp_rate,frequency,amplitude) head = blocks.head(8,test_len) sim = radar.static_target_simulator_cc(Range, velocity, rcs, azimuth, position_rx, samp_rate, center_freq, self_coupling_db, rndm_phase, self_coupling) mult = blocks.multiply_cc() snk = blocks.vector_sink_c() self.tb.connect(src,head,sim) self.tb.connect((sim,0),(mult,0)) self.tb.connect((head,0),(mult,1)) self.tb.connect(mult,snk) self.tb.run () # check data data = snk.data() doppler_freq = 2*velocity[0]*center_freq/3e8 # peak estimation, calc with doppler formula fft = numpy.fft.fft(data) # get fft num = np.argmax(abs(fft)) # index of max sample fft_freq = samp_rate*num/len(fft) # calc freq out of max sample index, works only for frequencies < samp_rate/2! self.assertAlmostEqual(fft_freq,doppler_freq,2) # check if peak in data is doppler peak
def __init__(self, fft_len, cp_len, nofdm_symbols): gr.hier_block2.__init__( self, "ofdm_basebandsignal_to_frames_cvc", gr.io_signature(1, 1, gr.sizeof_gr_complex), gr.io_signature(1, 1, fft_len*gr.sizeof_gr_complex) ) self.fft_len = fft_len self.cp_len = cp_len self.nofdm_symbols = nofdm_symbols sync_detect = digital.ofdm_sync_sc_cfb( fft_len = fft_len, cp_len = cp_len ) delay = blocks.delay(gr.sizeof_gr_complex, self.fft_len+self.cp_len) oscillator = analog.frequency_modulator_fc(-2.0 / self.fft_len) mixer = blocks.multiply_cc() frames = mimoots.ofdm_extract_frame_cvc( fft_len = self.fft_len, cp_len = self.cp_len, nsymbols_per_ofdmframe = self.nofdm_symbols+2 # +2 Sync-Words ) self.connect(self, sync_detect) self.connect((sync_detect,0), oscillator, (mixer,0)) self.connect((self,0), delay, (mixer,1)) self.connect((sync_detect,1), (frames,1)) self.connect(mixer, (frames,0)) self.connect(frames, self)
def __init__(self, fft_length, cp_length, snr, kstime, logging): ''' Maximum Likelihood OFDM synchronizer: J. van de Beek, M. Sandell, and P. O. Borjesson, "ML Estimation of Time and Frequency Offset in OFDM Systems," IEEE Trans. Signal Processing, vol. 45, no. 7, pp. 1800-1805, 1997. ''' gr.hier_block2.__init__(self, "ofdm_sync_ml", 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) SNR = 10.0**(snr / 10.0) rho = SNR / (SNR + 1.0) symbol_length = fft_length + cp_length # ML Sync # Energy Detection from ML Sync self.connect(self, self.input) # Create a delay line self.delay = blocks.delay(gr.sizeof_gr_complex, fft_length) self.connect(self.input, self.delay) # magnitude squared blocks self.magsqrd1 = blocks.complex_to_mag_squared() self.magsqrd2 = blocks.complex_to_mag_squared() self.adder = blocks.add_ff() moving_sum_taps = [rho / 2 for i in range(cp_length)] self.moving_sum_filter = filter.fir_filter_fff(1,moving_sum_taps) self.connect(self.input,self.magsqrd1) self.connect(self.delay,self.magsqrd2) self.connect(self.magsqrd1,(self.adder,0)) self.connect(self.magsqrd2,(self.adder,1)) self.connect(self.adder,self.moving_sum_filter) # Correlation from ML Sync self.conjg = blocks.conjugate_cc(); self.mixer = blocks.multiply_cc(); movingsum2_taps = [1.0 for i in range(cp_length)] self.movingsum2 = filter.fir_filter_ccf(1,movingsum2_taps) # Correlator data handler self.c2mag = blocks.complex_to_mag() self.angle = blocks.complex_to_arg() self.connect(self.input,(self.mixer,1)) self.connect(self.delay,self.conjg,(self.mixer,0)) self.connect(self.mixer,self.movingsum2,self.c2mag) self.connect(self.movingsum2,self.angle) # ML Sync output arg, need to find maximum point of this self.diff = blocks.sub_ff() self.connect(self.c2mag,(self.diff,0)) self.connect(self.moving_sum_filter,(self.diff,1)) #ML measurements input to sampler block and detect self.f2c = blocks.float_to_complex() self.pk_detect = blocks.peak_detector_fb(0.2, 0.25, 30, 0.0005) self.sample_and_hold = blocks.sample_and_hold_ff() # use the sync loop values to set the sampler and the NCO # self.diff = theta # self.angle = epsilon self.connect(self.diff, self.pk_detect) # The DPLL corrects for timing differences between CP correlations use_dpll = 0 if use_dpll: self.dpll = gr.dpll_bb(float(symbol_length),0.01) self.connect(self.pk_detect, self.dpll) self.connect(self.dpll, (self.sample_and_hold,1)) else: self.connect(self.pk_detect, (self.sample_and_hold,1)) self.connect(self.angle, (self.sample_and_hold,0)) ################################ # correlate against known symbol # This gives us the same timing signal as the PN sync block only on the preamble # we don't use the signal generated from the CP correlation because we don't want # to readjust the timing in the middle of the packet or we ruin the equalizer settings. kstime = [k.conjugate() for k in kstime] kstime.reverse() self.kscorr = filter.fir_filter_ccc(1, kstime) self.corrmag = blocks.complex_to_mag_squared() self.div = blocks.divide_ff() # The output signature of the correlation has a few spikes because the rest of the # system uses the repeated preamble symbol. It needs to work that generically if # anyone wants to use this against a WiMAX-like signal since it, too, repeats. # The output theta of the correlator above is multiplied with this correlation to # identify the proper peak and remove other products in this cross-correlation self.threshold_factor = 0.1 self.slice = blocks.threshold_ff(self.threshold_factor, self.threshold_factor, 0) self.f2b = blocks.float_to_char() self.b2f = blocks.char_to_float() self.mul = blocks.multiply_ff() # Normalize the power of the corr output by the energy. This is not really needed # and could be removed for performance, but it makes for a cleaner signal. # if this is removed, the threshold value needs adjustment. self.connect(self.input, self.kscorr, self.corrmag, (self.div,0)) self.connect(self.moving_sum_filter, (self.div,1)) self.connect(self.div, (self.mul,0)) self.connect(self.pk_detect, self.b2f, (self.mul,1)) self.connect(self.mul, self.slice) # Set output signals # Output 0: fine frequency correction value # Output 1: timing signal self.connect(self.sample_and_hold, (self,0)) self.connect(self.slice, self.f2b, (self,1)) if logging: self.connect(self.moving_sum_filter, blocks.file_sink(gr.sizeof_float, "ofdm_sync_ml-energy_f.dat")) self.connect(self.diff, blocks.file_sink(gr.sizeof_float, "ofdm_sync_ml-theta_f.dat")) self.connect(self.angle, blocks.file_sink(gr.sizeof_float, "ofdm_sync_ml-epsilon_f.dat")) self.connect(self.corrmag, blocks.file_sink(gr.sizeof_float, "ofdm_sync_ml-corrmag_f.dat")) self.connect(self.kscorr, blocks.file_sink(gr.sizeof_gr_complex, "ofdm_sync_ml-kscorr_c.dat")) self.connect(self.div, blocks.file_sink(gr.sizeof_float, "ofdm_sync_ml-div_f.dat")) self.connect(self.mul, blocks.file_sink(gr.sizeof_float, "ofdm_sync_ml-mul_f.dat")) self.connect(self.slice, blocks.file_sink(gr.sizeof_float, "ofdm_sync_ml-slice_f.dat")) self.connect(self.pk_detect, blocks.file_sink(gr.sizeof_char, "ofdm_sync_ml-peaks_b.dat")) if use_dpll: self.connect(self.dpll, blocks.file_sink(gr.sizeof_char, "ofdm_sync_ml-dpll_b.dat")) self.connect(self.sample_and_hold, blocks.file_sink(gr.sizeof_float, "ofdm_sync_ml-sample_and_hold_f.dat")) self.connect(self.input, blocks.file_sink(gr.sizeof_gr_complex, "ofdm_sync_ml-input_c.dat"))
def __init__(self, fft_length, cp_length, occupied_tones, snr, ks, logging=False): """ Hierarchical block for receiving OFDM symbols. The input is the complex modulated signal at baseband. Synchronized packets are sent back to the demodulator. Args: fft_length: total number of subcarriers (int) cp_length: length of cyclic prefix as specified in subcarriers (<= fft_length) (int) occupied_tones: number of subcarriers used for data (int) snr: estimated signal to noise ratio used to guide cyclic prefix synchronizer (float) ks: known symbols used as preambles to each packet (list of lists) logging: turn file logging on or off (bool) """ gr.hier_block2.__init__(self, "ofdm_receiver", gr.io_signature(1, 1, gr.sizeof_gr_complex), # Input signature gr.io_signature2(2, 2, gr.sizeof_gr_complex*occupied_tones, gr.sizeof_char)) # Output signature bw = (float(occupied_tones) / float(fft_length)) / 2.0 tb = bw*0.08 chan_coeffs = filter.firdes.low_pass (1.0, # gain 1.0, # sampling rate bw+tb, # midpoint of trans. band tb, # width of trans. band filter.firdes.WIN_HAMMING) # filter type self.chan_filt = filter.fft_filter_ccc(1, chan_coeffs) win = [1 for i in range(fft_length)] zeros_on_left = int(math.ceil((fft_length - occupied_tones)/2.0)) ks0 = fft_length*[0,] ks0[zeros_on_left : zeros_on_left + occupied_tones] = ks[0] ks0 = fft.ifftshift(ks0) ks0time = fft.ifft(ks0) # ADD SCALING FACTOR ks0time = ks0time.tolist() SYNC = "pn" if SYNC == "ml": nco_sensitivity = -1.0/fft_length # correct for fine frequency self.ofdm_sync = ofdm_sync_ml(fft_length, cp_length, snr, ks0time, logging) elif SYNC == "pn": nco_sensitivity = -2.0/fft_length # correct for fine frequency self.ofdm_sync = ofdm_sync_pn(fft_length, cp_length, logging) elif SYNC == "pnac": nco_sensitivity = -2.0/fft_length # correct for fine frequency self.ofdm_sync = ofdm_sync_pnac(fft_length, cp_length, ks0time, logging) # for testing only; do not user over the air # remove filter and filter delay for this elif SYNC == "fixed": self.chan_filt = blocks.multiply_const_cc(1.0) nsymbols = 18 # enter the number of symbols per packet freq_offset = 0.0 # if you use a frequency offset, enter it here nco_sensitivity = -2.0/fft_length # correct for fine frequency self.ofdm_sync = ofdm_sync_fixed(fft_length, cp_length, nsymbols, freq_offset, logging) # Set up blocks self.nco = analog.frequency_modulator_fc(nco_sensitivity) # generate a signal proportional to frequency error of sync block self.sigmix = blocks.multiply_cc() self.sampler = digital.ofdm_sampler(fft_length, fft_length+cp_length) self.fft_demod = gr_fft.fft_vcc(fft_length, True, win, True) self.ofdm_frame_acq = digital.ofdm_frame_acquisition(occupied_tones, fft_length, cp_length, ks[0]) self.connect(self, self.chan_filt) # filter the input channel self.connect(self.chan_filt, self.ofdm_sync) # into the synchronization alg. self.connect((self.ofdm_sync,0), self.nco, (self.sigmix,1)) # use sync freq. offset output to derotate input signal self.connect(self.chan_filt, (self.sigmix,0)) # signal to be derotated self.connect(self.sigmix, (self.sampler,0)) # sample off timing signal detected in sync alg self.connect((self.ofdm_sync,1), (self.sampler,1)) # timing signal to sample at self.connect((self.sampler,0), self.fft_demod) # send derotated sampled signal to FFT self.connect(self.fft_demod, (self.ofdm_frame_acq,0)) # find frame start and equalize signal self.connect((self.sampler,1), (self.ofdm_frame_acq,1)) # send timing signal to signal frame start self.connect((self.ofdm_frame_acq,0), (self,0)) # finished with fine/coarse freq correction, self.connect((self.ofdm_frame_acq,1), (self,1)) # frame and symbol timing, and equalization if logging: self.connect(self.chan_filt, blocks.file_sink(gr.sizeof_gr_complex, "ofdm_receiver-chan_filt_c.dat")) self.connect(self.fft_demod, blocks.file_sink(gr.sizeof_gr_complex*fft_length, "ofdm_receiver-fft_out_c.dat")) self.connect(self.ofdm_frame_acq, blocks.file_sink(gr.sizeof_gr_complex*occupied_tones, "ofdm_receiver-frame_acq_c.dat")) self.connect((self.ofdm_frame_acq,1), blocks.file_sink(1, "ofdm_receiver-found_corr_b.dat")) self.connect(self.sampler, blocks.file_sink(gr.sizeof_gr_complex*fft_length, "ofdm_receiver-sampler_c.dat")) self.connect(self.sigmix, blocks.file_sink(gr.sizeof_gr_complex, "ofdm_receiver-sigmix_c.dat")) self.connect(self.nco, blocks.file_sink(gr.sizeof_gr_complex, "ofdm_receiver-nco_c.dat"))
def __init__(self, fft_length, cp_length, occupied_tones, snr, ks, carrier_map_bin, nc_filter, logging=False): """ Hierarchical block for receiving OFDM symbols. The input is the complex modulated signal at baseband. Synchronized packets are sent back to the demodulator. @param fft_length: total number of subcarriers @type fft_length: int @param cp_length: length of cyclic prefix as specified in subcarriers (<= fft_length) @type cp_length: int @param occupied_tones: number of subcarriers used for data @type occupied_tones: int @param snr: estimated signal to noise ratio used to guide cyclic prefix synchronizer @type snr: float @param ks: known symbols used as preambles to each packet @type ks: list of lists @param logging: turn file logging on or off @type logging: bool """ gr.hier_block2.__init__(self, "ofdm_receiver", gr.io_signature(1, 1, gr.sizeof_gr_complex), # Input signature gr.io_signature2(2, 2, gr.sizeof_gr_complex*occupied_tones, gr.sizeof_char)) # Output signature bw = (float(occupied_tones) / float(fft_length)) / 2.0 tb = bw*0.04 print "ofdm_receiver:__init__:occupied_tones %s fft_length %d " % (occupied_tones, fft_length) chan_coeffs = filter.firdes.low_pass (1.0, # gain 1.0, # sampling rate bw+tb, # midpoint of trans. band tb, # width of trans. band filter.firdes.WIN_HAMMING) # filter type self.chan_filt = filter.fft_filter_ccc(1, chan_coeffs) # linklab, get ofdm parameters self._fft_length = fft_length self._occupied_tones = occupied_tones self._cp_length = cp_length self._nc_filter = nc_filter self._carrier_map_bin = carrier_map_bin win = [1 for i in range(fft_length)] # linklab, initialization function self.initialize(ks, self._carrier_map_bin) zeros_on_left = int(math.ceil((fft_length - occupied_tones)/2.0)) ks0 = fft_length*[0,] ks0[zeros_on_left : zeros_on_left + occupied_tones] = ks[0] ks0 = np_fft.ifftshift(ks0) ks0time = np_fft.ifft(ks0) # ADD SCALING FACTOR ks0time = ks0time.tolist() SYNC = "pn" if SYNC == "ml": nco_sensitivity = -1.0/fft_length # correct for fine frequency self.ofdm_sync = ofdm_sync_ml(fft_length, cp_length, snr, ks0time, logging) elif SYNC == "pn": nco_sensitivity = -2.0/fft_length # correct for fine frequency self.ofdm_sync = ofdm_sync_pn(fft_length, cp_length, logging) elif SYNC == "pnac": nco_sensitivity = -2.0/fft_length # correct for fine frequency self.ofdm_sync = ofdm_sync_pnac(fft_length, cp_length, ks0time, logging) # for testing only; do not user over the air # remove filter and filter delay for this elif SYNC == "fixed": self.chan_filt = gr.multiply_const_cc(1.0) nsymbols = 18 # enter the number of symbols per packet freq_offset = 0.0 # if you use a frequency offset, enter it here nco_sensitivity = -2.0/fft_length # correct for fine frequency self.ofdm_sync = ofdm_sync_fixed(fft_length, cp_length, nsymbols, freq_offset, logging) # Set up blocks # Create a delay line, linklab self.delay = blocks.delay(gr.sizeof_gr_complex, fft_length) self.nco = analog.frequency_modulator_fc(nco_sensitivity) # generate a signal proportional to frequency error of sync block self.sigmix = blocks.multiply_cc() self.sampler = gr_papyrus.ofdm_sampler(fft_length, fft_length+cp_length) self.fft_demod = gr_fft.fft_vcc(fft_length, True, win, True) self.ofdm_frame_acq = gr_papyrus.ofdm_frame_acquisition(occupied_tones, fft_length, cp_length, ks[0]) # linklab, check current mode: non-contiguous OFDM or not if self._nc_filter: print '\nMulti-band Filter Turned ON!' # linklab, non-contiguous filter self.ncofdm_filt = ncofdm_filt(self._fft_length, self._occupied_tones, self._carrier_map_bin) self.connect(self, self.chan_filt, self.ncofdm_filt) self.connect(self.ncofdm_filt, self.ofdm_sync) # into the synchronization alg. self.connect((self.ofdm_sync,0), self.nco, (self.sigmix,1)) # use sync freq. offset output to derotate input signal self.connect(self.ncofdm_filt, self.delay, (self.sigmix,0)) # signal to be derotated else : print '\nMulti-band Filter Turned OFF!' self.connect(self, self.chan_filt) self.connect(self.chan_filt, self.ofdm_sync) # into the synchronization alg. self.connect((self.ofdm_sync,0), self.nco, (self.sigmix,1)) # use sync freq. offset output to derotate input signal self.connect(self.chan_filt, self.delay, (self.sigmix,0)) # signal to be derotated self.connect(self.sigmix, (self.sampler,0)) # sample off timing signal detected in sync alg self.connect((self.ofdm_sync,1), (self.sampler,1)) # timing signal to sample at self.connect((self.sampler,0), self.fft_demod) # send derotated sampled signal to FFT self.connect(self.fft_demod, (self.ofdm_frame_acq,0)) # find frame start and equalize signal self.connect((self.sampler,1), (self.ofdm_frame_acq,1)) # send timing signal to signal frame start self.connect((self.ofdm_frame_acq,0), (self,0)) # finished with fine/coarse freq correction, self.connect((self.ofdm_frame_acq,1), (self,1)) # frame and symbol timing, and equalization if logging: self.connect(self.chan_filt, gr.file_sink(gr.sizeof_gr_complex, "ofdm_receiver-chan_filt_c.dat")) self.connect(self.fft_demod, gr.file_sink(gr.sizeof_gr_complex*fft_length, "ofdm_receiver-fft_out_c.dat")) self.connect(self.ofdm_frame_acq, gr.file_sink(gr.sizeof_gr_complex*occupied_tones, "ofdm_receiver-frame_acq_c.dat")) self.connect((self.ofdm_frame_acq,1), gr.file_sink(1, "ofdm_receiver-found_corr_b.dat")) self.connect(self.sampler, gr.file_sink(gr.sizeof_gr_complex*fft_length, "ofdm_receiver-sampler_c.dat")) self.connect(self.sigmix, gr.file_sink(gr.sizeof_gr_complex, "ofdm_receiver-sigmix_c.dat")) self.connect(self.nco, gr.file_sink(gr.sizeof_gr_complex, "ofdm_receiver-nco_c.dat"))
from gnuradio import gr from gnuradio import blocks as grblocks import sys if __name__ == '__main__': duration = float(sys.argv[1]) what = sys.argv[2] tb = gr.top_block() src0 = gr.null_source(8) src1 = gr.null_source(8) sink = gr.null_sink(8) if what == 'extras_add': math_op = grextras.Add.fc32_fc32() if what == 'blocks_add': math_op = grblocks.add_cc() if what == 'extras_mult': math_op = grextras.Multiply.fc32_fc32() if what == 'blocks_mult': math_op = grblocks.multiply_cc() tb.connect(src0, (math_op, 0)) tb.connect(src1, (math_op, 1)) tb.connect(math_op, sink) import time tb.start() time.sleep(duration) print '##RESULT##', sink.nitems_read(0)/duration import sys; sys.stdout.flush() tb.stop() tb.wait()
def multiply_cc(N): op = blocks.multiply_cc(1) tb = helper(N, op, gr.sizeof_gr_complex, gr.sizeof_gr_complex, 2, 1) return tb