def __init__(self, samples_per_symbol=_def_samples_per_symbol, gain_mu=_def_gain_mu, mu=_def_mu, omega_relative_limit=_def_omega_relative_limit, freq_error=_def_freq_error, verbose=_def_verbose, log=_def_log): gr.hier_block2.__init__( self, "gmsk_demod", gr.io_signature(1, 1, gr.sizeof_gr_complex), # Input signature gr.io_signature(1, 1, gr.sizeof_char)) # Output signature self._samples_per_symbol = samples_per_symbol self._gain_mu = gain_mu self._mu = mu self._omega_relative_limit = omega_relative_limit self._freq_error = freq_error self._differential = False if samples_per_symbol < 2: raise TypeError, "samples_per_symbol >= 2, is %f" % samples_per_symbol self._omega = samples_per_symbol * (1 + self._freq_error) if not self._gain_mu: self._gain_mu = 0.175 self._gain_omega = .25 * self._gain_mu * self._gain_mu # critically damped # Demodulate FM sensitivity = (pi / 2) / samples_per_symbol self.fmdemod = analog.quadrature_demod_cf(1.0 / sensitivity) # the clock recovery block tracks the symbol clock and resamples as needed. # the output of the block is a stream of soft symbols (float) self.clock_recovery = digital.clock_recovery_mm_ff( self._omega, self._gain_omega, self._mu, self._gain_mu, self._omega_relative_limit) # slice the floats at 0, outputting 1 bit (the LSB of the output byte) per sample self.slicer = digital.binary_slicer_fb() if verbose: self._print_verbage() if log: self._setup_logging() # Connect & Initialize base class self.connect(self, self.fmdemod, self.clock_recovery, self.slicer, self)
def __init__(self, samples_per_symbol=_def_samples_per_symbol, gain_mu=_def_gain_mu, mu=_def_mu, omega_relative_limit=_def_omega_relative_limit, freq_error=_def_freq_error, verbose=_def_verbose, log=_def_log): gr.hier_block2.__init__(self, "gmsk_demod", gr.io_signature(1, 1, gr.sizeof_gr_complex), # Input signature gr.io_signature(1, 1, gr.sizeof_char)) # Output signature self._samples_per_symbol = samples_per_symbol self._gain_mu = gain_mu self._mu = mu self._omega_relative_limit = omega_relative_limit self._freq_error = freq_error self._differential = False if samples_per_symbol < 2: raise TypeError, "samples_per_symbol >= 2, is %f" % samples_per_symbol self._omega = samples_per_symbol*(1+self._freq_error) if not self._gain_mu: self._gain_mu = 0.175 self._gain_omega = .25 * self._gain_mu * self._gain_mu # critically damped # Demodulate FM sensitivity = (pi / 2) / samples_per_symbol self.fmdemod = analog.quadrature_demod_cf(1.0 / sensitivity) # the clock recovery block tracks the symbol clock and resamples as needed. # the output of the block is a stream of soft symbols (float) self.clock_recovery = digital.clock_recovery_mm_ff(self._omega, self._gain_omega, self._mu, self._gain_mu, self._omega_relative_limit) # slice the floats at 0, outputting 1 bit (the LSB of the output byte) per sample self.slicer = digital.binary_slicer_fb() if verbose: self._print_verbage() if log: self._setup_logging() # Connect & Initialize base class self.connect(self, self.fmdemod, self.clock_recovery, self.slicer, self)
def test_binary_slicer_fb(self): expected_result = ( 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 1) src_data = (-1, 1, -1, -1, 1, 1, -1, -1, -1, 1, 1, 1, -1, 1, 1, 1, 1) src_data = [s + (1 - random.random()) for s in src_data] # add some noise src = gr.vector_source_f(src_data) op = digital.binary_slicer_fb() dst = gr.vector_sink_b() self.tb.connect(src, op) self.tb.connect(op, dst) self.tb.run() # run the graph and wait for it to finish actual_result = dst.data() # fetch the contents of the sink #print "actual result", actual_result #print "expected result", expected_result self.assertFloatTuplesAlmostEqual(expected_result, actual_result)
def test_binary_slicer_fb (self): expected_result = ( 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 1) src_data = (-1, 1, -1, -1, 1, 1, -1, -1, -1, 1, 1, 1, -1, 1, 1, 1, 1) src_data = [s + (1 - random.random()) for s in src_data] # add some noise src = gr.vector_source_f (src_data) op = digital_swig.binary_slicer_fb () dst = gr.vector_sink_b () self.tb.connect (src, op) self.tb.connect (op, dst) self.tb.run () # run the graph and wait for it to finish actual_result = dst.data () # fetch the contents of the sink #print "actual result", actual_result #print "expected result", expected_result self.assertFloatTuplesAlmostEqual (expected_result, actual_result)
def __init__(self, samples_per_symbol=_def_samples_per_symbol, sensitivity=_def_sensitivity, gain_mu=_def_gain_mu, mu=_def_mu, omega_relative_limit=_def_omega_relative_limit, freq_error=_def_freq_error, verbose=_def_verbose, log=_def_log): """ Hierarchical block for Gaussian Minimum Shift Key (GFSK) demodulation. The input is the complex modulated signal at baseband. The output is a stream of bits packed 1 bit per byte (the LSB) @param samples_per_symbol: samples per baud @type samples_per_symbol: integer @param verbose: Print information about modulator? @type verbose: bool @param log: Print modualtion data to files? @type log: bool Clock recovery parameters. These all have reasonble defaults. @param gain_mu: controls rate of mu adjustment @type gain_mu: float @param mu: fractional delay [0.0, 1.0] @type mu: float @param omega_relative_limit: sets max variation in omega @type omega_relative_limit: float, typically 0.000200 (200 ppm) @param freq_error: bit rate error as a fraction @param float """ gr.hier_block2.__init__(self, "gfsk_demod", gr.io_signature(1, 1, gr.sizeof_gr_complex), # Input signature gr.io_signature(1, 1, gr.sizeof_char)) # Output signature self._samples_per_symbol = samples_per_symbol self._gain_mu = gain_mu self._mu = mu self._omega_relative_limit = omega_relative_limit self._freq_error = freq_error self._differential = False if samples_per_symbol < 2: raise TypeError, "samples_per_symbol >= 2, is %f" % samples_per_symbol self._omega = samples_per_symbol*(1+self._freq_error) if not self._gain_mu: self._gain_mu = 0.175 self._gain_omega = .25 * self._gain_mu * self._gain_mu # critically damped # Demodulate FM #sensitivity = (pi / 2) / samples_per_symbol self.fmdemod = gr.quadrature_demod_cf(1.0 / sensitivity) # the clock recovery block tracks the symbol clock and resamples as needed. # the output of the block is a stream of soft symbols (float) self.clock_recovery = digital.clock_recovery_mm_ff(self._omega, self._gain_omega, self._mu, self._gain_mu, self._omega_relative_limit) # slice the floats at 0, outputting 1 bit (the LSB of the output byte) per sample self.slicer = digital.binary_slicer_fb() if verbose: self._print_verbage() if log: self._setup_logging() # Connect & Initialize base class self.connect(self, self.fmdemod, self.clock_recovery, self.slicer, self)