use super::config::{CarrierPlan, SubcarrierRole};
use crate::core::{Block, WorkReport};
use num_complex::Complex32 as C32;
#[derive(Debug, Clone)]
pub struct CarrierGrid {
n_fft: usize,
role: Vec<SubcarrierRole>,
data_bins: Vec<usize>,
pilot_bins: Vec<(usize, C32)>,
}
impl CarrierGrid {
pub fn from_plan(plan: &CarrierPlan) -> Self {
plan.validate()
.expect("CarrierGrid::from_plan: invalid CarrierPlan");
let n_fft = plan.n_fft();
let mut role = vec![SubcarrierRole::Null; n_fft];
let mut data_bins = Vec::with_capacity(plan.data_carriers().len());
for &idx in plan.data_carriers() {
let bin = idx.rem_euclid(n_fft as i32) as usize;
role[bin] = SubcarrierRole::Data;
data_bins.push(bin);
}
let mut pilot_bins = Vec::with_capacity(plan.pilot_carriers().len());
for &(idx, value) in plan.pilot_carriers() {
let bin = idx.rem_euclid(n_fft as i32) as usize;
role[bin] = SubcarrierRole::Pilot;
pilot_bins.push((bin, value));
}
Self {
n_fft,
role,
data_bins,
pilot_bins,
}
}
pub fn n_fft(&self) -> usize {
self.n_fft
}
pub fn role(&self) -> &[SubcarrierRole] {
&self.role
}
pub fn data_bins(&self) -> &[usize] {
&self.data_bins
}
pub fn pilot_bins(&self) -> &[(usize, C32)] {
&self.pilot_bins
}
pub fn num_data_carriers(&self) -> usize {
self.data_bins.len()
}
}
#[derive(Debug, Clone)]
pub struct GridMap {
grid: CarrierGrid,
}
impl GridMap {
pub fn new(grid: CarrierGrid) -> Self {
Self { grid }
}
pub fn num_data_carriers(&self) -> usize {
self.grid.num_data_carriers()
}
pub fn n_fft(&self) -> usize {
self.grid.n_fft()
}
}
impl Block for GridMap {
type In = C32;
type Out = C32;
fn process(&mut self, input: &[C32], output: &mut [C32]) -> WorkReport {
let n_data = self.grid.num_data_carriers();
let n_fft = self.grid.n_fft();
if input.len() < n_data || output.len() < n_fft {
return WorkReport::default();
}
for bin in output[..n_fft].iter_mut() {
*bin = C32::default();
}
for (k, &bin) in self.grid.data_bins().iter().enumerate() {
output[bin] = input[k];
}
for &(bin, value) in self.grid.pilot_bins() {
output[bin] = value;
}
WorkReport {
in_read: n_data,
out_written: n_fft,
}
}
}
#[derive(Debug, Clone)]
pub struct GridExtract {
grid: CarrierGrid,
}
impl GridExtract {
pub fn new(grid: CarrierGrid) -> Self {
Self { grid }
}
pub fn num_data_carriers(&self) -> usize {
self.grid.num_data_carriers()
}
pub fn n_fft(&self) -> usize {
self.grid.n_fft()
}
}
impl Block for GridExtract {
type In = C32;
type Out = C32;
fn process(&mut self, input: &[C32], output: &mut [C32]) -> WorkReport {
let n_fft = self.grid.n_fft();
let n_data = self.grid.num_data_carriers();
if input.len() < n_fft || output.len() < n_data {
return WorkReport::default();
}
for (k, &bin) in self.grid.data_bins().iter().enumerate() {
output[k] = input[bin];
}
WorkReport {
in_read: n_fft,
out_written: n_data,
}
}
}