use super::dvb_t_frame::{DvbTFrameDemod, DvbTRxError, DvbTRxFrame};
use crate::sync::dvb_t_gi_sync;
use crate::waveform::dvb_t::{DVB_T_N_FFT, DvbTFrameParams};
use num_complex::Complex32 as C32;
pub struct DvbTFrameStreamDemod {
demod: DvbTFrameDemod,
n_symbols: usize,
payload_len: usize,
sps: usize,
buf: Vec<C32>,
}
impl DvbTFrameStreamDemod {
pub fn new(params: DvbTFrameParams, n_symbols: usize, payload_len: usize) -> Self {
let cp_len = params.config().carrier_plan.cp_len();
Self {
demod: DvbTFrameDemod::new(params),
n_symbols,
payload_len,
sps: DVB_T_N_FFT + cp_len,
buf: Vec::new(),
}
}
pub fn with_integer_cfo_correction(mut self, on: bool) -> Self {
self.demod = self.demod.with_integer_cfo_correction(on);
self
}
pub fn with_rx_window_backoff(mut self, backoff: usize) -> Self {
self.demod = self.demod.with_rx_window_backoff(backoff);
self
}
pub fn len(&self) -> usize {
self.buf.len()
}
pub fn is_empty(&self) -> bool {
self.buf.is_empty()
}
pub fn view_buf(&self) -> &[C32] {
&self.buf
}
pub fn clear(&mut self) {
self.buf.clear();
}
fn frame_samples(&self) -> usize {
self.n_symbols * self.sps
}
pub fn feed(&mut self, iq: &[C32]) -> Vec<Result<DvbTRxFrame, DvbTRxError>> {
self.buf.extend_from_slice(iq);
self.drain()
}
pub fn flush(&mut self) -> Vec<Result<DvbTRxFrame, DvbTRxError>> {
self.drain()
}
fn drain(&mut self) -> Vec<Result<DvbTRxFrame, DvbTRxError>> {
let mut out = Vec::new();
while let FrameStep::Decoded(result, consume_to) = self.try_one_frame() {
self.buf.drain(..consume_to);
out.push(result);
}
out
}
fn try_one_frame(&mut self) -> FrameStep {
let n_fft = DVB_T_N_FFT;
let cp_len = self.sps - n_fft;
let fs = self.demod.params().config().fs;
let need = self.sps + self.frame_samples();
if self.buf.len() < need {
return FrameStep::NeedMore;
}
let Some(acq) = dvb_t_gi_sync(&self.buf, n_fft, cp_len, fs, self.sps) else {
return FrameStep::NeedMore;
};
let start = acq.start_sample;
let consume_to = start + self.frame_samples();
if consume_to > self.buf.len() {
return FrameStep::NeedMore;
}
match self
.demod
.decode(&self.buf[start..], self.n_symbols, self.payload_len)
{
Ok(frame) => FrameStep::Decoded(Ok(frame), consume_to),
Err(e) => FrameStep::Decoded(Err(e), consume_to),
}
}
}
enum FrameStep {
Decoded(Result<DvbTRxFrame, DvbTRxError>, usize),
NeedMore,
}