示例#1
0
class PollerCellsSpecimen(ExportedState):
    """Helper for TestPoller"""
    foo = None
    
    def __init__(self):
        self.subscribable = LooseCell(key='subscribable', value='', type=str)
    
    def state_def(self, callback):
        super(PollerCellsSpecimen, self).state_def(callback)
        # TODO make this possible to be decorator style
        callback(self.subscribable)
    
    # force worst-case
    def state_is_dynamic(self):
        return True
    
    @exported_value()
    def get_foo(self):
        return self.foo

    @setter
    def set_foo(self, value):
        self.foo = value

    def get_subscribable(self):
        return self.subscribable.get()
    
    def set_subscribable(self, value):
        self.subscribable.set(value)
示例#2
0
class _OsmoSDRTuning(object):
    def __init__(self, profile, correction_ppm, osmo_block):
        self.__profile = profile
        self.__correction_ppm = correction_ppm
        self.__osmo_block = osmo_block
        self.__vfo_cell = LooseCell(
            key='freq',
            value=0.0,
            # TODO: Eventually we'd like to be able to make the freq range vary dynamically with the correction setting
            type=convert_osmosdr_range(
                osmo_block.get_freq_range(ch),
                strict=False,
                transform=self.from_hardware_freq,
                unit=units.Hz,
                add_zero=profile.e4000),
            writable=True,
            persists=True,
            post_hook=self.__set_freq)
    
    def __set_freq(self, freq):
        self.__osmo_block.set_center_freq(self.to_hardware_freq(freq))
        
    def to_hardware_freq(self, effective_freq):
        if abs(effective_freq) < 1e-2 and self.__profile.e4000:
            # Quirk: Tuning to 3686.6-3730 MHz on the E4000 causes operation effectively at 0Hz.
            # Original report: <http://www.reddit.com/r/RTLSDR/comments/12d2wc/a_very_surprising_discovery/>
            return 3700e6
        else:
            return effective_freq * (1 - 1e-6 * self.__correction_ppm)
    
    def from_hardware_freq(self, freq):
        freq = freq / (1 - 1e-6 * self.__correction_ppm)
        if 3686.6e6 <= freq <= 3730e6 and self.__profile.e4000:
            freq = 0.0
        return freq
    
    def get_vfo_cell(self):
        return self.__vfo_cell

    def get_correction_ppm(self):
        return self.__correction_ppm
    
    def set_correction_ppm(self, value):
        self.__correction_ppm = float(value)
        # Not using the osmosdr feature because changing it at runtime produces glitches like the sample rate got changed; therefore we emulate it ourselves. TODO: I am informed that using set_freq_corr can correct sample-clock error, so we ought to at least use it on init.
        # self.osmosdr_source_block.set_freq_corr(value, 0)
        self.__set_freq(self.__vfo_cell.get())
    
    def calc_usable_bandwidth(self, sample_rate):
        passband = sample_rate * (3 / 8)  # 3/4 of + and - halves
        if self.__profile.dc_offset:
            epsilon = 1.0  # RangeT has only inclusive bounds, so we need a nonzero value.
            return RangeT([(-passband, -epsilon), (epsilon, passband)])
        else:
            return RangeT([(-passband, passband)])
    
    def set_block(self, value):
        self.__osmo_block = value
        if self.__osmo_block is not None:
            self.__set_freq(self.__vfo_cell.get())
示例#3
0
class PollerCellsSpecimen(ExportedState):
    """Helper for TestPoller"""
    foo = None
    
    def __init__(self):
        self.subscribable = LooseCell(key='subscribable', value='', type=str)
    
    def state_def(self, callback):
        super(PollerCellsSpecimen, self).state_def(callback)
        # TODO make this possible to be decorator style
        callback(self.subscribable)
    
    # force worst-case
    def state_is_dynamic(self):
        return True
    
    @exported_value(changes='continuous', persists=False)
    def get_foo(self):
        return self.foo

    @setter
    def set_foo(self, value):
        self.foo = value

    def get_subscribable(self):
        return self.subscribable.get()
    
    def set_subscribable(self, value):
        self.subscribable.set(value)
示例#4
0
class PollerCellsSpecimen(ExportedState):
    """Helper for TestPoller"""
    foo = None
    
    def __init__(self):
        self.subscribable = LooseCell(value='', type=str, writable=True)
    
    def state_def(self):
        for d in super(PollerCellsSpecimen, self).state_def():
            yield d
        # TODO make this possible to be decorator style
        yield 'subscribable', self.subscribable
    
    # force worst-case
    def state_is_dynamic(self):
        return True
    
    @exported_value(changes='continuous', persists=False)
    def get_foo(self):
        return self.foo

    @setter
    def set_foo(self, value):
        self.foo = value

    def get_subscribable(self):
        return self.subscribable.get()
    
    def set_subscribable(self, value):
        self.subscribable.set(value)
示例#5
0
    def __init_center_cell(self):
        base_freq_cell = self.__rx_main.state()[_FREQ_CELL_KEY]
        mode_cell = self.__rx_main.state()['MD']
        sidetone_cell = self.state()['CW']
        iq_offset_cell = LooseCell(key='iq_offset', value=0.0, type=float)

        self.__iq_center_cell = ViewCell(
            base=base_freq_cell,
            get_transform=lambda x: x + iq_offset_cell.get(),
            set_transform=lambda x: x - iq_offset_cell.get(),
            key=_FREQ_CELL_KEY,
            type=base_freq_cell.type(),  # runtime variable...
            writable=True,
            persists=base_freq_cell.metadata().persists)

        def changed_iq(_value=None):
            # TODO this is KX3-specific
            mode = mode_cell.get()
            if mode == 'CW':
                iq_offset = sidetone_cell.get()
            elif mode == 'CW-REV':
                iq_offset = -sidetone_cell.get()
            elif mode == 'AM' or mode == 'FM':
                iq_offset = 11000.0
            else:  # USB, LSB, other
                iq_offset = 0.0
            iq_offset_cell.set(iq_offset)
            self.__iq_center_cell.changed_transform()

        # TODO bad practice
        mode_cell._subscribe_immediate(changed_iq)
        sidetone_cell._subscribe_immediate(changed_iq)
        changed_iq()
示例#6
0
 def setUp(self):
     self.lc = LooseCell(value=0, key='a', ctor=int)
     self.vc = ViewCell(base=self.lc,
                        get_transform=lambda x: x + 1,
                        set_transform=lambda x: x - 1,
                        key='b',
                        ctor=int)
示例#7
0
 def setUp(self):
     self.lc = LooseCell(value=0, type=RangeT([(-100, 100)]))
     self.delta = 1
     self.vc = ViewCell(base=self.lc,
                        get_transform=lambda x: x + self.delta,
                        set_transform=lambda x: x - self.delta,
                        type=int)
示例#8
0
class _OsmoSDRTuning(object):
    def __init__(self, profile, correction_ppm, osmo_block):
        self.__profile = profile
        self.__correction_ppm = correction_ppm
        self.__osmo_block = osmo_block
        self.__vfo_cell = LooseCell(
            key='freq',
            value=0.0,
            # TODO: Eventually we'd like to be able to make the freq range vary dynamically with the correction setting
            type=convert_osmosdr_range(
                osmo_block.get_freq_range(ch),
                strict=False,
                transform=self.from_hardware_freq,
                unit=units.Hz,
                add_zero=profile.e4000),
            writable=True,
            persists=True,
            post_hook=self.__set_freq)
    
    def __set_freq(self, freq):
        self.__osmo_block.set_center_freq(self.to_hardware_freq(freq))
        
    def to_hardware_freq(self, effective_freq):
        if abs(effective_freq) < 1e-2 and self.__profile.e4000:
            # Quirk: Tuning to 3686.6-3730 MHz on the E4000 causes operation effectively at 0Hz.
            # Original report: <http://www.reddit.com/r/RTLSDR/comments/12d2wc/a_very_surprising_discovery/>
            return 3700e6
        else:
            return effective_freq * (1 - 1e-6 * self.__correction_ppm)
    
    def from_hardware_freq(self, freq):
        freq = freq / (1 - 1e-6 * self.__correction_ppm)
        if 3686.6e6 <= freq <= 3730e6 and self.__profile.e4000:
            freq = 0.0
        return freq
    
    def get_vfo_cell(self):
        return self.__vfo_cell

    def get_correction_ppm(self):
        return self.__correction_ppm
    
    def set_correction_ppm(self, value):
        self.__correction_ppm = float(value)
        # Not using the osmosdr feature because changing it at runtime produces glitches like the sample rate got changed; therefore we emulate it ourselves. TODO: I am informed that using set_freq_corr can correct sample-clock error, so we ought to at least use it on init.
        # self.osmosdr_source_block.set_freq_corr(value, 0)
        self.__set_freq(self.__vfo_cell.get())
    
    def calc_usable_bandwidth(self, sample_rate):
        passband = sample_rate * (3 / 8)  # 3/4 of + and - halves
        if self.__profile.dc_offset:
            epsilon = 1.0  # TODO: Put width in the profile.
            return RangeT([(-passband, -epsilon), (epsilon, passband)])
        else:
            return RangeT([(-passband, passband)])
    
    def set_block(self, value):
        self.__osmo_block = value
        if self.__osmo_block is not None:
            self.__set_freq(self.__vfo_cell.get())
示例#9
0
 def __init__(self, lime_block):
     self.__lime_block = lime_block
     self.__vfo_cell = LooseCell(value=0.0,
                                 type=RangeT([(10e6, 3500e6)],
                                             strict=False,
                                             unit=units.Hz),
                                 writable=True,
                                 persists=True,
                                 post_hook=self.__set_freq)
示例#10
0
 def setUp(self):
     self.lc = LooseCell(value=0, type=RangeT([(-100, 100)]), writable=True)
     self.delta = 1
     self.vc = ViewCell(base=self.lc,
                        get_transform=lambda x: x + self.delta,
                        set_transform=lambda x: x - self.delta,
                        type=int,
                        writable=True,
                        interest_tracker=LoopbackInterestTracker())
示例#11
0
    def __init__(self,
                 signal_type=None,
                 enable_scope=False,
                 freq_resolution=4096,
                 time_length=2048,
                 window_type=windows.WIN_BLACKMAN_HARRIS,
                 frame_rate=30.0,
                 input_center_freq=0.0,
                 paused=False,
                 context=None):
        assert isinstance(signal_type, SignalType)
        assert context is not None

        itemsize = signal_type.get_itemsize()
        gr.hier_block2.__init__(
            self,
            type(self).__name__,
            gr.io_signature(1, 1, itemsize),
            gr.io_signature(0, 0, 0),
        )

        # constant parameters
        self.__power_offset = 40  # TODO autoset or controllable
        self.__itemsize = itemsize
        self.__context = context
        self.__enable_scope = enable_scope

        # settable parameters
        self.__signal_type = signal_type
        self.__freq_resolution = int(freq_resolution)
        self.__time_length = int(time_length)
        self.__window_type = _window_type_enum(window_type)
        self.__frame_rate = float(frame_rate)
        self.__input_center_freq = float(input_center_freq)
        self.__paused = bool(paused)

        # interest tracking
        # this is indirect because we ignore interest when paused
        self.__interested_cell = LooseCell(type=bool,
                                           value=False,
                                           writable=False,
                                           persists=False)
        self.__has_subscriptions = False
        self.__interest = InterestTracker(self.__cell_interest_callback)

        self.__fft_queue = gr.msg_queue()
        self.__scope_queue = gr.msg_queue()

        # stuff created by __do_connect
        self.__gate = None
        self.__fft_sink = None
        self.__scope_sink = None
        self.__frame_dec = None
        self.__frame_rate_to_decimation_conversion = 0.0

        self.__do_connect()
示例#12
0
文件: blocks.py 项目: b8box/shinysdr
    def __init__(self,
                 signal_type=None,
                 enable_scope=False,
                 freq_resolution=4096,
                 time_length=2048,
                 frame_rate=30.0,
                 input_center_freq=0.0,
                 paused=False,
                 context=None):
        assert isinstance(signal_type, SignalType)
        assert context is not None

        itemsize = signal_type.get_itemsize()
        gr.hier_block2.__init__(
            self,
            type(self).__name__,
            gr.io_signature(1, 1, itemsize),
            gr.io_signature(0, 0, 0),
        )

        # constant parameters
        self.__power_offset = 40  # TODO autoset or controllable
        self.__itemsize = itemsize
        self.__context = context
        self.__enable_scope = enable_scope

        # settable parameters
        self.__signal_type = signal_type
        self.__freq_resolution = int(freq_resolution)
        self.__time_length = int(time_length)
        self.__frame_rate = float(frame_rate)
        self.__input_center_freq = float(input_center_freq)
        self.__paused = bool(paused)

        self.__interested_cell = LooseCell(key='interested',
                                           type=bool,
                                           value=False,
                                           writable=False,
                                           persists=False)

        # blocks
        self.__gate = None
        self.__fft_sink = None
        self.__scope_sink = None
        self.__scope_chunker = None
        self.__before_fft = None
        self.__logpwrfft = None
        self.__overlapper = None

        self.__rebuild()
        self.__connect()
示例#13
0
 def __init_center_cell(self):
     base_freq_cell = self.__rx_main.state()[_FREQ_CELL_KEY]
     mode_cell = self.__rx_main.state()['MD']
     sidetone_cell = self.state()['CW']
     submode_cell = self.state()['DT']
     iq_offset_cell = LooseCell(key='iq_offset', value=0.0, type=float)
     
     self.__iq_center_cell = ViewCell(
             base=base_freq_cell,
             get_transform=lambda x: x + iq_offset_cell.get(),
             set_transform=lambda x: x - iq_offset_cell.get(),
             key=_FREQ_CELL_KEY,
             type=base_freq_cell.type(),  # runtime variable...
             writable=True,
             persists=base_freq_cell.metadata().persists)
     
     def changed_iq(_value=None):
         # TODO this is KX3-specific
         mode = mode_cell.get()
         if mode == 'CW':
             iq_offset = sidetone_cell.get()
         elif mode == 'CW-REV':
             iq_offset = -sidetone_cell.get()
         elif mode == 'AM' or mode == 'FM':
             iq_offset = 11000.0
         elif mode == 'DATA' or mode == 'DATA-REV':
             submode = submode_cell.get()
             if submode == 0:  # "DATA A", SSB with less processing
                 iq_offset = 0.0  # ???
             elif submode == 1:  # "AFSK A", SSB with RTTY style filter
                 iq_offset = 0.0  # ???
             elif submode == 2:  # "FSK D", RTTY
                 iq_offset = 900.0
             elif submode == 3:  # "PSK D", PSK31
                 iq_offset = 1000.0  # I think so...
             else:
                 iq_offset = 0  # fallback
             if mode == 'DATA-REV':
                 iq_offset = -iq_offset
         else:  # USB, LSB, other
             iq_offset = 0.0
         iq_offset_cell.set(iq_offset)
         self.__iq_center_cell.changed_transform()
     
     # TODO bad practice
     mode_cell._subscribe_immediate(changed_iq)
     sidetone_cell._subscribe_immediate(changed_iq)
     submode_cell._subscribe_immediate(changed_iq)
     changed_iq()
示例#14
0
 def test_specify_all_metadata(self):
     # using LooseCell as an arbitrary concrete subclass
     cell = LooseCell(
         value=0,
         type=int,
         persists=False,  # the non-default value
         label='mylabel',
         description='mydescription',
         sort_key='mysortkey')
     self.assertEqual(cell.metadata().value_type, to_value_type(int))
     self.assertEqual(cell.metadata().persists, False)
     self.assertEqual(cell.metadata().naming, EnumRow(
         label='mylabel',
         description='mydescription',
         sort_key='mysortkey'))
示例#15
0
 def test_specify_all_metadata(self):
     # using LooseCell as an arbitrary concrete subclass
     cell = LooseCell(
         value=0,
         type=int,
         persists=False,  # the non-default value
         label='mylabel',
         description='mydescription',
         sort_key='mysortkey')
     self.assertEqual(cell.metadata().value_type, to_value_type(int))
     self.assertEqual(cell.metadata().persists, False)
     self.assertEqual(cell.metadata().naming, EnumRow(
         label='mylabel',
         description='mydescription',
         sort_key='mysortkey'))
示例#16
0
 def __init__(self, profile, correction_ppm, osmo_block):
     self.__profile = profile
     self.__correction_ppm = correction_ppm
     self.__osmo_block = osmo_block
     self.__vfo_cell = LooseCell(
         key='freq',
         value=0.0,
         # TODO: Eventually we'd like to be able to make the freq range vary dynamically with the correction setting
         type=convert_osmosdr_range(osmo_block.get_freq_range(ch),
                                    strict=False,
                                    transform=self.from_hardware_freq,
                                    add_zero=profile.e4000),
         writable=True,
         persists=True,
         post_hook=self.__set_freq)
示例#17
0
    def __init_center_cell(self):
        base_freq_cell = self.__rx_main.state()[_FREQ_CELL_KEY]
        mode_cell = self.__rx_main.state()['MD']
        sidetone_cell = self.state()['CW']
        submode_cell = self.state()['DT']
        iq_offset_cell = LooseCell(value=0.0, type=float, writable=True)

        self.__iq_center_cell = ViewCell(
            base=base_freq_cell,
            get_transform=lambda x: x + iq_offset_cell.get(),
            set_transform=lambda x: x - iq_offset_cell.get(),
            type=base_freq_cell.type(),  # runtime variable...
            writable=True,
            persists=base_freq_cell.metadata().persists)

        def changed_iq(_value=None):
            # TODO this is KX3-specific
            mode = mode_cell.get()
            if mode == 'CW':
                iq_offset = sidetone_cell.get()
            elif mode == 'CW-REV':
                iq_offset = -sidetone_cell.get()
            elif mode == 'AM' or mode == 'FM':
                iq_offset = 11000.0
            elif mode == 'DATA' or mode == 'DATA-REV':
                submode = submode_cell.get()
                if submode == 0:  # "DATA A", SSB with less processing
                    iq_offset = 0.0  # ???
                elif submode == 1:  # "AFSK A", SSB with RTTY style filter
                    iq_offset = 0.0  # ???
                elif submode == 2:  # "FSK D", RTTY
                    iq_offset = 900.0
                elif submode == 3:  # "PSK D", PSK31
                    iq_offset = 1000.0  # I think so...
                else:
                    iq_offset = 0  # fallback
                if mode == 'DATA-REV':
                    iq_offset = -iq_offset
            else:  # USB, LSB, other
                iq_offset = 0.0
            iq_offset_cell.set(iq_offset)
            self.__iq_center_cell.changed_transform()

        # TODO bad practice
        mode_cell._subscribe_immediate(changed_iq)
        sidetone_cell._subscribe_immediate(changed_iq)
        submode_cell._subscribe_immediate(changed_iq)
        changed_iq()
示例#18
0
class _LimeSDRTuning(object):
    def __init__(self, lime_block):
        self.__lime_block = lime_block
        self.__vfo_cell = LooseCell(value=0.0,
                                    type=RangeT([(10e6, 3500e6)],
                                                strict=False,
                                                unit=units.Hz),
                                    writable=True,
                                    persists=True,
                                    post_hook=self.__set_freq)

    def __set_freq(self, freq):
        self.__lime_block.set_rf_freq(freq)

    def get_vfo_cell(self):
        return self.__vfo_cell

    def calc_usable_bandwidth(self, total_bandwidth):
        # Assume right up against the edges of the filter are unusable.
        passband = total_bandwidth * (3 / 8)  # 3/4 of + and - halves
        return RangeT([(-passband, passband)])

    def set_block(self, value):
        self.__lime_block = value
        if self.__lime_block is not None:
            self.__set_freq(self.__vfo_cell.get())
示例#19
0
class _LimeSDRTuning(object):
    def __init__(self, lime_block):
        self.__lime_block = lime_block
        self.__vfo_cell = LooseCell(
            value=0.0,
            type=RangeT([(10e6, 3500e6)],
                        strict=False,
                        unit=units.Hz),
            writable=True,
            persists=True,
            post_hook=self.__set_freq)
    
    def __set_freq(self, freq):
        self.__lime_block.set_rf_freq(freq)
        
    def get_vfo_cell(self):
        return self.__vfo_cell

    def calc_usable_bandwidth(self, total_bandwidth):
        # Assume right up against the edges of the filter are unusable.
        passband = total_bandwidth * (3 / 8)  # 3/4 of + and - halves
        return RangeT([(-passband, passband)])
    
    def set_block(self, value):
        self.__lime_block = value
        if self.__lime_block is not None:
            self.__set_freq(self.__vfo_cell.get())
示例#20
0
 def test_vfos(self):
     d = merge_devices([
         Device(vfo_cell=_ConstantVFOCell(1)),
         Device(vfo_cell=LooseCell(
             value=0, type=RangeT([(10, 20)]), writable=True))
     ])
     self.assertTrue(d.get_vfo_cell().isWritable())
示例#21
0
def AudioDevice(
        rx_device='',  # may be used positionally, not recommented
        tx_device=None,
        name=None,
        sample_rate=44100,
        quadrature_as_stereo=False):
    rx_device = str(rx_device)
    if tx_device is not None:
        tx_device = str(tx_device)

    if name is None:
        full_name = u'Audio ' + rx_device
        if tx_device is not None:
            full_name += '/' + tx_device
    else:
        full_name = unicode(name)

    rx_driver = _AudioRXDriver(device_name=rx_device,
                               sample_rate=sample_rate,
                               quadrature_as_stereo=quadrature_as_stereo)
    if tx_device is not None:
        tx_driver = _AudioTXDriver(device_name=tx_device,
                                   sample_rate=sample_rate,
                                   quadrature_as_stereo=quadrature_as_stereo)
    else:
        tx_driver = nullExportedState

    return Device(name=full_name,
                  vfo_cell=LooseCell(key='freq',
                                     value=0.0,
                                     ctor=Range([(0.0, 0.0)]),
                                     writable=True,
                                     persists=False),
                  rx_driver=rx_driver,
                  tx_driver=tx_driver)
示例#22
0
def _ConstantVFOCell(value):
    value = float(value)
    return LooseCell(key='freq',
                     value=value,
                     ctor=Range([(value, value)]),
                     writable=False,
                     persists=False)
示例#23
0
def _ConstantVFOCell(value):
    value = float(value)
    return LooseCell(
        value=value,
        type=RangeT([(value, value)]),
        writable=False,
        persists=False)
示例#24
0
 def __init__(self, adapter, freq):
     self.__adapter = adapter
     self.__freq_cell = LooseCell(
         value=freq,
         type=float,
         persists=False,
         writable=False)
示例#25
0
def SimulatedDevice(name='Simulated RF', freq=0.0):
    return Device(name=name,
                  vfo_cell=LooseCell(key='freq',
                                     value=freq,
                                     ctor=Range([(freq, freq)]),
                                     writable=True,
                                     persists=False),
                  rx_driver=_SimulatedRXDriver(name))
示例#26
0
 def setUp(self):
     self.lc = LooseCell(value=0, type=RangeT([(-100, 100)]))
     self.delta = 1
     self.vc = ViewCell(
         base=self.lc,
         get_transform=lambda x: x + self.delta,
         set_transform=lambda x: x - self.delta,
         type=int)
示例#27
0
def _RetuningTestDevice(freq, has_dc_offset):
    return Device(
        rx_driver=_RetuningTestRXDriver(has_dc_offset),
        vfo_cell=LooseCell(
            value=freq,
            type=RangeT([(-1e9, 1e9)]),  # TODO kludge magic numbers
            writable=True,
            persists=False))
示例#28
0
 def setUp(self):
     self.lc = LooseCell(value=0, key='a', type=int)
     self.vc = ViewCell(
         base=self.lc,
         get_transform=lambda x: x + 1,
         set_transform=lambda x: x - 1,
         key='b',
         type=int)
示例#29
0
文件: blocks.py 项目: kpreid/shinysdr
    def __init__(self,
            signal_type=None,
            enable_scope=False,
            freq_resolution=4096,
            time_length=2048,
            window_type=windows.WIN_BLACKMAN_HARRIS,
            frame_rate=30.0,
            input_center_freq=0.0,
            paused=False,
            context=None):
        assert isinstance(signal_type, SignalType)
        assert context is not None
        
        itemsize = signal_type.get_itemsize()
        gr.hier_block2.__init__(
            self, type(self).__name__,
            gr.io_signature(1, 1, itemsize),
            gr.io_signature(0, 0, 0),
        )
        
        # constant parameters
        self.__power_offset = 40  # TODO autoset or controllable
        self.__itemsize = itemsize
        self.__context = context
        self.__enable_scope = enable_scope
        
        # settable parameters
        self.__signal_type = signal_type
        self.__freq_resolution = int(freq_resolution)
        self.__time_length = int(time_length)
        self.__window_type = _window_type_enum(window_type)
        self.__frame_rate = float(frame_rate)
        self.__input_center_freq = float(input_center_freq)
        self.__paused = bool(paused)
        
        # interest tracking
        # this is indirect because we ignore interest when paused
        self.__interested_cell = LooseCell(type=bool, value=False, writable=False, persists=False)
        self.__has_subscriptions = False
        self.__interest = InterestTracker(self.__cell_interest_callback)

        self.__fft_cell = ElementSinkCell(
            info_getter=self._get_fft_info,
            type=BulkDataT(array_format='b', info_format='dff'),
            interest_tracker=self.__interest,
            label='Spectrum')
        self.__scope_cell = ElementSinkCell(
            info_getter=self._get_scope_info,
            type=BulkDataT(array_format='f', info_format='d'),
            interest_tracker=self.__interest,
            label='Scope')
        
        # stuff created by __do_connect
        self.__gate = None
        self.__frame_dec = None
        self.__frame_rate_to_decimation_conversion = 0.0
        
        self.__do_connect()
示例#30
0
class TestViewCell(unittest.TestCase):
    def setUp(self):
        self.lc = LooseCell(value=0, key='a', type=int)
        self.vc = ViewCell(
            base=self.lc,
            get_transform=lambda x: x + 1,
            set_transform=lambda x: x - 1,
            key='b',
            type=int)
    
    def test_get_set(self):
        self.assertEqual(0, self.lc.get())
        self.assertEqual(1, self.vc.get())
        self.vc.set(2)
        self.assertEqual(1, self.lc.get())
        self.assertEqual(2, self.vc.get())
        self.lc.set(3)
        self.assertEqual(3, self.lc.get())
        self.assertEqual(4, self.vc.get())
    
    def test_subscription(self):
        fired = []
        
        def f():
            fired.append(self.vc.get())
        
        self.vc.subscribe(f)
        self.lc.set(1)
        self.assertEqual([2], fired)
示例#31
0
class TestViewCell(unittest.TestCase):
    def setUp(self):
        self.lc = LooseCell(value=0, key='a', type=int)
        self.vc = ViewCell(
            base=self.lc,
            get_transform=lambda x: x + 1,
            set_transform=lambda x: x - 1,
            key='b',
            type=int)
    
    def test_get_set(self):
        self.assertEqual(0, self.lc.get())
        self.assertEqual(1, self.vc.get())
        self.vc.set(2)
        self.assertEqual(1, self.lc.get())
        self.assertEqual(2, self.vc.get())
        self.lc.set(3)
        self.assertEqual(3, self.lc.get())
        self.assertEqual(4, self.vc.get())
    
    def test_subscription(self):
        fired = []
        
        def f():
            fired.append(self.vc.get())
        
        self.vc.subscribe(f)
        self.lc.set(1)
        self.assertEqual([2], fired)
示例#32
0
    def __init__(self):
        self.messages = []
        # 12,345,678 Hz, all the time, every day.
        self.__absolute_frequency_cell = LooseCell(value=12345678,
                                                   type=float,
                                                   writable=False,
                                                   persists=False)

        verifyObject(IDemodulatorContext, self)  # Ensure we are a good fake.
示例#33
0
 def _install_cells(self, callback, send, encoding):
     callback(
         LooseCell(
             key=self.__name,
             type=self.__type,
             value=u'',
             writable=True,
             persists=True,
             post_hook=lambda value: send(unicode(value).encode(encoding))))
示例#34
0
 def _cells(self, send, encoding):
     # TODO: Autogenerate unique keys instead of requiring __name to be unique.
     yield self.__name, LooseCell(
         type=self.__type,
         value=u'',
         writable=True,
         persists=True,
         post_hook=lambda value: send(unicode(value).encode(encoding)),
         label=self.__name)
示例#35
0
 def setUp(self):
     self.lc = LooseCell(value=0, type=RangeT([(-100, 100)]), writable=True)
     self.delta = 1
     self.vc = ViewCell(
         base=self.lc,
         get_transform=lambda x: x + self.delta,
         set_transform=lambda x: x - self.delta,
         type=int,
         writable=True,
         interest_tracker=LoopbackInterestTracker())
示例#36
0
def SimulatedDevice(name='Simulated RF', freq=0.0, allow_tuning=False):
    return Device(
        name=name,
        vfo_cell=LooseCell(
            key='freq',
            value=freq,
            ctor=Range([(-1e9, 1e9)]) if allow_tuning else Range([(freq, freq)]),  # TODO kludge magic numbers
            writable=True,
            persists=False),
        rx_driver=_SimulatedRXDriver(name))
示例#37
0
 def __init__(self, lime_block):
     self.__lime_block = lime_block
     self.__vfo_cell = LooseCell(
         value=0.0,
         type=RangeT([(10e6, 3500e6)],
                     strict=False,
                     unit=units.Hz),
         writable=True,
         persists=True,
         post_hook=self.__set_freq)
示例#38
0
    def make_cell(self, protocol, is_sub):
        key = self.__command_name

        def send(value):
            protocol.send_command(
                _format_command(key,
                                self.__syntax.format(value),
                                is_sub=is_sub))

        if self.__has_sub == (is_sub is not None):
            return key, LooseCell(post_hook=send, **self.__cell_kwargs)
示例#39
0
 def _install_cells(self, callback, send, encoding):
     callback(
         LooseCell(
             # TODO: Autogenerate unique keys instead of requiring __name to be unique.
             key=self.__name,
             type=self.__type,
             value=u'',
             writable=True,
             persists=True,
             post_hook=lambda value: send(unicode(value).encode(encoding)),
             label=self.__name))
示例#40
0
def _install_cell(self, name, is_level, writable, callback, caps):
    # this is a function for the sake of the closure variables
    
    if name == 'Frequency':
        cell_name = 'freq'  # consistency with our naming scheme elsewhere, also IHasFrequency
    else:
        cell_name = name
    
    if is_level:
        # TODO: Use range info from hamlib if available
        if name == 'STRENGTH level':
            vtype = Range([(-54, 50)], strict=False)
        elif name == 'SWR level':
            vtype = Range([(1, 30)], strict=False)
        elif name == 'RFPOWER level':
            vtype = Range([(0, 100)], strict=False)
        else:
            vtype = Range([(-10, 10)], strict=False)
    elif name == 'Mode' or name == 'TX Mode':
        # kludge
        vtype = Enum({x: x for x in caps['Mode list'].strip().split(' ')})
    elif name == 'VFO' or name == 'TX VFO':
        vtype = Enum({x: x for x in caps['VFO list'].strip().split(' ')})
    else:
        vtype = self._info[name]
    
    def updater(strval):
        try:
            if vtype is bool:
                value = bool(int(strval))
            else:
                value = vtype(strval)
        except ValueError:
            value = unicode(strval)
        cell.set_internal(value)
    
    def actually_write_value(value):
        if vtype is bool:
            self._ehs_set(name, str(int(value)))
        else:
            self._ehs_set(name, str(vtype(value)))
    
    cell = LooseCell(
        key=cell_name,
        value='placeholder',
        type=vtype,
        writable=writable,
        persists=False,
        post_hook=actually_write_value,
        label=name)  # TODO: supply label values from _info table
    self._cell_updaters[name] = updater
    updater(self._ehs_get(name))
    callback(cell)
示例#41
0
 def receive(self, message_wrapper):
     """Implements ITelemetryObject."""
     self.__last_heard_time = message_wrapper.receive_time
     for k, v in message_wrapper.message.iteritems():
         if _message_field_is_id.get(k, False) or k == u'time':
             continue
         if k not in self.__cells:
             self.__cells[k] = LooseCell(key=k,
                                         value=None,
                                         type=object,
                                         writable=False,
                                         persists=False)
         self.__cells[k].set_internal(v)
示例#42
0
	def __init__(self, profile, correction_ppm, source):
		self.__profile = profile
		self.__correction_ppm = correction_ppm
		self.__source = source
		self.__vfo_cell = LooseCell(
			key='freq',
			value=0.0,
			# TODO: Eventually we'd like to be able to make the freq range vary dynamically with the correction setting
			ctor=convert_osmosdr_range(
				source.get_freq_range(ch),
				strict=False,
				transform=self.from_hardware_freq,
				add_zero=profile.e4000),
			writable=True,
			persists=True,
			post_hook=self.__set_freq)
示例#43
0
 def __init__(self, profile, correction_ppm, osmo_block):
     self.__profile = profile
     self.__correction_ppm = correction_ppm
     self.__osmo_block = osmo_block
     self.__vfo_cell = LooseCell(
         value=0.0,
         # TODO: Eventually we'd like to be able to make the freq range vary dynamically with the correction setting
         type=convert_osmosdr_range(
             osmo_block.get_freq_range(ch),
             strict=False,
             transform=self.from_hardware_freq,
             unit=units.Hz,
             add_zero=profile.e4000),
         writable=True,
         persists=True,
         post_hook=self.__set_freq)
示例#44
0
 def __init__(self,
         signal_type=None,
         enable_scope=False,
         freq_resolution=4096,
         time_length=2048,
         frame_rate=30.0,
         input_center_freq=0.0,
         paused=False,
         context=None):
     assert isinstance(signal_type, SignalType)
     assert context is not None
     
     itemsize = signal_type.get_itemsize()
     gr.hier_block2.__init__(
         self, type(self).__name__,
         gr.io_signature(1, 1, itemsize),
         gr.io_signature(0, 0, 0),
     )
     
     # constant parameters
     self.__power_offset = 40  # TODO autoset or controllable
     self.__itemsize = itemsize
     self.__context = context
     self.__enable_scope = enable_scope
     
     # settable parameters
     self.__signal_type = signal_type
     self.__freq_resolution = int(freq_resolution)
     self.__time_length = int(time_length)
     self.__frame_rate = float(frame_rate)
     self.__input_center_freq = float(input_center_freq)
     self.__paused = bool(paused)
     
     self.__interested_cell = LooseCell(key='interested', type=bool, value=False, writable=False, persists=False)
     
     # blocks
     self.__gate = None
     self.__fft_sink = None
     self.__scope_sink = None
     self.__scope_chunker = None
     self.__before_fft = None
     self.__logpwrfft = None
     self.__overlapper = None
     
     self.__rebuild()
     self.__connect()
示例#45
0
class TestLooseCell(unittest.TestCase):
    def setUp(self):
        self.lc = LooseCell(value=0, type=int)
    
    def test_get_set(self):
        self.assertEqual(0, self.lc.get())
        self.lc.set(1)
        self.assertEqual(1, self.lc.get())
        self.lc.set(2.1)
        self.assertEqual(2, self.lc.get())
    
    def test_subscription(self):
        st = CellSubscriptionTester(self.lc)
        self.lc.set(1)
        st.expect_now(1)
        st.unsubscribe()
        self.lc.set(2)
        st.advance()  # check for unwanted callbacks
    
    def test_repr(self):
        self.assertEqual(repr(self.lc), '<LooseCell PythonT(<type \'int\'>) 0>')
示例#46
0
 def __init__(self):
     self.subscribable = LooseCell(value='', type=str, writable=True)
示例#47
0
class MonitorSink(gr.hier_block2, ExportedState):
    """Convenience wrapper around all the bits and pieces to display the signal spectrum to the client.
    
    The units of the FFT output are dB power/Hz (power spectral density) relative to unit amplitude (i.e. dBFS assuming the source clips at +/-1). Note this is different from the standard logpwrfft result of power _per bin_, which would be undesirably dependent on the sample rate and bin size.
    """
    implements(IMonitor)
    
    def __init__(self,
            signal_type=None,
            enable_scope=False,
            freq_resolution=4096,
            time_length=2048,
            frame_rate=30.0,
            input_center_freq=0.0,
            paused=False,
            context=None):
        assert isinstance(signal_type, SignalType)
        assert context is not None
        
        itemsize = signal_type.get_itemsize()
        gr.hier_block2.__init__(
            self, type(self).__name__,
            gr.io_signature(1, 1, itemsize),
            gr.io_signature(0, 0, 0),
        )
        
        # constant parameters
        self.__power_offset = 40  # TODO autoset or controllable
        self.__itemsize = itemsize
        self.__context = context
        self.__enable_scope = enable_scope
        
        # settable parameters
        self.__signal_type = signal_type
        self.__freq_resolution = int(freq_resolution)
        self.__time_length = int(time_length)
        self.__frame_rate = float(frame_rate)
        self.__input_center_freq = float(input_center_freq)
        self.__paused = bool(paused)
        
        self.__interested_cell = LooseCell(key='interested', type=bool, value=False, writable=False, persists=False)
        
        # blocks
        self.__gate = None
        self.__fft_sink = None
        self.__scope_sink = None
        self.__scope_chunker = None
        self.__before_fft = None
        self.__logpwrfft = None
        self.__overlapper = None
        
        self.__rebuild()
        self.__connect()
    
    def state_def(self, callback):
        super(MonitorSink, self).state_def(callback)
        # TODO make this possible to be decorator style
        callback(StreamCell(self, 'fft',
            type=BulkDataT(array_format='b', info_format='dff'),
            label='Spectrum'))
        callback(StreamCell(self, 'scope',
            type=BulkDataT(array_format='f', info_format='d'),
            label='Scope'))

    def __rebuild(self):
        if self.__signal_type.is_analytic():
            input_length = self.__freq_resolution
            output_length = self.__freq_resolution
            self.__after_fft = None
        else:
            # use vector_to_streams to cut the output in half and discard the redundant part
            input_length = self.__freq_resolution * 2
            output_length = self.__freq_resolution
            self.__after_fft = blocks.vector_to_streams(itemsize=output_length * gr.sizeof_float, nstreams=2)
        
        sample_rate = self.__signal_type.get_sample_rate()
        overlap_factor = int(math.ceil(_maximum_fft_rate * input_length / sample_rate))
        # sanity limit -- OverlapGimmick is not free
        overlap_factor = min(16, overlap_factor)
        
        self.__gate = blocks.copy(gr.sizeof_gr_complex)
        self.__gate.set_enabled(not self.__paused)
        
        self.__fft_sink = MessageDistributorSink(
            itemsize=output_length * gr.sizeof_char,
            context=self.__context,
            migrate=self.__fft_sink,
            notify=self.__update_interested)
        self.__overlapper = _OverlapGimmick(
            size=input_length,
            factor=overlap_factor,
            itemsize=self.__itemsize)
        
        # Adjusts units so displayed level is independent of resolution and sample rate. Also throw in the packing offset
        compensation = to_dB(input_length / sample_rate) + self.__power_offset
        # TODO: Consider not using the logpwrfft block
        
        self.__logpwrfft = logpwrfft.logpwrfft_c(
            sample_rate=sample_rate * overlap_factor,
            fft_size=input_length,
            ref_scale=10.0 ** (-compensation / 20.0) * 2,  # not actually using this as a reference scale value but avoiding needing to use a separate add operation to apply the unit change -- this expression is the inverse of what logpwrfft does internally
            frame_rate=self.__frame_rate,
            avg_alpha=1.0,
            average=False)
        # It would make slightly more sense to use unsigned chars, but blocks.float_to_uchar does not support vlen.
        self.__fft_converter = blocks.float_to_char(vlen=self.__freq_resolution, scale=1.0)
    
        self.__scope_sink = MessageDistributorSink(
            itemsize=self.__time_length * gr.sizeof_gr_complex,
            context=self.__context,
            migrate=self.__scope_sink,
            notify=self.__update_interested)
        self.__scope_chunker = blocks.stream_to_vector_decimator(
            item_size=gr.sizeof_gr_complex,
            sample_rate=sample_rate,
            vec_rate=self.__frame_rate,  # TODO doesn't need to be coupled
            vec_len=self.__time_length)

    def __connect(self):
        self.__context.lock()
        try:
            self.disconnect_all()
            self.connect(
                self,
                self.__gate,
                self.__overlapper,
                self.__logpwrfft)
            if self.__after_fft is not None:
                self.connect(self.__logpwrfft, self.__after_fft)
                self.connect(self.__after_fft, self.__fft_converter, self.__fft_sink)
                self.connect((self.__after_fft, 1), blocks.null_sink(gr.sizeof_float * self.__freq_resolution))
            else:
                self.connect(self.__logpwrfft, self.__fft_converter, self.__fft_sink)
            if self.__enable_scope:
                self.connect(
                    self.__gate,
                    self.__scope_chunker,
                    self.__scope_sink)
        finally:
            self.__context.unlock()
    
    # non-exported
    def get_interested_cell(self):
        return self.__interested_cell
    
    def __update_interested(self):
        self.__interested_cell.set_internal(not self.__paused and (
            self.__fft_sink.get_subscription_count() > 0 or
            self.__scope_sink.get_subscription_count() > 0))
    
    @exported_value(type=SignalType, changes='explicit')
    def get_signal_type(self):
        return self.__signal_type
    
    # non-exported
    def set_signal_type(self, value):
        # TODO: don't rebuild if the rate did not change and the spectrum-sidedness of the type did not change
        assert self.__signal_type.compatible_items(value)
        self.__signal_type = value
        self.__rebuild()
        self.__connect()
        self.state_changed('signal_type')
    
    # non-exported
    def set_input_center_freq(self, value):
        self.__input_center_freq = float(value) 
    
    @exported_value(
        type=RangeT([(2, 4096)], logarithmic=True, integer=True),
        changes='this_setter',
        label='Resolution',
        description='Frequency domain resolution; number of FFT bins.')
    def get_freq_resolution(self):
        return self.__freq_resolution

    @setter
    def set_freq_resolution(self, freq_resolution):
        self.__freq_resolution = freq_resolution
        self.__rebuild()
        self.__connect()

    @exported_value(type=RangeT([(1, 4096)], logarithmic=True, integer=True), changes='this_setter')
    def get_time_length(self):
        return self.__time_length

    @setter
    def set_time_length(self, value):
        self.__time_length = value
        self.__rebuild()
        self.__connect()

    @exported_value(
        type=RangeT([(1, _maximum_fft_rate)],
        logarithmic=True, integer=False),
        changes='this_setter',
        label='Rate',
        description='Number of FFT frames per second.')
    def get_frame_rate(self):
        return self.__frame_rate

    @setter
    def set_frame_rate(self, value):
        self.__logpwrfft.set_vec_rate(float(value))
        self.__frame_rate = self.__logpwrfft.frame_rate()
    
    @exported_value(type=bool, changes='this_setter', label='Pause')
    def get_paused(self):
        return self.__paused

    @setter
    def set_paused(self, value):
        self.__paused = value
        self.__gate.set_enabled(not value)
        self.__update_interested()

    # exported via state_def
    def get_fft_info(self):
        return (self.__input_center_freq, self.__signal_type.get_sample_rate(), self.__power_offset)
    
    def get_fft_distributor(self):
        return self.__fft_sink
    
    # exported via state_def
    def get_scope_info(self):
        return (self.__signal_type.get_sample_rate(),)
    
    def get_scope_distributor(self):
        return self.__scope_sink
示例#48
0
 def setUp(self):
     self.lc = LooseCell(
         value=0,
         type=int,
         writable=True,
         interest_tracker=LoopbackInterestTracker())
示例#49
0
class TestLooseCell(unittest.TestCase):
    def setUp(self):
        self.lc = LooseCell(
            value=0,
            type=int,
            writable=True,
            interest_tracker=LoopbackInterestTracker())
    
    def test_get_set(self):
        self.assertEqual(0, self.lc.get())
        self.lc.set(1)
        self.assertEqual(1, self.lc.get())
        self.lc.set(2.1)
        self.assertEqual(2, self.lc.get())
    
    def test_subscription(self):
        st = CellSubscriptionTester(self.lc)
        self.lc.set(1)
        st.expect_now(1)
        st.unsubscribe()
        self.lc.set(2)
        st.advance()  # check for unwanted callbacks
    
    def test_repr(self):
        if six.PY2:
            self.assertEqual(repr(self.lc), '<LooseCell PythonT(<type \'int\'>) 0>')
        else:
            self.assertEqual(repr(self.lc), '<LooseCell PythonT(<class \'int\'>) 0>')
    
    def test_default_writability(self):
        self.assertFalse(LooseCell(value=0, type=int).isWritable())
    
    def test_not_writable(self):
        self.lc = LooseCell(value=0, type=int, writable=False)
        self.assertRaises(Exception, lambda:
            self.lc.set(1))
        self.assertEqual(self.lc.get(), 0)
示例#50
0
 def test_not_writable(self):
     self.lc = LooseCell(value=0, type=int, writable=False)
     self.assertRaises(Exception, lambda:
         self.lc.set(1))
     self.assertEqual(self.lc.get(), 0)
示例#51
0
class MonitorSink(gr.hier_block2, ExportedState):
    """Convenience wrapper around all the bits and pieces to display the signal spectrum to the client.
    
    The units of the FFT output are dB power/Hz (power spectral density) relative to unit amplitude (i.e. dBFS assuming the source clips at +/-1). Note this is different from the standard logpwrfft result of power _per bin_, which would be undesirably dependent on the sample rate and bin size.
    """
    def __init__(self,
            signal_type=None,
            enable_scope=False,
            freq_resolution=4096,
            time_length=2048,
            frame_rate=30.0,
            input_center_freq=0.0,
            paused=False,
            context=None):
        assert isinstance(signal_type, SignalType)
        assert context is not None
        
        itemsize = signal_type.get_itemsize()
        gr.hier_block2.__init__(
            self, type(self).__name__,
            gr.io_signature(1, 1, itemsize),
            gr.io_signature(0, 0, 0),
        )
        
        # constant parameters
        self.__power_offset = 40  # TODO autoset or controllable
        self.__itemsize = itemsize
        self.__context = context
        self.__enable_scope = enable_scope
        
        # settable parameters
        self.__signal_type = signal_type
        self.__freq_resolution = int(freq_resolution)
        self.__time_length = int(time_length)
        self.__frame_rate = float(frame_rate)
        self.__input_center_freq = float(input_center_freq)
        self.__paused = bool(paused)
        
        self.__interested_cell = LooseCell(type=bool, value=False, writable=False, persists=False)
        
        # stuff created by __do_connect
        self.__gate = None
        self.__fft_sink = None
        self.__scope_sink = None
        self.__frame_dec = None
        self.__frame_rate_to_decimation_conversion = 0.0
        
        self.__do_connect()
    
    def state_def(self):
        for d in super(MonitorSink, self).state_def():
            yield d
        # TODO make this possible to be decorator style
        yield 'fft', StreamCell(self, 'fft',
            type=BulkDataT(array_format='b', info_format='dff'),
            label='Spectrum')
        yield 'scope', StreamCell(self, 'scope',
            type=BulkDataT(array_format='f', info_format='d'),
            label='Scope')

    def __do_connect(self):
        itemsize = self.__itemsize
        
        if self.__signal_type.is_analytic():
            input_length = self.__freq_resolution
            output_length = self.__freq_resolution
            self.__after_fft = None
        else:
            # use vector_to_streams to cut the output in half and discard the redundant part
            input_length = self.__freq_resolution * 2
            output_length = self.__freq_resolution
            self.__after_fft = blocks.vector_to_streams(itemsize=output_length * gr.sizeof_float, nstreams=2)
        
        sample_rate = self.__signal_type.get_sample_rate()
        overlap_factor = int(math.ceil(_maximum_fft_rate * input_length / sample_rate))
        # sanity limit -- OverlapGimmick is not free
        overlap_factor = min(16, overlap_factor)
        
        self.__frame_rate_to_decimation_conversion = sample_rate * overlap_factor / input_length
        
        self.__gate = blocks.copy(itemsize)
        self.__gate.set_enabled(not self.__paused)
        
        overlapper = _OverlappedStreamToVector(
            size=input_length,
            factor=overlap_factor,
            itemsize=itemsize)
        
        self.__frame_dec = blocks.keep_one_in_n(
            itemsize=itemsize * input_length,
            n=int(round(self.__frame_rate_to_decimation_conversion / self.__frame_rate)))
        
        # the actual FFT logic, which is similar to GR's logpwrfft_c
        window = windows.blackmanharris(input_length)
        window_power = sum(x * x for x in window)
        # TODO: use fft_vfc when applicable
        fft_block = (fft_vcc if itemsize == gr.sizeof_gr_complex else fft_vfc)(
            fft_size=input_length,
            forward=True,
            window=window)
        mag_squared = blocks.complex_to_mag_squared(input_length)
        logarithmizer = blocks.nlog10_ff(
            n=10,  # the "deci" in "decibel"
            vlen=input_length,
            k=(
                -to_dB(window_power) +  # compensate for window
                -to_dB(sample_rate) +  # convert from power-per-sample to power-per-Hz
                self.__power_offset  # offset for packing into bytes
            ))
        
        # It would make slightly more sense to use unsigned chars, but blocks.float_to_uchar does not support vlen.
        self.__fft_converter = blocks.float_to_char(vlen=self.__freq_resolution, scale=1.0)
        
        self.__fft_sink = MessageDistributorSink(
            itemsize=output_length * gr.sizeof_char,
            context=self.__context,
            migrate=self.__fft_sink,
            notify=self.__update_interested)
    
        self.__scope_sink = MessageDistributorSink(
            itemsize=self.__time_length * gr.sizeof_gr_complex,
            context=self.__context,
            migrate=self.__scope_sink,
            notify=self.__update_interested)
        scope_chunker = blocks.stream_to_vector_decimator(
            item_size=gr.sizeof_gr_complex,
            sample_rate=sample_rate,
            vec_rate=self.__frame_rate,  # TODO doesn't need to be coupled
            vec_len=self.__time_length)

        # connect everything
        self.__context.lock()
        try:
            self.disconnect_all()
            self.connect(
                self,
                self.__gate,
                overlapper,
                self.__frame_dec,
                fft_block,
                mag_squared,
                logarithmizer)
            if self.__after_fft is not None:
                self.connect(logarithmizer, self.__after_fft)
                self.connect(self.__after_fft, self.__fft_converter, self.__fft_sink)
                self.connect((self.__after_fft, 1), blocks.null_sink(gr.sizeof_float * self.__freq_resolution))
            else:
                self.connect(logarithmizer, self.__fft_converter, self.__fft_sink)
            if self.__enable_scope:
                self.connect(
                    self.__gate,
                    scope_chunker,
                    self.__scope_sink)
        finally:
            self.__context.unlock()
    
    # non-exported
    def get_interested_cell(self):
        return self.__interested_cell
    
    def __update_interested(self):
        self.__interested_cell.set_internal(not self.__paused and (
            self.__fft_sink.get_subscription_count() > 0 or
            self.__scope_sink.get_subscription_count() > 0))
    
    @exported_value(type=SignalType, changes='explicit')
    def get_signal_type(self):
        return self.__signal_type
    
    # non-exported
    def set_signal_type(self, value):
        # TODO: don't rebuild if the rate did not change and the spectrum-sidedness of the type did not change
        assert self.__signal_type.compatible_items(value)
        self.__signal_type = value
        self.__do_connect()
        self.state_changed('signal_type')
    
    # non-exported
    def set_input_center_freq(self, value):
        self.__input_center_freq = float(value) 
    
    @exported_value(
        type=RangeT([(2, 4096)], logarithmic=True, integer=True),
        changes='this_setter',
        label='Resolution',
        description='Frequency domain resolution; number of FFT bins.')
    def get_freq_resolution(self):
        return self.__freq_resolution

    @setter
    def set_freq_resolution(self, freq_resolution):
        self.__freq_resolution = freq_resolution
        self.__do_connect()

    @exported_value(type=RangeT([(1, 4096)], logarithmic=True, integer=True), changes='this_setter')
    def get_time_length(self):
        return self.__time_length

    @setter
    def set_time_length(self, value):
        self.__time_length = value
        self.__do_connect()

    @exported_value(
        type=RangeT([(1, _maximum_fft_rate)],
            unit=units.Hz,
            logarithmic=True,
            integer=False),
        changes='this_setter',
        label='Rate',
        description='Number of FFT frames per second.')
    def get_frame_rate(self):
        return self.__frame_rate

    @setter
    def set_frame_rate(self, value):
        n = int(round(self.__frame_rate_to_decimation_conversion / value))
        self.__frame_dec.set_n(n)
        # derive effective value by calculating inverse
        self.__frame_rate = self.__frame_rate_to_decimation_conversion / n
    
    @exported_value(type=bool, changes='this_setter', label='Pause')
    def get_paused(self):
        return self.__paused

    @setter
    def set_paused(self, value):
        self.__paused = value
        self.__gate.set_enabled(not value)
        self.__update_interested()

    # exported via state_def
    def get_fft_info(self):
        return (self.__input_center_freq, self.__signal_type.get_sample_rate(), self.__power_offset)
    
    def get_fft_distributor(self):
        return self.__fft_sink
    
    # exported via state_def
    def get_scope_info(self):
        return (self.__signal_type.get_sample_rate(),)
    
    def get_scope_distributor(self):
        return self.__scope_sink
示例#52
0
 def setUp(self):
     self.lc = LooseCell(value=0, type=int)
示例#53
0
class TestViewCell(unittest.TestCase):
    def setUp(self):
        self.lc = LooseCell(value=0, type=RangeT([(-100, 100)]))
        self.delta = 1
        self.vc = ViewCell(
            base=self.lc,
            get_transform=lambda x: x + self.delta,
            set_transform=lambda x: x - self.delta,
            type=int)
    
    # TODO: Add tests for behavior when the transform is not perfectly one-to-one (such as due to floating-point error).
    
    def test_get_set(self):
        self.assertEqual(0, self.lc.get())
        self.assertEqual(1, self.vc.get())
        self.vc.set(2)
        self.assertEqual(1, self.lc.get())
        self.assertEqual(2, self.vc.get())
        self.lc.set(3)
        self.assertEqual(3, self.lc.get())
        self.assertEqual(4, self.vc.get())
        
        self.delta = 10
        self.vc.changed_transform()
        self.assertEqual(3, self.lc.get())
        self.assertEqual(13, self.vc.get())
    
    def test_subscription(self):
        st = CellSubscriptionTester(self.vc)
        
        self.lc.set(1)
        st.expect_now(2)
        
        self.delta = 10
        self.vc.changed_transform()
        self.assertEqual(1, self.lc.get())
        st.expect_now(11)
        st.unsubscribe()
        self.lc.set(2)
        st.advance()
    
    def test_coerced_base_value(self):
        self.vc.set(999)  # out of base cell's range, gets clamped
        self.assertEqual(100 + self.delta, self.vc.get())
示例#54
0
 def __init__(self):
     self.subscribable = LooseCell(key='subscribable', value='', type=str)