Example #1
0
    def __init__(self, context, mode, angle=0.0):
        gr.hier_block2.__init__(
            self,
            type(self).__name__,
            gr.io_signature(1, 1, gr.sizeof_float * 1),
            gr.io_signature(1, 1, gr.sizeof_gr_complex * 1),
        )

        self.__angle = 0.0  # dummy statically visible value will be overwritten

        # TODO: My signal level parameters are probably wrong because this signal doesn't look like a real VOR signal

        vor_30 = analog.sig_source_f(self.__audio_rate, analog.GR_COS_WAVE,
                                     self.__vor_sig_freq, 1, 0)
        vor_add = blocks.add_cc(1)
        vor_audio = blocks.add_ff(1)
        # Audio/AM signal
        self.connect(
            vor_30,
            blocks.multiply_const_ff(0.3),  # M_n
            (vor_audio, 0))
        self.connect(
            self,
            blocks.multiply_const_ff(audio_modulation_index),  # M_i
            (vor_audio, 1))
        # Carrier component
        self.connect(analog.sig_source_c(0, analog.GR_CONST_WAVE, 0, 0, 1),
                     (vor_add, 0))
        # AM component
        self.__delay = blocks.delay(gr.sizeof_gr_complex,
                                    0)  # configured by set_angle
        self.connect(
            vor_audio,
            make_resampler(self.__audio_rate, self.__rf_rate
                           ),  # TODO make a complex version and do this last
            blocks.float_to_complex(1),
            self.__delay,
            (vor_add, 1))
        # FM component
        vor_fm_mult = blocks.multiply_cc(1)
        self.connect(  # carrier generation
            analog.sig_source_f(self.__rf_rate,
                                analog.GR_COS_WAVE, fm_subcarrier, 1, 0),
            blocks.float_to_complex(1), (vor_fm_mult, 1))
        self.connect(  # modulation
            vor_30,
            make_resampler(self.__audio_rate, self.__rf_rate),
            analog.frequency_modulator_fc(2 * math.pi * fm_deviation /
                                          self.__rf_rate),
            blocks.multiply_const_cc(0.3),  # M_d
            vor_fm_mult,
            (vor_add, 2))
        self.connect(vor_add, self)

        # calculate and initialize delay
        self.set_angle(angle)
Example #2
0
 def __init__(self, mode, input_rate, output_rate, demod_class=None, freq=0.0, quiet=False):
     gr.hier_block2.__init__(
         self, type(self).__name__,
         gr.io_signature(1, 1, gr.sizeof_gr_complex),
         gr.io_signature(2, 2, gr.sizeof_float))
     
     if demod_class is None:
         mode_def = lookup_mode(mode)
         if mode_def is None:
             raise Exception('{}: No demodulator registered for mode {!r}, only {!r}'.format(
                 type(self).__name__, mode, [md.mode for md in get_modes()]))
         demod_class = mode_def.demod_class
     
     context = _DemodulatorAdapterContext(adapter=self, freq=freq)
     
     demod = self.__demodulator = IDemodulator(demod_class(
         mode=mode,
         input_rate=input_rate,
         context=context))
     self.connect(self, demod)
     
     output_type = demod.get_output_type()
     demod_output_rate = output_type.get_sample_rate()
     same_rate = demod_output_rate == output_rate
     stereo = output_type.get_kind() == 'STEREO'
     
     # connect outputs, resampling and adapting mono/stereo as needed
     # TODO: Make the logic for this in receiver.py reusable?
     if output_type.get_kind() == 'NONE':
         # TODO: produce correct sample rate of zeroes and maybe a warning
         dummy = blocks.vector_source_f([])
         self.connect(dummy, (self, 0))
         self.connect(dummy, (self, 1))
     else:
         if stereo:
             splitter = blocks.vector_to_streams(gr.sizeof_float, 2)
             self.connect(demod, splitter)
         if same_rate:
             if stereo:
                 self.connect((splitter, 0), (self, 0))
                 self.connect((splitter, 1), (self, 1))
             else:
                 self.connect(demod, (self, 0))
                 self.connect(demod, (self, 1))
         else:
             if not quiet:
                 gr.log.info(b'{}: Native {} demodulated rate is {}; resampling to {}'.format(
                     type(self).__name__, mode, demod_output_rate, output_rate))
             if stereo:
                 self.connect((splitter, 0), make_resampler(demod_output_rate, output_rate), (self, 0))
                 self.connect((splitter, 1), make_resampler(demod_output_rate, output_rate), (self, 1))
             else:
                 resampler = make_resampler(demod_output_rate, output_rate)
                 self.connect(demod, resampler, (self, 0))
                 self.connect(resampler, (self, 1))
Example #3
0
 def __init__(self, mode, input_rate, output_rate, demod_class=None, freq=0.0, quiet=False):
     gr.hier_block2.__init__(
         self, type(self).__name__,
         gr.io_signature(1, 1, gr.sizeof_gr_complex),
         gr.io_signature(2, 2, gr.sizeof_float))
     
     if demod_class is None:
         mode_def = lookup_mode(mode)
         if mode_def is None:
             raise Exception('{}: No demodulator registered for mode {!r}, only {!r}'.format(
                 type(self).__name__, mode, [md.mode for md in get_modes()]))
         demod_class = mode_def.demod_class
     
     context = _DemodulatorAdapterContext(adapter=self, freq=freq)
     
     demod = self.__demodulator = IDemodulator(demod_class(
         mode=mode,
         input_rate=input_rate,
         context=context))
     self.connect(self, demod)
     
     output_type = demod.get_output_type()
     demod_output_rate = output_type.get_sample_rate()
     same_rate = demod_output_rate == output_rate
     stereo = output_type.get_kind() == 'STEREO'
     
     # connect outputs, resampling and adapting mono/stereo as needed
     # TODO: Make the logic for this in receiver.py reusable?
     if output_type.get_kind() == 'NONE':
         # TODO: produce correct sample rate of zeroes and maybe a warning
         dummy = blocks.vector_source_f([])
         self.connect(dummy, (self, 0))
         self.connect(dummy, (self, 1))
     else:
         if stereo:
             splitter = blocks.vector_to_streams(gr.sizeof_float, 2)
             self.connect(demod, splitter)
         if same_rate:
             if stereo:
                 self.connect((splitter, 0), (self, 0))
                 self.connect((splitter, 1), (self, 1))
             else:
                 self.connect(demod, (self, 0))
                 self.connect(demod, (self, 1))
         else:
             if not quiet:
                 gr.log.info('{}: Native {} demodulated rate is {}; resampling to {}'.format(
                     type(self).__name__, mode, demod_output_rate, output_rate))
             if stereo:
                 self.connect((splitter, 0), make_resampler(demod_output_rate, output_rate), (self, 0))
                 self.connect((splitter, 1), make_resampler(demod_output_rate, output_rate), (self, 1))
             else:
                 resampler = make_resampler(demod_output_rate, output_rate)
                 self.connect(demod, resampler, (self, 0))
                 self.connect(resampler, (self, 1))
Example #4
0
 def __init__(self, context, mode, angle=0.0):
     gr.hier_block2.__init__(
         self, 'SimulatedDevice VOR modulator',
         gr.io_signature(1, 1, gr.sizeof_float * 1),
         gr.io_signature(1, 1, gr.sizeof_gr_complex * 1),
     )
     
     self.__angle = 0.0  # dummy statically visible value will be overwritten
     
     # TODO: My signal level parameters are probably wrong because this signal doesn't look like a real VOR signal
     
     vor_30 = analog.sig_source_f(self.__audio_rate, analog.GR_COS_WAVE, self.__vor_sig_freq, 1, 0)
     vor_add = blocks.add_cc(1)
     vor_audio = blocks.add_ff(1)
     # Audio/AM signal
     self.connect(
         vor_30,
         blocks.multiply_const_ff(0.3),  # M_n
         (vor_audio, 0))
     self.connect(
         self,
         blocks.multiply_const_ff(audio_modulation_index),  # M_i
         (vor_audio, 1))
     # Carrier component
     self.connect(
         analog.sig_source_c(0, analog.GR_CONST_WAVE, 0, 0, 1),
         (vor_add, 0))
     # AM component
     self.__delay = blocks.delay(gr.sizeof_gr_complex, 0)  # configured by set_angle
     self.connect(
         vor_audio,
         make_resampler(self.__audio_rate, self.__rf_rate),  # TODO make a complex version and do this last
         blocks.float_to_complex(1),
         self.__delay,
         (vor_add, 1))
     # FM component
     vor_fm_mult = blocks.multiply_cc(1)
     self.connect(  # carrier generation
         analog.sig_source_f(self.__rf_rate, analog.GR_COS_WAVE, fm_subcarrier, 1, 0), 
         blocks.float_to_complex(1),
         (vor_fm_mult, 1))
     self.connect(  # modulation
         vor_30,
         make_resampler(self.__audio_rate, self.__rf_rate),
         analog.frequency_modulator_fc(2 * math.pi * fm_deviation / self.__rf_rate),
         blocks.multiply_const_cc(0.3),  # M_d
         vor_fm_mult,
         (vor_add, 2))
     self.connect(
         vor_add,
         self)
     
     # calculate and initialize delay
     self.set_angle(angle)
Example #5
0
    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)
Example #6
0
 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)
Example #7
0
    def __init__(self, mode, input_rate=0, context=None):
        assert input_rate > 0
        assert context is not None
        gr.hier_block2.__init__(
            self,
            str(mode) + ' (FM + Multimon-NG) demodulator',
            gr.io_signature(1, 1, gr.sizeof_gr_complex * 1),
            gr.io_signature(1, 1, gr.sizeof_float * 1),
        )
        self.mode = mode
        self.input_rate = input_rate

        # FM demod
        # TODO: Retry telling the NFMDemodulator to have its output rate be pipe_rate instead of using a resampler. Something went wrong when trying that before. Same thing is done in dsd.py
        self.fm_demod = NFMDemodulator(
            mode='NFM',
            input_rate=input_rate,
            no_audio_filter=True,  # don't remove CTCSS tone
            tau=None)  # no deemphasis
        assert self.fm_demod.get_output_type().get_kind() == 'MONO'
        fm_audio_rate = self.fm_demod.get_output_type().get_sample_rate()

        # Subprocess
        self.mm_demod = APRSDemodulator(context=context)
        mm_audio_rate = self.mm_demod.get_input_type().get_sample_rate()

        # Output
        self.connect(self, self.fm_demod,
                     make_resampler(fm_audio_rate, mm_audio_rate),
                     self.mm_demod, self)
Example #8
0
 def __init__(self, mode, input_rate=0, context=None):
     assert input_rate > 0
     assert context is not None
     gr.hier_block2.__init__(
         self, str(mode) + ' (FM + Multimon-NG) demodulator',
         gr.io_signature(1, 1, gr.sizeof_gr_complex * 1),
         gr.io_signature(1, 1, gr.sizeof_float * 1),
     )
     self.mode = mode
     self.input_rate = input_rate
     
     # FM demod
     # TODO: Retry telling the NFMDemodulator to have its output rate be pipe_rate instead of using a resampler. Something went wrong when trying that before. Same thing is done in dsd.py
     self.fm_demod = NFMDemodulator(
         mode='NFM',
         input_rate=input_rate,
         no_audio_filter=True,  # don't remove CTCSS tone
         tau=None)  # no deemphasis
     assert self.fm_demod.get_output_type().get_kind() == 'MONO'
     fm_audio_rate = self.fm_demod.get_output_type().get_sample_rate()
     
     # Subprocess
     self.mm_demod = APRSDemodulator(context=context)
     mm_audio_rate = self.mm_demod.get_input_type().get_sample_rate()
     
     # Output
     self.connect(
         self,
         self.fm_demod,
         make_resampler(fm_audio_rate, mm_audio_rate),
         self.mm_demod,
         self)
Example #9
0
    def __init__(self, mode, input_rate, output_rate, freq=0.0):
        gr.hier_block2.__init__(self,
                                type(self).__name__,
                                gr.io_signature(1, 1, gr.sizeof_gr_complex),
                                gr.io_signature(2, 2, gr.sizeof_float))

        mode_def = lookup_mode(mode)
        if mode_def is None:
            raise Exception(
                '{}: No demodulator registered for mode {!r}, only {!r}'.
                format(
                    type(self).__name__, mode,
                    [md.mode for md in get_modes()]))

        context = _DemodulatorAdapterContext(adapter=self, freq=freq)

        demod = self.__demodulator = IDemodulator(
            mode_def.demod_class(mode=mode,
                                 input_rate=input_rate,
                                 context=context))
        self.connect(self, demod)

        output_type = demod.get_output_type()
        demod_output_rate = output_type.get_sample_rate()
        same_rate = demod_output_rate == output_rate
        stereo = output_type.get_kind() == 'STEREO'

        # connect outputs, resampling and adapting mono/stereo as needed
        if same_rate:
            self.connect((demod, 0), (self, 0))
            self.connect((demod, 1 if stereo else 0), (self, 1))
        else:
            gr.log.info(
                '{}: Native {} demodulated rate is {}; resampling to {}'.
                format(
                    type(self).__name__, mode, demod_output_rate, output_rate))
            if stereo:
                self.connect((demod, 0),
                             make_resampler(demod_output_rate, output_rate),
                             (self, 0))
                self.connect((demod, 1),
                             make_resampler(demod_output_rate, output_rate),
                             (self, 1))
            else:
                resampler = make_resampler(demod_output_rate, output_rate)
                self.connect((demod, 0), resampler, (self, 0))
                self.connect(resampler, (self, 1))
Example #10
0
 def __connect_with_resampling(self, from_endpoint, from_rate, to_endpoint,
                               to_rate, complex):
     if from_rate == to_rate:
         self.connect(from_endpoint, to_endpoint)
     else:
         gr.log.info('{}: Resampling {} to {}'.format(
             type(self).__name__, from_rate, to_rate))
         resampler = make_resampler(from_rate, to_rate, complex=complex)
         self.connect(from_endpoint, resampler, to_endpoint)
Example #11
0
 def __connect_with_resampling(self, from_endpoint, from_rate, to_endpoint, to_rate, complex):
     # pylint: disable=redefined-builtin
     
     if from_rate == to_rate:
         self.connect(from_endpoint, to_endpoint)
     else:
         gr.log.info(b'{}: Resampling {} to {}'.format(
             type(self).__name__, from_rate, to_rate))
         resampler = make_resampler(from_rate, to_rate, complex=complex)
         self.connect(from_endpoint, resampler, to_endpoint)
Example #12
0
    def __init__(self, in_rate, out_rate, vlen, complex=False):
        # pylint: disable=redefined-builtin
        vitemsize = gr.sizeof_gr_complex if complex else gr.sizeof_float
        itemsize = vitemsize * vlen
        gr.hier_block2.__init__(
            self, type(self).__name__,
            gr.io_signature(1, 1, itemsize),
            gr.io_signature(1, 1, itemsize))

        if vlen == 1:
            self.connect(self, make_resampler(in_rate, out_rate, complex=complex), self)
        else:
            splitter = blocks.vector_to_streams(vitemsize, vlen)
            joiner = blocks.streams_to_vector(vitemsize, vlen)
            self.connect(self, splitter)
            for ch in xrange(vlen):
                self.connect(
                    (splitter, ch),
                    make_resampler(in_rate, out_rate, complex=complex),
                    (joiner, ch))
            self.connect(joiner, self)
Example #13
0
    def __connect_with_resampling(self, from_endpoint, from_rate, to_endpoint,
                                  to_rate, complex):
        # pylint: disable=redefined-builtin

        if from_rate == to_rate:
            self.connect(from_endpoint, to_endpoint)
        else:
            gr.log.info(
                defaultstr('{}: Resampling {} to {}'.format(
                    type(self).__name__, from_rate, to_rate)))
            resampler = make_resampler(from_rate, to_rate, complex=complex)
            self.connect(from_endpoint, resampler, to_endpoint)
Example #14
0
    def __init__(self, in_rate, out_rate, vlen, complex=False):
        # pylint: disable=redefined-builtin
        vitemsize = gr.sizeof_gr_complex if complex else gr.sizeof_float
        itemsize = vitemsize * vlen
        gr.hier_block2.__init__(self,
                                type(self).__name__,
                                gr.io_signature(1, 1, itemsize),
                                gr.io_signature(1, 1, itemsize))

        if vlen == 1:
            self.connect(self,
                         make_resampler(in_rate, out_rate, complex=complex),
                         self)
        else:
            splitter = blocks.vector_to_streams(vitemsize, vlen)
            joiner = blocks.streams_to_vector(vitemsize, vlen)
            self.connect(self, splitter)
            for ch in six.moves.range(vlen):
                self.connect((splitter, ch),
                             make_resampler(in_rate, out_rate,
                                            complex=complex), (joiner, ch))
            self.connect(joiner, self)
Example #15
0
 def _make_resampler(self, input_port, input_rate):
     taps = design_lofi_audio_filter(input_rate, self.__no_audio_filter)
     if self.audio_rate == input_rate:
         filt = grfilter.fir_filter_fff(1, taps)
         self.connect(input_port, filt)
         return filt
     elif input_rate % self.audio_rate == 0:
         filt = grfilter.fir_filter_fff(input_rate // self.audio_rate, taps)
         self.connect(input_port, filt)
         return filt
     else:
         # TODO: use combined filter and resampler (need to move filter design)
         filt = grfilter.fir_filter_fff(1, taps)
         resampler = make_resampler(input_rate, self.audio_rate)
         self.connect(input_port, filt, resampler)
         return resampler
Example #16
0
 def _make_resampler(self, input_port, input_rate):
     taps = design_lofi_audio_filter(input_rate, self.__no_audio_filter)
     if self.audio_rate == input_rate:
         filt = grfilter.fir_filter_fff(1, taps)
         self.connect(input_port, filt)
         return filt
     elif input_rate % self.audio_rate == 0:
         filt = grfilter.fir_filter_fff(input_rate // self.audio_rate, taps)
         self.connect(input_port, filt)
         return filt
     else:
         # TODO: use combined filter and resampler (need to move filter design)
         filt = grfilter.fir_filter_fff(1, taps)
         resampler = make_resampler(input_rate, self.audio_rate)
         self.connect(input_port, filt, resampler)
         return resampler
Example #17
0
    def __init__(self, mode, input_rate=0, context=None):
        assert input_rate > 0
        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))

        # TODO: Retry telling the NFMDemodulator to have its output rate be pipe_rate instead of using a resampler. Something went wrong when trying that before. Same thing is done in multimon.py
        self.__fm_demod = NFMDemodulator(
            mode='NFM',
            input_rate=input_rate,
            no_audio_filter=True,  # don't remove CTCSS tone
            tau=None)  # no deemphasis
        assert self.__fm_demod.get_output_type().get_kind() == 'MONO'
        fm_audio_rate = self.__fm_demod.get_output_type().get_sample_rate()

        self.__output_type = SignalType(kind='MONO', sample_rate=8000)

        self.connect(self, self.__fm_demod,
                     make_resampler(fm_audio_rate, _demod_rate),
                     dsd_block_ff(), self)
Example #18
0
 def __init__(self, mode, input_rate=0, uvquality=3, context=None):
     assert input_rate > 0
     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.__context = context
     self.__output_type = SignalType(kind='MONO', sample_rate=8000)
     self.__uvquality = uvquality
     
     # TODO: Retry telling the NFMDemodulator to have its output rate be _demod_rate instead of using a resampler. Something went wrong when trying that before. Same thing is done in multimon.py
     self.__fm_demod = NFMDemodulator(
         mode='NFM',
         input_rate=input_rate,
         no_audio_filter=True,  # don't remove CTCSS tone
         tau=None)  # no deemphasis
     assert self.__fm_demod.get_output_type().get_kind() == 'MONO'
     fm_audio_rate = self.__fm_demod.get_output_type().get_sample_rate()
     self.__resampler = make_resampler(fm_audio_rate, _demod_rate)
     
     self.__do_connect(False)
Example #19
0
    def __init__(self, name, add_transmitters):
        gr.hier_block2.__init__(
            self,
            type(self).__name__ + b' ' + str(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
        if add_transmitters:
            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)

        if signals:
            for bus_input, signal in enumerate(signals):
                self.connect(signal, (self.__bus, bus_input))
        else:
            # kludge up a correct-sample-rate no-op
            self.connect(audio_signal, blocks.multiply_const_ff(0),
                         make_resampler(audio_rate, rf_rate),
                         blocks.float_to_complex(), self.__bus)

        self.__signal_type = SignalType(kind='IQ', sample_rate=rf_rate)
        self.__usable_bandwidth = RangeT([(-rf_rate / 2, rf_rate / 2)])
Example #20
0
    def connect(self, inputs, outputs):
        """
        Make all new connections (graph.disconnect_all() must have been done) between inputs and outputs.
        
        inputs and outputs must be iterables of (sample_rate, block) tuples.
        """
        inputs = list(inputs)
        outputs = list(outputs)

        # Determine bus rate.
        # The bus obviously does not need to be higher than the rate of any bus input, because that would be extraneous data. It also does not need to be higher than the rate of any bus output, because no output has use for the information.
        max_in_rate = max((rate for rate, _ in inputs)) if len(inputs) > 0 else 0.0
        max_out_rate = max((rate for rate, _ in outputs)) if len(outputs) > 0 else 0.0
        new_bus_rate = min(max_out_rate, max_in_rate)
        if new_bus_rate == 0.0:
            # There are either no inputs or no outputs. Use the other side's rate so we have a well-defined value.
            new_bus_rate = max(max_out_rate, max_in_rate)
        if new_bus_rate == 0.0:
            # There are both no inputs and no outputs. No point in not keeping the old rate (and its resampler cache).
            new_bus_rate = self.__bus_rate
        elif new_bus_rate != self.__bus_rate:
            self.__bus_rate = new_bus_rate
            self.__resampler_cache.clear()

        # recreated each time because reusing an add_ff w/ different
        # input counts fails; TODO: report/fix bug
        bus_sums = [blocks.add_ff() for _ in self.__channels]

        in_index = 0
        for in_rate, in_block in inputs:
            if in_rate == self.__bus_rate:
                for ch in self.__channels:
                    self.__graph.connect((in_block, ch), (bus_sums[ch], in_index))
            else:
                for ch in self.__channels:
                    self.__graph.connect(
                        (in_block, ch),
                        # TODO pool these resamplers
                        make_resampler(in_rate, self.__bus_rate),
                        (bus_sums[ch], in_index),
                    )
            in_index += 1

        if in_index > 0:
            # connect output only if there is at least one input
            if len(outputs) > 0:
                used_resamplers = set()
                for out_rate, out_block in outputs:
                    if out_rate == self.__bus_rate:
                        for ch in self.__channels:
                            self.__graph.connect(bus_sums[ch], (out_block, ch))
                    else:
                        if out_rate not in self.__resampler_cache:
                            # Moderately expensive due to the internals using optfir
                            log.msg("Constructing resampler for audio rate %i" % out_rate)
                            self.__resampler_cache[out_rate] = tuple(
                                make_resampler(self.__bus_rate, out_rate) for _ in self.__channels
                            )
                        resamplers = self.__resampler_cache[out_rate]
                        used_resamplers.add(resamplers)
                        for ch in self.__channels:
                            self.__graph.connect(resamplers[ch], (out_block, ch))
                for resamplers in used_resamplers:
                    for ch in self.__channels:
                        self.__graph.connect(bus_sums[ch], resamplers[ch])
            else:
                # gnuradio requires at least one connected output
                for ch in self.__channels:
                    self.__graph.connect(bus_sums[ch], blocks.null_sink(gr.sizeof_float))
Example #21
0
    def connect(self, inputs, outputs):
        """
        Make all new connections (graph.disconnect_all() must have been done) between inputs and outputs.
        
        inputs and outputs must be iterables of (sample_rate, block) tuples.
        """
        inputs = list(inputs)
        outputs = list(outputs)

        # Determine bus rate.
        # The bus obviously does not need to be higher than the rate of any bus input, because that would be extraneous data. It also does not need to be higher than the rate of any bus output, because no output has use for the information.
        max_in_rate = max(
            (rate for rate, _ in inputs)) if len(inputs) > 0 else 0.0
        max_out_rate = max(
            (rate for rate, _ in outputs)) if len(outputs) > 0 else 0.0
        new_bus_rate = min(max_out_rate, max_in_rate)
        if new_bus_rate == 0.0:
            # There are either no inputs or no outputs. Use the other side's rate so we have a well-defined value.
            new_bus_rate = max(max_out_rate, max_in_rate)
        if new_bus_rate == 0.0:
            # There are both no inputs and no outputs. No point in not keeping the old rate (and its resampler cache).
            new_bus_rate = self.__bus_rate
        elif new_bus_rate != self.__bus_rate:
            self.__bus_rate = new_bus_rate
            self.__resampler_cache.clear()

        # recreated each time because reusing an add_ff w/ different
        # input counts fails; TODO: report/fix bug
        bus_sums = [blocks.add_ff() for _ in self.__channels]

        in_index = 0
        for in_rate, in_block in inputs:
            if in_rate == self.__bus_rate:
                for ch in self.__channels:
                    self.__graph.connect((in_block, ch),
                                         (bus_sums[ch], in_index))
            else:
                for ch in self.__channels:
                    self.__graph.connect(
                        (in_block, ch),
                        # TODO pool these resamplers
                        make_resampler(in_rate, self.__bus_rate),
                        (bus_sums[ch], in_index))
            in_index += 1

        if in_index > 0:
            # connect output only if there is at least one input
            if len(outputs) > 0:
                used_resamplers = set()
                for out_rate, out_block in outputs:
                    if out_rate == self.__bus_rate:
                        for ch in self.__channels:
                            self.__graph.connect(bus_sums[ch], (out_block, ch))
                    else:
                        if out_rate not in self.__resampler_cache:
                            # Moderately expensive due to the internals using optfir
                            log.msg(
                                'Constructing resampler for audio rate %i' %
                                out_rate)
                            self.__resampler_cache[out_rate] = tuple(
                                make_resampler(self.__bus_rate, out_rate)
                                for _ in self.__channels)
                        resamplers = self.__resampler_cache[out_rate]
                        used_resamplers.add(resamplers)
                        for ch in self.__channels:
                            self.__graph.connect(resamplers[ch],
                                                 (out_block, ch))
                for resamplers in used_resamplers:
                    for ch in self.__channels:
                        self.__graph.connect(bus_sums[ch], resamplers[ch])
            else:
                # gnuradio requires at least one connected output
                for ch in self.__channels:
                    self.__graph.connect(bus_sums[ch],
                                         blocks.null_sink(gr.sizeof_float))
Example #22
0
 def __init__(self, name, add_transmitters):
     gr.hier_block2.__init__(
         self, defaultstr(type(self).__name__ + ' ' + 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
     if add_transmitters:
         add_modulator(0.0, 'usb', 'USB')
         add_modulator(10e3, 'am', 'AM')
         add_modulator(30e3, 'fm', 'NFM')
         add_modulator(50e3, 'rtty', 'RTTY', message='The quick brown fox jumped over the lazy dog.\n')
         add_modulator(80e3, 'chirp', ChirpModulator)
     
     if signals:
         for bus_input, signal in enumerate(signals):
             self.connect(signal, (self.__bus, bus_input))
     else:
         # kludge up a correct-sample-rate no-op
         self.connect(
             audio_signal,
             blocks.multiply_const_ff(0),
             make_resampler(audio_rate, rf_rate),
             blocks.float_to_complex(),
             self.__bus)
     
     self.__signal_type = SignalType(
         kind='IQ',
         sample_rate=rf_rate)
     self.__usable_bandwidth = RangeT([(-rf_rate / 2, rf_rate / 2)])