added option to run demodulator without bandpass

This commit is contained in:
Jakob Ketterl 2023-08-25 21:12:13 +02:00
parent 5b86ebdcba
commit 37ee7796db
7 changed files with 64 additions and 15 deletions

View File

@ -94,19 +94,24 @@ class Chain(Module):
if self.writer is not None: if self.writer is not None:
newWorker.setWriter(self.writer) newWorker.setWriter(self.writer)
def insert(self, newWorker): def insert(self, newWorker, index=0):
nextWorker = None nextWorker = None
if self.workers: previousWorker = None
nextWorker = self.workers[0] if index < len(self.workers):
nextWorker = self.workers[index]
if index > 0:
previousWorker = self.workers[index - 1]
self.workers.insert(0, newWorker) self.workers.insert(index, newWorker)
if nextWorker: if nextWorker:
self._connect(newWorker, nextWorker) self._connect(newWorker, nextWorker)
elif self.writer is not None: elif self.writer is not None:
newWorker.setWriter(self.writer) newWorker.setWriter(self.writer)
if self.reader is not None: if previousWorker:
self._connect(previousWorker, newWorker)
elif self.reader is not None:
newWorker.setReader(self.reader) newWorker.setReader(self.reader)
def remove(self, index): def remove(self, index):

View File

@ -1,6 +1,7 @@
from csdr.chain import Chain from csdr.chain import Chain
from pycsdr.modules import Shift, FirDecimate, Bandpass, Squelch, FractionalDecimator, Writer from pycsdr.modules import Shift, FirDecimate, Bandpass, Squelch, FractionalDecimator, Writer
from pycsdr.types import Format from pycsdr.types import Format
from owrx.property import PropertyDeleted
import math import math
@ -80,7 +81,6 @@ class Selector(Chain):
self.bandpass = self._buildBandpass() self.bandpass = self._buildBandpass()
self.bandpassCutoffs = None self.bandpassCutoffs = None
self.setBandpass(-4000, 4000)
workers = [self.shift, self.decimation, self.bandpass] workers = [self.shift, self.decimation, self.bandpass]
@ -93,6 +93,8 @@ class Selector(Chain):
super().__init__(workers) super().__init__(workers)
self.setBandpass(-4000, 4000)
def _buildBandpass(self) -> Bandpass: def _buildBandpass(self) -> Bandpass:
bp_transition = 320.0 / self.outputRate bp_transition = 320.0 / self.outputRate
return Bandpass(transition=bp_transition, use_fft=True) return Bandpass(transition=bp_transition, use_fft=True)
@ -113,16 +115,34 @@ class Selector(Chain):
def setSquelchLevel(self, level: float) -> None: def setSquelchLevel(self, level: float) -> None:
self.squelch.setSquelchLevel(self._convertToLinear(level)) self.squelch.setSquelchLevel(self._convertToLinear(level))
def _enableBandpass(self):
index = self.indexOf(lambda x: isinstance(x, Bandpass))
if index < 0:
self.insert(self.bandpass, 2)
def _disableBandpass(self):
index = self.indexOf(lambda x: isinstance(x, Bandpass))
if index >= 0:
self.remove(index)
def setBandpass(self, lowCut: float, highCut: float) -> None: def setBandpass(self, lowCut: float, highCut: float) -> None:
self.bandpassCutoffs = [lowCut, highCut] self.bandpassCutoffs = [lowCut, highCut]
scaled = [x / self.outputRate for x in self.bandpassCutoffs] if None in self.bandpassCutoffs:
self.bandpass.setBandpass(*scaled) self._disableBandpass()
else:
self._enableBandpass()
scaled = [x / self.outputRate for x in self.bandpassCutoffs]
self.bandpass.setBandpass(*scaled)
def setLowCut(self, lowCut: float) -> None: def setLowCut(self, lowCut: float) -> None:
if lowCut is PropertyDeleted:
lowCut = None
self.bandpassCutoffs[0] = lowCut self.bandpassCutoffs[0] = lowCut
self.setBandpass(*self.bandpassCutoffs) self.setBandpass(*self.bandpassCutoffs)
def setHighCut(self, highCut: float) -> None: def setHighCut(self, highCut: float) -> None:
if highCut is PropertyDeleted:
highCut = None
self.bandpassCutoffs[1] = highCut self.bandpassCutoffs[1] = highCut
self.setBandpass(*self.bandpassCutoffs) self.setBandpass(*self.bandpassCutoffs)
@ -136,9 +156,11 @@ class Selector(Chain):
self.decimation.setOutputRate(outputRate) self.decimation.setOutputRate(outputRate)
self.squelch.setReportInterval(int(outputRate / (self.readings_per_second * 1024))) self.squelch.setReportInterval(int(outputRate / (self.readings_per_second * 1024)))
index = self.indexOf(lambda x: isinstance(x, Bandpass))
self.bandpass = self._buildBandpass() self.bandpass = self._buildBandpass()
self.setBandpass(*self.bandpassCutoffs) self.setBandpass(*self.bandpassCutoffs)
self.replace(2, self.bandpass) if index >= 0:
self.replace(index, self.bandpass)
def setInputRate(self, inputRate: int) -> None: def setInputRate(self, inputRate: int) -> None:
if inputRate == self.inputRate: if inputRate == self.inputRate:

View File

@ -83,9 +83,13 @@ Envelope.prototype.draw = function(visible_range){
scale_ctx.stroke(); scale_ctx.stroke();
scale_ctx.lineWidth = 1; scale_ctx.lineWidth = 1;
scale_ctx.textAlign = "left"; scale_ctx.textAlign = "left";
scale_ctx.fillText(this.demodulator.high_cut.toString(), to_px + env_att_w, env_h2); if (this.demodulator.high_cut) {
scale_ctx.fillText(this.demodulator.high_cut.toString(), to_px + env_att_w, env_h2);
}
scale_ctx.textAlign = "right"; scale_ctx.textAlign = "right";
scale_ctx.fillText(this.demodulator.low_cut.toString(), from_px - env_att_w, env_h2); if (this.demodulator.low_cut) {
scale_ctx.fillText(this.demodulator.low_cut.toString(), from_px - env_att_w, env_h2);
}
scale_ctx.lineWidth = 3; scale_ctx.lineWidth = 3;
} }
if (typeof line !== "undefined") // out of screen? if (typeof line !== "undefined") // out of screen?
@ -332,6 +336,13 @@ Demodulator.prototype.setBandpass = function(bandpass) {
this.set(); this.set();
}; };
Demodulator.prototype.disableBandpass = function() {
delete this.bandpass;
this.low_cut = null;
this.high_cut = null;
this.set()
}
Demodulator.prototype.setLowCut = function(low_cut) { Demodulator.prototype.setLowCut = function(low_cut) {
this.low_cut = low_cut; this.low_cut = low_cut;
this.set(); this.set();

View File

@ -137,6 +137,8 @@ DemodulatorPanel.prototype.setMode = function(requestedModulation, underlyingMod
this.demodulator.set_secondary_demod(mode.modulation); this.demodulator.set_secondary_demod(mode.modulation);
if (mode.bandpass) { if (mode.bandpass) {
this.demodulator.setBandpass(mode.bandpass); this.demodulator.setBandpass(mode.bandpass);
} else {
this.demodulator.disableBandpass();
} }
} else { } else {
this.demodulator.set_secondary_demod(false); this.demodulator.set_secondary_demod(false);

View File

@ -462,6 +462,8 @@ class DspManager(SdrSourceEventClient, ClientDemodulatorSecondaryDspEventClient)
if mode.bandpass: if mode.bandpass:
bpf = [mode.bandpass.low_cut, mode.bandpass.high_cut] bpf = [mode.bandpass.low_cut, mode.bandpass.high_cut]
self.chain.setBandpass(*bpf) self.chain.setBandpass(*bpf)
else:
self.chain.setBandpass(None, None)
else: else:
# TODO modes should be mandatory # TODO modes should be mandatory
self.setDemodulator(self.props["start_mod"]) self.setDemodulator(self.props["start_mod"])
@ -714,7 +716,11 @@ class DspManager(SdrSourceEventClient, ClientDemodulatorSecondaryDspEventClient)
self.setProperty(k, v) self.setProperty(k, v)
def setProperty(self, prop, value): def setProperty(self, prop, value):
self.localProps[prop] = value if value is None:
if prop in self.localProps:
del self.localProps[prop]
else:
self.localProps[prop] = value
def getClientClass(self) -> SdrClientClass: def getClientClass(self) -> SdrClientClass:
return SdrClientClass.USER return SdrClientClass.USER

View File

@ -168,7 +168,7 @@ class Modes(object):
"adsb", "adsb",
"ADS-B", "ADS-B",
underlying=["empty"], underlying=["empty"],
bandpass=Bandpass(-1e6, 1e6), bandpass=None,
requirements=["dump1090"], requirements=["dump1090"],
service=True, service=True,
squelch=False, squelch=False,

View File

@ -266,12 +266,15 @@ class ServiceHandler(SdrSourceEventClient):
secondaryDemod = self._getSecondaryDemodulator(modeObject.modulation) secondaryDemod = self._getSecondaryDemodulator(modeObject.modulation)
center_freq = source.getProps()["center_freq"] center_freq = source.getProps()["center_freq"]
sampleRate = source.getProps()["samp_rate"] sampleRate = source.getProps()["samp_rate"]
bandpass = modeObject.get_bandpass()
if isinstance(secondaryDemod, DialFrequencyReceiver): if isinstance(secondaryDemod, DialFrequencyReceiver):
secondaryDemod.setDialFrequency(dial["frequency"]) secondaryDemod.setDialFrequency(dial["frequency"])
chain = ServiceDemodulatorChain(demod, secondaryDemod, sampleRate, dial["frequency"] - center_freq) chain = ServiceDemodulatorChain(demod, secondaryDemod, sampleRate, dial["frequency"] - center_freq)
chain.setBandPass(bandpass.low_cut, bandpass.high_cut) bandpass = modeObject.get_bandpass()
if bandpass:
chain.setBandPass(bandpass.low_cut, bandpass.high_cut)
else:
chain.setBandPass(None, None)
chain.setReader(source.getBuffer().getReader()) chain.setReader(source.getBuffer().getReader())
# dummy buffer, we don't use the output right now # dummy buffer, we don't use the output right now