def run_test(tb, channel, fft_rotate, fft_filter): N = 1000 # number of samples to use M = 5 # Number of channels fs = 5000.0 # baseband sampling rate ifs = M * fs # input samp rate to decimator taps = filter.firdes.low_pass_2(1, ifs, fs / 2, fs / 10, attenuation_dB=80, window=filter.firdes.WIN_BLACKMAN_hARRIS) signals = list() add = blocks.add_cc() freqs = [-230., 121., 110., -513., 203.] Mch = ((len(freqs) - 1) // 2 + channel) % len(freqs) for i in range(len(freqs)): f = freqs[i] + (M // 2 - M + i + 1) * fs data = sig_source_c(ifs, f, 1, N) signals.append(blocks.vector_source_c(data)) tb.connect(signals[i], (add, i)) s2ss = blocks.stream_to_streams(gr.sizeof_gr_complex, M) pfb = filter.pfb_decimator_ccf(M, taps, channel, fft_rotate, fft_filter) snk = blocks.vector_sink_c() tb.connect(add, s2ss) for i in range(M): tb.connect((s2ss, i), (pfb, i)) tb.connect(pfb, snk) tb.run() L = len(snk.data()) # Adjusted phase rotations for data phase = [ 0.11058476216852586, 4.5108246571401693, 3.9739891674564594, 2.2820531095511924, 1.3782797467397869 ] phase = phase[channel] # Filter delay is the normal delay of each arm tpf = math.ceil(len(taps) / float(M)) delay = -(tpf - 1.0) / 2.0 delay = int(delay) # Create a time scale that's delayed to match the filter delay t = [float(x) / fs for x in range(delay, L + delay)] # Create known data as complex sinusoids for the baseband freq # of the extracted channel is due to decimator output order. expected_data = [ math.cos(2. * math.pi * freqs[Mch] * x + phase) + 1j * math.sin(2. * math.pi * freqs[Mch] * x + phase) for x in t ] dst_data = snk.data() return (dst_data, expected_data)
def run_test(tb, channel, fft_rotate, fft_filter): N = 1000 # number of samples to use M = 5 # Number of channels fs = 5000.0 # baseband sampling rate ifs = M*fs # input samp rate to decimator taps = filter.firdes.low_pass_2(1, ifs, fs/2, fs/10, attenuation_dB=80, window=filter.firdes.WIN_BLACKMAN_hARRIS) signals = list() add = blocks.add_cc() freqs = [-230., 121., 110., -513., 203.] Mch = ((len(freqs)-1)/2 + channel) % len(freqs) for i in xrange(len(freqs)): f = freqs[i] + (M/2-M+i+1)*fs data = sig_source_c(ifs, f, 1, N) signals.append(blocks.vector_source_c(data)) tb.connect(signals[i], (add,i)) s2ss = blocks.stream_to_streams(gr.sizeof_gr_complex, M) pfb = filter.pfb_decimator_ccf(M, taps, channel, fft_rotate, fft_filter) snk = blocks.vector_sink_c() tb.connect(add, s2ss) for i in xrange(M): tb.connect((s2ss,i), (pfb,i)) tb.connect(pfb, snk) tb.run() L = len(snk.data()) # Adjusted phase rotations for data phase = [ 0.11058476216852586, 4.5108246571401693, 3.9739891674564594, 2.2820531095511924, 1.3782797467397869] phase = phase[channel] # Filter delay is the normal delay of each arm tpf = math.ceil(len(taps) / float(M)) delay = -(tpf - 1.0) / 2.0 delay = int(delay) # Create a time scale that's delayed to match the filter delay t = map(lambda x: float(x)/fs, xrange(delay, L+delay)) # Create known data as complex sinusoids for the baseband freq # of the extracted channel is due to decimator output order. expected_data = map(lambda x: math.cos(2.*math.pi*freqs[Mch]*x+phase) + \ 1j*math.sin(2.*math.pi*freqs[Mch]*x+phase), t) dst_data = snk.data() return (dst_data, expected_data)
def run_test(tb, channel): N = 1000 # number of samples to use M = 5 # Number of channels fs = 5000.0 # baseband sampling rate ifs = M * fs # input samp rate to decimator taps = filter.firdes.low_pass_2(1, ifs, fs / 2, fs / 10, attenuation_dB=80, window=filter.firdes.WIN_BLACKMAN_hARRIS) signals = list() add = blocks.add_cc() freqs = [-230., 121., 110., -513., 203.] Mch = ((len(freqs) - 1) / 2 + channel) % len(freqs) for i in xrange(len(freqs)): f = freqs[i] + (M / 2 - M + i + 1) * fs data = sig_source_c(ifs, f, 1, N) signals.append(blocks.vector_source_c(data)) tb.connect(signals[i], (add, i)) s2ss = blocks.stream_to_streams(gr.sizeof_gr_complex, M) pfb = filter.pfb_decimator_ccf(M, taps, channel) snk = blocks.vector_sink_c() tb.connect(add, s2ss) for i in xrange(M): tb.connect((s2ss, i), (pfb, i)) tb.connect(pfb, snk) tb.run() L = len(snk.data()) # Each channel is rotated by 2pi/M phase = -2 * math.pi * channel / M # Filter delay is the normal delay of each arm tpf = math.ceil(len(taps) / float(M)) delay = -(tpf - 1.0) / 2.0 delay = int(delay) # Create a time scale that's delayed to match the filter delay t = map(lambda x: float(x) / fs, xrange(delay, L + delay)) # Create known data as complex sinusoids for the baseband freq # of the extracted channel is due to decimator output order. expected_data = map(lambda x: math.cos(2.*math.pi*freqs[Mch]*x+phase) + \ 1j*math.sin(2.*math.pi*freqs[Mch]*x+phase), t) dst_data = snk.data() return (dst_data, expected_data)
def test_000(self): N = 1000 # number of samples to use M = 5 # Number of channels fs = 1000 # baseband sampling rate ifs = M*fs # input samp rate to decimator channel = 0 # Extract channel 0 taps = filter.firdes.low_pass_2(1, ifs, fs/2, fs/10, attenuation_dB=80, window=filter.firdes.WIN_BLACKMAN_hARRIS) signals = list() add = blocks.add_cc() freqs = [-200, -100, 0, 100, 200] for i in xrange(len(freqs)): f = freqs[i] + (M/2-M+i+1)*fs data = sig_source_c(ifs, f, 1, N) signals.append(blocks.vector_source_c(data)) self.tb.connect(signals[i], (add,i)) head = blocks.head(gr.sizeof_gr_complex, N) s2ss = blocks.stream_to_streams(gr.sizeof_gr_complex, M) pfb = filter.pfb_decimator_ccf(M, taps, channel) snk = blocks.vector_sink_c() self.tb.connect(add, head, s2ss) for i in xrange(M): self.tb.connect((s2ss,i), (pfb,i)) self.tb.connect(pfb, snk) self.tb.run() Ntest = 50 L = len(snk.data()) t = map(lambda x: float(x)/fs, xrange(L)) # Create known data as complex sinusoids for the baseband freq # of the extracted channel is due to decimator output order. phase = 0 expected_data = map(lambda x: math.cos(2.*math.pi*freqs[2]*x+phase) + \ 1j*math.sin(2.*math.pi*freqs[2]*x+phase), t) dst_data = snk.data() self.assertComplexTuplesAlmostEqual(expected_data[-Ntest:], dst_data[-Ntest:], 4)
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)) #sq5bpf: dodalem ppm self.src.set_freq_corr(8) 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 = filter.firdes.low_pass(1.0, sample_rate, options.low_pass, options.low_pass * 0.2, filter.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)) 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): x = x - self.ifreq sys.stderr.write("sq5bpf: x: %d \n" % x) 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._rxfreq_text_box.set_value(self.ifreq - self.offset) #sq5bpf self.scope = fftsink2.fft_sink_c( self.Main.GetPage(0).GetWin(), title="Wideband Spectrum (click to coarse tune)", baseband_freq=self.ifreq, #sq5bpf 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._rxfreq_text_box.set_value(self.ifreq - self.offset) #sq5bpf 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) #sq5bpf self._rxfreq_text_box = forms.text_box( parent=self.GetWin(), value=self.ifreq - self.offset, label="RX Freq", converter=forms.float_converter(), ) self.Add(self._rxfreq_text_box)
self.connect((self,1), (ftc,1)) self.connect(ftc,mag,(self,0)) self.connect(ftc,arg,(self,1)) tb = gr.top_block() source= adc_signal(samp_rate) #Ddc mixer mixer = ddc_mixer(samp_rate, 20e6) #Decimation filter. Both must have the same taps, so, calculate it once taps = filter.firdes.low_pass_2(1, samp_rate, 5e3, 3e3, 60, filter.firdes.WIN_BLACKMAN_HARRIS) filter_I = filter.pfb_decimator_ccf(int(1e3), taps, 0) filter_Q = filter.pfb_decimator_ccf(int(1e3), taps, 0) #now, calculate Magnitude and Argument cordic = float_cordic() #output the result sink = blocks.vector_sink_f() tb.connect(source, head) tb.connect(head, mixer) tb.connect((mixer,0), filter_I) tb.connect((mixer,1), filter_Q) tb.connect(filter_I, (cordic,0))