Adding NAVTEX decoder and service.

This commit is contained in:
Marat Fayzullin 2024-04-06 17:16:34 -04:00
parent 5c719cc74b
commit 86b746edc4
5 changed files with 62 additions and 13 deletions

View File

@ -3,12 +3,12 @@ from csdr.module.msk144 import Msk144Module, ParserAdapter
from owrx.audio.chopper import AudioChopper, AudioChopperParser
from owrx.aprs.kiss import KissDeframer
from owrx.aprs import Ax25Parser, AprsParser
from pycsdr.modules import Convert, FmDemod, Agc, TimingRecovery, DBPskDecoder, VaricodeDecoder, RttyDecoder, BaudotDecoder, Lowpass, MFRttyDecoder, CwDecoder, SstvDecoder, FaxDecoder, SitorBDecoder, Ccir476Decoder, DscDecoder, Ccir493Decoder, Shift
from pycsdr.modules import Convert, FmDemod, Agc, TimingRecovery, DBPskDecoder, VaricodeDecoder, RttyDecoder, BaudotDecoder, Lowpass, MFRttyDecoder, CwDecoder, SstvDecoder, FaxDecoder, SitorBDecoder, Ccir476Decoder, DscDecoder, Ccir493Decoder, NavtexDecoder, Shift
from pycsdr.types import Format
from owrx.aprs.direwolf import DirewolfModule
from owrx.sstv import SstvParser
from owrx.fax import FaxParser
from owrx.dsc import DscParser
from owrx.marine import DscParser, NavtexParser
from owrx.config import Config
@ -226,9 +226,8 @@ class FaxDemodulator(ServiceDemodulator, DialFrequencyReceiver):
class SitorBDemodulator(SecondaryDemodulator, SecondarySelectorChain):
def __init__(self, baudRate=100, bandWidth=170, invert=False):
self.baudRate = baudRate
self.baudRate = baudRate
self.bandWidth = bandWidth
self.invert = invert
# this is an assumption, we will adjust in setSampleRate
self.sampleRate = self.bandWidth * 10 #12000
secondary_samples_per_bit = int(round(self.sampleRate / self.baudRate))
@ -260,10 +259,9 @@ class SitorBDemodulator(SecondaryDemodulator, SecondarySelectorChain):
class DscDemodulator(SecondaryDemodulator, SecondarySelectorChain, DialFrequencyReceiver):
def __init__(self, baudRate=100, bandWidth=170, invert=False, service=False):
self.baudRate = baudRate
self.bandWidth = bandWidth
self.invert = invert
self.parser = DscParser(service=service)
self.baudRate = baudRate
self.bandWidth = bandWidth
self.parser = DscParser(service=service)
# this is an assumption, we will adjust in setSampleRate
self.sampleRate = self.bandWidth * 10 #12000
secondary_samples_per_bit = int(round(self.sampleRate / self.baudRate))
@ -300,3 +298,46 @@ class DscDemodulator(SecondaryDemodulator, SecondarySelectorChain, DialFrequency
# ServiceDemodulator
def getFixedAudioRate(self):
return self.sampleRate
class NavtexDemodulator(SecondaryDemodulator, SecondarySelectorChain, DialFrequencyReceiver):
def __init__(self, baudRate=100, bandWidth=170, invert=False, service=False):
self.baudRate = baudRate
self.bandWidth = bandWidth
self.parser = NavtexParser(service=service)
# this is an assumption, we will adjust in setSampleRate
self.sampleRate = self.bandWidth * 10 #12000
secondary_samples_per_bit = int(round(self.sampleRate / self.baudRate))
cutoff = self.baudRate / self.sampleRate
loop_gain = self.sampleRate / self.getBandwidth() / 5
workers = [
Agc(Format.COMPLEX_FLOAT),
FmDemod(),
Lowpass(Format.FLOAT, cutoff),
TimingRecovery(Format.FLOAT, secondary_samples_per_bit, loop_gain, 10),
SitorBDecoder(invert=invert),
Ccir476Decoder(),
self.parser
]
super().__init__(workers)
def getBandwidth(self) -> float:
return self.bandWidth
def setSampleRate(self, sampleRate: int) -> None:
if sampleRate == self.sampleRate:
return
self.sampleRate = sampleRate
secondary_samples_per_bit = int(round(self.sampleRate / self.baudRate))
cutoff = self.baudRate / self.sampleRate
loop_gain = self.sampleRate / self.getBandwidth() / 5
self.replace(2, Lowpass(Format.FLOAT, cutoff))
self.replace(3, TimingRecovery(Format.FLOAT, secondary_samples_per_bit, loop_gain, 10))
# DialFrequencyReceiver
def setDialFrequency(self, frequency: int) -> None:
self.parser.setDialFrequency(frequency)
# ServiceDemodulator
def getFixedAudioRate(self):
return self.sampleRate

View File

@ -698,6 +698,9 @@ class DspManager(SdrSourceEventClient, ClientDemodulatorSecondaryDspEventClient)
elif mod == "sitorb":
from csdr.chain.digimodes import SitorBDemodulator
return SitorBDemodulator(100, 170 + 40)
elif mod == "navtex":
from csdr.chain.digimodes import NavtexDemodulator
return NavtexDemodulator(100, 170 + 40)
elif mod == "dsc":
from csdr.chain.digimodes import DscDemodulator
return DscDemodulator(100, 170 + 40)

View File

@ -8,18 +8,19 @@ import logging
logger = logging.getLogger(__name__)
class NavtexParser(TextParser):
def __init__(self, service: bool = False):
# Construct parent object
super().__init__(filePrefix="NAVTEX", service=service)
class DscParser(TextParser):
def __init__(self, service: bool = False):
# Colors will be assigned via this cache
self.colors = ColorCache()
# No frequency yet
self.frequency = 0
# Construct parent object
super().__init__(filePrefix="DSC", service=service)
def setDialFrequency(self, frequency: int) -> None:
self.frequency = frequency
def parse(self, msg: bytes):
# Do not parse in service mode
#if self.service:

View File

@ -142,6 +142,7 @@ class Modes(object):
DigitalMode("rtty450", "RTTY-450 (50N)", underlying=["usb", "lsb"]),
DigitalMode("rtty85", "RTTY-85 (50N)", underlying=["usb", "lsb"]),
DigitalMode("sitorb", "SITOR-B", underlying=["usb"]),
DigitalMode("navtex", "NAVTEX", underlying=["usb"], service=True),
DigitalMode("dsc", "DSC", underlying=["usb"], service=True),
WsjtMode("ft8", "FT8"),
WsjtMode("ft4", "FT4"),

View File

@ -326,6 +326,9 @@ class ServiceHandler(SdrSourceEventClient):
elif mod == "fax":
from csdr.chain.digimodes import FaxDemodulator
return FaxDemodulator(service=True)
elif mod == "navtex":
from csdr.chain.digimodes import NavtexDemodulator
return NavtexDemodulator(100, 170 + 40, service=True)
elif mod == "dsc":
from csdr.chain.digimodes import DscDemodulator
return DscDemodulator(100, 170 + 40, service=True)