introduce a way for different bandpass setups for underlying modes

This commit is contained in:
Jakob Ketterl 2024-02-20 00:53:11 +01:00
parent f3989bac52
commit b299c6cd6f
5 changed files with 59 additions and 28 deletions

View file

@ -18,7 +18,7 @@ function DemodulatorPanel(el) {
el.on('click', '.openwebrx-demodulator-button', function() {
var modulation = $(this).data('modulation');
if (modulation) {
if (self.mode && self.mode.type === 'digimode' && self.mode.underlying.indexOf(modulation) >= 0) {
if (self.mode && self.mode.type === 'digimode' && modulation in self.mode.configs) {
// keep the mode, just switch underlying modulation
self.setMode(self.mode.modulation, modulation)
} else {
@ -101,7 +101,7 @@ DemodulatorPanel.prototype.setMode = function(requestedModulation, underlyingMod
var modulation;
if (mode.type === 'digimode') {
modulation = underlyingModulation = underlyingModulation || mode.underlying[0];
modulation = underlyingModulation = underlyingModulation || Object.keys(mode.configs)[0];
} else {
underlyingModulation = undefined;
modulation = mode.modulation;
@ -136,7 +136,8 @@ DemodulatorPanel.prototype.setMode = function(requestedModulation, underlyingMod
if (mode.type === 'digimode') {
this.demodulator.set_secondary_demod(mode.modulation);
var uMode = Modes.findByModulation(underlyingModulation);
var bandpass = mode.bandpass || (uMode && uMode.bandpass);
var config = mode.configs[underlyingModulation] || {};
var bandpass = config.bandpass || mode.bandpass || (uMode && uMode.bandpass);
if (bandpass) {
this.demodulator.setBandpass(bandpass);
} else {
@ -262,7 +263,7 @@ DemodulatorPanel.prototype.updateButtons = function() {
var mode = Modes.findByModulation(secondary_demod);
if (mode) {
var self = this;
mode.underlying.filter(function(m) {
Object.keys(mode.configs).filter(function(m) {
return m !== demod.get_modulation();
}).forEach(function(m) {
self.el.find('[data-modulation=' + m + ']').addClass('same-mod')

View file

@ -45,7 +45,7 @@ var Mode = function(json){
this.ifRate = json.ifRate;
}
if (this.type === 'digimode') {
this.underlying = json.underlying;
this.configs = json.configs;
this.secondaryFft = json.secondaryFft;
}
};

View file

@ -43,7 +43,7 @@ class Band(object):
if not isinstance(m, DigitalMode):
logger.warning("%s is not a digital mode, cannot be used with \"underlying\" config", mode)
continue
if f_dict["underlying"] not in m.underlying:
if f_dict["underlying"] not in m.configs:
logger.warning(
"%s is not a valid underlying mode for %s; skipping",
f_dict["underlying"],

View file

@ -445,7 +445,13 @@ class OpenWebRxReceiverClient(OpenWebRxClient, SdrSourceEventClient):
if m.ifRate is not None:
res["ifRate"] = m.ifRate
if isinstance(m, DigitalMode):
res["underlying"] = m.underlying
configs = {}
for k, c in m.configs.items():
config = {}
if c.bandpass is not None:
config["bandpass"] = {"low_cut": c.bandpass.low_cut, "high_cut": c.bandpass.high_cut}
configs[k] = config
res["configs"] = configs
res["secondaryFft"] = m.secondaryFft
return res

View file

@ -2,6 +2,7 @@ from owrx.feature import FeatureDetector
from owrx.audio import ProfileSource
from functools import reduce
from abc import ABCMeta, abstractmethod
from typing import Dict, List
class Bandpass(object):
@ -41,25 +42,35 @@ class AnalogMode(Mode):
pass
class DigitalUnderlyingConfig(object):
def __init__(self, bandpass: Bandpass = None):
self.bandpass = bandpass
class DigitalMode(Mode):
def __init__(
self,
modulation,
name,
underlying,
bandpass: Bandpass = None,
ifRate = None,
ifRate=None,
requirements=None,
service=False,
squelch=True,
secondaryFft=True
secondaryFft=True,
configs: List[str] | Dict[str, DigitalUnderlyingConfig] = None,
):
super().__init__(modulation, name, bandpass, ifRate, requirements, service, squelch)
self.underlying = underlying
self.secondaryFft = secondaryFft
if configs is None:
self.configs = {}
elif isinstance(configs, list):
self.configs = {x: DigitalUnderlyingConfig() for x in configs}
else:
self.configs = configs
def get_underlying_mode(self):
mode = Modes.findByModulation(self.underlying[0])
mode = Modes.findByModulation(list(self.configs.keys())[0])
if mode is None:
mode = EmptyMode
return mode
@ -73,10 +84,20 @@ class DigitalMode(Mode):
return self.get_underlying_mode().get_modulation()
def for_underlying(self, underlying: str):
if underlying not in self.underlying:
if underlying not in self.configs:
raise ValueError("{} is not a valid underlying mode for {}".format(underlying, self.modulation))
config = self.configs[underlying]
bandpass = self.bandpass if config.bandpass is None else config.bandpass
return DigitalMode(
self.modulation, self.name, [underlying], self.bandpass, self.requirements, self.service, self.squelch
self.modulation,
self.name,
bandpass,
self.ifRate,
self.requirements,
self.service,
self.squelch,
self.secondaryFft,
{underlying: self.configs[underlying]}
)
@ -84,7 +105,7 @@ class AudioChopperMode(DigitalMode, metaclass=ABCMeta):
def __init__(self, modulation, name, bandpass=None, requirements=None):
if bandpass is None:
bandpass = Bandpass(0, 3000)
super().__init__(modulation, name, ["usb"], bandpass=bandpass, requirements=requirements, service=True)
super().__init__(modulation, name, bandpass=bandpass, requirements=requirements, service=True, configs=["usb"])
@abstractmethod
def get_profile_source(self) -> ProfileSource:
@ -135,15 +156,18 @@ class Modes(object):
),
AnalogMode("drm", "DRM", bandpass=Bandpass(-5000, 5000), requirements=["drm"], squelch=False),
AnalogMode("dab", "DAB", bandpass=None, ifRate=2.048e6, requirements=["dab"], squelch=False),
DigitalMode("bpsk31", "BPSK31", underlying=["usb"]),
DigitalMode("bpsk63", "BPSK63", underlying=["usb"]),
DigitalMode("rtty170", "RTTY 45/170", underlying=["usb", "lsb"]),
DigitalMode("rtty450", "RTTY 50N/450", underlying=["lsb", "usb"]),
DigitalMode("rtty85", "RTTY 50N/85", underlying=["lsb", "usb"]),
DigitalMode("bpsk31", "BPSK31", configs=["usb"]),
DigitalMode("bpsk63", "BPSK63", configs=["usb"]),
DigitalMode("rtty170", "RTTY 45/170", configs=["usb", "lsb"]),
DigitalMode("rtty450", "RTTY 50N/450", configs=["lsb", "usb"]),
DigitalMode("rtty85", "RTTY 50N/85", configs=["lsb", "usb"]),
DigitalMode(
"sstv",
"SSTV",
underlying=["usb", "lsb"],
configs={
"usb": DigitalUnderlyingConfig(bandpass=Bandpass(1100, 2400)),
"lsb": DigitalUnderlyingConfig(bandpass=Bandpass(-2400, -1100)),
},
bandpass=Bandpass(1100, 2400),
requirements=["sstv"],
service=True
@ -156,12 +180,12 @@ class Modes(object):
WsjtMode("fst4", "FST4", requirements=["wsjt-x-2-3"]),
WsjtMode("fst4w", "FST4W", bandpass=Bandpass(1350, 1650), requirements=["wsjt-x-2-3"]),
WsjtMode("q65", "Q65", requirements=["wsjt-x-2-4"]),
DigitalMode("msk144", "MSK144", requirements=["msk144"], underlying=["usb"], service=True),
DigitalMode("msk144", "MSK144", requirements=["msk144"], configs=["usb"], service=True),
Js8Mode("js8", "JS8Call"),
DigitalMode(
"packet",
"Packet",
underlying=["nfm", "usb", "lsb"],
configs=["nfm", "usb", "lsb"],
bandpass=Bandpass(-6250, 6250),
requirements=["packet"],
service=True,
@ -170,7 +194,7 @@ class Modes(object):
DigitalMode(
"pocsag",
"Pocsag",
underlying=["nfm"],
configs=["nfm"],
bandpass=Bandpass(-6250, 6250),
requirements=["pocsag"],
service=True,
@ -179,7 +203,7 @@ class Modes(object):
DigitalMode(
"adsb",
"ADS-B",
underlying=["empty"],
configs=["empty"],
bandpass=None,
ifRate=2.4e6,
requirements=["dump1090"],
@ -190,7 +214,7 @@ class Modes(object):
DigitalMode(
"ism",
"ISM",
underlying=["empty"],
configs=["empty"],
bandpass=Bandpass(-125000, 125000),
requirements=["ism"],
service=True,
@ -199,7 +223,7 @@ class Modes(object):
DigitalMode(
"hfdl",
"HFDL",
underlying=["empty"],
configs=["empty"],
bandpass=Bandpass(0, 3000),
requirements=["dumphfdl"],
service=True,
@ -208,7 +232,7 @@ class Modes(object):
DigitalMode(
"vdl2",
"VDL2",
underlying=["empty"],
configs=["empty"],
bandpass=Bandpass(-12500, 12500),
requirements=["dumpvdl2"],
service=True,