add DAB service selector

This commit is contained in:
Jakob Ketterl 2024-01-25 00:10:25 +01:00
parent f33dfda005
commit ad1b693dcb
7 changed files with 56 additions and 13 deletions

View file

@ -1,4 +1,5 @@
from csdr.chain.demodulator import BaseDemodulatorChain, FixedIfSampleRateChain, FixedAudioRateChain, HdAudio, MetaProvider from csdr.chain.demodulator import BaseDemodulatorChain, FixedIfSampleRateChain, FixedAudioRateChain, HdAudio, \
MetaProvider, DabServiceSelector
from csdr.module import PickleModule from csdr.module import PickleModule
from csdreti.modules import EtiDecoder from csdreti.modules import EtiDecoder
from owrx.dab.dablin import DablinModule from owrx.dab.dablin import DablinModule
@ -46,7 +47,7 @@ class MetaProcessor(PickleModule):
return result return result
class Dablin(BaseDemodulatorChain, FixedIfSampleRateChain, FixedAudioRateChain, HdAudio, MetaProvider): class Dablin(BaseDemodulatorChain, FixedIfSampleRateChain, FixedAudioRateChain, HdAudio, MetaProvider, DabServiceSelector):
def __init__(self): def __init__(self):
shift = Shift(0) shift = Shift(0)
decoder = EtiDecoder() decoder = EtiDecoder()
@ -59,10 +60,12 @@ class Dablin(BaseDemodulatorChain, FixedIfSampleRateChain, FixedAudioRateChain,
# will be replaced by setMetaWriter(). # will be replaced by setMetaWriter().
self.processor.setWriter(Buffer(Format.CHAR)) self.processor.setWriter(Buffer(Format.CHAR))
self.dablin = DablinModule()
workers = [ workers = [
shift, shift,
decoder, decoder,
DablinModule(), self.dablin,
Downmix(Format.FLOAT), Downmix(Format.FLOAT),
] ]
super().__init__(workers) super().__init__(workers)
@ -84,3 +87,6 @@ class Dablin(BaseDemodulatorChain, FixedIfSampleRateChain, FixedAudioRateChain,
def setMetaWriter(self, writer: Writer) -> None: def setMetaWriter(self, writer: Writer) -> None:
self.processor.setWriter(writer) self.processor.setWriter(writer)
def setDabServiceId(self, serviceId: int) -> None:
self.dablin.setDabServiceId(serviceId)

View file

@ -55,6 +55,12 @@ class RdsChain(ABC):
pass pass
class DabServiceSelector(ABC):
@abstractmethod
def setDabServiceId(self, serviceId: int) -> None:
pass
class BaseDemodulatorChain(Chain): class BaseDemodulatorChain(Chain):
def supportsSquelch(self) -> bool: def supportsSquelch(self) -> bool:
return True return True

View file

@ -32,13 +32,13 @@ popd
rm -rf js8py rm -rf js8py
git clone https://github.com/jketterl/csdr.git git clone https://github.com/jketterl/csdr.git
# latest develop as of 2024-01-22 (downmix format) # latest develop as of 2024-01-25 (exemodule setargs)
cmakebuild csdr e6ae546a6a1d3fd052fe962eb5a04fd33e794214 cmakebuild csdr 344179a616cdbadf501479ce9ed1b836543e657b
git clone https://github.com/jketterl/pycsdr.git git clone https://github.com/jketterl/pycsdr.git
cd pycsdr cd pycsdr
# latest develop as of 2024-01-22 (downmix format) # latest develop as of 2024-01-25 (execmodule setargs)
git checkout c7dafe83d08b74012e233502dff0bc6e6f17c01c git checkout 9063b8a119e366c31d089596641a24a427e3cbdc
./setup.py install install_headers ./setup.py install install_headers
cd .. cd ..
rm -rf pycsdr rm -rf pycsdr

View file

@ -205,6 +205,7 @@ function Demodulator(offset_frequency, modulation) {
this.filter = new Filter(this); this.filter = new Filter(this);
this.squelch_level = -150; this.squelch_level = -150;
this.dmr_filter = 3; this.dmr_filter = 3;
this.dab_service_id = 0;
this.started = false; this.started = false;
this.state = {}; this.state = {};
this.secondary_demod = false; this.secondary_demod = false;
@ -294,6 +295,7 @@ Demodulator.prototype.set = function () { //this function sends demodulator par
"offset_freq": this.offset_frequency, "offset_freq": this.offset_frequency,
"mod": this.modulation, "mod": this.modulation,
"dmr_filter": this.dmr_filter, "dmr_filter": this.dmr_filter,
"dab_service_id": this.dab_service_id,
"squelch_level": this.squelch_level, "squelch_level": this.squelch_level,
"secondary_mod": this.secondary_demod, "secondary_mod": this.secondary_demod,
"secondary_offset_freq": this.secondary_offset_freq "secondary_offset_freq": this.secondary_offset_freq
@ -331,6 +333,11 @@ Demodulator.prototype.setDmrFilter = function(dmr_filter) {
this.set(); this.set();
}; };
Demodulator.prototype.setDabServiceId = function(dab_service_id) {
this.dab_service_id = dab_service_id;
this.set();
}
Demodulator.prototype.setBandpass = function(bandpass) { Demodulator.prototype.setBandpass = function(bandpass) {
this.bandpass = bandpass; this.bandpass = bandpass;
this.low_cut = bandpass.low_cut; this.low_cut = bandpass.low_cut;

View file

@ -553,9 +553,12 @@ WfmMetaPanel.prototype.clear = function() {
function DabMetaPanel(el) { function DabMetaPanel(el) {
MetaPanel.call(this, el); MetaPanel.call(this, el);
this.modes = ['DAB']; this.modes = ['DAB'];
$(this.el).html( this.$select = $('<select id="dab-service-id"></select>');
'<select id="dab-service-id"></select>' $(this.el).append(this.$select);
) this.$select.on("change", function() {
var service_id = parseInt($(this).val());
$('#openwebrx-panel-receiver').demodulatorPanel().getDemodulator().setDabServiceId(service_id);
});
this.clear(); this.clear();
} }
@ -573,7 +576,10 @@ DabMetaPanel.prototype.update = function(data) {
var options = Object.entries(data.programmes).map(function(e) { var options = Object.entries(data.programmes).map(function(e) {
return '<option value="' + e[0] + '">' + e[1] + '</option>'; return '<option value="' + e[0] + '">' + e[1] + '</option>';
}); });
$(this.el).find('#dab-service-id').html(options.join('')); $(this.el).find('#dab-service-id').html(
'<option value="0" disabled selected></option>' +
options.join('')
);
} }
console.info(data); console.info(data);

View file

@ -4,8 +4,17 @@ from pycsdr.types import Format
class DablinModule(ExecModule): class DablinModule(ExecModule):
def __init__(self): def __init__(self):
self.serviceId = 0
super().__init__( super().__init__(
Format.CHAR, Format.CHAR,
Format.FLOAT, Format.FLOAT,
["dablin", "-1", "-p"] self._buildArgs()
) )
def _buildArgs(self):
return ["dablin", "-p", "-s", "{:#06x}".format(self.serviceId)]
def setDabServiceId(self, serviceId: int) -> None:
self.serviceId = serviceId
self.setArgs(self._buildArgs())
self.restart()

View file

@ -3,7 +3,9 @@ from owrx.property import PropertyStack, PropertyLayer, PropertyValidator, Prope
from owrx.property.validators import OrValidator, RegexValidator, BoolValidator from owrx.property.validators import OrValidator, RegexValidator, BoolValidator
from owrx.modes import Modes, DigitalMode from owrx.modes import Modes, DigitalMode
from csdr.chain import Chain from csdr.chain import Chain
from csdr.chain.demodulator import BaseDemodulatorChain, FixedIfSampleRateChain, FixedAudioRateChain, HdAudio, SecondaryDemodulator, DialFrequencyReceiver, MetaProvider, SlotFilterChain, SecondarySelectorChain, DeemphasisTauChain, DemodulatorError, RdsChain from csdr.chain.demodulator import BaseDemodulatorChain, FixedIfSampleRateChain, FixedAudioRateChain, HdAudio, \
SecondaryDemodulator, DialFrequencyReceiver, MetaProvider, SlotFilterChain, SecondarySelectorChain, \
DeemphasisTauChain, DemodulatorError, RdsChain, DabServiceSelector
from csdr.chain.selector import Selector, SecondarySelector from csdr.chain.selector import Selector, SecondarySelector
from csdr.chain.clientaudio import ClientAudioChain from csdr.chain.clientaudio import ClientAudioChain
from csdr.chain.fft import FftChain from csdr.chain.fft import FftChain
@ -328,6 +330,11 @@ class ClientDemodulatorChain(Chain):
return return
self.demodulator.setSlotFilter(filter) self.demodulator.setSlotFilter(filter)
def setDabServiceId(self, serviceId: int) -> None:
if not isinstance(self.demodulator, DabServiceSelector):
return
self.demodulator.setDabServiceId(serviceId)
def setSecondaryFftSize(self, size: int) -> None: def setSecondaryFftSize(self, size: int) -> None:
if size == self.secondaryFftSize: if size == self.secondaryFftSize:
return return
@ -422,6 +429,7 @@ class DspManager(SdrSourceEventClient, ClientDemodulatorSecondaryDspEventClient)
"mod": ModulationValidator(), "mod": ModulationValidator(),
"secondary_offset_freq": "int", "secondary_offset_freq": "int",
"dmr_filter": "int", "dmr_filter": "int",
"dab_service_id": "int",
} }
self.localProps = PropertyValidator(PropertyLayer().filter(*validators.keys()), validators) self.localProps = PropertyValidator(PropertyLayer().filter(*validators.keys()), validators)
@ -502,6 +510,7 @@ class DspManager(SdrSourceEventClient, ClientDemodulatorSecondaryDspEventClient)
self.props.wireProperty("high_cut", self.setHighCut), self.props.wireProperty("high_cut", self.setHighCut),
self.props.wireProperty("mod", self.setDemodulator), self.props.wireProperty("mod", self.setDemodulator),
self.props.wireProperty("dmr_filter", self.chain.setSlotFilter), self.props.wireProperty("dmr_filter", self.chain.setSlotFilter),
self.props.wireProperty("dab_service_id", self.chain.setDabServiceId),
self.props.wireProperty("wfm_deemphasis_tau", self.chain.setWfmDeemphasisTau), self.props.wireProperty("wfm_deemphasis_tau", self.chain.setWfmDeemphasisTau),
self.props.wireProperty("wfm_rds_rbds", self.chain.setRdsRbds), self.props.wireProperty("wfm_rds_rbds", self.chain.setRdsRbds),
self.props.wireProperty("secondary_mod", self.setSecondaryDemodulator), self.props.wireProperty("secondary_mod", self.setSecondaryDemodulator),