def __init__(self, mode, input_rate=0, context=None): assert input_rate > 0 self.__input_rate = input_rate gr.hier_block2.__init__( self, 'RTTY demodulator', gr.io_signature(1, 1, gr.sizeof_gr_complex * 1), gr.io_signature(1, 1, gr.sizeof_float * 1)) channel_filter = self.__make_channel_filter() self.__text = u'' self.__char_queue = gr.msg_queue(limit=100) self.__char_sink = blocks.message_sink(gr.sizeof_char, self.__char_queue, True) self.connect( self, channel_filter, self.__make_demodulator(), self.__char_sink) self.connect( channel_filter, self.__make_audio_filter(), blocks.rotator_cc(rotator_inc(self.__demod_rate, 2000 + self.__spacing / 2)), blocks.complex_to_real(vlen=1), analog.agc2_ff( reference=dB(-10), attack_rate=8e-1, decay_rate=8e-1), self)
def __init__(self, modulator, audio_rate, rf_rate, freq): modulator = IModulator(modulator) gr.hier_block2.__init__( self, 'SimulatedChannel', gr.io_signature(1, 1, gr.sizeof_float * 1), gr.io_signature(1, 1, gr.sizeof_gr_complex * 1), ) self.__freq = freq self.__rf_rate = rf_rate self.__modulator = modulator modulator_input_type = modulator.get_input_type() if modulator_input_type.get_kind() == 'MONO': audio_resampler = make_resampler(audio_rate, modulator_input_type.get_sample_rate()) self.connect(self, audio_resampler, modulator) elif modulator_input_type.get_kind() == 'NONE': self.connect(self, blocks.null_sink(gr.sizeof_float)) else: raise Exception('don\'t know how to supply input of type %s' % modulator_input_type) rf_resampler = rational_resampler.rational_resampler_ccf( interpolation=int(rf_rate), decimation=int(modulator.get_output_type().get_sample_rate())) self.__rotator = blocks.rotator_cc(rotator_inc(rate=rf_rate, shift=freq)) self.__mult = blocks.multiply_const_cc(dB(-10)) self.connect(modulator, rf_resampler, self.__rotator, self.__mult, self)
def __init__(self, mode, input_rate=0, context=None): assert input_rate > 0 self.__input_rate = input_rate gr.hier_block2.__init__( self, type(self).__name__, gr.io_signature(1, 1, gr.sizeof_gr_complex * 1), gr.io_signature(1, 1, gr.sizeof_float * 1)) channel_filter = self.__make_channel_filter() self.__text_cell = StringSinkCell(encoding='us-ascii') self.__text_sink = self.__text_cell.create_sink_internal() self.connect( self, channel_filter, self.__make_demodulator(), self.__text_sink) self.connect( channel_filter, self.__make_audio_filter(), blocks.rotator_cc(rotator_inc(self.__demod_rate, 2000 + self.__spacing / 2)), blocks.complex_to_real(vlen=1), analog.agc2_ff( reference=dB(-10), attack_rate=8e-1, decay_rate=8e-1), self)
def __update_audio_gain(self): gain_lin = dB(self.audio_gain) if self.__audio_channels == 2: pan = self.audio_pan # TODO: Determine correct computation for panning. http://en.wikipedia.org/wiki/Pan_law seems relevant but was short on actual formulas. May depend on headphones vs speakers? This may be correct already for headphones -- it sounds nearly-flat to me. self.__audio_gain_blocks[0].set_k(gain_lin * (1 - pan)) self.__audio_gain_blocks[1].set_k(gain_lin * (1 + pan)) else: self.__audio_gain_blocks[0].set_k(gain_lin)
def __update_audio_gain(self): gain_lin = dB(self.audio_gain) if self.__audio_channels == 2: pan = self.audio_pan # TODO: Instead of left-to-left and right-to-right, panning other than center should mix left and right content. (A "pan law" defines the proper mix.) This implies a matrix multiplication type operation. self.__audio_gain_block.set_k([ gain_lin * (1 - pan), gain_lin * (1 + pan), ]) else: self.__audio_gain_block.set_k([gain_lin])
def __init__(self, mode, input_rate, context): channels = 2 audio_rate = 10000 gr.hier_block2.__init__( self, str('%s demodulator' % (mode,)), gr.io_signature(1, 1, gr.sizeof_gr_complex), gr.io_signature(1, 1, gr.sizeof_float * channels)) self.__input_rate = input_rate self.__rec_freq_input = 0.0 self.__signal_type = SignalType(kind='STEREO', sample_rate=audio_rate) # Using agc2 rather than feedforward AGC for efficiency, because this runs at the RF rate rather than the audio rate. agc_block = analog.agc2_cc(reference=dB(-8)) agc_block.set_attack_rate(8e-3) agc_block.set_decay_rate(8e-3) agc_block.set_max_gain(dB(40)) self.connect( self, agc_block) channel_joiner = blocks.streams_to_vector(gr.sizeof_float, channels) self.connect(channel_joiner, self) for channel in xrange(0, channels): self.connect( agc_block, grfilter.fir_filter_ccc(1, design_sawtooth_filter(decreasing=channel == 0)), blocks.complex_to_mag(1), blocks.float_to_complex(), # So we can use the complex-input band filter. TODO eliminate this for efficiency MultistageChannelFilter( input_rate=input_rate, output_rate=audio_rate, cutoff_freq=5000, transition_width=5000), blocks.complex_to_real(), # assuming below 40Hz is not of interest grfilter.dc_blocker_ff(audio_rate // 40, False), (channel_joiner, channel))
def __do_connect(self): inherent_gain = 0.5 # fudge factor so that our output is similar level to narrow FM if self.__demod_method != 'async': inherent_gain *= 2 agc_block = analog.feedforward_agc_cc(int(.005 * self.__demod_rate), inherent_gain) # non-method-specific elements self.disconnect_all() self.connect( self, self.band_filter_block, # from SimpleAudioDemodulator self.rf_squelch_block, # from SquelchMixin agc_block) self.connect(self.band_filter_block, self.rf_probe_block) before_demod = agc_block if self.__demod_method == u'async': dc_blocker = self.__make_dc_blocker() self.connect( before_demod, blocks.complex_to_mag(1), dc_blocker) self.connect_audio_output(dc_blocker, dc_blocker) self.__pll = None else: # all other methods use carrier tracking # TODO: refine PLL parameters further pll = self.__pll = analog.pll_carriertracking_cc(.01 * pi, .1 * pi, -.1 * pi) pll.set_lock_threshold(dB(-20)) # pll.squelch_enable(True) self.connect(before_demod, pll) if self.__demod_method == u'stereo': left_input, left_output = self.__make_sideband_demod(False) right_input, right_output = self.__make_sideband_demod(True) self.connect(pll, left_input) self.connect(pll, right_input) self.connect_audio_output(left_output, right_output) else: (demod_input, demod_output) = self.__make_sideband_demod(self.__demod_method == u'usb') self.connect(pll, demod_input) self.connect_audio_output(demod_output, demod_output)
def __init__(self, input_rate, output_rate=12000, output_frequency=1500, transition_width=100, width=800): """Make a new WSPRFilter. input_rate: the incomming sample rate output_rate: output sample rate output_frequency: 0Hz in the complex input will be centered on this frequency in the real output width, transition_width: passband and transition band widths. """ gr.hier_block2.__init__( self, type(self).__name__, gr.io_signature(1, 1, gr.sizeof_gr_complex), gr.io_signature(1, 1, gr.sizeof_float)) self.connect( self, MultistageChannelFilter( input_rate=input_rate, output_rate=output_rate, cutoff_freq=width / 2, transition_width=transition_width), blocks.rotator_cc(2 * pi * output_frequency / output_rate), blocks.complex_to_real(vlen=1), analog.agc2_ff( reference=dB(-10), attack_rate=8e-1, decay_rate=8e-1), self)
def __init__(self, mode, input_rate=0, context=None): assert input_rate > 0 self.__input_rate = input_rate gr.hier_block2.__init__( self, type(self).__name__, gr.io_signature(1, 1, gr.sizeof_gr_complex), gr.io_signature(1, 1, gr.sizeof_float)) channel_filter = self.__make_channel_filter() self.__text = u'' self.__char_queue = gr.msg_queue(limit=100) self.__char_sink = blocks.message_sink(gr.sizeof_char, self.__char_queue, True) # The output of the channel filter is oversampled so we don't need to # interpolate for the audio monitor. So we'll downsample before going into # the demodulator. samp_per_sym = 8 downsample = self.__demod_rate / samp_per_sym / self.__symbol_rate assert downsample % 1 == 0 downsample = int(downsample) self.connect( self, channel_filter, blocks.keep_one_in_n(gr.sizeof_gr_complex, downsample), psk31_coherent_demodulator_cc(samp_per_sym=samp_per_sym), psk31_constellation_decoder_cb( varicode_decode=True, differential_decode=True), self.__char_sink) self.connect( channel_filter, blocks.rotator_cc(rotator_inc(self.__demod_rate, self.__audio_frequency)), blocks.complex_to_real(vlen=1), analog.agc2_ff( reference=dB(-10), attack_rate=8e-1, decay_rate=8e-1), self)
def __init__(self, mode, input_rate=0, context=None): assert input_rate > 0 self.__input_rate = input_rate gr.hier_block2.__init__( self, type(self).__name__, gr.io_signature(1, 1, gr.sizeof_gr_complex), gr.io_signature(1, 1, gr.sizeof_float)) channel_filter = self.__make_channel_filter() self.__char_queue = gr.msg_queue(limit=100) self.__char_sink = blocks.message_sink(gr.sizeof_char, self.__char_queue, True) # The output of the channel filter is oversampled so we don't need to # interpolate for the audio monitor. So we'll downsample before going into # the demodulator. samp_per_sym = 8 downsample = self.__demod_rate / samp_per_sym / self.__symbol_rate assert downsample % 1 == 0 downsample = int(downsample) self.connect( self, channel_filter, blocks.keep_one_in_n(gr.sizeof_gr_complex, downsample), psk31_coherent_demodulator_cc(samp_per_sym=samp_per_sym), psk31_constellation_decoder_cb( varicode_decode=True, differential_decode=True), self.__char_sink) self.connect( channel_filter, blocks.rotator_cc(rotator_inc(self.__demod_rate, self.__audio_frequency)), blocks.complex_to_real(vlen=1), analog.agc2_ff( reference=dB(-10), attack_rate=8e-1, decay_rate=8e-1), self)
def __init__(self, name): gr.hier_block2.__init__( self, name, gr.io_signature(0, 0, 0), gr.io_signature(1, 1, gr.sizeof_gr_complex * 1), ) rf_rate = self.rf_rate audio_rate = self.audio_rate self.__noise_level = -22 self.__transmitters = CellDict(dynamic=True) self.__transmitters_cs = CollectionState(self.__transmitters) self.__bus = blocks.add_vcc(1) self.__channel_model = channels.channel_model( noise_voltage=dB(self.__noise_level), frequency_offset=0, epsilon=1.01, # TODO: expose this parameter # taps=..., # TODO: apply something here? ) self.__rotator = blocks.rotator_cc() self.__throttle = blocks.throttle(gr.sizeof_gr_complex, rf_rate) self.connect( self.__bus, self.__throttle, self.__channel_model, self.__rotator, self) signals = [] def add_modulator(freq, key, mode_or_modulator_ctor, **kwargs): if isinstance(mode_or_modulator_ctor, type): mode = None ctor = mode_or_modulator_ctor else: mode = mode_or_modulator_ctor mode_def = lookup_mode(mode) if mode_def is None: # missing plugin, say return ctor = mode_def.mod_class context = None # TODO implement context modulator = ctor(context=context, mode=mode, **kwargs) tx = _SimulatedTransmitter(modulator, audio_rate, rf_rate, freq) self.connect(audio_signal, tx) signals.append(tx) self.__transmitters[key] = tx # Audio input signal pitch = analog.sig_source_f(audio_rate, analog.GR_SAW_WAVE, -1, 2000, 1000) audio_signal = vco = blocks.vco_f(audio_rate, 1, 1) self.connect(pitch, vco) # Channels add_modulator(0.0, 'usb', 'USB') add_modulator(10e3, 'am', 'AM') add_modulator(30e3, 'fm', 'NFM') add_modulator(-30e3, 'vor1', 'VOR', angle=0) add_modulator(-60e3, 'vor2', 'VOR', angle=math.pi / 2) add_modulator(50e3, 'rtty', 'RTTY', message='The quick brown fox jumped over the lazy dog.\n') add_modulator(80e3, 'chirp', ChirpModulator) bus_input = 0 for signal in signals: self.connect(signal, (self.__bus, bus_input)) bus_input = bus_input + 1 self.__signal_type = SignalType( kind='IQ', sample_rate=rf_rate) self.__usable_bandwidth = RangeT([(-rf_rate / 2, rf_rate / 2)])
def set_gain(self, value): self.__mult.set_k(dB(value))
def set_noise_level(self, value): self.__channel_model.set_noise_voltage(dB(value)) self.__noise_level = value
def __init__(self, mode='433', input_rate=0, context=None): assert input_rate > 0 assert context is not None gr.hier_block2.__init__( self, type(self).__name__, gr.io_signature(1, 1, gr.sizeof_gr_complex), gr.io_signature(0, 0, 0)) # The input bandwidth chosen is not primarily determined by the bandwidth of the input signals, but by the frequency error of the transmitters. Therefore it is not too critical, and we can choose the exact rate to make the filtering easy. if input_rate <= upper_preferred_demod_rate: # Skip having a filter at all. self.__band_filter = None demod_rate = input_rate else: # TODO: This gunk is very similar to the stuff that MultistageChannelFilter does. See if we can share some code. lower_rate = input_rate lower_rate_prev = None while lower_rate > upper_preferred_demod_rate and lower_rate != lower_rate_prev: lower_rate_prev = lower_rate if lower_rate % 5 == 0 and lower_rate > upper_preferred_demod_rate * 3: lower_rate /= 5 elif lower_rate % 2 == 0: lower_rate /= 2 else: # non-integer ratio lower_rate = upper_preferred_demod_rate break demod_rate = lower_rate self.__band_filter = MultistageChannelFilter( input_rate=input_rate, output_rate=demod_rate, cutoff_freq=demod_rate * 0.4, transition_width=demod_rate * 0.2) # Subprocess # using /usr/bin/env because twisted spawnProcess doesn't support path search # pylint: disable=no-member process = the_reactor.spawnProcess( RTL433ProcessProtocol(context.output_message), '/usr/bin/env', env=None, # inherit environment args=[ 'env', 'rtl_433', '-F', 'json', '-r', '-', # read from stdin '-m', '3', # complex float input '-s', str(demod_rate), ], childFDs={ 0: 'w', 1: 'r', 2: 2 }) sink = make_sink_to_process_stdin(process, itemsize=gr.sizeof_gr_complex) agc = analog.agc2_cc(reference=dB(-4)) agc.set_attack_rate(200 / demod_rate) agc.set_decay_rate(200 / demod_rate) if self.__band_filter: self.connect( self, self.__band_filter, agc) else: self.connect( self, agc) self.connect(agc, sink)
def __init__(self, mode='433', input_rate=0, context=None): assert input_rate > 0 assert context is not None gr.hier_block2.__init__(self, type(self).__name__, gr.io_signature(1, 1, gr.sizeof_gr_complex), gr.io_signature(0, 0, 0)) # The input bandwidth chosen is not primarily determined by the bandwidth of the input signals, but by the frequency error of the transmitters. Therefore it is not too critical, and we can choose the exact rate to make the filtering easy. if input_rate <= upper_preferred_demod_rate: # Skip having a filter at all. self.__band_filter = None demod_rate = input_rate else: # TODO: This gunk is very similar to the stuff that MultistageChannelFilter does. See if we can share some code. lower_rate = input_rate lower_rate_prev = None while lower_rate > upper_preferred_demod_rate and lower_rate != lower_rate_prev: lower_rate_prev = lower_rate if lower_rate % 5 == 0 and lower_rate > upper_preferred_demod_rate * 3: lower_rate /= 5 elif lower_rate % 2 == 0: lower_rate /= 2 else: # non-integer ratio lower_rate = upper_preferred_demod_rate break demod_rate = lower_rate self.__band_filter = MultistageChannelFilter( input_rate=input_rate, output_rate=demod_rate, cutoff_freq=demod_rate * 0.4, transition_width=demod_rate * 0.2) # Subprocess # using /usr/bin/env because twisted spawnProcess doesn't support path search # pylint: disable=no-member process = the_reactor.spawnProcess( RTL433ProcessProtocol(context.output_message), '/usr/bin/env', env=None, # inherit environment args=[ 'env', 'rtl_433', '-F', 'json', '-r', '-', # read from stdin '-m', '3', # complex float input '-s', str(demod_rate), ], childFDs={ 0: 'w', 1: 'r', 2: 2 }) sink = make_sink_to_process_stdin(process, itemsize=gr.sizeof_gr_complex) agc = analog.agc2_cc(reference=dB(-4)) agc.set_attack_rate(200 / demod_rate) agc.set_decay_rate(200 / demod_rate) if self.__band_filter: self.connect(self, self.__band_filter, agc) else: self.connect(self, agc) self.connect(agc, sink)
def __init__(self, name): gr.hier_block2.__init__( self, name, gr.io_signature(0, 0, 0), gr.io_signature(1, 1, gr.sizeof_gr_complex * 1), ) rf_rate = self.rf_rate audio_rate = self.audio_rate self.__noise_level = -22 self.__transmitters = CellDict(dynamic=True) self.__transmitters_cs = CollectionState(self.__transmitters) self.__bus = blocks.add_vcc(1) self.__channel_model = channels.channel_model( noise_voltage=dB(self.__noise_level), frequency_offset=0, epsilon=1.01, # TODO: expose this parameter # taps=..., # TODO: apply something here? ) self.__rotator = blocks.rotator_cc() self.__throttle = blocks.throttle(gr.sizeof_gr_complex, rf_rate) self.connect(self.__bus, self.__throttle, self.__channel_model, self.__rotator, self) signals = [] def add_modulator(freq, key, mode_or_modulator_ctor, **kwargs): if isinstance(mode_or_modulator_ctor, type): mode = None ctor = mode_or_modulator_ctor else: mode = mode_or_modulator_ctor mode_def = lookup_mode(mode) if mode_def is None: # missing plugin, say return ctor = mode_def.mod_class context = None # TODO implement context modulator = ctor(context=context, mode=mode, **kwargs) tx = _SimulatedTransmitter(modulator, audio_rate, rf_rate, freq) self.connect(audio_signal, tx) signals.append(tx) self.__transmitters[key] = tx # Audio input signal pitch = analog.sig_source_f(audio_rate, analog.GR_SAW_WAVE, -1, 2000, 1000) audio_signal = vco = blocks.vco_f(audio_rate, 1, 1) self.connect(pitch, vco) # Channels add_modulator(0.0, 'usb', 'USB') add_modulator(10e3, 'am', 'AM') add_modulator(30e3, 'fm', 'NFM') add_modulator(-30e3, 'vor1', 'VOR', angle=0) add_modulator(-60e3, 'vor2', 'VOR', angle=math.pi / 2) add_modulator( 50e3, 'rtty', 'RTTY', message='The quick brown fox jumped over the lazy dog.\n') add_modulator(80e3, 'chirp', ChirpModulator) bus_input = 0 for signal in signals: self.connect(signal, (self.__bus, bus_input)) bus_input = bus_input + 1 self.__signal_type = SignalType(kind='IQ', sample_rate=rf_rate) self.__usable_bandwidth = RangeT([(-rf_rate / 2, rf_rate / 2)])
def __init__(self, mode, **kwargs): if mode == 'LSB': lsb = True cw = False elif mode == 'USB': lsb = False cw = False elif mode == 'CW': lsb = False cw = True else: raise ValueError('Not an SSB mode: %r' % (mode,)) demod_rate = 8000 # round number close to SSB bandwidth * 2 SimpleAudioDemodulator.__init__(self, mode=mode, audio_rate=demod_rate, demod_rate=demod_rate, band_filter=demod_rate / 2, # note narrower filter applied later band_filter_transition=demod_rate / 2, **kwargs) if cw: self.__offset = 1500 # CW beat frequency half_bandwidth = self.half_bandwidth = 500 band_filter_width = 120 band_mid = 0 agc_reference = dB(-10) agc_rate = 1e-1 else: self.__offset = 0 half_bandwidth = self.half_bandwidth = 2800 / 2 # standard SSB bandwidth band_filter_width = half_bandwidth / 5 if lsb: band_mid = -200 - half_bandwidth else: band_mid = 200 + half_bandwidth agc_reference = dB(-8) agc_rate = 8e-1 band_filter_low = band_mid - half_bandwidth band_filter_high = band_mid + half_bandwidth sharp_filter_block = grfilter.fir_filter_ccc( 1, firdes.complex_band_pass(1.0, demod_rate, band_filter_low + self.__offset, band_filter_high + self.__offset, band_filter_width, firdes.WIN_HAMMING)) self.__filter_shape = BandShape.bandpass_transition( low=band_filter_low, high=band_filter_high, transition=band_filter_width, markers={}) self.agc_block = analog.agc2_cc(reference=agc_reference) self.agc_block.set_attack_rate(agc_rate) self.agc_block.set_decay_rate(agc_rate) self.agc_block.set_max_gain(dB(_ssb_max_agc)) ssb_demod_block = blocks.complex_to_real(1) self.connect( self, self.band_filter_block, sharp_filter_block, # TODO: We would like to have a squelch which does not interfere with the AGC, but this is impossible without combining the squelch and AGC self.rf_squelch_block, self.agc_block, ssb_demod_block) self.connect(sharp_filter_block, self.rf_probe_block) self.connect_audio_output(ssb_demod_block)
def __init__(self, mode, **kwargs): if mode == "LSB": lsb = True cw = False elif mode == "USB": lsb = False cw = False elif mode == "CW": lsb = False cw = True else: raise ValueError("Not an SSB mode: %r" % (mode,)) demod_rate = 8000 # round number close to SSB bandwidth * 2 SimpleAudioDemodulator.__init__( self, mode=mode, audio_rate=demod_rate, demod_rate=demod_rate, band_filter=demod_rate / 2, # note narrower filter applied later band_filter_transition=demod_rate / 2, **kwargs ) if cw: self.__offset = 1500 # CW beat frequency half_bandwidth = self.half_bandwidth = 500 self.band_filter_width = 120 band_mid = 0 agc_reference = dB(-10) agc_rate = 1e-1 else: self.__offset = 0 half_bandwidth = self.half_bandwidth = 2800 / 2 # standard SSB bandwidth self.band_filter_width = half_bandwidth / 5 if lsb: band_mid = -200 - half_bandwidth else: band_mid = 200 + half_bandwidth agc_reference = dB(-8) agc_rate = 8e-1 self.band_filter_low = band_mid - half_bandwidth self.band_filter_high = band_mid + half_bandwidth sharp_filter_block = grfilter.fir_filter_ccc( 1, firdes.complex_band_pass( 1.0, demod_rate, self.band_filter_low + self.__offset, self.band_filter_high + self.__offset, self.band_filter_width, firdes.WIN_HAMMING, ), ) self.agc_block = analog.agc2_cc(reference=agc_reference) self.agc_block.set_attack_rate(agc_rate) self.agc_block.set_decay_rate(agc_rate) self.agc_block.set_max_gain(dB(_ssb_max_agc)) ssb_demod_block = blocks.complex_to_real(1) self.connect( self, self.band_filter_block, sharp_filter_block, # TODO: We would like to have an in self.rf_squelch_block, self.agc_block, ssb_demod_block, ) self.connect(sharp_filter_block, self.rf_probe_block) self.connect_audio_output(ssb_demod_block)
def __init__(self, mode, **kwargs): if mode == 'LSB': lsb = True cw = False elif mode == 'USB': lsb = False cw = False elif mode == 'CW': lsb = False cw = True else: raise ValueError('Not an SSB mode: %r' % (mode, )) demod_rate = 8000 # round number close to SSB bandwidth * 2 SimpleAudioDemodulator.__init__( self, mode=mode, audio_rate=demod_rate, demod_rate=demod_rate, band_filter=demod_rate / 2, # note narrower filter applied later band_filter_transition=demod_rate / 2, **kwargs) if cw: self.__offset = 1500 # CW beat frequency half_bandwidth = self.half_bandwidth = 500 band_filter_width = 120 band_mid = 0 agc_reference = dB(-10) agc_rate = 1e-1 else: self.__offset = 0 half_bandwidth = self.half_bandwidth = 2800 / 2 # standard SSB bandwidth band_filter_width = half_bandwidth / 5 if lsb: band_mid = -200 - half_bandwidth else: band_mid = 200 + half_bandwidth agc_reference = dB(-8) agc_rate = 8e-1 band_filter_low = band_mid - half_bandwidth band_filter_high = band_mid + half_bandwidth sharp_filter_block = grfilter.fir_filter_ccc( 1, firdes.complex_band_pass(1.0, demod_rate, band_filter_low + self.__offset, band_filter_high + self.__offset, band_filter_width, firdes.WIN_HAMMING)) self.__filter_shape = BandShape.bandpass_transition( low=band_filter_low, high=band_filter_high, transition=band_filter_width, markers={}) self.agc_block = analog.agc2_cc(reference=agc_reference) self.agc_block.set_attack_rate(agc_rate) self.agc_block.set_decay_rate(agc_rate) self.agc_block.set_max_gain(dB(_ssb_max_agc)) ssb_demod_block = blocks.complex_to_real(1) self.connect( self, self.band_filter_block, sharp_filter_block, # TODO: We would like to have a squelch which does not interfere with the AGC, but this is impossible without combining the squelch and AGC self.rf_squelch_block, self.agc_block, ssb_demod_block) self.connect(sharp_filter_block, self.rf_probe_block) self.connect_audio_output(ssb_demod_block)
from gnuradio import analog from gnuradio import gr from gnuradio import blocks from shinysdr.i.modes import get_modes, lookup_mode from shinysdr.interfaces import IDemodulator, IDemodulatorContext, IDemodulatorModeChange, ITunableDemodulator from shinysdr.math import dB, rotator_inc, to_dB from shinysdr.signals import SignalType, no_signal from shinysdr.types import EnumT, QuantityT, RangeT, ReferenceT from shinysdr import units from shinysdr.values import ExportedState, exported_value, setter, unserialize_exported_state # arbitrary non-infinite limit _audio_power_minimum_dB = -60 _audio_power_minimum_amplitude = dB(_audio_power_minimum_dB) _dummy_audio_rate = 2000 class IReceiver(Interface): """ Marker interface for receivers. (This exists even though Receiver has no class hierarchy because the client would like to know what's a receiver block, and interface information is automatically delivered to the client.) """ @implementer(IReceiver) class Receiver(gr.hier_block2, ExportedState):
from gnuradio import analog from gnuradio import gr from gnuradio import blocks from shinysdr.i.modes import get_modes, lookup_mode from shinysdr.interfaces import ITunableDemodulator from shinysdr.math import dB, rotator_inc, to_dB from shinysdr.signals import SignalType from shinysdr.types import EnumT, QuantityT, RangeT, ReferenceT from shinysdr import units from shinysdr.values import ExportedState, exported_value, setter, unserialize_exported_state # arbitrary non-infinite limit _audio_power_minimum_dB = -60 _audio_power_minimum_amplitude = dB(_audio_power_minimum_dB) _dummy_audio_rate = 2000 class IReceiver(Interface): """ Marker interface for receivers. (This exists even though Receiver has no class hierarchy because the client would like to know what's a receiver block, and interface information is automatically delivered to the client.) """ class Receiver(gr.hier_block2, ExportedState): implements(IReceiver)
def __init__(self, mode, **kwargs): if mode == 'LSB': lsb = True cw = False elif mode == 'USB': lsb = False cw = False elif mode == 'CW': lsb = False cw = True else: raise ValueError('Not an SSB mode: %r' % (mode, )) demod_rate = 8000 # round number close to SSB bandwidth * 2 SimpleAudioDemodulator.__init__( self, mode=mode, audio_rate=demod_rate, demod_rate=demod_rate, band_filter=demod_rate / 2, # note narrower filter applied later band_filter_transition=demod_rate / 2, **kwargs) if cw: self.__offset = 1500 # CW beat frequency half_bandwidth = self.half_bandwidth = 500 self.band_filter_width = 120 band_mid = 0 agc_reference = dB(-13) else: self.__offset = 0 half_bandwidth = self.half_bandwidth = 2800 / 2 # standard SSB bandwidth self.band_filter_width = half_bandwidth / 5 if lsb: band_mid = -200 - half_bandwidth else: band_mid = 200 + half_bandwidth agc_reference = dB(-8) self.band_filter_low = band_mid - half_bandwidth self.band_filter_high = band_mid + half_bandwidth sharp_filter_block = grfilter.fir_filter_ccc( 1, firdes.complex_band_pass(1.0, demod_rate, self.band_filter_low + self.__offset, self.band_filter_high + self.__offset, self.band_filter_width, firdes.WIN_HAMMING)) self.agc_block = analog.agc2_cc(reference=agc_reference) self.agc_block.set_attack_rate(1e-1) self.agc_block.set_decay_rate(1e-1) self.agc_block.set_max_gain(dB(_ssb_max_agc)) ssb_demod_block = blocks.complex_to_real(1) self.connect(self, self.band_filter_block, sharp_filter_block, self.rf_squelch_block, self.agc_block, ssb_demod_block) self.connect(sharp_filter_block, self.rf_probe_block) self.connect_audio_output(ssb_demod_block)