def _update_filtered(self, translated): if translated is not None and self._taps is not None: filtered = TimeData(numpy.complex64(scipy.signal.lfilter(self._taps, 1, translated.samples)), translated.sampling_rate) filtered_abs = filtered.abs data_source = filtered_abs.samples numpy_source = NumpySource(data_source) peak_detector = blocks.peak_detector_fb(1.0, 0.3, 10, 0.001) sample_and_hold = blocks.sample_and_hold_ff() multiply_const = blocks.multiply_const_vff((0.5, )) subtract = blocks.sub_ff(1) numpy_sink = NumpySink(numpy.float32) top = gr.top_block() top.connect((numpy_source, 0), (peak_detector, 0)) top.connect((numpy_source, 0), (sample_and_hold, 0)) top.connect((numpy_source, 0), (subtract, 0)) top.connect((peak_detector, 0), (sample_and_hold, 1)) top.connect((sample_and_hold, 0), (multiply_const, 0)) top.connect((multiply_const, 0), (subtract, 1)) top.connect((subtract, 0), (numpy_sink, 0)) top.run() filtered = TimeData(numpy_sink.data, translated.sampling_rate) self.filtered_view.data = filtered # abs_min = filtered.abs.min # abs_max = filtered.abs.max # abs_mid = (abs_min + abs_max) / 2.0 # self.burst.filtered = filtered.abs - abs_mid self.burst.filtered = filtered else: self.filtered_view.data = None self.burst.filtered = None
def __init__(self, ts=(0+0j,), factor=0, alpha=0.01): gr.hier_block2.__init__( self, "timing_estimator_hier", gr.io_signature(1, 1, gr.sizeof_gr_complex*1), gr.io_signature(1, 1, gr.sizeof_char*1), ) ################################################## # Parameters ################################################## self.ts = ts self.factor = factor self.alpha = alpha ################################################## # Blocks ################################################## self.interp_fir_filter_xxx_0 = filter.interp_fir_filter_ccc(1, (numpy.conjugate(ts[::-1]))) self.blocks_peak_detector_xb_0_0 = blocks.peak_detector_fb(factor, factor, 0, alpha) self.blocks_complex_to_mag_squared_0 = blocks.complex_to_mag_squared(1) ################################################## # Connections ################################################## self.connect((self.blocks_complex_to_mag_squared_0, 0), (self.blocks_peak_detector_xb_0_0, 0)) self.connect((self.interp_fir_filter_xxx_0, 0), (self.blocks_complex_to_mag_squared_0, 0)) self.connect((self.blocks_peak_detector_xb_0_0, 0), (self, 0)) self.connect((self, 0), (self.interp_fir_filter_xxx_0, 0))
def __init__(self, length, debug=False): """ Hierarchical block to detect Null symbols @param length length of the Null symbol (in samples) @param debug whether to write signals out to files """ gr.hier_block2.__init__(self,"detect_null", gr.io_signature(1, 1, gr.sizeof_gr_complex), # input signature gr.io_signature(1, 1, gr.sizeof_char)) # output signature # get the magnitude squared self.ns_c2magsquared = blocks.complex_to_mag_squared() # this wastes cpu cycles: # ns_detect_taps = [1]*length # self.ns_moving_sum = gr.fir_filter_fff(1,ns_detect_taps) # this isn't better: #self.ns_filter = gr.iir_filter_ffd([1]+[0]*(length-1)+[-1],[0,1]) # this does the same again, but is actually faster (outsourced to an independent block ..): self.ns_moving_sum = dab_swig.moving_sum_ff(length) self.ns_invert = blocks.multiply_const_ff(-1) # peak detector on the inverted, summed up signal -> we get the nulls (i.e. the position of the start of a frame) self.ns_peak_detect = blocks.peak_detector_fb(0.6,0.7,10,0.0001) # mostly found by try and error -> remember that the values are negative! # connect it all self.connect(self, self.ns_c2magsquared, self.ns_moving_sum, self.ns_invert, self.ns_peak_detect, self) if debug: self.connect(self.ns_invert, blocks.file_sink(gr.sizeof_float, "debug/ofdm_sync_dab_ns_filter_inv_f.dat")) self.connect(self.ns_peak_detect,blocks.file_sink(gr.sizeof_char, "debug/ofdm_sync_dab_peak_detect_b.dat"))
def __init__(self, ts, factor, alpha, samp_rate, freqs): gr.hier_block2.__init__( self, "freq_timing_estimator_hier", gr.io_signature(1, 1, gr.sizeof_gr_complex*1), gr.io_signaturev(3, 3, [gr.sizeof_char*1, gr.sizeof_float*1, gr.sizeof_float*1]), ) ################################################## # Parameters ################################################## self.ts = ts self.factor = factor self.alpha = alpha self.samp_rate = samp_rate self.freqs = freqs self.n = n = len(freqs) ################################################## # Blocks ################################################## self._filter=[0]*self.n self._c2mag2=[0]*self.n for i in range(self.n): self._filter[i]= filter.freq_xlating_fir_filter_ccc(1, (numpy.conjugate(self.ts[::-1])), self.freqs[i], self.samp_rate) self._c2mag2[i] = blocks.complex_to_mag_squared(1) self.blocks_max = blocks.max_ff(1) self.blocks_peak_detector = blocks.peak_detector_fb(self.factor, self.factor, 0, self.alpha) self.blocks_argmax = blocks.argmax_fs(1) self.blocks_null_sink = blocks.null_sink(gr.sizeof_short*1) self.digital_chunks_to_symbols = digital.chunks_to_symbols_sf((freqs), 1) self.blocks_sample_and_hold = blocks.sample_and_hold_ff() ################################################## # Connections ################################################## for i in range(self.n): self.connect((self, 0), (self._filter[i], 0)) self.connect((self._filter[i], 0), (self._c2mag2[i], 0)) self.connect((self._c2mag2[i], 0), (self.blocks_max, i)) self.connect((self._c2mag2[i], 0), (self.blocks_argmax, i)) self.connect((self.blocks_max, 0), (self.blocks_peak_detector, 0)) self.connect((self.blocks_peak_detector, 0), (self, 0)) self.connect((self.blocks_argmax, 0), (self.blocks_null_sink, 0)) self.connect((self.blocks_argmax, 1), (self.digital_chunks_to_symbols, 0)) self.connect((self.digital_chunks_to_symbols, 0), (self.blocks_sample_and_hold, 0)) self.connect((self.blocks_peak_detector, 0), (self.blocks_sample_and_hold, 1)) self.connect((self.blocks_sample_and_hold, 0), (self, 1)) self.connect((self.blocks_max, 0), (self, 2))
def __init__(self, length, debug=False): """ Hierarchical block to detect Null symbols @param length length of the Null symbol (in samples) @param debug whether to write signals out to files """ gr.hier_block2.__init__( self, "detect_null", gr.io_signature(1, 1, gr.sizeof_gr_complex), # input signature gr.io_signature(1, 1, gr.sizeof_char)) # output signature # get the magnitude squared self.ns_c2magsquared = blocks.complex_to_mag_squared() # this wastes cpu cycles: # ns_detect_taps = [1]*length # self.ns_moving_sum = gr.fir_filter_fff(1,ns_detect_taps) # this isn't better: #self.ns_filter = gr.iir_filter_ffd([1]+[0]*(length-1)+[-1],[0,1]) # this does the same again, but is actually faster (outsourced to an independent block ..): self.ns_moving_sum = dab.moving_sum_ff(length) self.ns_invert = blocks.multiply_const_ff(-1) # peak detector on the inverted, summed up signal -> we get the nulls (i.e. the position of the start of a frame) self.ns_peak_detect = blocks.peak_detector_fb( 0.6, 0.7, 10, 0.0001 ) # mostly found by try and error -> remember that the values are negative! # connect it all self.connect(self, self.ns_c2magsquared, self.ns_moving_sum, self.ns_invert, self.ns_peak_detect, self) if debug: self.connect( self.ns_invert, blocks.file_sink(gr.sizeof_float, "debug/ofdm_sync_dab_ns_filter_inv_f.dat")) self.connect( self.ns_peak_detect, blocks.file_sink(gr.sizeof_char, "debug/ofdm_sync_dab_peak_detect_b.dat"))
def test_01(self): tb = self.tb data = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0] expected_result = (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) src = blocks.vector_source_f(data, False) regen = blocks.peak_detector_fb() dst = blocks.vector_sink_b() tb.connect(src, regen) tb.connect(regen, dst) tb.run() dst_data = dst.data() self.assertEqual(expected_result, dst_data)
def __init__(self, fft_length, cp_length, logging=False): """ OFDM synchronization using PN Correlation: T. M. Schmidl and D. C. Cox, "Robust Frequency and Timing Synchronization for OFDM," IEEE Trans. Communications, vol. 45, no. 12, 1997. """ gr.hier_block2.__init__(self, "ofdm_sync_pn", gr.io_signature(1, 1, gr.sizeof_gr_complex), # Input signature gr.io_signature2(2, 2, gr.sizeof_float, gr.sizeof_char)) # Output signature self.input = blocks.add_const_cc(0) # PN Sync # Create a delay line self.delay = blocks.delay(gr.sizeof_gr_complex, fft_length/2) # Correlation from ML Sync self.conjg = blocks.conjugate_cc(); self.corr = blocks.multiply_cc(); # Create a moving sum filter for the corr output self.moving_sum_filter = filter.fir_filter_ccf(1, [1.0] * (fft_length//2)) # Create a moving sum filter for the input self.inputmag2 = blocks.complex_to_mag_squared() self.inputmovingsum = filter.fir_filter_fff(1, [1.0] * (fft_length//2)) self.square = blocks.multiply_ff() self.normalize = blocks.divide_ff() # Get magnitude (peaks) and angle (phase/freq error) self.c2mag = blocks.complex_to_mag_squared() self.angle = blocks.complex_to_arg() self.sample_and_hold = blocks.sample_and_hold_ff() #ML measurements input to sampler block and detect self.sub1 = blocks.add_const_ff(-1) self.pk_detect = blocks.peak_detector_fb(0.20, 0.20, 30, 0.001) self.connect(self, self.input) # Calculate the frequency offset from the correlation of the preamble self.connect(self.input, self.delay) self.connect(self.input, (self.corr,0)) self.connect(self.delay, self.conjg) self.connect(self.conjg, (self.corr,1)) self.connect(self.corr, self.moving_sum_filter) self.connect(self.moving_sum_filter, self.c2mag) self.connect(self.moving_sum_filter, self.angle) self.connect(self.angle, (self.sample_and_hold,0)) # Get the power of the input signal to normalize the output of the correlation self.connect(self.input, self.inputmag2, self.inputmovingsum) self.connect(self.inputmovingsum, (self.square,0)) self.connect(self.inputmovingsum, (self.square,1)) self.connect(self.square, (self.normalize,1)) self.connect(self.c2mag, (self.normalize,0)) # Create a moving sum filter for the corr output matched_filter_taps = [1.0/cp_length for i in range(cp_length)] self.matched_filter = filter.fir_filter_fff(1,matched_filter_taps) self.connect(self.normalize, self.matched_filter) self.connect(self.matched_filter, self.sub1, self.pk_detect) #self.connect(self.matched_filter, self.pk_detect) self.connect(self.pk_detect, (self.sample_and_hold,1)) # Set output signals # Output 0: fine frequency correction value # Output 1: timing signal self.connect(self.sample_and_hold, (self,0)) self.connect(self.pk_detect, (self,1)) if logging: self.connect(self.matched_filter, blocks.file_sink(gr.sizeof_float, "ofdm_sync_pn-mf_f.dat")) self.connect(self.normalize, blocks.file_sink(gr.sizeof_float, "ofdm_sync_pn-theta_f.dat")) self.connect(self.angle, blocks.file_sink(gr.sizeof_float, "ofdm_sync_pn-epsilon_f.dat")) self.connect(self.pk_detect, blocks.file_sink(gr.sizeof_char, "ofdm_sync_pn-peaks_b.dat")) self.connect(self.sample_and_hold, blocks.file_sink(gr.sizeof_float, "ofdm_sync_pn-sample_and_hold_f.dat")) self.connect(self.input, blocks.file_sink(gr.sizeof_gr_complex, "ofdm_sync_pn-input_c.dat"))
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, kstime, overrate, logging=True): """ OFDM synchronization using PN Correlation: T. M. Schmidl and D. C. Cox, "Robust Frequency and Timing Synchonization for OFDM," IEEE Trans. Communications, vol. 45, no. 12, 1997. """ gr.hier_block2.__init__( self, "ofdm_sync_pn", gr.io_signature(1, 1, gr.sizeof_gr_complex), # Input signature gr.io_signature2(2, 2, gr.sizeof_float, gr.sizeof_char)) # Output signature self.input = blocks.add_const_cc(0) # cross-correlate with the known symbol kstime = [k.conjugate() for k in kstime] kstime.reverse() self.crosscorr_filter = filter.fir_filter_ccc(1, kstime) # PN Sync self.corrmag = blocks.complex_to_mag_squared() self.delay = blocks.delay(gr.sizeof_gr_complex, fft_length * overrate / 2) # Correlation from ML Sync self.conjg = blocks.conjugate_cc() self.corr = blocks.multiply_cc() #self.sub = blocks.add_const_ff(-1) self.pk_detect = blocks.peak_detector_fb(0.40, 0.25, fft_length * overrate, 0.00000000000) self.connect(self, self.input) self.connect(self.input, self.crosscorr_filter) self.connect(self.crosscorr_filter, self.corrmag) #self.inputmag = blocks.complex_to_mag_squared() #self.normalize = blocks.divide_ff() #self.inputmovingsum = filter.fir_filter_fff(1, [1.0] * (fft_length//2)) self.square = blocks.multiply_ff() #self.connect(self.input,self.inputmag,self.inputmovingsum) self.connect(self.corrmag, (self.square, 0)) self.connect(self.corrmag, (self.square, 1)) self.dsquare = blocks.multiply_ff() self.connect(self.square, (self.dsquare, 0)) self.connect(self.square, (self.dsquare, 1)) self.connect(self.dsquare, self.pk_detect) # Create a moving sum filter for the corr output self.moving_sum_filter = filter.fir_filter_ccf( 1, [1.0] * (fft_length * overrate // 2)) # Get magnitude (peaks) and angle (phase/freq error) self.angle = blocks.complex_to_arg() self.sample_and_hold = blocks.sample_and_hold_ff() # Calculate the frequency offset from the correlation of the preamble self.connect(self.input, self.delay) self.connect(self.input, (self.corr, 0)) self.connect(self.delay, self.conjg) self.connect(self.conjg, (self.corr, 1)) self.connect(self.corr, self.moving_sum_filter) self.connect(self.moving_sum_filter, self.angle) self.connect(self.angle, (self.sample_and_hold, 0)) self.connect(self.pk_detect, (self.sample_and_hold, 1)) # Set output signals # Output 0: fine frequency correction value # Output 1: timing signal self.connect(self.sample_and_hold, (self, 0)) self.connect(self.pk_detect, (self, 1)) if logging: self.connect( self.dsquare, blocks.file_sink(gr.sizeof_float, "ofdm_sync_pn-dsquare.dat")) self.connect( self.corrmag, blocks.file_sink(gr.sizeof_float, "ofdm_sync_pn-corrmag.dat")) self.connect( self.angle, blocks.file_sink(gr.sizeof_float, "ofdm_sync_pn-epsilon_f.dat")) self.connect( self.pk_detect, blocks.file_sink(gr.sizeof_char, "ofdm_sync_pn-peaks_b.dat")) self.connect( self.sample_and_hold, blocks.file_sink(gr.sizeof_float, "ofdm_sync_pn-sample_and_hold_f.dat")) self.connect( self.input, blocks.file_sink(gr.sizeof_gr_complex, "ofdm_sync_pn-input_c.dat"))
def __init__(self, seq1, seq2, factor, alpha, freqs): """ Description: frequency timing estimator class does frequency/timing acquisition from scratch.It uses a bank of parallel correlators at each specified frequency. It then takes the max abs value of all these and passes it through a peak detector to find timing. Args: seq1: sequence1 of kronecker filter, which is the given training sequence. seq2: sequence2 of kronecker filter, which is the pulse for each training symbol. factor: the rise and fall factors in peak detector, which is the factor determining when a peak has started and ended. In the peak detector, an average of the signal is calculated. When the value of the signal goes over factor*average, we start looking for a peak. When the value of the signal goes below factor*average, we stop looking for a peak. alpha: the smoothing factor of a moving average filter used in the peak detector taking values in (0,1). freqs: the vector of normalized center frequencies for each matched filter. Note that for a training sequence of length Nt, each matched filter can recover a sequence with normalized frequency offset ~ 1/(2Nt). """ gr.hier_block2.__init__(self, "freq_timing_estimator", gr.io_signature(1, 1, gr.sizeof_gr_complex*1), gr.io_signaturev(3, 3, [gr.sizeof_char*1, gr.sizeof_float*1, gr.sizeof_float*1]), ) ################################################## # Parameters ################################################## self.seq1 = seq1 self.seq2 = seq2 self.factor = factor self.alpha = alpha self.freqs = freqs self.n = n = len(freqs) ################################################## # Blocks ################################################## self._filter=[0]*self.n self._c2mag2=[0]*self.n for i in range(self.n): self._filter[i]= cdma.kronecker_filter(seq1,seq2,1,self.freqs[i]) #self._filter[i]= filter.freq_xlating_fir_filter_ccc(1, numpy.kron(seq1,seq2), self.freqs[i], 1) self._c2mag2[i] = blocks.complex_to_mag_squared(1) self.blocks_max = blocks.max_ff(1) self.blocks_peak_detector = blocks.peak_detector_fb(self.factor, self.factor, 0, self.alpha) self.blocks_argmax = blocks.argmax_fs(1) self.blocks_null_sink = blocks.null_sink(gr.sizeof_short*1) self.digital_chunks_to_symbols = digital.chunks_to_symbols_sf((freqs), 1) self.blocks_sample_and_hold = blocks.sample_and_hold_ff() ################################################## # Connections ################################################## for i in range(self.n): self.connect((self, 0), (self._filter[i], 0)) self.connect((self._filter[i], 0), (self._c2mag2[i], 0)) self.connect((self._c2mag2[i], 0), (self.blocks_max, i)) self.connect((self._c2mag2[i], 0), (self.blocks_argmax, i)) self.connect((self.blocks_max, 0), (self.blocks_peak_detector, 0)) self.connect((self.blocks_peak_detector, 0), (self, 0)) self.connect((self.blocks_argmax, 0), (self.blocks_null_sink, 0)) self.connect((self.blocks_argmax, 1), (self.digital_chunks_to_symbols, 0)) self.connect((self.digital_chunks_to_symbols, 0), (self.blocks_sample_and_hold, 0)) self.connect((self.blocks_peak_detector, 0), (self.blocks_sample_and_hold, 1)) self.connect((self.blocks_sample_and_hold, 0), (self, 1)) self.connect((self.blocks_max, 0), (self, 2))
def __init__(self, fft_length, cp_length, logging=False): """ OFDM synchronization using PN Correlation: T. M. Schmidl and D. C. Cox, "Robust Frequency and Timing Synchronization for OFDM," IEEE Trans. Communications, vol. 45, no. 12, 1997. """ gr.hier_block2.__init__( self, "ofdm_sync_pn", gr.io_signature(1, 1, gr.sizeof_gr_complex), # Input signature gr.io_signature2(2, 2, gr.sizeof_float, gr.sizeof_char)) # Output signature self.input = blocks.add_const_cc(0) # PN Sync # Create a delay line self.delay = blocks.delay(gr.sizeof_gr_complex, fft_length / 2) # Correlation from ML Sync self.conjg = blocks.conjugate_cc() self.corr = blocks.multiply_cc() # Create a moving sum filter for the corr output self.moving_sum_filter = filter.fir_filter_ccf(1, [1.0] * (fft_length // 2)) # Create a moving sum filter for the input self.inputmag2 = blocks.complex_to_mag_squared() self.inputmovingsum = filter.fir_filter_fff(1, [1.0] * (fft_length // 2)) self.square = blocks.multiply_ff() self.normalize = blocks.divide_ff() # Get magnitude (peaks) and angle (phase/freq error) self.c2mag = blocks.complex_to_mag_squared() self.angle = blocks.complex_to_arg() self.sample_and_hold = blocks.sample_and_hold_ff() #ML measurements input to sampler block and detect self.sub1 = blocks.add_const_ff(-1) self.pk_detect = blocks.peak_detector_fb(0.20, 0.20, 30, 0.001) self.connect(self, self.input) # Calculate the frequency offset from the correlation of the preamble self.connect(self.input, self.delay) self.connect(self.input, (self.corr, 0)) self.connect(self.delay, self.conjg) self.connect(self.conjg, (self.corr, 1)) self.connect(self.corr, self.moving_sum_filter) self.connect(self.moving_sum_filter, self.c2mag) self.connect(self.moving_sum_filter, self.angle) self.connect(self.angle, (self.sample_and_hold, 0)) # Get the power of the input signal to normalize the output of the correlation self.connect(self.input, self.inputmag2, self.inputmovingsum) self.connect(self.inputmovingsum, (self.square, 0)) self.connect(self.inputmovingsum, (self.square, 1)) self.connect(self.square, (self.normalize, 1)) self.connect(self.c2mag, (self.normalize, 0)) # Create a moving sum filter for the corr output matched_filter_taps = [1.0 / cp_length for i in range(cp_length)] self.matched_filter = filter.fir_filter_fff(1, matched_filter_taps) self.connect(self.normalize, self.matched_filter) self.connect(self.matched_filter, self.sub1, self.pk_detect) #self.connect(self.matched_filter, self.pk_detect) self.connect(self.pk_detect, (self.sample_and_hold, 1)) # Set output signals # Output 0: fine frequency correction value # Output 1: timing signal self.connect(self.sample_and_hold, (self, 0)) self.connect(self.pk_detect, (self, 1)) if logging: self.connect( self.matched_filter, blocks.file_sink(gr.sizeof_float, "ofdm_sync_pn-mf_f.dat")) self.connect( self.normalize, blocks.file_sink(gr.sizeof_float, "ofdm_sync_pn-theta_f.dat")) self.connect( self.angle, blocks.file_sink(gr.sizeof_float, "ofdm_sync_pn-epsilon_f.dat")) self.connect( self.pk_detect, blocks.file_sink(gr.sizeof_char, "ofdm_sync_pn-peaks_b.dat")) self.connect( self.sample_and_hold, blocks.file_sink(gr.sizeof_float, "ofdm_sync_pn-sample_and_hold_f.dat")) self.connect( self.input, blocks.file_sink(gr.sizeof_gr_complex, "ofdm_sync_pn-input_c.dat"))
def __init__(self, ts, factor, alpha, samp_rate, freqs): """ Description: This block is designed to perform frequency and timing acquisition for a known training sequence in the presense of frequency and timing offset and noise. Its input is a complex stream. It has three outputs: 1) a stream of flags (bytes) indicating the begining of the training sequence (to be used from subsequent blocks to "chop" the incoming stream, 2) a stream with the current acquired frequency offset, and 3) a stream with the current acquired peak of the matched filter Internally, it consists of a user defined number of parallel matched filters (as many as the size of the freqs vector), each consistng of a frequency Xlating FIR filter with sample rate samp_rate, filter taps matched to the training sequence ts, and center frequency freqs[i]. The filter outputs are magnitude squared and passed through a max block and then through a peak detector. Args: ts: the training sequence. For example, in DSSS system, it's the chip-based spread training sequence. factor: the rise and fall factors in peak detector, which is the factor determining when a peak has started and ended. In the peak detector, an average of the signal is calculated. When the value of the signal goes over factor*average, we start looking for a peak. When the value of the signal goes below factor*average, we stop looking for a peak. factor takes values in (0,1). alpha: the smoothing factor of a moving average filter used in the peak detector takeng values in (0,1). samp_rate: the sample rate of the system, which is used in the freq_xlating_fir_filter. freqs: the vector of center frequencies for each matched filter. Note that for a training sequence of length Nt, each matched filter can recover a sequence with normalized frequency offset ~ 1/(2Nt). """ gr.hier_block2.__init__( self, "freq_timing_estimator", gr.io_signature(1, 1, gr.sizeof_gr_complex*1), gr.io_signaturev(3, 3, [gr.sizeof_char*1, gr.sizeof_float*1, gr.sizeof_float*1]), ) ################################################## # Parameters ################################################## self.ts = ts self.factor = factor self.alpha = alpha self.samp_rate = samp_rate self.freqs = freqs self.n = n = len(freqs) ################################################## # Blocks ################################################## self._filter=[0]*self.n self._c2mag2=[0]*self.n for i in range(self.n): self._filter[i]= filter.freq_xlating_fir_filter_ccc(1, (numpy.conjugate(self.ts[::-1])), self.freqs[i], self.samp_rate) self._c2mag2[i] = blocks.complex_to_mag_squared(1) self.blocks_max = blocks.max_ff(1) self.blocks_peak_detector = blocks.peak_detector_fb(self.factor, self.factor, 0, self.alpha) self.blocks_argmax = blocks.argmax_fs(1) self.blocks_null_sink = blocks.null_sink(gr.sizeof_short*1) self.digital_chunks_to_symbols = digital.chunks_to_symbols_sf((freqs), 1) self.blocks_sample_and_hold = blocks.sample_and_hold_ff() ################################################## # Connections ################################################## for i in range(self.n): self.connect((self, 0), (self._filter[i], 0)) self.connect((self._filter[i], 0), (self._c2mag2[i], 0)) self.connect((self._c2mag2[i], 0), (self.blocks_max, i)) self.connect((self._c2mag2[i], 0), (self.blocks_argmax, i)) self.connect((self.blocks_max, 0), (self.blocks_peak_detector, 0)) self.connect((self.blocks_peak_detector, 0), (self, 0)) self.connect((self.blocks_argmax, 0), (self.blocks_null_sink, 0)) self.connect((self.blocks_argmax, 1), (self.digital_chunks_to_symbols, 0)) self.connect((self.digital_chunks_to_symbols, 0), (self.blocks_sample_and_hold, 0)) self.connect((self.blocks_peak_detector, 0), (self.blocks_sample_and_hold, 1)) self.connect((self.blocks_sample_and_hold, 0), (self, 1)) self.connect((self.blocks_max, 0), (self, 2))
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, seq1, seq2, factor, alpha, samp_rate, freqs): """ Description: This block is functionally equivalent to the frequency_timing_estimator block, except from the fact that each filter is matched to a sequence that can be written as the kronecker product of seq1 and seq2. Args: seq1: sequence1 of kronecker filter, which is the given training sequence. seq2: sequence2 of kronecker filter, which is the pulse for each training symbol. factor: the rise and fall factors in peak detector, which is the factor determining when a peak has started and ended. In the peak detector, an average of the signal is calculated. When the value of the signal goes over factor*average, we start looking for a peak. When the value of the signal goes below factor*average, we stop looking for a peak. factor takes values in (0,1). alpha: the smoothing factor of a moving average filter used in the peak detector takeng values in (0,1). samp_rate: the sample rate of the system, which is used in the kronecker_filter. freqs: the vector of center frequencies for each matched filter. Note that for a training sequence of length Nt, each matched filter can recover a sequence with normalized frequency offset ~ 1/(2Nt). """ gr.hier_block2.__init__(self, "freq_timing_estimator", gr.io_signature(1, 1, gr.sizeof_gr_complex*1), gr.io_signaturev(3, 3, [gr.sizeof_char*1, gr.sizeof_float*1, gr.sizeof_float*1]), ) ################################################## # Parameters ################################################## self.seq1 = seq1 self.seq2 = seq2 self.factor = factor self.alpha = alpha self.samp_rate = samp_rate self.freqs = freqs self.n = n = len(freqs) ################################################## # Blocks ################################################## self._filter=[0]*self.n self._c2mag2=[0]*self.n for i in range(self.n): self._filter[i]= cdma.kronecker_filter(seq1,seq2,samp_rate,self.freqs[i]) #self._filter[i]= filter.freq_xlating_fir_filter_ccc(1, (numpy.conjugate(self.ts[::-1])), self.freqs[i], self.samp_rate) self._c2mag2[i] = blocks.complex_to_mag_squared(1) self.blocks_max = blocks.max_ff(1) self.blocks_peak_detector = blocks.peak_detector_fb(self.factor, self.factor, 0, self.alpha) self.blocks_argmax = blocks.argmax_fs(1) self.blocks_null_sink = blocks.null_sink(gr.sizeof_short*1) self.digital_chunks_to_symbols = digital.chunks_to_symbols_sf((freqs), 1) self.blocks_sample_and_hold = blocks.sample_and_hold_ff() ################################################## # Connections ################################################## for i in range(self.n): self.connect((self, 0), (self._filter[i], 0)) self.connect((self._filter[i], 0), (self._c2mag2[i], 0)) self.connect((self._c2mag2[i], 0), (self.blocks_max, i)) self.connect((self._c2mag2[i], 0), (self.blocks_argmax, i)) self.connect((self.blocks_max, 0), (self.blocks_peak_detector, 0)) self.connect((self.blocks_peak_detector, 0), (self, 0)) self.connect((self.blocks_argmax, 0), (self.blocks_null_sink, 0)) self.connect((self.blocks_argmax, 1), (self.digital_chunks_to_symbols, 0)) self.connect((self.digital_chunks_to_symbols, 0), (self.blocks_sample_and_hold, 0)) self.connect((self.blocks_peak_detector, 0), (self.blocks_sample_and_hold, 1)) self.connect((self.blocks_sample_and_hold, 0), (self, 1)) self.connect((self.blocks_max, 0), (self, 2))
def __init__(self): gr.top_block.__init__(self, "Not titled yet") Qt.QWidget.__init__(self) self.setWindowTitle("Not titled yet") qtgui.util.check_set_qss() try: self.setWindowIcon(Qt.QIcon.fromTheme('gnuradio-grc')) except: pass self.top_scroll_layout = Qt.QVBoxLayout() self.setLayout(self.top_scroll_layout) self.top_scroll = Qt.QScrollArea() self.top_scroll.setFrameStyle(Qt.QFrame.NoFrame) self.top_scroll_layout.addWidget(self.top_scroll) self.top_scroll.setWidgetResizable(True) self.top_widget = Qt.QWidget() self.top_scroll.setWidget(self.top_widget) self.top_layout = Qt.QVBoxLayout(self.top_widget) self.top_grid_layout = Qt.QGridLayout() self.top_layout.addLayout(self.top_grid_layout) self.settings = Qt.QSettings("GNU Radio", "arduino") try: if StrictVersion(Qt.qVersion()) < StrictVersion("5.0.0"): self.restoreGeometry( self.settings.value("geometry").toByteArray()) else: self.restoreGeometry(self.settings.value("geometry")) except: pass ################################################## # Variables ################################################## self.samp_rate = samp_rate = 2.048e6 self.decimation = decimation = 64 self.clock_freq = clock_freq = 1e3 self.center_freq = center_freq = 434e6 ################################################## # Blocks ################################################## self.rtlsdr_source_0 = osmosdr.source(args="numchan=" + str(1) + " " + "") self.rtlsdr_source_0.set_time_unknown_pps(osmosdr.time_spec_t()) self.rtlsdr_source_0.set_sample_rate(samp_rate) self.rtlsdr_source_0.set_center_freq(center_freq, 0) self.rtlsdr_source_0.set_freq_corr(0, 0) self.rtlsdr_source_0.set_gain(0, 0) self.rtlsdr_source_0.set_if_gain(20, 0) self.rtlsdr_source_0.set_bb_gain(20, 0) self.rtlsdr_source_0.set_antenna('', 0) self.rtlsdr_source_0.set_bandwidth(0, 0) self.qtgui_time_sink_x_1_0 = qtgui.time_sink_f( 1024, #size samp_rate / decimation, #samp_rate 'Digital', #name 2 #number of inputs ) self.qtgui_time_sink_x_1_0.set_update_time(0.10) self.qtgui_time_sink_x_1_0.set_y_axis(-1, 1) self.qtgui_time_sink_x_1_0.set_y_label('Amplitude', "") self.qtgui_time_sink_x_1_0.enable_tags(True) self.qtgui_time_sink_x_1_0.set_trigger_mode(qtgui.TRIG_MODE_AUTO, qtgui.TRIG_SLOPE_POS, 0.0, -10e-3, 0, "") self.qtgui_time_sink_x_1_0.enable_autoscale(False) self.qtgui_time_sink_x_1_0.enable_grid(False) self.qtgui_time_sink_x_1_0.enable_axis_labels(True) self.qtgui_time_sink_x_1_0.enable_control_panel(False) self.qtgui_time_sink_x_1_0.enable_stem_plot(False) labels = [ 'Signal 1', 'Signal 2', 'Signal 3', 'Signal 4', 'Signal 5', 'Signal 6', 'Signal 7', 'Signal 8', 'Signal 9', 'Signal 10' ] widths = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1] colors = [ 'blue', 'red', 'green', 'black', 'cyan', 'magenta', 'yellow', 'dark red', 'dark green', 'dark blue' ] alphas = [1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0] styles = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1] markers = [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1] for i in range(2): if len(labels[i]) == 0: self.qtgui_time_sink_x_1_0.set_line_label( i, "Data {0}".format(i)) else: self.qtgui_time_sink_x_1_0.set_line_label(i, labels[i]) self.qtgui_time_sink_x_1_0.set_line_width(i, widths[i]) self.qtgui_time_sink_x_1_0.set_line_color(i, colors[i]) self.qtgui_time_sink_x_1_0.set_line_style(i, styles[i]) self.qtgui_time_sink_x_1_0.set_line_marker(i, markers[i]) self.qtgui_time_sink_x_1_0.set_line_alpha(i, alphas[i]) self._qtgui_time_sink_x_1_0_win = sip.wrapinstance( self.qtgui_time_sink_x_1_0.pyqwidget(), Qt.QWidget) self.top_grid_layout.addWidget(self._qtgui_time_sink_x_1_0_win) self.qtgui_time_sink_x_0 = qtgui.time_sink_f( 1024, #size samp_rate, #samp_rate "", #name 1 #number of inputs ) self.qtgui_time_sink_x_0.set_update_time(0.10) self.qtgui_time_sink_x_0.set_y_axis(-1, 1) self.qtgui_time_sink_x_0.set_y_label('Amplitude', "") self.qtgui_time_sink_x_0.enable_tags(True) self.qtgui_time_sink_x_0.set_trigger_mode(qtgui.TRIG_MODE_TAG, qtgui.TRIG_SLOPE_POS, 0.0, -1e-3, 0, 'burst') self.qtgui_time_sink_x_0.enable_autoscale(False) self.qtgui_time_sink_x_0.enable_grid(False) self.qtgui_time_sink_x_0.enable_axis_labels(True) self.qtgui_time_sink_x_0.enable_control_panel(False) self.qtgui_time_sink_x_0.enable_stem_plot(False) labels = [ 'Signal 1', 'Signal 2', 'Signal 3', 'Signal 4', 'Signal 5', 'Signal 6', 'Signal 7', 'Signal 8', 'Signal 9', 'Signal 10' ] widths = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1] colors = [ 'blue', 'red', 'green', 'black', 'cyan', 'magenta', 'yellow', 'dark red', 'dark green', 'dark blue' ] alphas = [1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0] styles = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1] markers = [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1] for i in range(1): if len(labels[i]) == 0: self.qtgui_time_sink_x_0.set_line_label( i, "Data {0}".format(i)) else: self.qtgui_time_sink_x_0.set_line_label(i, labels[i]) self.qtgui_time_sink_x_0.set_line_width(i, widths[i]) self.qtgui_time_sink_x_0.set_line_color(i, colors[i]) self.qtgui_time_sink_x_0.set_line_style(i, styles[i]) self.qtgui_time_sink_x_0.set_line_marker(i, markers[i]) self.qtgui_time_sink_x_0.set_line_alpha(i, alphas[i]) self._qtgui_time_sink_x_0_win = sip.wrapinstance( self.qtgui_time_sink_x_0.pyqwidget(), Qt.QWidget) self.top_grid_layout.addWidget(self._qtgui_time_sink_x_0_win) self.qtgui_freq_sink_x_2 = qtgui.freq_sink_c( 1024, #size firdes.WIN_BLACKMAN_hARRIS, #wintype 0, #fc samp_rate, #bw "Raw Spectrum", #name 1) self.qtgui_freq_sink_x_2.set_update_time(0.10) self.qtgui_freq_sink_x_2.set_y_axis(-140, 10) self.qtgui_freq_sink_x_2.set_y_label('Relative Gain', 'dB') self.qtgui_freq_sink_x_2.set_trigger_mode(qtgui.TRIG_MODE_FREE, 0.0, 0, "") self.qtgui_freq_sink_x_2.enable_autoscale(False) self.qtgui_freq_sink_x_2.enable_grid(False) self.qtgui_freq_sink_x_2.set_fft_average(1.0) self.qtgui_freq_sink_x_2.enable_axis_labels(True) self.qtgui_freq_sink_x_2.enable_control_panel(False) labels = ['', '', '', '', '', '', '', '', '', ''] widths = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1] colors = [ "blue", "red", "green", "black", "cyan", "magenta", "yellow", "dark red", "dark green", "dark blue" ] alphas = [1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0] for i in range(1): if len(labels[i]) == 0: self.qtgui_freq_sink_x_2.set_line_label( i, "Data {0}".format(i)) else: self.qtgui_freq_sink_x_2.set_line_label(i, labels[i]) self.qtgui_freq_sink_x_2.set_line_width(i, widths[i]) self.qtgui_freq_sink_x_2.set_line_color(i, colors[i]) self.qtgui_freq_sink_x_2.set_line_alpha(i, alphas[i]) self._qtgui_freq_sink_x_2_win = sip.wrapinstance( self.qtgui_freq_sink_x_2.pyqwidget(), Qt.QWidget) self.top_grid_layout.addWidget(self._qtgui_freq_sink_x_2_win) self.qtgui_freq_sink_x_1 = qtgui.freq_sink_c( 1024, #size firdes.WIN_BLACKMAN_hARRIS, #wintype 0, #fc samp_rate, #bw "Filtered GA Spectrum", #name 1) self.qtgui_freq_sink_x_1.set_update_time(0.10) self.qtgui_freq_sink_x_1.set_y_axis(-140, 10) self.qtgui_freq_sink_x_1.set_y_label('Relative Gain', 'dB') self.qtgui_freq_sink_x_1.set_trigger_mode(qtgui.TRIG_MODE_FREE, 0.0, 0, "") self.qtgui_freq_sink_x_1.enable_autoscale(False) self.qtgui_freq_sink_x_1.enable_grid(False) self.qtgui_freq_sink_x_1.set_fft_average(1.0) self.qtgui_freq_sink_x_1.enable_axis_labels(True) self.qtgui_freq_sink_x_1.enable_control_panel(False) labels = ['', '', '', '', '', '', '', '', '', ''] widths = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1] colors = [ "blue", "red", "green", "black", "cyan", "magenta", "yellow", "dark red", "dark green", "dark blue" ] alphas = [1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0] for i in range(1): if len(labels[i]) == 0: self.qtgui_freq_sink_x_1.set_line_label( i, "Data {0}".format(i)) else: self.qtgui_freq_sink_x_1.set_line_label(i, labels[i]) self.qtgui_freq_sink_x_1.set_line_width(i, widths[i]) self.qtgui_freq_sink_x_1.set_line_color(i, colors[i]) self.qtgui_freq_sink_x_1.set_line_alpha(i, alphas[i]) self._qtgui_freq_sink_x_1_win = sip.wrapinstance( self.qtgui_freq_sink_x_1.pyqwidget(), Qt.QWidget) self.top_grid_layout.addWidget(self._qtgui_freq_sink_x_1_win) self.qtgui_freq_sink_x_0 = qtgui.freq_sink_c( 1024, #size firdes.WIN_BLACKMAN_hARRIS, #wintype 0, #fc samp_rate / decimation, #bw "Filtered Spectrum", #name 1) self.qtgui_freq_sink_x_0.set_update_time(0.10) self.qtgui_freq_sink_x_0.set_y_axis(-140, 10) self.qtgui_freq_sink_x_0.set_y_label('Relative Gain', 'dB') self.qtgui_freq_sink_x_0.set_trigger_mode(qtgui.TRIG_MODE_FREE, 0.0, 0, "") self.qtgui_freq_sink_x_0.enable_autoscale(False) self.qtgui_freq_sink_x_0.enable_grid(False) self.qtgui_freq_sink_x_0.set_fft_average(1.0) self.qtgui_freq_sink_x_0.enable_axis_labels(True) self.qtgui_freq_sink_x_0.enable_control_panel(False) labels = ['', '', '', '', '', '', '', '', '', ''] widths = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1] colors = [ "blue", "red", "green", "black", "cyan", "magenta", "yellow", "dark red", "dark green", "dark blue" ] alphas = [1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0] for i in range(1): if len(labels[i]) == 0: self.qtgui_freq_sink_x_0.set_line_label( i, "Data {0}".format(i)) else: self.qtgui_freq_sink_x_0.set_line_label(i, labels[i]) self.qtgui_freq_sink_x_0.set_line_width(i, widths[i]) self.qtgui_freq_sink_x_0.set_line_color(i, colors[i]) self.qtgui_freq_sink_x_0.set_line_alpha(i, alphas[i]) self._qtgui_freq_sink_x_0_win = sip.wrapinstance( self.qtgui_freq_sink_x_0.pyqwidget(), Qt.QWidget) self.top_grid_layout.addWidget(self._qtgui_freq_sink_x_0_win) self.freq_xlating_fir_filter_xxx_0 = filter.freq_xlating_fir_filter_ccc( decimation, firdes.low_pass(1, samp_rate, 10e3, 1e3, firdes.WIN_HAMMING, 6.76), -53e3, samp_rate) self._clock_freq_range = Range(1e3, 1e5, 1, 1e3, 200) self._clock_freq_win = RangeWidget(self._clock_freq_range, self.set_clock_freq, 'Clock Frequency', "counter_slider", float) self.top_grid_layout.addWidget(self._clock_freq_win) self.blocks_threshold_ff_0 = blocks.threshold_ff(0.5, 0.5, 0) self.blocks_peak_detector_xb_0 = blocks.peak_detector_fb( 0.25, 0.40, 10, 0.001) self.blocks_moving_average_xx_0 = blocks.moving_average_ff( 5, 1, 4000, 1) self.blocks_complex_to_mag_squared_0 = blocks.complex_to_mag_squared(1) self.blocks_char_to_short_0 = blocks.char_to_short(1) self.blocks_burst_tagger_0 = blocks.burst_tagger(gr.sizeof_float) self.blocks_burst_tagger_0.set_true_tag('burst', True) self.blocks_burst_tagger_0.set_false_tag('burst', False) ################################################## # Connections ################################################## self.connect((self.blocks_burst_tagger_0, 0), (self.qtgui_time_sink_x_0, 0)) self.connect((self.blocks_char_to_short_0, 0), (self.blocks_burst_tagger_0, 1)) self.connect((self.blocks_complex_to_mag_squared_0, 0), (self.blocks_moving_average_xx_0, 0)) self.connect((self.blocks_moving_average_xx_0, 0), (self.blocks_threshold_ff_0, 0)) self.connect((self.blocks_peak_detector_xb_0, 0), (self.blocks_char_to_short_0, 0)) self.connect((self.blocks_threshold_ff_0, 0), (self.blocks_burst_tagger_0, 0)) self.connect((self.blocks_threshold_ff_0, 0), (self.blocks_peak_detector_xb_0, 0)) self.connect((self.blocks_threshold_ff_0, 0), (self.qtgui_time_sink_x_1_0, 0)) self.connect((self.freq_xlating_fir_filter_xxx_0, 0), (self.blocks_complex_to_mag_squared_0, 0)) self.connect((self.freq_xlating_fir_filter_xxx_0, 0), (self.qtgui_freq_sink_x_0, 0)) self.connect((self.freq_xlating_fir_filter_xxx_0, 0), (self.qtgui_freq_sink_x_1, 0)) self.connect((self.rtlsdr_source_0, 0), (self.freq_xlating_fir_filter_xxx_0, 0)) self.connect((self.rtlsdr_source_0, 0), (self.qtgui_freq_sink_x_2, 0))
def __init__(self, subdev="A:0", devid="addr=192.168.10.2", frequency=1.4125e9, fftsize=8192): grc_wxgui.top_block_gui.__init__(self, title="Total Power Radiometer - N200") ################################################## # Parameters ################################################## self.subdev = subdev self.devid = devid self.frequency = frequency self.fftsize = fftsize ################################################## # Variables ################################################## self.GUI_samp_rate = GUI_samp_rate = 10e6 self.samp_rate = samp_rate = int(GUI_samp_rate) self.prefix = prefix = "tpr_" self.text_samp_rate = text_samp_rate = GUI_samp_rate self.text_deviceID = text_deviceID = subdev self.text_Device_addr = text_Device_addr = devid self.spec_data_fifo = spec_data_fifo = "spectrum_" + datetime.now().strftime("%Y.%m.%d.%H.%M.%S") + ".dat" self.spavg = spavg = 1 self.scope_rate = scope_rate = 2 self.recfile_tpr = recfile_tpr = prefix + datetime.now().strftime("%Y.%m.%d.%H.%M.%S") + ".dat" self.recfile_kelvin = recfile_kelvin = prefix+"kelvin" + datetime.now().strftime("%Y.%m.%d.%H.%M.%S") + ".dat" self.rec_button_tpr = rec_button_tpr = 1 self.rec_button_iq = rec_button_iq = 1 self.noise_amplitude = noise_amplitude = .5 self.integ = integ = 2 self.gain = gain = 26 self.freq = freq = frequency self.file_rate = file_rate = 2.0 self.fftrate = fftrate = int(samp_rate/fftsize) self.det_rate = det_rate = int(20.0) self.dc_gain = dc_gain = 1 self.calib_2 = calib_2 = -342.774 self.calib_1 = calib_1 = 4.0755e3 self.add_noise = add_noise = 0 ################################################## # Blocks ################################################## self.Main = self.Main = wx.Notebook(self.GetWin(), style=wx.NB_TOP) self.Main.AddPage(grc_wxgui.Panel(self.Main), "N200 Control Panel") self.Main.AddPage(grc_wxgui.Panel(self.Main), "TPR Measurements") self.Add(self.Main) _spavg_sizer = wx.BoxSizer(wx.VERTICAL) self._spavg_text_box = forms.text_box( parent=self.Main.GetPage(0).GetWin(), sizer=_spavg_sizer, value=self.spavg, callback=self.set_spavg, label="Spectral Averaging (Seconds)", converter=forms.int_converter(), proportion=0, ) self._spavg_slider = forms.slider( parent=self.Main.GetPage(0).GetWin(), sizer=_spavg_sizer, value=self.spavg, callback=self.set_spavg, minimum=1, maximum=20, num_steps=20, style=wx.SL_HORIZONTAL, cast=int, proportion=1, ) self.Main.GetPage(0).GridAdd(_spavg_sizer, 1, 1, 1, 1) self._rec_button_tpr_chooser = forms.button( parent=self.Main.GetPage(0).GetWin(), value=self.rec_button_tpr, callback=self.set_rec_button_tpr, label="Record TPR Data", choices=[0,1], labels=['Stop','Start'], ) self.Main.GetPage(0).GridAdd(self._rec_button_tpr_chooser, 4, 1, 1, 1) self._rec_button_iq_chooser = forms.button( parent=self.Main.GetPage(0).GetWin(), value=self.rec_button_iq, callback=self.set_rec_button_iq, label="Record I/Q Data", choices=[0,1], labels=['Stop','Start'], ) self.Main.GetPage(0).GridAdd(self._rec_button_iq_chooser, 4, 0, 1, 1) _integ_sizer = wx.BoxSizer(wx.VERTICAL) self._integ_text_box = forms.text_box( parent=self.Main.GetPage(0).GetWin(), sizer=_integ_sizer, value=self.integ, callback=self.set_integ, label="Integration Time (Seconds)", converter=forms.float_converter(), proportion=0, ) self._integ_slider = forms.slider( parent=self.Main.GetPage(0).GetWin(), sizer=_integ_sizer, value=self.integ, callback=self.set_integ, minimum=1, maximum=60, num_steps=100, style=wx.SL_HORIZONTAL, cast=float, proportion=1, ) self.Main.GetPage(0).GridAdd(_integ_sizer, 0, 2, 1, 1) _gain_sizer = wx.BoxSizer(wx.VERTICAL) self._gain_text_box = forms.text_box( parent=self.Main.GetPage(0).GetWin(), sizer=_gain_sizer, value=self.gain, callback=self.set_gain, label="RF Gain (dB)", converter=forms.float_converter(), proportion=0, ) self._gain_slider = forms.slider( parent=self.Main.GetPage(0).GetWin(), sizer=_gain_sizer, value=self.gain, callback=self.set_gain, minimum=0, maximum=50, num_steps=100, style=wx.SL_HORIZONTAL, cast=float, proportion=1, ) self.Main.GetPage(0).GridAdd(_gain_sizer, 0, 1, 1, 1) self._freq_text_box = forms.text_box( parent=self.Main.GetPage(0).GetWin(), value=self.freq, callback=self.set_freq, label="Center Frequency (Hz)", converter=forms.float_converter(), ) self.Main.GetPage(0).GridAdd(self._freq_text_box, 0, 0, 1, 1) self._dc_gain_chooser = forms.radio_buttons( parent=self.Main.GetPage(0).GetWin(), value=self.dc_gain, callback=self.set_dc_gain, label="DC Gain", choices=[1, 10, 100, 1000, 10000], labels=[], style=wx.RA_HORIZONTAL, ) self.Main.GetPage(0).GridAdd(self._dc_gain_chooser, 1, 0, 1, 1) self._calib_2_text_box = forms.text_box( parent=self.Main.GetPage(0).GetWin(), value=self.calib_2, callback=self.set_calib_2, label="Calibration value 2", converter=forms.float_converter(), ) self.Main.GetPage(0).GridAdd(self._calib_2_text_box, 3, 1, 1, 1) self._calib_1_text_box = forms.text_box( parent=self.Main.GetPage(0).GetWin(), value=self.calib_1, callback=self.set_calib_1, label="Calibration value 1", converter=forms.float_converter(), ) self.Main.GetPage(0).GridAdd(self._calib_1_text_box, 3, 0, 1, 1) self._GUI_samp_rate_chooser = forms.radio_buttons( parent=self.Main.GetPage(0).GetWin(), value=self.GUI_samp_rate, callback=self.set_GUI_samp_rate, label="Sample Rate (BW)", choices=[1e6,2e6,5e6,10e6,25e6], labels=['1 MHz','2 MHz','5 MHz','10 MHz','25 MHz'], style=wx.RA_HORIZONTAL, ) self.Main.GetPage(0).GridAdd(self._GUI_samp_rate_chooser, 1, 3, 1, 1) self.wxgui_scopesink2_2 = scopesink2.scope_sink_f( self.Main.GetPage(1).GetWin(), title="Total Power", sample_rate=2, v_scale=.1, v_offset=0, t_scale=100, ac_couple=False, xy_mode=False, num_inputs=1, trig_mode=wxgui.TRIG_MODE_STRIPCHART, y_axis_label="power level", ) self.Main.GetPage(1).Add(self.wxgui_scopesink2_2.win) self.wxgui_numbersink2_2 = numbersink2.number_sink_f( self.GetWin(), unit="Units", minval=0, maxval=1, factor=1.0, decimal_places=10, ref_level=0, sample_rate=GUI_samp_rate, number_rate=15, average=False, avg_alpha=None, label="Number Plot", peak_hold=False, show_gauge=True, ) self.Add(self.wxgui_numbersink2_2.win) self.wxgui_numbersink2_0_0 = numbersink2.number_sink_f( self.Main.GetPage(1).GetWin(), unit="", minval=0, maxval=.2, factor=1, decimal_places=6, ref_level=0, sample_rate=scope_rate, number_rate=15, average=True, avg_alpha=.01, label="Raw Power level", peak_hold=False, show_gauge=True, ) self.Main.GetPage(1).Add(self.wxgui_numbersink2_0_0.win) self.wxgui_numbersink2_0 = numbersink2.number_sink_f( self.Main.GetPage(1).GetWin(), unit="Kelvin", minval=0, maxval=400, factor=1, decimal_places=6, ref_level=0, sample_rate=scope_rate, number_rate=15, average=False, avg_alpha=None, label="Calibrated Temperature", peak_hold=False, show_gauge=True, ) self.Main.GetPage(1).Add(self.wxgui_numbersink2_0.win) self.wxgui_fftsink2_0 = fftsink2.fft_sink_c( self.Main.GetPage(0).GetWin(), baseband_freq=freq, y_per_div=10, y_divs=10, ref_level=20, ref_scale=2.0, sample_rate=GUI_samp_rate, fft_size=1024, fft_rate=5, average=True, avg_alpha=0.1, title="Spectrum", peak_hold=False, size=(800,400), ) self.Main.GetPage(0).Add(self.wxgui_fftsink2_0.win) self.uhd_usrp_source_0 = uhd.usrp_source( ",".join((devid, "")), uhd.stream_args( cpu_format="fc32", channels=range(1), ), ) self.uhd_usrp_source_0.set_samp_rate(GUI_samp_rate) self.uhd_usrp_source_0.set_center_freq(freq, 0) self.uhd_usrp_source_0.set_gain(gain, 0) (self.uhd_usrp_source_0).set_processor_affinity([0]) self._text_samp_rate_static_text = forms.static_text( parent=self.Main.GetPage(0).GetWin(), value=self.text_samp_rate, callback=self.set_text_samp_rate, label="Samp rate", converter=forms.float_converter(), ) self.Main.GetPage(0).GridAdd(self._text_samp_rate_static_text, 2, 0, 1, 1) self._text_deviceID_static_text = forms.static_text( parent=self.Main.GetPage(0).GetWin(), value=self.text_deviceID, callback=self.set_text_deviceID, label="SubDev", converter=forms.str_converter(), ) self.Main.GetPage(0).GridAdd(self._text_deviceID_static_text, 2, 1, 1, 1) self._text_Device_addr_static_text = forms.static_text( parent=self.Main.GetPage(0).GetWin(), value=self.text_Device_addr, callback=self.set_text_Device_addr, label="Device Address", converter=forms.str_converter(), ) self.Main.GetPage(0).GridAdd(self._text_Device_addr_static_text, 2, 2, 1, 1) self.single_pole_iir_filter_xx_0 = filter.single_pole_iir_filter_ff(1.0/((samp_rate*integ)/2.0), 1) (self.single_pole_iir_filter_xx_0).set_processor_affinity([1]) _noise_amplitude_sizer = wx.BoxSizer(wx.VERTICAL) self._noise_amplitude_text_box = forms.text_box( parent=self.Main.GetPage(0).GetWin(), sizer=_noise_amplitude_sizer, value=self.noise_amplitude, callback=self.set_noise_amplitude, label='noise_amplitude', converter=forms.float_converter(), proportion=0, ) self._noise_amplitude_slider = forms.slider( parent=self.Main.GetPage(0).GetWin(), sizer=_noise_amplitude_sizer, value=self.noise_amplitude, callback=self.set_noise_amplitude, minimum=.01, maximum=1, num_steps=100, style=wx.SL_HORIZONTAL, cast=float, proportion=1, ) self.Main.GetPage(0).GridAdd(_noise_amplitude_sizer, 3, 2, 1, 1) self.logpwrfft_x_0 = logpwrfft.logpwrfft_c( sample_rate=samp_rate, fft_size=fftsize, ref_scale=2, frame_rate=fftrate, avg_alpha=1.0/float(spavg*fftrate), average=True, ) self.blocks_peak_detector_xb_0 = blocks.peak_detector_fb(0.25, 0.40, 10, 0.001) self.blocks_multiply_const_vxx_1 = blocks.multiply_const_vff((calib_1, )) self.blocks_multiply_const_vxx_0 = blocks.multiply_const_vff((dc_gain, )) self.blocks_keep_one_in_n_4 = blocks.keep_one_in_n(gr.sizeof_float*1, samp_rate/det_rate) self.blocks_keep_one_in_n_3 = blocks.keep_one_in_n(gr.sizeof_float*fftsize, fftrate) self.blocks_keep_one_in_n_1 = blocks.keep_one_in_n(gr.sizeof_float*1, int(det_rate/file_rate)) self.blocks_file_sink_5 = blocks.file_sink(gr.sizeof_float*fftsize, spec_data_fifo, False) self.blocks_file_sink_5.set_unbuffered(True) self.blocks_file_sink_4 = blocks.file_sink(gr.sizeof_float*1, recfile_tpr, False) self.blocks_file_sink_4.set_unbuffered(True) self.blocks_file_sink_1 = blocks.file_sink(gr.sizeof_gr_complex*1, prefix+"iq_raw" + datetime.now().strftime("%Y.%m.%d.%H.%M.%S") + ".dat", False) self.blocks_file_sink_1.set_unbuffered(False) self.blocks_file_sink_0 = blocks.file_sink(gr.sizeof_float*1, recfile_kelvin, False) self.blocks_file_sink_0.set_unbuffered(True) self.blocks_complex_to_real_0 = blocks.complex_to_real(1) self.blocks_complex_to_mag_squared_1 = blocks.complex_to_mag_squared(1) self.blocks_char_to_float_0 = blocks.char_to_float(1, 1) self.blocks_add_const_vxx_1 = blocks.add_const_vff((calib_2, )) self.blks2_valve_2 = grc_blks2.valve(item_size=gr.sizeof_gr_complex*1, open=bool(rec_button_iq)) self.blks2_valve_1 = grc_blks2.valve(item_size=gr.sizeof_float*1, open=bool(0)) self.blks2_valve_0 = grc_blks2.valve(item_size=gr.sizeof_float*1, open=bool(rec_button_tpr)) self._add_noise_chooser = forms.button( parent=self.Main.GetPage(0).GetWin(), value=self.add_noise, callback=self.set_add_noise, label="Noise Source", choices=[0,1], labels=['Off','On'], ) self.Main.GetPage(0).GridAdd(self._add_noise_chooser, 3, 3, 1, 1) ################################################## # Connections ################################################## self.connect((self.blks2_valve_0, 0), (self.blocks_file_sink_4, 0)) self.connect((self.blks2_valve_1, 0), (self.blocks_file_sink_0, 0)) self.connect((self.blks2_valve_2, 0), (self.blocks_file_sink_1, 0)) self.connect((self.blocks_add_const_vxx_1, 0), (self.blks2_valve_1, 0)) self.connect((self.blocks_add_const_vxx_1, 0), (self.wxgui_numbersink2_0, 0)) self.connect((self.blocks_char_to_float_0, 0), (self.wxgui_numbersink2_2, 0)) self.connect((self.blocks_complex_to_mag_squared_1, 0), (self.single_pole_iir_filter_xx_0, 0)) self.connect((self.blocks_complex_to_real_0, 0), (self.blocks_peak_detector_xb_0, 0)) self.connect((self.blocks_keep_one_in_n_1, 0), (self.blks2_valve_0, 0)) self.connect((self.blocks_keep_one_in_n_1, 0), (self.blocks_multiply_const_vxx_1, 0)) self.connect((self.blocks_keep_one_in_n_1, 0), (self.wxgui_scopesink2_2, 0)) self.connect((self.blocks_keep_one_in_n_3, 0), (self.blocks_file_sink_5, 0)) self.connect((self.blocks_keep_one_in_n_4, 0), (self.blocks_multiply_const_vxx_0, 0)) self.connect((self.blocks_multiply_const_vxx_0, 0), (self.blocks_keep_one_in_n_1, 0)) self.connect((self.blocks_multiply_const_vxx_0, 0), (self.wxgui_numbersink2_0_0, 0)) self.connect((self.blocks_multiply_const_vxx_1, 0), (self.blocks_add_const_vxx_1, 0)) self.connect((self.blocks_peak_detector_xb_0, 0), (self.blocks_char_to_float_0, 0)) self.connect((self.logpwrfft_x_0, 0), (self.blocks_keep_one_in_n_3, 0)) self.connect((self.single_pole_iir_filter_xx_0, 0), (self.blocks_keep_one_in_n_4, 0)) self.connect((self.uhd_usrp_source_0, 0), (self.blks2_valve_2, 0)) self.connect((self.uhd_usrp_source_0, 0), (self.blocks_complex_to_mag_squared_1, 0)) self.connect((self.uhd_usrp_source_0, 0), (self.blocks_complex_to_real_0, 0)) self.connect((self.uhd_usrp_source_0, 0), (self.logpwrfft_x_0, 0)) self.connect((self.uhd_usrp_source_0, 0), (self.wxgui_fftsink2_0, 0))
def __init__(self): gr.top_block.__init__(self, "Not titled yet") Qt.QWidget.__init__(self) self.setWindowTitle("Not titled yet") qtgui.util.check_set_qss() try: self.setWindowIcon(Qt.QIcon.fromTheme('gnuradio-grc')) except: pass self.top_scroll_layout = Qt.QVBoxLayout() self.setLayout(self.top_scroll_layout) self.top_scroll = Qt.QScrollArea() self.top_scroll.setFrameStyle(Qt.QFrame.NoFrame) self.top_scroll_layout.addWidget(self.top_scroll) self.top_scroll.setWidgetResizable(True) self.top_widget = Qt.QWidget() self.top_scroll.setWidget(self.top_widget) self.top_layout = Qt.QVBoxLayout(self.top_widget) self.top_grid_layout = Qt.QGridLayout() self.top_layout.addLayout(self.top_grid_layout) self.settings = Qt.QSettings("GNU Radio", "clock_recovery") try: if StrictVersion(Qt.qVersion()) < StrictVersion("5.0.0"): self.restoreGeometry( self.settings.value("geometry").toByteArray()) else: self.restoreGeometry(self.settings.value("geometry")) except: pass ################################################## # Variables ################################################## self.xlate_freq = xlate_freq = -223 self.trans_width = trans_width = 20e3 self.samp_rate = samp_rate = 2048e3 self.samp_per_sym = samp_per_sym = 10 self.filter_freq = filter_freq = 80e3 self.decimation = decimation = 1 ################################################## # Blocks ################################################## self._xlate_freq_range = Range(-10000, +10000, 1, -223, 200) self._xlate_freq_win = RangeWidget(self._xlate_freq_range, self.set_xlate_freq, 'Translating Frequency', "counter_slider", float) self.top_grid_layout.addWidget(self._xlate_freq_win) self._trans_width_range = Range(1e3, 100e3, 1e3, 20e3, 200) self._trans_width_win = RangeWidget(self._trans_width_range, self.set_trans_width, 'Transition Width', "counter_slider", float) self.top_grid_layout.addWidget(self._trans_width_win) self._filter_freq_range = Range(20e3, 500e3, 1e3, 80e3, 200) self._filter_freq_win = RangeWidget(self._filter_freq_range, self.set_filter_freq, 'Filter Frequency', "counter_slider", float) self.top_grid_layout.addWidget(self._filter_freq_win) self.qtgui_time_sink_x_3 = qtgui.time_sink_f( 1024, #size samp_rate, #samp_rate "", #name 1 #number of inputs ) self.qtgui_time_sink_x_3.set_update_time(0.10) self.qtgui_time_sink_x_3.set_y_axis(-1, 1) self.qtgui_time_sink_x_3.set_y_label('Amplitude', "") self.qtgui_time_sink_x_3.enable_tags(True) self.qtgui_time_sink_x_3.set_trigger_mode(qtgui.TRIG_MODE_FREE, qtgui.TRIG_SLOPE_POS, 0.0, 0, 0, "") self.qtgui_time_sink_x_3.enable_autoscale(False) self.qtgui_time_sink_x_3.enable_grid(False) self.qtgui_time_sink_x_3.enable_axis_labels(True) self.qtgui_time_sink_x_3.enable_control_panel(True) self.qtgui_time_sink_x_3.enable_stem_plot(False) labels = [ 'Signal 1', 'Signal 2', 'Signal 3', 'Signal 4', 'Signal 5', 'Signal 6', 'Signal 7', 'Signal 8', 'Signal 9', 'Signal 10' ] widths = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1] colors = [ 'blue', 'red', 'green', 'black', 'cyan', 'magenta', 'yellow', 'dark red', 'dark green', 'dark blue' ] alphas = [1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0] styles = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1] markers = [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1] for i in range(1): if len(labels[i]) == 0: self.qtgui_time_sink_x_3.set_line_label( i, "Data {0}".format(i)) else: self.qtgui_time_sink_x_3.set_line_label(i, labels[i]) self.qtgui_time_sink_x_3.set_line_width(i, widths[i]) self.qtgui_time_sink_x_3.set_line_color(i, colors[i]) self.qtgui_time_sink_x_3.set_line_style(i, styles[i]) self.qtgui_time_sink_x_3.set_line_marker(i, markers[i]) self.qtgui_time_sink_x_3.set_line_alpha(i, alphas[i]) self._qtgui_time_sink_x_3_win = sip.wrapinstance( self.qtgui_time_sink_x_3.pyqwidget(), Qt.QWidget) self.top_grid_layout.addWidget(self._qtgui_time_sink_x_3_win) self.qtgui_time_sink_x_0 = qtgui.time_sink_c( 1024, #size samp_rate, #samp_rate 'Xlated Signal', #name 1 #number of inputs ) self.qtgui_time_sink_x_0.set_update_time(0.10) self.qtgui_time_sink_x_0.set_y_axis(-1, 1) self.qtgui_time_sink_x_0.set_y_label('Amplitude', "") self.qtgui_time_sink_x_0.enable_tags(True) self.qtgui_time_sink_x_0.set_trigger_mode(qtgui.TRIG_MODE_FREE, qtgui.TRIG_SLOPE_POS, 0.0, 0, 0, "") self.qtgui_time_sink_x_0.enable_autoscale(False) self.qtgui_time_sink_x_0.enable_grid(False) self.qtgui_time_sink_x_0.enable_axis_labels(True) self.qtgui_time_sink_x_0.enable_control_panel(False) self.qtgui_time_sink_x_0.enable_stem_plot(False) labels = [ 'Signal 1', 'Signal 2', 'Signal 3', 'Signal 4', 'Signal 5', 'Signal 6', 'Signal 7', 'Signal 8', 'Signal 9', 'Signal 10' ] widths = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1] colors = [ 'blue', 'red', 'green', 'black', 'cyan', 'magenta', 'yellow', 'dark red', 'dark green', 'dark blue' ] alphas = [1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0] styles = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1] markers = [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1] for i in range(2): if len(labels[i]) == 0: if (i % 2 == 0): self.qtgui_time_sink_x_0.set_line_label( i, "Re{{Data {0}}}".format(i / 2)) else: self.qtgui_time_sink_x_0.set_line_label( i, "Im{{Data {0}}}".format(i / 2)) else: self.qtgui_time_sink_x_0.set_line_label(i, labels[i]) self.qtgui_time_sink_x_0.set_line_width(i, widths[i]) self.qtgui_time_sink_x_0.set_line_color(i, colors[i]) self.qtgui_time_sink_x_0.set_line_style(i, styles[i]) self.qtgui_time_sink_x_0.set_line_marker(i, markers[i]) self.qtgui_time_sink_x_0.set_line_alpha(i, alphas[i]) self._qtgui_time_sink_x_0_win = sip.wrapinstance( self.qtgui_time_sink_x_0.pyqwidget(), Qt.QWidget) self.top_grid_layout.addWidget(self._qtgui_time_sink_x_0_win) self.qtgui_freq_sink_x_0 = qtgui.freq_sink_c( 1024, #size firdes.WIN_BLACKMAN_hARRIS, #wintype 0, #fc samp_rate, #bw 'Xlated Signal', #name 1) self.qtgui_freq_sink_x_0.set_update_time(0.10) self.qtgui_freq_sink_x_0.set_y_axis(-140, 10) self.qtgui_freq_sink_x_0.set_y_label('Relative Gain', 'dB') self.qtgui_freq_sink_x_0.set_trigger_mode(qtgui.TRIG_MODE_FREE, 0.0, 0, "") self.qtgui_freq_sink_x_0.enable_autoscale(False) self.qtgui_freq_sink_x_0.enable_grid(False) self.qtgui_freq_sink_x_0.set_fft_average(1.0) self.qtgui_freq_sink_x_0.enable_axis_labels(True) self.qtgui_freq_sink_x_0.enable_control_panel(True) labels = ['', '', '', '', '', '', '', '', '', ''] widths = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1] colors = [ "blue", "red", "green", "black", "cyan", "magenta", "yellow", "dark red", "dark green", "dark blue" ] alphas = [1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0] for i in range(1): if len(labels[i]) == 0: self.qtgui_freq_sink_x_0.set_line_label( i, "Data {0}".format(i)) else: self.qtgui_freq_sink_x_0.set_line_label(i, labels[i]) self.qtgui_freq_sink_x_0.set_line_width(i, widths[i]) self.qtgui_freq_sink_x_0.set_line_color(i, colors[i]) self.qtgui_freq_sink_x_0.set_line_alpha(i, alphas[i]) self._qtgui_freq_sink_x_0_win = sip.wrapinstance( self.qtgui_freq_sink_x_0.pyqwidget(), Qt.QWidget) self.top_grid_layout.addWidget(self._qtgui_freq_sink_x_0_win) self.freq_xlating_fir_filter_xxx_0 = filter.freq_xlating_fir_filter_ccc( decimation, firdes.low_pass(1, samp_rate, filter_freq, trans_width, firdes.WIN_HAMMING, 6.76), xlate_freq, samp_rate) self.digital_clock_recovery_mm_xx_0 = digital.clock_recovery_mm_ff( samp_per_sym * (1 + 0.0), 0.25 * 0.175 * 0.175, 0.5, 0.175, 0.005) self.digital_binary_slicer_fb_0_0 = digital.binary_slicer_fb() self.digital_binary_slicer_fb_0 = digital.binary_slicer_fb() self.blocks_uchar_to_float_1 = blocks.uchar_to_float() self.blocks_uchar_to_float_0 = blocks.uchar_to_float() self.blocks_threshold_ff_0 = blocks.threshold_ff(0.1, 0.1, 0) self.blocks_peak_detector_xb_0 = blocks.peak_detector_fb( 0.25, 0.40, 10, 0.001) self.blocks_multiply_const_vxx_0_0 = blocks.multiply_const_ff(1 / 255) self.blocks_multiply_const_vxx_0 = blocks.multiply_const_ff(1 / 255) self.blocks_float_to_complex_0 = blocks.float_to_complex(1) self.blocks_file_source_0 = blocks.file_source( gr.sizeof_char * 1, '/Users/bodokaiser/Repositories/github.com/bodokaiser/arduino-rtlsdr/reverse-engineering/data/10111_11111.cu8', True, 0, 0) self.blocks_file_source_0.set_begin_tag(pmt.PMT_NIL) self.blocks_deinterleave_0 = blocks.deinterleave(gr.sizeof_char * 1, 1) self.blocks_complex_to_mag_squared_0 = blocks.complex_to_mag_squared(1) self.blocks_char_to_short_0 = blocks.char_to_short(1) self.blocks_char_to_float_0 = blocks.char_to_float(1, 1) self.blocks_burst_tagger_0 = blocks.burst_tagger(gr.sizeof_float) self.blocks_burst_tagger_0.set_true_tag('burst', True) self.blocks_burst_tagger_0.set_false_tag('burst', False) self.blocks_and_xx_0 = blocks.and_bb() self.blocks_add_const_vxx_1 = blocks.add_const_ff(-0.5) self.blocks_add_const_vxx_0 = blocks.add_const_ff(-0.5) ################################################## # Connections ################################################## self.connect((self.blocks_add_const_vxx_0, 0), (self.blocks_float_to_complex_0, 0)) self.connect((self.blocks_add_const_vxx_1, 0), (self.blocks_float_to_complex_0, 1)) self.connect((self.blocks_and_xx_0, 0), (self.blocks_char_to_float_0, 0)) self.connect((self.blocks_burst_tagger_0, 0), (self.digital_binary_slicer_fb_0_0, 0)) self.connect((self.blocks_burst_tagger_0, 0), (self.digital_clock_recovery_mm_xx_0, 0)) self.connect((self.blocks_char_to_float_0, 0), (self.qtgui_time_sink_x_3, 0)) self.connect((self.blocks_char_to_short_0, 0), (self.blocks_burst_tagger_0, 1)) self.connect((self.blocks_complex_to_mag_squared_0, 0), (self.blocks_threshold_ff_0, 0)) self.connect((self.blocks_deinterleave_0, 0), (self.blocks_uchar_to_float_0, 0)) self.connect((self.blocks_deinterleave_0, 1), (self.blocks_uchar_to_float_1, 0)) self.connect((self.blocks_file_source_0, 0), (self.blocks_deinterleave_0, 0)) self.connect((self.blocks_float_to_complex_0, 0), (self.freq_xlating_fir_filter_xxx_0, 0)) self.connect((self.blocks_multiply_const_vxx_0, 0), (self.blocks_add_const_vxx_0, 0)) self.connect((self.blocks_multiply_const_vxx_0_0, 0), (self.blocks_add_const_vxx_1, 0)) self.connect((self.blocks_peak_detector_xb_0, 0), (self.blocks_char_to_short_0, 0)) self.connect((self.blocks_threshold_ff_0, 0), (self.blocks_burst_tagger_0, 0)) self.connect((self.blocks_threshold_ff_0, 0), (self.blocks_peak_detector_xb_0, 0)) self.connect((self.blocks_uchar_to_float_0, 0), (self.blocks_multiply_const_vxx_0, 0)) self.connect((self.blocks_uchar_to_float_1, 0), (self.blocks_multiply_const_vxx_0_0, 0)) self.connect((self.digital_binary_slicer_fb_0, 0), (self.blocks_and_xx_0, 1)) self.connect((self.digital_binary_slicer_fb_0_0, 0), (self.blocks_and_xx_0, 0)) self.connect((self.digital_clock_recovery_mm_xx_0, 0), (self.digital_binary_slicer_fb_0, 0)) self.connect((self.freq_xlating_fir_filter_xxx_0, 0), (self.blocks_complex_to_mag_squared_0, 0)) self.connect((self.freq_xlating_fir_filter_xxx_0, 0), (self.qtgui_freq_sink_x_0, 0)) self.connect((self.freq_xlating_fir_filter_xxx_0, 0), (self.qtgui_time_sink_x_0, 0))