Compare commits
2 Commits
develop
...
underlying
Author | SHA1 | Date | |
---|---|---|---|
|
258aebd0c3 | ||
|
a54a5fd560 |
@ -11,7 +11,7 @@ function BookmarkBar() {
|
|||||||
if (!b || !b.frequency || !b.modulation) return;
|
if (!b || !b.frequency || !b.modulation) return;
|
||||||
me.getDemodulator().set_offset_frequency(b.frequency - center_freq);
|
me.getDemodulator().set_offset_frequency(b.frequency - center_freq);
|
||||||
if (b.modulation) {
|
if (b.modulation) {
|
||||||
me.getDemodulatorPanel().setMode(b.modulation);
|
me.getDemodulatorPanel().setMode(b.modulation, b.underlying);
|
||||||
}
|
}
|
||||||
$bookmark.addClass('selected');
|
$bookmark.addClass('selected');
|
||||||
});
|
});
|
||||||
|
@ -18,7 +18,12 @@ function DemodulatorPanel(el) {
|
|||||||
el.on('click', '.openwebrx-demodulator-button', function() {
|
el.on('click', '.openwebrx-demodulator-button', function() {
|
||||||
var modulation = $(this).data('modulation');
|
var modulation = $(this).data('modulation');
|
||||||
if (modulation) {
|
if (modulation) {
|
||||||
self.setMode(modulation);
|
if (self.mode && self.mode.type === 'digimode' && self.mode.underlying.indexOf(modulation) >= 0) {
|
||||||
|
// keep the mode, just switch underlying modulation
|
||||||
|
self.setMode(self.mode.modulation, modulation)
|
||||||
|
} else {
|
||||||
|
self.setMode(modulation);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
self.disableDigiMode();
|
self.disableDigiMode();
|
||||||
}
|
}
|
||||||
@ -80,12 +85,13 @@ DemodulatorPanel.prototype.render = function() {
|
|||||||
this.el.find(".openwebrx-modes").html(html);
|
this.el.find(".openwebrx-modes").html(html);
|
||||||
};
|
};
|
||||||
|
|
||||||
DemodulatorPanel.prototype.setMode = function(requestedModulation) {
|
DemodulatorPanel.prototype.setMode = function(requestedModulation, underlyingModulation) {
|
||||||
var mode = Modes.findByModulation(requestedModulation);
|
var mode = Modes.findByModulation(requestedModulation);
|
||||||
if (!mode) {
|
if (!mode) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (this.mode === mode) {
|
|
||||||
|
if (this.mode === mode && this.underlyingModulation === underlyingModulation) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!mode.isAvailable()) {
|
if (!mode.isAvailable()) {
|
||||||
@ -93,16 +99,15 @@ DemodulatorPanel.prototype.setMode = function(requestedModulation) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var modulation;
|
||||||
if (mode.type === 'digimode') {
|
if (mode.type === 'digimode') {
|
||||||
modulation = mode.underlying[0];
|
if (underlyingModulation) {
|
||||||
} else {
|
modulation = underlyingModulation
|
||||||
if (this.mode && this.mode.type === 'digimode' && this.mode.underlying.indexOf(requestedModulation) >= 0) {
|
|
||||||
// keep the mode, just switch underlying modulation
|
|
||||||
mode = this.mode;
|
|
||||||
modulation = requestedModulation;
|
|
||||||
} else {
|
} else {
|
||||||
modulation = mode.modulation;
|
modulation = mode.underlying[0];
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
modulation = mode.modulation;
|
||||||
}
|
}
|
||||||
|
|
||||||
var current = this.collectParams();
|
var current = this.collectParams();
|
||||||
@ -142,6 +147,7 @@ DemodulatorPanel.prototype.setMode = function(requestedModulation) {
|
|||||||
|
|
||||||
this.demodulator.start();
|
this.demodulator.start();
|
||||||
this.mode = mode;
|
this.mode = mode;
|
||||||
|
this.underlyingModulation = modulation;
|
||||||
|
|
||||||
this.updateButtons();
|
this.updateButtons();
|
||||||
this.updatePanels();
|
this.updatePanels();
|
||||||
@ -149,8 +155,6 @@ DemodulatorPanel.prototype.setMode = function(requestedModulation) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
DemodulatorPanel.prototype.disableDigiMode = function() {
|
DemodulatorPanel.prototype.disableDigiMode = function() {
|
||||||
// just a little trick to get out of the digimode
|
|
||||||
delete this.mode;
|
|
||||||
this.setMode(this.getDemodulator().get_modulation());
|
this.setMode(this.getDemodulator().get_modulation());
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -203,7 +207,11 @@ DemodulatorPanel.prototype.stopDemodulator = function() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
DemodulatorPanel.prototype._apply = function(params) {
|
DemodulatorPanel.prototype._apply = function(params) {
|
||||||
this.setMode(params.mod);
|
if (params.secondary_mod) {
|
||||||
|
this.setMode(params.secondary_mod, params.mod)
|
||||||
|
} else {
|
||||||
|
this.setMode(params.mod);
|
||||||
|
}
|
||||||
this.getDemodulator().set_offset_frequency(params.offset_frequency);
|
this.getDemodulator().set_offset_frequency(params.offset_frequency);
|
||||||
this.getDemodulator().setSquelch(params.squelch_level);
|
this.getDemodulator().setSquelch(params.squelch_level);
|
||||||
this.updateButtons();
|
this.updateButtons();
|
||||||
@ -223,8 +231,9 @@ DemodulatorPanel.prototype.onHashChange = function() {
|
|||||||
|
|
||||||
DemodulatorPanel.prototype.transformHashParams = function(params) {
|
DemodulatorPanel.prototype.transformHashParams = function(params) {
|
||||||
var ret = {
|
var ret = {
|
||||||
mod: params.secondary_mod || params.mod
|
mod: params.mod
|
||||||
};
|
};
|
||||||
|
if (typeof(params.secondary_mod) !== 'undefined') ret.secondary_mod = params.secondary_mod;
|
||||||
if (typeof(params.offset_frequency) !== 'undefined') ret.offset_frequency = params.offset_frequency;
|
if (typeof(params.offset_frequency) !== 'undefined') ret.offset_frequency = params.offset_frequency;
|
||||||
if (typeof(params.sql) !== 'undefined') ret.squelch_level = parseInt(params.sql);
|
if (typeof(params.sql) !== 'undefined') ret.squelch_level = parseInt(params.sql);
|
||||||
return ret;
|
return ret;
|
||||||
@ -329,7 +338,7 @@ DemodulatorPanel.prototype.updateHash = function() {
|
|||||||
freq: demod.get_offset_frequency() + self.center_freq,
|
freq: demod.get_offset_frequency() + self.center_freq,
|
||||||
mod: demod.get_modulation(),
|
mod: demod.get_modulation(),
|
||||||
secondary_mod: demod.get_secondary_demod(),
|
secondary_mod: demod.get_secondary_demod(),
|
||||||
sql: demod.getSquelch(),
|
sql: demod.getSquelch()
|
||||||
}, function(value, key){
|
}, function(value, key){
|
||||||
if (typeof(value) === 'undefined' || value === false) return undefined;
|
if (typeof(value) === 'undefined' || value === false) return undefined;
|
||||||
return key + '=' + value;
|
return key + '=' + value;
|
||||||
|
@ -831,7 +831,8 @@ function on_ws_recv(evt) {
|
|||||||
return {
|
return {
|
||||||
name: d['mode'].toUpperCase(),
|
name: d['mode'].toUpperCase(),
|
||||||
modulation: d['mode'],
|
modulation: d['mode'],
|
||||||
frequency: d['frequency']
|
frequency: d['frequency'],
|
||||||
|
underlying: d['underlying']
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
bookmarks.replace_bookmarks(as_bookmarks, 'dial_frequencies');
|
bookmarks.replace_bookmarks(as_bookmarks, 'dial_frequencies');
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
from owrx.modes import Modes
|
from owrx.modes import Modes, DigitalMode
|
||||||
from datetime import datetime, timezone
|
from datetime import datetime, timezone
|
||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
@ -9,14 +9,14 @@ logger = logging.getLogger(__name__)
|
|||||||
|
|
||||||
|
|
||||||
class Band(object):
|
class Band(object):
|
||||||
def __init__(self, dict):
|
def __init__(self, b_dict):
|
||||||
self.name = dict["name"]
|
self.name = b_dict["name"]
|
||||||
self.lower_bound = dict["lower_bound"]
|
self.lower_bound = b_dict["lower_bound"]
|
||||||
self.upper_bound = dict["upper_bound"]
|
self.upper_bound = b_dict["upper_bound"]
|
||||||
self.frequencies = []
|
self.frequencies = []
|
||||||
if "frequencies" in dict:
|
if "frequencies" in b_dict:
|
||||||
availableModes = [mode.modulation for mode in Modes.getAvailableModes()]
|
availableModes = [mode.modulation for mode in Modes.getAvailableModes()]
|
||||||
for (mode, freqs) in dict["frequencies"].items():
|
for (mode, freqs) in b_dict["frequencies"].items():
|
||||||
if mode not in availableModes:
|
if mode not in availableModes:
|
||||||
logger.info(
|
logger.info(
|
||||||
'Modulation "{mode}" is not available, bandplan bookmark will not be displayed'.format(
|
'Modulation "{mode}" is not available, bandplan bookmark will not be displayed'.format(
|
||||||
@ -27,14 +27,30 @@ class Band(object):
|
|||||||
if not isinstance(freqs, list):
|
if not isinstance(freqs, list):
|
||||||
freqs = [freqs]
|
freqs = [freqs]
|
||||||
for f in freqs:
|
for f in freqs:
|
||||||
if not self.inBand(f):
|
f_dict = {"frequency": f} if not isinstance(f, dict) else f
|
||||||
|
f_dict["mode"] = mode
|
||||||
|
|
||||||
|
if not self.inBand(f_dict["frequency"]):
|
||||||
logger.warning(
|
logger.warning(
|
||||||
"Frequency for {mode} on {band} is not within band limits: {frequency}".format(
|
"Frequency for {mode} on {band} is not within band limits: {frequency}".format(
|
||||||
mode=mode, frequency=f, band=self.name
|
mode=mode, frequency=f_dict["frequency"], band=self.name
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
continue
|
continue
|
||||||
self.frequencies.append({"mode": mode, "frequency": f})
|
|
||||||
|
if "underlying" in f_dict:
|
||||||
|
m = Modes.findByModulation(mode)
|
||||||
|
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:
|
||||||
|
logger.warning(
|
||||||
|
"%s is not a valid underlying mode for %s; skipping",
|
||||||
|
f_dict["underlying"],
|
||||||
|
mode
|
||||||
|
)
|
||||||
|
|
||||||
|
self.frequencies.append(f_dict)
|
||||||
|
|
||||||
def inBand(self, freq):
|
def inBand(self, freq):
|
||||||
return self.lower_bound <= freq <= self.upper_bound
|
return self.lower_bound <= freq <= self.upper_bound
|
||||||
|
@ -55,6 +55,13 @@ class DigitalMode(Mode):
|
|||||||
def get_modulation(self):
|
def get_modulation(self):
|
||||||
return self.get_underlying_mode().get_modulation()
|
return self.get_underlying_mode().get_modulation()
|
||||||
|
|
||||||
|
def for_underlying(self, underlying: str):
|
||||||
|
if underlying not in self.underlying:
|
||||||
|
raise ValueError("{} is not a valid underlying mode for {}".format(underlying, self.modulation))
|
||||||
|
return DigitalMode(
|
||||||
|
self.modulation, self.name, [underlying], self.bandpass, self.requirements, self.service, self.squelch
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class AudioChopperMode(DigitalMode, metaclass=ABCMeta):
|
class AudioChopperMode(DigitalMode, metaclass=ABCMeta):
|
||||||
def __init__(self, modulation, name, bandpass=None, requirements=None):
|
def __init__(self, modulation, name, bandpass=None, requirements=None):
|
||||||
|
@ -123,13 +123,11 @@ class ServiceHandler(SdrSourceEventClient):
|
|||||||
|
|
||||||
def updateServices(self):
|
def updateServices(self):
|
||||||
def addService(dial, source):
|
def addService(dial, source):
|
||||||
mode = dial["mode"]
|
|
||||||
frequency = dial["frequency"]
|
|
||||||
try:
|
try:
|
||||||
service = self.setupService(mode, frequency, source)
|
service = self.setupService(dial, source)
|
||||||
self.services.append(service)
|
self.services.append(service)
|
||||||
except Exception:
|
except Exception:
|
||||||
logger.exception("Error setting up service %s on frequency %d", mode, frequency)
|
logger.exception("Error setting up service {mode} on frequency {frequency}".format(**dial))
|
||||||
|
|
||||||
with self.lock:
|
with self.lock:
|
||||||
logger.debug("re-scheduling services due to sdr changes")
|
logger.debug("re-scheduling services due to sdr changes")
|
||||||
@ -247,23 +245,26 @@ class ServiceHandler(SdrSourceEventClient):
|
|||||||
return None
|
return None
|
||||||
return best["groups"]
|
return best["groups"]
|
||||||
|
|
||||||
def setupService(self, mode, frequency, source):
|
def setupService(self, dial, source):
|
||||||
logger.debug("setting up service {0} on frequency {1}".format(mode, frequency))
|
logger.debug("setting up service {mode} on frequency {frequency}".format(**dial))
|
||||||
|
|
||||||
modeObject = Modes.findByModulation(mode)
|
modeObject = Modes.findByModulation(dial["mode"])
|
||||||
if not isinstance(modeObject, DigitalMode):
|
if not isinstance(modeObject, DigitalMode):
|
||||||
logger.warning("mode is not a digimode: %s", mode)
|
logger.warning("mode is not a digimode: %s", dial["mode"])
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
if "underlying" in dial:
|
||||||
|
modeObject = modeObject.for_underlying(dial["underlying"])
|
||||||
|
|
||||||
demod = self._getDemodulator(modeObject.get_modulation())
|
demod = self._getDemodulator(modeObject.get_modulation())
|
||||||
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()
|
bandpass = modeObject.get_bandpass()
|
||||||
if isinstance(secondaryDemod, DialFrequencyReceiver):
|
if isinstance(secondaryDemod, DialFrequencyReceiver):
|
||||||
secondaryDemod.setDialFrequency(frequency)
|
secondaryDemod.setDialFrequency(dial["frequency"])
|
||||||
|
|
||||||
chain = ServiceDemodulatorChain(demod, secondaryDemod, sampleRate, frequency - center_freq)
|
chain = ServiceDemodulatorChain(demod, secondaryDemod, sampleRate, dial["frequency"] - center_freq)
|
||||||
chain.setBandPass(bandpass.low_cut, bandpass.high_cut)
|
chain.setBandPass(bandpass.low_cut, bandpass.high_cut)
|
||||||
chain.setReader(source.getBuffer().getReader())
|
chain.setReader(source.getBuffer().getReader())
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user