use crate::util::*;
use crate::words::its::{data_words::ib_data_word_id_to_lane, lane_data_frame::LaneDataFrame};
#[derive(Default)]
pub struct AlpideReadoutFrame {
frame_start_mem_pos: u64,
frame_end_mem_pos: u64,
lane_data_frames: Vec<LaneDataFrame>, from_layer: Option<Layer>,
}
impl AlpideReadoutFrame {
const IL_FRAME_LANE_COUNT: usize = 3;
const ML_FRAME_LANE_COUNT: usize = 8;
const OL_FRAME_LANE_COUNT: usize = 14;
pub fn new(start_mem_pos: u64) -> Self {
Self {
frame_start_mem_pos: start_mem_pos,
..Default::default()
}
}
pub fn store_lane_data(&mut self, data_word: &[u8], from_layer: Layer) {
debug_assert_eq!(
self.frame_end_mem_pos, 0,
"Attempted to store lane data after the data frame was closed"
);
if self.from_layer.is_none() {
self.from_layer = Some(from_layer);
}
match self
.lane_data_frames
.iter_mut()
.find(|lane_data_frame| lane_data_frame.id() == data_word[9])
{
Some(lane_data_frame) => {
lane_data_frame.append_data(&data_word[0..=8]);
}
None => self
.lane_data_frames
.push(LaneDataFrame::new(data_word[9], data_word[0..=8].to_vec())),
}
}
pub fn check_frame_lanes_valid(&self, fatal_lanes: Option<&[u8]>) -> Result<(), String> {
debug_assert_ne!(
self.frame_end_mem_pos, 0,
"Attempted check a lane data frame's validity before closing it"
);
let mut expect_lane_count = match self.from_layer() {
Layer::Inner => Self::IL_FRAME_LANE_COUNT,
Layer::Middle => Self::ML_FRAME_LANE_COUNT,
Layer::Outer => Self::OL_FRAME_LANE_COUNT,
};
if let Some(fatal_lanes) = fatal_lanes {
expect_lane_count -= fatal_lanes.len();
}
if self.lane_data_frames.len() != expect_lane_count {
Err(format!(
"Invalid number of lanes: {num_lanes}, expected {expect_lane_count}",
num_lanes = self.lane_data_frames.len()
))
} else if self.from_layer() == Layer::Inner {
validate_inner_lane_groupings(&self.lane_data_frames, fatal_lanes)
} else {
Ok(())
}
}
}
#[inline]
pub(crate) fn validate_inner_lane_groupings(
lane_data_frames: &[LaneDataFrame],
fatal_lanes: Option<&[u8]>,
) -> Result<(), String> {
let mut lane_ids = lane_data_frames
.iter()
.map(|lane_data_frame| ib_data_word_id_to_lane(lane_data_frame.id()))
.collect::<Vec<u8>>();
lane_ids.sort_unstable();
let mut valid_lane_groupings: [Vec<u8>; 3] = [vec![0, 1, 2], vec![3, 4, 5], vec![6, 7, 8]];
if let Some(fatal_lane) = fatal_lanes {
for fl in fatal_lane {
match fl {
0..=2 => valid_lane_groupings
.get_mut(0)
.unwrap()
.retain(|&x| x != *fl),
3..=5 => valid_lane_groupings
.get_mut(1)
.unwrap()
.retain(|&x| x != *fl),
6..=8 => valid_lane_groupings
.get_mut(2)
.unwrap()
.retain(|&x| x != *fl),
_ => unreachable!("Invalid fatal lane number: {fl}"),
}
}
}
for lane_grouping in valid_lane_groupings.iter() {
if lane_ids == lane_grouping.as_slice() {
return Ok(());
}
}
Err("Invalid lane grouping".into())
}
impl AlpideReadoutFrame {
pub fn from_layer(&self) -> Layer {
self.from_layer.expect("No barrel set for readout frame")
}
pub fn close_frame(&mut self, frame_end_mem_pos: u64) {
debug_assert_eq!(
self.frame_end_mem_pos, 0,
"frame_end_mem_pos set more than once!"
);
self.frame_end_mem_pos = frame_end_mem_pos
}
pub fn start_mem_pos(&self) -> u64 {
self.frame_start_mem_pos
}
pub fn end_mem_pos(&self) -> u64 {
self.frame_end_mem_pos
}
pub fn is_empty(&self) -> bool {
self.lane_data_frames.is_empty()
}
pub fn lane_data_frames_as_slice(&self) -> &[LaneDataFrame] {
&self.lane_data_frames
}
pub fn drain_lane_data_frames(&mut self) -> Drain<LaneDataFrame> {
self.lane_data_frames.drain(..)
}
pub fn take_lane_data_frames(&mut self) -> Vec<LaneDataFrame> {
mem::take(&mut self.lane_data_frames)
}
}