pub fn tdh_trigger_as_string(tdh_slice: &[u8]) -> String {
if tdh_soc_trigger(tdh_slice) {
String::from("SOC ")
} else if tdh_internal_trigger(tdh_slice) {
String::from("Internal")
} else if tdh_physics_trigger(tdh_slice) {
String::from("PhT ")
} else {
String::from("Other ")
}
}
pub fn tdh_continuation_as_string(tdh_slice: &[u8]) -> String {
debug_assert!(tdh_slice.len() == 10);
if tdh_continuation(tdh_slice) {
String::from("Cont.")
} else {
String::from(" ")
}
}
pub fn ddw0_tdt_lane_status_as_string(ddw0_tdt_slice: &[u8]) -> String {
if ddw0_tdt_lane_status_any_fatal(ddw0_tdt_slice) {
String::from("Fatal ")
} else if ddw0_tdt_lane_status_any_error(ddw0_tdt_slice) {
String::from("Error ")
} else if ddw0_tdt_lane_status_any_warning(ddw0_tdt_slice) {
String::from("Warning")
} else {
String::from("- ")
}
}
pub fn tdh_no_data_as_string(tdh_slice: &[u8]) -> String {
if tdh_no_data(tdh_slice) {
String::from("No data")
} else {
String::from("Data! ")
}
}
pub fn tdh_trigger_orbit_bc_as_string(tdh_slice: &[u8]) -> String {
let bc = u16::from_le_bytes([tdh_slice[2], tdh_slice[3]]) & 0x0FFF;
let orbit = u32::from_le_bytes([tdh_slice[4], tdh_slice[5], tdh_slice[6], tdh_slice[7]]);
format!("{orbit}_{bc:>4}")
}
pub fn tdh_no_data(tdh_slice: &[u8]) -> bool {
debug_assert!(tdh_slice.len() == 10);
tdh_slice[1] & 0b10_0000 != 0
}
pub fn tdh_continuation(tdh_slice: &[u8]) -> bool {
debug_assert!(tdh_slice.len() == 10);
tdh_slice[1] & 0b100_0000 != 0
}
fn tdh_soc_trigger(tdh_slice: &[u8]) -> bool {
debug_assert!(tdh_slice.len() == 10);
const SOC_BIT_MASK: u8 = 0b10;
tdh_slice[1] & SOC_BIT_MASK != 0
}
fn tdh_internal_trigger(tdh_slice: &[u8]) -> bool {
debug_assert!(tdh_slice.len() == 10);
tdh_slice[1] & 0b1_0000 != 0
}
fn tdh_physics_trigger(tdh_slice: &[u8]) -> bool {
debug_assert!(tdh_slice.len() == 10);
tdh_slice[0] & 0b1_0000 != 0
}
pub fn tdt_packet_done(tdt_slice: &[u8]) -> bool {
debug_assert!(tdt_slice.len() == 10);
tdt_slice[8] & 0b1 != 0
}
pub fn tdt_packet_done_as_string(tdt_slice: &[u8]) -> String {
debug_assert!(tdt_slice.len() == 10);
if tdt_packet_done(tdt_slice) {
String::from("Complete")
} else {
String::from("Split ")
}
}
#[allow(dead_code)]
fn ddw0_lane_status_not_ok(ddw0_slice: &[u8]) -> bool {
debug_assert!(ddw0_slice.len() == 10);
let first_7_bytes = &ddw0_slice[..7];
first_7_bytes.iter().any(|byte| *byte != 0)
}
fn ddw0_tdt_lane_status_any_warning(ddw0_slice: &[u8]) -> bool {
debug_assert!(ddw0_slice.len() == 10);
const LANE_WARNING_MASK: u8 = 0b0101_0101;
let first_7_bytes = &ddw0_slice[..7];
first_7_bytes
.iter()
.any(|byte| *byte & LANE_WARNING_MASK != 0)
}
fn ddw0_tdt_lane_status_any_error(ddw0_slice: &[u8]) -> bool {
debug_assert!(ddw0_slice.len() == 10);
const LANE_ERROR_MASK: u8 = 0b1010_1010;
let first_7_bytes = &ddw0_slice[..7];
first_7_bytes
.iter()
.any(|byte| *byte & LANE_ERROR_MASK != 0)
}
fn ddw0_tdt_lane_status_any_fatal(ddw0_slice: &[u8]) -> bool {
debug_assert!(ddw0_slice.len() == 10);
const LANE_FATAL_MASK0: u8 = 0b0000_0011;
const LANE_FATAL_MASK1: u8 = 0b0000_1100;
const LANE_FATAL_MASK2: u8 = 0b0011_0000;
const LANE_FATAL_MASK3: u8 = 0b1100_0000;
let first_7_bytes = &ddw0_slice[..7];
first_7_bytes.iter().any(|byte| {
*byte & LANE_FATAL_MASK0 == LANE_FATAL_MASK0
|| *byte & LANE_FATAL_MASK1 == LANE_FATAL_MASK1
|| *byte & LANE_FATAL_MASK2 == LANE_FATAL_MASK2
|| *byte & LANE_FATAL_MASK3 == LANE_FATAL_MASK3
})
}
#[allow(dead_code)]
fn ddw0_lane_starts_violation(ddw0_slice: &[u8]) -> bool {
debug_assert!(ddw0_slice.len() == 10);
ddw0_slice[8] & 0b1000 != 0
}
#[allow(dead_code)]
fn ddw0_transmission_timeout(ddw0_slice: &[u8]) -> bool {
debug_assert!(ddw0_slice.len() == 10);
ddw0_slice[8] & 0b10 != 0
}
pub fn is_lane_active(lane: u8, active_lanes: u32) -> bool {
let lane = lane as u32;
let mask = 1 << lane;
active_lanes & mask != 0
}
#[cfg(test)]
mod tests {
use crate::Tdh;
use super::*;
use pretty_assertions::assert_eq;
#[test]
fn test_tdh_trigger_as_string() {
let tdh_slice = [
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
Tdh::ID,
];
let trig_as_string = tdh_trigger_as_string(&tdh_slice);
assert_eq!(trig_as_string, "Other ");
}
#[test]
fn test_tdh_continuation_as_string() {
let tdh_slice = [
0x00,
0b0100_0000, 0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
Tdh::ID,
];
let cont_as_string = tdh_continuation_as_string(&tdh_slice);
assert_eq!(cont_as_string, "Cont.");
}
}