use super::dvb_t_frame::{DvbTRxError, DvbTRxFrame, dvb_t_frame_demodulate};
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 {
params: DvbTFrameParams,
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 {
params,
n_symbols,
payload_len,
sps: DVB_T_N_FFT + cp_len,
buf: Vec::new(),
}
}
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.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 dvb_t_frame_demodulate(
self.params,
&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,
}