Exemple #1
0
 def get_min_max(self, group):
     frequencies = sorted(group, key=lambda f: f["frequency"])
     lowest = frequencies[0]
     min = lowest["frequency"] + Modes.findByModulation(lowest["mode"]).get_bandpass().low_cut
     highest = frequencies[-1]
     max = highest["frequency"] + Modes.findByModulation(highest["mode"]).get_bandpass().high_cut
     return min, max
Exemple #2
0
 def setupService(self, mode, frequency, source):
     logger.debug("setting up service {0} on frequency {1}".format(
         mode, frequency))
     # TODO selecting outputs will need some more intelligence here
     if mode == "packet":
         output = AprsServiceOutput(frequency)
     elif mode == "js8":
         output = Js8ServiceOutput(frequency)
     else:
         output = WsjtServiceOutput(frequency)
     d = Dsp(output)
     d.nc_port = source.getPort()
     center_freq = source.getProps()["center_freq"]
     d.set_offset_freq(frequency - center_freq)
     d.set_center_freq(center_freq)
     modeObject = Modes.findByModulation(mode)
     d.set_demodulator(modeObject.get_modulation())
     d.set_bandpass(modeObject.get_bandpass())
     d.set_secondary_demodulator(mode)
     d.set_audio_compression("none")
     d.set_samp_rate(source.getProps()["samp_rate"])
     d.set_temporary_directory(CoreConfig().get_temporary_directory())
     d.set_service()
     d.start()
     return d
Exemple #3
0
 def __init__(self, mode_str: str, parser: AudioChopperParser):
     self.parser = parser
     self.dialFrequency = None
     self.doRun = True
     self.writers = []
     mode = Modes.findByModulation(mode_str)
     if mode is None or not isinstance(mode, AudioChopperMode):
         raise ValueError(
             "Mode {} is not an audio chopper mode".format(mode_str))
     self.profile_source = mode.get_profile_source()
     super().__init__()
Exemple #4
0
 def __init__(self, active_dsp, mode_str: str):
     self.read_fn = None
     self.doRun = True
     self.dsp = active_dsp
     self.writers = []
     mode = Modes.findByModulation(mode_str)
     if mode is None or not isinstance(mode, AudioChopperMode):
         raise ValueError(
             "Mode {} is not an audio chopper mode".format(mode_str))
     self.profile_source = mode.get_profile_source()
     (self.outputReader, self.outputWriter) = Pipe()
     super().__init__()
Exemple #5
0
    def render_bookmark(self, bookmark: Bookmark):
        def render_frequency(freq):
            suffixes = {
                0: "",
                3: "k",
                6: "M",
                9: "G",
                12: "T",
            }
            exp = 0
            if freq > 0:
                exp = int(math.log10(freq) / 3) * 3
            num = freq
            suffix = ""
            if exp in suffixes:
                num = freq / 10 ** exp
                suffix = suffixes[exp]
            return "{num:g} {suffix}Hz".format(num=num, suffix=suffix)

        mode = Modes.findByModulation(bookmark.getModulation())
        return """
            <tr data-id="{id}">
                <td data-editor="name" data-value="{name}">{name}</td>
                <td data-editor="frequency" data-value="{frequency}" class="frequency">{rendered_frequency}</td>
                <td data-editor="modulation" data-value="{modulation}">{modulation_name}</td>
                <td>
                    <button type="button" class="btn btn-sm btn-danger bookmark-delete">delete</button>
                </td>
            </tr>
        """.format(
            id=id(bookmark),
            name=bookmark.getName(),
            # TODO render frequency in si units
            frequency=bookmark.getFrequency(),
            rendered_frequency=render_frequency(bookmark.getFrequency()),
            modulation=bookmark.getModulation() if mode is None else mode.modulation,
            modulation_name=bookmark.getModulation() if mode is None else mode.name,
        )
Exemple #6
0
    def setupService(self, mode, frequency, source):
        logger.debug("setting up service {0} on frequency {1}".format(mode, frequency))

        modeObject = Modes.findByModulation(mode)
        if not isinstance(modeObject, DigitalMode):
            logger.warning("mode is not a digimode: %s", mode)
            return None

        demod = self._getDemodulator(modeObject.get_modulation())
        secondaryDemod = self._getSecondaryDemodulator(modeObject.modulation)
        center_freq = source.getProps()["center_freq"]
        sampleRate = source.getProps()["samp_rate"]
        bandpass = modeObject.get_bandpass()
        if isinstance(secondaryDemod, DialFrequencyReceiver):
            secondaryDemod.setDialFrequency(frequency)

        chain = ServiceDemodulatorChain(demod, secondaryDemod, sampleRate, frequency - center_freq)
        chain.setBandPass(bandpass.low_cut, bandpass.high_cut)
        chain.setReader(source.getBuffer().getReader())

        # dummy buffer, we don't use the output right now
        buffer = Buffer(chain.getOutputFormat())
        chain.setWriter(buffer)
        return chain
Exemple #7
0
    def __init__(self, handler, sdrSource):
        self.handler = handler
        self.sdrSource = sdrSource
        self.parsers = {
            "meta": MetaParser(self.handler),
            "wsjt_demod": WsjtParser(self.handler),
            "packet_demod": AprsParser(self.handler),
            "pocsag_demod": PocsagParser(self.handler),
            "js8_demod": Js8Parser(self.handler),
        }

        self.props = PropertyStack()

        # local demodulator properties not forwarded to the sdr
        # ensure strict validation since these can be set from the client
        # and are used to build executable commands
        validators = {
            "output_rate": "int",
            "hd_output_rate": "int",
            "squelch_level": "num",
            "secondary_mod": ModulationValidator(),
            "low_cut": "num",
            "high_cut": "num",
            "offset_freq": "int",
            "mod": ModulationValidator(),
            "secondary_offset_freq": "int",
            "dmr_filter": "int",
        }
        self.localProps = PropertyValidator(
            PropertyLayer().filter(*validators.keys()), validators)

        self.props.addLayer(0, self.localProps)
        # properties that we inherit from the sdr
        self.props.addLayer(
            1,
            self.sdrSource.getProps().filter(
                "audio_compression",
                "fft_compression",
                "digimodes_fft_size",
                "csdr_dynamic_bufsize",
                "csdr_print_bufsizes",
                "csdr_through",
                "digimodes_enable",
                "samp_rate",
                "digital_voice_unvoiced_quality",
                "temporary_directory",
                "center_freq",
                "start_mod",
                "start_freq",
                "wfm_deemphasis_tau",
            ))

        self.dsp = csdr.dsp(self)
        self.dsp.nc_port = self.sdrSource.getPort()

        def set_low_cut(cut):
            bpf = self.dsp.get_bpf()
            bpf[0] = cut
            self.dsp.set_bpf(*bpf)

        def set_high_cut(cut):
            bpf = self.dsp.get_bpf()
            bpf[1] = cut
            self.dsp.set_bpf(*bpf)

        def set_dial_freq(key, value):
            if self.props["center_freq"] is None or self.props[
                    "offset_freq"] is None:
                return
            freq = self.props["center_freq"] + self.props["offset_freq"]
            for parser in self.parsers.values():
                parser.setDialFrequency(freq)

        if "start_mod" in self.props:
            self.dsp.set_demodulator(self.props["start_mod"])
            mode = Modes.findByModulation(self.props["start_mod"])

            if mode and mode.bandpass:
                self.dsp.set_bpf(mode.bandpass.low_cut, mode.bandpass.high_cut)
            else:
                self.dsp.set_bpf(-4000, 4000)

        if "start_freq" in self.props and "center_freq" in self.props:
            self.dsp.set_offset_freq(self.props["start_freq"] -
                                     self.props["center_freq"])
        else:
            self.dsp.set_offset_freq(0)

        self.subscriptions = [
            self.props.wireProperty("audio_compression",
                                    self.dsp.set_audio_compression),
            self.props.wireProperty("fft_compression",
                                    self.dsp.set_fft_compression),
            self.props.wireProperty("digimodes_fft_size",
                                    self.dsp.set_secondary_fft_size),
            self.props.wireProperty("samp_rate", self.dsp.set_samp_rate),
            self.props.wireProperty("output_rate", self.dsp.set_output_rate),
            self.props.wireProperty("hd_output_rate",
                                    self.dsp.set_hd_output_rate),
            self.props.wireProperty("offset_freq", self.dsp.set_offset_freq),
            self.props.wireProperty("center_freq", self.dsp.set_center_freq),
            self.props.wireProperty("squelch_level",
                                    self.dsp.set_squelch_level),
            self.props.wireProperty("low_cut", set_low_cut),
            self.props.wireProperty("high_cut", set_high_cut),
            self.props.wireProperty("mod", self.dsp.set_demodulator),
            self.props.wireProperty("digital_voice_unvoiced_quality",
                                    self.dsp.set_unvoiced_quality),
            self.props.wireProperty("dmr_filter", self.dsp.set_dmr_filter),
            self.props.wireProperty("temporary_directory",
                                    self.dsp.set_temporary_directory),
            self.props.wireProperty("wfm_deemphasis_tau",
                                    self.dsp.set_wfm_deemphasis_tau),
            self.props.filter("center_freq",
                              "offset_freq").wire(set_dial_freq),
        ]

        self.dsp.csdr_dynamic_bufsize = self.props["csdr_dynamic_bufsize"]
        self.dsp.csdr_print_bufsizes = self.props["csdr_print_bufsizes"]
        self.dsp.csdr_through = self.props["csdr_through"]

        if self.props["digimodes_enable"]:

            def set_secondary_mod(mod):
                if mod == False:
                    mod = None
                self.dsp.set_secondary_demodulator(mod)
                if mod is not None:
                    self.handler.write_secondary_dsp_config({
                        "secondary_fft_size":
                        self.props["digimodes_fft_size"],
                        "if_samp_rate":
                        self.dsp.if_samp_rate(),
                        "secondary_bw":
                        self.dsp.secondary_bw(),
                    })

            self.subscriptions += [
                self.props.wireProperty("secondary_mod", set_secondary_mod),
                self.props.wireProperty("secondary_offset_freq",
                                        self.dsp.set_secondary_offset_freq),
            ]

        self.startOnAvailable = False

        self.sdrSource.addClient(self)

        super().__init__()
Exemple #8
0
    def __init__(self, handler, sdrSource):
        self.handler = handler
        self.sdrSource = sdrSource

        self.props = PropertyStack()

        # current audio mode. should be "audio" or "hd_audio" depending on what demodulatur is in use.
        self.audioOutput = None

        # local demodulator properties not forwarded to the sdr
        # ensure strict validation since these can be set from the client
        # and are used to build executable commands
        validators = {
            "output_rate": "int",
            "hd_output_rate": "int",
            "squelch_level": "num",
            "secondary_mod": ModulationValidator(),
            "low_cut": "num",
            "high_cut": "num",
            "offset_freq": "int",
            "mod": ModulationValidator(),
            "secondary_offset_freq": "int",
            "dmr_filter": "int",
        }
        self.localProps = PropertyValidator(
            PropertyLayer().filter(*validators.keys()), validators)

        self.props.addLayer(0, self.localProps)
        # properties that we inherit from the sdr
        self.props.addLayer(
            1,
            self.sdrSource.getProps().filter(
                "audio_compression",
                "fft_compression",
                "digimodes_fft_size",
                "samp_rate",
                "center_freq",
                "start_mod",
                "start_freq",
                "wfm_deemphasis_tau",
                "digital_voice_codecserver",
            ),
        )

        # defaults for values that may not be set
        self.props.addLayer(
            2,
            PropertyLayer(
                output_rate=12000,
                hd_output_rate=48000,
                digital_voice_codecserver="",
            ).readonly())

        self.chain = ClientDemodulatorChain(self._getDemodulator("nfm"),
                                            self.props["samp_rate"],
                                            self.props["output_rate"],
                                            self.props["hd_output_rate"],
                                            self.props["audio_compression"],
                                            self)

        self.readers = {}

        if "start_mod" in self.props:
            mode = Modes.findByModulation(self.props["start_mod"])
            if mode:
                self.setDemodulator(mode.get_modulation())
                if isinstance(mode, DigitalMode):
                    self.setSecondaryDemodulator(mode.modulation)
                if mode.bandpass:
                    bpf = [mode.bandpass.low_cut, mode.bandpass.high_cut]
                    self.chain.setBandpass(*bpf)
            else:
                # TODO modes should be mandatory
                self.setDemodulator(self.props["start_mod"])

        if "start_freq" in self.props and "center_freq" in self.props:
            self.chain.setFrequencyOffset(self.props["start_freq"] -
                                          self.props["center_freq"])
        else:
            self.chain.setFrequencyOffset(0)

        self.subscriptions = [
            self.props.wireProperty("audio_compression",
                                    self.setAudioCompression),
            self.props.wireProperty("fft_compression",
                                    self.chain.setSecondaryFftCompression),
            self.props.wireProperty("fft_voverlap_factor",
                                    self.chain.setSecondaryFftOverlapFactor),
            self.props.wireProperty("fft_fps", self.chain.setSecondaryFftFps),
            self.props.wireProperty("digimodes_fft_size",
                                    self.setSecondaryFftSize),
            self.props.wireProperty("samp_rate", self.chain.setSampleRate),
            self.props.wireProperty("output_rate", self.chain.setOutputRate),
            self.props.wireProperty("hd_output_rate",
                                    self.chain.setHdOutputRate),
            self.props.wireProperty("offset_freq",
                                    self.chain.setFrequencyOffset),
            self.props.wireProperty("center_freq",
                                    self.chain.setCenterFrequency),
            self.props.wireProperty("squelch_level",
                                    self.chain.setSquelchLevel),
            self.props.wireProperty("low_cut", self.chain.setLowCut),
            self.props.wireProperty("high_cut", self.chain.setHighCut),
            self.props.wireProperty("mod", self.setDemodulator),
            self.props.wireProperty("dmr_filter", self.chain.setSlotFilter),
            self.props.wireProperty("wfm_deemphasis_tau",
                                    self.chain.setWfmDeemphasisTau),
            self.props.wireProperty("secondary_mod",
                                    self.setSecondaryDemodulator),
            self.props.wireProperty("secondary_offset_freq",
                                    self.chain.setSecondaryFrequencyOffset),
        ]

        # wire power level output
        buffer = Buffer(Format.FLOAT)
        self.chain.setPowerWriter(buffer)
        self.wireOutput("smeter", buffer)

        # wire meta output
        buffer = Buffer(Format.CHAR)
        self.chain.setMetaWriter(buffer)
        self.wireOutput("meta", buffer)

        # wire secondary FFT
        buffer = Buffer(self.chain.getSecondaryFftOutputFormat())
        self.chain.setSecondaryFftWriter(buffer)
        self.wireOutput("secondary_fft", buffer)

        # wire secondary demodulator
        buffer = Buffer(Format.CHAR)
        self.chain.setSecondaryWriter(buffer)
        self.wireOutput("secondary_demod", buffer)

        self.startOnAvailable = False

        self.sdrSource.addClient(self)