implement frequency correction feedback loop

This commit is contained in:
Jakob Ketterl 2024-01-23 21:52:41 +01:00
parent 5ddd719364
commit 9d705da813
2 changed files with 55 additions and 3 deletions

View File

@ -1,21 +1,73 @@
from csdr.chain.demodulator import BaseDemodulatorChain, FixedIfSampleRateChain, FixedAudioRateChain, HdAudio from csdr.chain.demodulator import BaseDemodulatorChain, FixedIfSampleRateChain, FixedAudioRateChain, HdAudio
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
from pycsdr.modules import Downmix from pycsdr.modules import Downmix, Buffer, Shift
from pycsdr.types import Format from pycsdr.types import Format
from typing import Optional
from random import random
import logging
logger = logging.getLogger(__name__)
class MetaProcessor(PickleModule):
def __init__(self, shifter: Shift):
self.shifter = shifter
self.shift = 0.0
self.coarse_increment = -32 / 2048000
self.fine_increment = - (1/3) / 2048000
super().__init__()
def process(self, data):
if "coarse_frequency_shift" in data:
value = int(data["coarse_frequency_shift"])
if value > 0:
self.shift += random() * self.coarse_increment
else:
self.shift -= random() * self.coarse_increment
logger.debug("coarse adjustment - new shift: %f", self.shift)
self.shifter.setRate(self.shift)
if "fine_frequency_shift" in data:
value = float(data["fine_frequency_shift"])
if abs(value) > 10:
self.shift += self.fine_increment * value
logger.debug("ffs: %f", value)
logger.debug("fine adjustment - new shift: %f", self.shift)
self.shifter.setRate(self.shift)
class Dablin(BaseDemodulatorChain, FixedIfSampleRateChain, FixedAudioRateChain, HdAudio): class Dablin(BaseDemodulatorChain, FixedIfSampleRateChain, FixedAudioRateChain, HdAudio):
def __init__(self): def __init__(self):
shift = Shift(0)
decoder = EtiDecoder()
metaBuffer = Buffer(Format.CHAR)
decoder.setMetaWriter(metaBuffer)
self.processor = MetaProcessor(shift)
self.processor.setReader(metaBuffer.getReader())
self.processor.setWriter(Buffer(Format.CHAR))
workers = [ workers = [
EtiDecoder(), shift,
decoder,
DablinModule(), DablinModule(),
Downmix(Format.FLOAT), Downmix(Format.FLOAT),
] ]
super().__init__(workers) super().__init__(workers)
def _connect(self, w1, w2, buffer: Optional[Buffer] = None) -> None:
if isinstance(w2, EtiDecoder):
# eti decoder needs big chunks of data
buffer = Buffer(w1.getOutputFormat(), size=1048576)
super()._connect(w1, w2, buffer)
def getFixedIfSampleRate(self) -> int: def getFixedIfSampleRate(self) -> int:
return 2048000 return 2048000
def getFixedAudioRate(self) -> int: def getFixedAudioRate(self) -> int:
return 48000 return 48000
def stop(self):
self.processor.stop()

View File

@ -40,7 +40,7 @@ class ClientDemodulatorChain(Chain):
self.hdOutputRate = hdOutputRate self.hdOutputRate = hdOutputRate
self.secondaryDspEventReceiver = secondaryDspEventReceiver self.secondaryDspEventReceiver = secondaryDspEventReceiver
self.selector = Selector(sampleRate, outputRate) self.selector = Selector(sampleRate, outputRate)
self.selectorBuffer = Buffer(Format.COMPLEX_FLOAT, size=524288) self.selectorBuffer = Buffer(Format.COMPLEX_FLOAT)
self.audioBuffer = None self.audioBuffer = None
self.demodulator = demod self.demodulator = demod
self.secondaryDemodulator = None self.secondaryDemodulator = None